blob: ea2698f00727e6b85ddec99c1c56bda0b9faae87 [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 Gunasingheadf66922022-05-10 08:49:53 +0000162 log_rkp_error_stats(MetricsRkpError::FALL_BACK_DURING_HYBRID,
163 &self.security_level);
Max Bires31cdfb82021-07-06 02:59:25 -0700164 Ok(None)
165 }
166 Ok(v) => match v {
Max Bires55620ff2022-02-11 13:34:15 -0800167 Some((guard, cert_chain)) => Ok(Some((
168 guard,
Max Bires31cdfb82021-07-06 02:59:25 -0700169 AttestationKey {
170 keyBlob: cert_chain.private_key.to_vec(),
171 attestKeyParams: vec![],
172 issuerSubjectName: parse_subject_from_certificate(
173 &cert_chain.batch_cert,
174 )
Max Bires97f96812021-02-23 23:44:57 -0800175 .context(concat!(
Max Bires31cdfb82021-07-06 02:59:25 -0700176 "In get_remote_provisioning_key_and_certs: Failed to ",
177 "parse subject."
178 ))?,
179 },
180 Certificate { encodedCertificate: cert_chain.cert_chain },
181 ))),
182 None => Ok(None),
183 },
Max Bires97f96812021-02-23 23:44:57 -0800184 }
185 }
186 }
187}
Max Bires148c08e2020-10-13 13:41:41 -0700188/// Implementation of the IRemoteProvisioning service.
Max Biresb2e1d032021-02-08 21:35:05 -0800189#[derive(Default)]
Max Bires148c08e2020-10-13 13:41:41 -0700190pub struct RemoteProvisioningService {
Janis Danisevskis5f3a0572021-06-18 11:26:42 -0700191 device_by_sec_level: HashMap<SecurityLevel, Strong<dyn IRemotelyProvisionedComponent>>,
Max Biresd2ce46b2021-07-06 02:54:47 -0700192 curve_by_sec_level: HashMap<SecurityLevel, i32>,
Max Bires148c08e2020-10-13 13:41:41 -0700193}
194
195impl RemoteProvisioningService {
Max Biresb2e1d032021-02-08 21:35:05 -0800196 fn get_dev_by_sec_level(
197 &self,
198 sec_level: &SecurityLevel,
Seth Moore7ee79f92021-12-07 11:42:49 -0800199 ) -> Result<&dyn IRemotelyProvisionedComponent> {
Max Biresb2e1d032021-02-08 21:35:05 -0800200 if let Some(dev) = self.device_by_sec_level.get(sec_level) {
Seth Moore7ee79f92021-12-07 11:42:49 -0800201 Ok(dev.as_ref())
Max Biresb2e1d032021-02-08 21:35:05 -0800202 } else {
203 Err(error::Error::sys()).context(concat!(
204 "In get_dev_by_sec_level: Remote instance for requested security level",
205 " not found."
206 ))
207 }
208 }
209
Max Bires148c08e2020-10-13 13:41:41 -0700210 /// Creates a new instance of the remote provisioning service
Stephen Crane221bbb52020-12-16 15:52:10 -0800211 pub fn new_native_binder() -> Result<Strong<dyn IRemoteProvisioning>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800212 let mut result: Self = Default::default();
213 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
214 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
Max Biresd2ce46b2021-07-06 02:54:47 -0700215 result.curve_by_sec_level.insert(
216 SecurityLevel::TRUSTED_ENVIRONMENT,
217 dev.getHardwareInfo()
218 .context("In new_native_binder: Failed to get hardware info for the TEE.")?
219 .supportedEekCurve,
220 );
Max Biresb2e1d032021-02-08 21:35:05 -0800221 result.device_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, dev);
222 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
Max Biresd2ce46b2021-07-06 02:54:47 -0700223 result.curve_by_sec_level.insert(
224 SecurityLevel::STRONGBOX,
225 dev.getHardwareInfo()
226 .context("In new_native_binder: Failed to get hardware info for StrongBox.")?
227 .supportedEekCurve,
228 );
Max Biresb2e1d032021-02-08 21:35:05 -0800229 result.device_by_sec_level.insert(SecurityLevel::STRONGBOX, dev);
230 }
Andrew Walbrande45c8b2021-04-13 14:42:38 +0000231 Ok(BnRemoteProvisioning::new_binder(result, BinderFeatures::default()))
Max Bires148c08e2020-10-13 13:41:41 -0700232 }
233
Max Bires48fc2e52021-11-17 10:13:04 -0800234 fn extract_payload_from_cose_mac(data: &[u8]) -> Result<Value> {
235 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data).context(
236 "In extract_payload_from_cose_mac: COSE_Mac0 returned from IRPC cannot be parsed",
237 )?;
238 if cose_mac0.len() != COSE_MAC0_LEN {
239 return Err(error::Error::sys()).context(format!(
240 "In extract_payload_from_cose_mac: COSE_Mac0 has improper length. \
241 Expected: {}, Actual: {}",
242 COSE_MAC0_LEN,
243 cose_mac0.len(),
244 ));
245 }
246 match &cose_mac0[COSE_MAC0_PAYLOAD] {
247 Value::Bytes(key) => Ok(serde_cbor::from_slice(key)
248 .context("In extract_payload_from_cose_mac: COSE_Mac0 payload is malformed.")?),
249 _ => Err(error::Error::sys()).context(
250 "In extract_payload_from_cose_mac: COSE_Mac0 payload is the wrong type.",
251 )?,
252 }
253 }
254
Max Bires148c08e2020-10-13 13:41:41 -0700255 /// Generates a CBOR blob which will be assembled by the calling code into a larger
256 /// CBOR blob intended for delivery to a provisioning serever. This blob will contain
257 /// `num_csr` certificate signing requests for attestation keys generated in the TEE,
258 /// along with a server provided `eek` and `challenge`. The endpoint encryption key will
259 /// be used to encrypt the sensitive contents being transmitted to the server, and the
260 /// challenge will ensure freshness. A `test_mode` flag will instruct the remote provisioning
261 /// HAL if it is okay to accept EEKs that aren't signed by something that chains back to the
262 /// baked in root of trust in the underlying IRemotelyProvisionedComponent instance.
Max Bires834dd362021-03-23 13:01:57 -0700263 #[allow(clippy::too_many_arguments)]
Max Bires148c08e2020-10-13 13:41:41 -0700264 pub fn generate_csr(
265 &self,
Max Biresb2e1d032021-02-08 21:35:05 -0800266 test_mode: bool,
267 num_csr: i32,
268 eek: &[u8],
269 challenge: &[u8],
270 sec_level: SecurityLevel,
271 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700272 device_info: &mut DeviceInfo,
Max Bires148c08e2020-10-13 13:41:41 -0700273 ) -> Result<Vec<u8>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800274 let dev = self.get_dev_by_sec_level(&sec_level)?;
275 let (_, _, uuid) = get_keymint_device(&sec_level)?;
276 let keys_to_sign = DB.with::<_, Result<Vec<MacedPublicKey>>>(|db| {
277 let mut db = db.borrow_mut();
278 Ok(db
279 .fetch_unsigned_attestation_keys(num_csr, &uuid)?
280 .iter()
281 .map(|key| MacedPublicKey { macedKey: key.to_vec() })
282 .collect())
283 })?;
Max Bires48fc2e52021-11-17 10:13:04 -0800284 let mac = map_rem_prov_error(dev.generateCertificateRequest(
Max Biresb2e1d032021-02-08 21:35:05 -0800285 test_mode,
286 &keys_to_sign,
287 eek,
288 challenge,
Max Bires834dd362021-03-23 13:01:57 -0700289 device_info,
Max Biresb2e1d032021-02-08 21:35:05 -0800290 protected_data,
291 ))
292 .context("In generate_csr: Failed to generate csr")?;
Max Bires48fc2e52021-11-17 10:13:04 -0800293 let mut mac_and_keys: Vec<Value> = vec![Value::from(mac)];
Max Bires97f96812021-02-23 23:44:57 -0800294 for maced_public_key in keys_to_sign {
Max Bires48fc2e52021-11-17 10:13:04 -0800295 mac_and_keys.push(
296 Self::extract_payload_from_cose_mac(&maced_public_key.macedKey)
297 .context("In generate_csr: Failed to get the payload from the COSE_Mac0")?,
298 )
Max Bires97f96812021-02-23 23:44:57 -0800299 }
Max Bires48fc2e52021-11-17 10:13:04 -0800300 let cbor_array: Value = Value::Array(mac_and_keys);
301 serde_cbor::to_vec(&cbor_array)
302 .context("In generate_csr: Failed to serialize the mac and keys array")
Max Bires148c08e2020-10-13 13:41:41 -0700303 }
304
305 /// Provisions a certificate chain for a key whose CSR was included in generate_csr. The
306 /// `public_key` is used to index into the SQL database in order to insert the `certs` blob
307 /// which represents a PEM encoded X.509 certificate chain. The `expiration_date` is provided
308 /// as a convenience from the caller to avoid having to parse the certificates semantically
309 /// here.
310 pub fn provision_cert_chain(
311 &self,
Seth Moore7ee79f92021-12-07 11:42:49 -0800312 db: &mut KeystoreDB,
Max Bires148c08e2020-10-13 13:41:41 -0700313 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800314 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700315 certs: &[u8],
316 expiration_date: i64,
317 sec_level: SecurityLevel,
318 ) -> Result<()> {
Seth Moore7ee79f92021-12-07 11:42:49 -0800319 let (_, _, uuid) = get_keymint_device(&sec_level)?;
320 db.store_signed_attestation_certificate_chain(
321 public_key,
322 batch_cert,
323 certs, /* DER encoded certificate chain */
324 expiration_date,
325 &uuid,
326 )
Max Bires148c08e2020-10-13 13:41:41 -0700327 }
328
Max Bires48fc2e52021-11-17 10:13:04 -0800329 fn parse_cose_mac0_for_coords(data: &[u8]) -> Result<Vec<u8>> {
330 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data).context(
331 "In parse_cose_mac0_for_coords: COSE_Mac0 returned from IRPC cannot be parsed",
332 )?;
333 if cose_mac0.len() != COSE_MAC0_LEN {
334 return Err(error::Error::sys()).context(format!(
335 "In parse_cose_mac0_for_coords: COSE_Mac0 has improper length. \
336 Expected: {}, Actual: {}",
337 COSE_MAC0_LEN,
338 cose_mac0.len(),
339 ));
340 }
341 let cose_key: BTreeMap<Value, Value> = match &cose_mac0[COSE_MAC0_PAYLOAD] {
342 Value::Bytes(key) => serde_cbor::from_slice(key)
343 .context("In parse_cose_mac0_for_coords: COSE_Key is malformed.")?,
344 _ => Err(error::Error::sys())
345 .context("In parse_cose_mac0_for_coords: COSE_Mac0 payload is the wrong type.")?,
346 };
347 if !cose_key.contains_key(&COSE_KEY_XCOORD) || !cose_key.contains_key(&COSE_KEY_YCOORD) {
348 return Err(error::Error::sys()).context(
349 "In parse_cose_mac0_for_coords: \
350 COSE_Key returned from IRPC is lacking required fields",
351 );
352 }
353 let mut raw_key: Vec<u8> = vec![0; 64];
354 match &cose_key[&COSE_KEY_XCOORD] {
355 Value::Bytes(x_coord) if x_coord.len() == 32 => {
356 raw_key[0..32].clone_from_slice(x_coord)
357 }
358 Value::Bytes(x_coord) => {
359 return Err(error::Error::sys()).context(format!(
360 "In parse_cose_mac0_for_coords: COSE_Key X-coordinate is not the right length. \
361 Expected: 32; Actual: {}",
362 x_coord.len()
363 ))
364 }
365 _ => {
366 return Err(error::Error::sys())
367 .context("In parse_cose_mac0_for_coords: COSE_Key X-coordinate is not a bstr")
368 }
369 }
370 match &cose_key[&COSE_KEY_YCOORD] {
371 Value::Bytes(y_coord) if y_coord.len() == 32 => {
372 raw_key[32..64].clone_from_slice(y_coord)
373 }
374 Value::Bytes(y_coord) => {
375 return Err(error::Error::sys()).context(format!(
376 "In parse_cose_mac0_for_coords: COSE_Key Y-coordinate is not the right length. \
377 Expected: 32; Actual: {}",
378 y_coord.len()
379 ))
380 }
381 _ => {
382 return Err(error::Error::sys())
383 .context("In parse_cose_mac0_for_coords: COSE_Key Y-coordinate is not a bstr")
384 }
385 }
386 Ok(raw_key)
387 }
388
Max Bires148c08e2020-10-13 13:41:41 -0700389 /// Submits a request to the Remote Provisioner HAL to generate a signing key pair.
390 /// `is_test_mode` indicates whether or not the returned public key should be marked as being
391 /// for testing in order to differentiate them from private keys. If the call is successful,
392 /// the key pair is then added to the database.
Seth Moore7ee79f92021-12-07 11:42:49 -0800393 pub fn generate_key_pair(
394 &self,
395 db: &mut KeystoreDB,
396 is_test_mode: bool,
397 sec_level: SecurityLevel,
398 ) -> Result<()> {
Max Biresb2e1d032021-02-08 21:35:05 -0800399 let (_, _, uuid) = get_keymint_device(&sec_level)?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800400 let dev = self.get_dev_by_sec_level(&sec_level).context(format!(
401 "In generate_key_pair: Failed to get device for security level {:?}",
402 sec_level
403 ))?;
Max Biresb2e1d032021-02-08 21:35:05 -0800404 let mut maced_key = MacedPublicKey { macedKey: Vec::new() };
405 let priv_key =
406 map_rem_prov_error(dev.generateEcdsaP256KeyPair(is_test_mode, &mut maced_key))
407 .context("In generate_key_pair: Failed to generated ECDSA keypair.")?;
Max Bires48fc2e52021-11-17 10:13:04 -0800408 let raw_key = Self::parse_cose_mac0_for_coords(&maced_key.macedKey)
409 .context("In generate_key_pair: Failed to parse raw key")?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800410 db.create_attestation_key_entry(&maced_key.macedKey, &raw_key, &priv_key, &uuid)
411 .context("In generate_key_pair: Failed to insert attestation key entry")
Max Biresb2e1d032021-02-08 21:35:05 -0800412 }
413
414 /// Checks the security level of each available IRemotelyProvisionedComponent hal and returns
415 /// all levels in an array to the caller.
Max Biresd2ce46b2021-07-06 02:54:47 -0700416 pub fn get_implementation_info(&self) -> Result<Vec<ImplInfo>> {
417 Ok(self
418 .curve_by_sec_level
419 .iter()
420 .map(|(sec_level, curve)| ImplInfo { secLevel: *sec_level, supportedCurve: *curve })
421 .collect())
Max Bires148c08e2020-10-13 13:41:41 -0700422 }
Max Bires60d7ed12021-03-05 15:59:22 -0800423
424 /// Deletes all attestation keys generated by the IRemotelyProvisionedComponent from the device,
425 /// regardless of what state of the attestation key lifecycle they were in.
426 pub fn delete_all_keys(&self) -> Result<i64> {
427 DB.with::<_, Result<i64>>(|db| {
428 let mut db = db.borrow_mut();
Matthew Maurerb77a28d2021-05-07 16:08:20 -0700429 db.delete_all_attestation_keys()
Max Bires60d7ed12021-03-05 15:59:22 -0800430 })
431 }
Max Bires148c08e2020-10-13 13:41:41 -0700432}
433
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000434/// Populates the AttestationPoolStatus parcelable with information about how many
435/// certs will be expiring by the date provided in `expired_by` along with how many
436/// keys have not yet been assigned.
437pub fn get_pool_status(expired_by: i64, sec_level: SecurityLevel) -> Result<AttestationPoolStatus> {
438 let (_, _, uuid) = get_keymint_device(&sec_level)?;
439 DB.with::<_, Result<AttestationPoolStatus>>(|db| {
440 let mut db = db.borrow_mut();
441 // delete_expired_attestation_keys is always safe to call, and will remove anything
442 // older than the date at the time of calling. No work should be done on the
443 // attestation keys unless the pool status is checked first, so this call should be
444 // enough to routinely clean out expired keys.
445 db.delete_expired_attestation_keys()?;
446 db.get_attestation_pool_status(expired_by, &uuid)
447 })
448}
449
Seth Moore7ee79f92021-12-07 11:42:49 -0800450/// Fetches a remote provisioning attestation key and certificate chain inside of the
451/// returned `CertificateChain` struct if one exists for the given caller_uid. If one has not
452/// been assigned, this function will assign it. If there are no signed attestation keys
453/// available to be assigned, it will return the ResponseCode `OUT_OF_KEYS`
454fn get_rem_prov_attest_key(
455 domain: Domain,
456 caller_uid: u32,
457 db: &mut KeystoreDB,
458 km_uuid: &Uuid,
Max Bires55620ff2022-02-11 13:34:15 -0800459) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
Seth Moore7ee79f92021-12-07 11:42:49 -0800460 match domain {
461 Domain::APP => {
462 // Attempt to get an Attestation Key once. If it fails, then the app doesn't
463 // have a valid chain assigned to it. The helper function will return None after
464 // attempting to assign a key. An error will be thrown if the pool is simply out
465 // of usable keys. Then another attempt to fetch the just-assigned key will be
466 // made. If this fails too, something is very wrong.
467 get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid)
468 .context("In get_rem_prov_attest_key: Failed to get a key")?
469 .map_or_else(
470 || get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid),
471 |v| Ok(Some(v)),
472 )
473 .context(concat!(
474 "In get_rem_prov_attest_key: Failed to get a key after",
475 "attempting to assign one."
476 ))?
477 .map_or_else(
478 || {
479 Err(Error::sys()).context(concat!(
480 "In get_rem_prov_attest_key: Attempted to assign a ",
481 "key and failed silently. Something is very wrong."
482 ))
483 },
Max Bires55620ff2022-02-11 13:34:15 -0800484 |(guard, cert_chain)| Ok(Some((guard, cert_chain))),
Seth Moore7ee79f92021-12-07 11:42:49 -0800485 )
486 }
487 _ => Ok(None),
488 }
489}
490
491/// Returns None if an AttestationKey fails to be assigned. Errors if no keys are available.
492fn get_rem_prov_attest_key_helper(
493 domain: Domain,
494 caller_uid: u32,
495 db: &mut KeystoreDB,
496 km_uuid: &Uuid,
Max Bires55620ff2022-02-11 13:34:15 -0800497) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
498 let guard_and_chain = db
Seth Moore7ee79f92021-12-07 11:42:49 -0800499 .retrieve_attestation_key_and_cert_chain(domain, caller_uid as i64, km_uuid)
500 .context("In get_rem_prov_attest_key_helper: Failed to retrieve a key + cert chain")?;
Max Bires55620ff2022-02-11 13:34:15 -0800501 match guard_and_chain {
502 Some((guard, cert_chain)) => Ok(Some((guard, cert_chain))),
Seth Moore7ee79f92021-12-07 11:42:49 -0800503 // Either this app needs to be assigned a key, or the pool is empty. An error will
504 // be thrown if there is no key available to assign. This will indicate that the app
505 // should be nudged to provision more keys so keystore can retry.
506 None => {
507 db.assign_attestation_key(domain, caller_uid as i64, km_uuid)
508 .context("In get_rem_prov_attest_key_helper: Failed to assign a key")?;
509 Ok(None)
510 }
511 }
512}
513
Max Bires148c08e2020-10-13 13:41:41 -0700514impl binder::Interface for RemoteProvisioningService {}
515
516// Implementation of IRemoteProvisioning. See AIDL spec at
517// :aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
518impl IRemoteProvisioning for RemoteProvisioningService {
519 fn getPoolStatus(
520 &self,
521 expired_by: i64,
522 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700523 ) -> binder::Result<AttestationPoolStatus> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000524 let _wp = wd::watch_millis("IRemoteProvisioning::getPoolStatus", 500);
Hasini Gunasinghe8af67ea2021-06-30 17:09:01 +0000525 map_or_log_err(get_pool_status(expired_by, sec_level), Ok)
Max Bires148c08e2020-10-13 13:41:41 -0700526 }
527
528 fn generateCsr(
529 &self,
530 test_mode: bool,
531 num_csr: i32,
532 eek: &[u8],
533 challenge: &[u8],
534 sec_level: SecurityLevel,
Max Biresb2e1d032021-02-08 21:35:05 -0800535 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700536 device_info: &mut DeviceInfo,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700537 ) -> binder::Result<Vec<u8>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000538 let _wp = wd::watch_millis("IRemoteProvisioning::generateCsr", 500);
Max Biresb2e1d032021-02-08 21:35:05 -0800539 map_or_log_err(
Max Bires834dd362021-03-23 13:01:57 -0700540 self.generate_csr(
541 test_mode,
542 num_csr,
543 eek,
544 challenge,
545 sec_level,
546 protected_data,
547 device_info,
548 ),
Max Biresb2e1d032021-02-08 21:35:05 -0800549 Ok,
550 )
Max Bires148c08e2020-10-13 13:41:41 -0700551 }
552
553 fn provisionCertChain(
554 &self,
555 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800556 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700557 certs: &[u8],
558 expiration_date: i64,
559 sec_level: SecurityLevel,
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700560 ) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000561 let _wp = wd::watch_millis("IRemoteProvisioning::provisionCertChain", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800562 DB.with::<_, binder::Result<()>>(|db| {
563 map_or_log_err(
564 self.provision_cert_chain(
565 &mut db.borrow_mut(),
566 public_key,
567 batch_cert,
568 certs,
569 expiration_date,
570 sec_level,
571 ),
572 Ok,
573 )
574 })
Max Bires148c08e2020-10-13 13:41:41 -0700575 }
576
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700577 fn generateKeyPair(&self, is_test_mode: bool, sec_level: SecurityLevel) -> binder::Result<()> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000578 let _wp = wd::watch_millis("IRemoteProvisioning::generateKeyPair", 500);
Seth Moore7ee79f92021-12-07 11:42:49 -0800579 DB.with::<_, binder::Result<()>>(|db| {
580 map_or_log_err(
581 self.generate_key_pair(&mut db.borrow_mut(), is_test_mode, sec_level),
582 Ok,
583 )
584 })
Max Bires148c08e2020-10-13 13:41:41 -0700585 }
Max Biresb2e1d032021-02-08 21:35:05 -0800586
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700587 fn getImplementationInfo(&self) -> binder::Result<Vec<ImplInfo>> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000588 let _wp = wd::watch_millis("IRemoteProvisioning::getSecurityLevels", 500);
Max Biresd2ce46b2021-07-06 02:54:47 -0700589 map_or_log_err(self.get_implementation_info(), Ok)
Max Biresb2e1d032021-02-08 21:35:05 -0800590 }
Max Bires60d7ed12021-03-05 15:59:22 -0800591
Stephen Craneeb3bd5d2021-08-16 16:44:15 -0700592 fn deleteAllKeys(&self) -> binder::Result<i64> {
Hasini Gunasinghe5a893e82021-05-05 14:32:32 +0000593 let _wp = wd::watch_millis("IRemoteProvisioning::deleteAllKeys", 500);
Max Bires60d7ed12021-03-05 15:59:22 -0800594 map_or_log_err(self.delete_all_keys(), Ok)
595 }
Max Bires148c08e2020-10-13 13:41:41 -0700596}
Max Bires48fc2e52021-11-17 10:13:04 -0800597
Seth Moore92648b62022-02-02 13:26:18 -0800598/// Implementation of the IRemotelyProvisionedKeyPool service.
599#[derive(Default)]
600pub struct RemotelyProvisionedKeyPoolService {
601 unique_id_to_sec_level: HashMap<String, SecurityLevel>,
602}
603
604impl RemotelyProvisionedKeyPoolService {
605 /// Fetches a remotely provisioned certificate chain and key for the given client uid that
606 /// was provisioned using the IRemotelyProvisionedComponent with the given id. The same key
607 /// will be returned for a given caller_uid on every request. If there are no attestation keys
608 /// available, `OUT_OF_KEYS` is returned.
609 fn get_attestation_key(
610 &self,
611 db: &mut KeystoreDB,
612 caller_uid: i32,
613 irpc_id: &str,
614 ) -> Result<RemotelyProvisionedKey> {
615 log::info!("get_attestation_key(self, {}, {}", caller_uid, irpc_id);
616
617 let sec_level = self
618 .unique_id_to_sec_level
619 .get(irpc_id)
620 .ok_or(Error::Rc(ResponseCode::INVALID_ARGUMENT))
621 .context(format!("In get_attestation_key: unknown irpc id '{}'", irpc_id))?;
622 let (_, _, km_uuid) = get_keymint_device(sec_level)?;
623
Max Bires55620ff2022-02-11 13:34:15 -0800624 let guard_and_cert_chain =
625 get_rem_prov_attest_key(Domain::APP, caller_uid as u32, db, &km_uuid)
626 .context("In get_attestation_key")?;
627 match guard_and_cert_chain {
628 Some((_, chain)) => Ok(RemotelyProvisionedKey {
Seth Moore92648b62022-02-02 13:26:18 -0800629 keyBlob: chain.private_key.to_vec(),
630 encodedCertChain: chain.cert_chain,
631 }),
632 // It should be impossible to get `None`, but handle it just in case as a
633 // precaution against future behavioral changes in `get_rem_prov_attest_key`.
634 None => Err(error::Error::Rc(ResponseCode::OUT_OF_KEYS))
635 .context("In get_attestation_key: No available attestation keys"),
636 }
637 }
638
639 /// Creates a new instance of the remotely provisioned key pool service, used for fetching
640 /// remotely provisioned attestation keys.
641 pub fn new_native_binder() -> Result<Strong<dyn IRemotelyProvisionedKeyPool>> {
642 let mut result: Self = Default::default();
643
644 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
645 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
646 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
647 result.unique_id_to_sec_level.insert(id, SecurityLevel::TRUSTED_ENVIRONMENT);
648 }
649
650 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
651 if let Some(id) = dev.getHardwareInfo()?.uniqueId {
652 if result.unique_id_to_sec_level.contains_key(&id) {
653 anyhow::bail!("In new_native_binder: duplicate irpc id found: '{}'", id)
654 }
655 result.unique_id_to_sec_level.insert(id, SecurityLevel::STRONGBOX);
656 }
657 }
658
659 // If none of the remotely provisioned components have unique ids, then we shouldn't
660 // bother publishing the service, as it's impossible to match keys with their backends.
661 if result.unique_id_to_sec_level.is_empty() {
662 anyhow::bail!(
663 "In new_native_binder: No remotely provisioned components have unique ids"
664 )
665 }
666
667 Ok(BnRemotelyProvisionedKeyPool::new_binder(
668 result,
669 BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
670 ))
671 }
672}
673
674impl binder::Interface for RemotelyProvisionedKeyPoolService {}
675
Seth Moore7ee79f92021-12-07 11:42:49 -0800676// Implementation of IRemotelyProvisionedKeyPool. See AIDL spec at
677// :aidl/android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.aidl
Seth Moore92648b62022-02-02 13:26:18 -0800678impl IRemotelyProvisionedKeyPool for RemotelyProvisionedKeyPoolService {
Seth Moore7ee79f92021-12-07 11:42:49 -0800679 fn getAttestationKey(
680 &self,
681 caller_uid: i32,
682 irpc_id: &str,
683 ) -> binder::Result<RemotelyProvisionedKey> {
684 let _wp = wd::watch_millis("IRemotelyProvisionedKeyPool::getAttestationKey", 500);
685 map_or_log_err(check_keystore_permission(KeystorePerm::GetAttestationKey), Ok)?;
686 DB.with::<_, binder::Result<RemotelyProvisionedKey>>(|db| {
687 map_or_log_err(self.get_attestation_key(&mut db.borrow_mut(), caller_uid, irpc_id), Ok)
688 })
689 }
690}
691
Max Bires48fc2e52021-11-17 10:13:04 -0800692#[cfg(test)]
693mod tests {
694 use super::*;
695 use serde_cbor::Value;
696 use std::collections::BTreeMap;
Seth Moore7ee79f92021-12-07 11:42:49 -0800697 use std::sync::{Arc, Mutex};
698 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
699 RpcHardwareInfo::RpcHardwareInfo,
700 };
701
702 #[derive(Default)]
703 struct MockRemotelyProvisionedComponentValues {
704 hw_info: RpcHardwareInfo,
705 private_key: Vec<u8>,
706 maced_public_key: Vec<u8>,
707 }
708
709 // binder::Interface requires the Send trait, so we have to use a Mutex even though the test
710 // is single threaded.
711 #[derive(Default)]
712 struct MockRemotelyProvisionedComponent(Arc<Mutex<MockRemotelyProvisionedComponentValues>>);
713
714 impl binder::Interface for MockRemotelyProvisionedComponent {}
715
716 impl IRemotelyProvisionedComponent for MockRemotelyProvisionedComponent {
717 fn getHardwareInfo(&self) -> binder::Result<RpcHardwareInfo> {
718 Ok(self.0.lock().unwrap().hw_info.clone())
719 }
720
721 fn generateEcdsaP256KeyPair(
722 &self,
723 test_mode: bool,
724 maced_public_key: &mut MacedPublicKey,
725 ) -> binder::Result<Vec<u8>> {
726 assert!(test_mode);
727 maced_public_key.macedKey = self.0.lock().unwrap().maced_public_key.clone();
728 Ok(self.0.lock().unwrap().private_key.clone())
729 }
730
731 fn generateCertificateRequest(
732 &self,
733 _test_mode: bool,
734 _keys_to_sign: &[MacedPublicKey],
735 _eek: &[u8],
736 _challenge: &[u8],
737 _device_info: &mut DeviceInfo,
738 _protected_data: &mut ProtectedData,
739 ) -> binder::Result<Vec<u8>> {
740 Err(binder::StatusCode::INVALID_OPERATION.into())
741 }
742 }
743
744 // Hard coded cert that can be parsed -- the content doesn't matter for testing, only that it's valid.
745 fn get_fake_cert() -> Vec<u8> {
746 vec![
747 0x30, 0x82, 0x01, 0xbb, 0x30, 0x82, 0x01, 0x61, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
748 0x14, 0x3a, 0xd5, 0x67, 0xce, 0xfe, 0x93, 0xe1, 0xea, 0xb7, 0xe4, 0xbf, 0x64, 0x19,
749 0xa4, 0x11, 0xe1, 0x87, 0x40, 0x20, 0x37, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
750 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
751 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
752 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
753 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
754 0x6c, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x30, 0x32, 0x32,
755 0x30, 0x38, 0x35, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x34, 0x32, 0x36, 0x32,
756 0x32, 0x30, 0x38, 0x35, 0x32, 0x5a, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
757 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
758 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
759 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f,
760 0x67, 0x6c, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
761 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
762 0x00, 0x04, 0x1e, 0xac, 0x0c, 0xe0, 0x0d, 0xc5, 0x25, 0x84, 0x1b, 0xd2, 0x77, 0x2d,
763 0xe7, 0xba, 0xf1, 0xde, 0xa7, 0xf6, 0x39, 0x7f, 0x38, 0x91, 0xbf, 0xa4, 0x58, 0xf5,
764 0x62, 0x6b, 0xce, 0x06, 0xcf, 0xb9, 0x73, 0x91, 0x0d, 0x8a, 0x60, 0xa0, 0xc6, 0xa2,
765 0x22, 0xe6, 0x51, 0x2e, 0x58, 0xd6, 0x43, 0x02, 0x80, 0x43, 0x44, 0x29, 0x38, 0x9a,
766 0x99, 0xf3, 0xa4, 0xdd, 0xd0, 0xb4, 0x6f, 0x8b, 0x44, 0x2d, 0xa3, 0x53, 0x30, 0x51,
767 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdb, 0x13, 0x68,
768 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe, 0x42, 0x3c, 0xd9, 0x3f, 0x1a,
769 0x33, 0xe9, 0xaa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
770 0x80, 0x14, 0xdb, 0x13, 0x68, 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe,
771 0x42, 0x3c, 0xd9, 0x3f, 0x1a, 0x33, 0xe9, 0xaa, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
772 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06,
773 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
774 0x02, 0x20, 0x10, 0xdf, 0x40, 0xc3, 0x20, 0x54, 0x36, 0xb5, 0xc9, 0x3c, 0x70, 0xe3,
775 0x55, 0x37, 0xd2, 0x04, 0x51, 0xeb, 0x0f, 0x18, 0x83, 0xd0, 0x58, 0xa1, 0x08, 0x77,
776 0x8d, 0x4d, 0xa4, 0x20, 0xee, 0x33, 0x02, 0x21, 0x00, 0x8d, 0xe3, 0xa6, 0x6c, 0x0d,
777 0x86, 0x25, 0xdc, 0x59, 0x0d, 0x21, 0x43, 0x22, 0x3a, 0xb9, 0xa1, 0x73, 0x28, 0xc9,
778 0x16, 0x9e, 0x91, 0x15, 0xc4, 0xc3, 0xd7, 0xeb, 0xe5, 0xce, 0xdc, 0x1c, 0x1b,
779 ]
780 }
781
782 // Generate a fake COSE_Mac0 with a key that's just `byte` repeated
783 fn generate_maced_pubkey(byte: u8) -> Vec<u8> {
784 vec![
785 0x84, 0x43, 0xA1, 0x01, 0x05, 0xA0, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20,
786 0x01, 0x21, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
787 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
788 byte, byte, byte, byte, byte, byte, byte, byte, 0x22, 0x58, 0x20, byte, byte, byte,
789 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
790 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
791 byte, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
792 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
793 byte, byte, byte, byte, byte, byte, byte,
794 ]
795 }
Max Bires48fc2e52021-11-17 10:13:04 -0800796
797 #[test]
798 fn test_parse_cose_mac0_for_coords_raw_bytes() -> Result<()> {
799 let cose_mac0: Vec<u8> = vec![
800 0x84, 0x01, 0x02, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
801 0x20, 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9,
802 0x21, 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C,
803 0x43, 0x22, 0xC8, 0xEE, 0x03, 0x22, 0x58, 0x20, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95,
804 0x90, 0xA7, 0x5C, 0x5A, 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A,
805 0xA3, 0xB3, 0x1A, 0xB4, 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC, 0x03,
806 ];
807 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&cose_mac0)?;
808 assert_eq!(
809 raw_key,
810 vec![
811 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9, 0x21,
812 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C, 0x43,
813 0x22, 0xC8, 0xEE, 0x03, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95, 0x90, 0xA7, 0x5C, 0x5A,
814 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A, 0xA3, 0xB3, 0x1A, 0xB4,
815 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC,
816 ]
817 );
818 Ok(())
819 }
820
821 #[test]
822 fn test_parse_cose_mac0_for_coords_constructed_mac() -> Result<()> {
823 let x_coord: Vec<u8> = vec![0; 32];
824 let y_coord: Vec<u8> = vec![1; 32];
825 let mut expected_key: Vec<u8> = Vec::new();
826 expected_key.extend(&x_coord);
827 expected_key.extend(&y_coord);
828 let key_map: BTreeMap<Value, Value> = BTreeMap::from([
829 (Value::Integer(1), Value::Integer(2)),
830 (Value::Integer(3), Value::Integer(-7)),
831 (Value::Integer(-1), Value::Integer(1)),
832 (Value::Integer(-2), Value::Bytes(x_coord)),
833 (Value::Integer(-3), Value::Bytes(y_coord)),
834 ]);
835 let cose_mac0: Vec<Value> = vec![
836 Value::Integer(0),
837 Value::Integer(1),
838 Value::from(serde_cbor::to_vec(&key_map)?),
839 Value::Integer(2),
840 ];
841 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&serde_cbor::to_vec(
842 &Value::from(cose_mac0),
843 )?)?;
844 assert_eq!(expected_key, raw_key);
845 Ok(())
846 }
847
848 #[test]
849 fn test_extract_payload_from_cose_mac() -> Result<()> {
850 let key_map = Value::Map(BTreeMap::from([(Value::Integer(1), Value::Integer(2))]));
851 let payload = Value::Bytes(serde_cbor::to_vec(&key_map)?);
852 let cose_mac0 =
853 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
854 let extracted_map = RemoteProvisioningService::extract_payload_from_cose_mac(
855 &serde_cbor::to_vec(&cose_mac0)?,
856 )?;
857 assert_eq!(key_map, extracted_map);
858 Ok(())
859 }
860
861 #[test]
862 fn test_extract_payload_from_cose_mac_fails_malformed_payload() -> Result<()> {
863 let payload = Value::Bytes(vec![5; 10]);
864 let cose_mac0 =
865 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
866 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
867 &serde_cbor::to_vec(&cose_mac0)?,
868 );
869 assert!(extracted_payload.is_err());
870 Ok(())
871 }
872
873 #[test]
874 fn test_extract_payload_from_cose_mac_fails_type() -> Result<()> {
875 let payload = Value::Integer(1);
876 let cose_mac0 =
877 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
878 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
879 &serde_cbor::to_vec(&cose_mac0)?,
880 );
881 assert!(extracted_payload.is_err());
882 Ok(())
883 }
884
885 #[test]
886 fn test_extract_payload_from_cose_mac_fails_length() -> Result<()> {
887 let cose_mac0 = Value::Array(vec![Value::Integer(0), Value::Integer(1)]);
888 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
889 &serde_cbor::to_vec(&cose_mac0)?,
890 );
891 assert!(extracted_payload.is_err());
892 Ok(())
893 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800894
895 #[test]
896 #[ignore] // b/215746308
897 fn test_get_attestation_key_no_keys_provisioned() {
898 let mut db = crate::database::tests::new_test_db().unwrap();
899 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
900 mock_rpc.0.lock().unwrap().hw_info.uniqueId = Some(String::from("mallory"));
901
Seth Moore92648b62022-02-02 13:26:18 -0800902 let mut service: RemotelyProvisionedKeyPoolService = Default::default();
Seth Moore7ee79f92021-12-07 11:42:49 -0800903 service
Seth Moore92648b62022-02-02 13:26:18 -0800904 .unique_id_to_sec_level
905 .insert(String::from("mallory"), SecurityLevel::TRUSTED_ENVIRONMENT);
Seth Moore7ee79f92021-12-07 11:42:49 -0800906
907 assert_eq!(
908 service
909 .get_attestation_key(&mut db, 0, "mallory")
910 .unwrap_err()
911 .downcast::<error::Error>()
912 .unwrap(),
913 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
914 );
915 }
916
917 #[test]
918 #[ignore] // b/215746308
919 fn test_get_attestation_key() {
920 let mut db = crate::database::tests::new_test_db().unwrap();
921 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
922 let irpc_id = "paul";
923 let caller_uid = 0;
924
925 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
926 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800927 let mut remote_provisioning: RemoteProvisioningService = Default::default();
928 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
929 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
930 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800931
932 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
933 mock_values.lock().unwrap().private_key = vec![8, 6, 7, 5, 3, 0, 9];
934 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -0800935 remote_provisioning.generate_key_pair(&mut db, true, sec_level).unwrap();
Seth Moore7ee79f92021-12-07 11:42:49 -0800936
937 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
938 mock_values.lock().unwrap().maced_public_key.as_slice(),
939 )
940 .unwrap();
941 let batch_cert = get_fake_cert();
942 let certs = &[5, 6, 7, 8];
Seth Moore92648b62022-02-02 13:26:18 -0800943 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -0800944 .provision_cert_chain(
945 &mut db,
946 public_key.as_slice(),
947 batch_cert.as_slice(),
948 certs,
949 0,
950 sec_level
951 )
952 .is_ok());
953
954 // ensure we got the key we expected
Seth Moore92648b62022-02-02 13:26:18 -0800955 let first_key = key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800956 .get_attestation_key(&mut db, caller_uid, irpc_id)
957 .context("get first key")
958 .unwrap();
959 assert_eq!(first_key.keyBlob, mock_values.lock().unwrap().private_key);
960 assert_eq!(first_key.encodedCertChain, certs);
961
962 // ensure that multiple calls get the same key
963 assert_eq!(
964 first_key,
Seth Moore92648b62022-02-02 13:26:18 -0800965 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800966 .get_attestation_key(&mut db, caller_uid, irpc_id)
967 .context("get second key")
968 .unwrap()
969 );
970
971 // no more keys for new clients
972 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -0800973 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800974 .get_attestation_key(&mut db, caller_uid + 1, irpc_id)
975 .unwrap_err()
976 .downcast::<error::Error>()
977 .unwrap(),
978 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
979 );
980 }
981
982 #[test]
983 #[ignore] // b/215746308
984 fn test_get_attestation_key_gets_different_key_for_different_client() {
985 let mut db = crate::database::tests::new_test_db().unwrap();
986 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
987 let irpc_id = "ringo";
988 let first_caller = 0;
989 let second_caller = first_caller + 1;
990
991 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
992 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800993 let mut remote_provisioning: RemoteProvisioningService = Default::default();
994 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
995 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
996 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800997
998 // generate two distinct keys and provision them with certs
999 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1000 mock_values.lock().unwrap().private_key = vec![3, 1, 4, 1, 5];
1001 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -08001002 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001003 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1004 mock_values.lock().unwrap().maced_public_key.as_slice(),
1005 )
1006 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001007 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001008 .provision_cert_chain(
1009 &mut db,
1010 public_key.as_slice(),
1011 get_fake_cert().as_slice(),
1012 &[1],
1013 0,
1014 sec_level
1015 )
1016 .is_ok());
1017
1018 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1019 mock_values.lock().unwrap().private_key = vec![9, 0, 2, 1, 0];
1020 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x22);
Seth Moore92648b62022-02-02 13:26:18 -08001021 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001022 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1023 mock_values.lock().unwrap().maced_public_key.as_slice(),
1024 )
1025 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001026 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001027 .provision_cert_chain(
1028 &mut db,
1029 public_key.as_slice(),
1030 get_fake_cert().as_slice(),
1031 &[2],
1032 0,
1033 sec_level
1034 )
1035 .is_ok());
1036
1037 // make sure each caller gets a distinct key
1038 assert_ne!(
Seth Moore92648b62022-02-02 13:26:18 -08001039 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001040 .get_attestation_key(&mut db, first_caller, irpc_id)
1041 .context("get first key")
1042 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001043 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001044 .get_attestation_key(&mut db, second_caller, irpc_id)
1045 .context("get second key")
1046 .unwrap()
1047 );
1048
1049 // repeated calls should return the same key for a given caller
1050 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001051 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001052 .get_attestation_key(&mut db, first_caller, irpc_id)
1053 .context("first caller a")
1054 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001055 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001056 .get_attestation_key(&mut db, first_caller, irpc_id)
1057 .context("first caller b")
1058 .unwrap(),
1059 );
1060
1061 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001062 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001063 .get_attestation_key(&mut db, second_caller, irpc_id)
1064 .context("second caller a")
1065 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001066 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001067 .get_attestation_key(&mut db, second_caller, irpc_id)
1068 .context("second caller b")
1069 .unwrap()
1070 );
1071 }
Max Bires48fc2e52021-11-17 10:13:04 -08001072}