blob: cc97573ecd5cb7deccb56e5ddc84fb4ff05ccb38 [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,
26 IRemotelyProvisionedComponent::IRemotelyProvisionedComponent, KeyParameter::KeyParameter,
27 KeyParameterValue::KeyParameterValue, MacedPublicKey::MacedPublicKey,
28 ProtectedData::ProtectedData, SecurityLevel::SecurityLevel, Tag::Tag,
Max Biresb2e1d032021-02-08 21:35:05 -080029};
Max Bires148c08e2020-10-13 13:41:41 -070030use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{
31 AttestationPoolStatus::AttestationPoolStatus, IRemoteProvisioning::BnRemoteProvisioning,
32 IRemoteProvisioning::IRemoteProvisioning,
33};
Stephen Crane221bbb52020-12-16 15:52:10 -080034use android_security_remoteprovisioning::binder::Strong;
Max Bires97f96812021-02-23 23:44:57 -080035use android_system_keystore2::aidl::android::system::keystore2::{
36 Domain::Domain, KeyDescriptor::KeyDescriptor,
37};
Max Biresb2e1d032021-02-08 21:35:05 -080038use anyhow::{Context, Result};
Max Bires97f96812021-02-23 23:44:57 -080039use keystore2_crypto::parse_subject_from_certificate;
40use std::sync::atomic::{AtomicBool, Ordering};
Max Bires148c08e2020-10-13 13:41:41 -070041
Max Bires97f96812021-02-23 23:44:57 -080042use crate::database::{CertificateChain, KeystoreDB, Uuid};
43use crate::error::{self, map_or_log_err, map_rem_prov_error, Error};
Max Biresb2e1d032021-02-08 21:35:05 -080044use crate::globals::{get_keymint_device, get_remotely_provisioned_component, DB};
45use crate::utils::Asp;
Max Bires148c08e2020-10-13 13:41:41 -070046
Max Bires97f96812021-02-23 23:44:57 -080047/// Contains helper functions to check if remote provisioning is enabled on the system and, if so,
48/// to assign and retrieve attestation keys and certificate chains.
49#[derive(Default)]
50pub struct RemProvState {
51 security_level: SecurityLevel,
52 km_uuid: Uuid,
53 is_hal_present: AtomicBool,
54}
55
56impl RemProvState {
57 /// Creates a RemProvState struct.
58 pub fn new(security_level: SecurityLevel, km_uuid: Uuid) -> Self {
59 Self { security_level, km_uuid, is_hal_present: AtomicBool::new(true) }
60 }
61
62 /// Checks if remote provisioning is enabled and partially caches the result. On a hybrid system
63 /// remote provisioning can flip from being disabled to enabled depending on responses from the
64 /// server, so unfortunately caching the presence or absence of the HAL is not enough to fully
65 /// make decisions about the state of remote provisioning during runtime.
66 fn check_rem_prov_enabled(&self, db: &mut KeystoreDB) -> Result<bool> {
67 if !self.is_hal_present.load(Ordering::Relaxed)
68 || get_remotely_provisioned_component(&self.security_level).is_err()
69 {
70 self.is_hal_present.store(false, Ordering::Relaxed);
71 return Ok(false);
72 }
73 // To check if remote provisioning is enabled on a system that supports both remote
74 // provisioning and factory provisioned keys, we only need to check if there are any
75 // keys at all generated to indicate if the app has gotten the signal to begin filling
76 // the key pool from the server.
77 let pool_status = db
78 .get_attestation_pool_status(0 /* date */, &self.km_uuid)
79 .context("In check_rem_prov_enabled: failed to get attestation pool status.")?;
80 Ok(pool_status.total != 0)
81 }
82
83 /// Fetches a remote provisioning attestation key and certificate chain inside of the
84 /// returned `CertificateChain` struct if one exists for the given caller_uid. If one has not
85 /// been assigned, this function will assign it. If there are no signed attestation keys
86 /// available to be assigned, it will return the ResponseCode `OUT_OF_KEYS`
87 fn get_rem_prov_attest_key(
88 &self,
89 key: &KeyDescriptor,
90 caller_uid: u32,
91 db: &mut KeystoreDB,
92 ) -> Result<Option<CertificateChain>> {
93 match key.domain {
94 Domain::APP => {
95 // Attempt to get an Attestation Key once. If it fails, then the app doesn't
96 // have a valid chain assigned to it. The helper function will return None after
97 // attempting to assign a key. An error will be thrown if the pool is simply out
98 // of usable keys. Then another attempt to fetch the just-assigned key will be
99 // made. If this fails too, something is very wrong.
100 self.get_rem_prov_attest_key_helper(key, caller_uid, db)
101 .context("In get_rem_prov_attest_key: Failed to get a key")?
102 .map_or_else(
103 || self.get_rem_prov_attest_key_helper(key, caller_uid, db),
104 |v| Ok(Some(v)),
105 )
106 .context(concat!(
107 "In get_rem_prov_attest_key: Failed to get a key after",
108 "attempting to assign one."
109 ))?
110 .map_or_else(
111 || {
112 Err(Error::sys()).context(concat!(
113 "In get_rem_prov_attest_key: Attempted to assign a ",
114 "key and failed silently. Something is very wrong."
115 ))
116 },
117 |cert_chain| Ok(Some(cert_chain)),
118 )
119 }
120 _ => Ok(None),
121 }
122 }
123
124 /// Returns None if an AttestationKey fails to be assigned. Errors if no keys are available.
125 fn get_rem_prov_attest_key_helper(
126 &self,
127 key: &KeyDescriptor,
128 caller_uid: u32,
129 db: &mut KeystoreDB,
130 ) -> Result<Option<CertificateChain>> {
131 let cert_chain = db
132 .retrieve_attestation_key_and_cert_chain(key.domain, caller_uid as i64, &self.km_uuid)
133 .context("In get_rem_prov_attest_key_helper: Failed to retrieve a key + cert chain")?;
134 match cert_chain {
135 Some(cert_chain) => Ok(Some(cert_chain)),
136 // Either this app needs to be assigned a key, or the pool is empty. An error will
137 // be thrown if there is no key available to assign. This will indicate that the app
138 // should be nudged to provision more keys so keystore can retry.
139 None => {
140 db.assign_attestation_key(key.domain, caller_uid as i64, &self.km_uuid)
141 .context("In get_rem_prov_attest_key_helper: Failed to assign a key")?;
142 Ok(None)
143 }
144 }
145 }
146
147 fn is_asymmetric_key(&self, params: &[KeyParameter]) -> bool {
148 params.iter().any(|kp| {
149 matches!(
150 kp,
151 KeyParameter {
152 tag: Tag::ALGORITHM,
153 value: KeyParameterValue::Algorithm(Algorithm::RSA)
154 } | KeyParameter {
155 tag: Tag::ALGORITHM,
156 value: KeyParameterValue::Algorithm(Algorithm::EC)
157 }
158 )
159 })
160 }
161
162 /// Checks to see (1) if the key in question should be attested to based on the algorithm and
163 /// (2) if remote provisioning is present and enabled on the system. If these conditions are
164 /// met, it makes an attempt to fetch the attestation key assigned to the `caller_uid`.
165 ///
166 /// It returns the ResponseCode `OUT_OF_KEYS` if there is not one key currently assigned to the
167 /// `caller_uid` and there are none available to assign.
168 pub fn get_remote_provisioning_key_and_certs(
169 &self,
170 key: &KeyDescriptor,
171 caller_uid: u32,
172 params: &[KeyParameter],
173 db: &mut KeystoreDB,
174 ) -> Result<(Option<AttestationKey>, Option<Certificate>)> {
175 if !self.is_asymmetric_key(params) || !self.check_rem_prov_enabled(db)? {
176 // There is no remote provisioning component for this security level on the
177 // device. Return None so the underlying KM instance knows to use its
178 // factory provisioned key instead. Alternatively, it's not an asymmetric key
179 // and therefore will not be attested.
180 Ok((None, None))
181 } else {
182 match self.get_rem_prov_attest_key(&key, caller_uid, db).context(concat!(
183 "In get_remote_provisioning_key_and_certs: Failed to get ",
184 "attestation key"
185 ))? {
186 Some(cert_chain) => Ok((
187 Some(AttestationKey {
188 keyBlob: cert_chain.private_key.to_vec(),
189 attestKeyParams: vec![],
190 issuerSubjectName: parse_subject_from_certificate(&cert_chain.batch_cert)
191 .context(concat!(
192 "In get_remote_provisioning_key_and_certs: Failed to ",
193 "parse subject."
194 ))?,
195 }),
196 Some(Certificate { encodedCertificate: cert_chain.cert_chain }),
197 )),
198 None => Ok((None, None)),
199 }
200 }
201 }
202}
Max Bires148c08e2020-10-13 13:41:41 -0700203/// Implementation of the IRemoteProvisioning service.
Max Biresb2e1d032021-02-08 21:35:05 -0800204#[derive(Default)]
Max Bires148c08e2020-10-13 13:41:41 -0700205pub struct RemoteProvisioningService {
Max Biresb2e1d032021-02-08 21:35:05 -0800206 device_by_sec_level: HashMap<SecurityLevel, Asp>,
Max Bires148c08e2020-10-13 13:41:41 -0700207}
208
209impl RemoteProvisioningService {
Max Biresb2e1d032021-02-08 21:35:05 -0800210 fn get_dev_by_sec_level(
211 &self,
212 sec_level: &SecurityLevel,
213 ) -> Result<Strong<dyn IRemotelyProvisionedComponent>> {
214 if let Some(dev) = self.device_by_sec_level.get(sec_level) {
215 dev.get_interface().context("In get_dev_by_sec_level.")
216 } else {
217 Err(error::Error::sys()).context(concat!(
218 "In get_dev_by_sec_level: Remote instance for requested security level",
219 " not found."
220 ))
221 }
222 }
223
Max Bires148c08e2020-10-13 13:41:41 -0700224 /// Creates a new instance of the remote provisioning service
Stephen Crane221bbb52020-12-16 15:52:10 -0800225 pub fn new_native_binder() -> Result<Strong<dyn IRemoteProvisioning>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800226 let mut result: Self = Default::default();
227 let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
228 .context("In new_native_binder: Failed to get TEE Remote Provisioner instance.")?;
229 result.device_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, dev);
230 if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
231 result.device_by_sec_level.insert(SecurityLevel::STRONGBOX, dev);
232 }
233 Ok(BnRemoteProvisioning::new_binder(result))
Max Bires148c08e2020-10-13 13:41:41 -0700234 }
235
236 /// Populates the AttestationPoolStatus parcelable with information about how many
237 /// certs will be expiring by the date provided in `expired_by` along with how many
238 /// keys have not yet been assigned.
239 pub fn get_pool_status(
240 &self,
241 expired_by: i64,
242 sec_level: SecurityLevel,
243 ) -> Result<AttestationPoolStatus> {
244 let (_, _, uuid) = get_keymint_device(&sec_level)?;
245 DB.with::<_, Result<AttestationPoolStatus>>(|db| {
246 let mut db = db.borrow_mut();
Max Biresb2e1d032021-02-08 21:35:05 -0800247 // delete_expired_attestation_keys is always safe to call, and will remove anything
248 // older than the date at the time of calling. No work should be done on the
249 // attestation keys unless the pool status is checked first, so this call should be
250 // enough to routinely clean out expired keys.
251 db.delete_expired_attestation_keys()?;
Max Bires148c08e2020-10-13 13:41:41 -0700252 Ok(db.get_attestation_pool_status(expired_by, &uuid)?)
253 })
254 }
255
256 /// 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.
264 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 Bires148c08e2020-10-13 13:41:41 -0700272 ) -> Result<Vec<u8>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800273 let dev = self.get_dev_by_sec_level(&sec_level)?;
274 let (_, _, uuid) = get_keymint_device(&sec_level)?;
275 let keys_to_sign = DB.with::<_, Result<Vec<MacedPublicKey>>>(|db| {
276 let mut db = db.borrow_mut();
277 Ok(db
278 .fetch_unsigned_attestation_keys(num_csr, &uuid)?
279 .iter()
280 .map(|key| MacedPublicKey { macedKey: key.to_vec() })
281 .collect())
282 })?;
283 let mut mac = Vec::<u8>::with_capacity(32);
284 map_rem_prov_error(dev.generateCertificateRequest(
285 test_mode,
286 &keys_to_sign,
287 eek,
288 challenge,
289 &mut mac,
290 protected_data,
291 ))
292 .context("In generate_csr: Failed to generate csr")?;
Max Bires97f96812021-02-23 23:44:57 -0800293 let mut cose_mac_0 = Vec::<u8>::new();
294 // TODO(b/180392379): Replace this manual CBOR generation with the cbor-serde crate as well.
295 // This generates an array consisting of the mac and the public key Maps.
296 // Just generate the actual MacedPublicKeys structure when the crate is
297 // available.
298 cose_mac_0.push((0b100_00000 | (keys_to_sign.len() + 1)) as u8);
299 cose_mac_0.push(0b010_11000); //push mac
300 cose_mac_0.push(mac.len() as u8);
301 cose_mac_0.append(&mut mac);
302 for maced_public_key in keys_to_sign {
303 if maced_public_key.macedKey.len() > 83 + 8 {
304 cose_mac_0.extend_from_slice(&maced_public_key.macedKey[8..83 + 8]);
305 }
306 }
307 Ok(cose_mac_0)
Max Bires148c08e2020-10-13 13:41:41 -0700308 }
309
310 /// Provisions a certificate chain for a key whose CSR was included in generate_csr. The
311 /// `public_key` is used to index into the SQL database in order to insert the `certs` blob
312 /// which represents a PEM encoded X.509 certificate chain. The `expiration_date` is provided
313 /// as a convenience from the caller to avoid having to parse the certificates semantically
314 /// here.
315 pub fn provision_cert_chain(
316 &self,
317 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800318 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700319 certs: &[u8],
320 expiration_date: i64,
321 sec_level: SecurityLevel,
322 ) -> Result<()> {
323 DB.with::<_, Result<()>>(|db| {
324 let mut db = db.borrow_mut();
325 let (_, _, uuid) = get_keymint_device(&sec_level)?;
326 Ok(db.store_signed_attestation_certificate_chain(
327 public_key,
Max Biresb2e1d032021-02-08 21:35:05 -0800328 batch_cert,
Max Bires148c08e2020-10-13 13:41:41 -0700329 certs, /* DER encoded certificate chain */
330 expiration_date,
331 &uuid,
332 )?)
333 })
334 }
335
336 /// Submits a request to the Remote Provisioner HAL to generate a signing key pair.
337 /// `is_test_mode` indicates whether or not the returned public key should be marked as being
338 /// for testing in order to differentiate them from private keys. If the call is successful,
339 /// the key pair is then added to the database.
Max Biresb2e1d032021-02-08 21:35:05 -0800340 pub fn generate_key_pair(&self, is_test_mode: bool, sec_level: SecurityLevel) -> Result<()> {
341 let (_, _, uuid) = get_keymint_device(&sec_level)?;
342 let dev = self.get_dev_by_sec_level(&sec_level)?;
343 let mut maced_key = MacedPublicKey { macedKey: Vec::new() };
344 let priv_key =
345 map_rem_prov_error(dev.generateEcdsaP256KeyPair(is_test_mode, &mut maced_key))
346 .context("In generate_key_pair: Failed to generated ECDSA keypair.")?;
347 // TODO(b/180392379): This is a brittle hack that relies on the consistent formatting of
348 // the returned CBOR blob in order to extract the public key.
349 let data = &maced_key.macedKey;
350 if data.len() < 85 {
351 return Err(error::Error::sys()).context(concat!(
352 "In generate_key_pair: CBOR blob returned from",
353 "RemotelyProvisionedComponent is definitely malformatted or empty."
354 ));
355 }
356 let mut raw_key: Vec<u8> = vec![0; 64];
357 raw_key[0..32].clone_from_slice(&data[18..18 + 32]);
358 raw_key[32..64].clone_from_slice(&data[53..53 + 32]);
359 DB.with::<_, Result<()>>(|db| {
360 let mut db = db.borrow_mut();
361 Ok(db.create_attestation_key_entry(&maced_key.macedKey, &raw_key, &priv_key, &uuid)?)
362 })
363 }
364
365 /// Checks the security level of each available IRemotelyProvisionedComponent hal and returns
366 /// all levels in an array to the caller.
367 pub fn get_security_levels(&self) -> Result<Vec<SecurityLevel>> {
368 Ok(self.device_by_sec_level.keys().cloned().collect())
Max Bires148c08e2020-10-13 13:41:41 -0700369 }
Max Bires60d7ed12021-03-05 15:59:22 -0800370
371 /// Deletes all attestation keys generated by the IRemotelyProvisionedComponent from the device,
372 /// regardless of what state of the attestation key lifecycle they were in.
373 pub fn delete_all_keys(&self) -> Result<i64> {
374 DB.with::<_, Result<i64>>(|db| {
375 let mut db = db.borrow_mut();
376 Ok(db.delete_all_attestation_keys()?)
377 })
378 }
Max Bires148c08e2020-10-13 13:41:41 -0700379}
380
381impl binder::Interface for RemoteProvisioningService {}
382
383// Implementation of IRemoteProvisioning. See AIDL spec at
384// :aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
385impl IRemoteProvisioning for RemoteProvisioningService {
386 fn getPoolStatus(
387 &self,
388 expired_by: i64,
389 sec_level: SecurityLevel,
390 ) -> binder::public_api::Result<AttestationPoolStatus> {
391 map_or_log_err(self.get_pool_status(expired_by, sec_level), Ok)
392 }
393
394 fn generateCsr(
395 &self,
396 test_mode: bool,
397 num_csr: i32,
398 eek: &[u8],
399 challenge: &[u8],
400 sec_level: SecurityLevel,
Max Biresb2e1d032021-02-08 21:35:05 -0800401 protected_data: &mut ProtectedData,
Max Bires148c08e2020-10-13 13:41:41 -0700402 ) -> binder::public_api::Result<Vec<u8>> {
Max Biresb2e1d032021-02-08 21:35:05 -0800403 map_or_log_err(
404 self.generate_csr(test_mode, num_csr, eek, challenge, sec_level, protected_data),
405 Ok,
406 )
Max Bires148c08e2020-10-13 13:41:41 -0700407 }
408
409 fn provisionCertChain(
410 &self,
411 public_key: &[u8],
Max Biresb2e1d032021-02-08 21:35:05 -0800412 batch_cert: &[u8],
Max Bires148c08e2020-10-13 13:41:41 -0700413 certs: &[u8],
414 expiration_date: i64,
415 sec_level: SecurityLevel,
416 ) -> binder::public_api::Result<()> {
Max Biresb2e1d032021-02-08 21:35:05 -0800417 map_or_log_err(
418 self.provision_cert_chain(public_key, batch_cert, certs, expiration_date, sec_level),
419 Ok,
420 )
Max Bires148c08e2020-10-13 13:41:41 -0700421 }
422
423 fn generateKeyPair(
424 &self,
425 is_test_mode: bool,
426 sec_level: SecurityLevel,
427 ) -> binder::public_api::Result<()> {
428 map_or_log_err(self.generate_key_pair(is_test_mode, sec_level), Ok)
429 }
Max Biresb2e1d032021-02-08 21:35:05 -0800430
431 fn getSecurityLevels(&self) -> binder::public_api::Result<Vec<SecurityLevel>> {
432 map_or_log_err(self.get_security_levels(), Ok)
433 }
Max Bires60d7ed12021-03-05 15:59:22 -0800434
435 fn deleteAllKeys(&self) -> binder::public_api::Result<i64> {
436 map_or_log_err(self.delete_all_keys(), Ok)
437 }
Max Bires148c08e2020-10-13 13:41:41 -0700438}