Keystore 2.0: Use secure clock service.
Test: CtsVerifier Fingerprint Bound Keys Test
Change-Id: Ia93794f7bcd9f5e26a4121a7bf689440fb1eeed4
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index 035dac1..3c79eed 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -80,12 +80,12 @@
pub static ref SUPER_KEY: SuperKeyManager = Default::default();
/// Map of KeyMint devices.
static ref KEY_MINT_DEVICES: Mutex<HashMap<SecurityLevel, Asp>> = Default::default();
+ /// Timestamp service.
+ static ref TIME_STAMP_DEVICE: Mutex<Option<Asp>> = Default::default();
/// A single on-demand worker thread that handles deferred tasks with two different
/// priorities.
pub static ref ASYNC_TASK: AsyncTask = Default::default();
/// Singeleton for enforcements.
- /// It is safe for this enforcements object to be called by multiple threads because the two
- /// data structures which maintain its state are protected by mutexes.
pub static ref ENFORCEMENTS: Enforcements = Enforcements::new();
/// Background task handler is initialized and exists globally.
/// The other modules (e.g. enforcements) communicate with it via a channel initialized during
@@ -142,11 +142,58 @@
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))
- })?;
+ let dev = connect_keymint(security_level).context("In get_keymint_device.")?;
devices_map.insert(security_level, dev.clone());
Ok(dev)
}
}
+
+static TIME_STAMP_SERVICE_NAME: &str = "android.hardware.security.secureclock.ISecureClock";
+
+/// Make a new connection to a secure clock service.
+/// If no native SecureClock device can be found brings up the compatibility service and attempts
+/// to connect to the legacy wrapper.
+fn connect_secureclock() -> Result<Asp> {
+ let secureclock = map_binder_status_code(binder::get_interface(TIME_STAMP_SERVICE_NAME))
+ .context("In connect_secureclock: Trying to connect to genuine secure clock service.")
+ .or_else(|e| {
+ match e.root_cause().downcast_ref::<Error>() {
+ Some(Error::BinderTransaction(StatusCode::NAME_NOT_FOUND)) => {
+ // This is a no-op if it was called before.
+ keystore2_km_compat::add_keymint_device_service();
+
+ let keystore_compat_service: Box<dyn IKeystoreCompatService> =
+ map_binder_status_code(binder::get_interface("android.security.compat"))
+ .context(
+ "In connect_secureclock: Trying to connect to compat service.",
+ )?;
+
+ // Legacy secure clock services were only implemented by TEE.
+ map_binder_status(keystore_compat_service.getSecureClock())
+ .map_err(|e| match e {
+ Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => {
+ Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)
+ }
+ e => e,
+ })
+ .context("In connect_secureclock: Trying to get Legacy wrapper.")
+ }
+ _ => Err(e),
+ }
+ })?;
+
+ Ok(Asp::new(secureclock.as_binder()))
+}
+
+/// Get the timestamp service that verifies auth token timeliness towards security levels with
+/// different clocks.
+pub fn get_timestamp_service() -> Result<Asp> {
+ let mut ts_device = TIME_STAMP_DEVICE.lock().unwrap();
+ if let Some(dev) = &*ts_device {
+ Ok(dev.clone())
+ } else {
+ let dev = connect_secureclock().context("In get_timestamp_service.")?;
+ *ts_device = Some(dev.clone());
+ Ok(dev)
+ }
+}