blob: 639fe1efccdfbb7eb34c103027ec832575b83c7e [file] [log] [blame]
Max Bires148c08e2020-10-13 13:41:41 -07001// Copyright 2020, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! This is the implementation for the remote provisioning AIDL interface between
16//! the network providers for remote provisioning and the system. This interface
17//! allows the caller to prompt the Remote Provisioning HAL to generate keys and
18//! CBOR blobs that can be ferried to a provisioning server that will return
19//! certificate chains signed by some root authority and stored in a keystore SQLite
20//! DB.
21
Max Biresb2e1d032021-02-08 21:35:05 -080022use std::collections::HashMap;
Max Bires148c08e2020-10-13 13:41:41 -070023
Max Biresb2e1d032021-02-08 21:35:05 -080024use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Max Bires97f96812021-02-23 23:44:57 -080025 Algorithm::Algorithm, AttestationKey::AttestationKey, Certificate::Certificate,
Max Bires834dd362021-03-23 13:01:57 -070026 DeviceInfo::DeviceInfo, IRemotelyProvisionedComponent::IRemotelyProvisionedComponent,
27 KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue,
28 MacedPublicKey::MacedPublicKey, ProtectedData::ProtectedData, SecurityLevel::SecurityLevel,
29 Tag::Tag,
Max Biresb2e1d032021-02-08 21:35:05 -080030};
Max Bires148c08e2020-10-13 13:41:41 -070031use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{
32 AttestationPoolStatus::AttestationPoolStatus, IRemoteProvisioning::BnRemoteProvisioning,
Seth Moore7ee79f92021-12-07 11:42:49 -080033 IRemoteProvisioning::IRemoteProvisioning,
Seth Moore92648b62022-02-02 13:26:18 -080034 IRemotelyProvisionedKeyPool::BnRemotelyProvisionedKeyPool,
Seth Moore7ee79f92021-12-07 11:42:49 -080035 IRemotelyProvisionedKeyPool::IRemotelyProvisionedKeyPool, ImplInfo::ImplInfo,
36 RemotelyProvisionedKey::RemotelyProvisionedKey,
Max Bires148c08e2020-10-13 13:41:41 -070037};
Andrew Walbrande45c8b2021-04-13 14:42:38 +000038use android_security_remoteprovisioning::binder::{BinderFeatures, Strong};
Max Bires97f96812021-02-23 23:44:57 -080039use android_system_keystore2::aidl::android::system::keystore2::{
Seth Moore7ee79f92021-12-07 11:42:49 -080040 Domain::Domain, KeyDescriptor::KeyDescriptor, ResponseCode::ResponseCode,
Max Bires97f96812021-02-23 23:44:57 -080041};
Max Biresb2e1d032021-02-08 21:35:05 -080042use anyhow::{Context, Result};
Max Bires97f96812021-02-23 23:44:57 -080043use keystore2_crypto::parse_subject_from_certificate;
Max Bires48fc2e52021-11-17 10:13:04 -080044use serde_cbor::Value;
45use std::collections::BTreeMap;
Max Bires97f96812021-02-23 23:44:57 -080046use std::sync::atomic::{AtomicBool, Ordering};
Max Bires148c08e2020-10-13 13:41:41 -070047
Max Bires97f96812021-02-23 23:44:57 -080048use crate::database::{CertificateChain, KeystoreDB, Uuid};
49use crate::error::{self, map_or_log_err, map_rem_prov_error, Error};
Max Biresb2e1d032021-02-08 21:35:05 -080050use crate::globals::{get_keymint_device, get_remotely_provisioned_component, DB};
Hasini Gunasinghe8a1a2242021-08-02 22:28:39 +000051use crate::metrics_store::log_rkp_error_stats;
Seth Moore7ee79f92021-12-07 11:42:49 -080052use crate::permission::KeystorePerm;
53use crate::utils::{check_keystore_permission, watchdog as wd};
Hasini Gunasinghe8a1a2242021-08-02 22:28:39 +000054use android_security_metrics::aidl::android::security::metrics::RkpError::RkpError as MetricsRkpError;
Max Bires148c08e2020-10-13 13:41:41 -070055
Max Bires97f96812021-02-23 23:44:57 -080056/// Contains helper functions to check if remote provisioning is enabled on the system and, if so,
57/// to assign and retrieve attestation keys and certificate chains.
58#[derive(Default)]
59pub struct RemProvState {
60 security_level: SecurityLevel,
61 km_uuid: Uuid,
62 is_hal_present: AtomicBool,
63}
64
Max Bires48fc2e52021-11-17 10:13:04 -080065static COSE_KEY_XCOORD: Value = Value::Integer(-2);
66static COSE_KEY_YCOORD: Value = Value::Integer(-3);
67static COSE_MAC0_LEN: usize = 4;
68static COSE_MAC0_PAYLOAD: usize = 2;
69
Max Bires97f96812021-02-23 23:44:57 -080070impl RemProvState {
71 /// Creates a RemProvState struct.
72 pub fn new(security_level: SecurityLevel, km_uuid: Uuid) -> Self {
73 Self { security_level, km_uuid, is_hal_present: AtomicBool::new(true) }
74 }
75
76 /// Checks if remote provisioning is enabled and partially caches the result. On a hybrid system
77 /// remote provisioning can flip from being disabled to enabled depending on responses from the
78 /// server, so unfortunately caching the presence or absence of the HAL is not enough to fully
79 /// make decisions about the state of remote provisioning during runtime.
80 fn check_rem_prov_enabled(&self, db: &mut KeystoreDB) -> Result<bool> {
81 if !self.is_hal_present.load(Ordering::Relaxed)
82 || get_remotely_provisioned_component(&self.security_level).is_err()
83 {
84 self.is_hal_present.store(false, Ordering::Relaxed);
85 return Ok(false);
86 }
87 // To check if remote provisioning is enabled on a system that supports both remote
88 // provisioning and factory provisioned keys, we only need to check if there are any
89 // keys at all generated to indicate if the app has gotten the signal to begin filling
90 // the key pool from the server.
91 let pool_status = db
92 .get_attestation_pool_status(0 /* date */, &self.km_uuid)
93 .context("In check_rem_prov_enabled: failed to get attestation pool status.")?;
94 Ok(pool_status.total != 0)
95 }
96
Max Bires97f96812021-02-23 23:44:57 -080097 fn is_asymmetric_key(&self, params: &[KeyParameter]) -> bool {
98 params.iter().any(|kp| {
99 matches!(
100 kp,
101 KeyParameter {
102 tag: Tag::ALGORITHM,
103 value: KeyParameterValue::Algorithm(Algorithm::RSA)
104 } | KeyParameter {
105 tag: Tag::ALGORITHM,
106 value: KeyParameterValue::Algorithm(Algorithm::EC)
107 }
108 )
109 })
110 }
111
112 /// Checks to see (1) if the key in question should be attested to based on the algorithm and
113 /// (2) if remote provisioning is present and enabled on the system. If these conditions are
114 /// met, it makes an attempt to fetch the attestation key assigned to the `caller_uid`.
115 ///
116 /// It returns the ResponseCode `OUT_OF_KEYS` if there is not one key currently assigned to the
117 /// `caller_uid` and there are none available to assign.
Janis Danisevskis3541f3e2021-03-20 14:18:52 -0700118 pub fn get_remotely_provisioned_attestation_key_and_certs(
Max Bires97f96812021-02-23 23:44:57 -0800119 &self,
120 key: &KeyDescriptor,
121 caller_uid: u32,
122 params: &[KeyParameter],
123 db: &mut KeystoreDB,
Janis Danisevskis3541f3e2021-03-20 14:18:52 -0700124 ) -> Result<Option<(AttestationKey, Certificate)>> {
Max Bires97f96812021-02-23 23:44:57 -0800125 if !self.is_asymmetric_key(params) || !self.check_rem_prov_enabled(db)? {
126 // There is no remote provisioning component for this security level on the
127 // device. Return None so the underlying KM instance knows to use its
128 // factory provisioned key instead. Alternatively, it's not an asymmetric key
129 // and therefore will not be attested.
Janis Danisevskis3541f3e2021-03-20 14:18:52 -0700130 Ok(None)
Max Bires97f96812021-02-23 23:44:57 -0800131 } else {
Seth Moore7ee79f92021-12-07 11:42:49 -0800132 match get_rem_prov_attest_key(key.domain, caller_uid, db, &self.km_uuid) {
Max Bires31cdfb82021-07-06 02:59:25 -0700133 Err(e) => {
134 log::error!(
135 concat!(
136 "In get_remote_provisioning_key_and_certs: Failed to get ",
137 "attestation key. {:?}"
138 ),
139 e
140 );
Hasini Gunasinghe8a1a2242021-08-02 22:28:39 +0000141 log_rkp_error_stats(MetricsRkpError::FALL_BACK_DURING_HYBRID);
Max Bires31cdfb82021-07-06 02:59:25 -0700142 Ok(None)
143 }
144 Ok(v) => match v {
145 Some(cert_chain) => Ok(Some((
146 AttestationKey {
147 keyBlob: cert_chain.private_key.to_vec(),
148 attestKeyParams: vec![],
149 issuerSubjectName: parse_subject_from_certificate(
150 &cert_chain.batch_cert,
151 )
Max Bires97f96812021-02-23 23:44:57 -0800152 .context(concat!(
Max Bires31cdfb82021-07-06 02:59:25 -0700153 "In get_remote_provisioning_key_and_certs: Failed to ",
154 "parse subject."
155 ))?,
156 },
157 Certificate { encodedCertificate: cert_chain.cert_chain },
158 ))),
159 None => Ok(None),
160 },
Max Bires97f96812021-02-23 23:44:57 -0800161 }
162 }
163 }
164}
Max Bires148c08e2020-10-13 13:41:41 -0700165/// Implementation of the IRemoteProvisioning service.
Max Biresb2e1d032021-02-08 21:35:05 -0800166#[derive(Default)]
Max Bires148c08e2020-10-13 13:41:41 -0700167pub struct RemoteProvisioningService {
Janis Danisevskis5f3a0572021-06-18 11:26:42 -0700168 device_by_sec_level: HashMap<SecurityLevel, Strong<dyn IRemotelyProvisionedComponent>>,
Max Biresd2ce46b2021-07-06 02:54:47 -0700169 curve_by_sec_level: HashMap<SecurityLevel, i32>,
Max Bires148c08e2020-10-13 13:41:41 -0700170}
171
172impl RemoteProvisioningService {
Max Biresb2e1d032021-02-08 21:35:05 -0800173 fn get_dev_by_sec_level(
174 &self,
175 sec_level: &SecurityLevel,
Seth Moore7ee79f92021-12-07 11:42:49 -0800176 ) -> Result<&dyn IRemotelyProvisionedComponent> {
Max Biresb2e1d032021-02-08 21:35:05 -0800177 if let Some(dev) = self.device_by_sec_level.get(sec_level) {
Seth Moore7ee79f92021-12-07 11:42:49 -0800178 Ok(dev.as_ref())
Max Biresb2e1d032021-02-08 21:35:05 -0800179 } else {
180 Err(error::Error::sys()).context(concat!(
181 "In get_dev_by_sec_level: Remote instance for requested security level",
182 " not found."
183 ))
184 }
185 }
186
Max Bires148c08e2020-10-13 13:41:41 -0700187 /// Creates a new instance of the remote provisioning service
Stephen Crane221bbb52020-12-16 15:52:10 -0800188 pub fn new_native_binder() -> Result<Strong<dyn IRemoteProvisioning>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800189 let mut result: Self = Default::default();
190 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
191 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
Max Biresd2ce46b2021-07-06 02:54:47 -0700192 result.curve_by_sec_level.insert(
193 SecurityLevel::TRUSTED_ENVIRONMENT,
194 dev.getHardwareInfo()
195 .context("In new_native_binder: Failed to get hardware info for the TEE.")?
196 .supportedEekCurve,
197 );
Max Biresb2e1d032021-02-08 21:35:05 -0800198 result.device_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, dev);
199 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
Max Biresd2ce46b2021-07-06 02:54:47 -0700200 result.curve_by_sec_level.insert(
201 SecurityLevel::STRONGBOX,
202 dev.getHardwareInfo()
203 .context("In new_native_binder: Failed to get hardware info for StrongBox.")?
204 .supportedEekCurve,
205 );
Max Biresb2e1d032021-02-08 21:35:05 -0800206 result.device_by_sec_level.insert(SecurityLevel::STRONGBOX, dev);
207 }
Andrew Walbrande45c8b2021-04-13 14:42:38 +0000208 Ok(BnRemoteProvisioning::new_binder(result, BinderFeatures::default()))
Max Bires148c08e2020-10-13 13:41:41 -0700209 }
210
Max Bires48fc2e52021-11-17 10:13:04 -0800211 fn extract_payload_from_cose_mac(data: &[u8]) -> Result<Value> {
212 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data).context(
213 "In extract_payload_from_cose_mac: COSE_Mac0 returned from IRPC cannot be parsed",
214 )?;
215 if cose_mac0.len() != COSE_MAC0_LEN {
216 return Err(error::Error::sys()).context(format!(
217 "In extract_payload_from_cose_mac: COSE_Mac0 has improper length. \
218 Expected: {}, Actual: {}",
219 COSE_MAC0_LEN,
220 cose_mac0.len(),
221 ));
222 }
223 match &cose_mac0[COSE_MAC0_PAYLOAD] {
224 Value::Bytes(key) => Ok(serde_cbor::from_slice(key)
225 .context("In extract_payload_from_cose_mac: COSE_Mac0 payload is malformed.")?),
226 _ => Err(error::Error::sys()).context(
227 "In extract_payload_from_cose_mac: COSE_Mac0 payload is the wrong type.",
228 )?,
229 }
230 }
231
Max Bires148c08e2020-10-13 13:41:41 -0700232 /// Generates a CBOR blob which will be assembled by the calling code into a larger
233 /// CBOR blob intended for delivery to a provisioning serever. This blob will contain
234 /// `num_csr` certificate signing requests for attestation keys generated in the TEE,
235 /// along with a server provided `eek` and `challenge`. The endpoint encryption key will
236 /// be used to encrypt the sensitive contents being transmitted to the server, and the
237 /// challenge will ensure freshness. A `test_mode` flag will instruct the remote provisioning
238 /// HAL if it is okay to accept EEKs that aren't signed by something that chains back to the
239 /// baked in root of trust in the underlying IRemotelyProvisionedComponent instance.
Max Bires834dd362021-03-23 13:01:57 -0700240 #[allow(clippy::too_many_arguments)]
Max Bires148c08e2020-10-13 13:41:41 -0700241 pub fn generate_csr(
242 &self,
Max Biresb2e1d032021-02-08 21:35:05 -0800243 test_mode: bool,
244 num_csr: i32,
245 eek: &[u8],
246 challenge: &[u8],
247 sec_level: SecurityLevel,
248 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700249 device_info: &mut DeviceInfo,
Max Bires148c08e2020-10-13 13:41:41 -0700250 ) -> Result<Vec<u8>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800251 let dev = self.get_dev_by_sec_level(&sec_level)?;
252 let (_, _, uuid) = get_keymint_device(&sec_level)?;
253 let keys_to_sign = DB.with::<_, Result<Vec<MacedPublicKey>>>(|db| {
254 let mut db = db.borrow_mut();
255 Ok(db
256 .fetch_unsigned_attestation_keys(num_csr, &uuid)?
257 .iter()
258 .map(|key| MacedPublicKey { macedKey: key.to_vec() })
259 .collect())
260 })?;
Max Bires48fc2e52021-11-17 10:13:04 -0800261 let mac = map_rem_prov_error(dev.generateCertificateRequest(
Max Biresb2e1d032021-02-08 21:35:05 -0800262 test_mode,
263 &keys_to_sign,
264 eek,
265 challenge,
Max Bires834dd362021-03-23 13:01:57 -0700266 device_info,
Max Biresb2e1d032021-02-08 21:35:05 -0800267 protected_data,
268 ))
269 .context("In generate_csr: Failed to generate csr")?;
Max Bires48fc2e52021-11-17 10:13:04 -0800270 let mut mac_and_keys: Vec<Value> = vec![Value::from(mac)];
Max Bires97f96812021-02-23 23:44:57 -0800271 for maced_public_key in keys_to_sign {
Max Bires48fc2e52021-11-17 10:13:04 -0800272 mac_and_keys.push(
273 Self::extract_payload_from_cose_mac(&maced_public_key.macedKey)
274 .context("In generate_csr: Failed to get the payload from the COSE_Mac0")?,
275 )
Max Bires97f96812021-02-23 23:44:57 -0800276 }
Max Bires48fc2e52021-11-17 10:13:04 -0800277 let cbor_array: Value = Value::Array(mac_and_keys);
278 serde_cbor::to_vec(&cbor_array)
279 .context("In generate_csr: Failed to serialize the mac and keys array")
Max Bires148c08e2020-10-13 13:41:41 -0700280 }
281
282 /// Provisions a certificate chain for a key whose CSR was included in generate_csr. The
283 /// `public_key` is used to index into the SQL database in order to insert the `certs` blob
284 /// which represents a PEM encoded X.509 certificate chain. The `expiration_date` is provided
285 /// as a convenience from the caller to avoid having to parse the certificates semantically
286 /// here.
287 pub fn provision_cert_chain(
288 &self,
Seth Moore7ee79f92021-12-07 11:42:49 -0800289 db: &mut KeystoreDB,
Max Bires148c08e2020-10-13 13:41:41 -0700290 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800291 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700292 certs: &[u8],
293 expiration_date: i64,
294 sec_level: SecurityLevel,
295 ) -> Result<()> {
Seth Moore7ee79f92021-12-07 11:42:49 -0800296 let (_, _, uuid) = get_keymint_device(&sec_level)?;
297 db.store_signed_attestation_certificate_chain(
298 public_key,
299 batch_cert,
300 certs, /* DER encoded certificate chain */
301 expiration_date,
302 &uuid,
303 )
Max Bires148c08e2020-10-13 13:41:41 -0700304 }
305
Max Bires48fc2e52021-11-17 10:13:04 -0800306 fn parse_cose_mac0_for_coords(data: &[u8]) -> Result<Vec<u8>> {
307 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data).context(
308 "In parse_cose_mac0_for_coords: COSE_Mac0 returned from IRPC cannot be parsed",
309 )?;
310 if cose_mac0.len() != COSE_MAC0_LEN {
311 return Err(error::Error::sys()).context(format!(
312 "In parse_cose_mac0_for_coords: COSE_Mac0 has improper length. \
313 Expected: {}, Actual: {}",
314 COSE_MAC0_LEN,
315 cose_mac0.len(),
316 ));
317 }
318 let cose_key: BTreeMap<Value, Value> = match &cose_mac0[COSE_MAC0_PAYLOAD] {
319 Value::Bytes(key) => serde_cbor::from_slice(key)
320 .context("In parse_cose_mac0_for_coords: COSE_Key is malformed.")?,
321 _ => Err(error::Error::sys())
322 .context("In parse_cose_mac0_for_coords: COSE_Mac0 payload is the wrong type.")?,
323 };
324 if !cose_key.contains_key(&COSE_KEY_XCOORD) || !cose_key.contains_key(&COSE_KEY_YCOORD) {
325 return Err(error::Error::sys()).context(
326 "In parse_cose_mac0_for_coords: \
327 COSE_Key returned from IRPC is lacking required fields",
328 );
329 }
330 let mut raw_key: Vec<u8> = vec![0; 64];
331 match &cose_key[&COSE_KEY_XCOORD] {
332 Value::Bytes(x_coord) if x_coord.len() == 32 => {
333 raw_key[0..32].clone_from_slice(x_coord)
334 }
335 Value::Bytes(x_coord) => {
336 return Err(error::Error::sys()).context(format!(
337 "In parse_cose_mac0_for_coords: COSE_Key X-coordinate is not the right length. \
338 Expected: 32; Actual: {}",
339 x_coord.len()
340 ))
341 }
342 _ => {
343 return Err(error::Error::sys())
344 .context("In parse_cose_mac0_for_coords: COSE_Key X-coordinate is not a bstr")
345 }
346 }
347 match &cose_key[&COSE_KEY_YCOORD] {
348 Value::Bytes(y_coord) if y_coord.len() == 32 => {
349 raw_key[32..64].clone_from_slice(y_coord)
350 }
351 Value::Bytes(y_coord) => {
352 return Err(error::Error::sys()).context(format!(
353 "In parse_cose_mac0_for_coords: COSE_Key Y-coordinate is not the right length. \
354 Expected: 32; Actual: {}",
355 y_coord.len()
356 ))
357 }
358 _ => {
359 return Err(error::Error::sys())
360 .context("In parse_cose_mac0_for_coords: COSE_Key Y-coordinate is not a bstr")
361 }
362 }
363 Ok(raw_key)
364 }
365
Max Bires148c08e2020-10-13 13:41:41 -0700366 /// Submits a request to the Remote Provisioner HAL to generate a signing key pair.
367 /// `is_test_mode` indicates whether or not the returned public key should be marked as being
368 /// for testing in order to differentiate them from private keys. If the call is successful,
369 /// the key pair is then added to the database.
Seth Moore7ee79f92021-12-07 11:42:49 -0800370 pub fn generate_key_pair(
371 &self,
372 db: &mut KeystoreDB,
373 is_test_mode: bool,
374 sec_level: SecurityLevel,
375 ) -> Result<()> {
Max Biresb2e1d032021-02-08 21:35:05 -0800376 let (_, _, uuid) = get_keymint_device(&sec_level)?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800377 let dev = self.get_dev_by_sec_level(&sec_level).context(format!(
378 "In generate_key_pair: Failed to get device for security level {:?}",
379 sec_level
380 ))?;
Max Biresb2e1d032021-02-08 21:35:05 -0800381 let mut maced_key = MacedPublicKey { macedKey: Vec::new() };
382 let priv_key =
383 map_rem_prov_error(dev.generateEcdsaP256KeyPair(is_test_mode, &mut maced_key))
384 .context("In generate_key_pair: Failed to generated ECDSA keypair.")?;
Max Bires48fc2e52021-11-17 10:13:04 -0800385 let raw_key = Self::parse_cose_mac0_for_coords(&maced_key.macedKey)
386 .context("In generate_key_pair: Failed to parse raw key")?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800387 db.create_attestation_key_entry(&maced_key.macedKey, &raw_key, &priv_key, &uuid)
388 .context("In generate_key_pair: Failed to insert attestation key entry")
Max Biresb2e1d032021-02-08 21:35:05 -0800389 }
390
391 /// Checks the security level of each available IRemotelyProvisionedComponent hal and returns
392 /// all levels in an array to the caller.
Max Biresd2ce46b2021-07-06 02:54:47 -0700393 pub fn get_implementation_info(&self) -> Result<Vec<ImplInfo>> {
394 Ok(self
395 .curve_by_sec_level
396 .iter()
397 .map(|(sec_level, curve)| ImplInfo { secLevel: *sec_level, supportedCurve: *curve })
398 .collect())
Max Bires148c08e2020-10-13 13:41:41 -0700399 }
Max Bires60d7ed12021-03-05 15:59:22 -0800400
401 /// Deletes all attestation keys generated by the IRemotelyProvisionedComponent from the device,
402 /// regardless of what state of the attestation key lifecycle they were in.
403 pub fn delete_all_keys(&self) -> Result<i64> {
404 DB.with::<_, Result<i64>>(|db| {
405 let mut db = db.borrow_mut();
Matthew Maurerb77a28d2021-05-07 16:08:20 -0700406 db.delete_all_attestation_keys()
Max Bires60d7ed12021-03-05 15:59:22 -0800407 })
408 }
Max Bires148c08e2020-10-13 13:41:41 -0700409}
410
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000411/// Populates the AttestationPoolStatus parcelable with information about how many
412/// certs will be expiring by the date provided in `expired_by` along with how many
413/// keys have not yet been assigned.
414pub fn get_pool_status(expired_by: i64, sec_level: SecurityLevel) -> Result<AttestationPoolStatus> {
415 let (_, _, uuid) = get_keymint_device(&sec_level)?;
416 DB.with::<_, Result<AttestationPoolStatus>>(|db| {
417 let mut db = db.borrow_mut();
418 // delete_expired_attestation_keys is always safe to call, and will remove anything
419 // older than the date at the time of calling. No work should be done on the
420 // attestation keys unless the pool status is checked first, so this call should be
421 // enough to routinely clean out expired keys.
422 db.delete_expired_attestation_keys()?;
423 db.get_attestation_pool_status(expired_by, &uuid)
424 })
425}
426
Seth Moore7ee79f92021-12-07 11:42:49 -0800427/// Fetches a remote provisioning attestation key and certificate chain inside of the
428/// returned `CertificateChain` struct if one exists for the given caller_uid. If one has not
429/// been assigned, this function will assign it. If there are no signed attestation keys
430/// available to be assigned, it will return the ResponseCode `OUT_OF_KEYS`
431fn get_rem_prov_attest_key(
432 domain: Domain,
433 caller_uid: u32,
434 db: &mut KeystoreDB,
435 km_uuid: &Uuid,
436) -> Result<Option<CertificateChain>> {
437 match domain {
438 Domain::APP => {
439 // Attempt to get an Attestation Key once. If it fails, then the app doesn't
440 // have a valid chain assigned to it. The helper function will return None after
441 // attempting to assign a key. An error will be thrown if the pool is simply out
442 // of usable keys. Then another attempt to fetch the just-assigned key will be
443 // made. If this fails too, something is very wrong.
444 get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid)
445 .context("In get_rem_prov_attest_key: Failed to get a key")?
446 .map_or_else(
447 || get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid),
448 |v| Ok(Some(v)),
449 )
450 .context(concat!(
451 "In get_rem_prov_attest_key: Failed to get a key after",
452 "attempting to assign one."
453 ))?
454 .map_or_else(
455 || {
456 Err(Error::sys()).context(concat!(
457 "In get_rem_prov_attest_key: Attempted to assign a ",
458 "key and failed silently. Something is very wrong."
459 ))
460 },
461 |cert_chain| Ok(Some(cert_chain)),
462 )
463 }
464 _ => Ok(None),
465 }
466}
467
468/// Returns None if an AttestationKey fails to be assigned. Errors if no keys are available.
469fn get_rem_prov_attest_key_helper(
470 domain: Domain,
471 caller_uid: u32,
472 db: &mut KeystoreDB,
473 km_uuid: &Uuid,
474) -> Result<Option<CertificateChain>> {
475 let cert_chain = db
476 .retrieve_attestation_key_and_cert_chain(domain, caller_uid as i64, km_uuid)
477 .context("In get_rem_prov_attest_key_helper: Failed to retrieve a key + cert chain")?;
478 match cert_chain {
479 Some(cert_chain) => Ok(Some(cert_chain)),
480 // Either this app needs to be assigned a key, or the pool is empty. An error will
481 // be thrown if there is no key available to assign. This will indicate that the app
482 // should be nudged to provision more keys so keystore can retry.
483 None => {
484 db.assign_attestation_key(domain, caller_uid as i64, km_uuid)
485 .context("In get_rem_prov_attest_key_helper: Failed to assign a key")?;
486 Ok(None)
487 }
488 }
489}
490
Max Bires148c08e2020-10-13 13:41:41 -0700491impl binder::Interface for RemoteProvisioningService {}
492
493// Implementation of IRemoteProvisioning. See AIDL spec at
494// :aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
495impl IRemoteProvisioning for RemoteProvisioningService {
496 fn getPoolStatus(
497 &self,
498 expired_by: i64,
499 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700500 ) -> binder::Result<AttestationPoolStatus> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000501 let _wp = wd::watch_millis("IRemoteProvisioning::getPoolStatus", 500);
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000502 map_or_log_err(get_pool_status(expired_by, sec_level), Ok)
Max Bires148c08e2020-10-13 13:41:41 -0700503 }
504
505 fn generateCsr(
506 &self,
507 test_mode: bool,
508 num_csr: i32,
509 eek: &[u8],
510 challenge: &[u8],
511 sec_level: SecurityLevel,
Max Biresb2e1d032021-02-08 21:35:05 -0800512 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700513 device_info: &mut DeviceInfo,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700514 ) -> binder::Result<Vec<u8>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000515 let _wp = wd::watch_millis("IRemoteProvisioning::generateCsr", 500);
Max Biresb2e1d032021-02-08 21:35:05 -0800516 map_or_log_err(
Max Bires834dd362021-03-23 13:01:57 -0700517 self.generate_csr(
518 test_mode,
519 num_csr,
520 eek,
521 challenge,
522 sec_level,
523 protected_data,
524 device_info,
525 ),
Max Biresb2e1d032021-02-08 21:35:05 -0800526 Ok,
527 )
Max Bires148c08e2020-10-13 13:41:41 -0700528 }
529
530 fn provisionCertChain(
531 &self,
532 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800533 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700534 certs: &[u8],
535 expiration_date: i64,
536 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700537 ) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000538 let _wp = wd::watch_millis("IRemoteProvisioning::provisionCertChain", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800539 DB.with::<_, binder::Result<()>>(|db| {
540 map_or_log_err(
541 self.provision_cert_chain(
542 &mut db.borrow_mut(),
543 public_key,
544 batch_cert,
545 certs,
546 expiration_date,
547 sec_level,
548 ),
549 Ok,
550 )
551 })
Max Bires148c08e2020-10-13 13:41:41 -0700552 }
553
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700554 fn generateKeyPair(&self, is_test_mode: bool, sec_level: SecurityLevel) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000555 let _wp = wd::watch_millis("IRemoteProvisioning::generateKeyPair", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800556 DB.with::<_, binder::Result<()>>(|db| {
557 map_or_log_err(
558 self.generate_key_pair(&mut db.borrow_mut(), is_test_mode, sec_level),
559 Ok,
560 )
561 })
Max Bires148c08e2020-10-13 13:41:41 -0700562 }
Max Biresb2e1d032021-02-08 21:35:05 -0800563
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700564 fn getImplementationInfo(&self) -> binder::Result<Vec<ImplInfo>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000565 let _wp = wd::watch_millis("IRemoteProvisioning::getSecurityLevels", 500);
Max Biresd2ce46b2021-07-06 02:54:47 -0700566 map_or_log_err(self.get_implementation_info(), Ok)
Max Biresb2e1d032021-02-08 21:35:05 -0800567 }
Max Bires60d7ed12021-03-05 15:59:22 -0800568
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700569 fn deleteAllKeys(&self) -> binder::Result<i64> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000570 let _wp = wd::watch_millis("IRemoteProvisioning::deleteAllKeys", 500);
Max Bires60d7ed12021-03-05 15:59:22 -0800571 map_or_log_err(self.delete_all_keys(), Ok)
572 }
Max Bires148c08e2020-10-13 13:41:41 -0700573}
Max Bires48fc2e52021-11-17 10:13:04 -0800574
Seth Moore92648b62022-02-02 13:26:18 -0800575/// Implementation of the IRemotelyProvisionedKeyPool service.
576#[derive(Default)]
577pub struct RemotelyProvisionedKeyPoolService {
578 unique_id_to_sec_level: HashMap<String, SecurityLevel>,
579}
580
581impl RemotelyProvisionedKeyPoolService {
582 /// Fetches a remotely provisioned certificate chain and key for the given client uid that
583 /// was provisioned using the IRemotelyProvisionedComponent with the given id. The same key
584 /// will be returned for a given caller_uid on every request. If there are no attestation keys
585 /// available, `OUT_OF_KEYS` is returned.
586 fn get_attestation_key(
587 &self,
588 db: &mut KeystoreDB,
589 caller_uid: i32,
590 irpc_id: &str,
591 ) -> Result<RemotelyProvisionedKey> {
592 log::info!("get_attestation_key(self, {}, {}", caller_uid, irpc_id);
593
594 let sec_level = self
595 .unique_id_to_sec_level
596 .get(irpc_id)
597 .ok_or(Error::Rc(ResponseCode::INVALID_ARGUMENT))
598 .context(format!("In get_attestation_key: unknown irpc id '{}'", irpc_id))?;
599 let (_, _, km_uuid) = get_keymint_device(sec_level)?;
600
601 let cert_chain = get_rem_prov_attest_key(Domain::APP, caller_uid as u32, db, &km_uuid)
602 .context("In get_attestation_key")?;
603 match cert_chain {
604 Some(chain) => Ok(RemotelyProvisionedKey {
605 keyBlob: chain.private_key.to_vec(),
606 encodedCertChain: chain.cert_chain,
607 }),
608 // It should be impossible to get `None`, but handle it just in case as a
609 // precaution against future behavioral changes in `get_rem_prov_attest_key`.
610 None => Err(error::Error::Rc(ResponseCode::OUT_OF_KEYS))
611 .context("In get_attestation_key: No available attestation keys"),
612 }
613 }
614
615 /// Creates a new instance of the remotely provisioned key pool service, used for fetching
616 /// remotely provisioned attestation keys.
617 pub fn new_native_binder() -> Result<Strong<dyn IRemotelyProvisionedKeyPool>> {
618 let mut result: Self = Default::default();
619
620 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
621 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
622 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
623 result.unique_id_to_sec_level.insert(id, SecurityLevel::TRUSTED_ENVIRONMENT);
624 }
625
626 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
627 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
628 if result.unique_id_to_sec_level.contains_key(&id) {
629 anyhow::bail!("In new_native_binder: duplicate irpc id found: '{}'", id)
630 }
631 result.unique_id_to_sec_level.insert(id, SecurityLevel::STRONGBOX);
632 }
633 }
634
635 // If none of the remotely provisioned components have unique ids, then we shouldn't
636 // bother publishing the service, as it's impossible to match keys with their backends.
637 if result.unique_id_to_sec_level.is_empty() {
638 anyhow::bail!(
639 "In new_native_binder: No remotely provisioned components have unique ids"
640 )
641 }
642
643 Ok(BnRemotelyProvisionedKeyPool::new_binder(
644 result,
645 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
646 ))
647 }
648}
649
650impl binder::Interface for RemotelyProvisionedKeyPoolService {}
651
Seth Moore7ee79f92021-12-07 11:42:49 -0800652// Implementation of IRemotelyProvisionedKeyPool. See AIDL spec at
653// :aidl/android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.aidl
Seth Moore92648b62022-02-02 13:26:18 -0800654impl IRemotelyProvisionedKeyPool for RemotelyProvisionedKeyPoolService {
Seth Moore7ee79f92021-12-07 11:42:49 -0800655 fn getAttestationKey(
656 &self,
657 caller_uid: i32,
658 irpc_id: &str,
659 ) -> binder::Result<RemotelyProvisionedKey> {
660 let _wp = wd::watch_millis("IRemotelyProvisionedKeyPool::getAttestationKey", 500);
661 map_or_log_err(check_keystore_permission(KeystorePerm::GetAttestationKey), Ok)?;
662 DB.with::<_, binder::Result<RemotelyProvisionedKey>>(|db| {
663 map_or_log_err(self.get_attestation_key(&mut db.borrow_mut(), caller_uid, irpc_id), Ok)
664 })
665 }
666}
667
Max Bires48fc2e52021-11-17 10:13:04 -0800668#[cfg(test)]
669mod tests {
670 use super::*;
671 use serde_cbor::Value;
672 use std::collections::BTreeMap;
Seth Moore7ee79f92021-12-07 11:42:49 -0800673 use std::sync::{Arc, Mutex};
674 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
675 RpcHardwareInfo::RpcHardwareInfo,
676 };
677
678 #[derive(Default)]
679 struct MockRemotelyProvisionedComponentValues {
680 hw_info: RpcHardwareInfo,
681 private_key: Vec<u8>,
682 maced_public_key: Vec<u8>,
683 }
684
685 // binder::Interface requires the Send trait, so we have to use a Mutex even though the test
686 // is single threaded.
687 #[derive(Default)]
688 struct MockRemotelyProvisionedComponent(Arc<Mutex<MockRemotelyProvisionedComponentValues>>);
689
690 impl binder::Interface for MockRemotelyProvisionedComponent {}
691
692 impl IRemotelyProvisionedComponent for MockRemotelyProvisionedComponent {
693 fn getHardwareInfo(&self) -> binder::Result<RpcHardwareInfo> {
694 Ok(self.0.lock().unwrap().hw_info.clone())
695 }
696
697 fn generateEcdsaP256KeyPair(
698 &self,
699 test_mode: bool,
700 maced_public_key: &mut MacedPublicKey,
701 ) -> binder::Result<Vec<u8>> {
702 assert!(test_mode);
703 maced_public_key.macedKey = self.0.lock().unwrap().maced_public_key.clone();
704 Ok(self.0.lock().unwrap().private_key.clone())
705 }
706
707 fn generateCertificateRequest(
708 &self,
709 _test_mode: bool,
710 _keys_to_sign: &[MacedPublicKey],
711 _eek: &[u8],
712 _challenge: &[u8],
713 _device_info: &mut DeviceInfo,
714 _protected_data: &mut ProtectedData,
715 ) -> binder::Result<Vec<u8>> {
716 Err(binder::StatusCode::INVALID_OPERATION.into())
717 }
718 }
719
720 // Hard coded cert that can be parsed -- the content doesn't matter for testing, only that it's valid.
721 fn get_fake_cert() -> Vec<u8> {
722 vec![
723 0x30, 0x82, 0x01, 0xbb, 0x30, 0x82, 0x01, 0x61, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
724 0x14, 0x3a, 0xd5, 0x67, 0xce, 0xfe, 0x93, 0xe1, 0xea, 0xb7, 0xe4, 0xbf, 0x64, 0x19,
725 0xa4, 0x11, 0xe1, 0x87, 0x40, 0x20, 0x37, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
726 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
727 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
728 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
729 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
730 0x6c, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x30, 0x32, 0x32,
731 0x30, 0x38, 0x35, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x34, 0x32, 0x36, 0x32,
732 0x32, 0x30, 0x38, 0x35, 0x32, 0x5a, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
733 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
734 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
735 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f,
736 0x67, 0x6c, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
737 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
738 0x00, 0x04, 0x1e, 0xac, 0x0c, 0xe0, 0x0d, 0xc5, 0x25, 0x84, 0x1b, 0xd2, 0x77, 0x2d,
739 0xe7, 0xba, 0xf1, 0xde, 0xa7, 0xf6, 0x39, 0x7f, 0x38, 0x91, 0xbf, 0xa4, 0x58, 0xf5,
740 0x62, 0x6b, 0xce, 0x06, 0xcf, 0xb9, 0x73, 0x91, 0x0d, 0x8a, 0x60, 0xa0, 0xc6, 0xa2,
741 0x22, 0xe6, 0x51, 0x2e, 0x58, 0xd6, 0x43, 0x02, 0x80, 0x43, 0x44, 0x29, 0x38, 0x9a,
742 0x99, 0xf3, 0xa4, 0xdd, 0xd0, 0xb4, 0x6f, 0x8b, 0x44, 0x2d, 0xa3, 0x53, 0x30, 0x51,
743 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdb, 0x13, 0x68,
744 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe, 0x42, 0x3c, 0xd9, 0x3f, 0x1a,
745 0x33, 0xe9, 0xaa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
746 0x80, 0x14, 0xdb, 0x13, 0x68, 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe,
747 0x42, 0x3c, 0xd9, 0x3f, 0x1a, 0x33, 0xe9, 0xaa, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
748 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06,
749 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
750 0x02, 0x20, 0x10, 0xdf, 0x40, 0xc3, 0x20, 0x54, 0x36, 0xb5, 0xc9, 0x3c, 0x70, 0xe3,
751 0x55, 0x37, 0xd2, 0x04, 0x51, 0xeb, 0x0f, 0x18, 0x83, 0xd0, 0x58, 0xa1, 0x08, 0x77,
752 0x8d, 0x4d, 0xa4, 0x20, 0xee, 0x33, 0x02, 0x21, 0x00, 0x8d, 0xe3, 0xa6, 0x6c, 0x0d,
753 0x86, 0x25, 0xdc, 0x59, 0x0d, 0x21, 0x43, 0x22, 0x3a, 0xb9, 0xa1, 0x73, 0x28, 0xc9,
754 0x16, 0x9e, 0x91, 0x15, 0xc4, 0xc3, 0xd7, 0xeb, 0xe5, 0xce, 0xdc, 0x1c, 0x1b,
755 ]
756 }
757
758 // Generate a fake COSE_Mac0 with a key that's just `byte` repeated
759 fn generate_maced_pubkey(byte: u8) -> Vec<u8> {
760 vec![
761 0x84, 0x43, 0xA1, 0x01, 0x05, 0xA0, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20,
762 0x01, 0x21, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
763 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
764 byte, byte, byte, byte, byte, byte, byte, byte, 0x22, 0x58, 0x20, byte, byte, byte,
765 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
766 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
767 byte, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
768 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
769 byte, byte, byte, byte, byte, byte, byte,
770 ]
771 }
Max Bires48fc2e52021-11-17 10:13:04 -0800772
773 #[test]
774 fn test_parse_cose_mac0_for_coords_raw_bytes() -> Result<()> {
775 let cose_mac0: Vec<u8> = vec![
776 0x84, 0x01, 0x02, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
777 0x20, 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9,
778 0x21, 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C,
779 0x43, 0x22, 0xC8, 0xEE, 0x03, 0x22, 0x58, 0x20, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95,
780 0x90, 0xA7, 0x5C, 0x5A, 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A,
781 0xA3, 0xB3, 0x1A, 0xB4, 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC, 0x03,
782 ];
783 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&cose_mac0)?;
784 assert_eq!(
785 raw_key,
786 vec![
787 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9, 0x21,
788 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C, 0x43,
789 0x22, 0xC8, 0xEE, 0x03, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95, 0x90, 0xA7, 0x5C, 0x5A,
790 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A, 0xA3, 0xB3, 0x1A, 0xB4,
791 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC,
792 ]
793 );
794 Ok(())
795 }
796
797 #[test]
798 fn test_parse_cose_mac0_for_coords_constructed_mac() -> Result<()> {
799 let x_coord: Vec<u8> = vec![0; 32];
800 let y_coord: Vec<u8> = vec![1; 32];
801 let mut expected_key: Vec<u8> = Vec::new();
802 expected_key.extend(&x_coord);
803 expected_key.extend(&y_coord);
804 let key_map: BTreeMap<Value, Value> = BTreeMap::from([
805 (Value::Integer(1), Value::Integer(2)),
806 (Value::Integer(3), Value::Integer(-7)),
807 (Value::Integer(-1), Value::Integer(1)),
808 (Value::Integer(-2), Value::Bytes(x_coord)),
809 (Value::Integer(-3), Value::Bytes(y_coord)),
810 ]);
811 let cose_mac0: Vec<Value> = vec![
812 Value::Integer(0),
813 Value::Integer(1),
814 Value::from(serde_cbor::to_vec(&key_map)?),
815 Value::Integer(2),
816 ];
817 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&serde_cbor::to_vec(
818 &Value::from(cose_mac0),
819 )?)?;
820 assert_eq!(expected_key, raw_key);
821 Ok(())
822 }
823
824 #[test]
825 fn test_extract_payload_from_cose_mac() -> Result<()> {
826 let key_map = Value::Map(BTreeMap::from([(Value::Integer(1), Value::Integer(2))]));
827 let payload = Value::Bytes(serde_cbor::to_vec(&key_map)?);
828 let cose_mac0 =
829 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
830 let extracted_map = RemoteProvisioningService::extract_payload_from_cose_mac(
831 &serde_cbor::to_vec(&cose_mac0)?,
832 )?;
833 assert_eq!(key_map, extracted_map);
834 Ok(())
835 }
836
837 #[test]
838 fn test_extract_payload_from_cose_mac_fails_malformed_payload() -> Result<()> {
839 let payload = Value::Bytes(vec![5; 10]);
840 let cose_mac0 =
841 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
842 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
843 &serde_cbor::to_vec(&cose_mac0)?,
844 );
845 assert!(extracted_payload.is_err());
846 Ok(())
847 }
848
849 #[test]
850 fn test_extract_payload_from_cose_mac_fails_type() -> Result<()> {
851 let payload = Value::Integer(1);
852 let cose_mac0 =
853 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
854 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
855 &serde_cbor::to_vec(&cose_mac0)?,
856 );
857 assert!(extracted_payload.is_err());
858 Ok(())
859 }
860
861 #[test]
862 fn test_extract_payload_from_cose_mac_fails_length() -> Result<()> {
863 let cose_mac0 = Value::Array(vec![Value::Integer(0), Value::Integer(1)]);
864 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
865 &serde_cbor::to_vec(&cose_mac0)?,
866 );
867 assert!(extracted_payload.is_err());
868 Ok(())
869 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800870
871 #[test]
872 #[ignore] // b/215746308
873 fn test_get_attestation_key_no_keys_provisioned() {
874 let mut db = crate::database::tests::new_test_db().unwrap();
875 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
876 mock_rpc.0.lock().unwrap().hw_info.uniqueId = Some(String::from("mallory"));
877
Seth Moore92648b62022-02-02 13:26:18 -0800878 let mut service: RemotelyProvisionedKeyPoolService = Default::default();
Seth Moore7ee79f92021-12-07 11:42:49 -0800879 service
Seth Moore92648b62022-02-02 13:26:18 -0800880 .unique_id_to_sec_level
881 .insert(String::from("mallory"), SecurityLevel::TRUSTED_ENVIRONMENT);
Seth Moore7ee79f92021-12-07 11:42:49 -0800882
883 assert_eq!(
884 service
885 .get_attestation_key(&mut db, 0, "mallory")
886 .unwrap_err()
887 .downcast::<error::Error>()
888 .unwrap(),
889 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
890 );
891 }
892
893 #[test]
894 #[ignore] // b/215746308
895 fn test_get_attestation_key() {
896 let mut db = crate::database::tests::new_test_db().unwrap();
897 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
898 let irpc_id = "paul";
899 let caller_uid = 0;
900
901 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
902 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800903 let mut remote_provisioning: RemoteProvisioningService = Default::default();
904 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
905 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
906 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800907
908 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
909 mock_values.lock().unwrap().private_key = vec![8, 6, 7, 5, 3, 0, 9];
910 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -0800911 remote_provisioning.generate_key_pair(&mut db, true, sec_level).unwrap();
Seth Moore7ee79f92021-12-07 11:42:49 -0800912
913 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
914 mock_values.lock().unwrap().maced_public_key.as_slice(),
915 )
916 .unwrap();
917 let batch_cert = get_fake_cert();
918 let certs = &[5, 6, 7, 8];
Seth Moore92648b62022-02-02 13:26:18 -0800919 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -0800920 .provision_cert_chain(
921 &mut db,
922 public_key.as_slice(),
923 batch_cert.as_slice(),
924 certs,
925 0,
926 sec_level
927 )
928 .is_ok());
929
930 // ensure we got the key we expected
Seth Moore92648b62022-02-02 13:26:18 -0800931 let first_key = key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800932 .get_attestation_key(&mut db, caller_uid, irpc_id)
933 .context("get first key")
934 .unwrap();
935 assert_eq!(first_key.keyBlob, mock_values.lock().unwrap().private_key);
936 assert_eq!(first_key.encodedCertChain, certs);
937
938 // ensure that multiple calls get the same key
939 assert_eq!(
940 first_key,
Seth Moore92648b62022-02-02 13:26:18 -0800941 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800942 .get_attestation_key(&mut db, caller_uid, irpc_id)
943 .context("get second key")
944 .unwrap()
945 );
946
947 // no more keys for new clients
948 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -0800949 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800950 .get_attestation_key(&mut db, caller_uid + 1, irpc_id)
951 .unwrap_err()
952 .downcast::<error::Error>()
953 .unwrap(),
954 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
955 );
956 }
957
958 #[test]
959 #[ignore] // b/215746308
960 fn test_get_attestation_key_gets_different_key_for_different_client() {
961 let mut db = crate::database::tests::new_test_db().unwrap();
962 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
963 let irpc_id = "ringo";
964 let first_caller = 0;
965 let second_caller = first_caller + 1;
966
967 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
968 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800969 let mut remote_provisioning: RemoteProvisioningService = Default::default();
970 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
971 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
972 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800973
974 // generate two distinct keys and provision them with certs
975 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
976 mock_values.lock().unwrap().private_key = vec![3, 1, 4, 1, 5];
977 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -0800978 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -0800979 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
980 mock_values.lock().unwrap().maced_public_key.as_slice(),
981 )
982 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -0800983 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -0800984 .provision_cert_chain(
985 &mut db,
986 public_key.as_slice(),
987 get_fake_cert().as_slice(),
988 &[1],
989 0,
990 sec_level
991 )
992 .is_ok());
993
994 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
995 mock_values.lock().unwrap().private_key = vec![9, 0, 2, 1, 0];
996 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x22);
Seth Moore92648b62022-02-02 13:26:18 -0800997 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -0800998 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
999 mock_values.lock().unwrap().maced_public_key.as_slice(),
1000 )
1001 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001002 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001003 .provision_cert_chain(
1004 &mut db,
1005 public_key.as_slice(),
1006 get_fake_cert().as_slice(),
1007 &[2],
1008 0,
1009 sec_level
1010 )
1011 .is_ok());
1012
1013 // make sure each caller gets a distinct key
1014 assert_ne!(
Seth Moore92648b62022-02-02 13:26:18 -08001015 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001016 .get_attestation_key(&mut db, first_caller, irpc_id)
1017 .context("get first key")
1018 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001019 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001020 .get_attestation_key(&mut db, second_caller, irpc_id)
1021 .context("get second key")
1022 .unwrap()
1023 );
1024
1025 // repeated calls should return the same key for a given caller
1026 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001027 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001028 .get_attestation_key(&mut db, first_caller, irpc_id)
1029 .context("first caller a")
1030 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001031 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001032 .get_attestation_key(&mut db, first_caller, irpc_id)
1033 .context("first caller b")
1034 .unwrap(),
1035 );
1036
1037 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001038 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001039 .get_attestation_key(&mut db, second_caller, irpc_id)
1040 .context("second caller a")
1041 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001042 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001043 .get_attestation_key(&mut db, second_caller, irpc_id)
1044 .context("second caller b")
1045 .unwrap()
1046 );
1047 }
Max Bires48fc2e52021-11-17 10:13:04 -08001048}