Keystore 2.0: Use preferred KM instance for level zero key.
Prefer KM4.1 and higher over KM4.0 and lower, but prefer TEE over
Strongbox if TEE meets the minimal requirements.
Ignore-AOSP-First: No automerge path from AOSP.
Bug: 187862706
Test: Manually tested by observing logs during boot.
Merged-In: I1d27c80ef7c869b84b6d0c1a5d8eec287c242f6c
Change-Id: I1d27c80ef7c869b84b6d0c1a5d8eec287c242f6c
Merged-In: I1d27c80ef7c869b84b6d0c1a5d8eec287c242f6c
diff --git a/keystore2/src/boot_level_keys.rs b/keystore2/src/boot_level_keys.rs
index 3084195..5b7c3c3 100644
--- a/keystore2/src/boot_level_keys.rs
+++ b/keystore2/src/boot_level_keys.rs
@@ -14,6 +14,7 @@
//! Offer keys based on the "boot level" for superencryption.
+use crate::{database::KeystoreDB, key_parameter::KeyParameterValue, raw_device::KeyMintDevice};
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Algorithm::Algorithm, Digest::Digest, KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
};
@@ -21,26 +22,46 @@
use keystore2_crypto::{hkdf_expand, ZVec, AES_256_KEY_LENGTH};
use std::{collections::VecDeque, convert::TryFrom};
-use crate::{database::KeystoreDB, key_parameter::KeyParameterValue, raw_device::KeyMintDevice};
+fn get_preferred_km_instance_for_level_zero_key() -> Result<KeyMintDevice> {
+ let tee = KeyMintDevice::get(SecurityLevel::TRUSTED_ENVIRONMENT)
+ .context("In get_preferred_km_instance_for_level_zero_key: Get TEE instance failed.")?;
+ if tee.version() >= KeyMintDevice::KEY_MASTER_V4_1 {
+ Ok(tee)
+ } else {
+ match KeyMintDevice::get_or_none(SecurityLevel::STRONGBOX).context(
+ "In get_preferred_km_instance_for_level_zero_key: Get Strongbox instance failed.",
+ )? {
+ Some(strongbox) if strongbox.version() >= KeyMintDevice::KEY_MASTER_V4_1 => {
+ Ok(strongbox)
+ }
+ _ => Ok(tee),
+ }
+ }
+}
/// This is not thread safe; caller must hold a lock before calling.
/// In practice the caller is SuperKeyManager and the lock is the
/// Mutex on its internal state.
pub fn get_level_zero_key(db: &mut KeystoreDB) -> Result<ZVec> {
+ let km_dev = get_preferred_km_instance_for_level_zero_key()
+ .context("In get_level_zero_key: get preferred KM instance failed")?;
+
let key_desc = KeyMintDevice::internal_descriptor("boot_level_key".to_string());
- let params = [
+ let mut params = vec![
KeyParameterValue::Algorithm(Algorithm::HMAC).into(),
KeyParameterValue::Digest(Digest::SHA_2_256).into(),
KeyParameterValue::KeySize(256).into(),
KeyParameterValue::MinMacLength(256).into(),
KeyParameterValue::KeyPurpose(KeyPurpose::SIGN).into(),
KeyParameterValue::NoAuthRequired.into(),
- KeyParameterValue::MaxUsesPerBoot(1).into(),
];
- // We use TRUSTED_ENVIRONMENT here because it is the authority on when
- // the device has rebooted.
- let km_dev: KeyMintDevice = KeyMintDevice::get(SecurityLevel::TRUSTED_ENVIRONMENT)
- .context("In get_level_zero_key: KeyMintDevice::get failed")?;
+
+ if km_dev.version() >= KeyMintDevice::KEY_MASTER_V4_1 {
+ params.push(KeyParameterValue::EarlyBootOnly.into());
+ } else {
+ params.push(KeyParameterValue::MaxUsesPerBoot(1).into())
+ }
+
let (key_id_guard, key_entry) = km_dev
.lookup_or_generate_key(db, &key_desc, ¶ms)
.context("In get_level_zero_key: lookup_or_generate_key failed")?;