blob: 8ed2be482542871e287dcb5c353f439e9213c719 [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 }
744 }
745
746 // Hard coded cert that can be parsed -- the content doesn't matter for testing, only that it's valid.
747 fn get_fake_cert() -> Vec<u8> {
748 vec![
749 0x30, 0x82, 0x01, 0xbb, 0x30, 0x82, 0x01, 0x61, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
750 0x14, 0x3a, 0xd5, 0x67, 0xce, 0xfe, 0x93, 0xe1, 0xea, 0xb7, 0xe4, 0xbf, 0x64, 0x19,
751 0xa4, 0x11, 0xe1, 0x87, 0x40, 0x20, 0x37, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
752 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
753 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
754 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
755 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
756 0x6c, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x30, 0x32, 0x32,
757 0x30, 0x38, 0x35, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x34, 0x32, 0x36, 0x32,
758 0x32, 0x30, 0x38, 0x35, 0x32, 0x5a, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
759 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
760 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
761 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f,
762 0x67, 0x6c, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
763 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
764 0x00, 0x04, 0x1e, 0xac, 0x0c, 0xe0, 0x0d, 0xc5, 0x25, 0x84, 0x1b, 0xd2, 0x77, 0x2d,
765 0xe7, 0xba, 0xf1, 0xde, 0xa7, 0xf6, 0x39, 0x7f, 0x38, 0x91, 0xbf, 0xa4, 0x58, 0xf5,
766 0x62, 0x6b, 0xce, 0x06, 0xcf, 0xb9, 0x73, 0x91, 0x0d, 0x8a, 0x60, 0xa0, 0xc6, 0xa2,
767 0x22, 0xe6, 0x51, 0x2e, 0x58, 0xd6, 0x43, 0x02, 0x80, 0x43, 0x44, 0x29, 0x38, 0x9a,
768 0x99, 0xf3, 0xa4, 0xdd, 0xd0, 0xb4, 0x6f, 0x8b, 0x44, 0x2d, 0xa3, 0x53, 0x30, 0x51,
769 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdb, 0x13, 0x68,
770 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe, 0x42, 0x3c, 0xd9, 0x3f, 0x1a,
771 0x33, 0xe9, 0xaa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
772 0x80, 0x14, 0xdb, 0x13, 0x68, 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe,
773 0x42, 0x3c, 0xd9, 0x3f, 0x1a, 0x33, 0xe9, 0xaa, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
774 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06,
775 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
776 0x02, 0x20, 0x10, 0xdf, 0x40, 0xc3, 0x20, 0x54, 0x36, 0xb5, 0xc9, 0x3c, 0x70, 0xe3,
777 0x55, 0x37, 0xd2, 0x04, 0x51, 0xeb, 0x0f, 0x18, 0x83, 0xd0, 0x58, 0xa1, 0x08, 0x77,
778 0x8d, 0x4d, 0xa4, 0x20, 0xee, 0x33, 0x02, 0x21, 0x00, 0x8d, 0xe3, 0xa6, 0x6c, 0x0d,
779 0x86, 0x25, 0xdc, 0x59, 0x0d, 0x21, 0x43, 0x22, 0x3a, 0xb9, 0xa1, 0x73, 0x28, 0xc9,
780 0x16, 0x9e, 0x91, 0x15, 0xc4, 0xc3, 0xd7, 0xeb, 0xe5, 0xce, 0xdc, 0x1c, 0x1b,
781 ]
782 }
783
784 // Generate a fake COSE_Mac0 with a key that's just `byte` repeated
785 fn generate_maced_pubkey(byte: u8) -> Vec<u8> {
786 vec![
787 0x84, 0x43, 0xA1, 0x01, 0x05, 0xA0, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20,
788 0x01, 0x21, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
789 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
790 byte, byte, byte, byte, byte, byte, byte, byte, 0x22, 0x58, 0x20, byte, byte, byte,
791 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
792 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
793 byte, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
794 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
795 byte, byte, byte, byte, byte, byte, byte,
796 ]
797 }
Max Bires48fc2e52021-11-17 10:13:04 -0800798
799 #[test]
800 fn test_parse_cose_mac0_for_coords_raw_bytes() -> Result<()> {
801 let cose_mac0: Vec<u8> = vec![
802 0x84, 0x01, 0x02, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
803 0x20, 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9,
804 0x21, 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C,
805 0x43, 0x22, 0xC8, 0xEE, 0x03, 0x22, 0x58, 0x20, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95,
806 0x90, 0xA7, 0x5C, 0x5A, 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A,
807 0xA3, 0xB3, 0x1A, 0xB4, 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC, 0x03,
808 ];
809 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&cose_mac0)?;
810 assert_eq!(
811 raw_key,
812 vec![
813 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9, 0x21,
814 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C, 0x43,
815 0x22, 0xC8, 0xEE, 0x03, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95, 0x90, 0xA7, 0x5C, 0x5A,
816 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A, 0xA3, 0xB3, 0x1A, 0xB4,
817 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC,
818 ]
819 );
820 Ok(())
821 }
822
823 #[test]
824 fn test_parse_cose_mac0_for_coords_constructed_mac() -> Result<()> {
825 let x_coord: Vec<u8> = vec![0; 32];
826 let y_coord: Vec<u8> = vec![1; 32];
827 let mut expected_key: Vec<u8> = Vec::new();
828 expected_key.extend(&x_coord);
829 expected_key.extend(&y_coord);
830 let key_map: BTreeMap<Value, Value> = BTreeMap::from([
831 (Value::Integer(1), Value::Integer(2)),
832 (Value::Integer(3), Value::Integer(-7)),
833 (Value::Integer(-1), Value::Integer(1)),
834 (Value::Integer(-2), Value::Bytes(x_coord)),
835 (Value::Integer(-3), Value::Bytes(y_coord)),
836 ]);
837 let cose_mac0: Vec<Value> = vec![
838 Value::Integer(0),
839 Value::Integer(1),
840 Value::from(serde_cbor::to_vec(&key_map)?),
841 Value::Integer(2),
842 ];
843 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&serde_cbor::to_vec(
844 &Value::from(cose_mac0),
845 )?)?;
846 assert_eq!(expected_key, raw_key);
847 Ok(())
848 }
849
850 #[test]
851 fn test_extract_payload_from_cose_mac() -> Result<()> {
852 let key_map = Value::Map(BTreeMap::from([(Value::Integer(1), Value::Integer(2))]));
853 let payload = Value::Bytes(serde_cbor::to_vec(&key_map)?);
854 let cose_mac0 =
855 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
856 let extracted_map = RemoteProvisioningService::extract_payload_from_cose_mac(
857 &serde_cbor::to_vec(&cose_mac0)?,
858 )?;
859 assert_eq!(key_map, extracted_map);
860 Ok(())
861 }
862
863 #[test]
864 fn test_extract_payload_from_cose_mac_fails_malformed_payload() -> Result<()> {
865 let payload = Value::Bytes(vec![5; 10]);
866 let cose_mac0 =
867 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
868 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
869 &serde_cbor::to_vec(&cose_mac0)?,
870 );
871 assert!(extracted_payload.is_err());
872 Ok(())
873 }
874
875 #[test]
876 fn test_extract_payload_from_cose_mac_fails_type() -> Result<()> {
877 let payload = Value::Integer(1);
878 let cose_mac0 =
879 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
880 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
881 &serde_cbor::to_vec(&cose_mac0)?,
882 );
883 assert!(extracted_payload.is_err());
884 Ok(())
885 }
886
887 #[test]
888 fn test_extract_payload_from_cose_mac_fails_length() -> Result<()> {
889 let cose_mac0 = Value::Array(vec![Value::Integer(0), Value::Integer(1)]);
890 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
891 &serde_cbor::to_vec(&cose_mac0)?,
892 );
893 assert!(extracted_payload.is_err());
894 Ok(())
895 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800896
897 #[test]
898 #[ignore] // b/215746308
899 fn test_get_attestation_key_no_keys_provisioned() {
900 let mut db = crate::database::tests::new_test_db().unwrap();
901 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
902 mock_rpc.0.lock().unwrap().hw_info.uniqueId = Some(String::from("mallory"));
903
Seth Moore92648b62022-02-02 13:26:18 -0800904 let mut service: RemotelyProvisionedKeyPoolService = Default::default();
Seth Moore7ee79f92021-12-07 11:42:49 -0800905 service
Seth Moore92648b62022-02-02 13:26:18 -0800906 .unique_id_to_sec_level
907 .insert(String::from("mallory"), SecurityLevel::TRUSTED_ENVIRONMENT);
Seth Moore7ee79f92021-12-07 11:42:49 -0800908
909 assert_eq!(
910 service
911 .get_attestation_key(&mut db, 0, "mallory")
912 .unwrap_err()
913 .downcast::<error::Error>()
914 .unwrap(),
915 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
916 );
917 }
918
919 #[test]
920 #[ignore] // b/215746308
921 fn test_get_attestation_key() {
922 let mut db = crate::database::tests::new_test_db().unwrap();
923 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
924 let irpc_id = "paul";
925 let caller_uid = 0;
926
927 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
928 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800929 let mut remote_provisioning: RemoteProvisioningService = Default::default();
930 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
931 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
932 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800933
934 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
935 mock_values.lock().unwrap().private_key = vec![8, 6, 7, 5, 3, 0, 9];
936 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -0800937 remote_provisioning.generate_key_pair(&mut db, true, sec_level).unwrap();
Seth Moore7ee79f92021-12-07 11:42:49 -0800938
939 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
940 mock_values.lock().unwrap().maced_public_key.as_slice(),
941 )
942 .unwrap();
943 let batch_cert = get_fake_cert();
944 let certs = &[5, 6, 7, 8];
Seth Moore92648b62022-02-02 13:26:18 -0800945 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -0800946 .provision_cert_chain(
947 &mut db,
948 public_key.as_slice(),
949 batch_cert.as_slice(),
950 certs,
951 0,
952 sec_level
953 )
954 .is_ok());
955
956 // ensure we got the key we expected
Seth Moore92648b62022-02-02 13:26:18 -0800957 let first_key = key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800958 .get_attestation_key(&mut db, caller_uid, irpc_id)
959 .context("get first key")
960 .unwrap();
961 assert_eq!(first_key.keyBlob, mock_values.lock().unwrap().private_key);
962 assert_eq!(first_key.encodedCertChain, certs);
963
964 // ensure that multiple calls get the same key
965 assert_eq!(
966 first_key,
Seth Moore92648b62022-02-02 13:26:18 -0800967 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800968 .get_attestation_key(&mut db, caller_uid, irpc_id)
969 .context("get second key")
970 .unwrap()
971 );
972
973 // no more keys for new clients
974 assert_eq!(
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 + 1, irpc_id)
977 .unwrap_err()
978 .downcast::<error::Error>()
979 .unwrap(),
980 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
981 );
982 }
983
984 #[test]
985 #[ignore] // b/215746308
986 fn test_get_attestation_key_gets_different_key_for_different_client() {
987 let mut db = crate::database::tests::new_test_db().unwrap();
988 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
989 let irpc_id = "ringo";
990 let first_caller = 0;
991 let second_caller = first_caller + 1;
992
993 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
994 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800995 let mut remote_provisioning: RemoteProvisioningService = Default::default();
996 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
997 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
998 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800999
1000 // generate two distinct keys and provision them with certs
1001 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1002 mock_values.lock().unwrap().private_key = vec![3, 1, 4, 1, 5];
1003 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -08001004 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001005 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1006 mock_values.lock().unwrap().maced_public_key.as_slice(),
1007 )
1008 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001009 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001010 .provision_cert_chain(
1011 &mut db,
1012 public_key.as_slice(),
1013 get_fake_cert().as_slice(),
1014 &[1],
1015 0,
1016 sec_level
1017 )
1018 .is_ok());
1019
1020 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1021 mock_values.lock().unwrap().private_key = vec![9, 0, 2, 1, 0];
1022 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x22);
Seth Moore92648b62022-02-02 13:26:18 -08001023 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001024 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1025 mock_values.lock().unwrap().maced_public_key.as_slice(),
1026 )
1027 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001028 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001029 .provision_cert_chain(
1030 &mut db,
1031 public_key.as_slice(),
1032 get_fake_cert().as_slice(),
1033 &[2],
1034 0,
1035 sec_level
1036 )
1037 .is_ok());
1038
1039 // make sure each caller gets a distinct key
1040 assert_ne!(
Seth Moore92648b62022-02-02 13:26:18 -08001041 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001042 .get_attestation_key(&mut db, first_caller, irpc_id)
1043 .context("get first key")
1044 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001045 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001046 .get_attestation_key(&mut db, second_caller, irpc_id)
1047 .context("get second key")
1048 .unwrap()
1049 );
1050
1051 // repeated calls should return the same key for a given caller
1052 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001053 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001054 .get_attestation_key(&mut db, first_caller, irpc_id)
1055 .context("first caller a")
1056 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001057 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001058 .get_attestation_key(&mut db, first_caller, irpc_id)
1059 .context("first caller b")
1060 .unwrap(),
1061 );
1062
1063 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001064 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001065 .get_attestation_key(&mut db, second_caller, irpc_id)
1066 .context("second caller a")
1067 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001068 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001069 .get_attestation_key(&mut db, second_caller, irpc_id)
1070 .context("second caller b")
1071 .unwrap()
1072 );
1073 }
Max Bires48fc2e52021-11-17 10:13:04 -08001074}