Max Bires | 148c08e | 2020-10-13 13:41:41 -0700 | [diff] [blame] | 1 | // 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 Bires | b2e1d03 | 2021-02-08 21:35:05 -0800 | [diff] [blame] | 22 | use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{ |
Max Bires | 97f9681 | 2021-02-23 23:44:57 -0800 | [diff] [blame] | 23 | Algorithm::Algorithm, AttestationKey::AttestationKey, Certificate::Certificate, |
Seth Moore | cd6e918 | 2022-11-04 17:39:05 +0000 | [diff] [blame] | 24 | KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel, |
Max Bires | 834dd36 | 2021-03-23 13:01:57 -0700 | [diff] [blame] | 25 | Tag::Tag, |
Max Bires | b2e1d03 | 2021-02-08 21:35:05 -0800 | [diff] [blame] | 26 | }; |
Alice Wang | b03ed83 | 2023-11-22 16:35:54 +0000 | [diff] [blame] | 27 | use android_security_rkp_aidl::aidl::android::security::rkp::RemotelyProvisionedKey::RemotelyProvisionedKey; |
Max Bires | 97f9681 | 2021-02-23 23:44:57 -0800 | [diff] [blame] | 28 | use android_system_keystore2::aidl::android::system::keystore2::{ |
Tri Vo | a1634bb | 2022-12-01 15:54:19 -0800 | [diff] [blame] | 29 | Domain::Domain, KeyDescriptor::KeyDescriptor, |
Max Bires | 97f9681 | 2021-02-23 23:44:57 -0800 | [diff] [blame] | 30 | }; |
Max Bires | b2e1d03 | 2021-02-08 21:35:05 -0800 | [diff] [blame] | 31 | use anyhow::{Context, Result}; |
Max Bires | 97f9681 | 2021-02-23 23:44:57 -0800 | [diff] [blame] | 32 | use keystore2_crypto::parse_subject_from_certificate; |
Max Bires | 148c08e | 2020-10-13 13:41:41 -0700 | [diff] [blame] | 33 | |
Alice Wang | 849cfe4 | 2023-11-10 12:43:36 +0000 | [diff] [blame] | 34 | use crate::error::wrapped_rkpd_error_to_ks_error; |
Alice Wang | bf6a693 | 2023-11-07 11:47:12 +0000 | [diff] [blame] | 35 | use crate::globals::get_remotely_provisioned_component_name; |
Shaquille Johnson | 9da2e1c | 2022-09-19 12:39:01 +0000 | [diff] [blame] | 36 | use crate::ks_err; |
Hasini Gunasinghe | 8a1a224 | 2021-08-02 22:28:39 +0000 | [diff] [blame] | 37 | use crate::metrics_store::log_rkp_error_stats; |
Alice Wang | 4277d2e | 2023-11-08 09:15:54 +0000 | [diff] [blame] | 38 | use crate::watchdog_helper::watchdog as wd; |
Hasini Gunasinghe | 8a1a224 | 2021-08-02 22:28:39 +0000 | [diff] [blame] | 39 | use android_security_metrics::aidl::android::security::metrics::RkpError::RkpError as MetricsRkpError; |
Max Bires | 148c08e | 2020-10-13 13:41:41 -0700 | [diff] [blame] | 40 | |
Max Bires | 97f9681 | 2021-02-23 23:44:57 -0800 | [diff] [blame] | 41 | /// Contains helper functions to check if remote provisioning is enabled on the system and, if so, |
| 42 | /// to assign and retrieve attestation keys and certificate chains. |
| 43 | #[derive(Default)] |
| 44 | pub struct RemProvState { |
| 45 | security_level: SecurityLevel, |
Max Bires | 97f9681 | 2021-02-23 23:44:57 -0800 | [diff] [blame] | 46 | } |
| 47 | |
| 48 | impl RemProvState { |
| 49 | /// Creates a RemProvState struct. |
David Drysdale | 8c4c4f3 | 2023-10-31 12:14:11 +0000 | [diff] [blame] | 50 | pub fn new(security_level: SecurityLevel) -> Self { |
| 51 | Self { security_level } |
Max Bires | 55620ff | 2022-02-11 13:34:15 -0800 | [diff] [blame] | 52 | } |
| 53 | |
Seth Moore | dfdcb87 | 2022-04-20 14:33:19 -0700 | [diff] [blame] | 54 | fn is_rkp_only(&self) -> bool { |
Max Bires | 65207b5 | 2022-03-29 23:58:08 -0700 | [diff] [blame] | 55 | let default_value = false; |
| 56 | |
Seth Moore | dfdcb87 | 2022-04-20 14:33:19 -0700 | [diff] [blame] | 57 | let property_name = match self.security_level { |
| 58 | SecurityLevel::STRONGBOX => "remote_provisioning.strongbox.rkp_only", |
| 59 | SecurityLevel::TRUSTED_ENVIRONMENT => "remote_provisioning.tee.rkp_only", |
Max Bires | 65207b5 | 2022-03-29 23:58:08 -0700 | [diff] [blame] | 60 | _ => return default_value, |
| 61 | }; |
| 62 | |
| 63 | rustutils::system_properties::read_bool(property_name, default_value) |
| 64 | .unwrap_or(default_value) |
| 65 | } |
| 66 | |
Max Bires | 97f9681 | 2021-02-23 23:44:57 -0800 | [diff] [blame] | 67 | fn is_asymmetric_key(&self, params: &[KeyParameter]) -> bool { |
| 68 | params.iter().any(|kp| { |
| 69 | matches!( |
| 70 | kp, |
| 71 | KeyParameter { |
| 72 | tag: Tag::ALGORITHM, |
| 73 | value: KeyParameterValue::Algorithm(Algorithm::RSA) |
| 74 | } | KeyParameter { |
| 75 | tag: Tag::ALGORITHM, |
| 76 | value: KeyParameterValue::Algorithm(Algorithm::EC) |
| 77 | } |
| 78 | ) |
| 79 | }) |
| 80 | } |
| 81 | |
Tri Vo | b5e43d1 | 2022-12-21 08:54:14 -0800 | [diff] [blame] | 82 | /// Fetches attestation key and corresponding certificates from RKPD. |
| 83 | pub fn get_rkpd_attestation_key_and_certs( |
| 84 | &self, |
| 85 | key: &KeyDescriptor, |
| 86 | caller_uid: u32, |
| 87 | params: &[KeyParameter], |
| 88 | ) -> Result<Option<(AttestationKey, Certificate)>> { |
| 89 | if !self.is_asymmetric_key(params) || key.domain != Domain::APP { |
| 90 | Ok(None) |
| 91 | } else { |
Alice Wang | b03ed83 | 2023-11-22 16:35:54 +0000 | [diff] [blame] | 92 | match get_rkpd_attestation_key(&self.security_level, caller_uid) { |
Tri Vo | b5e43d1 | 2022-12-21 08:54:14 -0800 | [diff] [blame] | 93 | Err(e) => { |
| 94 | if self.is_rkp_only() { |
| 95 | log::error!("Error occurred: {:?}", e); |
Alice Wang | 849cfe4 | 2023-11-10 12:43:36 +0000 | [diff] [blame] | 96 | return Err(wrapped_rkpd_error_to_ks_error(&e)).context(format!("{e:?}")); |
Tri Vo | b5e43d1 | 2022-12-21 08:54:14 -0800 | [diff] [blame] | 97 | } |
| 98 | log::warn!("Error occurred: {:?}", e); |
| 99 | log_rkp_error_stats( |
| 100 | MetricsRkpError::FALL_BACK_DURING_HYBRID, |
| 101 | &self.security_level, |
| 102 | ); |
| 103 | Ok(None) |
| 104 | } |
| 105 | Ok(rkpd_key) => Ok(Some(( |
| 106 | AttestationKey { |
| 107 | keyBlob: rkpd_key.keyBlob, |
| 108 | attestKeyParams: vec![], |
| 109 | // Batch certificate is at the beginning of the certificate chain. |
| 110 | issuerSubjectName: parse_subject_from_certificate( |
| 111 | &rkpd_key.encodedCertChain, |
| 112 | ) |
| 113 | .context(ks_err!("Failed to parse subject."))?, |
| 114 | }, |
| 115 | Certificate { encodedCertificate: rkpd_key.encodedCertChain }, |
| 116 | ))), |
| 117 | } |
| 118 | } |
| 119 | } |
Max Bires | 97f9681 | 2021-02-23 23:44:57 -0800 | [diff] [blame] | 120 | } |
Alice Wang | b03ed83 | 2023-11-22 16:35:54 +0000 | [diff] [blame] | 121 | |
| 122 | fn get_rkpd_attestation_key( |
| 123 | security_level: &SecurityLevel, |
| 124 | caller_uid: u32, |
| 125 | ) -> Result<RemotelyProvisionedKey> { |
Alice Wang | f714840 | 2023-11-24 08:36:51 +0000 | [diff] [blame] | 126 | // Depending on the Android release, RKP may not have been mandatory for the |
| 127 | // TEE or StrongBox KM instances. In such cases, lookup failure for the IRPC |
| 128 | // HAL service is WAI and should not cause a failure. The error should be caught |
| 129 | // by the calling function and allow for natural fallback to the factory key. |
Alice Wang | b03ed83 | 2023-11-22 16:35:54 +0000 | [diff] [blame] | 130 | let rpc_name = get_remotely_provisioned_component_name(security_level) |
| 131 | .context(ks_err!("Trying to get IRPC name."))?; |
David Drysdale | 541846b | 2024-05-23 13:16:07 +0100 | [diff] [blame] | 132 | let _wd = wd::watch("Calling get_rkpd_attestation_key()"); |
Alice Wang | b03ed83 | 2023-11-22 16:35:54 +0000 | [diff] [blame] | 133 | rkpd_client::get_rkpd_attestation_key(&rpc_name, caller_uid) |
| 134 | } |