blob: e4099dfadb58df75760ed4908436f994cb50a871 [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 Bires55620ff2022-02-11 13:34:15 -080048use crate::database::{CertificateChain, KeyIdGuard, KeystoreDB, Uuid};
Max Bires97f96812021-02-23 23:44:57 -080049use 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 {
Seth Mooredfdcb872022-04-20 14:33:19 -070073 Self { security_level, km_uuid, is_hal_present: AtomicBool::new(true) }
Max Bires97f96812021-02-23 23:44:57 -080074 }
75
Max Bires55620ff2022-02-11 13:34:15 -080076 /// Returns the uuid for the KM instance attached to this RemProvState struct.
77 pub fn get_uuid(&self) -> Uuid {
78 self.km_uuid
79 }
80
Seth Mooredfdcb872022-04-20 14:33:19 -070081 fn is_rkp_only(&self) -> bool {
Max Bires65207b52022-03-29 23:58:08 -070082 let default_value = false;
83
Seth Mooredfdcb872022-04-20 14:33:19 -070084 let property_name = match self.security_level {
85 SecurityLevel::STRONGBOX => "remote_provisioning.strongbox.rkp_only",
86 SecurityLevel::TRUSTED_ENVIRONMENT => "remote_provisioning.tee.rkp_only",
Max Bires65207b52022-03-29 23:58:08 -070087 _ => return default_value,
88 };
89
90 rustutils::system_properties::read_bool(property_name, default_value)
91 .unwrap_or(default_value)
92 }
93
Max Bires97f96812021-02-23 23:44:57 -080094 /// Checks if remote provisioning is enabled and partially caches the result. On a hybrid system
95 /// remote provisioning can flip from being disabled to enabled depending on responses from the
96 /// server, so unfortunately caching the presence or absence of the HAL is not enough to fully
97 /// make decisions about the state of remote provisioning during runtime.
98 fn check_rem_prov_enabled(&self, db: &mut KeystoreDB) -> Result<bool> {
Seth Mooredfdcb872022-04-20 14:33:19 -070099 if self.is_rkp_only() {
Seth Moore562aebb2022-04-18 17:03:27 -0700100 return Ok(true);
101 }
Max Bires97f96812021-02-23 23:44:57 -0800102 if !self.is_hal_present.load(Ordering::Relaxed)
103 || get_remotely_provisioned_component(&self.security_level).is_err()
104 {
105 self.is_hal_present.store(false, Ordering::Relaxed);
106 return Ok(false);
107 }
108 // To check if remote provisioning is enabled on a system that supports both remote
109 // provisioning and factory provisioned keys, we only need to check if there are any
110 // keys at all generated to indicate if the app has gotten the signal to begin filling
111 // the key pool from the server.
112 let pool_status = db
113 .get_attestation_pool_status(0 /* date */, &self.km_uuid)
114 .context("In check_rem_prov_enabled: failed to get attestation pool status.")?;
115 Ok(pool_status.total != 0)
116 }
117
Max Bires97f96812021-02-23 23:44:57 -0800118 fn is_asymmetric_key(&self, params: &[KeyParameter]) -> bool {
119 params.iter().any(|kp| {
120 matches!(
121 kp,
122 KeyParameter {
123 tag: Tag::ALGORITHM,
124 value: KeyParameterValue::Algorithm(Algorithm::RSA)
125 } | KeyParameter {
126 tag: Tag::ALGORITHM,
127 value: KeyParameterValue::Algorithm(Algorithm::EC)
128 }
129 )
130 })
131 }
132
133 /// Checks to see (1) if the key in question should be attested to based on the algorithm and
134 /// (2) if remote provisioning is present and enabled on the system. If these conditions are
135 /// met, it makes an attempt to fetch the attestation key assigned to the `caller_uid`.
136 ///
137 /// It returns the ResponseCode `OUT_OF_KEYS` if there is not one key currently assigned to the
138 /// `caller_uid` and there are none available to assign.
Janis Danisevskis3541f3e2021-03-20 14:18:52 -0700139 pub fn get_remotely_provisioned_attestation_key_and_certs(
Max Bires97f96812021-02-23 23:44:57 -0800140 &self,
141 key: &KeyDescriptor,
142 caller_uid: u32,
143 params: &[KeyParameter],
144 db: &mut KeystoreDB,
Max Bires55620ff2022-02-11 13:34:15 -0800145 ) -> Result<Option<(KeyIdGuard, AttestationKey, Certificate)>> {
Max Bires97f96812021-02-23 23:44:57 -0800146 if !self.is_asymmetric_key(params) || !self.check_rem_prov_enabled(db)? {
147 // There is no remote provisioning component for this security level on the
148 // device. Return None so the underlying KM instance knows to use its
149 // factory provisioned key instead. Alternatively, it's not an asymmetric key
150 // and therefore will not be attested.
Janis Danisevskis3541f3e2021-03-20 14:18:52 -0700151 Ok(None)
Max Bires97f96812021-02-23 23:44:57 -0800152 } else {
Seth Moore7ee79f92021-12-07 11:42:49 -0800153 match get_rem_prov_attest_key(key.domain, caller_uid, db, &self.km_uuid) {
Max Bires31cdfb82021-07-06 02:59:25 -0700154 Err(e) => {
155 log::error!(
Max Bires65207b52022-03-29 23:58:08 -0700156 "In get_remote_provisioning_key_and_certs: Error occurred: {:?}",
Max Bires31cdfb82021-07-06 02:59:25 -0700157 e
158 );
Seth Mooredfdcb872022-04-20 14:33:19 -0700159 if self.is_rkp_only() {
Max Bires65207b52022-03-29 23:58:08 -0700160 return Err(e);
161 }
Shaquille Johnsonbcab6012022-09-02 11:16:24 +0000162 log_rkp_error_stats(
163 MetricsRkpError::FALL_BACK_DURING_HYBRID,
164 &self.security_level,
165 );
Max Bires31cdfb82021-07-06 02:59:25 -0700166 Ok(None)
167 }
168 Ok(v) => match v {
Max Bires55620ff2022-02-11 13:34:15 -0800169 Some((guard, cert_chain)) => Ok(Some((
170 guard,
Max Bires31cdfb82021-07-06 02:59:25 -0700171 AttestationKey {
172 keyBlob: cert_chain.private_key.to_vec(),
173 attestKeyParams: vec![],
174 issuerSubjectName: parse_subject_from_certificate(
175 &cert_chain.batch_cert,
176 )
Max Bires97f96812021-02-23 23:44:57 -0800177 .context(concat!(
Max Bires31cdfb82021-07-06 02:59:25 -0700178 "In get_remote_provisioning_key_and_certs: Failed to ",
179 "parse subject."
180 ))?,
181 },
182 Certificate { encodedCertificate: cert_chain.cert_chain },
183 ))),
184 None => Ok(None),
185 },
Max Bires97f96812021-02-23 23:44:57 -0800186 }
187 }
188 }
189}
Max Bires148c08e2020-10-13 13:41:41 -0700190/// Implementation of the IRemoteProvisioning service.
Max Biresb2e1d032021-02-08 21:35:05 -0800191#[derive(Default)]
Max Bires148c08e2020-10-13 13:41:41 -0700192pub struct RemoteProvisioningService {
Janis Danisevskis5f3a0572021-06-18 11:26:42 -0700193 device_by_sec_level: HashMap<SecurityLevel, Strong<dyn IRemotelyProvisionedComponent>>,
Max Biresd2ce46b2021-07-06 02:54:47 -0700194 curve_by_sec_level: HashMap<SecurityLevel, i32>,
Max Bires148c08e2020-10-13 13:41:41 -0700195}
196
197impl RemoteProvisioningService {
Max Biresb2e1d032021-02-08 21:35:05 -0800198 fn get_dev_by_sec_level(
199 &self,
200 sec_level: &SecurityLevel,
Seth Moore7ee79f92021-12-07 11:42:49 -0800201 ) -> Result<&dyn IRemotelyProvisionedComponent> {
Max Biresb2e1d032021-02-08 21:35:05 -0800202 if let Some(dev) = self.device_by_sec_level.get(sec_level) {
Seth Moore7ee79f92021-12-07 11:42:49 -0800203 Ok(dev.as_ref())
Max Biresb2e1d032021-02-08 21:35:05 -0800204 } else {
205 Err(error::Error::sys()).context(concat!(
206 "In get_dev_by_sec_level: Remote instance for requested security level",
207 " not found."
208 ))
209 }
210 }
211
Max Bires148c08e2020-10-13 13:41:41 -0700212 /// Creates a new instance of the remote provisioning service
Stephen Crane221bbb52020-12-16 15:52:10 -0800213 pub fn new_native_binder() -> Result<Strong<dyn IRemoteProvisioning>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800214 let mut result: Self = Default::default();
215 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
216 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
Max Biresd2ce46b2021-07-06 02:54:47 -0700217 result.curve_by_sec_level.insert(
218 SecurityLevel::TRUSTED_ENVIRONMENT,
219 dev.getHardwareInfo()
220 .context("In new_native_binder: Failed to get hardware info for the TEE.")?
221 .supportedEekCurve,
222 );
Max Biresb2e1d032021-02-08 21:35:05 -0800223 result.device_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, dev);
224 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
Max Biresd2ce46b2021-07-06 02:54:47 -0700225 result.curve_by_sec_level.insert(
226 SecurityLevel::STRONGBOX,
227 dev.getHardwareInfo()
228 .context("In new_native_binder: Failed to get hardware info for StrongBox.")?
229 .supportedEekCurve,
230 );
Max Biresb2e1d032021-02-08 21:35:05 -0800231 result.device_by_sec_level.insert(SecurityLevel::STRONGBOX, dev);
232 }
Andrew Walbrande45c8b2021-04-13 14:42:38 +0000233 Ok(BnRemoteProvisioning::new_binder(result, BinderFeatures::default()))
Max Bires148c08e2020-10-13 13:41:41 -0700234 }
235
Max Bires48fc2e52021-11-17 10:13:04 -0800236 fn extract_payload_from_cose_mac(data: &[u8]) -> Result<Value> {
237 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data).context(
238 "In extract_payload_from_cose_mac: COSE_Mac0 returned from IRPC cannot be parsed",
239 )?;
240 if cose_mac0.len() != COSE_MAC0_LEN {
241 return Err(error::Error::sys()).context(format!(
242 "In extract_payload_from_cose_mac: COSE_Mac0 has improper length. \
243 Expected: {}, Actual: {}",
244 COSE_MAC0_LEN,
245 cose_mac0.len(),
246 ));
247 }
248 match &cose_mac0[COSE_MAC0_PAYLOAD] {
249 Value::Bytes(key) => Ok(serde_cbor::from_slice(key)
250 .context("In extract_payload_from_cose_mac: COSE_Mac0 payload is malformed.")?),
251 _ => Err(error::Error::sys()).context(
252 "In extract_payload_from_cose_mac: COSE_Mac0 payload is the wrong type.",
253 )?,
254 }
255 }
256
Max Bires148c08e2020-10-13 13:41:41 -0700257 /// Generates a CBOR blob which will be assembled by the calling code into a larger
258 /// CBOR blob intended for delivery to a provisioning serever. This blob will contain
259 /// `num_csr` certificate signing requests for attestation keys generated in the TEE,
260 /// along with a server provided `eek` and `challenge`. The endpoint encryption key will
261 /// be used to encrypt the sensitive contents being transmitted to the server, and the
262 /// challenge will ensure freshness. A `test_mode` flag will instruct the remote provisioning
263 /// HAL if it is okay to accept EEKs that aren't signed by something that chains back to the
264 /// baked in root of trust in the underlying IRemotelyProvisionedComponent instance.
Max Bires834dd362021-03-23 13:01:57 -0700265 #[allow(clippy::too_many_arguments)]
Max Bires148c08e2020-10-13 13:41:41 -0700266 pub fn generate_csr(
267 &self,
Max Biresb2e1d032021-02-08 21:35:05 -0800268 test_mode: bool,
269 num_csr: i32,
270 eek: &[u8],
271 challenge: &[u8],
272 sec_level: SecurityLevel,
273 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700274 device_info: &mut DeviceInfo,
Max Bires148c08e2020-10-13 13:41:41 -0700275 ) -> Result<Vec<u8>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800276 let dev = self.get_dev_by_sec_level(&sec_level)?;
277 let (_, _, uuid) = get_keymint_device(&sec_level)?;
278 let keys_to_sign = DB.with::<_, Result<Vec<MacedPublicKey>>>(|db| {
279 let mut db = db.borrow_mut();
280 Ok(db
281 .fetch_unsigned_attestation_keys(num_csr, &uuid)?
282 .iter()
283 .map(|key| MacedPublicKey { macedKey: key.to_vec() })
284 .collect())
285 })?;
Max Bires48fc2e52021-11-17 10:13:04 -0800286 let mac = map_rem_prov_error(dev.generateCertificateRequest(
Max Biresb2e1d032021-02-08 21:35:05 -0800287 test_mode,
288 &keys_to_sign,
289 eek,
290 challenge,
Max Bires834dd362021-03-23 13:01:57 -0700291 device_info,
Max Biresb2e1d032021-02-08 21:35:05 -0800292 protected_data,
293 ))
294 .context("In generate_csr: Failed to generate csr")?;
Max Bires48fc2e52021-11-17 10:13:04 -0800295 let mut mac_and_keys: Vec<Value> = vec![Value::from(mac)];
Max Bires97f96812021-02-23 23:44:57 -0800296 for maced_public_key in keys_to_sign {
Max Bires48fc2e52021-11-17 10:13:04 -0800297 mac_and_keys.push(
298 Self::extract_payload_from_cose_mac(&maced_public_key.macedKey)
299 .context("In generate_csr: Failed to get the payload from the COSE_Mac0")?,
300 )
Max Bires97f96812021-02-23 23:44:57 -0800301 }
Max Bires48fc2e52021-11-17 10:13:04 -0800302 let cbor_array: Value = Value::Array(mac_and_keys);
303 serde_cbor::to_vec(&cbor_array)
304 .context("In generate_csr: Failed to serialize the mac and keys array")
Max Bires148c08e2020-10-13 13:41:41 -0700305 }
306
307 /// Provisions a certificate chain for a key whose CSR was included in generate_csr. The
308 /// `public_key` is used to index into the SQL database in order to insert the `certs` blob
309 /// which represents a PEM encoded X.509 certificate chain. The `expiration_date` is provided
310 /// as a convenience from the caller to avoid having to parse the certificates semantically
311 /// here.
312 pub fn provision_cert_chain(
313 &self,
Seth Moore7ee79f92021-12-07 11:42:49 -0800314 db: &mut KeystoreDB,
Max Bires148c08e2020-10-13 13:41:41 -0700315 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800316 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700317 certs: &[u8],
318 expiration_date: i64,
319 sec_level: SecurityLevel,
320 ) -> Result<()> {
Seth Moore7ee79f92021-12-07 11:42:49 -0800321 let (_, _, uuid) = get_keymint_device(&sec_level)?;
322 db.store_signed_attestation_certificate_chain(
323 public_key,
324 batch_cert,
325 certs, /* DER encoded certificate chain */
326 expiration_date,
327 &uuid,
328 )
Max Bires148c08e2020-10-13 13:41:41 -0700329 }
330
Max Bires48fc2e52021-11-17 10:13:04 -0800331 fn parse_cose_mac0_for_coords(data: &[u8]) -> Result<Vec<u8>> {
332 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data).context(
333 "In parse_cose_mac0_for_coords: COSE_Mac0 returned from IRPC cannot be parsed",
334 )?;
335 if cose_mac0.len() != COSE_MAC0_LEN {
336 return Err(error::Error::sys()).context(format!(
337 "In parse_cose_mac0_for_coords: COSE_Mac0 has improper length. \
338 Expected: {}, Actual: {}",
339 COSE_MAC0_LEN,
340 cose_mac0.len(),
341 ));
342 }
343 let cose_key: BTreeMap<Value, Value> = match &cose_mac0[COSE_MAC0_PAYLOAD] {
344 Value::Bytes(key) => serde_cbor::from_slice(key)
345 .context("In parse_cose_mac0_for_coords: COSE_Key is malformed.")?,
346 _ => Err(error::Error::sys())
347 .context("In parse_cose_mac0_for_coords: COSE_Mac0 payload is the wrong type.")?,
348 };
349 if !cose_key.contains_key(&COSE_KEY_XCOORD) || !cose_key.contains_key(&COSE_KEY_YCOORD) {
350 return Err(error::Error::sys()).context(
351 "In parse_cose_mac0_for_coords: \
352 COSE_Key returned from IRPC is lacking required fields",
353 );
354 }
355 let mut raw_key: Vec<u8> = vec![0; 64];
356 match &cose_key[&COSE_KEY_XCOORD] {
357 Value::Bytes(x_coord) if x_coord.len() == 32 => {
358 raw_key[0..32].clone_from_slice(x_coord)
359 }
360 Value::Bytes(x_coord) => {
361 return Err(error::Error::sys()).context(format!(
362 "In parse_cose_mac0_for_coords: COSE_Key X-coordinate is not the right length. \
363 Expected: 32; Actual: {}",
364 x_coord.len()
365 ))
366 }
367 _ => {
368 return Err(error::Error::sys())
369 .context("In parse_cose_mac0_for_coords: COSE_Key X-coordinate is not a bstr")
370 }
371 }
372 match &cose_key[&COSE_KEY_YCOORD] {
373 Value::Bytes(y_coord) if y_coord.len() == 32 => {
374 raw_key[32..64].clone_from_slice(y_coord)
375 }
376 Value::Bytes(y_coord) => {
377 return Err(error::Error::sys()).context(format!(
378 "In parse_cose_mac0_for_coords: COSE_Key Y-coordinate is not the right length. \
379 Expected: 32; Actual: {}",
380 y_coord.len()
381 ))
382 }
383 _ => {
384 return Err(error::Error::sys())
385 .context("In parse_cose_mac0_for_coords: COSE_Key Y-coordinate is not a bstr")
386 }
387 }
388 Ok(raw_key)
389 }
390
Max Bires148c08e2020-10-13 13:41:41 -0700391 /// Submits a request to the Remote Provisioner HAL to generate a signing key pair.
392 /// `is_test_mode` indicates whether or not the returned public key should be marked as being
393 /// for testing in order to differentiate them from private keys. If the call is successful,
394 /// the key pair is then added to the database.
Seth Moore7ee79f92021-12-07 11:42:49 -0800395 pub fn generate_key_pair(
396 &self,
397 db: &mut KeystoreDB,
398 is_test_mode: bool,
399 sec_level: SecurityLevel,
400 ) -> Result<()> {
Max Biresb2e1d032021-02-08 21:35:05 -0800401 let (_, _, uuid) = get_keymint_device(&sec_level)?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800402 let dev = self.get_dev_by_sec_level(&sec_level).context(format!(
403 "In generate_key_pair: Failed to get device for security level {:?}",
404 sec_level
405 ))?;
Max Biresb2e1d032021-02-08 21:35:05 -0800406 let mut maced_key = MacedPublicKey { macedKey: Vec::new() };
407 let priv_key =
408 map_rem_prov_error(dev.generateEcdsaP256KeyPair(is_test_mode, &mut maced_key))
409 .context("In generate_key_pair: Failed to generated ECDSA keypair.")?;
Max Bires48fc2e52021-11-17 10:13:04 -0800410 let raw_key = Self::parse_cose_mac0_for_coords(&maced_key.macedKey)
411 .context("In generate_key_pair: Failed to parse raw key")?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800412 db.create_attestation_key_entry(&maced_key.macedKey, &raw_key, &priv_key, &uuid)
413 .context("In generate_key_pair: Failed to insert attestation key entry")
Max Biresb2e1d032021-02-08 21:35:05 -0800414 }
415
416 /// Checks the security level of each available IRemotelyProvisionedComponent hal and returns
417 /// all levels in an array to the caller.
Max Biresd2ce46b2021-07-06 02:54:47 -0700418 pub fn get_implementation_info(&self) -> Result<Vec<ImplInfo>> {
419 Ok(self
420 .curve_by_sec_level
421 .iter()
422 .map(|(sec_level, curve)| ImplInfo { secLevel: *sec_level, supportedCurve: *curve })
423 .collect())
Max Bires148c08e2020-10-13 13:41:41 -0700424 }
Max Bires60d7ed12021-03-05 15:59:22 -0800425
426 /// Deletes all attestation keys generated by the IRemotelyProvisionedComponent from the device,
427 /// regardless of what state of the attestation key lifecycle they were in.
428 pub fn delete_all_keys(&self) -> Result<i64> {
429 DB.with::<_, Result<i64>>(|db| {
430 let mut db = db.borrow_mut();
Matthew Maurerb77a28d2021-05-07 16:08:20 -0700431 db.delete_all_attestation_keys()
Max Bires60d7ed12021-03-05 15:59:22 -0800432 })
433 }
Max Bires148c08e2020-10-13 13:41:41 -0700434}
435
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000436/// Populates the AttestationPoolStatus parcelable with information about how many
437/// certs will be expiring by the date provided in `expired_by` along with how many
438/// keys have not yet been assigned.
439pub fn get_pool_status(expired_by: i64, sec_level: SecurityLevel) -> Result<AttestationPoolStatus> {
440 let (_, _, uuid) = get_keymint_device(&sec_level)?;
441 DB.with::<_, Result<AttestationPoolStatus>>(|db| {
442 let mut db = db.borrow_mut();
443 // delete_expired_attestation_keys is always safe to call, and will remove anything
444 // older than the date at the time of calling. No work should be done on the
445 // attestation keys unless the pool status is checked first, so this call should be
446 // enough to routinely clean out expired keys.
447 db.delete_expired_attestation_keys()?;
448 db.get_attestation_pool_status(expired_by, &uuid)
449 })
450}
451
Seth Moore7ee79f92021-12-07 11:42:49 -0800452/// Fetches a remote provisioning attestation key and certificate chain inside of the
453/// returned `CertificateChain` struct if one exists for the given caller_uid. If one has not
454/// been assigned, this function will assign it. If there are no signed attestation keys
455/// available to be assigned, it will return the ResponseCode `OUT_OF_KEYS`
456fn get_rem_prov_attest_key(
457 domain: Domain,
458 caller_uid: u32,
459 db: &mut KeystoreDB,
460 km_uuid: &Uuid,
Max Bires55620ff2022-02-11 13:34:15 -0800461) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
Seth Moore7ee79f92021-12-07 11:42:49 -0800462 match domain {
463 Domain::APP => {
464 // Attempt to get an Attestation Key once. If it fails, then the app doesn't
465 // have a valid chain assigned to it. The helper function will return None after
466 // attempting to assign a key. An error will be thrown if the pool is simply out
467 // of usable keys. Then another attempt to fetch the just-assigned key will be
468 // made. If this fails too, something is very wrong.
469 get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid)
470 .context("In get_rem_prov_attest_key: Failed to get a key")?
471 .map_or_else(
472 || get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid),
473 |v| Ok(Some(v)),
474 )
475 .context(concat!(
476 "In get_rem_prov_attest_key: Failed to get a key after",
477 "attempting to assign one."
478 ))?
479 .map_or_else(
480 || {
481 Err(Error::sys()).context(concat!(
482 "In get_rem_prov_attest_key: Attempted to assign a ",
483 "key and failed silently. Something is very wrong."
484 ))
485 },
Max Bires55620ff2022-02-11 13:34:15 -0800486 |(guard, cert_chain)| Ok(Some((guard, cert_chain))),
Seth Moore7ee79f92021-12-07 11:42:49 -0800487 )
488 }
489 _ => Ok(None),
490 }
491}
492
493/// Returns None if an AttestationKey fails to be assigned. Errors if no keys are available.
494fn get_rem_prov_attest_key_helper(
495 domain: Domain,
496 caller_uid: u32,
497 db: &mut KeystoreDB,
498 km_uuid: &Uuid,
Max Bires55620ff2022-02-11 13:34:15 -0800499) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
500 let guard_and_chain = db
Seth Moore7ee79f92021-12-07 11:42:49 -0800501 .retrieve_attestation_key_and_cert_chain(domain, caller_uid as i64, km_uuid)
502 .context("In get_rem_prov_attest_key_helper: Failed to retrieve a key + cert chain")?;
Max Bires55620ff2022-02-11 13:34:15 -0800503 match guard_and_chain {
504 Some((guard, cert_chain)) => Ok(Some((guard, cert_chain))),
Seth Moore7ee79f92021-12-07 11:42:49 -0800505 // Either this app needs to be assigned a key, or the pool is empty. An error will
506 // be thrown if there is no key available to assign. This will indicate that the app
507 // should be nudged to provision more keys so keystore can retry.
508 None => {
509 db.assign_attestation_key(domain, caller_uid as i64, km_uuid)
510 .context("In get_rem_prov_attest_key_helper: Failed to assign a key")?;
511 Ok(None)
512 }
513 }
514}
515
Max Bires148c08e2020-10-13 13:41:41 -0700516impl binder::Interface for RemoteProvisioningService {}
517
518// Implementation of IRemoteProvisioning. See AIDL spec at
519// :aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
520impl IRemoteProvisioning for RemoteProvisioningService {
521 fn getPoolStatus(
522 &self,
523 expired_by: i64,
524 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700525 ) -> binder::Result<AttestationPoolStatus> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000526 let _wp = wd::watch_millis("IRemoteProvisioning::getPoolStatus", 500);
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000527 map_or_log_err(get_pool_status(expired_by, sec_level), Ok)
Max Bires148c08e2020-10-13 13:41:41 -0700528 }
529
530 fn generateCsr(
531 &self,
532 test_mode: bool,
533 num_csr: i32,
534 eek: &[u8],
535 challenge: &[u8],
536 sec_level: SecurityLevel,
Max Biresb2e1d032021-02-08 21:35:05 -0800537 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700538 device_info: &mut DeviceInfo,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700539 ) -> binder::Result<Vec<u8>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000540 let _wp = wd::watch_millis("IRemoteProvisioning::generateCsr", 500);
Max Biresb2e1d032021-02-08 21:35:05 -0800541 map_or_log_err(
Max Bires834dd362021-03-23 13:01:57 -0700542 self.generate_csr(
543 test_mode,
544 num_csr,
545 eek,
546 challenge,
547 sec_level,
548 protected_data,
549 device_info,
550 ),
Max Biresb2e1d032021-02-08 21:35:05 -0800551 Ok,
552 )
Max Bires148c08e2020-10-13 13:41:41 -0700553 }
554
555 fn provisionCertChain(
556 &self,
557 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800558 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700559 certs: &[u8],
560 expiration_date: i64,
561 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700562 ) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000563 let _wp = wd::watch_millis("IRemoteProvisioning::provisionCertChain", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800564 DB.with::<_, binder::Result<()>>(|db| {
565 map_or_log_err(
566 self.provision_cert_chain(
567 &mut db.borrow_mut(),
568 public_key,
569 batch_cert,
570 certs,
571 expiration_date,
572 sec_level,
573 ),
574 Ok,
575 )
576 })
Max Bires148c08e2020-10-13 13:41:41 -0700577 }
578
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700579 fn generateKeyPair(&self, is_test_mode: bool, sec_level: SecurityLevel) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000580 let _wp = wd::watch_millis("IRemoteProvisioning::generateKeyPair", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800581 DB.with::<_, binder::Result<()>>(|db| {
582 map_or_log_err(
583 self.generate_key_pair(&mut db.borrow_mut(), is_test_mode, sec_level),
584 Ok,
585 )
586 })
Max Bires148c08e2020-10-13 13:41:41 -0700587 }
Max Biresb2e1d032021-02-08 21:35:05 -0800588
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700589 fn getImplementationInfo(&self) -> binder::Result<Vec<ImplInfo>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000590 let _wp = wd::watch_millis("IRemoteProvisioning::getSecurityLevels", 500);
Max Biresd2ce46b2021-07-06 02:54:47 -0700591 map_or_log_err(self.get_implementation_info(), Ok)
Max Biresb2e1d032021-02-08 21:35:05 -0800592 }
Max Bires60d7ed12021-03-05 15:59:22 -0800593
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700594 fn deleteAllKeys(&self) -> binder::Result<i64> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000595 let _wp = wd::watch_millis("IRemoteProvisioning::deleteAllKeys", 500);
Max Bires60d7ed12021-03-05 15:59:22 -0800596 map_or_log_err(self.delete_all_keys(), Ok)
597 }
Max Bires148c08e2020-10-13 13:41:41 -0700598}
Max Bires48fc2e52021-11-17 10:13:04 -0800599
Seth Moore92648b62022-02-02 13:26:18 -0800600/// Implementation of the IRemotelyProvisionedKeyPool service.
601#[derive(Default)]
602pub struct RemotelyProvisionedKeyPoolService {
603 unique_id_to_sec_level: HashMap<String, SecurityLevel>,
604}
605
606impl RemotelyProvisionedKeyPoolService {
607 /// Fetches a remotely provisioned certificate chain and key for the given client uid that
608 /// was provisioned using the IRemotelyProvisionedComponent with the given id. The same key
609 /// will be returned for a given caller_uid on every request. If there are no attestation keys
610 /// available, `OUT_OF_KEYS` is returned.
611 fn get_attestation_key(
612 &self,
613 db: &mut KeystoreDB,
614 caller_uid: i32,
615 irpc_id: &str,
616 ) -> Result<RemotelyProvisionedKey> {
617 log::info!("get_attestation_key(self, {}, {}", caller_uid, irpc_id);
618
619 let sec_level = self
620 .unique_id_to_sec_level
621 .get(irpc_id)
622 .ok_or(Error::Rc(ResponseCode::INVALID_ARGUMENT))
623 .context(format!("In get_attestation_key: unknown irpc id '{}'", irpc_id))?;
624 let (_, _, km_uuid) = get_keymint_device(sec_level)?;
625
Max Bires55620ff2022-02-11 13:34:15 -0800626 let guard_and_cert_chain =
627 get_rem_prov_attest_key(Domain::APP, caller_uid as u32, db, &km_uuid)
628 .context("In get_attestation_key")?;
629 match guard_and_cert_chain {
630 Some((_, chain)) => Ok(RemotelyProvisionedKey {
Seth Moore92648b62022-02-02 13:26:18 -0800631 keyBlob: chain.private_key.to_vec(),
632 encodedCertChain: chain.cert_chain,
633 }),
634 // It should be impossible to get `None`, but handle it just in case as a
635 // precaution against future behavioral changes in `get_rem_prov_attest_key`.
636 None => Err(error::Error::Rc(ResponseCode::OUT_OF_KEYS))
637 .context("In get_attestation_key: No available attestation keys"),
638 }
639 }
640
641 /// Creates a new instance of the remotely provisioned key pool service, used for fetching
642 /// remotely provisioned attestation keys.
643 pub fn new_native_binder() -> Result<Strong<dyn IRemotelyProvisionedKeyPool>> {
644 let mut result: Self = Default::default();
645
646 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
647 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
648 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
649 result.unique_id_to_sec_level.insert(id, SecurityLevel::TRUSTED_ENVIRONMENT);
650 }
651
652 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
653 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
654 if result.unique_id_to_sec_level.contains_key(&id) {
655 anyhow::bail!("In new_native_binder: duplicate irpc id found: '{}'", id)
656 }
657 result.unique_id_to_sec_level.insert(id, SecurityLevel::STRONGBOX);
658 }
659 }
660
661 // If none of the remotely provisioned components have unique ids, then we shouldn't
662 // bother publishing the service, as it's impossible to match keys with their backends.
663 if result.unique_id_to_sec_level.is_empty() {
664 anyhow::bail!(
665 "In new_native_binder: No remotely provisioned components have unique ids"
666 )
667 }
668
669 Ok(BnRemotelyProvisionedKeyPool::new_binder(
670 result,
671 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
672 ))
673 }
674}
675
676impl binder::Interface for RemotelyProvisionedKeyPoolService {}
677
Seth Moore7ee79f92021-12-07 11:42:49 -0800678// Implementation of IRemotelyProvisionedKeyPool. See AIDL spec at
679// :aidl/android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.aidl
Seth Moore92648b62022-02-02 13:26:18 -0800680impl IRemotelyProvisionedKeyPool for RemotelyProvisionedKeyPoolService {
Seth Moore7ee79f92021-12-07 11:42:49 -0800681 fn getAttestationKey(
682 &self,
683 caller_uid: i32,
684 irpc_id: &str,
685 ) -> binder::Result<RemotelyProvisionedKey> {
686 let _wp = wd::watch_millis("IRemotelyProvisionedKeyPool::getAttestationKey", 500);
687 map_or_log_err(check_keystore_permission(KeystorePerm::GetAttestationKey), Ok)?;
688 DB.with::<_, binder::Result<RemotelyProvisionedKey>>(|db| {
689 map_or_log_err(self.get_attestation_key(&mut db.borrow_mut(), caller_uid, irpc_id), Ok)
690 })
691 }
692}
693
Max Bires48fc2e52021-11-17 10:13:04 -0800694#[cfg(test)]
695mod tests {
696 use super::*;
697 use serde_cbor::Value;
698 use std::collections::BTreeMap;
Seth Moore7ee79f92021-12-07 11:42:49 -0800699 use std::sync::{Arc, Mutex};
700 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
701 RpcHardwareInfo::RpcHardwareInfo,
702 };
703
704 #[derive(Default)]
705 struct MockRemotelyProvisionedComponentValues {
706 hw_info: RpcHardwareInfo,
707 private_key: Vec<u8>,
708 maced_public_key: Vec<u8>,
709 }
710
711 // binder::Interface requires the Send trait, so we have to use a Mutex even though the test
712 // is single threaded.
713 #[derive(Default)]
714 struct MockRemotelyProvisionedComponent(Arc<Mutex<MockRemotelyProvisionedComponentValues>>);
715
716 impl binder::Interface for MockRemotelyProvisionedComponent {}
717
718 impl IRemotelyProvisionedComponent for MockRemotelyProvisionedComponent {
719 fn getHardwareInfo(&self) -> binder::Result<RpcHardwareInfo> {
720 Ok(self.0.lock().unwrap().hw_info.clone())
721 }
722
723 fn generateEcdsaP256KeyPair(
724 &self,
725 test_mode: bool,
726 maced_public_key: &mut MacedPublicKey,
727 ) -> binder::Result<Vec<u8>> {
728 assert!(test_mode);
729 maced_public_key.macedKey = self.0.lock().unwrap().maced_public_key.clone();
730 Ok(self.0.lock().unwrap().private_key.clone())
731 }
732
733 fn generateCertificateRequest(
734 &self,
735 _test_mode: bool,
736 _keys_to_sign: &[MacedPublicKey],
737 _eek: &[u8],
738 _challenge: &[u8],
739 _device_info: &mut DeviceInfo,
740 _protected_data: &mut ProtectedData,
741 ) -> binder::Result<Vec<u8>> {
742 Err(binder::StatusCode::INVALID_OPERATION.into())
743 }
Tri Vo113a1c92022-10-02 15:23:19 -0700744
745 fn generateCertificateRequestV2(
746 &self,
747 _keys_to_sign: &[MacedPublicKey],
748 _challenge: &[u8],
749 ) -> binder::Result<Vec<u8>> {
750 Err(binder::StatusCode::INVALID_OPERATION.into())
751 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800752 }
753
754 // Hard coded cert that can be parsed -- the content doesn't matter for testing, only that it's valid.
755 fn get_fake_cert() -> Vec<u8> {
756 vec![
757 0x30, 0x82, 0x01, 0xbb, 0x30, 0x82, 0x01, 0x61, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
758 0x14, 0x3a, 0xd5, 0x67, 0xce, 0xfe, 0x93, 0xe1, 0xea, 0xb7, 0xe4, 0xbf, 0x64, 0x19,
759 0xa4, 0x11, 0xe1, 0x87, 0x40, 0x20, 0x37, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
760 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
761 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
762 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
763 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
764 0x6c, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x30, 0x32, 0x32,
765 0x30, 0x38, 0x35, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x34, 0x32, 0x36, 0x32,
766 0x32, 0x30, 0x38, 0x35, 0x32, 0x5a, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
767 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
768 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
769 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f,
770 0x67, 0x6c, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
771 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
772 0x00, 0x04, 0x1e, 0xac, 0x0c, 0xe0, 0x0d, 0xc5, 0x25, 0x84, 0x1b, 0xd2, 0x77, 0x2d,
773 0xe7, 0xba, 0xf1, 0xde, 0xa7, 0xf6, 0x39, 0x7f, 0x38, 0x91, 0xbf, 0xa4, 0x58, 0xf5,
774 0x62, 0x6b, 0xce, 0x06, 0xcf, 0xb9, 0x73, 0x91, 0x0d, 0x8a, 0x60, 0xa0, 0xc6, 0xa2,
775 0x22, 0xe6, 0x51, 0x2e, 0x58, 0xd6, 0x43, 0x02, 0x80, 0x43, 0x44, 0x29, 0x38, 0x9a,
776 0x99, 0xf3, 0xa4, 0xdd, 0xd0, 0xb4, 0x6f, 0x8b, 0x44, 0x2d, 0xa3, 0x53, 0x30, 0x51,
777 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdb, 0x13, 0x68,
778 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe, 0x42, 0x3c, 0xd9, 0x3f, 0x1a,
779 0x33, 0xe9, 0xaa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
780 0x80, 0x14, 0xdb, 0x13, 0x68, 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe,
781 0x42, 0x3c, 0xd9, 0x3f, 0x1a, 0x33, 0xe9, 0xaa, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
782 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06,
783 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
784 0x02, 0x20, 0x10, 0xdf, 0x40, 0xc3, 0x20, 0x54, 0x36, 0xb5, 0xc9, 0x3c, 0x70, 0xe3,
785 0x55, 0x37, 0xd2, 0x04, 0x51, 0xeb, 0x0f, 0x18, 0x83, 0xd0, 0x58, 0xa1, 0x08, 0x77,
786 0x8d, 0x4d, 0xa4, 0x20, 0xee, 0x33, 0x02, 0x21, 0x00, 0x8d, 0xe3, 0xa6, 0x6c, 0x0d,
787 0x86, 0x25, 0xdc, 0x59, 0x0d, 0x21, 0x43, 0x22, 0x3a, 0xb9, 0xa1, 0x73, 0x28, 0xc9,
788 0x16, 0x9e, 0x91, 0x15, 0xc4, 0xc3, 0xd7, 0xeb, 0xe5, 0xce, 0xdc, 0x1c, 0x1b,
789 ]
790 }
791
792 // Generate a fake COSE_Mac0 with a key that's just `byte` repeated
793 fn generate_maced_pubkey(byte: u8) -> Vec<u8> {
794 vec![
795 0x84, 0x43, 0xA1, 0x01, 0x05, 0xA0, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20,
796 0x01, 0x21, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
797 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
798 byte, byte, byte, byte, byte, byte, byte, byte, 0x22, 0x58, 0x20, byte, byte, byte,
799 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
800 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
801 byte, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
802 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
803 byte, byte, byte, byte, byte, byte, byte,
804 ]
805 }
Max Bires48fc2e52021-11-17 10:13:04 -0800806
807 #[test]
808 fn test_parse_cose_mac0_for_coords_raw_bytes() -> Result<()> {
809 let cose_mac0: Vec<u8> = vec![
810 0x84, 0x01, 0x02, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
811 0x20, 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9,
812 0x21, 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C,
813 0x43, 0x22, 0xC8, 0xEE, 0x03, 0x22, 0x58, 0x20, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95,
814 0x90, 0xA7, 0x5C, 0x5A, 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A,
815 0xA3, 0xB3, 0x1A, 0xB4, 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC, 0x03,
816 ];
817 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&cose_mac0)?;
818 assert_eq!(
819 raw_key,
820 vec![
821 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9, 0x21,
822 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C, 0x43,
823 0x22, 0xC8, 0xEE, 0x03, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95, 0x90, 0xA7, 0x5C, 0x5A,
824 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A, 0xA3, 0xB3, 0x1A, 0xB4,
825 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC,
826 ]
827 );
828 Ok(())
829 }
830
831 #[test]
832 fn test_parse_cose_mac0_for_coords_constructed_mac() -> Result<()> {
833 let x_coord: Vec<u8> = vec![0; 32];
834 let y_coord: Vec<u8> = vec![1; 32];
835 let mut expected_key: Vec<u8> = Vec::new();
836 expected_key.extend(&x_coord);
837 expected_key.extend(&y_coord);
838 let key_map: BTreeMap<Value, Value> = BTreeMap::from([
839 (Value::Integer(1), Value::Integer(2)),
840 (Value::Integer(3), Value::Integer(-7)),
841 (Value::Integer(-1), Value::Integer(1)),
842 (Value::Integer(-2), Value::Bytes(x_coord)),
843 (Value::Integer(-3), Value::Bytes(y_coord)),
844 ]);
845 let cose_mac0: Vec<Value> = vec![
846 Value::Integer(0),
847 Value::Integer(1),
848 Value::from(serde_cbor::to_vec(&key_map)?),
849 Value::Integer(2),
850 ];
851 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&serde_cbor::to_vec(
852 &Value::from(cose_mac0),
853 )?)?;
854 assert_eq!(expected_key, raw_key);
855 Ok(())
856 }
857
858 #[test]
859 fn test_extract_payload_from_cose_mac() -> Result<()> {
860 let key_map = Value::Map(BTreeMap::from([(Value::Integer(1), Value::Integer(2))]));
861 let payload = Value::Bytes(serde_cbor::to_vec(&key_map)?);
862 let cose_mac0 =
863 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
864 let extracted_map = RemoteProvisioningService::extract_payload_from_cose_mac(
865 &serde_cbor::to_vec(&cose_mac0)?,
866 )?;
867 assert_eq!(key_map, extracted_map);
868 Ok(())
869 }
870
871 #[test]
872 fn test_extract_payload_from_cose_mac_fails_malformed_payload() -> Result<()> {
873 let payload = Value::Bytes(vec![5; 10]);
874 let cose_mac0 =
875 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
876 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
877 &serde_cbor::to_vec(&cose_mac0)?,
878 );
879 assert!(extracted_payload.is_err());
880 Ok(())
881 }
882
883 #[test]
884 fn test_extract_payload_from_cose_mac_fails_type() -> Result<()> {
885 let payload = Value::Integer(1);
886 let cose_mac0 =
887 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
888 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
889 &serde_cbor::to_vec(&cose_mac0)?,
890 );
891 assert!(extracted_payload.is_err());
892 Ok(())
893 }
894
895 #[test]
896 fn test_extract_payload_from_cose_mac_fails_length() -> Result<()> {
897 let cose_mac0 = Value::Array(vec![Value::Integer(0), Value::Integer(1)]);
898 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
899 &serde_cbor::to_vec(&cose_mac0)?,
900 );
901 assert!(extracted_payload.is_err());
902 Ok(())
903 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800904
905 #[test]
906 #[ignore] // b/215746308
907 fn test_get_attestation_key_no_keys_provisioned() {
908 let mut db = crate::database::tests::new_test_db().unwrap();
909 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
910 mock_rpc.0.lock().unwrap().hw_info.uniqueId = Some(String::from("mallory"));
911
Seth Moore92648b62022-02-02 13:26:18 -0800912 let mut service: RemotelyProvisionedKeyPoolService = Default::default();
Seth Moore7ee79f92021-12-07 11:42:49 -0800913 service
Seth Moore92648b62022-02-02 13:26:18 -0800914 .unique_id_to_sec_level
915 .insert(String::from("mallory"), SecurityLevel::TRUSTED_ENVIRONMENT);
Seth Moore7ee79f92021-12-07 11:42:49 -0800916
917 assert_eq!(
918 service
919 .get_attestation_key(&mut db, 0, "mallory")
920 .unwrap_err()
921 .downcast::<error::Error>()
922 .unwrap(),
923 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
924 );
925 }
926
927 #[test]
928 #[ignore] // b/215746308
929 fn test_get_attestation_key() {
930 let mut db = crate::database::tests::new_test_db().unwrap();
931 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
932 let irpc_id = "paul";
933 let caller_uid = 0;
934
935 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
936 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800937 let mut remote_provisioning: RemoteProvisioningService = Default::default();
938 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
939 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
940 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800941
942 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
943 mock_values.lock().unwrap().private_key = vec![8, 6, 7, 5, 3, 0, 9];
944 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -0800945 remote_provisioning.generate_key_pair(&mut db, true, sec_level).unwrap();
Seth Moore7ee79f92021-12-07 11:42:49 -0800946
947 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
948 mock_values.lock().unwrap().maced_public_key.as_slice(),
949 )
950 .unwrap();
951 let batch_cert = get_fake_cert();
952 let certs = &[5, 6, 7, 8];
Seth Moore92648b62022-02-02 13:26:18 -0800953 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -0800954 .provision_cert_chain(
955 &mut db,
956 public_key.as_slice(),
957 batch_cert.as_slice(),
958 certs,
959 0,
960 sec_level
961 )
962 .is_ok());
963
964 // ensure we got the key we expected
Seth Moore92648b62022-02-02 13:26:18 -0800965 let first_key = key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800966 .get_attestation_key(&mut db, caller_uid, irpc_id)
967 .context("get first key")
968 .unwrap();
969 assert_eq!(first_key.keyBlob, mock_values.lock().unwrap().private_key);
970 assert_eq!(first_key.encodedCertChain, certs);
971
972 // ensure that multiple calls get the same key
973 assert_eq!(
974 first_key,
Seth Moore92648b62022-02-02 13:26:18 -0800975 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800976 .get_attestation_key(&mut db, caller_uid, irpc_id)
977 .context("get second key")
978 .unwrap()
979 );
980
981 // no more keys for new clients
982 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -0800983 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800984 .get_attestation_key(&mut db, caller_uid + 1, irpc_id)
985 .unwrap_err()
986 .downcast::<error::Error>()
987 .unwrap(),
988 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
989 );
990 }
991
992 #[test]
993 #[ignore] // b/215746308
994 fn test_get_attestation_key_gets_different_key_for_different_client() {
995 let mut db = crate::database::tests::new_test_db().unwrap();
996 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
997 let irpc_id = "ringo";
998 let first_caller = 0;
999 let second_caller = first_caller + 1;
1000
1001 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
1002 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -08001003 let mut remote_provisioning: RemoteProvisioningService = Default::default();
1004 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
1005 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
1006 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -08001007
1008 // generate two distinct keys and provision them with certs
1009 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1010 mock_values.lock().unwrap().private_key = vec![3, 1, 4, 1, 5];
1011 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -08001012 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001013 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1014 mock_values.lock().unwrap().maced_public_key.as_slice(),
1015 )
1016 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001017 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001018 .provision_cert_chain(
1019 &mut db,
1020 public_key.as_slice(),
1021 get_fake_cert().as_slice(),
1022 &[1],
1023 0,
1024 sec_level
1025 )
1026 .is_ok());
1027
1028 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1029 mock_values.lock().unwrap().private_key = vec![9, 0, 2, 1, 0];
1030 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x22);
Seth Moore92648b62022-02-02 13:26:18 -08001031 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001032 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1033 mock_values.lock().unwrap().maced_public_key.as_slice(),
1034 )
1035 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001036 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001037 .provision_cert_chain(
1038 &mut db,
1039 public_key.as_slice(),
1040 get_fake_cert().as_slice(),
1041 &[2],
1042 0,
1043 sec_level
1044 )
1045 .is_ok());
1046
1047 // make sure each caller gets a distinct key
1048 assert_ne!(
Seth Moore92648b62022-02-02 13:26:18 -08001049 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001050 .get_attestation_key(&mut db, first_caller, irpc_id)
1051 .context("get first key")
1052 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001053 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001054 .get_attestation_key(&mut db, second_caller, irpc_id)
1055 .context("get second key")
1056 .unwrap()
1057 );
1058
1059 // repeated calls should return the same key for a given caller
1060 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001061 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001062 .get_attestation_key(&mut db, first_caller, irpc_id)
1063 .context("first caller a")
1064 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001065 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001066 .get_attestation_key(&mut db, first_caller, irpc_id)
1067 .context("first caller b")
1068 .unwrap(),
1069 );
1070
1071 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001072 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001073 .get_attestation_key(&mut db, second_caller, irpc_id)
1074 .context("second caller a")
1075 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001076 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001077 .get_attestation_key(&mut db, second_caller, irpc_id)
1078 .context("second caller b")
1079 .unwrap()
1080 );
1081 }
Max Bires48fc2e52021-11-17 10:13:04 -08001082}