blob: fec1b92b6ae69c2700db42a734fe48ac7982e8af [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,
Seth Moorecd6e9182022-11-04 17:39:05 +000026 KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel,
Max Bires834dd362021-03-23 13:01:57 -070027 Tag::Tag,
Max Biresb2e1d032021-02-08 21:35:05 -080028};
Seth Moorecd6e9182022-11-04 17:39:05 +000029use android_hardware_security_rkp::aidl::android::hardware::security::keymint::{
30 DeviceInfo::DeviceInfo, IRemotelyProvisionedComponent::IRemotelyProvisionedComponent,
31 MacedPublicKey::MacedPublicKey, ProtectedData::ProtectedData,
32};
Max Bires148c08e2020-10-13 13:41:41 -070033use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{
34 AttestationPoolStatus::AttestationPoolStatus, IRemoteProvisioning::BnRemoteProvisioning,
Seth Moore7ee79f92021-12-07 11:42:49 -080035 IRemoteProvisioning::IRemoteProvisioning,
Seth Moore92648b62022-02-02 13:26:18 -080036 IRemotelyProvisionedKeyPool::BnRemotelyProvisionedKeyPool,
Seth Moore7ee79f92021-12-07 11:42:49 -080037 IRemotelyProvisionedKeyPool::IRemotelyProvisionedKeyPool, ImplInfo::ImplInfo,
38 RemotelyProvisionedKey::RemotelyProvisionedKey,
Max Bires148c08e2020-10-13 13:41:41 -070039};
Andrew Walbrande45c8b2021-04-13 14:42:38 +000040use android_security_remoteprovisioning::binder::{BinderFeatures, Strong};
Max Bires97f96812021-02-23 23:44:57 -080041use android_system_keystore2::aidl::android::system::keystore2::{
Seth Moore7ee79f92021-12-07 11:42:49 -080042 Domain::Domain, KeyDescriptor::KeyDescriptor, ResponseCode::ResponseCode,
Max Bires97f96812021-02-23 23:44:57 -080043};
Max Biresb2e1d032021-02-08 21:35:05 -080044use anyhow::{Context, Result};
Max Bires97f96812021-02-23 23:44:57 -080045use keystore2_crypto::parse_subject_from_certificate;
Max Bires48fc2e52021-11-17 10:13:04 -080046use serde_cbor::Value;
47use std::collections::BTreeMap;
Max Bires97f96812021-02-23 23:44:57 -080048use std::sync::atomic::{AtomicBool, Ordering};
Max Bires148c08e2020-10-13 13:41:41 -070049
Max Bires55620ff2022-02-11 13:34:15 -080050use crate::database::{CertificateChain, KeyIdGuard, KeystoreDB, Uuid};
Max Bires97f96812021-02-23 23:44:57 -080051use crate::error::{self, map_or_log_err, map_rem_prov_error, Error};
Max Biresb2e1d032021-02-08 21:35:05 -080052use crate::globals::{get_keymint_device, get_remotely_provisioned_component, DB};
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +000053use crate::ks_err;
Hasini Gunasinghe8a1a2242021-08-02 22:28:39 +000054use crate::metrics_store::log_rkp_error_stats;
Seth Moore7ee79f92021-12-07 11:42:49 -080055use crate::permission::KeystorePerm;
56use crate::utils::{check_keystore_permission, watchdog as wd};
Hasini Gunasinghe8a1a2242021-08-02 22:28:39 +000057use android_security_metrics::aidl::android::security::metrics::RkpError::RkpError as MetricsRkpError;
Max Bires148c08e2020-10-13 13:41:41 -070058
Max Bires97f96812021-02-23 23:44:57 -080059/// Contains helper functions to check if remote provisioning is enabled on the system and, if so,
60/// to assign and retrieve attestation keys and certificate chains.
61#[derive(Default)]
62pub struct RemProvState {
63 security_level: SecurityLevel,
64 km_uuid: Uuid,
65 is_hal_present: AtomicBool,
66}
67
Max Bires48fc2e52021-11-17 10:13:04 -080068static COSE_KEY_XCOORD: Value = Value::Integer(-2);
69static COSE_KEY_YCOORD: Value = Value::Integer(-3);
70static COSE_MAC0_LEN: usize = 4;
71static COSE_MAC0_PAYLOAD: usize = 2;
72
Max Bires97f96812021-02-23 23:44:57 -080073impl RemProvState {
74 /// Creates a RemProvState struct.
75 pub fn new(security_level: SecurityLevel, km_uuid: Uuid) -> Self {
Seth Mooredfdcb872022-04-20 14:33:19 -070076 Self { security_level, km_uuid, is_hal_present: AtomicBool::new(true) }
Max Bires97f96812021-02-23 23:44:57 -080077 }
78
Max Bires55620ff2022-02-11 13:34:15 -080079 /// Returns the uuid for the KM instance attached to this RemProvState struct.
80 pub fn get_uuid(&self) -> Uuid {
81 self.km_uuid
82 }
83
Seth Mooredfdcb872022-04-20 14:33:19 -070084 fn is_rkp_only(&self) -> bool {
Max Bires65207b52022-03-29 23:58:08 -070085 let default_value = false;
86
Seth Mooredfdcb872022-04-20 14:33:19 -070087 let property_name = match self.security_level {
88 SecurityLevel::STRONGBOX => "remote_provisioning.strongbox.rkp_only",
89 SecurityLevel::TRUSTED_ENVIRONMENT => "remote_provisioning.tee.rkp_only",
Max Bires65207b52022-03-29 23:58:08 -070090 _ => return default_value,
91 };
92
93 rustutils::system_properties::read_bool(property_name, default_value)
94 .unwrap_or(default_value)
95 }
96
Max Bires97f96812021-02-23 23:44:57 -080097 /// Checks if remote provisioning is enabled and partially caches the result. On a hybrid system
98 /// remote provisioning can flip from being disabled to enabled depending on responses from the
99 /// server, so unfortunately caching the presence or absence of the HAL is not enough to fully
100 /// make decisions about the state of remote provisioning during runtime.
101 fn check_rem_prov_enabled(&self, db: &mut KeystoreDB) -> Result<bool> {
Seth Mooredfdcb872022-04-20 14:33:19 -0700102 if self.is_rkp_only() {
Seth Moore562aebb2022-04-18 17:03:27 -0700103 return Ok(true);
104 }
Max Bires97f96812021-02-23 23:44:57 -0800105 if !self.is_hal_present.load(Ordering::Relaxed)
106 || get_remotely_provisioned_component(&self.security_level).is_err()
107 {
108 self.is_hal_present.store(false, Ordering::Relaxed);
109 return Ok(false);
110 }
111 // To check if remote provisioning is enabled on a system that supports both remote
112 // provisioning and factory provisioned keys, we only need to check if there are any
113 // keys at all generated to indicate if the app has gotten the signal to begin filling
114 // the key pool from the server.
115 let pool_status = db
116 .get_attestation_pool_status(0 /* date */, &self.km_uuid)
117 .context("In check_rem_prov_enabled: failed to get attestation pool status.")?;
118 Ok(pool_status.total != 0)
119 }
120
Max Bires97f96812021-02-23 23:44:57 -0800121 fn is_asymmetric_key(&self, params: &[KeyParameter]) -> bool {
122 params.iter().any(|kp| {
123 matches!(
124 kp,
125 KeyParameter {
126 tag: Tag::ALGORITHM,
127 value: KeyParameterValue::Algorithm(Algorithm::RSA)
128 } | KeyParameter {
129 tag: Tag::ALGORITHM,
130 value: KeyParameterValue::Algorithm(Algorithm::EC)
131 }
132 )
133 })
134 }
135
136 /// Checks to see (1) if the key in question should be attested to based on the algorithm and
137 /// (2) if remote provisioning is present and enabled on the system. If these conditions are
138 /// met, it makes an attempt to fetch the attestation key assigned to the `caller_uid`.
139 ///
140 /// It returns the ResponseCode `OUT_OF_KEYS` if there is not one key currently assigned to the
141 /// `caller_uid` and there are none available to assign.
Janis Danisevskis3541f3e2021-03-20 14:18:52 -0700142 pub fn get_remotely_provisioned_attestation_key_and_certs(
Max Bires97f96812021-02-23 23:44:57 -0800143 &self,
144 key: &KeyDescriptor,
145 caller_uid: u32,
146 params: &[KeyParameter],
147 db: &mut KeystoreDB,
Max Bires55620ff2022-02-11 13:34:15 -0800148 ) -> Result<Option<(KeyIdGuard, AttestationKey, Certificate)>> {
Max Bires97f96812021-02-23 23:44:57 -0800149 if !self.is_asymmetric_key(params) || !self.check_rem_prov_enabled(db)? {
150 // There is no remote provisioning component for this security level on the
151 // device. Return None so the underlying KM instance knows to use its
152 // factory provisioned key instead. Alternatively, it's not an asymmetric key
153 // and therefore will not be attested.
Janis Danisevskis3541f3e2021-03-20 14:18:52 -0700154 Ok(None)
Max Bires97f96812021-02-23 23:44:57 -0800155 } else {
Seth Moore7ee79f92021-12-07 11:42:49 -0800156 match get_rem_prov_attest_key(key.domain, caller_uid, db, &self.km_uuid) {
Max Bires31cdfb82021-07-06 02:59:25 -0700157 Err(e) => {
Seth Mooredfdcb872022-04-20 14:33:19 -0700158 if self.is_rkp_only() {
Shaquille Johnson32bd2672022-10-21 13:18:56 +0100159 log::error!("Error occurred: {:?}", e);
Max Bires65207b52022-03-29 23:58:08 -0700160 return Err(e);
161 }
Shaquille Johnson32bd2672022-10-21 13:18:56 +0100162 log::warn!("Error occurred: {:?}", e);
Shaquille Johnsonbcab6012022-09-02 11:16:24 +0000163 log_rkp_error_stats(
164 MetricsRkpError::FALL_BACK_DURING_HYBRID,
165 &self.security_level,
166 );
Max Bires31cdfb82021-07-06 02:59:25 -0700167 Ok(None)
168 }
169 Ok(v) => match v {
Max Bires55620ff2022-02-11 13:34:15 -0800170 Some((guard, cert_chain)) => Ok(Some((
171 guard,
Max Bires31cdfb82021-07-06 02:59:25 -0700172 AttestationKey {
173 keyBlob: cert_chain.private_key.to_vec(),
174 attestKeyParams: vec![],
175 issuerSubjectName: parse_subject_from_certificate(
176 &cert_chain.batch_cert,
177 )
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000178 .context(ks_err!("Failed to parse subject."))?,
Max Bires31cdfb82021-07-06 02:59:25 -0700179 },
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 {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000203 Err(error::Error::sys()).context(ks_err!(
204 "Remote instance for requested security level \
205 not found.",
Max Biresb2e1d032021-02-08 21:35:05 -0800206 ))
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)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000214 .context(ks_err!("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()
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000218 .context(ks_err!("Failed to get hardware info for the TEE."))?
Max Biresd2ce46b2021-07-06 02:54:47 -0700219 .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()
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000226 .context(ks_err!("Failed to get hardware info for StrongBox."))?
Max Biresd2ce46b2021-07-06 02:54:47 -0700227 .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> {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000235 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data)
236 .context(ks_err!("COSE_Mac0 returned from IRPC cannot be parsed"))?;
Max Bires48fc2e52021-11-17 10:13:04 -0800237 if cose_mac0.len() != COSE_MAC0_LEN {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000238 return Err(error::Error::sys()).context(ks_err!(
239 "COSE_Mac0 has improper length. \
Max Bires48fc2e52021-11-17 10:13:04 -0800240 Expected: {}, Actual: {}",
241 COSE_MAC0_LEN,
242 cose_mac0.len(),
243 ));
244 }
245 match &cose_mac0[COSE_MAC0_PAYLOAD] {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000246 Value::Bytes(key) => {
247 Ok(serde_cbor::from_slice(key)
248 .context(ks_err!("COSE_Mac0 payload is malformed."))?)
249 }
250 _ => {
251 Err(error::Error::sys()).context(ks_err!("COSE_Mac0 payload is the wrong type."))?
252 }
Max Bires48fc2e52021-11-17 10:13:04 -0800253 }
254 }
255
Max Bires148c08e2020-10-13 13:41:41 -0700256 /// Generates a CBOR blob which will be assembled by the calling code into a larger
257 /// CBOR blob intended for delivery to a provisioning serever. This blob will contain
258 /// `num_csr` certificate signing requests for attestation keys generated in the TEE,
259 /// along with a server provided `eek` and `challenge`. The endpoint encryption key will
260 /// be used to encrypt the sensitive contents being transmitted to the server, and the
261 /// challenge will ensure freshness. A `test_mode` flag will instruct the remote provisioning
262 /// HAL if it is okay to accept EEKs that aren't signed by something that chains back to the
263 /// baked in root of trust in the underlying IRemotelyProvisionedComponent instance.
Max Bires834dd362021-03-23 13:01:57 -0700264 #[allow(clippy::too_many_arguments)]
Max Bires148c08e2020-10-13 13:41:41 -0700265 pub fn generate_csr(
266 &self,
Max Biresb2e1d032021-02-08 21:35:05 -0800267 test_mode: bool,
268 num_csr: i32,
269 eek: &[u8],
270 challenge: &[u8],
271 sec_level: SecurityLevel,
272 protected_data: &mut ProtectedData,
Max Bires834dd362021-03-23 13:01:57 -0700273 device_info: &mut DeviceInfo,
Max Bires148c08e2020-10-13 13:41:41 -0700274 ) -> Result<Vec<u8>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800275 let dev = self.get_dev_by_sec_level(&sec_level)?;
276 let (_, _, uuid) = get_keymint_device(&sec_level)?;
277 let keys_to_sign = DB.with::<_, Result<Vec<MacedPublicKey>>>(|db| {
278 let mut db = db.borrow_mut();
279 Ok(db
280 .fetch_unsigned_attestation_keys(num_csr, &uuid)?
281 .iter()
282 .map(|key| MacedPublicKey { macedKey: key.to_vec() })
283 .collect())
284 })?;
Max Bires48fc2e52021-11-17 10:13:04 -0800285 let mac = map_rem_prov_error(dev.generateCertificateRequest(
Max Biresb2e1d032021-02-08 21:35:05 -0800286 test_mode,
287 &keys_to_sign,
288 eek,
289 challenge,
Max Bires834dd362021-03-23 13:01:57 -0700290 device_info,
Max Biresb2e1d032021-02-08 21:35:05 -0800291 protected_data,
292 ))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000293 .context(ks_err!("Failed to generate csr"))?;
Max Bires48fc2e52021-11-17 10:13:04 -0800294 let mut mac_and_keys: Vec<Value> = vec![Value::from(mac)];
Max Bires97f96812021-02-23 23:44:57 -0800295 for maced_public_key in keys_to_sign {
Max Bires48fc2e52021-11-17 10:13:04 -0800296 mac_and_keys.push(
297 Self::extract_payload_from_cose_mac(&maced_public_key.macedKey)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000298 .context(ks_err!("Failed to get the payload from the COSE_Mac0"))?,
Max Bires48fc2e52021-11-17 10:13:04 -0800299 )
Max Bires97f96812021-02-23 23:44:57 -0800300 }
Max Bires48fc2e52021-11-17 10:13:04 -0800301 let cbor_array: Value = Value::Array(mac_and_keys);
302 serde_cbor::to_vec(&cbor_array)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000303 .context(ks_err!("Failed to serialize the mac and keys array"))
Max Bires148c08e2020-10-13 13:41:41 -0700304 }
305
306 /// Provisions a certificate chain for a key whose CSR was included in generate_csr. The
307 /// `public_key` is used to index into the SQL database in order to insert the `certs` blob
308 /// which represents a PEM encoded X.509 certificate chain. The `expiration_date` is provided
309 /// as a convenience from the caller to avoid having to parse the certificates semantically
310 /// here.
311 pub fn provision_cert_chain(
312 &self,
Seth Moore7ee79f92021-12-07 11:42:49 -0800313 db: &mut KeystoreDB,
Max Bires148c08e2020-10-13 13:41:41 -0700314 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800315 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700316 certs: &[u8],
317 expiration_date: i64,
318 sec_level: SecurityLevel,
319 ) -> Result<()> {
Seth Moore7ee79f92021-12-07 11:42:49 -0800320 let (_, _, uuid) = get_keymint_device(&sec_level)?;
321 db.store_signed_attestation_certificate_chain(
322 public_key,
323 batch_cert,
324 certs, /* DER encoded certificate chain */
325 expiration_date,
326 &uuid,
327 )
Max Bires148c08e2020-10-13 13:41:41 -0700328 }
329
Max Bires48fc2e52021-11-17 10:13:04 -0800330 fn parse_cose_mac0_for_coords(data: &[u8]) -> Result<Vec<u8>> {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000331 let cose_mac0: Vec<Value> = serde_cbor::from_slice(data)
332 .context(ks_err!("COSE_Mac0 returned from IRPC cannot be parsed"))?;
Max Bires48fc2e52021-11-17 10:13:04 -0800333 if cose_mac0.len() != COSE_MAC0_LEN {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000334 return Err(error::Error::sys()).context(ks_err!(
335 "COSE_Mac0 has improper length. \
Max Bires48fc2e52021-11-17 10:13:04 -0800336 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] {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000342 Value::Bytes(key) => {
343 serde_cbor::from_slice(key).context(ks_err!("COSE_Key is malformed."))?
344 }
345 _ => {
346 Err(error::Error::sys()).context(ks_err!("COSE_Mac0 payload is the wrong type."))?
347 }
Max Bires48fc2e52021-11-17 10:13:04 -0800348 };
349 if !cose_key.contains_key(&COSE_KEY_XCOORD) || !cose_key.contains_key(&COSE_KEY_YCOORD) {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000350 return Err(error::Error::sys())
351 .context(ks_err!("COSE_Key returned from IRPC is lacking required fields"));
Max Bires48fc2e52021-11-17 10:13:04 -0800352 }
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) => {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000359 return Err(error::Error::sys()).context(ks_err!(
360 "COSE_Key X-coordinate is not the right length. \
Max Bires48fc2e52021-11-17 10:13:04 -0800361 Expected: 32; Actual: {}",
362 x_coord.len()
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000363 ));
Max Bires48fc2e52021-11-17 10:13:04 -0800364 }
365 _ => {
366 return Err(error::Error::sys())
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000367 .context(ks_err!("COSE_Key X-coordinate is not a bstr"));
Max Bires48fc2e52021-11-17 10:13:04 -0800368 }
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) => {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000375 return Err(error::Error::sys()).context(ks_err!(
376 "COSE_Key Y-coordinate is not the right length. \
Max Bires48fc2e52021-11-17 10:13:04 -0800377 Expected: 32; Actual: {}",
378 y_coord.len()
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000379 ));
Max Bires48fc2e52021-11-17 10:13:04 -0800380 }
381 _ => {
382 return Err(error::Error::sys())
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000383 .context(ks_err!("COSE_Key Y-coordinate is not a bstr"));
Max Bires48fc2e52021-11-17 10:13:04 -0800384 }
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)?;
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000400 let dev = self
401 .get_dev_by_sec_level(&sec_level)
402 .context(ks_err!("Failed to get device for security level {:?}", sec_level))?;
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))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000406 .context(ks_err!("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)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000408 .context(ks_err!("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)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000410 .context(ks_err!("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 )
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000472 .context(ks_err!(
473 "Failed to get a key after \
474 attempting to assign one.",
Seth Moore7ee79f92021-12-07 11:42:49 -0800475 ))?
476 .map_or_else(
477 || {
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000478 Err(Error::sys()).context(ks_err!(
479 "Attempted to assign a \
480 key and failed silently. Something is very wrong.",
Seth Moore7ee79f92021-12-07 11:42:49 -0800481 ))
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)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000499 .context(ks_err!("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)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000507 .context(ks_err!("Failed to assign a key"))?;
Seth Moore7ee79f92021-12-07 11:42:49 -0800508 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)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000625 .context(ks_err!())?;
Max Bires55620ff2022-02-11 13:34:15 -0800626 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))
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000634 .context(ks_err!("No available attestation keys")),
Seth Moore92648b62022-02-02 13:26:18 -0800635 }
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)
Shaquille Johnson9da2e1c2022-09-19 12:39:01 +0000644 .context(ks_err!("Failed to get TEE Remote Provisioner instance."))?;
Seth Moore92648b62022-02-02 13:26:18 -0800645 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};
Seth Moorecd6e9182022-11-04 17:39:05 +0000697 use android_hardware_security_rkp::aidl::android::hardware::security::keymint::{
Seth Moore7ee79f92021-12-07 11:42:49 -0800698 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 }
Tri Vo113a1c92022-10-02 15:23:19 -0700741
742 fn generateCertificateRequestV2(
743 &self,
744 _keys_to_sign: &[MacedPublicKey],
745 _challenge: &[u8],
746 ) -> binder::Result<Vec<u8>> {
747 Err(binder::StatusCode::INVALID_OPERATION.into())
748 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800749 }
750
751 // Hard coded cert that can be parsed -- the content doesn't matter for testing, only that it's valid.
752 fn get_fake_cert() -> Vec<u8> {
753 vec![
754 0x30, 0x82, 0x01, 0xbb, 0x30, 0x82, 0x01, 0x61, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
755 0x14, 0x3a, 0xd5, 0x67, 0xce, 0xfe, 0x93, 0xe1, 0xea, 0xb7, 0xe4, 0xbf, 0x64, 0x19,
756 0xa4, 0x11, 0xe1, 0x87, 0x40, 0x20, 0x37, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
757 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
758 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
759 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
760 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
761 0x6c, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x30, 0x32, 0x32,
762 0x30, 0x38, 0x35, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x34, 0x32, 0x36, 0x32,
763 0x32, 0x30, 0x38, 0x35, 0x32, 0x5a, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
764 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
765 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
766 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f,
767 0x67, 0x6c, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
768 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
769 0x00, 0x04, 0x1e, 0xac, 0x0c, 0xe0, 0x0d, 0xc5, 0x25, 0x84, 0x1b, 0xd2, 0x77, 0x2d,
770 0xe7, 0xba, 0xf1, 0xde, 0xa7, 0xf6, 0x39, 0x7f, 0x38, 0x91, 0xbf, 0xa4, 0x58, 0xf5,
771 0x62, 0x6b, 0xce, 0x06, 0xcf, 0xb9, 0x73, 0x91, 0x0d, 0x8a, 0x60, 0xa0, 0xc6, 0xa2,
772 0x22, 0xe6, 0x51, 0x2e, 0x58, 0xd6, 0x43, 0x02, 0x80, 0x43, 0x44, 0x29, 0x38, 0x9a,
773 0x99, 0xf3, 0xa4, 0xdd, 0xd0, 0xb4, 0x6f, 0x8b, 0x44, 0x2d, 0xa3, 0x53, 0x30, 0x51,
774 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdb, 0x13, 0x68,
775 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe, 0x42, 0x3c, 0xd9, 0x3f, 0x1a,
776 0x33, 0xe9, 0xaa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
777 0x80, 0x14, 0xdb, 0x13, 0x68, 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe,
778 0x42, 0x3c, 0xd9, 0x3f, 0x1a, 0x33, 0xe9, 0xaa, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
779 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06,
780 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
781 0x02, 0x20, 0x10, 0xdf, 0x40, 0xc3, 0x20, 0x54, 0x36, 0xb5, 0xc9, 0x3c, 0x70, 0xe3,
782 0x55, 0x37, 0xd2, 0x04, 0x51, 0xeb, 0x0f, 0x18, 0x83, 0xd0, 0x58, 0xa1, 0x08, 0x77,
783 0x8d, 0x4d, 0xa4, 0x20, 0xee, 0x33, 0x02, 0x21, 0x00, 0x8d, 0xe3, 0xa6, 0x6c, 0x0d,
784 0x86, 0x25, 0xdc, 0x59, 0x0d, 0x21, 0x43, 0x22, 0x3a, 0xb9, 0xa1, 0x73, 0x28, 0xc9,
785 0x16, 0x9e, 0x91, 0x15, 0xc4, 0xc3, 0xd7, 0xeb, 0xe5, 0xce, 0xdc, 0x1c, 0x1b,
786 ]
787 }
788
789 // Generate a fake COSE_Mac0 with a key that's just `byte` repeated
790 fn generate_maced_pubkey(byte: u8) -> Vec<u8> {
791 vec![
792 0x84, 0x43, 0xA1, 0x01, 0x05, 0xA0, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20,
793 0x01, 0x21, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
794 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
795 byte, byte, byte, byte, byte, byte, byte, byte, 0x22, 0x58, 0x20, byte, byte, byte,
796 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
797 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
798 byte, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
799 byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
800 byte, byte, byte, byte, byte, byte, byte,
801 ]
802 }
Max Bires48fc2e52021-11-17 10:13:04 -0800803
804 #[test]
805 fn test_parse_cose_mac0_for_coords_raw_bytes() -> Result<()> {
806 let cose_mac0: Vec<u8> = vec![
807 0x84, 0x01, 0x02, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
808 0x20, 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9,
809 0x21, 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C,
810 0x43, 0x22, 0xC8, 0xEE, 0x03, 0x22, 0x58, 0x20, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95,
811 0x90, 0xA7, 0x5C, 0x5A, 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A,
812 0xA3, 0xB3, 0x1A, 0xB4, 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC, 0x03,
813 ];
814 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&cose_mac0)?;
815 assert_eq!(
816 raw_key,
817 vec![
818 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9, 0x21,
819 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C, 0x43,
820 0x22, 0xC8, 0xEE, 0x03, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95, 0x90, 0xA7, 0x5C, 0x5A,
821 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A, 0xA3, 0xB3, 0x1A, 0xB4,
822 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC,
823 ]
824 );
825 Ok(())
826 }
827
828 #[test]
829 fn test_parse_cose_mac0_for_coords_constructed_mac() -> Result<()> {
830 let x_coord: Vec<u8> = vec![0; 32];
831 let y_coord: Vec<u8> = vec![1; 32];
832 let mut expected_key: Vec<u8> = Vec::new();
833 expected_key.extend(&x_coord);
834 expected_key.extend(&y_coord);
835 let key_map: BTreeMap<Value, Value> = BTreeMap::from([
836 (Value::Integer(1), Value::Integer(2)),
837 (Value::Integer(3), Value::Integer(-7)),
838 (Value::Integer(-1), Value::Integer(1)),
839 (Value::Integer(-2), Value::Bytes(x_coord)),
840 (Value::Integer(-3), Value::Bytes(y_coord)),
841 ]);
842 let cose_mac0: Vec<Value> = vec![
843 Value::Integer(0),
844 Value::Integer(1),
845 Value::from(serde_cbor::to_vec(&key_map)?),
846 Value::Integer(2),
847 ];
848 let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&serde_cbor::to_vec(
849 &Value::from(cose_mac0),
850 )?)?;
851 assert_eq!(expected_key, raw_key);
852 Ok(())
853 }
854
855 #[test]
856 fn test_extract_payload_from_cose_mac() -> Result<()> {
857 let key_map = Value::Map(BTreeMap::from([(Value::Integer(1), Value::Integer(2))]));
858 let payload = Value::Bytes(serde_cbor::to_vec(&key_map)?);
859 let cose_mac0 =
860 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
861 let extracted_map = RemoteProvisioningService::extract_payload_from_cose_mac(
862 &serde_cbor::to_vec(&cose_mac0)?,
863 )?;
864 assert_eq!(key_map, extracted_map);
865 Ok(())
866 }
867
868 #[test]
869 fn test_extract_payload_from_cose_mac_fails_malformed_payload() -> Result<()> {
870 let payload = Value::Bytes(vec![5; 10]);
871 let cose_mac0 =
872 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
873 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
874 &serde_cbor::to_vec(&cose_mac0)?,
875 );
876 assert!(extracted_payload.is_err());
877 Ok(())
878 }
879
880 #[test]
881 fn test_extract_payload_from_cose_mac_fails_type() -> Result<()> {
882 let payload = Value::Integer(1);
883 let cose_mac0 =
884 Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
885 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
886 &serde_cbor::to_vec(&cose_mac0)?,
887 );
888 assert!(extracted_payload.is_err());
889 Ok(())
890 }
891
892 #[test]
893 fn test_extract_payload_from_cose_mac_fails_length() -> Result<()> {
894 let cose_mac0 = Value::Array(vec![Value::Integer(0), Value::Integer(1)]);
895 let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
896 &serde_cbor::to_vec(&cose_mac0)?,
897 );
898 assert!(extracted_payload.is_err());
899 Ok(())
900 }
Seth Moore7ee79f92021-12-07 11:42:49 -0800901
902 #[test]
903 #[ignore] // b/215746308
904 fn test_get_attestation_key_no_keys_provisioned() {
905 let mut db = crate::database::tests::new_test_db().unwrap();
906 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
907 mock_rpc.0.lock().unwrap().hw_info.uniqueId = Some(String::from("mallory"));
908
Seth Moore92648b62022-02-02 13:26:18 -0800909 let mut service: RemotelyProvisionedKeyPoolService = Default::default();
Seth Moore7ee79f92021-12-07 11:42:49 -0800910 service
Seth Moore92648b62022-02-02 13:26:18 -0800911 .unique_id_to_sec_level
912 .insert(String::from("mallory"), SecurityLevel::TRUSTED_ENVIRONMENT);
Seth Moore7ee79f92021-12-07 11:42:49 -0800913
914 assert_eq!(
915 service
916 .get_attestation_key(&mut db, 0, "mallory")
917 .unwrap_err()
918 .downcast::<error::Error>()
919 .unwrap(),
920 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
921 );
922 }
923
924 #[test]
925 #[ignore] // b/215746308
926 fn test_get_attestation_key() {
927 let mut db = crate::database::tests::new_test_db().unwrap();
928 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
929 let irpc_id = "paul";
930 let caller_uid = 0;
931
932 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
933 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -0800934 let mut remote_provisioning: RemoteProvisioningService = Default::default();
935 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
936 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
937 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -0800938
939 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
940 mock_values.lock().unwrap().private_key = vec![8, 6, 7, 5, 3, 0, 9];
941 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -0800942 remote_provisioning.generate_key_pair(&mut db, true, sec_level).unwrap();
Seth Moore7ee79f92021-12-07 11:42:49 -0800943
944 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
945 mock_values.lock().unwrap().maced_public_key.as_slice(),
946 )
947 .unwrap();
948 let batch_cert = get_fake_cert();
949 let certs = &[5, 6, 7, 8];
Seth Moore92648b62022-02-02 13:26:18 -0800950 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -0800951 .provision_cert_chain(
952 &mut db,
953 public_key.as_slice(),
954 batch_cert.as_slice(),
955 certs,
956 0,
957 sec_level
958 )
959 .is_ok());
960
961 // ensure we got the key we expected
Seth Moore92648b62022-02-02 13:26:18 -0800962 let first_key = key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800963 .get_attestation_key(&mut db, caller_uid, irpc_id)
964 .context("get first key")
965 .unwrap();
966 assert_eq!(first_key.keyBlob, mock_values.lock().unwrap().private_key);
967 assert_eq!(first_key.encodedCertChain, certs);
968
969 // ensure that multiple calls get the same key
970 assert_eq!(
971 first_key,
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, irpc_id)
974 .context("get second key")
975 .unwrap()
976 );
977
978 // no more keys for new clients
979 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -0800980 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -0800981 .get_attestation_key(&mut db, caller_uid + 1, irpc_id)
982 .unwrap_err()
983 .downcast::<error::Error>()
984 .unwrap(),
985 error::Error::Rc(ResponseCode::OUT_OF_KEYS)
986 );
987 }
988
989 #[test]
990 #[ignore] // b/215746308
991 fn test_get_attestation_key_gets_different_key_for_different_client() {
992 let mut db = crate::database::tests::new_test_db().unwrap();
993 let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
994 let irpc_id = "ringo";
995 let first_caller = 0;
996 let second_caller = first_caller + 1;
997
998 let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
999 let mock_values = mock_rpc.0.clone();
Seth Moore92648b62022-02-02 13:26:18 -08001000 let mut remote_provisioning: RemoteProvisioningService = Default::default();
1001 remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
1002 let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
1003 key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
Seth Moore7ee79f92021-12-07 11:42:49 -08001004
1005 // generate two distinct keys and provision them with certs
1006 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1007 mock_values.lock().unwrap().private_key = vec![3, 1, 4, 1, 5];
1008 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
Seth Moore92648b62022-02-02 13:26:18 -08001009 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001010 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1011 mock_values.lock().unwrap().maced_public_key.as_slice(),
1012 )
1013 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001014 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001015 .provision_cert_chain(
1016 &mut db,
1017 public_key.as_slice(),
1018 get_fake_cert().as_slice(),
1019 &[1],
1020 0,
1021 sec_level
1022 )
1023 .is_ok());
1024
1025 mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
1026 mock_values.lock().unwrap().private_key = vec![9, 0, 2, 1, 0];
1027 mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x22);
Seth Moore92648b62022-02-02 13:26:18 -08001028 assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
Seth Moore7ee79f92021-12-07 11:42:49 -08001029 let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
1030 mock_values.lock().unwrap().maced_public_key.as_slice(),
1031 )
1032 .unwrap();
Seth Moore92648b62022-02-02 13:26:18 -08001033 assert!(remote_provisioning
Seth Moore7ee79f92021-12-07 11:42:49 -08001034 .provision_cert_chain(
1035 &mut db,
1036 public_key.as_slice(),
1037 get_fake_cert().as_slice(),
1038 &[2],
1039 0,
1040 sec_level
1041 )
1042 .is_ok());
1043
1044 // make sure each caller gets a distinct key
1045 assert_ne!(
Seth Moore92648b62022-02-02 13:26:18 -08001046 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001047 .get_attestation_key(&mut db, first_caller, irpc_id)
1048 .context("get first key")
1049 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001050 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001051 .get_attestation_key(&mut db, second_caller, irpc_id)
1052 .context("get second key")
1053 .unwrap()
1054 );
1055
1056 // repeated calls should return the same key for a given caller
1057 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001058 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001059 .get_attestation_key(&mut db, first_caller, irpc_id)
1060 .context("first caller a")
1061 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001062 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001063 .get_attestation_key(&mut db, first_caller, irpc_id)
1064 .context("first caller b")
1065 .unwrap(),
1066 );
1067
1068 assert_eq!(
Seth Moore92648b62022-02-02 13:26:18 -08001069 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001070 .get_attestation_key(&mut db, second_caller, irpc_id)
1071 .context("second caller a")
1072 .unwrap(),
Seth Moore92648b62022-02-02 13:26:18 -08001073 key_pool
Seth Moore7ee79f92021-12-07 11:42:49 -08001074 .get_attestation_key(&mut db, second_caller, irpc_id)
1075 .context("second caller b")
1076 .unwrap()
1077 );
1078 }
Max Bires48fc2e52021-11-17 10:13:04 -08001079}