Merge "Fix CSR format for RKPv3"
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index d8c0081..4084ace 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -31,7 +31,6 @@
],
rustlibs: [
- "android.hardware.security.rkp-V3-rust",
"android.hardware.security.secureclock-V1-rust",
"android.hardware.security.sharedsecret-V1-rust",
"android.os.permissions_aidl-rust",
@@ -40,7 +39,6 @@
"android.security.compat-rust",
"android.security.maintenance-rust",
"android.security.metrics-rust",
- "android.security.remoteprovisioning-rust",
"android.security.rkp_aidl-rust",
"libanyhow",
"libbinder_rs",
@@ -87,7 +85,6 @@
"keystore2_use_latest_aidl_rust",
],
rustlibs: [
- "android.hardware.security.rkp-V3-rust",
"libbinder_rs",
"libkeystore2_selinux",
"liblog_rust",
@@ -125,7 +122,6 @@
auto_gen_config: true,
compile_multilib: "first",
rustlibs: [
- "android.hardware.security.rkp-V3-rust",
"libbinder_rs",
"libkeystore2_selinux",
"liblog_rust",
diff --git a/keystore2/src/attestation_key_utils.rs b/keystore2/src/attestation_key_utils.rs
index 8c4cdea..184b3cb 100644
--- a/keystore2/src/attestation_key_utils.rs
+++ b/keystore2/src/attestation_key_utils.rs
@@ -30,17 +30,11 @@
};
use anyhow::{Context, Result};
use keystore2_crypto::parse_subject_from_certificate;
-use rustutils::system_properties;
/// KeyMint takes two different kinds of attestation keys. Remote provisioned keys
/// and those that have been generated by the user. Unfortunately, they need to be
/// handled quite differently, thus the different representations.
pub enum AttestationKeyInfo {
- RemoteProvisioned {
- key_id_guard: KeyIdGuard,
- attestation_key: AttestationKey,
- attestation_certs: Certificate,
- },
RkpdProvisioned {
attestation_key: AttestationKey,
attestation_certs: Certificate,
@@ -53,12 +47,6 @@
},
}
-fn use_rkpd() -> bool {
- let property = "remote_provisioning.enable_rkpd";
- let default_value = true;
- system_properties::read_bool(property, default_value).unwrap_or(default_value)
-}
-
/// This function loads and, optionally, assigns the caller's remote provisioned
/// attestation key if a challenge is present. Alternatively, if `attest_key_descriptor` is given,
/// it loads the user generated attestation key from the database.
@@ -75,34 +63,14 @@
params.iter().any(|kp| kp.tag == Tag::DEVICE_UNIQUE_ATTESTATION);
match attest_key_descriptor {
// Do not select an RKP key if DEVICE_UNIQUE_ATTESTATION is present.
- None if challenge_present && !is_device_unique_attestation => {
- if use_rkpd() {
- rem_prov_state
- .get_rkpd_attestation_key_and_certs(key, caller_uid, params)
- .context(ks_err!("Trying to get attestation key from RKPD."))
- .map(|result| {
- result.map(|(attestation_key, attestation_certs)| {
- AttestationKeyInfo::RkpdProvisioned {
- attestation_key,
- attestation_certs,
- }
- })
- })
- } else {
- rem_prov_state
- .get_remotely_provisioned_attestation_key_and_certs(key, caller_uid, params, db)
- .context(ks_err!("Trying to get remotely provisioned attestation key."))
- .map(|result| {
- result.map(|(key_id_guard, attestation_key, attestation_certs)| {
- AttestationKeyInfo::RemoteProvisioned {
- key_id_guard,
- attestation_key,
- attestation_certs,
- }
- })
- })
- }
- }
+ None if challenge_present && !is_device_unique_attestation => rem_prov_state
+ .get_rkpd_attestation_key_and_certs(key, caller_uid, params)
+ .context(ks_err!("Trying to get attestation key from RKPD."))
+ .map(|result| {
+ result.map(|(attestation_key, attestation_certs)| {
+ AttestationKeyInfo::RkpdProvisioned { attestation_key, attestation_certs }
+ })
+ }),
None => Ok(None),
Some(attest_key) => get_user_generated_attestation_key(attest_key, caller_uid, db)
.context(ks_err!("Trying to load attest key"))
diff --git a/keystore2/src/crypto/tests/certificate_utils_test.cpp b/keystore2/src/crypto/tests/certificate_utils_test.cpp
index bd94928..a851798 100644
--- a/keystore2/src/crypto/tests/certificate_utils_test.cpp
+++ b/keystore2/src/crypto/tests/certificate_utils_test.cpp
@@ -313,7 +313,15 @@
const uint8_t* p = encCert.data();
X509_Ptr decoded_cert(d2i_X509(nullptr, &p, (long)encCert.size()));
EVP_PKEY_Ptr decoded_pkey(X509_get_pubkey(decoded_cert.get()));
- ASSERT_TRUE(X509_verify(decoded_cert.get(), decoded_pkey.get()));
+ if ((padding == Padding::PSS) && (digest == Digest::SHA1 || digest == Digest::SHA224)) {
+ // BoringSSL after https://boringssl-review.googlesource.com/c/boringssl/+/53865
+ // does not support these PSS combinations, so skip certificate verification for them
+ // and just check _something_ was returned.
+ EXPECT_NE(decoded_cert.get(), nullptr);
+ EXPECT_NE(decoded_pkey.get(), nullptr);
+ } else {
+ ASSERT_TRUE(X509_verify(decoded_cert.get(), decoded_pkey.get()));
+ }
}
TEST(TimeStringTests, toTimeStringTest) {
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index c9c28f6..7b90fd5 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -63,20 +63,16 @@
use utils::SqlField;
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
- HardwareAuthToken::HardwareAuthToken,
- HardwareAuthenticatorType::HardwareAuthenticatorType, SecurityLevel::SecurityLevel,
+ HardwareAuthToken::HardwareAuthToken, HardwareAuthenticatorType::HardwareAuthenticatorType,
+ SecurityLevel::SecurityLevel,
+};
+use android_security_metrics::aidl::android::security::metrics::{
+ RkpError::RkpError as MetricsRkpError, Storage::Storage as MetricsStorage,
+ StorageStats::StorageStats,
};
use android_system_keystore2::aidl::android::system::keystore2::{
Domain::Domain, KeyDescriptor::KeyDescriptor,
};
-use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{
- AttestationPoolStatus::AttestationPoolStatus,
-};
-use android_security_metrics::aidl::android::security::metrics::{
- StorageStats::StorageStats,
- Storage::Storage as MetricsStorage,
- RkpError::RkpError as MetricsRkpError,
-};
use keystore2_crypto::ZVec;
use lazy_static::lazy_static;
@@ -1983,73 +1979,6 @@
.context(ks_err!())
}
- /// Counts the number of keys that will expire by the provided epoch date and the number of
- /// keys not currently assigned to a domain.
- pub fn get_attestation_pool_status(
- &mut self,
- date: i64,
- km_uuid: &Uuid,
- ) -> Result<AttestationPoolStatus> {
- let _wp = wd::watch_millis("KeystoreDB::get_attestation_pool_status", 500);
-
- self.with_transaction(TransactionBehavior::Immediate, |tx| {
- let mut stmt = tx.prepare(
- "SELECT data
- FROM persistent.keymetadata
- WHERE tag = ? AND keyentryid IN
- (SELECT id
- FROM persistent.keyentry
- WHERE alias IS NOT NULL
- AND key_type = ?
- AND km_uuid = ?
- AND state = ?);",
- )?;
- let times = stmt
- .query_map(
- params![
- KeyMetaData::AttestationExpirationDate,
- KeyType::Attestation,
- km_uuid,
- KeyLifeCycle::Live
- ],
- |row| row.get(0),
- )?
- .collect::<rusqlite::Result<Vec<DateTime>>>()
- .context("Failed to execute metadata statement")?;
- let expiring =
- times.iter().filter(|time| time < &&DateTime::from_millis_epoch(date)).count()
- as i32;
- stmt = tx.prepare(
- "SELECT alias, domain
- FROM persistent.keyentry
- WHERE key_type = ? AND km_uuid = ? AND state = ?;",
- )?;
- let rows = stmt
- .query_map(params![KeyType::Attestation, km_uuid, KeyLifeCycle::Live], |row| {
- Ok((row.get(0)?, row.get(1)?))
- })?
- .collect::<rusqlite::Result<Vec<(Option<String>, Option<u32>)>>>()
- .context("Failed to execute keyentry statement")?;
- let mut unassigned = 0i32;
- let mut attested = 0i32;
- let total = rows.len() as i32;
- for (alias, domain) in rows {
- match (alias, domain) {
- (Some(_alias), None) => {
- attested += 1;
- unassigned += 1;
- }
- (Some(_alias), Some(_domain)) => {
- attested += 1;
- }
- _ => {}
- }
- }
- Ok(AttestationPoolStatus { expiring, unassigned, attested, total }).no_gc()
- })
- .context(ks_err!())
- }
-
fn query_kid_for_attestation_key_and_cert_chain(
&self,
tx: &Transaction,
@@ -3556,62 +3485,6 @@
}
#[test]
- fn test_get_attestation_pool_status() -> Result<()> {
- let mut db = new_test_db()?;
- let namespace: i64 = 30;
- load_attestation_key_pool(
- &mut db, 10, /* expiration */
- namespace, 0x01, /* base_byte */
- )?;
- load_attestation_key_pool(&mut db, 20 /* expiration */, namespace + 1, 0x02)?;
- load_attestation_key_pool(&mut db, 40 /* expiration */, namespace + 2, 0x03)?;
- let mut status = db.get_attestation_pool_status(9 /* expiration */, &KEYSTORE_UUID)?;
- assert_eq!(status.expiring, 0);
- assert_eq!(status.attested, 3);
- assert_eq!(status.unassigned, 0);
- assert_eq!(status.total, 3);
- assert_eq!(
- db.get_attestation_pool_status(15 /* expiration */, &KEYSTORE_UUID)?.expiring,
- 1
- );
- assert_eq!(
- db.get_attestation_pool_status(25 /* expiration */, &KEYSTORE_UUID)?.expiring,
- 2
- );
- assert_eq!(
- db.get_attestation_pool_status(60 /* expiration */, &KEYSTORE_UUID)?.expiring,
- 3
- );
- let public_key: Vec<u8> = vec![0x01, 0x02, 0x03];
- let private_key: Vec<u8> = vec![0x04, 0x05, 0x06];
- let raw_public_key: Vec<u8> = vec![0x07, 0x08, 0x09];
- let cert_chain: Vec<u8> = vec![0x0a, 0x0b, 0x0c];
- let batch_cert: Vec<u8> = vec![0x0d, 0x0e, 0x0f];
- db.create_attestation_key_entry(
- &public_key,
- &raw_public_key,
- &private_key,
- &KEYSTORE_UUID,
- )?;
- status = db.get_attestation_pool_status(0 /* expiration */, &KEYSTORE_UUID)?;
- assert_eq!(status.attested, 3);
- assert_eq!(status.unassigned, 0);
- assert_eq!(status.total, 4);
- db.store_signed_attestation_certificate_chain(
- &raw_public_key,
- &batch_cert,
- &cert_chain,
- 20,
- &KEYSTORE_UUID,
- )?;
- status = db.get_attestation_pool_status(0 /* expiration */, &KEYSTORE_UUID)?;
- assert_eq!(status.attested, 4);
- assert_eq!(status.unassigned, 1);
- assert_eq!(status.total, 4);
- Ok(())
- }
-
- #[test]
fn test_remove_expired_certs() -> Result<()> {
let temp_dir =
TempDir::new("test_remove_expired_certs_").expect("Failed to create temp dir.");
diff --git a/keystore2/src/fuzzers/Android.bp b/keystore2/src/fuzzers/Android.bp
index 9a2d98d..4ac83e3 100644
--- a/keystore2/src/fuzzers/Android.bp
+++ b/keystore2/src/fuzzers/Android.bp
@@ -20,6 +20,7 @@
name: "keystore2_unsafe_fuzzer",
srcs: ["keystore2_unsafe_fuzzer.rs"],
rustlibs: [
+ "libbinder_rs",
"libkeystore2",
"libkeystore2_crypto_rust",
"libkeystore2_vintf_rust",
diff --git a/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
index 1a385e7..0dca3a2 100644
--- a/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
+++ b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
@@ -14,10 +14,9 @@
//! Fuzzes unsafe APIs of libkeystore2 module
-#![feature(slice_internals)]
#![no_main]
-use core::slice::memchr;
+use binder::get_declared_instances;
use keystore2::{legacy_blob::LegacyBlobLoader, utils::ui_opts_2_compat};
use keystore2_aaid::get_aaid;
use keystore2_apc_compat::ApcHal;
@@ -28,7 +27,7 @@
hmac_sha256, parse_subject_from_certificate, Password, ZVec,
};
use keystore2_selinux::{check_access, getpidcon, setcon, Backend, Context, KeystoreKeyBackend};
-use keystore2_vintf::{get_aidl_instances, get_hidl_instances};
+use keystore2_vintf::get_hidl_instances;
use libfuzzer_sys::{arbitrary::Arbitrary, fuzz_target};
use std::{ffi::CString, sync::Arc};
@@ -37,7 +36,7 @@
/// CString does not contain any internal 0 bytes
fn get_valid_cstring_data(data: &[u8]) -> &[u8] {
- match memchr::memchr(0, data) {
+ match data.iter().position(|&b| b == 0) {
Some(idx) => &data[0..idx],
None => data,
}
@@ -97,7 +96,6 @@
},
GetAidlInstances {
aidl_package: &'a str,
- version: usize,
aidl_interface_name: &'a str,
},
GetAaid {
@@ -191,8 +189,11 @@
} => {
get_hidl_instances(hidl_package, major_version, minor_version, hidl_interface_name);
}
- FuzzCommand::GetAidlInstances { aidl_package, version, aidl_interface_name } => {
- get_aidl_instances(aidl_package, version, aidl_interface_name);
+ FuzzCommand::GetAidlInstances { aidl_package, aidl_interface_name } => {
+ get_declared_instances(
+ format!("{}.{}", aidl_package, aidl_interface_name).as_str(),
+ )
+ .unwrap();
}
FuzzCommand::GetAaid { aaid_uid } => {
let _res = get_aaid(aaid_uid);
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index ed59578..8b26ceb 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -34,7 +34,6 @@
IKeyMintDevice::IKeyMintDevice, KeyMintHardwareInfo::KeyMintHardwareInfo,
SecurityLevel::SecurityLevel,
};
-use android_hardware_security_rkp::aidl::android::hardware::security::keymint::IRemotelyProvisionedComponent::IRemotelyProvisionedComponent;
use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
ISecureClock::ISecureClock,
};
@@ -42,7 +41,7 @@
use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
use anyhow::{Context, Result};
use binder::FromIBinder;
-use keystore2_vintf::get_aidl_instances;
+use binder::get_declared_instances;
use lazy_static::lazy_static;
use std::sync::{Arc, Mutex, RwLock};
use std::{cell::RefCell, sync::Once};
@@ -134,26 +133,6 @@
}
}
-struct RemotelyProvisionedDevicesMap<T: FromIBinder + ?Sized> {
- devices_by_sec_level: HashMap<SecurityLevel, Strong<T>>,
-}
-
-impl<T: FromIBinder + ?Sized> Default for RemotelyProvisionedDevicesMap<T> {
- fn default() -> Self {
- Self { devices_by_sec_level: HashMap::<SecurityLevel, Strong<T>>::new() }
- }
-}
-
-impl<T: FromIBinder + ?Sized> RemotelyProvisionedDevicesMap<T> {
- fn dev_by_sec_level(&self, sec_level: &SecurityLevel) -> Option<Strong<T>> {
- self.devices_by_sec_level.get(sec_level).map(|dev| (*dev).clone())
- }
-
- fn insert(&mut self, sec_level: SecurityLevel, dev: Strong<T>) {
- self.devices_by_sec_level.insert(sec_level, dev);
- }
-}
-
lazy_static! {
/// The path where keystore stores all its keys.
pub static ref DB_PATH: RwLock<PathBuf> = RwLock::new(
@@ -164,10 +143,6 @@
static ref KEY_MINT_DEVICES: Mutex<DevicesMap<dyn IKeyMintDevice>> = Default::default();
/// Timestamp service.
static ref TIME_STAMP_DEVICE: Mutex<Option<Strong<dyn ISecureClock>>> = Default::default();
- /// RemotelyProvisionedComponent HAL devices.
- static ref REMOTELY_PROVISIONED_COMPONENT_DEVICES:
- Mutex<RemotelyProvisionedDevicesMap<dyn IRemotelyProvisionedComponent>> =
- Default::default();
/// A single on-demand worker thread that handles deferred tasks with two different
/// priorities.
pub static ref ASYNC_TASK: Arc<AsyncTask> = Default::default();
@@ -208,7 +183,7 @@
version: i32,
) -> Result<Option<(i32, String)>> {
let keymint_instances =
- get_aidl_instances("android.hardware.security.keymint", version as usize, "IKeyMintDevice");
+ get_declared_instances("android.hardware.security.keymint.IKeyMintDevice").unwrap();
let service_name = match *security_level {
SecurityLevel::TRUSTED_ENVIRONMENT => {
@@ -254,7 +229,7 @@
Ok(sl)
}
})
- .context(ks_err!())?;
+ .context(ks_err!("Get service name by version"))?;
let (keymint, hal_version) = if let Some((version, service_name)) = service_name {
let km: Strong<dyn IKeyMintDevice> =
@@ -359,7 +334,8 @@
if let Some((dev, hw_info, uuid)) = devices_map.dev_by_sec_level(security_level) {
Ok((dev, hw_info, uuid))
} else {
- let (dev, hw_info) = connect_keymint(security_level).context(ks_err!())?;
+ let (dev, hw_info) =
+ connect_keymint(security_level).context(ks_err!("Cannot connect to Keymint"))?;
devices_map.insert(*security_level, dev, hw_info);
// Unwrap must succeed because we just inserted it.
Ok(devices_map.dev_by_sec_level(security_level).unwrap())
@@ -393,7 +369,7 @@
/// to connect to the legacy wrapper.
fn connect_secureclock() -> Result<Strong<dyn ISecureClock>> {
let secureclock_instances =
- get_aidl_instances("android.hardware.security.secureclock", 1, "ISecureClock");
+ get_declared_instances("android.hardware.security.secureclock.ISecureClock").unwrap();
let secure_clock_available =
secureclock_instances.iter().any(|instance| *instance == "default");
@@ -444,7 +420,7 @@
/// Get the service name of a remotely provisioned component corresponding to given security level.
pub fn get_remotely_provisioned_component_name(security_level: &SecurityLevel) -> Result<String> {
let remotely_prov_instances =
- get_aidl_instances("android.hardware.security.keymint", 1, "IRemotelyProvisionedComponent");
+ get_declared_instances(REMOTE_PROVISIONING_HAL_SERVICE_NAME).unwrap();
match *security_level {
SecurityLevel::TRUSTED_ENVIRONMENT => {
@@ -466,29 +442,3 @@
.ok_or(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
.context(ks_err!())
}
-
-fn connect_remotely_provisioned_component(
- security_level: &SecurityLevel,
-) -> Result<Strong<dyn IRemotelyProvisionedComponent>> {
- let service_name = get_remotely_provisioned_component_name(security_level)?;
- let rem_prov_hal: Strong<dyn IRemotelyProvisionedComponent> =
- map_binder_status_code(binder::get_interface(&service_name))
- .context(ks_err!("Trying to connect to RemotelyProvisionedComponent service."))?;
- Ok(rem_prov_hal)
-}
-
-/// Get a remote provisiong component device for the given security level either from the cache or
-/// by making a new connection. Returns the device.
-pub fn get_remotely_provisioned_component(
- security_level: &SecurityLevel,
-) -> Result<Strong<dyn IRemotelyProvisionedComponent>> {
- let mut devices_map = REMOTELY_PROVISIONED_COMPONENT_DEVICES.lock().unwrap();
- if let Some(dev) = devices_map.dev_by_sec_level(security_level) {
- Ok(dev)
- } else {
- let dev = connect_remotely_provisioned_component(security_level).context(ks_err!())?;
- devices_map.insert(*security_level, dev);
- // Unwrap must succeed because we just inserted it.
- Ok(devices_map.dev_by_sec_level(security_level).unwrap())
- }
-}
diff --git a/keystore2/src/keystore2_main.rs b/keystore2/src/keystore2_main.rs
index 8c5bf0f..31c1e29 100644
--- a/keystore2/src/keystore2_main.rs
+++ b/keystore2/src/keystore2_main.rs
@@ -19,9 +19,6 @@
use keystore2::maintenance::Maintenance;
use keystore2::metrics::Metrics;
use keystore2::metrics_store;
-use keystore2::remote_provisioning::{
- RemoteProvisioningService, RemotelyProvisionedKeyPoolService,
-};
use keystore2::service::KeystoreService;
use keystore2::{apc::ApcManager, shared_secret_negotiation};
use keystore2::{authorization::AuthorizationManager, id_rotation::IdRotationState};
@@ -34,9 +31,6 @@
static APC_SERVICE_NAME: &str = "android.security.apc";
static AUTHORIZATION_SERVICE_NAME: &str = "android.security.authorization";
static METRICS_SERVICE_NAME: &str = "android.security.metrics";
-static REMOTE_PROVISIONING_SERVICE_NAME: &str = "android.security.remoteprovisioning";
-static REMOTELY_PROVISIONED_KEY_POOL_SERVICE_NAME: &str =
- "android.security.remoteprovisioning.IRemotelyProvisionedKeyPool";
static USER_MANAGER_SERVICE_NAME: &str = "android.security.maintenance";
static LEGACY_KEYSTORE_SERVICE_NAME: &str = "android.security.legacykeystore";
@@ -146,43 +140,6 @@
panic!("Failed to register service {} because of {:?}.", METRICS_SERVICE_NAME, e);
});
- // Devices with KS2 and KM 1.0 may not have any IRemotelyProvisionedComponent HALs at all. Do
- // not panic if new_native_binder returns failure because it could not find the TEE HAL.
- match RemoteProvisioningService::new_native_binder() {
- Ok(remote_provisioning_service) => {
- binder::add_service(
- REMOTE_PROVISIONING_SERVICE_NAME,
- remote_provisioning_service.as_binder(),
- )
- .unwrap_or_else(|e| {
- panic!(
- "Failed to register service {} because of {:?}.",
- REMOTE_PROVISIONING_SERVICE_NAME, e
- );
- });
- }
- Err(e) => log::info!("Not publishing {}: {:?}", REMOTE_PROVISIONING_SERVICE_NAME, e),
- }
-
- // Even if the IRemotelyProvisionedComponent HAL is implemented, it doesn't mean that the keys
- // may be fetched via the key pool. The HAL must be a new version that exports a unique id. If
- // none of the HALs support this, then the key pool service is not published.
- match RemotelyProvisionedKeyPoolService::new_native_binder() {
- Ok(key_pool_service) => {
- binder::add_service(
- REMOTELY_PROVISIONED_KEY_POOL_SERVICE_NAME,
- key_pool_service.as_binder(),
- )
- .unwrap_or_else(|e| {
- panic!(
- "Failed to register service {} because of {:?}.",
- REMOTELY_PROVISIONED_KEY_POOL_SERVICE_NAME, e
- );
- });
- }
- Err(e) => log::info!("Not publishing IRemotelyProvisionedKeyPool service: {:?}", e),
- }
-
binder::add_service(LEGACY_KEYSTORE_SERVICE_NAME, legacykeystore.as_binder()).unwrap_or_else(
|e| {
panic!(
diff --git a/keystore2/src/metrics_store.rs b/keystore2/src/metrics_store.rs
index 6043612..77cead8 100644
--- a/keystore2/src/metrics_store.rs
+++ b/keystore2/src/metrics_store.rs
@@ -17,12 +17,11 @@
//! stores them in an in-memory store.
//! 2. Returns the collected metrics when requested by the statsd proxy.
-use crate::error::{get_error_code, Error};
+use crate::error::get_error_code;
use crate::globals::DB;
use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
use crate::ks_err;
use crate::operation::Outcome;
-use crate::remote_provisioning::get_pool_status;
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
@@ -42,16 +41,13 @@
KeystoreAtom::KeystoreAtom, KeystoreAtomPayload::KeystoreAtomPayload,
Outcome::Outcome as MetricsOutcome, Purpose::Purpose as MetricsPurpose,
RkpError::RkpError as MetricsRkpError, RkpErrorStats::RkpErrorStats,
- RkpPoolStats::RkpPoolStats, SecurityLevel::SecurityLevel as MetricsSecurityLevel,
- Storage::Storage as MetricsStorage,
+ SecurityLevel::SecurityLevel as MetricsSecurityLevel, Storage::Storage as MetricsStorage,
};
-use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
use anyhow::{Context, Result};
use lazy_static::lazy_static;
use rustutils::system_properties::PropertyWatcherError;
use std::collections::HashMap;
use std::sync::Mutex;
-use std::time::{Duration, SystemTime, UNIX_EPOCH};
// Note: Crash events are recorded at keystore restarts, based on the assumption that keystore only
// gets restarted after a crash, during a boot cycle.
@@ -95,11 +91,6 @@
return pull_storage_stats();
}
- // Process and return RKP pool stats.
- if AtomID::RKP_POOL_STATS == atom_id {
- return pull_attestation_pool_stats();
- }
-
// Process keystore crash stats.
if AtomID::CRASH_STATS == atom_id {
return Ok(vec![KeystoreAtom {
@@ -560,45 +551,6 @@
Ok(atom_vec)
}
-fn pull_attestation_pool_stats() -> Result<Vec<KeystoreAtom>> {
- let mut atoms = Vec::<KeystoreAtom>::new();
- for sec_level in &[SecurityLevel::TRUSTED_ENVIRONMENT, SecurityLevel::STRONGBOX] {
- // set the expired_by date to be three days from now
- let expired_by = SystemTime::now()
- .checked_add(Duration::from_secs(60 * 60 * 24 * 3))
- .ok_or(Error::Rc(ResponseCode::SYSTEM_ERROR))
- .context(ks_err!("Failed to compute expired by system time."))?
- .duration_since(UNIX_EPOCH)
- .context(ks_err!("Failed to compute expired by duration."))?
- .as_millis() as i64;
-
- let result = get_pool_status(expired_by, *sec_level);
-
- if let Ok(pool_status) = result {
- let rkp_pool_stats = RkpPoolStats {
- security_level: process_security_level(*sec_level),
- expiring: pool_status.expiring,
- unassigned: pool_status.unassigned,
- attested: pool_status.attested,
- total: pool_status.total,
- };
- atoms.push(KeystoreAtom {
- payload: KeystoreAtomPayload::RkpPoolStats(rkp_pool_stats),
- ..Default::default()
- });
- } else {
- log::error!(
- concat!(
- "In pull_attestation_pool_stats: Failed to retrieve pool status",
- " for security level: {:?}"
- ),
- sec_level
- );
- }
- }
- Ok(atoms)
-}
-
/// Log error events related to Remote Key Provisioning (RKP).
pub fn log_rkp_error_stats(rkp_error: MetricsRkpError, sec_level: &SecurityLevel) {
let rkp_error_stats = KeystoreAtomPayload::RkpErrorStats(RkpErrorStats {
diff --git a/keystore2/src/remote_provisioning.rs b/keystore2/src/remote_provisioning.rs
index 1a83339..811ad98 100644
--- a/keystore2/src/remote_provisioning.rs
+++ b/keystore2/src/remote_provisioning.rs
@@ -19,42 +19,21 @@
//! certificate chains signed by some root authority and stored in a keystore SQLite
//! DB.
-use std::collections::HashMap;
-
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Algorithm::Algorithm, AttestationKey::AttestationKey, Certificate::Certificate,
KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel,
Tag::Tag,
};
-use android_hardware_security_rkp::aidl::android::hardware::security::keymint::{
- DeviceInfo::DeviceInfo, IRemotelyProvisionedComponent::IRemotelyProvisionedComponent,
- MacedPublicKey::MacedPublicKey, ProtectedData::ProtectedData,
-};
-use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{
- AttestationPoolStatus::AttestationPoolStatus, IRemoteProvisioning::BnRemoteProvisioning,
- IRemoteProvisioning::IRemoteProvisioning,
- IRemotelyProvisionedKeyPool::BnRemotelyProvisionedKeyPool,
- IRemotelyProvisionedKeyPool::IRemotelyProvisionedKeyPool, ImplInfo::ImplInfo,
- RemotelyProvisionedKey::RemotelyProvisionedKey,
-};
-use android_security_remoteprovisioning::binder::{BinderFeatures, Strong};
use android_system_keystore2::aidl::android::system::keystore2::{
- Domain::Domain, KeyDescriptor::KeyDescriptor, ResponseCode::ResponseCode,
+ Domain::Domain, KeyDescriptor::KeyDescriptor,
};
use anyhow::{Context, Result};
use keystore2_crypto::parse_subject_from_certificate;
-use serde_cbor::Value;
-use std::collections::BTreeMap;
-use std::sync::atomic::{AtomicBool, Ordering};
-use crate::database::{CertificateChain, KeyIdGuard, KeystoreDB, Uuid};
-use crate::error::{self, map_or_log_err, map_rem_prov_error, Error};
-use crate::globals::{get_keymint_device, get_remotely_provisioned_component, DB};
+use crate::database::Uuid;
use crate::ks_err;
use crate::metrics_store::log_rkp_error_stats;
-use crate::permission::KeystorePerm;
use crate::rkpd_client::get_rkpd_attestation_key;
-use crate::utils::{check_keystore_permission, watchdog as wd};
use android_security_metrics::aidl::android::security::metrics::RkpError::RkpError as MetricsRkpError;
/// Contains helper functions to check if remote provisioning is enabled on the system and, if so,
@@ -63,18 +42,12 @@
pub struct RemProvState {
security_level: SecurityLevel,
km_uuid: Uuid,
- is_hal_present: AtomicBool,
}
-static COSE_KEY_XCOORD: Value = Value::Integer(-2);
-static COSE_KEY_YCOORD: Value = Value::Integer(-3);
-static COSE_MAC0_LEN: usize = 4;
-static COSE_MAC0_PAYLOAD: usize = 2;
-
impl RemProvState {
/// Creates a RemProvState struct.
pub fn new(security_level: SecurityLevel, km_uuid: Uuid) -> Self {
- Self { security_level, km_uuid, is_hal_present: AtomicBool::new(true) }
+ Self { security_level, km_uuid }
}
/// Returns the uuid for the KM instance attached to this RemProvState struct.
@@ -95,30 +68,6 @@
.unwrap_or(default_value)
}
- /// Checks if remote provisioning is enabled and partially caches the result. On a hybrid system
- /// remote provisioning can flip from being disabled to enabled depending on responses from the
- /// server, so unfortunately caching the presence or absence of the HAL is not enough to fully
- /// make decisions about the state of remote provisioning during runtime.
- fn check_rem_prov_enabled(&self, db: &mut KeystoreDB) -> Result<bool> {
- if self.is_rkp_only() {
- return Ok(true);
- }
- if !self.is_hal_present.load(Ordering::Relaxed)
- || get_remotely_provisioned_component(&self.security_level).is_err()
- {
- self.is_hal_present.store(false, Ordering::Relaxed);
- return Ok(false);
- }
- // To check if remote provisioning is enabled on a system that supports both remote
- // provisioning and factory provisioned keys, we only need to check if there are any
- // keys at all generated to indicate if the app has gotten the signal to begin filling
- // the key pool from the server.
- let pool_status = db
- .get_attestation_pool_status(0 /* date */, &self.km_uuid)
- .context("In check_rem_prov_enabled: failed to get attestation pool status.")?;
- Ok(pool_status.total != 0)
- }
-
fn is_asymmetric_key(&self, params: &[KeyParameter]) -> bool {
params.iter().any(|kp| {
matches!(
@@ -134,58 +83,6 @@
})
}
- /// Checks to see (1) if the key in question should be attested to based on the algorithm and
- /// (2) if remote provisioning is present and enabled on the system. If these conditions are
- /// met, it makes an attempt to fetch the attestation key assigned to the `caller_uid`.
- ///
- /// It returns the ResponseCode `OUT_OF_KEYS_TRANSIENT_ERROR` if there is not one key currently
- /// assigned to the `caller_uid` and there are none available to assign.
- pub fn get_remotely_provisioned_attestation_key_and_certs(
- &self,
- key: &KeyDescriptor,
- caller_uid: u32,
- params: &[KeyParameter],
- db: &mut KeystoreDB,
- ) -> Result<Option<(KeyIdGuard, AttestationKey, Certificate)>> {
- if !self.is_asymmetric_key(params) || !self.check_rem_prov_enabled(db)? {
- // There is no remote provisioning component for this security level on the
- // device. Return None so the underlying KM instance knows to use its
- // factory provisioned key instead. Alternatively, it's not an asymmetric key
- // and therefore will not be attested.
- Ok(None)
- } else {
- match get_rem_prov_attest_key(key.domain, caller_uid, db, &self.km_uuid) {
- Err(e) => {
- if self.is_rkp_only() {
- log::error!("Error occurred: {:?}", e);
- return Err(e);
- }
- log::warn!("Error occurred: {:?}", e);
- log_rkp_error_stats(
- MetricsRkpError::FALL_BACK_DURING_HYBRID,
- &self.security_level,
- );
- Ok(None)
- }
- Ok(v) => match v {
- Some((guard, cert_chain)) => Ok(Some((
- guard,
- AttestationKey {
- keyBlob: cert_chain.private_key.to_vec(),
- attestKeyParams: vec![],
- issuerSubjectName: parse_subject_from_certificate(
- &cert_chain.batch_cert,
- )
- .context(ks_err!("Failed to parse subject."))?,
- },
- Certificate { encodedCertificate: cert_chain.cert_chain },
- ))),
- None => Ok(None),
- },
- }
- }
- }
-
/// Fetches attestation key and corresponding certificates from RKPD.
pub fn get_rkpd_attestation_key_and_certs(
&self,
@@ -225,896 +122,3 @@
}
}
}
-
-/// Implementation of the IRemoteProvisioning service.
-#[derive(Default)]
-pub struct RemoteProvisioningService {
- device_by_sec_level: HashMap<SecurityLevel, Strong<dyn IRemotelyProvisionedComponent>>,
- curve_by_sec_level: HashMap<SecurityLevel, i32>,
-}
-
-impl RemoteProvisioningService {
- fn get_dev_by_sec_level(
- &self,
- sec_level: &SecurityLevel,
- ) -> Result<&dyn IRemotelyProvisionedComponent> {
- if let Some(dev) = self.device_by_sec_level.get(sec_level) {
- Ok(dev.as_ref())
- } else {
- Err(error::Error::sys()).context(ks_err!(
- "Remote instance for requested security level \
- not found.",
- ))
- }
- }
-
- /// Creates a new instance of the remote provisioning service
- pub fn new_native_binder() -> Result<Strong<dyn IRemoteProvisioning>> {
- let mut result: Self = Default::default();
- let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
- .context(ks_err!("Failed to get TEE Remote Provisioner instance."))?;
- result.curve_by_sec_level.insert(
- SecurityLevel::TRUSTED_ENVIRONMENT,
- dev.getHardwareInfo()
- .context(ks_err!("Failed to get hardware info for the TEE."))?
- .supportedEekCurve,
- );
- result.device_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, dev);
- if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
- result.curve_by_sec_level.insert(
- SecurityLevel::STRONGBOX,
- dev.getHardwareInfo()
- .context(ks_err!("Failed to get hardware info for StrongBox."))?
- .supportedEekCurve,
- );
- result.device_by_sec_level.insert(SecurityLevel::STRONGBOX, dev);
- }
- Ok(BnRemoteProvisioning::new_binder(result, BinderFeatures::default()))
- }
-
- fn extract_payload_from_cose_mac(data: &[u8]) -> Result<Value> {
- let cose_mac0: Vec<Value> = serde_cbor::from_slice(data)
- .context(ks_err!("COSE_Mac0 returned from IRPC cannot be parsed"))?;
- if cose_mac0.len() != COSE_MAC0_LEN {
- return Err(error::Error::sys()).context(ks_err!(
- "COSE_Mac0 has improper length. \
- Expected: {}, Actual: {}",
- COSE_MAC0_LEN,
- cose_mac0.len(),
- ));
- }
- match &cose_mac0[COSE_MAC0_PAYLOAD] {
- Value::Bytes(key) => {
- Ok(serde_cbor::from_slice(key)
- .context(ks_err!("COSE_Mac0 payload is malformed."))?)
- }
- _ => {
- Err(error::Error::sys()).context(ks_err!("COSE_Mac0 payload is the wrong type."))?
- }
- }
- }
-
- /// Generates a CBOR blob which will be assembled by the calling code into a larger
- /// CBOR blob intended for delivery to a provisioning serever. This blob will contain
- /// `num_csr` certificate signing requests for attestation keys generated in the TEE,
- /// along with a server provided `eek` and `challenge`. The endpoint encryption key will
- /// be used to encrypt the sensitive contents being transmitted to the server, and the
- /// challenge will ensure freshness. A `test_mode` flag will instruct the remote provisioning
- /// HAL if it is okay to accept EEKs that aren't signed by something that chains back to the
- /// baked in root of trust in the underlying IRemotelyProvisionedComponent instance.
- #[allow(clippy::too_many_arguments)]
- pub fn generate_csr(
- &self,
- test_mode: bool,
- num_csr: i32,
- eek: &[u8],
- challenge: &[u8],
- sec_level: SecurityLevel,
- protected_data: &mut ProtectedData,
- device_info: &mut DeviceInfo,
- ) -> Result<Vec<u8>> {
- let dev = self.get_dev_by_sec_level(&sec_level)?;
- let (_, _, uuid) = get_keymint_device(&sec_level)?;
- let keys_to_sign = DB.with::<_, Result<Vec<MacedPublicKey>>>(|db| {
- let mut db = db.borrow_mut();
- Ok(db
- .fetch_unsigned_attestation_keys(num_csr, &uuid)?
- .iter()
- .map(|key| MacedPublicKey { macedKey: key.to_vec() })
- .collect())
- })?;
- let mac = map_rem_prov_error(dev.generateCertificateRequest(
- test_mode,
- &keys_to_sign,
- eek,
- challenge,
- device_info,
- protected_data,
- ))
- .context(ks_err!("Failed to generate csr"))?;
- let mut mac_and_keys: Vec<Value> = vec![Value::from(mac)];
- for maced_public_key in keys_to_sign {
- mac_and_keys.push(
- Self::extract_payload_from_cose_mac(&maced_public_key.macedKey)
- .context(ks_err!("Failed to get the payload from the COSE_Mac0"))?,
- )
- }
- let cbor_array: Value = Value::Array(mac_and_keys);
- serde_cbor::to_vec(&cbor_array)
- .context(ks_err!("Failed to serialize the mac and keys array"))
- }
-
- /// Provisions a certificate chain for a key whose CSR was included in generate_csr. The
- /// `public_key` is used to index into the SQL database in order to insert the `certs` blob
- /// which represents a PEM encoded X.509 certificate chain. The `expiration_date` is provided
- /// as a convenience from the caller to avoid having to parse the certificates semantically
- /// here.
- pub fn provision_cert_chain(
- &self,
- db: &mut KeystoreDB,
- public_key: &[u8],
- batch_cert: &[u8],
- certs: &[u8],
- expiration_date: i64,
- sec_level: SecurityLevel,
- ) -> Result<()> {
- let (_, _, uuid) = get_keymint_device(&sec_level)?;
- db.store_signed_attestation_certificate_chain(
- public_key,
- batch_cert,
- certs, /* DER encoded certificate chain */
- expiration_date,
- &uuid,
- )
- }
-
- fn parse_cose_mac0_for_coords(data: &[u8]) -> Result<Vec<u8>> {
- let cose_mac0: Vec<Value> = serde_cbor::from_slice(data)
- .context(ks_err!("COSE_Mac0 returned from IRPC cannot be parsed"))?;
- if cose_mac0.len() != COSE_MAC0_LEN {
- return Err(error::Error::sys()).context(ks_err!(
- "COSE_Mac0 has improper length. \
- Expected: {}, Actual: {}",
- COSE_MAC0_LEN,
- cose_mac0.len(),
- ));
- }
- let cose_key: BTreeMap<Value, Value> = match &cose_mac0[COSE_MAC0_PAYLOAD] {
- Value::Bytes(key) => {
- serde_cbor::from_slice(key).context(ks_err!("COSE_Key is malformed."))?
- }
- _ => {
- Err(error::Error::sys()).context(ks_err!("COSE_Mac0 payload is the wrong type."))?
- }
- };
- if !cose_key.contains_key(&COSE_KEY_XCOORD) || !cose_key.contains_key(&COSE_KEY_YCOORD) {
- return Err(error::Error::sys())
- .context(ks_err!("COSE_Key returned from IRPC is lacking required fields"));
- }
- let mut raw_key: Vec<u8> = vec![0; 64];
- match &cose_key[&COSE_KEY_XCOORD] {
- Value::Bytes(x_coord) if x_coord.len() == 32 => {
- raw_key[0..32].clone_from_slice(x_coord)
- }
- Value::Bytes(x_coord) => {
- return Err(error::Error::sys()).context(ks_err!(
- "COSE_Key X-coordinate is not the right length. \
- Expected: 32; Actual: {}",
- x_coord.len()
- ));
- }
- _ => {
- return Err(error::Error::sys())
- .context(ks_err!("COSE_Key X-coordinate is not a bstr"));
- }
- }
- match &cose_key[&COSE_KEY_YCOORD] {
- Value::Bytes(y_coord) if y_coord.len() == 32 => {
- raw_key[32..64].clone_from_slice(y_coord)
- }
- Value::Bytes(y_coord) => {
- return Err(error::Error::sys()).context(ks_err!(
- "COSE_Key Y-coordinate is not the right length. \
- Expected: 32; Actual: {}",
- y_coord.len()
- ));
- }
- _ => {
- return Err(error::Error::sys())
- .context(ks_err!("COSE_Key Y-coordinate is not a bstr"));
- }
- }
- Ok(raw_key)
- }
-
- /// Submits a request to the Remote Provisioner HAL to generate a signing key pair.
- /// `is_test_mode` indicates whether or not the returned public key should be marked as being
- /// for testing in order to differentiate them from private keys. If the call is successful,
- /// the key pair is then added to the database.
- pub fn generate_key_pair(
- &self,
- db: &mut KeystoreDB,
- is_test_mode: bool,
- sec_level: SecurityLevel,
- ) -> Result<()> {
- let (_, _, uuid) = get_keymint_device(&sec_level)?;
- let dev = self
- .get_dev_by_sec_level(&sec_level)
- .context(ks_err!("Failed to get device for security level {:?}", sec_level))?;
- let mut maced_key = MacedPublicKey { macedKey: Vec::new() };
- let priv_key =
- map_rem_prov_error(dev.generateEcdsaP256KeyPair(is_test_mode, &mut maced_key))
- .context(ks_err!("Failed to generated ECDSA keypair."))?;
- let raw_key = Self::parse_cose_mac0_for_coords(&maced_key.macedKey)
- .context(ks_err!("Failed to parse raw key"))?;
- db.create_attestation_key_entry(&maced_key.macedKey, &raw_key, &priv_key, &uuid)
- .context(ks_err!("Failed to insert attestation key entry"))
- }
-
- /// Checks the security level of each available IRemotelyProvisionedComponent hal and returns
- /// all levels in an array to the caller.
- pub fn get_implementation_info(&self) -> Result<Vec<ImplInfo>> {
- Ok(self
- .curve_by_sec_level
- .iter()
- .map(|(sec_level, curve)| ImplInfo { secLevel: *sec_level, supportedCurve: *curve })
- .collect())
- }
-
- /// Deletes all attestation keys generated by the IRemotelyProvisionedComponent from the device,
- /// regardless of what state of the attestation key lifecycle they were in.
- pub fn delete_all_keys(&self) -> Result<i64> {
- DB.with::<_, Result<i64>>(|db| {
- let mut db = db.borrow_mut();
- db.delete_all_attestation_keys()
- })
- }
-}
-
-/// Populates the AttestationPoolStatus parcelable with information about how many
-/// certs will be expiring by the date provided in `expired_by` along with how many
-/// keys have not yet been assigned.
-pub fn get_pool_status(expired_by: i64, sec_level: SecurityLevel) -> Result<AttestationPoolStatus> {
- let (_, _, uuid) = get_keymint_device(&sec_level)?;
- DB.with::<_, Result<AttestationPoolStatus>>(|db| {
- let mut db = db.borrow_mut();
- // delete_expired_attestation_keys is always safe to call, and will remove anything
- // older than the date at the time of calling. No work should be done on the
- // attestation keys unless the pool status is checked first, so this call should be
- // enough to routinely clean out expired keys.
- db.delete_expired_attestation_keys()?;
- db.get_attestation_pool_status(expired_by, &uuid)
- })
-}
-
-/// Fetches a remote provisioning attestation key and certificate chain inside of the
-/// returned `CertificateChain` struct if one exists for the given caller_uid. If one has not
-/// been assigned, this function will assign it. If there are no signed attestation keys
-/// available to be assigned, it will return the ResponseCode `OUT_OF_KEYS_TRANSIENT_ERROR`
-fn get_rem_prov_attest_key(
- domain: Domain,
- caller_uid: u32,
- db: &mut KeystoreDB,
- km_uuid: &Uuid,
-) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
- match domain {
- Domain::APP => {
- // Attempt to get an Attestation Key once. If it fails, then the app doesn't
- // have a valid chain assigned to it. The helper function will return None after
- // attempting to assign a key. An error will be thrown if the pool is simply out
- // of usable keys. Then another attempt to fetch the just-assigned key will be
- // made. If this fails too, something is very wrong.
- get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid)
- .context("In get_rem_prov_attest_key: Failed to get a key")?
- .map_or_else(
- || get_rem_prov_attest_key_helper(domain, caller_uid, db, km_uuid),
- |v| Ok(Some(v)),
- )
- .context(ks_err!(
- "Failed to get a key after \
- attempting to assign one.",
- ))?
- .map_or_else(
- || {
- Err(Error::sys()).context(ks_err!(
- "Attempted to assign a \
- key and failed silently. Something is very wrong.",
- ))
- },
- |(guard, cert_chain)| Ok(Some((guard, cert_chain))),
- )
- }
- _ => Ok(None),
- }
-}
-
-/// Returns None if an AttestationKey fails to be assigned. Errors if no keys are available.
-fn get_rem_prov_attest_key_helper(
- domain: Domain,
- caller_uid: u32,
- db: &mut KeystoreDB,
- km_uuid: &Uuid,
-) -> Result<Option<(KeyIdGuard, CertificateChain)>> {
- let guard_and_chain = db
- .retrieve_attestation_key_and_cert_chain(domain, caller_uid as i64, km_uuid)
- .context(ks_err!("Failed to retrieve a key + cert chain"))?;
- match guard_and_chain {
- Some((guard, cert_chain)) => Ok(Some((guard, cert_chain))),
- // Either this app needs to be assigned a key, or the pool is empty. An error will
- // be thrown if there is no key available to assign. This will indicate that the app
- // should be nudged to provision more keys so keystore can retry.
- None => {
- db.assign_attestation_key(domain, caller_uid as i64, km_uuid)
- .context(ks_err!("Failed to assign a key"))?;
- Ok(None)
- }
- }
-}
-
-impl binder::Interface for RemoteProvisioningService {}
-
-// Implementation of IRemoteProvisioning. See AIDL spec at
-// :aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
-impl IRemoteProvisioning for RemoteProvisioningService {
- fn getPoolStatus(
- &self,
- expired_by: i64,
- sec_level: SecurityLevel,
- ) -> binder::Result<AttestationPoolStatus> {
- let _wp = wd::watch_millis("IRemoteProvisioning::getPoolStatus", 500);
- map_or_log_err(get_pool_status(expired_by, sec_level), Ok)
- }
-
- fn generateCsr(
- &self,
- test_mode: bool,
- num_csr: i32,
- eek: &[u8],
- challenge: &[u8],
- sec_level: SecurityLevel,
- protected_data: &mut ProtectedData,
- device_info: &mut DeviceInfo,
- ) -> binder::Result<Vec<u8>> {
- let _wp = wd::watch_millis("IRemoteProvisioning::generateCsr", 500);
- map_or_log_err(
- self.generate_csr(
- test_mode,
- num_csr,
- eek,
- challenge,
- sec_level,
- protected_data,
- device_info,
- ),
- Ok,
- )
- }
-
- fn provisionCertChain(
- &self,
- public_key: &[u8],
- batch_cert: &[u8],
- certs: &[u8],
- expiration_date: i64,
- sec_level: SecurityLevel,
- ) -> binder::Result<()> {
- let _wp = wd::watch_millis("IRemoteProvisioning::provisionCertChain", 500);
- DB.with::<_, binder::Result<()>>(|db| {
- map_or_log_err(
- self.provision_cert_chain(
- &mut db.borrow_mut(),
- public_key,
- batch_cert,
- certs,
- expiration_date,
- sec_level,
- ),
- Ok,
- )
- })
- }
-
- fn generateKeyPair(&self, is_test_mode: bool, sec_level: SecurityLevel) -> binder::Result<()> {
- let _wp = wd::watch_millis("IRemoteProvisioning::generateKeyPair", 500);
- DB.with::<_, binder::Result<()>>(|db| {
- map_or_log_err(
- self.generate_key_pair(&mut db.borrow_mut(), is_test_mode, sec_level),
- Ok,
- )
- })
- }
-
- fn getImplementationInfo(&self) -> binder::Result<Vec<ImplInfo>> {
- let _wp = wd::watch_millis("IRemoteProvisioning::getSecurityLevels", 500);
- map_or_log_err(self.get_implementation_info(), Ok)
- }
-
- fn deleteAllKeys(&self) -> binder::Result<i64> {
- let _wp = wd::watch_millis("IRemoteProvisioning::deleteAllKeys", 500);
- map_or_log_err(self.delete_all_keys(), Ok)
- }
-}
-
-/// Implementation of the IRemotelyProvisionedKeyPool service.
-#[derive(Default)]
-pub struct RemotelyProvisionedKeyPoolService {
- unique_id_to_sec_level: HashMap<String, SecurityLevel>,
-}
-
-impl RemotelyProvisionedKeyPoolService {
- /// Fetches a remotely provisioned certificate chain and key for the given client uid that
- /// was provisioned using the IRemotelyProvisionedComponent with the given id. The same key
- /// will be returned for a given caller_uid on every request. If there are no attestation keys
- /// available, `OUT_OF_KEYS_TRANSIENT_ERROR` is returned.
- fn get_attestation_key(
- &self,
- db: &mut KeystoreDB,
- caller_uid: i32,
- irpc_id: &str,
- ) -> Result<RemotelyProvisionedKey> {
- log::info!("get_attestation_key(self, {}, {}", caller_uid, irpc_id);
-
- let sec_level = self
- .unique_id_to_sec_level
- .get(irpc_id)
- .ok_or(Error::Rc(ResponseCode::INVALID_ARGUMENT))
- .context(format!("In get_attestation_key: unknown irpc id '{}'", irpc_id))?;
- let (_, _, km_uuid) = get_keymint_device(sec_level)?;
-
- let guard_and_cert_chain =
- get_rem_prov_attest_key(Domain::APP, caller_uid as u32, db, &km_uuid)
- .context(ks_err!())?;
- match guard_and_cert_chain {
- Some((_, chain)) => Ok(RemotelyProvisionedKey {
- keyBlob: chain.private_key.to_vec(),
- encodedCertChain: chain.cert_chain,
- }),
- // It should be impossible to get `None`, but handle it just in case as a
- // precaution against future behavioral changes in `get_rem_prov_attest_key`.
- None => Err(error::Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
- .context(ks_err!("No available attestation keys")),
- }
- }
-
- /// Creates a new instance of the remotely provisioned key pool service, used for fetching
- /// remotely provisioned attestation keys.
- pub fn new_native_binder() -> Result<Strong<dyn IRemotelyProvisionedKeyPool>> {
- let mut result: Self = Default::default();
-
- let dev = get_remotely_provisioned_component(&SecurityLevel::TRUSTED_ENVIRONMENT)
- .context(ks_err!("Failed to get TEE Remote Provisioner instance."))?;
- if let Some(id) = dev.getHardwareInfo()?.uniqueId {
- result.unique_id_to_sec_level.insert(id, SecurityLevel::TRUSTED_ENVIRONMENT);
- }
-
- if let Ok(dev) = get_remotely_provisioned_component(&SecurityLevel::STRONGBOX) {
- if let Some(id) = dev.getHardwareInfo()?.uniqueId {
- if result.unique_id_to_sec_level.contains_key(&id) {
- anyhow::bail!("In new_native_binder: duplicate irpc id found: '{}'", id)
- }
- result.unique_id_to_sec_level.insert(id, SecurityLevel::STRONGBOX);
- }
- }
-
- // If none of the remotely provisioned components have unique ids, then we shouldn't
- // bother publishing the service, as it's impossible to match keys with their backends.
- if result.unique_id_to_sec_level.is_empty() {
- anyhow::bail!(
- "In new_native_binder: No remotely provisioned components have unique ids"
- )
- }
-
- Ok(BnRemotelyProvisionedKeyPool::new_binder(
- result,
- BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
- ))
- }
-}
-
-impl binder::Interface for RemotelyProvisionedKeyPoolService {}
-
-// Implementation of IRemotelyProvisionedKeyPool. See AIDL spec at
-// :aidl/android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.aidl
-impl IRemotelyProvisionedKeyPool for RemotelyProvisionedKeyPoolService {
- fn getAttestationKey(
- &self,
- caller_uid: i32,
- irpc_id: &str,
- ) -> binder::Result<RemotelyProvisionedKey> {
- let _wp = wd::watch_millis("IRemotelyProvisionedKeyPool::getAttestationKey", 500);
- map_or_log_err(check_keystore_permission(KeystorePerm::GetAttestationKey), Ok)?;
- DB.with::<_, binder::Result<RemotelyProvisionedKey>>(|db| {
- map_or_log_err(self.get_attestation_key(&mut db.borrow_mut(), caller_uid, irpc_id), Ok)
- })
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use serde_cbor::Value;
- use std::collections::BTreeMap;
- use std::sync::{Arc, Mutex};
- use android_hardware_security_rkp::aidl::android::hardware::security::keymint::{
- RpcHardwareInfo::RpcHardwareInfo,
- };
-
- #[derive(Default)]
- struct MockRemotelyProvisionedComponentValues {
- hw_info: RpcHardwareInfo,
- private_key: Vec<u8>,
- maced_public_key: Vec<u8>,
- }
-
- // binder::Interface requires the Send trait, so we have to use a Mutex even though the test
- // is single threaded.
- #[derive(Default)]
- struct MockRemotelyProvisionedComponent(Arc<Mutex<MockRemotelyProvisionedComponentValues>>);
-
- impl binder::Interface for MockRemotelyProvisionedComponent {}
-
- impl IRemotelyProvisionedComponent for MockRemotelyProvisionedComponent {
- fn getHardwareInfo(&self) -> binder::Result<RpcHardwareInfo> {
- Ok(self.0.lock().unwrap().hw_info.clone())
- }
-
- fn generateEcdsaP256KeyPair(
- &self,
- test_mode: bool,
- maced_public_key: &mut MacedPublicKey,
- ) -> binder::Result<Vec<u8>> {
- assert!(test_mode);
- maced_public_key.macedKey = self.0.lock().unwrap().maced_public_key.clone();
- Ok(self.0.lock().unwrap().private_key.clone())
- }
-
- fn generateCertificateRequest(
- &self,
- _test_mode: bool,
- _keys_to_sign: &[MacedPublicKey],
- _eek: &[u8],
- _challenge: &[u8],
- _device_info: &mut DeviceInfo,
- _protected_data: &mut ProtectedData,
- ) -> binder::Result<Vec<u8>> {
- Err(binder::StatusCode::INVALID_OPERATION.into())
- }
-
- fn generateCertificateRequestV2(
- &self,
- _keys_to_sign: &[MacedPublicKey],
- _challenge: &[u8],
- ) -> binder::Result<Vec<u8>> {
- Err(binder::StatusCode::INVALID_OPERATION.into())
- }
- }
-
- // Hard coded cert that can be parsed -- the content doesn't matter for testing, only that it's valid.
- fn get_fake_cert() -> Vec<u8> {
- vec![
- 0x30, 0x82, 0x01, 0xbb, 0x30, 0x82, 0x01, 0x61, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
- 0x14, 0x3a, 0xd5, 0x67, 0xce, 0xfe, 0x93, 0xe1, 0xea, 0xb7, 0xe4, 0xbf, 0x64, 0x19,
- 0xa4, 0x11, 0xe1, 0x87, 0x40, 0x20, 0x37, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
- 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
- 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
- 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
- 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
- 0x6c, 0x65, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x31, 0x30, 0x32, 0x32,
- 0x30, 0x38, 0x35, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x39, 0x30, 0x34, 0x32, 0x36, 0x32,
- 0x32, 0x30, 0x38, 0x35, 0x32, 0x5a, 0x30, 0x33, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
- 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x54, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
- 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
- 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f,
- 0x67, 0x6c, 0x65, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
- 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
- 0x00, 0x04, 0x1e, 0xac, 0x0c, 0xe0, 0x0d, 0xc5, 0x25, 0x84, 0x1b, 0xd2, 0x77, 0x2d,
- 0xe7, 0xba, 0xf1, 0xde, 0xa7, 0xf6, 0x39, 0x7f, 0x38, 0x91, 0xbf, 0xa4, 0x58, 0xf5,
- 0x62, 0x6b, 0xce, 0x06, 0xcf, 0xb9, 0x73, 0x91, 0x0d, 0x8a, 0x60, 0xa0, 0xc6, 0xa2,
- 0x22, 0xe6, 0x51, 0x2e, 0x58, 0xd6, 0x43, 0x02, 0x80, 0x43, 0x44, 0x29, 0x38, 0x9a,
- 0x99, 0xf3, 0xa4, 0xdd, 0xd0, 0xb4, 0x6f, 0x8b, 0x44, 0x2d, 0xa3, 0x53, 0x30, 0x51,
- 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdb, 0x13, 0x68,
- 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe, 0x42, 0x3c, 0xd9, 0x3f, 0x1a,
- 0x33, 0xe9, 0xaa, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
- 0x80, 0x14, 0xdb, 0x13, 0x68, 0xe0, 0x0e, 0x47, 0x10, 0xf8, 0xcb, 0x88, 0x83, 0xfe,
- 0x42, 0x3c, 0xd9, 0x3f, 0x1a, 0x33, 0xe9, 0xaa, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d,
- 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06,
- 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
- 0x02, 0x20, 0x10, 0xdf, 0x40, 0xc3, 0x20, 0x54, 0x36, 0xb5, 0xc9, 0x3c, 0x70, 0xe3,
- 0x55, 0x37, 0xd2, 0x04, 0x51, 0xeb, 0x0f, 0x18, 0x83, 0xd0, 0x58, 0xa1, 0x08, 0x77,
- 0x8d, 0x4d, 0xa4, 0x20, 0xee, 0x33, 0x02, 0x21, 0x00, 0x8d, 0xe3, 0xa6, 0x6c, 0x0d,
- 0x86, 0x25, 0xdc, 0x59, 0x0d, 0x21, 0x43, 0x22, 0x3a, 0xb9, 0xa1, 0x73, 0x28, 0xc9,
- 0x16, 0x9e, 0x91, 0x15, 0xc4, 0xc3, 0xd7, 0xeb, 0xe5, 0xce, 0xdc, 0x1c, 0x1b,
- ]
- }
-
- // Generate a fake COSE_Mac0 with a key that's just `byte` repeated
- fn generate_maced_pubkey(byte: u8) -> Vec<u8> {
- vec![
- 0x84, 0x43, 0xA1, 0x01, 0x05, 0xA0, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20,
- 0x01, 0x21, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
- byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
- byte, byte, byte, byte, byte, byte, byte, byte, 0x22, 0x58, 0x20, byte, byte, byte,
- byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
- byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
- byte, 0x58, 0x20, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
- byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte, byte,
- byte, byte, byte, byte, byte, byte, byte,
- ]
- }
-
- #[test]
- fn test_parse_cose_mac0_for_coords_raw_bytes() -> Result<()> {
- let cose_mac0: Vec<u8> = vec![
- 0x84, 0x01, 0x02, 0x58, 0x4D, 0xA5, 0x01, 0x02, 0x03, 0x26, 0x20, 0x01, 0x21, 0x58,
- 0x20, 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9,
- 0x21, 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C,
- 0x43, 0x22, 0xC8, 0xEE, 0x03, 0x22, 0x58, 0x20, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95,
- 0x90, 0xA7, 0x5C, 0x5A, 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A,
- 0xA3, 0xB3, 0x1A, 0xB4, 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC, 0x03,
- ];
- let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&cose_mac0)?;
- assert_eq!(
- raw_key,
- vec![
- 0x1A, 0xFB, 0xB2, 0xD9, 0x9D, 0xF6, 0x2D, 0xF0, 0xC3, 0xA8, 0xFC, 0x7E, 0xC9, 0x21,
- 0x26, 0xED, 0xB5, 0x4A, 0x98, 0x9B, 0xF3, 0x0D, 0x91, 0x3F, 0xC6, 0x42, 0x5C, 0x43,
- 0x22, 0xC8, 0xEE, 0x03, 0x40, 0xB3, 0x9B, 0xFC, 0x47, 0x95, 0x90, 0xA7, 0x5C, 0x5A,
- 0x16, 0x31, 0x34, 0xAF, 0x0C, 0x5B, 0xF2, 0xB2, 0xD8, 0x2A, 0xA3, 0xB3, 0x1A, 0xB4,
- 0x4C, 0xA6, 0x3B, 0xE7, 0x22, 0xEC, 0x41, 0xDC,
- ]
- );
- Ok(())
- }
-
- #[test]
- fn test_parse_cose_mac0_for_coords_constructed_mac() -> Result<()> {
- let x_coord: Vec<u8> = vec![0; 32];
- let y_coord: Vec<u8> = vec![1; 32];
- let mut expected_key: Vec<u8> = Vec::new();
- expected_key.extend(&x_coord);
- expected_key.extend(&y_coord);
- let key_map: BTreeMap<Value, Value> = BTreeMap::from([
- (Value::Integer(1), Value::Integer(2)),
- (Value::Integer(3), Value::Integer(-7)),
- (Value::Integer(-1), Value::Integer(1)),
- (Value::Integer(-2), Value::Bytes(x_coord)),
- (Value::Integer(-3), Value::Bytes(y_coord)),
- ]);
- let cose_mac0: Vec<Value> = vec![
- Value::Integer(0),
- Value::Integer(1),
- Value::from(serde_cbor::to_vec(&key_map)?),
- Value::Integer(2),
- ];
- let raw_key = RemoteProvisioningService::parse_cose_mac0_for_coords(&serde_cbor::to_vec(
- &Value::from(cose_mac0),
- )?)?;
- assert_eq!(expected_key, raw_key);
- Ok(())
- }
-
- #[test]
- fn test_extract_payload_from_cose_mac() -> Result<()> {
- let key_map = Value::Map(BTreeMap::from([(Value::Integer(1), Value::Integer(2))]));
- let payload = Value::Bytes(serde_cbor::to_vec(&key_map)?);
- let cose_mac0 =
- Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
- let extracted_map = RemoteProvisioningService::extract_payload_from_cose_mac(
- &serde_cbor::to_vec(&cose_mac0)?,
- )?;
- assert_eq!(key_map, extracted_map);
- Ok(())
- }
-
- #[test]
- fn test_extract_payload_from_cose_mac_fails_malformed_payload() -> Result<()> {
- let payload = Value::Bytes(vec![5; 10]);
- let cose_mac0 =
- Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
- let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
- &serde_cbor::to_vec(&cose_mac0)?,
- );
- assert!(extracted_payload.is_err());
- Ok(())
- }
-
- #[test]
- fn test_extract_payload_from_cose_mac_fails_type() -> Result<()> {
- let payload = Value::Integer(1);
- let cose_mac0 =
- Value::Array(vec![Value::Integer(0), Value::Integer(1), payload, Value::Integer(3)]);
- let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
- &serde_cbor::to_vec(&cose_mac0)?,
- );
- assert!(extracted_payload.is_err());
- Ok(())
- }
-
- #[test]
- fn test_extract_payload_from_cose_mac_fails_length() -> Result<()> {
- let cose_mac0 = Value::Array(vec![Value::Integer(0), Value::Integer(1)]);
- let extracted_payload = RemoteProvisioningService::extract_payload_from_cose_mac(
- &serde_cbor::to_vec(&cose_mac0)?,
- );
- assert!(extracted_payload.is_err());
- Ok(())
- }
-
- #[test]
- #[ignore] // b/215746308
- fn test_get_attestation_key_no_keys_provisioned() {
- let mut db = crate::database::tests::new_test_db().unwrap();
- let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
- mock_rpc.0.lock().unwrap().hw_info.uniqueId = Some(String::from("mallory"));
-
- let mut service: RemotelyProvisionedKeyPoolService = Default::default();
- service
- .unique_id_to_sec_level
- .insert(String::from("mallory"), SecurityLevel::TRUSTED_ENVIRONMENT);
-
- assert_eq!(
- service
- .get_attestation_key(&mut db, 0, "mallory")
- .unwrap_err()
- .downcast::<error::Error>()
- .unwrap(),
- error::Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
- );
- }
-
- #[test]
- #[ignore] // b/215746308
- fn test_get_attestation_key() {
- let mut db = crate::database::tests::new_test_db().unwrap();
- let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
- let irpc_id = "paul";
- let caller_uid = 0;
-
- let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
- let mock_values = mock_rpc.0.clone();
- let mut remote_provisioning: RemoteProvisioningService = Default::default();
- remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
- let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
- key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
-
- mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
- mock_values.lock().unwrap().private_key = vec![8, 6, 7, 5, 3, 0, 9];
- mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
- remote_provisioning.generate_key_pair(&mut db, true, sec_level).unwrap();
-
- let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
- mock_values.lock().unwrap().maced_public_key.as_slice(),
- )
- .unwrap();
- let batch_cert = get_fake_cert();
- let certs = &[5, 6, 7, 8];
- assert!(remote_provisioning
- .provision_cert_chain(
- &mut db,
- public_key.as_slice(),
- batch_cert.as_slice(),
- certs,
- 0,
- sec_level
- )
- .is_ok());
-
- // ensure we got the key we expected
- let first_key = key_pool
- .get_attestation_key(&mut db, caller_uid, irpc_id)
- .context("get first key")
- .unwrap();
- assert_eq!(first_key.keyBlob, mock_values.lock().unwrap().private_key);
- assert_eq!(first_key.encodedCertChain, certs);
-
- // ensure that multiple calls get the same key
- assert_eq!(
- first_key,
- key_pool
- .get_attestation_key(&mut db, caller_uid, irpc_id)
- .context("get second key")
- .unwrap()
- );
-
- // no more keys for new clients
- assert_eq!(
- key_pool
- .get_attestation_key(&mut db, caller_uid + 1, irpc_id)
- .unwrap_err()
- .downcast::<error::Error>()
- .unwrap(),
- error::Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
- );
- }
-
- #[test]
- #[ignore] // b/215746308
- fn test_get_attestation_key_gets_different_key_for_different_client() {
- let mut db = crate::database::tests::new_test_db().unwrap();
- let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
- let irpc_id = "ringo";
- let first_caller = 0;
- let second_caller = first_caller + 1;
-
- let mock_rpc = Box::<MockRemotelyProvisionedComponent>::default();
- let mock_values = mock_rpc.0.clone();
- let mut remote_provisioning: RemoteProvisioningService = Default::default();
- remote_provisioning.device_by_sec_level.insert(sec_level, Strong::new(mock_rpc));
- let mut key_pool: RemotelyProvisionedKeyPoolService = Default::default();
- key_pool.unique_id_to_sec_level.insert(String::from(irpc_id), sec_level);
-
- // generate two distinct keys and provision them with certs
- mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
- mock_values.lock().unwrap().private_key = vec![3, 1, 4, 1, 5];
- mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x11);
- assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
- let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
- mock_values.lock().unwrap().maced_public_key.as_slice(),
- )
- .unwrap();
- assert!(remote_provisioning
- .provision_cert_chain(
- &mut db,
- public_key.as_slice(),
- get_fake_cert().as_slice(),
- &[1],
- 0,
- sec_level
- )
- .is_ok());
-
- mock_values.lock().unwrap().hw_info.uniqueId = Some(String::from(irpc_id));
- mock_values.lock().unwrap().private_key = vec![9, 0, 2, 1, 0];
- mock_values.lock().unwrap().maced_public_key = generate_maced_pubkey(0x22);
- assert!(remote_provisioning.generate_key_pair(&mut db, true, sec_level).is_ok());
- let public_key = RemoteProvisioningService::parse_cose_mac0_for_coords(
- mock_values.lock().unwrap().maced_public_key.as_slice(),
- )
- .unwrap();
- assert!(remote_provisioning
- .provision_cert_chain(
- &mut db,
- public_key.as_slice(),
- get_fake_cert().as_slice(),
- &[2],
- 0,
- sec_level
- )
- .is_ok());
-
- // make sure each caller gets a distinct key
- assert_ne!(
- key_pool
- .get_attestation_key(&mut db, first_caller, irpc_id)
- .context("get first key")
- .unwrap(),
- key_pool
- .get_attestation_key(&mut db, second_caller, irpc_id)
- .context("get second key")
- .unwrap()
- );
-
- // repeated calls should return the same key for a given caller
- assert_eq!(
- key_pool
- .get_attestation_key(&mut db, first_caller, irpc_id)
- .context("first caller a")
- .unwrap(),
- key_pool
- .get_attestation_key(&mut db, first_caller, irpc_id)
- .context("first caller b")
- .unwrap(),
- );
-
- assert_eq!(
- key_pool
- .get_attestation_key(&mut db, second_caller, irpc_id)
- .context("second caller a")
- .unwrap(),
- key_pool
- .get_attestation_key(&mut db, second_caller, irpc_id)
- .context("second caller b")
- .unwrap()
- );
- }
-}
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index cc1f816..5eed37c 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -583,40 +583,6 @@
)
.context(ks_err!("Using user generated attestation key."))
.map(|(result, _)| result),
- Some(AttestationKeyInfo::RemoteProvisioned {
- key_id_guard,
- attestation_key,
- attestation_certs,
- }) => self
- .upgrade_keyblob_if_required_with(
- &*self.keymint,
- Some(key_id_guard),
- &KeyBlob::Ref(&attestation_key.keyBlob),
- Some(self.rem_prov_state.get_uuid()),
- &[],
- |blob| {
- map_km_error({
- let _wp = self.watch_millis(
- concat!(
- "In KeystoreSecurityLevel::generate_key (RemoteProvisioned): ",
- "calling generate_key.",
- ),
- 5000, // Generate can take a little longer.
- );
- let dynamic_attest_key = Some(AttestationKey {
- keyBlob: blob.to_vec(),
- attestKeyParams: vec![],
- issuerSubjectName: attestation_key.issuerSubjectName.clone(),
- });
- self.keymint.generateKey(¶ms, dynamic_attest_key.as_ref())
- })
- },
- )
- .context(ks_err!("While generating Key with remote provisioned attestation key."))
- .map(|(mut result, _)| {
- result.certificateChain.push(attestation_certs);
- result
- }),
Some(AttestationKeyInfo::RkpdProvisioned { attestation_key, attestation_certs }) => {
self.upgrade_rkpd_keyblob_if_required_with(&attestation_key.keyBlob, &[], |blob| {
map_km_error({
diff --git a/keystore2/src/shared_secret_negotiation.rs b/keystore2/src/shared_secret_negotiation.rs
index 81644ec..739f4ba 100644
--- a/keystore2/src/shared_secret_negotiation.rs
+++ b/keystore2/src/shared_secret_negotiation.rs
@@ -23,7 +23,8 @@
};
use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
use anyhow::Result;
-use keystore2_vintf::{get_aidl_instances, get_hidl_instances};
+use binder::get_declared_instances;
+use keystore2_vintf::get_hidl_instances;
use std::fmt::{self, Display, Formatter};
use std::time::Duration;
@@ -111,6 +112,8 @@
static KEYMASTER_INTERFACE_NAME: &str = "IKeymasterDevice";
static SHARED_SECRET_PACKAGE_NAME: &str = "android.hardware.security.sharedsecret";
static SHARED_SECRET_INTERFACE_NAME: &str = "ISharedSecret";
+static SHARED_SECRET_PACKAGE_AND_INTERFACE_NAME: &str =
+ "android.hardware.security.sharedsecret.ISharedSecret";
static COMPAT_PACKAGE_NAME: &str = "android.security.compat";
/// Lists participants.
@@ -141,7 +144,8 @@
.collect::<Vec<SharedSecretParticipant>>()
})
.chain({
- get_aidl_instances(SHARED_SECRET_PACKAGE_NAME, 1, SHARED_SECRET_INTERFACE_NAME)
+ get_declared_instances(SHARED_SECRET_PACKAGE_AND_INTERFACE_NAME)
+ .unwrap()
.into_iter()
.map(SharedSecretParticipant::Aidl)
.collect::<Vec<_>>()
diff --git a/keystore2/src/vintf/lib.rs b/keystore2/src/vintf/lib.rs
index 08384bd..5bb015f 100644
--- a/keystore2/src/vintf/lib.rs
+++ b/keystore2/src/vintf/lib.rs
@@ -27,10 +27,6 @@
minor_version: usize,
interface_name: &str,
) -> Vec<String>;
-
- /// Gets the instances of the given package, version, and interface tuple.
- /// Note that this is not a zero-cost shim: it will make copies of the strings.
- fn get_aidl_instances(package: &str, version: usize, interface_name: &str) -> Vec<String>;
}
}
diff --git a/keystore2/src/vintf/vintf.cpp b/keystore2/src/vintf/vintf.cpp
index a550b10..bf77f5e 100644
--- a/keystore2/src/vintf/vintf.cpp
+++ b/keystore2/src/vintf/vintf.cpp
@@ -34,11 +34,3 @@
static_cast<std::string>(interfaceName));
return convert(names);
}
-
-rust::Vec<rust::String> get_aidl_instances(rust::Str package, size_t version,
- rust::Str interfaceName) {
- const auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
- const auto names = manifest->getAidlInstances(static_cast<std::string>(package), version,
- static_cast<std::string>(interfaceName));
- return convert(names);
-}
diff --git a/keystore2/src/vintf/vintf.hpp b/keystore2/src/vintf/vintf.hpp
index c4a7ef6..ef1e788 100644
--- a/keystore2/src/vintf/vintf.hpp
+++ b/keystore2/src/vintf/vintf.hpp
@@ -20,5 +20,3 @@
rust::Vec<rust::String> get_hidl_instances(rust::Str package, size_t major_version,
size_t minor_version, rust::Str interfaceName);
-rust::Vec<rust::String> get_aidl_instances(rust::Str package, size_t version,
- rust::Str interfaceName);
diff --git a/prng_seeder/OWNERS b/prng_seeder/OWNERS
index 9202b90..51b7f38 100644
--- a/prng_seeder/OWNERS
+++ b/prng_seeder/OWNERS
@@ -1,2 +1,2 @@
paulcrowley@google.com
-prb@google.com
\ No newline at end of file
+prb@google.com
diff --git a/prng_seeder/src/conditioner.rs b/prng_seeder/src/conditioner.rs
index eca8af8..ec1181b 100644
--- a/prng_seeder/src/conditioner.rs
+++ b/prng_seeder/src/conditioner.rs
@@ -12,11 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use std::{fs::File, io::Read, os::unix::io::AsRawFd};
+use std::{fs::File, io::Read};
use anyhow::{ensure, Context, Result};
use log::debug;
-use nix::fcntl::{fcntl, FcntlArg::F_SETFL, OFlag};
use tokio::io::AsyncReadExt;
use crate::drbg;
@@ -34,8 +33,6 @@
let mut et: drbg::Entropy = [0; drbg::ENTROPY_LEN];
hwrng.read_exact(&mut et).context("hwrng.read_exact in new")?;
let rg = drbg::Drbg::new(&et)?;
- fcntl(hwrng.as_raw_fd(), F_SETFL(OFlag::O_NONBLOCK))
- .context("setting O_NONBLOCK on hwrng")?;
Ok(ConditionerBuilder { hwrng, rg })
}