Use ro.keystore.boot_level_key.strategy
Choose the strategy for generating the boot level key from a property,
if present, instead of looking at KM versions.
Bug: 241241178
Test: set property on Cuttlefish, check logs for strategy used.
Change-Id: I2c7a6fb2c6471ab4a7cb7f650791930f41068bfa
diff --git a/keystore2/src/boot_level_keys.rs b/keystore2/src/boot_level_keys.rs
index 6320c7b..237d7d2 100644
--- a/keystore2/src/boot_level_keys.rs
+++ b/keystore2/src/boot_level_keys.rs
@@ -39,7 +39,58 @@
EarlyBootOnly,
}
+/// Generally the L0 KM and strategy are chosen by probing KM versions in TEE and Strongbox.
+/// However, once a device is launched the KM and strategy must never change, even if the
+/// KM version in TEE or Strongbox is updated. Setting this property at build time using
+/// `PRODUCT_VENDOR_PROPERTIES` means that the strategy can be fixed no matter what versions
+/// of KM are present.
+const PROPERTY_NAME: &str = "ro.keystore.boot_level_key.strategy";
+
+fn lookup_level_zero_km_and_strategy() -> Result<Option<(SecurityLevel, DenyLaterStrategy)>> {
+ let property_val = rustutils::system_properties::read(PROPERTY_NAME).with_context(|| {
+ format!("In lookup_level_zero_km_and_strategy: property read failed: {}", PROPERTY_NAME)
+ })?;
+ // TODO: use feature(let_else) when that's stabilized.
+ let property_val = if let Some(p) = property_val {
+ p
+ } else {
+ log::info!("{} not set, inferring from installed KM instances", PROPERTY_NAME);
+ return Ok(None);
+ };
+ let (level, strategy) = if let Some(c) = property_val.split_once(':') {
+ c
+ } else {
+ log::error!("Missing colon in {}: {:?}", PROPERTY_NAME, property_val);
+ return Ok(None);
+ };
+ let level = match level {
+ "TRUSTED_ENVIRONMENT" => SecurityLevel::TRUSTED_ENVIRONMENT,
+ "STRONGBOX" => SecurityLevel::STRONGBOX,
+ _ => {
+ log::error!("Unknown security level in {}: {:?}", PROPERTY_NAME, level);
+ return Ok(None);
+ }
+ };
+ let strategy = match strategy {
+ "EARLY_BOOT_ONLY" => DenyLaterStrategy::EarlyBootOnly,
+ "MAX_USES_PER_BOOT" => DenyLaterStrategy::MaxUsesPerBoot,
+ _ => {
+ log::error!("Unknown DenyLaterStrategy in {}: {:?}", PROPERTY_NAME, strategy);
+ return Ok(None);
+ }
+ };
+ log::info!("Set from {}: {}", PROPERTY_NAME, property_val);
+ Ok(Some((level, strategy)))
+}
+
fn get_level_zero_key_km_and_strategy() -> Result<(KeyMintDevice, DenyLaterStrategy)> {
+ if let Some((level, strategy)) = lookup_level_zero_km_and_strategy()? {
+ return Ok((
+ KeyMintDevice::get(level)
+ .context("In get_level_zero_key_km_and_strategy: Get KM instance failed.")?,
+ strategy,
+ ));
+ }
let tee = KeyMintDevice::get(SecurityLevel::TRUSTED_ENVIRONMENT)
.context("In get_level_zero_key_km_and_strategy: Get TEE instance failed.")?;
if tee.version() >= KeyMintDevice::KEY_MASTER_V4_1 {