Keystore 2.0: Initialize all KeyMint instances.
Test: Strongbox CTS tests on Devices sporting Strongbox.
Bug: 173546020
Change-Id: Ief1983571c8a16979ed1e0ed7e4f636ab269ce8d
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index eff3196..d6c2ba4 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -16,10 +16,20 @@
//! database connections and connections to services that Keystore needs
//! to talk to.
-use crate::database::KeystoreDB;
use crate::super_key::SuperKeyManager;
+use crate::utils::Asp;
+use crate::{
+ database::KeystoreDB,
+ error::{map_binder_status_code, Error, ErrorCode},
+};
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+ IKeyMintDevice::IKeyMintDevice, SecurityLevel::SecurityLevel,
+};
+use anyhow::{Context, Result};
use lazy_static::lazy_static;
use std::cell::RefCell;
+use std::collections::HashMap;
+use std::sync::Mutex;
thread_local! {
/// Database connections are not thread safe, but connecting to the
@@ -40,4 +50,42 @@
lazy_static! {
/// Runtime database of unwrapped super keys.
pub static ref SUPER_KEY: SuperKeyManager = Default::default();
+ /// Map of KeyMint devices.
+ static ref KEY_MINT_DEVICES: Mutex<HashMap<SecurityLevel, Asp>> = Default::default();
+}
+
+static KEYMINT_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice";
+
+/// Make a new connection to a KeyMint device of the given security level.
+fn connect_keymint(security_level: SecurityLevel) -> Result<Asp> {
+ let service_name = match security_level {
+ SecurityLevel::TRUSTED_ENVIRONMENT => format!("{}/default", KEYMINT_SERVICE_NAME),
+ SecurityLevel::STRONGBOX => format!("{}/strongbox", KEYMINT_SERVICE_NAME),
+ _ => {
+ return Err(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
+ .context("In connect_keymint.")
+ }
+ };
+
+ let keymint: Box<dyn IKeyMintDevice> =
+ map_binder_status_code(binder::get_interface(&service_name))
+ .context("In connect_keymint: Trying to connect to genuine KeyMint service.")?;
+
+ Ok(Asp::new(keymint.as_binder()))
+}
+
+/// Get a keymint device for the given security level either from our cache or
+/// by making a new connection.
+pub fn get_keymint_device(security_level: SecurityLevel) -> Result<Asp> {
+ let mut devices_map = KEY_MINT_DEVICES.lock().unwrap();
+ if let Some(dev) = devices_map.get(&security_level) {
+ Ok(dev.clone())
+ } else {
+ let dev = connect_keymint(security_level).map_err(|e| {
+ anyhow::anyhow!(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
+ .context(format!("In get_keymint_device: {:?}", e))
+ })?;
+ devices_map.insert(security_level, dev.clone());
+ Ok(dev)
+ }
}