blob: 00fb572e9be91ad363ce98f77a5652de71fc0c4f [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};
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +000051use crate::ks_err;
Hasini Gunasinghe8a1a2242021-08-02 22:28:39 +000052use crate::metrics_store::log_rkp_error_stats;
Seth Moore7ee79f92021-12-07 11:42:49 -080053use crate::permission::KeystorePerm;
54use crate::utils::{check_keystore_permission, watchdog as wd};
Hasini Gunasinghe8a1a2242021-08-02 22:28:39 +000055use android_security_metrics::aidl::android::security::metrics::RkpError::RkpError as MetricsRkpError;
Max Bires148c08e2020-10-13 13:41:41 -070056
Max Bires97f96812021-02-23 23:44:57 -080057/// Contains helper functions to check if remote provisioning is enabled on the system and, if so,
58/// to assign and retrieve attestation keys and certificate chains.
59#[derive(Default)]
60pub struct RemProvState {
61 security_level: SecurityLevel,
62 km_uuid: Uuid,
63 is_hal_present: AtomicBool,
64}
65
Max Bires48fc2e52021-11-17 10:13:04 -080066static COSE_KEY_XCOORD: Value = Value::Integer(-2);
67static COSE_KEY_YCOORD: Value = Value::Integer(-3);
68static COSE_MAC0_LEN: usize = 4;
69static COSE_MAC0_PAYLOAD: usize = 2;
70
Max Bires97f96812021-02-23 23:44:57 -080071impl RemProvState {
72 /// Creates a RemProvState struct.
73 pub fn new(security_level: SecurityLevel, km_uuid: Uuid) -> Self {
Seth Mooredfdcb872022-04-20 14:33:19 -070074 Self { security_level, km_uuid, is_hal_present: AtomicBool::new(true) }
Max Bires97f96812021-02-23 23:44:57 -080075 }
76
Max Bires55620ff2022-02-11 13:34:15 -080077 /// Returns the uuid for the KM instance attached to this RemProvState struct.
78 pub fn get_uuid(&self) -> Uuid {
79 self.km_uuid
80 }
81
Seth Mooredfdcb872022-04-20 14:33:19 -070082 fn is_rkp_only(&self) -> bool {
Max Bires65207b52022-03-29 23:58:08 -070083 let default_value = false;
84
Seth Mooredfdcb872022-04-20 14:33:19 -070085 let property_name = match self.security_level {
86 SecurityLevel::STRONGBOX => "remote_provisioning.strongbox.rkp_only",
87 SecurityLevel::TRUSTED_ENVIRONMENT => "remote_provisioning.tee.rkp_only",
Max Bires65207b52022-03-29 23:58:08 -070088 _ => return default_value,
89 };
90
91 rustutils::system_properties::read_bool(property_name, default_value)
92 .unwrap_or(default_value)
93 }
94
Max Bires97f96812021-02-23 23:44:57 -080095 /// Checks if remote provisioning is enabled and partially caches the result. On a hybrid system
96 /// remote provisioning can flip from being disabled to enabled depending on responses from the
97 /// server, so unfortunately caching the presence or absence of the HAL is not enough to fully
98 /// make decisions about the state of remote provisioning during runtime.
99 fn check_rem_prov_enabled(&self, db: &mut KeystoreDB) -> Result<bool> {
Seth Mooredfdcb872022-04-20 14:33:19 -0700100 if self.is_rkp_only() {
Seth Moore562aebb2022-04-18 17:03:27 -0700101 return Ok(true);
102 }
Max Bires97f96812021-02-23 23:44:57 -0800103 if !self.is_hal_present.load(Ordering::Relaxed)
104 || get_remotely_provisioned_component(&self.security_level).is_err()
105 {
106 self.is_hal_present.store(false, Ordering::Relaxed);
107 return Ok(false);
108 }
109 // To check if remote provisioning is enabled on a system that supports both remote
110 // provisioning and factory provisioned keys, we only need to check if there are any
111 // keys at all generated to indicate if the app has gotten the signal to begin filling
112 // the key pool from the server.
113 let pool_status = db
114 .get_attestation_pool_status(0 /* date */, &self.km_uuid)
115 .context("In check_rem_prov_enabled: failed to get attestation pool status.")?;
116 Ok(pool_status.total != 0)
117 }
118
Max Bires97f96812021-02-23 23:44:57 -0800119 fn is_asymmetric_key(&self, params: &[KeyParameter]) -> bool {
120 params.iter().any(|kp| {
121 matches!(
122 kp,
123 KeyParameter {
124 tag: Tag::ALGORITHM,
125 value: KeyParameterValue::Algorithm(Algorithm::RSA)
126 } | KeyParameter {
127 tag: Tag::ALGORITHM,
128 value: KeyParameterValue::Algorithm(Algorithm::EC)
129 }
130 )
131 })
132 }
133
134 /// Checks to see (1) if the key in question should be attested to based on the algorithm and
135 /// (2) if remote provisioning is present and enabled on the system. If these conditions are
136 /// met, it makes an attempt to fetch the attestation key assigned to the `caller_uid`.
137 ///
138 /// It returns the ResponseCode `OUT_OF_KEYS` if there is not one key currently assigned to the
139 /// `caller_uid` and there are none available to assign.
Janis Danisevskis3541f3e2021-03-20 14:18:52 -0700140 pub fn get_remotely_provisioned_attestation_key_and_certs(
Max Bires97f96812021-02-23 23:44:57 -0800141 &self,
142 key: &KeyDescriptor,
143 caller_uid: u32,
144 params: &[KeyParameter],
145 db: &mut KeystoreDB,
Max Bires55620ff2022-02-11 13:34:15 -0800146 ) -> Result<Option<(KeyIdGuard, AttestationKey, Certificate)>> {
Max Bires97f96812021-02-23 23:44:57 -0800147 if !self.is_asymmetric_key(params) || !self.check_rem_prov_enabled(db)? {
148 // There is no remote provisioning component for this security level on the
149 // device. Return None so the underlying KM instance knows to use its
150 // factory provisioned key instead. Alternatively, it's not an asymmetric key
151 // and therefore will not be attested.
Janis Danisevskis3541f3e2021-03-20 14:18:52 -0700152 Ok(None)
Max Bires97f96812021-02-23 23:44:57 -0800153 } else {
Seth Moore7ee79f92021-12-07 11:42:49 -0800154 match get_rem_prov_attest_key(key.domain, caller_uid, db, &self.km_uuid) {
Max Bires31cdfb82021-07-06 02:59:25 -0700155 Err(e) => {
Seth Mooredfdcb872022-04-20 14:33:19 -0700156 if self.is_rkp_only() {
Shaquille Johnson32bd2672022-10-21 13:18:56 +0100157 log::error!("Error occurred: {:?}", e);
Max Bires65207b52022-03-29 23:58:08 -0700158 return Err(e);
159 }
Shaquille Johnson32bd2672022-10-21 13:18:56 +0100160 log::warn!("Error occurred: {:?}", e);
Shaquille Johnsonbcab6012022-09-02 11:16:24 +0000161 log_rkp_error_stats(
162 MetricsRkpError::FALL_BACK_DURING_HYBRID,
163 &self.security_level,
164 );
Max Bires31cdfb82021-07-06 02:59:25 -0700165 Ok(None)
166 }
167 Ok(v) => match v {
Max Bires55620ff2022-02-11 13:34:15 -0800168 Some((guard, cert_chain)) => Ok(Some((
169 guard,
Max Bires31cdfb82021-07-06 02:59:25 -0700170 AttestationKey {
171 keyBlob: cert_chain.private_key.to_vec(),
172 attestKeyParams: vec![],
173 issuerSubjectName: parse_subject_from_certificate(
174 &cert_chain.batch_cert,
175 )
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000176 .context(ks_err!("Failed to parse subject."))?,
Max Bires31cdfb82021-07-06 02:59:25 -0700177 },
178 Certificate { encodedCertificate: cert_chain.cert_chain },
179 ))),
180 None => Ok(None),
181 },
Max Bires97f96812021-02-23 23:44:57 -0800182 }
183 }
184 }
185}
Max Bires148c08e2020-10-13 13:41:41 -0700186/// Implementation of the IRemoteProvisioning service.
Max Biresb2e1d032021-02-08 21:35:05 -0800187#[derive(Default)]
Max Bires148c08e2020-10-13 13:41:41 -0700188pub struct RemoteProvisioningService {
Janis Danisevskis5f3a0572021-06-18 11:26:42 -0700189 device_by_sec_level: HashMap<SecurityLevel, Strong<dyn IRemotelyProvisionedComponent>>,
Max Biresd2ce46b2021-07-06 02:54:47 -0700190 curve_by_sec_level: HashMap<SecurityLevel, i32>,
Max Bires148c08e2020-10-13 13:41:41 -0700191}
192
193impl RemoteProvisioningService {
Max Biresb2e1d032021-02-08 21:35:05 -0800194 fn get_dev_by_sec_level(
195 &self,
196 sec_level: &SecurityLevel,
Seth Moore7ee79f92021-12-07 11:42:49 -0800197 ) -> Result<&dyn IRemotelyProvisionedComponent> {
Max Biresb2e1d032021-02-08 21:35:05 -0800198 if let Some(dev) = self.device_by_sec_level.get(sec_level) {
Seth Moore7ee79f92021-12-07 11:42:49 -0800199 Ok(dev.as_ref())
Max Biresb2e1d032021-02-08 21:35:05 -0800200 } else {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000201 Err(error::Error::sys()).context(ks_err!(
202 "Remote instance for requested security level \
203 not found.",
Max Biresb2e1d032021-02-08 21:35:05 -0800204 ))
205 }
206 }
207
Max Bires148c08e2020-10-13 13:41:41 -0700208 /// Creates a new instance of the remote provisioning service
Stephen Crane221bbb52020-12-16 15:52:10 -0800209 pub fn new_native_binder() -> Result<Strong<dyn IRemoteProvisioning>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800210 let mut result: Self = Default::default();
211 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000212 .context(ks_err!("Failed to get TEE Remote Provisioner instance."))?;
Max Biresd2ce46b2021-07-06 02:54:47 -0700213 result.curve_by_sec_level.insert(
214 SecurityLevel::TRUSTED_ENVIRONMENT,
215 dev.getHardwareInfo()
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000216 .context(ks_err!("Failed to get hardware info for the TEE."))?
Max Biresd2ce46b2021-07-06 02:54:47 -0700217 .supportedEekCurve,
218 );
Max Biresb2e1d032021-02-08 21:35:05 -0800219 result.device_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, dev);
220 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
Max Biresd2ce46b2021-07-06 02:54:47 -0700221 result.curve_by_sec_level.insert(
222 SecurityLevel::STRONGBOX,
223 dev.getHardwareInfo()
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000224 .context(ks_err!("Failed to get hardware info for StrongBox."))?
Max Biresd2ce46b2021-07-06 02:54:47 -0700225 .supportedEekCurve,
226 );
Max Biresb2e1d032021-02-08 21:35:05 -0800227 result.device_by_sec_level.insert(SecurityLevel::STRONGBOX, dev);
228 }
Andrew Walbrande45c8b2021-04-13 14:42:38 +0000229 Ok(BnRemoteProvisioning::new_binder(result, BinderFeatures::default()))
Max Bires148c08e2020-10-13 13:41:41 -0700230 }
231
Max Bires48fc2e52021-11-17 10:13:04 -0800232 fn extract_payload_from_cose_mac(data: &[u8]) -> Result<Value> {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000233 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data)
234 .context(ks_err!("COSE_Mac0 returned from IRPC cannot be parsed"))?;
Max Bires48fc2e52021-11-17 10:13:04 -0800235 if cose_mac0.len() != COSE_MAC0_LEN {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000236 return Err(error::Error::sys()).context(ks_err!(
237 "COSE_Mac0 has improper length. \
Max Bires48fc2e52021-11-17 10:13:04 -0800238 Expected: {}, Actual: {}",
239 COSE_MAC0_LEN,
240 cose_mac0.len(),
241 ));
242 }
243 match &cose_mac0[COSE_MAC0_PAYLOAD] {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000244 Value::Bytes(key) => {
245 Ok(serde_cbor::from_slice(key)
246 .context(ks_err!("COSE_Mac0 payload is malformed."))?)
247 }
248 _ => {
249 Err(error::Error::sys()).context(ks_err!("COSE_Mac0 payload is the wrong type."))?
250 }
Max Bires48fc2e52021-11-17 10:13:04 -0800251 }
252 }
253
Max Bires148c08e2020-10-13 13:41:41 -0700254 /// Generates a CBOR blob which will be assembled by the calling code into a larger
255 /// CBOR blob intended for delivery to a provisioning serever. This blob will contain
256 /// `num_csr` certificate signing requests for attestation keys generated in the TEE,
257 /// along with a server provided `eek` and `challenge`. The endpoint encryption key will
258 /// be used to encrypt the sensitive contents being transmitted to the server, and the
259 /// challenge will ensure freshness. A `test_mode` flag will instruct the remote provisioning
260 /// HAL if it is okay to accept EEKs that aren't signed by something that chains back to the
261 /// baked in root of trust in the underlying IRemotelyProvisionedComponent instance.
Max Bires834dd362021-03-23 13:01:57 -0700262 #[allow(clippy::too_many_arguments)]
Max Bires148c08e2020-10-13 13:41:41 -0700263 pub fn generate_csr(
264 &self,
Max Biresb2e1d032021-02-08 21:35:05 -0800265 test_mode: bool,
266 num_csr: i32,
267 eek: &[u8],
268 challenge: &[u8],
269 sec_level: SecurityLevel,
270 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700271 device_info: &mut DeviceInfo,
Max Bires148c08e2020-10-13 13:41:41 -0700272 ) -> Result<Vec<u8>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800273 let dev = self.get_dev_by_sec_level(&sec_level)?;
274 let (_, _, uuid) = get_keymint_device(&sec_level)?;
275 let keys_to_sign = DB.with::<_, Result<Vec<MacedPublicKey>>>(|db| {
276 let mut db = db.borrow_mut();
277 Ok(db
278 .fetch_unsigned_attestation_keys(num_csr, &uuid)?
279 .iter()
280 .map(|key| MacedPublicKey { macedKey: key.to_vec() })
281 .collect())
282 })?;
Max Bires48fc2e52021-11-17 10:13:04 -0800283 let mac = map_rem_prov_error(dev.generateCertificateRequest(
Max Biresb2e1d032021-02-08 21:35:05 -0800284 test_mode,
285 &keys_to_sign,
286 eek,
287 challenge,
Max Bires834dd362021-03-23 13:01:57 -0700288 device_info,
Max Biresb2e1d032021-02-08 21:35:05 -0800289 protected_data,
290 ))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000291 .context(ks_err!("Failed to generate csr"))?;
Max Bires48fc2e52021-11-17 10:13:04 -0800292 let mut mac_and_keys: Vec<Value> = vec![Value::from(mac)];
Max Bires97f96812021-02-23 23:44:57 -0800293 for maced_public_key in keys_to_sign {
Max Bires48fc2e52021-11-17 10:13:04 -0800294 mac_and_keys.push(
295 Self::extract_payload_from_cose_mac(&maced_public_key.macedKey)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000296 .context(ks_err!("Failed to get the payload from the COSE_Mac0"))?,
Max Bires48fc2e52021-11-17 10:13:04 -0800297 )
Max Bires97f96812021-02-23 23:44:57 -0800298 }
Max Bires48fc2e52021-11-17 10:13:04 -0800299 let cbor_array: Value = Value::Array(mac_and_keys);
300 serde_cbor::to_vec(&cbor_array)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000301 .context(ks_err!("Failed to serialize the mac and keys array"))
Max Bires148c08e2020-10-13 13:41:41 -0700302 }
303
304 /// Provisions a certificate chain for a key whose CSR was included in generate_csr. The
305 /// `public_key` is used to index into the SQL database in order to insert the `certs` blob
306 /// which represents a PEM encoded X.509 certificate chain. The `expiration_date` is provided
307 /// as a convenience from the caller to avoid having to parse the certificates semantically
308 /// here.
309 pub fn provision_cert_chain(
310 &self,
Seth Moore7ee79f92021-12-07 11:42:49 -0800311 db: &mut KeystoreDB,
Max Bires148c08e2020-10-13 13:41:41 -0700312 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800313 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700314 certs: &[u8],
315 expiration_date: i64,
316 sec_level: SecurityLevel,
317 ) -> Result<()> {
Seth Moore7ee79f92021-12-07 11:42:49 -0800318 let (_, _, uuid) = get_keymint_device(&sec_level)?;
319 db.store_signed_attestation_certificate_chain(
320 public_key,
321 batch_cert,
322 certs, /* DER encoded certificate chain */
323 expiration_date,
324 &uuid,
325 )
Max Bires148c08e2020-10-13 13:41:41 -0700326 }
327
Max Bires48fc2e52021-11-17 10:13:04 -0800328 fn parse_cose_mac0_for_coords(data: &[u8]) -> Result<Vec<u8>> {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000329 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data)
330 .context(ks_err!("COSE_Mac0 returned from IRPC cannot be parsed"))?;
Max Bires48fc2e52021-11-17 10:13:04 -0800331 if cose_mac0.len() != COSE_MAC0_LEN {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000332 return Err(error::Error::sys()).context(ks_err!(
333 "COSE_Mac0 has improper length. \
Max Bires48fc2e52021-11-17 10:13:04 -0800334 Expected: {}, Actual: {}",
335 COSE_MAC0_LEN,
336 cose_mac0.len(),
337 ));
338 }
339 let cose_key: BTreeMap<Value, Value> = match &cose_mac0[COSE_MAC0_PAYLOAD] {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000340 Value::Bytes(key) => {
341 serde_cbor::from_slice(key).context(ks_err!("COSE_Key is malformed."))?
342 }
343 _ => {
344 Err(error::Error::sys()).context(ks_err!("COSE_Mac0 payload is the wrong type."))?
345 }
Max Bires48fc2e52021-11-17 10:13:04 -0800346 };
347 if !cose_key.contains_key(&COSE_KEY_XCOORD) || !cose_key.contains_key(&COSE_KEY_YCOORD) {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000348 return Err(error::Error::sys())
349 .context(ks_err!("COSE_Key returned from IRPC is lacking required fields"));
Max Bires48fc2e52021-11-17 10:13:04 -0800350 }
351 let mut raw_key: Vec<u8> = vec![0; 64];
352 match &cose_key[&COSE_KEY_XCOORD] {
353 Value::Bytes(x_coord) if x_coord.len() == 32 => {
354 raw_key[0..32].clone_from_slice(x_coord)
355 }
356 Value::Bytes(x_coord) => {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000357 return Err(error::Error::sys()).context(ks_err!(
358 "COSE_Key X-coordinate is not the right length. \
Max Bires48fc2e52021-11-17 10:13:04 -0800359 Expected: 32; Actual: {}",
360 x_coord.len()
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000361 ));
Max Bires48fc2e52021-11-17 10:13:04 -0800362 }
363 _ => {
364 return Err(error::Error::sys())
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000365 .context(ks_err!("COSE_Key X-coordinate is not a bstr"));
Max Bires48fc2e52021-11-17 10:13:04 -0800366 }
367 }
368 match &cose_key[&COSE_KEY_YCOORD] {
369 Value::Bytes(y_coord) if y_coord.len() == 32 => {
370 raw_key[32..64].clone_from_slice(y_coord)
371 }
372 Value::Bytes(y_coord) => {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000373 return Err(error::Error::sys()).context(ks_err!(
374 "COSE_Key Y-coordinate is not the right length. \
Max Bires48fc2e52021-11-17 10:13:04 -0800375 Expected: 32; Actual: {}",
376 y_coord.len()
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000377 ));
Max Bires48fc2e52021-11-17 10:13:04 -0800378 }
379 _ => {
380 return Err(error::Error::sys())
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000381 .context(ks_err!("COSE_Key Y-coordinate is not a bstr"));
Max Bires48fc2e52021-11-17 10:13:04 -0800382 }
383 }
384 Ok(raw_key)
385 }
386
Max Bires148c08e2020-10-13 13:41:41 -0700387 /// Submits a request to the Remote Provisioner HAL to generate a signing key pair.
388 /// `is_test_mode` indicates whether or not the returned public key should be marked as being
389 /// for testing in order to differentiate them from private keys. If the call is successful,
390 /// the key pair is then added to the database.
Seth Moore7ee79f92021-12-07 11:42:49 -0800391 pub fn generate_key_pair(
392 &self,
393 db: &mut KeystoreDB,
394 is_test_mode: bool,
395 sec_level: SecurityLevel,
396 ) -> Result<()> {
Max Biresb2e1d032021-02-08 21:35:05 -0800397 let (_, _, uuid) = get_keymint_device(&sec_level)?;
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000398 let dev = self
399 .get_dev_by_sec_level(&sec_level)
400 .context(ks_err!("Failed to get device for security level {:?}", sec_level))?;
Max Biresb2e1d032021-02-08 21:35:05 -0800401 let mut maced_key = MacedPublicKey { macedKey: Vec::new() };
402 let priv_key =
403 map_rem_prov_error(dev.generateEcdsaP256KeyPair(is_test_mode, &mut maced_key))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000404 .context(ks_err!("Failed to generated ECDSA keypair."))?;
Max Bires48fc2e52021-11-17 10:13:04 -0800405 let raw_key = Self::parse_cose_mac0_for_coords(&maced_key.macedKey)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000406 .context(ks_err!("Failed to parse raw key"))?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800407 db.create_attestation_key_entry(&maced_key.macedKey, &raw_key, &priv_key, &uuid)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000408 .context(ks_err!("Failed to insert attestation key entry"))
Max Biresb2e1d032021-02-08 21:35:05 -0800409 }
410
411 /// Checks the security level of each available IRemotelyProvisionedComponent hal and returns
412 /// all levels in an array to the caller.
Max Biresd2ce46b2021-07-06 02:54:47 -0700413 pub fn get_implementation_info(&self) -> Result<Vec<ImplInfo>> {
414 Ok(self
415 .curve_by_sec_level
416 .iter()
417 .map(|(sec_level, curve)| ImplInfo { secLevel: *sec_level, supportedCurve: *curve })
418 .collect())
Max Bires148c08e2020-10-13 13:41:41 -0700419 }
Max Bires60d7ed12021-03-05 15:59:22 -0800420
421 /// Deletes all attestation keys generated by the IRemotelyProvisionedComponent from the device,
422 /// regardless of what state of the attestation key lifecycle they were in.
423 pub fn delete_all_keys(&self) -> Result<i64> {
424 DB.with::<_, Result<i64>>(|db| {
425 let mut db = db.borrow_mut();
Matthew Maurerb77a28d2021-05-07 16:08:20 -0700426 db.delete_all_attestation_keys()
Max Bires60d7ed12021-03-05 15:59:22 -0800427 })
428 }
Max Bires148c08e2020-10-13 13:41:41 -0700429}
430
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000431/// Populates the AttestationPoolStatus parcelable with information about how many
432/// certs will be expiring by the date provided in `expired_by` along with how many
433/// keys have not yet been assigned.
434pub fn get_pool_status(expired_by: i64, sec_level: SecurityLevel) -> Result<AttestationPoolStatus> {
435 let (_, _, uuid) = get_keymint_device(&sec_level)?;
436 DB.with::<_, Result<AttestationPoolStatus>>(|db| {
437 let mut db = db.borrow_mut();
438 // delete_expired_attestation_keys is always safe to call, and will remove anything
439 // older than the date at the time of calling. No work should be done on the
440 // attestation keys unless the pool status is checked first, so this call should be
441 // enough to routinely clean out expired keys.
442 db.delete_expired_attestation_keys()?;
443 db.get_attestation_pool_status(expired_by, &uuid)
444 })
445}
446
Seth Moore7ee79f92021-12-07 11:42:49 -0800447/// Fetches a remote provisioning attestation key and certificate chain inside of the
448/// returned `CertificateChain` struct if one exists for the given caller_uid. If one has not
449/// been assigned, this function will assign it. If there are no signed attestation keys
450/// available to be assigned, it will return the ResponseCode `OUT_OF_KEYS`
451fn get_rem_prov_attest_key(
452 domain: Domain,
453 caller_uid: u32,
454 db: &mut KeystoreDB,
455 km_uuid: &Uuid,
Max Bires55620ff2022-02-11 13:34:15 -0800456) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
Seth Moore7ee79f92021-12-07 11:42:49 -0800457 match domain {
458 Domain::APP => {
459 // Attempt to get an Attestation Key once. If it fails, then the app doesn't
460 // have a valid chain assigned to it. The helper function will return None after
461 // attempting to assign a key. An error will be thrown if the pool is simply out
462 // of usable keys. Then another attempt to fetch the just-assigned key will be
463 // made. If this fails too, something is very wrong.
464 get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid)
465 .context("In get_rem_prov_attest_key: Failed to get a key")?
466 .map_or_else(
467 || get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid),
468 |v| Ok(Some(v)),
469 )
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000470 .context(ks_err!(
471 "Failed to get a key after \
472 attempting to assign one.",
Seth Moore7ee79f92021-12-07 11:42:49 -0800473 ))?
474 .map_or_else(
475 || {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000476 Err(Error::sys()).context(ks_err!(
477 "Attempted to assign a \
478 key and failed silently. Something is very wrong.",
Seth Moore7ee79f92021-12-07 11:42:49 -0800479 ))
480 },
Max Bires55620ff2022-02-11 13:34:15 -0800481 |(guard, cert_chain)| Ok(Some((guard, cert_chain))),
Seth Moore7ee79f92021-12-07 11:42:49 -0800482 )
483 }
484 _ => Ok(None),
485 }
486}
487
488/// Returns None if an AttestationKey fails to be assigned. Errors if no keys are available.
489fn get_rem_prov_attest_key_helper(
490 domain: Domain,
491 caller_uid: u32,
492 db: &mut KeystoreDB,
493 km_uuid: &Uuid,
Max Bires55620ff2022-02-11 13:34:15 -0800494) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
495 let guard_and_chain = db
Seth Moore7ee79f92021-12-07 11:42:49 -0800496 .retrieve_attestation_key_and_cert_chain(domain, caller_uid as i64, km_uuid)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000497 .context(ks_err!("Failed to retrieve a key + cert chain"))?;
Max Bires55620ff2022-02-11 13:34:15 -0800498 match guard_and_chain {
499 Some((guard, cert_chain)) => Ok(Some((guard, cert_chain))),
Seth Moore7ee79f92021-12-07 11:42:49 -0800500 // Either this app needs to be assigned a key, or the pool is empty. An error will
501 // be thrown if there is no key available to assign. This will indicate that the app
502 // should be nudged to provision more keys so keystore can retry.
503 None => {
504 db.assign_attestation_key(domain, caller_uid as i64, km_uuid)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000505 .context(ks_err!("Failed to assign a key"))?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800506 Ok(None)
507 }
508 }
509}
510
Max Bires148c08e2020-10-13 13:41:41 -0700511impl binder::Interface for RemoteProvisioningService {}
512
513// Implementation of IRemoteProvisioning. See AIDL spec at
514// :aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
515impl IRemoteProvisioning for RemoteProvisioningService {
516 fn getPoolStatus(
517 &self,
518 expired_by: i64,
519 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700520 ) -> binder::Result<AttestationPoolStatus> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000521 let _wp = wd::watch_millis("IRemoteProvisioning::getPoolStatus", 500);
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000522 map_or_log_err(get_pool_status(expired_by, sec_level), Ok)
Max Bires148c08e2020-10-13 13:41:41 -0700523 }
524
525 fn generateCsr(
526 &self,
527 test_mode: bool,
528 num_csr: i32,
529 eek: &[u8],
530 challenge: &[u8],
531 sec_level: SecurityLevel,
Max Biresb2e1d032021-02-08 21:35:05 -0800532 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700533 device_info: &mut DeviceInfo,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700534 ) -> binder::Result<Vec<u8>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000535 let _wp = wd::watch_millis("IRemoteProvisioning::generateCsr", 500);
Max Biresb2e1d032021-02-08 21:35:05 -0800536 map_or_log_err(
Max Bires834dd362021-03-23 13:01:57 -0700537 self.generate_csr(
538 test_mode,
539 num_csr,
540 eek,
541 challenge,
542 sec_level,
543 protected_data,
544 device_info,
545 ),
Max Biresb2e1d032021-02-08 21:35:05 -0800546 Ok,
547 )
Max Bires148c08e2020-10-13 13:41:41 -0700548 }
549
550 fn provisionCertChain(
551 &self,
552 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800553 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700554 certs: &[u8],
555 expiration_date: i64,
556 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700557 ) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000558 let _wp = wd::watch_millis("IRemoteProvisioning::provisionCertChain", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800559 DB.with::<_, binder::Result<()>>(|db| {
560 map_or_log_err(
561 self.provision_cert_chain(
562 &mut db.borrow_mut(),
563 public_key,
564 batch_cert,
565 certs,
566 expiration_date,
567 sec_level,
568 ),
569 Ok,
570 )
571 })
Max Bires148c08e2020-10-13 13:41:41 -0700572 }
573
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700574 fn generateKeyPair(&self, is_test_mode: bool, sec_level: SecurityLevel) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000575 let _wp = wd::watch_millis("IRemoteProvisioning::generateKeyPair", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800576 DB.with::<_, binder::Result<()>>(|db| {
577 map_or_log_err(
578 self.generate_key_pair(&mut db.borrow_mut(), is_test_mode, sec_level),
579 Ok,
580 )
581 })
Max Bires148c08e2020-10-13 13:41:41 -0700582 }
Max Biresb2e1d032021-02-08 21:35:05 -0800583
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700584 fn getImplementationInfo(&self) -> binder::Result<Vec<ImplInfo>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000585 let _wp = wd::watch_millis("IRemoteProvisioning::getSecurityLevels", 500);
Max Biresd2ce46b2021-07-06 02:54:47 -0700586 map_or_log_err(self.get_implementation_info(), Ok)
Max Biresb2e1d032021-02-08 21:35:05 -0800587 }
Max Bires60d7ed12021-03-05 15:59:22 -0800588
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700589 fn deleteAllKeys(&self) -> binder::Result<i64> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000590 let _wp = wd::watch_millis("IRemoteProvisioning::deleteAllKeys", 500);
Max Bires60d7ed12021-03-05 15:59:22 -0800591 map_or_log_err(self.delete_all_keys(), Ok)
592 }
Max Bires148c08e2020-10-13 13:41:41 -0700593}
Max Bires48fc2e52021-11-17 10:13:04 -0800594
Seth Moore92648b62022-02-02 13:26:18 -0800595/// Implementation of the IRemotelyProvisionedKeyPool service.
596#[derive(Default)]
597pub struct RemotelyProvisionedKeyPoolService {
598 unique_id_to_sec_level: HashMap<String, SecurityLevel>,
599}
600
601impl RemotelyProvisionedKeyPoolService {
602 /// Fetches a remotely provisioned certificate chain and key for the given client uid that
603 /// was provisioned using the IRemotelyProvisionedComponent with the given id. The same key
604 /// will be returned for a given caller_uid on every request. If there are no attestation keys
605 /// available, `OUT_OF_KEYS` is returned.
606 fn get_attestation_key(
607 &self,
608 db: &mut KeystoreDB,
609 caller_uid: i32,
610 irpc_id: &str,
611 ) -> Result<RemotelyProvisionedKey> {
612 log::info!("get_attestation_key(self, {}, {}", caller_uid, irpc_id);
613
614 let sec_level = self
615 .unique_id_to_sec_level
616 .get(irpc_id)
617 .ok_or(Error::Rc(ResponseCode::INVALID_ARGUMENT))
618 .context(format!("In get_attestation_key: unknown irpc id '{}'", irpc_id))?;
619 let (_, _, km_uuid) = get_keymint_device(sec_level)?;
620
Max Bires55620ff2022-02-11 13:34:15 -0800621 let guard_and_cert_chain =
622 get_rem_prov_attest_key(Domain::APP, caller_uid as u32, db, &km_uuid)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000623 .context(ks_err!())?;
Max Bires55620ff2022-02-11 13:34:15 -0800624 match guard_and_cert_chain {
625 Some((_, chain)) => Ok(RemotelyProvisionedKey {
Seth Moore92648b62022-02-02 13:26:18 -0800626 keyBlob: chain.private_key.to_vec(),
627 encodedCertChain: chain.cert_chain,
628 }),
629 // It should be impossible to get `None`, but handle it just in case as a
630 // precaution against future behavioral changes in `get_rem_prov_attest_key`.
631 None => Err(error::Error::Rc(ResponseCode::OUT_OF_KEYS))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000632 .context(ks_err!("No available attestation keys")),
Seth Moore92648b62022-02-02 13:26:18 -0800633 }
634 }
635
636 /// Creates a new instance of the remotely provisioned key pool service, used for fetching
637 /// remotely provisioned attestation keys.
638 pub fn new_native_binder() -> Result<Strong<dyn IRemotelyProvisionedKeyPool>> {
639 let mut result: Self = Default::default();
640
641 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000642 .context(ks_err!("Failed to get TEE Remote Provisioner instance."))?;
Seth Moore92648b62022-02-02 13:26:18 -0800643 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
644 result.unique_id_to_sec_level.insert(id, SecurityLevel::TRUSTED_ENVIRONMENT);
645 }
646
647 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
648 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
649 if result.unique_id_to_sec_level.contains_key(&id) {
650 anyhow::bail!("In new_native_binder: duplicate irpc id found: '{}'", id)
651 }
652 result.unique_id_to_sec_level.insert(id, SecurityLevel::STRONGBOX);
653 }
654 }
655
656 // If none of the remotely provisioned components have unique ids, then we shouldn't
657 // bother publishing the service, as it's impossible to match keys with their backends.
658 if result.unique_id_to_sec_level.is_empty() {
659 anyhow::bail!(
660 "In new_native_binder: No remotely provisioned components have unique ids"
661 )
662 }
663
664 Ok(BnRemotelyProvisionedKeyPool::new_binder(
665 result,
666 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
667 ))
668 }
669}
670
671impl binder::Interface for RemotelyProvisionedKeyPoolService {}
672
Seth Moore7ee79f92021-12-07 11:42:49 -0800673// Implementation of IRemotelyProvisionedKeyPool. See AIDL spec at
674// :aidl/android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.aidl
Seth Moore92648b62022-02-02 13:26:18 -0800675impl IRemotelyProvisionedKeyPool for RemotelyProvisionedKeyPoolService {
Seth Moore7ee79f92021-12-07 11:42:49 -0800676 fn getAttestationKey(
677 &self,
678 caller_uid: i32,
679 irpc_id: &str,
680 ) -> binder::Result<RemotelyProvisionedKey> {
681 let _wp = wd::watch_millis("IRemotelyProvisionedKeyPool::getAttestationKey", 500);
682 map_or_log_err(check_keystore_permission(KeystorePerm::GetAttestationKey), Ok)?;
683 DB.with::<_, binder::Result<RemotelyProvisionedKey>>(|db| {
684 map_or_log_err(self.get_attestation_key(&mut db.borrow_mut(), caller_uid, irpc_id), Ok)
685 })
686 }
687}
688
Max Bires48fc2e52021-11-17 10:13:04 -0800689#[cfg(test)]
690mod tests {
691 use super::*;
692 use serde_cbor::Value;
693 use std::collections::BTreeMap;
Seth Moore7ee79f92021-12-07 11:42:49 -0800694 use std::sync::{Arc, Mutex};
695 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
696 RpcHardwareInfo::RpcHardwareInfo,
697 };
698
699 #[derive(Default)]
700 struct MockRemotelyProvisionedComponentValues {
701 hw_info: RpcHardwareInfo,
702 private_key: Vec<u8>,
703 maced_public_key: Vec<u8>,
704 }
705
706 // binder::Interface requires the Send trait, so we have to use a Mutex even though the test
707 // is single threaded.
708 #[derive(Default)]
709 struct MockRemotelyProvisionedComponent(Arc<Mutex<MockRemotelyProvisionedComponentValues>>);
710
711 impl binder::Interface for MockRemotelyProvisionedComponent {}
712
713 impl IRemotelyProvisionedComponent for MockRemotelyProvisionedComponent {
714 fn getHardwareInfo(&self) -> binder::Result<RpcHardwareInfo> {
715 Ok(self.0.lock().unwrap().hw_info.clone())
716 }
717
718 fn generateEcdsaP256KeyPair(
719 &self,
720 test_mode: bool,
721 maced_public_key: &mut MacedPublicKey,
722 ) -> binder::Result<Vec<u8>> {
723 assert!(test_mode);
724 maced_public_key.macedKey = self.0.lock().unwrap().maced_public_key.clone();
725 Ok(self.0.lock().unwrap().private_key.clone())
726 }
727
728 fn generateCertificateRequest(
729 &self,
730 _test_mode: bool,
731 _keys_to_sign: &[MacedPublicKey],
732 _eek: &[u8],
733 _challenge: &[u8],
734 _device_info: &mut DeviceInfo,
735 _protected_data: &mut ProtectedData,
736 ) -> binder::Result<Vec<u8>> {
737 Err(binder::StatusCode::INVALID_OPERATION.into())
738 }
Tri Vo113a1c92022-10-02 15:23:19 -0700739
740 fn generateCertificateRequestV2(
741 &self,
742 _keys_to_sign: &[MacedPublicKey],
743 _challenge: &[u8],
744 ) -> binder::Result<Vec<u8>> {
745 Err(binder::StatusCode::INVALID_OPERATION.into())
746 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800747 }
748
749 // Hard coded cert that can be parsed -- the content doesn't matter for testing, only that it's valid.
750 fn get_fake_cert() -> Vec<u8> {
751 vec![
752 0x30, 0x82, 0x01, 0xbb, 0x30, 0x82, 0x01, 0x61, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
753 0x14, 0x3a, 0xd5, 0x67, 0xce, 0xfe, 0x93, 0xe1, 0xea, 0xb7, 0xe4, 0xbf, 0x64, 0x19,
754 0xa4, 0x11, 0xe1, 0x87, 0x40, 0x20, 0x37, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
755 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
756 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
757 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
758 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
759 0x6c, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x30, 0x32, 0x32,
760 0x30, 0x38, 0x35, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x34, 0x32, 0x36, 0x32,
761 0x32, 0x30, 0x38, 0x35, 0x32, 0x5a, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
762 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
763 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
764 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f,
765 0x67, 0x6c, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
766 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
767 0x00, 0x04, 0x1e, 0xac, 0x0c, 0xe0, 0x0d, 0xc5, 0x25, 0x84, 0x1b, 0xd2, 0x77, 0x2d,
768 0xe7, 0xba, 0xf1, 0xde, 0xa7, 0xf6, 0x39, 0x7f, 0x38, 0x91, 0xbf, 0xa4, 0x58, 0xf5,
769 0x62, 0x6b, 0xce, 0x06, 0xcf, 0xb9, 0x73, 0x91, 0x0d, 0x8a, 0x60, 0xa0, 0xc6, 0xa2,
770 0x22, 0xe6, 0x51, 0x2e, 0x58, 0xd6, 0x43, 0x02, 0x80, 0x43, 0x44, 0x29, 0x38, 0x9a,
771 0x99, 0xf3, 0xa4, 0xdd, 0xd0, 0xb4, 0x6f, 0x8b, 0x44, 0x2d, 0xa3, 0x53, 0x30, 0x51,
772 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdb, 0x13, 0x68,
773 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe, 0x42, 0x3c, 0xd9, 0x3f, 0x1a,
774 0x33, 0xe9, 0xaa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
775 0x80, 0x14, 0xdb, 0x13, 0x68, 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe,
776 0x42, 0x3c, 0xd9, 0x3f, 0x1a, 0x33, 0xe9, 0xaa, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
777 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06,
778 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
779 0x02, 0x20, 0x10, 0xdf, 0x40, 0xc3, 0x20, 0x54, 0x36, 0xb5, 0xc9, 0x3c, 0x70, 0xe3,
780 0x55, 0x37, 0xd2, 0x04, 0x51, 0xeb, 0x0f, 0x18, 0x83, 0xd0, 0x58, 0xa1, 0x08, 0x77,
781 0x8d, 0x4d, 0xa4, 0x20, 0xee, 0x33, 0x02, 0x21, 0x00, 0x8d, 0xe3, 0xa6, 0x6c, 0x0d,
782 0x86, 0x25, 0xdc, 0x59, 0x0d, 0x21, 0x43, 0x22, 0x3a, 0xb9, 0xa1, 0x73, 0x28, 0xc9,
783 0x16, 0x9e, 0x91, 0x15, 0xc4, 0xc3, 0xd7, 0xeb, 0xe5, 0xce, 0xdc, 0x1c, 0x1b,
784 ]
785 }
786
787 // Generate a fake COSE_Mac0 with a key that's just `byte` repeated
788 fn generate_maced_pubkey(byte: u8) -> Vec<u8> {
789 vec![
790 0x84, 0x43, 0xA1, 0x01, 0x05, 0xA0, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20,
791 0x01, 0x21, 0x58, 0x20, 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, byte, byte, byte, byte, byte, byte, byte, 0x22, 0x58, 0x20, 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, byte, byte, byte, byte, byte, byte, byte,
796 byte, 0x58, 0x20, byte, 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,
799 ]
800 }
Max Bires48fc2e52021-11-17 10:13:04 -0800801
802 #[test]
803 fn test_parse_cose_mac0_for_coords_raw_bytes() -> Result<()> {
804 let cose_mac0: Vec<u8> = vec![
805 0x84, 0x01, 0x02, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
806 0x20, 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9,
807 0x21, 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C,
808 0x43, 0x22, 0xC8, 0xEE, 0x03, 0x22, 0x58, 0x20, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95,
809 0x90, 0xA7, 0x5C, 0x5A, 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A,
810 0xA3, 0xB3, 0x1A, 0xB4, 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC, 0x03,
811 ];
812 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&cose_mac0)?;
813 assert_eq!(
814 raw_key,
815 vec![
816 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9, 0x21,
817 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C, 0x43,
818 0x22, 0xC8, 0xEE, 0x03, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95, 0x90, 0xA7, 0x5C, 0x5A,
819 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A, 0xA3, 0xB3, 0x1A, 0xB4,
820 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC,
821 ]
822 );
823 Ok(())
824 }
825
826 #[test]
827 fn test_parse_cose_mac0_for_coords_constructed_mac() -> Result<()> {
828 let x_coord: Vec<u8> = vec![0; 32];
829 let y_coord: Vec<u8> = vec![1; 32];
830 let mut expected_key: Vec<u8> = Vec::new();
831 expected_key.extend(&x_coord);
832 expected_key.extend(&y_coord);
833 let key_map: BTreeMap<Value, Value> = BTreeMap::from([
834 (Value::Integer(1), Value::Integer(2)),
835 (Value::Integer(3), Value::Integer(-7)),
836 (Value::Integer(-1), Value::Integer(1)),
837 (Value::Integer(-2), Value::Bytes(x_coord)),
838 (Value::Integer(-3), Value::Bytes(y_coord)),
839 ]);
840 let cose_mac0: Vec<Value> = vec![
841 Value::Integer(0),
842 Value::Integer(1),
843 Value::from(serde_cbor::to_vec(&key_map)?),
844 Value::Integer(2),
845 ];
846 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&serde_cbor::to_vec(
847 &Value::from(cose_mac0),
848 )?)?;
849 assert_eq!(expected_key, raw_key);
850 Ok(())
851 }
852
853 #[test]
854 fn test_extract_payload_from_cose_mac() -> Result<()> {
855 let key_map = Value::Map(BTreeMap::from([(Value::Integer(1), Value::Integer(2))]));
856 let payload = Value::Bytes(serde_cbor::to_vec(&key_map)?);
857 let cose_mac0 =
858 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
859 let extracted_map = RemoteProvisioningService::extract_payload_from_cose_mac(
860 &serde_cbor::to_vec(&cose_mac0)?,
861 )?;
862 assert_eq!(key_map, extracted_map);
863 Ok(())
864 }
865
866 #[test]
867 fn test_extract_payload_from_cose_mac_fails_malformed_payload() -> Result<()> {
868 let payload = Value::Bytes(vec![5; 10]);
869 let cose_mac0 =
870 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
871 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
872 &serde_cbor::to_vec(&cose_mac0)?,
873 );
874 assert!(extracted_payload.is_err());
875 Ok(())
876 }
877
878 #[test]
879 fn test_extract_payload_from_cose_mac_fails_type() -> Result<()> {
880 let payload = Value::Integer(1);
881 let cose_mac0 =
882 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
883 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
884 &serde_cbor::to_vec(&cose_mac0)?,
885 );
886 assert!(extracted_payload.is_err());
887 Ok(())
888 }
889
890 #[test]
891 fn test_extract_payload_from_cose_mac_fails_length() -> Result<()> {
892 let cose_mac0 = Value::Array(vec![Value::Integer(0), Value::Integer(1)]);
893 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
894 &serde_cbor::to_vec(&cose_mac0)?,
895 );
896 assert!(extracted_payload.is_err());
897 Ok(())
898 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800899
900 #[test]
901 #[ignore] // b/215746308
902 fn test_get_attestation_key_no_keys_provisioned() {
903 let mut db = crate::database::tests::new_test_db().unwrap();
904 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
905 mock_rpc.0.lock().unwrap().hw_info.uniqueId = Some(String::from("mallory"));
906
Seth Moore92648b62022-02-02 13:26:18 -0800907 let mut service: RemotelyProvisionedKeyPoolService = Default::default();
Seth Moore7ee79f92021-12-07 11:42:49 -0800908 service
Seth Moore92648b62022-02-02 13:26:18 -0800909 .unique_id_to_sec_level
910 .insert(String::from("mallory"), SecurityLevel::TRUSTED_ENVIRONMENT);
Seth Moore7ee79f92021-12-07 11:42:49 -0800911
912 assert_eq!(
913 service
914 .get_attestation_key(&mut db, 0, "mallory")
915 .unwrap_err()
916 .downcast::<error::Error>()
917 .unwrap(),
918 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
919 );
920 }
921
922 #[test]
923 #[ignore] // b/215746308
924 fn test_get_attestation_key() {
925 let mut db = crate::database::tests::new_test_db().unwrap();
926 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
927 let irpc_id = "paul";
928 let caller_uid = 0;
929
930 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
931 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800932 let mut remote_provisioning: RemoteProvisioningService = Default::default();
933 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
934 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
935 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800936
937 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
938 mock_values.lock().unwrap().private_key = vec![8, 6, 7, 5, 3, 0, 9];
939 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -0800940 remote_provisioning.generate_key_pair(&mut db, true, sec_level).unwrap();
Seth Moore7ee79f92021-12-07 11:42:49 -0800941
942 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
943 mock_values.lock().unwrap().maced_public_key.as_slice(),
944 )
945 .unwrap();
946 let batch_cert = get_fake_cert();
947 let certs = &[5, 6, 7, 8];
Seth Moore92648b62022-02-02 13:26:18 -0800948 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -0800949 .provision_cert_chain(
950 &mut db,
951 public_key.as_slice(),
952 batch_cert.as_slice(),
953 certs,
954 0,
955 sec_level
956 )
957 .is_ok());
958
959 // ensure we got the key we expected
Seth Moore92648b62022-02-02 13:26:18 -0800960 let first_key = key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800961 .get_attestation_key(&mut db, caller_uid, irpc_id)
962 .context("get first key")
963 .unwrap();
964 assert_eq!(first_key.keyBlob, mock_values.lock().unwrap().private_key);
965 assert_eq!(first_key.encodedCertChain, certs);
966
967 // ensure that multiple calls get the same key
968 assert_eq!(
969 first_key,
Seth Moore92648b62022-02-02 13:26:18 -0800970 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800971 .get_attestation_key(&mut db, caller_uid, irpc_id)
972 .context("get second key")
973 .unwrap()
974 );
975
976 // no more keys for new clients
977 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -0800978 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800979 .get_attestation_key(&mut db, caller_uid + 1, irpc_id)
980 .unwrap_err()
981 .downcast::<error::Error>()
982 .unwrap(),
983 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
984 );
985 }
986
987 #[test]
988 #[ignore] // b/215746308
989 fn test_get_attestation_key_gets_different_key_for_different_client() {
990 let mut db = crate::database::tests::new_test_db().unwrap();
991 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
992 let irpc_id = "ringo";
993 let first_caller = 0;
994 let second_caller = first_caller + 1;
995
996 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
997 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800998 let mut remote_provisioning: RemoteProvisioningService = Default::default();
999 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
1000 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
1001 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -08001002
1003 // generate two distinct keys and provision them with certs
1004 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1005 mock_values.lock().unwrap().private_key = vec![3, 1, 4, 1, 5];
1006 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -08001007 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001008 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1009 mock_values.lock().unwrap().maced_public_key.as_slice(),
1010 )
1011 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001012 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001013 .provision_cert_chain(
1014 &mut db,
1015 public_key.as_slice(),
1016 get_fake_cert().as_slice(),
1017 &[1],
1018 0,
1019 sec_level
1020 )
1021 .is_ok());
1022
1023 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1024 mock_values.lock().unwrap().private_key = vec![9, 0, 2, 1, 0];
1025 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x22);
Seth Moore92648b62022-02-02 13:26:18 -08001026 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001027 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1028 mock_values.lock().unwrap().maced_public_key.as_slice(),
1029 )
1030 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001031 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001032 .provision_cert_chain(
1033 &mut db,
1034 public_key.as_slice(),
1035 get_fake_cert().as_slice(),
1036 &[2],
1037 0,
1038 sec_level
1039 )
1040 .is_ok());
1041
1042 // make sure each caller gets a distinct key
1043 assert_ne!(
Seth Moore92648b62022-02-02 13:26:18 -08001044 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001045 .get_attestation_key(&mut db, first_caller, irpc_id)
1046 .context("get first key")
1047 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001048 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001049 .get_attestation_key(&mut db, second_caller, irpc_id)
1050 .context("get second key")
1051 .unwrap()
1052 );
1053
1054 // repeated calls should return the same key for a given caller
1055 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001056 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001057 .get_attestation_key(&mut db, first_caller, irpc_id)
1058 .context("first caller a")
1059 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001060 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001061 .get_attestation_key(&mut db, first_caller, irpc_id)
1062 .context("first caller b")
1063 .unwrap(),
1064 );
1065
1066 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001067 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001068 .get_attestation_key(&mut db, second_caller, irpc_id)
1069 .context("second caller a")
1070 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001071 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001072 .get_attestation_key(&mut db, second_caller, irpc_id)
1073 .context("second caller b")
1074 .unwrap()
1075 );
1076 }
Max Bires48fc2e52021-11-17 10:13:04 -08001077}