blob: b47b3731bc0a86516886a0d6cb5b8eff3b8f5058 [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 }
Hasini Gunasinghe8a1a2242021-08-02 22:28:39 +0000162 log_rkp_error_stats(MetricsRkpError::FALL_BACK_DURING_HYBRID);
Max Bires31cdfb82021-07-06 02:59:25 -0700163 Ok(None)
164 }
165 Ok(v) => match v {
Max Bires55620ff2022-02-11 13:34:15 -0800166 Some((guard, cert_chain)) => Ok(Some((
167 guard,
Max Bires31cdfb82021-07-06 02:59:25 -0700168 AttestationKey {
169 keyBlob: cert_chain.private_key.to_vec(),
170 attestKeyParams: vec![],
171 issuerSubjectName: parse_subject_from_certificate(
172 &cert_chain.batch_cert,
173 )
Max Bires97f96812021-02-23 23:44:57 -0800174 .context(concat!(
Max Bires31cdfb82021-07-06 02:59:25 -0700175 "In get_remote_provisioning_key_and_certs: Failed to ",
176 "parse subject."
177 ))?,
178 },
179 Certificate { encodedCertificate: cert_chain.cert_chain },
180 ))),
181 None => Ok(None),
182 },
Max Bires97f96812021-02-23 23:44:57 -0800183 }
184 }
185 }
186}
Max Bires148c08e2020-10-13 13:41:41 -0700187/// Implementation of the IRemoteProvisioning service.
Max Biresb2e1d032021-02-08 21:35:05 -0800188#[derive(Default)]
Max Bires148c08e2020-10-13 13:41:41 -0700189pub struct RemoteProvisioningService {
Janis Danisevskis5f3a0572021-06-18 11:26:42 -0700190 device_by_sec_level: HashMap<SecurityLevel, Strong<dyn IRemotelyProvisionedComponent>>,
Max Biresd2ce46b2021-07-06 02:54:47 -0700191 curve_by_sec_level: HashMap<SecurityLevel, i32>,
Max Bires148c08e2020-10-13 13:41:41 -0700192}
193
194impl RemoteProvisioningService {
Max Biresb2e1d032021-02-08 21:35:05 -0800195 fn get_dev_by_sec_level(
196 &self,
197 sec_level: &SecurityLevel,
Seth Moore7ee79f92021-12-07 11:42:49 -0800198 ) -> Result<&dyn IRemotelyProvisionedComponent> {
Max Biresb2e1d032021-02-08 21:35:05 -0800199 if let Some(dev) = self.device_by_sec_level.get(sec_level) {
Seth Moore7ee79f92021-12-07 11:42:49 -0800200 Ok(dev.as_ref())
Max Biresb2e1d032021-02-08 21:35:05 -0800201 } else {
202 Err(error::Error::sys()).context(concat!(
203 "In get_dev_by_sec_level: Remote instance for requested security level",
204 " not found."
205 ))
206 }
207 }
208
Max Bires148c08e2020-10-13 13:41:41 -0700209 /// Creates a new instance of the remote provisioning service
Stephen Crane221bbb52020-12-16 15:52:10 -0800210 pub fn new_native_binder() -> Result<Strong<dyn IRemoteProvisioning>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800211 let mut result: Self = Default::default();
212 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
213 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
Max Biresd2ce46b2021-07-06 02:54:47 -0700214 result.curve_by_sec_level.insert(
215 SecurityLevel::TRUSTED_ENVIRONMENT,
216 dev.getHardwareInfo()
217 .context("In new_native_binder: Failed to get hardware info for the TEE.")?
218 .supportedEekCurve,
219 );
Max Biresb2e1d032021-02-08 21:35:05 -0800220 result.device_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, dev);
221 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
Max Biresd2ce46b2021-07-06 02:54:47 -0700222 result.curve_by_sec_level.insert(
223 SecurityLevel::STRONGBOX,
224 dev.getHardwareInfo()
225 .context("In new_native_binder: Failed to get hardware info for StrongBox.")?
226 .supportedEekCurve,
227 );
Max Biresb2e1d032021-02-08 21:35:05 -0800228 result.device_by_sec_level.insert(SecurityLevel::STRONGBOX, dev);
229 }
Andrew Walbrande45c8b2021-04-13 14:42:38 +0000230 Ok(BnRemoteProvisioning::new_binder(result, BinderFeatures::default()))
Max Bires148c08e2020-10-13 13:41:41 -0700231 }
232
Max Bires48fc2e52021-11-17 10:13:04 -0800233 fn extract_payload_from_cose_mac(data: &[u8]) -> Result<Value> {
234 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data).context(
235 "In extract_payload_from_cose_mac: COSE_Mac0 returned from IRPC cannot be parsed",
236 )?;
237 if cose_mac0.len() != COSE_MAC0_LEN {
238 return Err(error::Error::sys()).context(format!(
239 "In extract_payload_from_cose_mac: COSE_Mac0 has improper length. \
240 Expected: {}, Actual: {}",
241 COSE_MAC0_LEN,
242 cose_mac0.len(),
243 ));
244 }
245 match &cose_mac0[COSE_MAC0_PAYLOAD] {
246 Value::Bytes(key) => Ok(serde_cbor::from_slice(key)
247 .context("In extract_payload_from_cose_mac: COSE_Mac0 payload is malformed.")?),
248 _ => Err(error::Error::sys()).context(
249 "In extract_payload_from_cose_mac: COSE_Mac0 payload is the wrong type.",
250 )?,
251 }
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 ))
291 .context("In generate_csr: 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)
296 .context("In generate_csr: Failed to get the payload from the COSE_Mac0")?,
297 )
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)
301 .context("In generate_csr: 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>> {
329 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data).context(
330 "In parse_cose_mac0_for_coords: COSE_Mac0 returned from IRPC cannot be parsed",
331 )?;
332 if cose_mac0.len() != COSE_MAC0_LEN {
333 return Err(error::Error::sys()).context(format!(
334 "In parse_cose_mac0_for_coords: COSE_Mac0 has improper length. \
335 Expected: {}, Actual: {}",
336 COSE_MAC0_LEN,
337 cose_mac0.len(),
338 ));
339 }
340 let cose_key: BTreeMap<Value, Value> = match &cose_mac0[COSE_MAC0_PAYLOAD] {
341 Value::Bytes(key) => serde_cbor::from_slice(key)
342 .context("In parse_cose_mac0_for_coords: COSE_Key is malformed.")?,
343 _ => Err(error::Error::sys())
344 .context("In parse_cose_mac0_for_coords: COSE_Mac0 payload is the wrong type.")?,
345 };
346 if !cose_key.contains_key(&COSE_KEY_XCOORD) || !cose_key.contains_key(&COSE_KEY_YCOORD) {
347 return Err(error::Error::sys()).context(
348 "In parse_cose_mac0_for_coords: \
349 COSE_Key returned from IRPC is lacking required fields",
350 );
351 }
352 let mut raw_key: Vec<u8> = vec![0; 64];
353 match &cose_key[&COSE_KEY_XCOORD] {
354 Value::Bytes(x_coord) if x_coord.len() == 32 => {
355 raw_key[0..32].clone_from_slice(x_coord)
356 }
357 Value::Bytes(x_coord) => {
358 return Err(error::Error::sys()).context(format!(
359 "In parse_cose_mac0_for_coords: COSE_Key X-coordinate is not the right length. \
360 Expected: 32; Actual: {}",
361 x_coord.len()
362 ))
363 }
364 _ => {
365 return Err(error::Error::sys())
366 .context("In parse_cose_mac0_for_coords: COSE_Key X-coordinate is not a bstr")
367 }
368 }
369 match &cose_key[&COSE_KEY_YCOORD] {
370 Value::Bytes(y_coord) if y_coord.len() == 32 => {
371 raw_key[32..64].clone_from_slice(y_coord)
372 }
373 Value::Bytes(y_coord) => {
374 return Err(error::Error::sys()).context(format!(
375 "In parse_cose_mac0_for_coords: COSE_Key Y-coordinate is not the right length. \
376 Expected: 32; Actual: {}",
377 y_coord.len()
378 ))
379 }
380 _ => {
381 return Err(error::Error::sys())
382 .context("In parse_cose_mac0_for_coords: COSE_Key Y-coordinate is not a bstr")
383 }
384 }
385 Ok(raw_key)
386 }
387
Max Bires148c08e2020-10-13 13:41:41 -0700388 /// Submits a request to the Remote Provisioner HAL to generate a signing key pair.
389 /// `is_test_mode` indicates whether or not the returned public key should be marked as being
390 /// for testing in order to differentiate them from private keys. If the call is successful,
391 /// the key pair is then added to the database.
Seth Moore7ee79f92021-12-07 11:42:49 -0800392 pub fn generate_key_pair(
393 &self,
394 db: &mut KeystoreDB,
395 is_test_mode: bool,
396 sec_level: SecurityLevel,
397 ) -> Result<()> {
Max Biresb2e1d032021-02-08 21:35:05 -0800398 let (_, _, uuid) = get_keymint_device(&sec_level)?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800399 let dev = self.get_dev_by_sec_level(&sec_level).context(format!(
400 "In generate_key_pair: Failed to get device for security level {:?}",
401 sec_level
402 ))?;
Max Biresb2e1d032021-02-08 21:35:05 -0800403 let mut maced_key = MacedPublicKey { macedKey: Vec::new() };
404 let priv_key =
405 map_rem_prov_error(dev.generateEcdsaP256KeyPair(is_test_mode, &mut maced_key))
406 .context("In generate_key_pair: Failed to generated ECDSA keypair.")?;
Max Bires48fc2e52021-11-17 10:13:04 -0800407 let raw_key = Self::parse_cose_mac0_for_coords(&maced_key.macedKey)
408 .context("In generate_key_pair: Failed to parse raw key")?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800409 db.create_attestation_key_entry(&maced_key.macedKey, &raw_key, &priv_key, &uuid)
410 .context("In generate_key_pair: Failed to insert attestation key entry")
Max Biresb2e1d032021-02-08 21:35:05 -0800411 }
412
413 /// Checks the security level of each available IRemotelyProvisionedComponent hal and returns
414 /// all levels in an array to the caller.
Max Biresd2ce46b2021-07-06 02:54:47 -0700415 pub fn get_implementation_info(&self) -> Result<Vec<ImplInfo>> {
416 Ok(self
417 .curve_by_sec_level
418 .iter()
419 .map(|(sec_level, curve)| ImplInfo { secLevel: *sec_level, supportedCurve: *curve })
420 .collect())
Max Bires148c08e2020-10-13 13:41:41 -0700421 }
Max Bires60d7ed12021-03-05 15:59:22 -0800422
423 /// Deletes all attestation keys generated by the IRemotelyProvisionedComponent from the device,
424 /// regardless of what state of the attestation key lifecycle they were in.
425 pub fn delete_all_keys(&self) -> Result<i64> {
426 DB.with::<_, Result<i64>>(|db| {
427 let mut db = db.borrow_mut();
Matthew Maurerb77a28d2021-05-07 16:08:20 -0700428 db.delete_all_attestation_keys()
Max Bires60d7ed12021-03-05 15:59:22 -0800429 })
430 }
Max Bires148c08e2020-10-13 13:41:41 -0700431}
432
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000433/// Populates the AttestationPoolStatus parcelable with information about how many
434/// certs will be expiring by the date provided in `expired_by` along with how many
435/// keys have not yet been assigned.
436pub fn get_pool_status(expired_by: i64, sec_level: SecurityLevel) -> Result<AttestationPoolStatus> {
437 let (_, _, uuid) = get_keymint_device(&sec_level)?;
438 DB.with::<_, Result<AttestationPoolStatus>>(|db| {
439 let mut db = db.borrow_mut();
440 // delete_expired_attestation_keys is always safe to call, and will remove anything
441 // older than the date at the time of calling. No work should be done on the
442 // attestation keys unless the pool status is checked first, so this call should be
443 // enough to routinely clean out expired keys.
444 db.delete_expired_attestation_keys()?;
445 db.get_attestation_pool_status(expired_by, &uuid)
446 })
447}
448
Seth Moore7ee79f92021-12-07 11:42:49 -0800449/// Fetches a remote provisioning attestation key and certificate chain inside of the
450/// returned `CertificateChain` struct if one exists for the given caller_uid. If one has not
451/// been assigned, this function will assign it. If there are no signed attestation keys
452/// available to be assigned, it will return the ResponseCode `OUT_OF_KEYS`
453fn get_rem_prov_attest_key(
454 domain: Domain,
455 caller_uid: u32,
456 db: &mut KeystoreDB,
457 km_uuid: &Uuid,
Max Bires55620ff2022-02-11 13:34:15 -0800458) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
Seth Moore7ee79f92021-12-07 11:42:49 -0800459 match domain {
460 Domain::APP => {
461 // Attempt to get an Attestation Key once. If it fails, then the app doesn't
462 // have a valid chain assigned to it. The helper function will return None after
463 // attempting to assign a key. An error will be thrown if the pool is simply out
464 // of usable keys. Then another attempt to fetch the just-assigned key will be
465 // made. If this fails too, something is very wrong.
466 get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid)
467 .context("In get_rem_prov_attest_key: Failed to get a key")?
468 .map_or_else(
469 || get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid),
470 |v| Ok(Some(v)),
471 )
472 .context(concat!(
473 "In get_rem_prov_attest_key: Failed to get a key after",
474 "attempting to assign one."
475 ))?
476 .map_or_else(
477 || {
478 Err(Error::sys()).context(concat!(
479 "In get_rem_prov_attest_key: Attempted to assign a ",
480 "key and failed silently. Something is very wrong."
481 ))
482 },
Max Bires55620ff2022-02-11 13:34:15 -0800483 |(guard, cert_chain)| Ok(Some((guard, cert_chain))),
Seth Moore7ee79f92021-12-07 11:42:49 -0800484 )
485 }
486 _ => Ok(None),
487 }
488}
489
490/// Returns None if an AttestationKey fails to be assigned. Errors if no keys are available.
491fn get_rem_prov_attest_key_helper(
492 domain: Domain,
493 caller_uid: u32,
494 db: &mut KeystoreDB,
495 km_uuid: &Uuid,
Max Bires55620ff2022-02-11 13:34:15 -0800496) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
497 let guard_and_chain = db
Seth Moore7ee79f92021-12-07 11:42:49 -0800498 .retrieve_attestation_key_and_cert_chain(domain, caller_uid as i64, km_uuid)
499 .context("In get_rem_prov_attest_key_helper: Failed to retrieve a key + cert chain")?;
Max Bires55620ff2022-02-11 13:34:15 -0800500 match guard_and_chain {
501 Some((guard, cert_chain)) => Ok(Some((guard, cert_chain))),
Seth Moore7ee79f92021-12-07 11:42:49 -0800502 // Either this app needs to be assigned a key, or the pool is empty. An error will
503 // be thrown if there is no key available to assign. This will indicate that the app
504 // should be nudged to provision more keys so keystore can retry.
505 None => {
506 db.assign_attestation_key(domain, caller_uid as i64, km_uuid)
507 .context("In get_rem_prov_attest_key_helper: Failed to assign a key")?;
508 Ok(None)
509 }
510 }
511}
512
Max Bires148c08e2020-10-13 13:41:41 -0700513impl binder::Interface for RemoteProvisioningService {}
514
515// Implementation of IRemoteProvisioning. See AIDL spec at
516// :aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
517impl IRemoteProvisioning for RemoteProvisioningService {
518 fn getPoolStatus(
519 &self,
520 expired_by: i64,
521 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700522 ) -> binder::Result<AttestationPoolStatus> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000523 let _wp = wd::watch_millis("IRemoteProvisioning::getPoolStatus", 500);
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000524 map_or_log_err(get_pool_status(expired_by, sec_level), Ok)
Max Bires148c08e2020-10-13 13:41:41 -0700525 }
526
527 fn generateCsr(
528 &self,
529 test_mode: bool,
530 num_csr: i32,
531 eek: &[u8],
532 challenge: &[u8],
533 sec_level: SecurityLevel,
Max Biresb2e1d032021-02-08 21:35:05 -0800534 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700535 device_info: &mut DeviceInfo,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700536 ) -> binder::Result<Vec<u8>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000537 let _wp = wd::watch_millis("IRemoteProvisioning::generateCsr", 500);
Max Biresb2e1d032021-02-08 21:35:05 -0800538 map_or_log_err(
Max Bires834dd362021-03-23 13:01:57 -0700539 self.generate_csr(
540 test_mode,
541 num_csr,
542 eek,
543 challenge,
544 sec_level,
545 protected_data,
546 device_info,
547 ),
Max Biresb2e1d032021-02-08 21:35:05 -0800548 Ok,
549 )
Max Bires148c08e2020-10-13 13:41:41 -0700550 }
551
552 fn provisionCertChain(
553 &self,
554 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800555 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700556 certs: &[u8],
557 expiration_date: i64,
558 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700559 ) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000560 let _wp = wd::watch_millis("IRemoteProvisioning::provisionCertChain", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800561 DB.with::<_, binder::Result<()>>(|db| {
562 map_or_log_err(
563 self.provision_cert_chain(
564 &mut db.borrow_mut(),
565 public_key,
566 batch_cert,
567 certs,
568 expiration_date,
569 sec_level,
570 ),
571 Ok,
572 )
573 })
Max Bires148c08e2020-10-13 13:41:41 -0700574 }
575
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700576 fn generateKeyPair(&self, is_test_mode: bool, sec_level: SecurityLevel) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000577 let _wp = wd::watch_millis("IRemoteProvisioning::generateKeyPair", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800578 DB.with::<_, binder::Result<()>>(|db| {
579 map_or_log_err(
580 self.generate_key_pair(&mut db.borrow_mut(), is_test_mode, sec_level),
581 Ok,
582 )
583 })
Max Bires148c08e2020-10-13 13:41:41 -0700584 }
Max Biresb2e1d032021-02-08 21:35:05 -0800585
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700586 fn getImplementationInfo(&self) -> binder::Result<Vec<ImplInfo>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000587 let _wp = wd::watch_millis("IRemoteProvisioning::getSecurityLevels", 500);
Max Biresd2ce46b2021-07-06 02:54:47 -0700588 map_or_log_err(self.get_implementation_info(), Ok)
Max Biresb2e1d032021-02-08 21:35:05 -0800589 }
Max Bires60d7ed12021-03-05 15:59:22 -0800590
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700591 fn deleteAllKeys(&self) -> binder::Result<i64> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000592 let _wp = wd::watch_millis("IRemoteProvisioning::deleteAllKeys", 500);
Max Bires60d7ed12021-03-05 15:59:22 -0800593 map_or_log_err(self.delete_all_keys(), Ok)
594 }
Max Bires148c08e2020-10-13 13:41:41 -0700595}
Max Bires48fc2e52021-11-17 10:13:04 -0800596
Seth Moore92648b62022-02-02 13:26:18 -0800597/// Implementation of the IRemotelyProvisionedKeyPool service.
598#[derive(Default)]
599pub struct RemotelyProvisionedKeyPoolService {
600 unique_id_to_sec_level: HashMap<String, SecurityLevel>,
601}
602
603impl RemotelyProvisionedKeyPoolService {
604 /// Fetches a remotely provisioned certificate chain and key for the given client uid that
605 /// was provisioned using the IRemotelyProvisionedComponent with the given id. The same key
606 /// will be returned for a given caller_uid on every request. If there are no attestation keys
607 /// available, `OUT_OF_KEYS` is returned.
608 fn get_attestation_key(
609 &self,
610 db: &mut KeystoreDB,
611 caller_uid: i32,
612 irpc_id: &str,
613 ) -> Result<RemotelyProvisionedKey> {
614 log::info!("get_attestation_key(self, {}, {}", caller_uid, irpc_id);
615
616 let sec_level = self
617 .unique_id_to_sec_level
618 .get(irpc_id)
619 .ok_or(Error::Rc(ResponseCode::INVALID_ARGUMENT))
620 .context(format!("In get_attestation_key: unknown irpc id '{}'", irpc_id))?;
621 let (_, _, km_uuid) = get_keymint_device(sec_level)?;
622
Max Bires55620ff2022-02-11 13:34:15 -0800623 let guard_and_cert_chain =
624 get_rem_prov_attest_key(Domain::APP, caller_uid as u32, db, &km_uuid)
625 .context("In get_attestation_key")?;
626 match guard_and_cert_chain {
627 Some((_, chain)) => Ok(RemotelyProvisionedKey {
Seth Moore92648b62022-02-02 13:26:18 -0800628 keyBlob: chain.private_key.to_vec(),
629 encodedCertChain: chain.cert_chain,
630 }),
631 // It should be impossible to get `None`, but handle it just in case as a
632 // precaution against future behavioral changes in `get_rem_prov_attest_key`.
633 None => Err(error::Error::Rc(ResponseCode::OUT_OF_KEYS))
634 .context("In get_attestation_key: No available attestation keys"),
635 }
636 }
637
638 /// Creates a new instance of the remotely provisioned key pool service, used for fetching
639 /// remotely provisioned attestation keys.
640 pub fn new_native_binder() -> Result<Strong<dyn IRemotelyProvisionedKeyPool>> {
641 let mut result: Self = Default::default();
642
643 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
644 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
645 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
646 result.unique_id_to_sec_level.insert(id, SecurityLevel::TRUSTED_ENVIRONMENT);
647 }
648
649 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
650 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
651 if result.unique_id_to_sec_level.contains_key(&id) {
652 anyhow::bail!("In new_native_binder: duplicate irpc id found: '{}'", id)
653 }
654 result.unique_id_to_sec_level.insert(id, SecurityLevel::STRONGBOX);
655 }
656 }
657
658 // If none of the remotely provisioned components have unique ids, then we shouldn't
659 // bother publishing the service, as it's impossible to match keys with their backends.
660 if result.unique_id_to_sec_level.is_empty() {
661 anyhow::bail!(
662 "In new_native_binder: No remotely provisioned components have unique ids"
663 )
664 }
665
666 Ok(BnRemotelyProvisionedKeyPool::new_binder(
667 result,
668 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
669 ))
670 }
671}
672
673impl binder::Interface for RemotelyProvisionedKeyPoolService {}
674
Seth Moore7ee79f92021-12-07 11:42:49 -0800675// Implementation of IRemotelyProvisionedKeyPool. See AIDL spec at
676// :aidl/android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.aidl
Seth Moore92648b62022-02-02 13:26:18 -0800677impl IRemotelyProvisionedKeyPool for RemotelyProvisionedKeyPoolService {
Seth Moore7ee79f92021-12-07 11:42:49 -0800678 fn getAttestationKey(
679 &self,
680 caller_uid: i32,
681 irpc_id: &str,
682 ) -> binder::Result<RemotelyProvisionedKey> {
683 let _wp = wd::watch_millis("IRemotelyProvisionedKeyPool::getAttestationKey", 500);
684 map_or_log_err(check_keystore_permission(KeystorePerm::GetAttestationKey), Ok)?;
685 DB.with::<_, binder::Result<RemotelyProvisionedKey>>(|db| {
686 map_or_log_err(self.get_attestation_key(&mut db.borrow_mut(), caller_uid, irpc_id), Ok)
687 })
688 }
689}
690
Max Bires48fc2e52021-11-17 10:13:04 -0800691#[cfg(test)]
692mod tests {
693 use super::*;
694 use serde_cbor::Value;
695 use std::collections::BTreeMap;
Seth Moore7ee79f92021-12-07 11:42:49 -0800696 use std::sync::{Arc, Mutex};
697 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
698 RpcHardwareInfo::RpcHardwareInfo,
699 };
700
701 #[derive(Default)]
702 struct MockRemotelyProvisionedComponentValues {
703 hw_info: RpcHardwareInfo,
704 private_key: Vec<u8>,
705 maced_public_key: Vec<u8>,
706 }
707
708 // binder::Interface requires the Send trait, so we have to use a Mutex even though the test
709 // is single threaded.
710 #[derive(Default)]
711 struct MockRemotelyProvisionedComponent(Arc<Mutex<MockRemotelyProvisionedComponentValues>>);
712
713 impl binder::Interface for MockRemotelyProvisionedComponent {}
714
715 impl IRemotelyProvisionedComponent for MockRemotelyProvisionedComponent {
716 fn getHardwareInfo(&self) -> binder::Result<RpcHardwareInfo> {
717 Ok(self.0.lock().unwrap().hw_info.clone())
718 }
719
720 fn generateEcdsaP256KeyPair(
721 &self,
722 test_mode: bool,
723 maced_public_key: &mut MacedPublicKey,
724 ) -> binder::Result<Vec<u8>> {
725 assert!(test_mode);
726 maced_public_key.macedKey = self.0.lock().unwrap().maced_public_key.clone();
727 Ok(self.0.lock().unwrap().private_key.clone())
728 }
729
730 fn generateCertificateRequest(
731 &self,
732 _test_mode: bool,
733 _keys_to_sign: &[MacedPublicKey],
734 _eek: &[u8],
735 _challenge: &[u8],
736 _device_info: &mut DeviceInfo,
737 _protected_data: &mut ProtectedData,
738 ) -> binder::Result<Vec<u8>> {
739 Err(binder::StatusCode::INVALID_OPERATION.into())
740 }
741 }
742
743 // Hard coded cert that can be parsed -- the content doesn't matter for testing, only that it's valid.
744 fn get_fake_cert() -> Vec<u8> {
745 vec![
746 0x30, 0x82, 0x01, 0xbb, 0x30, 0x82, 0x01, 0x61, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
747 0x14, 0x3a, 0xd5, 0x67, 0xce, 0xfe, 0x93, 0xe1, 0xea, 0xb7, 0xe4, 0xbf, 0x64, 0x19,
748 0xa4, 0x11, 0xe1, 0x87, 0x40, 0x20, 0x37, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
749 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
750 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
751 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
752 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
753 0x6c, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x30, 0x32, 0x32,
754 0x30, 0x38, 0x35, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x34, 0x32, 0x36, 0x32,
755 0x32, 0x30, 0x38, 0x35, 0x32, 0x5a, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
756 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
757 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
758 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f,
759 0x67, 0x6c, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
760 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
761 0x00, 0x04, 0x1e, 0xac, 0x0c, 0xe0, 0x0d, 0xc5, 0x25, 0x84, 0x1b, 0xd2, 0x77, 0x2d,
762 0xe7, 0xba, 0xf1, 0xde, 0xa7, 0xf6, 0x39, 0x7f, 0x38, 0x91, 0xbf, 0xa4, 0x58, 0xf5,
763 0x62, 0x6b, 0xce, 0x06, 0xcf, 0xb9, 0x73, 0x91, 0x0d, 0x8a, 0x60, 0xa0, 0xc6, 0xa2,
764 0x22, 0xe6, 0x51, 0x2e, 0x58, 0xd6, 0x43, 0x02, 0x80, 0x43, 0x44, 0x29, 0x38, 0x9a,
765 0x99, 0xf3, 0xa4, 0xdd, 0xd0, 0xb4, 0x6f, 0x8b, 0x44, 0x2d, 0xa3, 0x53, 0x30, 0x51,
766 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdb, 0x13, 0x68,
767 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe, 0x42, 0x3c, 0xd9, 0x3f, 0x1a,
768 0x33, 0xe9, 0xaa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
769 0x80, 0x14, 0xdb, 0x13, 0x68, 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe,
770 0x42, 0x3c, 0xd9, 0x3f, 0x1a, 0x33, 0xe9, 0xaa, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
771 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06,
772 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
773 0x02, 0x20, 0x10, 0xdf, 0x40, 0xc3, 0x20, 0x54, 0x36, 0xb5, 0xc9, 0x3c, 0x70, 0xe3,
774 0x55, 0x37, 0xd2, 0x04, 0x51, 0xeb, 0x0f, 0x18, 0x83, 0xd0, 0x58, 0xa1, 0x08, 0x77,
775 0x8d, 0x4d, 0xa4, 0x20, 0xee, 0x33, 0x02, 0x21, 0x00, 0x8d, 0xe3, 0xa6, 0x6c, 0x0d,
776 0x86, 0x25, 0xdc, 0x59, 0x0d, 0x21, 0x43, 0x22, 0x3a, 0xb9, 0xa1, 0x73, 0x28, 0xc9,
777 0x16, 0x9e, 0x91, 0x15, 0xc4, 0xc3, 0xd7, 0xeb, 0xe5, 0xce, 0xdc, 0x1c, 0x1b,
778 ]
779 }
780
781 // Generate a fake COSE_Mac0 with a key that's just `byte` repeated
782 fn generate_maced_pubkey(byte: u8) -> Vec<u8> {
783 vec![
784 0x84, 0x43, 0xA1, 0x01, 0x05, 0xA0, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20,
785 0x01, 0x21, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
786 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
787 byte, byte, byte, byte, byte, byte, byte, byte, 0x22, 0x58, 0x20, byte, byte, byte,
788 byte, byte, byte, byte, 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, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, 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,
793 ]
794 }
Max Bires48fc2e52021-11-17 10:13:04 -0800795
796 #[test]
797 fn test_parse_cose_mac0_for_coords_raw_bytes() -> Result<()> {
798 let cose_mac0: Vec<u8> = vec![
799 0x84, 0x01, 0x02, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
800 0x20, 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9,
801 0x21, 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C,
802 0x43, 0x22, 0xC8, 0xEE, 0x03, 0x22, 0x58, 0x20, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95,
803 0x90, 0xA7, 0x5C, 0x5A, 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A,
804 0xA3, 0xB3, 0x1A, 0xB4, 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC, 0x03,
805 ];
806 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&cose_mac0)?;
807 assert_eq!(
808 raw_key,
809 vec![
810 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9, 0x21,
811 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C, 0x43,
812 0x22, 0xC8, 0xEE, 0x03, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95, 0x90, 0xA7, 0x5C, 0x5A,
813 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A, 0xA3, 0xB3, 0x1A, 0xB4,
814 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC,
815 ]
816 );
817 Ok(())
818 }
819
820 #[test]
821 fn test_parse_cose_mac0_for_coords_constructed_mac() -> Result<()> {
822 let x_coord: Vec<u8> = vec![0; 32];
823 let y_coord: Vec<u8> = vec![1; 32];
824 let mut expected_key: Vec<u8> = Vec::new();
825 expected_key.extend(&x_coord);
826 expected_key.extend(&y_coord);
827 let key_map: BTreeMap<Value, Value> = BTreeMap::from([
828 (Value::Integer(1), Value::Integer(2)),
829 (Value::Integer(3), Value::Integer(-7)),
830 (Value::Integer(-1), Value::Integer(1)),
831 (Value::Integer(-2), Value::Bytes(x_coord)),
832 (Value::Integer(-3), Value::Bytes(y_coord)),
833 ]);
834 let cose_mac0: Vec<Value> = vec![
835 Value::Integer(0),
836 Value::Integer(1),
837 Value::from(serde_cbor::to_vec(&key_map)?),
838 Value::Integer(2),
839 ];
840 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&serde_cbor::to_vec(
841 &Value::from(cose_mac0),
842 )?)?;
843 assert_eq!(expected_key, raw_key);
844 Ok(())
845 }
846
847 #[test]
848 fn test_extract_payload_from_cose_mac() -> Result<()> {
849 let key_map = Value::Map(BTreeMap::from([(Value::Integer(1), Value::Integer(2))]));
850 let payload = Value::Bytes(serde_cbor::to_vec(&key_map)?);
851 let cose_mac0 =
852 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
853 let extracted_map = RemoteProvisioningService::extract_payload_from_cose_mac(
854 &serde_cbor::to_vec(&cose_mac0)?,
855 )?;
856 assert_eq!(key_map, extracted_map);
857 Ok(())
858 }
859
860 #[test]
861 fn test_extract_payload_from_cose_mac_fails_malformed_payload() -> Result<()> {
862 let payload = Value::Bytes(vec![5; 10]);
863 let cose_mac0 =
864 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
865 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
866 &serde_cbor::to_vec(&cose_mac0)?,
867 );
868 assert!(extracted_payload.is_err());
869 Ok(())
870 }
871
872 #[test]
873 fn test_extract_payload_from_cose_mac_fails_type() -> Result<()> {
874 let payload = Value::Integer(1);
875 let cose_mac0 =
876 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
877 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
878 &serde_cbor::to_vec(&cose_mac0)?,
879 );
880 assert!(extracted_payload.is_err());
881 Ok(())
882 }
883
884 #[test]
885 fn test_extract_payload_from_cose_mac_fails_length() -> Result<()> {
886 let cose_mac0 = Value::Array(vec![Value::Integer(0), Value::Integer(1)]);
887 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
888 &serde_cbor::to_vec(&cose_mac0)?,
889 );
890 assert!(extracted_payload.is_err());
891 Ok(())
892 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800893
894 #[test]
895 #[ignore] // b/215746308
896 fn test_get_attestation_key_no_keys_provisioned() {
897 let mut db = crate::database::tests::new_test_db().unwrap();
898 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
899 mock_rpc.0.lock().unwrap().hw_info.uniqueId = Some(String::from("mallory"));
900
Seth Moore92648b62022-02-02 13:26:18 -0800901 let mut service: RemotelyProvisionedKeyPoolService = Default::default();
Seth Moore7ee79f92021-12-07 11:42:49 -0800902 service
Seth Moore92648b62022-02-02 13:26:18 -0800903 .unique_id_to_sec_level
904 .insert(String::from("mallory"), SecurityLevel::TRUSTED_ENVIRONMENT);
Seth Moore7ee79f92021-12-07 11:42:49 -0800905
906 assert_eq!(
907 service
908 .get_attestation_key(&mut db, 0, "mallory")
909 .unwrap_err()
910 .downcast::<error::Error>()
911 .unwrap(),
912 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
913 );
914 }
915
916 #[test]
917 #[ignore] // b/215746308
918 fn test_get_attestation_key() {
919 let mut db = crate::database::tests::new_test_db().unwrap();
920 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
921 let irpc_id = "paul";
922 let caller_uid = 0;
923
924 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
925 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800926 let mut remote_provisioning: RemoteProvisioningService = Default::default();
927 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
928 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
929 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800930
931 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
932 mock_values.lock().unwrap().private_key = vec![8, 6, 7, 5, 3, 0, 9];
933 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -0800934 remote_provisioning.generate_key_pair(&mut db, true, sec_level).unwrap();
Seth Moore7ee79f92021-12-07 11:42:49 -0800935
936 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
937 mock_values.lock().unwrap().maced_public_key.as_slice(),
938 )
939 .unwrap();
940 let batch_cert = get_fake_cert();
941 let certs = &[5, 6, 7, 8];
Seth Moore92648b62022-02-02 13:26:18 -0800942 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -0800943 .provision_cert_chain(
944 &mut db,
945 public_key.as_slice(),
946 batch_cert.as_slice(),
947 certs,
948 0,
949 sec_level
950 )
951 .is_ok());
952
953 // ensure we got the key we expected
Seth Moore92648b62022-02-02 13:26:18 -0800954 let first_key = key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800955 .get_attestation_key(&mut db, caller_uid, irpc_id)
956 .context("get first key")
957 .unwrap();
958 assert_eq!(first_key.keyBlob, mock_values.lock().unwrap().private_key);
959 assert_eq!(first_key.encodedCertChain, certs);
960
961 // ensure that multiple calls get the same key
962 assert_eq!(
963 first_key,
Seth Moore92648b62022-02-02 13:26:18 -0800964 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800965 .get_attestation_key(&mut db, caller_uid, irpc_id)
966 .context("get second key")
967 .unwrap()
968 );
969
970 // no more keys for new clients
971 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -0800972 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800973 .get_attestation_key(&mut db, caller_uid + 1, irpc_id)
974 .unwrap_err()
975 .downcast::<error::Error>()
976 .unwrap(),
977 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
978 );
979 }
980
981 #[test]
982 #[ignore] // b/215746308
983 fn test_get_attestation_key_gets_different_key_for_different_client() {
984 let mut db = crate::database::tests::new_test_db().unwrap();
985 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
986 let irpc_id = "ringo";
987 let first_caller = 0;
988 let second_caller = first_caller + 1;
989
990 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
991 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800992 let mut remote_provisioning: RemoteProvisioningService = Default::default();
993 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
994 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
995 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800996
997 // generate two distinct keys and provision them with certs
998 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
999 mock_values.lock().unwrap().private_key = vec![3, 1, 4, 1, 5];
1000 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -08001001 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001002 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1003 mock_values.lock().unwrap().maced_public_key.as_slice(),
1004 )
1005 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001006 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001007 .provision_cert_chain(
1008 &mut db,
1009 public_key.as_slice(),
1010 get_fake_cert().as_slice(),
1011 &[1],
1012 0,
1013 sec_level
1014 )
1015 .is_ok());
1016
1017 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1018 mock_values.lock().unwrap().private_key = vec![9, 0, 2, 1, 0];
1019 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x22);
Seth Moore92648b62022-02-02 13:26:18 -08001020 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001021 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1022 mock_values.lock().unwrap().maced_public_key.as_slice(),
1023 )
1024 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001025 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001026 .provision_cert_chain(
1027 &mut db,
1028 public_key.as_slice(),
1029 get_fake_cert().as_slice(),
1030 &[2],
1031 0,
1032 sec_level
1033 )
1034 .is_ok());
1035
1036 // make sure each caller gets a distinct key
1037 assert_ne!(
Seth Moore92648b62022-02-02 13:26:18 -08001038 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001039 .get_attestation_key(&mut db, first_caller, irpc_id)
1040 .context("get first key")
1041 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001042 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001043 .get_attestation_key(&mut db, second_caller, irpc_id)
1044 .context("get second key")
1045 .unwrap()
1046 );
1047
1048 // repeated calls should return the same key for a given caller
1049 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001050 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001051 .get_attestation_key(&mut db, first_caller, irpc_id)
1052 .context("first caller a")
1053 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001054 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001055 .get_attestation_key(&mut db, first_caller, irpc_id)
1056 .context("first caller b")
1057 .unwrap(),
1058 );
1059
1060 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001061 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001062 .get_attestation_key(&mut db, second_caller, irpc_id)
1063 .context("second caller a")
1064 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001065 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001066 .get_attestation_key(&mut db, second_caller, irpc_id)
1067 .context("second caller b")
1068 .unwrap()
1069 );
1070 }
Max Bires48fc2e52021-11-17 10:13:04 -08001071}