Merge "Keystore 2.0: Adding uuid field to persistent.keyentry"
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index 840fbc6..8e5507e 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -48,7 +48,7 @@
 use crate::permission::KeyPermSet;
 use crate::utils::get_current_time_in_seconds;
 use anyhow::{anyhow, Context, Result};
-use std::{convert::TryFrom, convert::TryInto, time::SystemTimeError};
+use std::{convert::TryFrom, convert::TryInto, ops::Deref, time::SystemTimeError};
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     HardwareAuthToken::HardwareAuthToken,
@@ -187,6 +187,50 @@
     }
 }
 
+/// Uuid representation that can be stored in the database.
+/// Right now it can only be initialized from SecurityLevel.
+/// Once KeyMint provides a UUID type a corresponding From impl shall be added.
+#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Uuid([u8; 16]);
+
+impl Deref for Uuid {
+    type Target = [u8; 16];
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl From<SecurityLevel> for Uuid {
+    fn from(sec_level: SecurityLevel) -> Self {
+        Self((sec_level.0 as u128).to_be_bytes())
+    }
+}
+
+impl ToSql for Uuid {
+    fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
+        self.0.to_sql()
+    }
+}
+
+impl FromSql for Uuid {
+    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
+        let blob = Vec::<u8>::column_result(value)?;
+        if blob.len() != 16 {
+            return Err(FromSqlError::OutOfRange(blob.len() as i64));
+        }
+        let mut arr = [0u8; 16];
+        arr.copy_from_slice(&blob);
+        Ok(Self(arr))
+    }
+}
+
+/// Key entries that are not associated with any KeyMint instance, such as pure certificate
+/// entries are associated with this UUID.
+pub static KEYSTORE_UUID: Uuid = Uuid([
+    0x41, 0xe3, 0xb9, 0xce, 0x27, 0x58, 0x4e, 0x91, 0xbc, 0xfd, 0xa5, 0x5d, 0x91, 0x85, 0xab, 0x11,
+]);
+
 /// Indicates how the sensitive part of this key blob is encrypted.
 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
 pub enum EncryptedBy {
@@ -435,6 +479,30 @@
     }
 }
 
+/// This type represents a certificate and certificate chain entry for a key.
+#[derive(Debug)]
+pub struct CertificateInfo {
+    cert: Option<Vec<u8>>,
+    cert_chain: Option<Vec<u8>>,
+}
+
+impl CertificateInfo {
+    /// Constructs a new CertificateInfo object from `cert` and `cert_chain`
+    pub fn new(cert: Option<Vec<u8>>, cert_chain: Option<Vec<u8>>) -> Self {
+        Self { cert, cert_chain }
+    }
+
+    /// Take the cert
+    pub fn take_cert(&mut self) -> Option<Vec<u8>> {
+        self.cert.take()
+    }
+
+    /// Take the cert chain
+    pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
+        self.cert_chain.take()
+    }
+}
+
 /// This type represents a Keystore 2.0 key entry.
 /// An entry has a unique `id` by which it can be found in the database.
 /// It has a security level field, key parameters, and three optional fields
@@ -445,7 +513,7 @@
     km_blob: Option<Vec<u8>>,
     cert: Option<Vec<u8>>,
     cert_chain: Option<Vec<u8>>,
-    sec_level: SecurityLevel,
+    km_uuid: Uuid,
     parameters: Vec<KeyParameter>,
     metadata: KeyMetaData,
     pure_cert: bool,
@@ -480,9 +548,9 @@
     pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
         self.cert_chain.take()
     }
-    /// Returns the security level of the key entry.
-    pub fn sec_level(&self) -> SecurityLevel {
-        self.sec_level
+    /// Returns the uuid of the owning KeyMint instance.
+    pub fn km_uuid(&self) -> &Uuid {
+        &self.km_uuid
     }
     /// Exposes the key parameters of this key entry.
     pub fn key_parameters(&self) -> &Vec<KeyParameter> {
@@ -641,7 +709,8 @@
                      domain INTEGER,
                      namespace INTEGER,
                      alias BLOB,
-                     state INTEGER);",
+                     state INTEGER,
+                     km_uuid BLOB);",
             NO_PARAMS,
         )
         .context("Failed to initialize \"keyentry\" table.")?;
@@ -830,6 +899,7 @@
         domain: Domain,
         namespace: i64,
         alias: &str,
+        km_uuid: Uuid,
         create_new_key: F,
     ) -> Result<(KeyIdGuard, KeyEntry)>
     where
@@ -876,9 +946,17 @@
                 let id = Self::insert_with_retry(|id| {
                     tx.execute(
                         "INSERT into persistent.keyentry
-                        (id, key_type, domain, namespace, alias, state)
-                        VALUES(?, ?, ?, ?, ?, ?);",
-                        params![id, KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live],
+                        (id, key_type, domain, namespace, alias, state, km_uuid)
+                        VALUES(?, ?, ?, ?, ?, ?, ?);",
+                        params![
+                            id,
+                            KeyType::Super,
+                            domain.0,
+                            namespace,
+                            alias,
+                            KeyLifeCycle::Live,
+                            km_uuid,
+                        ],
                     )
                 })
                 .context("In get_or_create_key_with.")?;
@@ -925,9 +1003,14 @@
     /// key artifacts, i.e., blobs and parameters have been associated with the new
     /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
     /// atomic even if key generation is not.
-    pub fn create_key_entry(&mut self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
+    pub fn create_key_entry(
+        &mut self,
+        domain: Domain,
+        namespace: i64,
+        km_uuid: &Uuid,
+    ) -> Result<KeyIdGuard> {
         self.with_transaction(TransactionBehavior::Immediate, |tx| {
-            Self::create_key_entry_internal(tx, domain, namespace)
+            Self::create_key_entry_internal(tx, domain, namespace, km_uuid)
         })
         .context("In create_key_entry.")
     }
@@ -936,6 +1019,7 @@
         tx: &Transaction,
         domain: Domain,
         namespace: i64,
+        km_uuid: &Uuid,
     ) -> Result<KeyIdGuard> {
         match domain {
             Domain::APP | Domain::SELINUX => {}
@@ -948,14 +1032,15 @@
             Self::insert_with_retry(|id| {
                 tx.execute(
                     "INSERT into persistent.keyentry
-                     (id, key_type, domain, namespace, alias, state)
-                     VALUES(?, ?, ?, ?, NULL, ?);",
+                     (id, key_type, domain, namespace, alias, state, km_uuid)
+                     VALUES(?, ?, ?, ?, NULL, ?, ?);",
                     params![
                         id,
                         KeyType::Client,
                         domain.0 as u32,
                         namespace,
-                        KeyLifeCycle::Existing
+                        KeyLifeCycle::Existing,
+                        km_uuid,
                     ],
                 )
             })
@@ -1105,7 +1190,7 @@
                     newid.0,
                     domain.0 as u32,
                     namespace,
-                    KeyLifeCycle::Existing
+                    KeyLifeCycle::Existing,
                 ],
             )
             .context("In rebind_alias: Failed to set alias.")?;
@@ -1128,9 +1213,9 @@
         key: KeyDescriptor,
         params: impl IntoIterator<Item = &'a KeyParameter>,
         blob: &[u8],
-        cert: Option<&[u8]>,
-        cert_chain: Option<&[u8]>,
+        cert_info: &CertificateInfo,
         metadata: &KeyMetaData,
+        km_uuid: &Uuid,
     ) -> Result<(bool, KeyIdGuard)> {
         let (alias, domain, namespace) = match key {
             KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None }
@@ -1143,15 +1228,15 @@
             }
         };
         self.with_transaction(TransactionBehavior::Immediate, |tx| {
-            let key_id = Self::create_key_entry_internal(tx, domain, namespace)
+            let key_id = Self::create_key_entry_internal(tx, domain, namespace, km_uuid)
                 .context("Trying to create new key entry.")?;
             Self::set_blob_internal(tx, key_id.id(), SubComponentType::KEY_BLOB, Some(blob))
                 .context("Trying to insert the key blob.")?;
-            if let Some(cert) = cert {
+            if let Some(cert) = &cert_info.cert {
                 Self::set_blob_internal(tx, key_id.id(), SubComponentType::CERT, Some(&cert))
                     .context("Trying to insert the certificate.")?;
             }
-            if let Some(cert_chain) = cert_chain {
+            if let Some(cert_chain) = &cert_info.cert_chain {
                 Self::set_blob_internal(
                     tx,
                     key_id.id(),
@@ -1173,7 +1258,12 @@
     /// Store a new certificate
     /// The function creates a new key entry, populates the blob field and metadata, and rebinds
     /// the given alias to the new cert.
-    pub fn store_new_certificate(&mut self, key: KeyDescriptor, cert: &[u8]) -> Result<KeyIdGuard> {
+    pub fn store_new_certificate(
+        &mut self,
+        key: KeyDescriptor,
+        cert: &[u8],
+        km_uuid: &Uuid,
+    ) -> Result<KeyIdGuard> {
         let (alias, domain, namespace) = match key {
             KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None }
             | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => {
@@ -1186,7 +1276,7 @@
             }
         };
         self.with_transaction(TransactionBehavior::Immediate, |tx| {
-            let key_id = Self::create_key_entry_internal(tx, domain, namespace)
+            let key_id = Self::create_key_entry_internal(tx, domain, namespace, km_uuid)
                 .context("Trying to create new key entry.")?;
 
             Self::set_blob_internal(tx, key_id.id(), SubComponentType::CERT_CHAIN, Some(cert))
@@ -1592,6 +1682,15 @@
         .context("In unbind_key.")
     }
 
+    fn get_key_km_uuid(tx: &Transaction, key_id: i64) -> Result<Uuid> {
+        tx.query_row(
+            "SELECT km_uuid FROM persistent.keyentry WHERE id = ?",
+            params![key_id],
+            |row| row.get(0),
+        )
+        .context("In get_key_km_uuid.")
+    }
+
     fn load_key_components(
         tx: &Transaction,
         load_bits: KeyEntryLoadBits,
@@ -1603,25 +1702,18 @@
             Self::load_blob_components(key_id, load_bits, &tx)
                 .context("In load_key_components.")?;
 
-        let parameters =
-            Self::load_key_parameters(key_id, &tx).context("In load_key_components.")?;
+        let parameters = Self::load_key_parameters(key_id, &tx)
+            .context("In load_key_components: Trying to load key parameters.")?;
 
-        // Extract the security level by checking the security level of the origin tag.
-        // Super keys don't have key parameters so we use security_level software by default.
-        let sec_level = parameters
-            .iter()
-            .find_map(|k| match k.get_tag() {
-                Tag::ORIGIN => Some(*k.security_level()),
-                _ => None,
-            })
-            .unwrap_or(SecurityLevel::SOFTWARE);
+        let km_uuid = Self::get_key_km_uuid(&tx, key_id)
+            .context("In load_key_components: Trying to get KM uuid.")?;
 
         Ok(KeyEntry {
             id: key_id,
             km_blob,
             cert: cert_blob,
             cert_chain: cert_chain_blob,
-            sec_level,
+            km_uuid,
             parameters,
             metadata,
             pure_cert: !has_km_blob,
@@ -2072,7 +2164,7 @@
         let temp_dir = TempDir::new("persistent_db_test")?;
         let mut db = KeystoreDB::new(temp_dir.path())?;
 
-        db.create_key_entry(Domain::APP, 100)?;
+        db.create_key_entry(Domain::APP, 100, &KEYSTORE_UUID)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 1);
 
@@ -2085,31 +2177,31 @@
 
     #[test]
     fn test_create_key_entry() -> Result<()> {
-        fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
-            (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
+        fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>, Uuid) {
+            (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref(), ke.km_uuid.unwrap())
         }
 
         let mut db = new_test_db()?;
 
-        db.create_key_entry(Domain::APP, 100)?;
-        db.create_key_entry(Domain::SELINUX, 101)?;
+        db.create_key_entry(Domain::APP, 100, &KEYSTORE_UUID)?;
+        db.create_key_entry(Domain::SELINUX, 101, &KEYSTORE_UUID)?;
 
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
-        assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
-        assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
+        assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None, KEYSTORE_UUID));
+        assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None, KEYSTORE_UUID));
 
         // Test that we must pass in a valid Domain.
         check_result_is_error_containing_string(
-            db.create_key_entry(Domain::GRANT, 102),
+            db.create_key_entry(Domain::GRANT, 102, &KEYSTORE_UUID),
             "Domain Domain(1) must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
-            db.create_key_entry(Domain::BLOB, 103),
+            db.create_key_entry(Domain::BLOB, 103, &KEYSTORE_UUID),
             "Domain Domain(3) must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
-            db.create_key_entry(Domain::KEY_ID, 104),
+            db.create_key_entry(Domain::KEY_ID, 104, &KEYSTORE_UUID),
             "Domain Domain(4) must be either App or SELinux.",
         );
 
@@ -2118,31 +2210,48 @@
 
     #[test]
     fn test_rebind_alias() -> Result<()> {
-        fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
-            (ke.domain, ke.namespace, ke.alias.as_deref())
+        fn extractor(
+            ke: &KeyEntryRow,
+        ) -> (Option<Domain>, Option<i64>, Option<&str>, Option<Uuid>) {
+            (ke.domain, ke.namespace, ke.alias.as_deref(), ke.km_uuid)
         }
 
         let mut db = new_test_db()?;
-        db.create_key_entry(Domain::APP, 42)?;
-        db.create_key_entry(Domain::APP, 42)?;
+        db.create_key_entry(Domain::APP, 42, &KEYSTORE_UUID)?;
+        db.create_key_entry(Domain::APP, 42, &KEYSTORE_UUID)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
-        assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
-        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
+        assert_eq!(
+            extractor(&entries[0]),
+            (Some(Domain::APP), Some(42), None, Some(KEYSTORE_UUID))
+        );
+        assert_eq!(
+            extractor(&entries[1]),
+            (Some(Domain::APP), Some(42), None, Some(KEYSTORE_UUID))
+        );
 
         // Test that the first call to rebind_alias sets the alias.
         rebind_alias(&mut db, &KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
-        assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
-        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
+        assert_eq!(
+            extractor(&entries[0]),
+            (Some(Domain::APP), Some(42), Some("foo"), Some(KEYSTORE_UUID))
+        );
+        assert_eq!(
+            extractor(&entries[1]),
+            (Some(Domain::APP), Some(42), None, Some(KEYSTORE_UUID))
+        );
 
         // Test that the second call to rebind_alias also empties the old one.
         rebind_alias(&mut db, &KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
-        assert_eq!(extractor(&entries[0]), (None, None, None));
-        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
+        assert_eq!(extractor(&entries[0]), (None, None, None, Some(KEYSTORE_UUID)));
+        assert_eq!(
+            extractor(&entries[1]),
+            (Some(Domain::APP), Some(42), Some("foo"), Some(KEYSTORE_UUID))
+        );
 
         // Test that we must pass in a valid Domain.
         check_result_is_error_containing_string(
@@ -2166,8 +2275,11 @@
         // Test that we correctly abort the transaction in this case.
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
-        assert_eq!(extractor(&entries[0]), (None, None, None));
-        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
+        assert_eq!(extractor(&entries[0]), (None, None, None, Some(KEYSTORE_UUID)));
+        assert_eq!(
+            extractor(&entries[1]),
+            (Some(Domain::APP), Some(42), Some("foo"), Some(KEYSTORE_UUID))
+        );
 
         Ok(())
     }
@@ -2180,9 +2292,9 @@
 
         let mut db = new_test_db()?;
         db.conn.execute(
-            "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias, state)
-                VALUES (1, 0, 0, 15, 'key', 1), (2, 0, 2, 7, 'yek', 1);",
-            NO_PARAMS,
+            "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias, state, km_uuid)
+                VALUES (1, 0, 0, 15, 'key', 1, ?), (2, 0, 2, 7, 'yek', 1, ?);",
+            params![KEYSTORE_UUID, KEYSTORE_UUID],
         )?;
         let app_key = KeyDescriptor {
             domain: super::Domain::APP,
@@ -2426,6 +2538,7 @@
                 blob: None,
             },
             TEST_CERT_BLOB,
+            &KEYSTORE_UUID,
         )
         .expect("Trying to insert cert.");
 
@@ -2965,6 +3078,7 @@
         namespace: Option<i64>,
         alias: Option<String>,
         state: KeyLifeCycle,
+        km_uuid: Option<Uuid>,
     }
 
     fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
@@ -2981,6 +3095,7 @@
                     namespace: row.get(3)?,
                     alias: row.get(4)?,
                     state: row.get(5)?,
+                    km_uuid: row.get(6)?,
                 })
             })?
             .map(|r| r.context("Could not read keyentry row."))
@@ -3223,7 +3338,7 @@
         alias: &str,
         max_usage_count: Option<i32>,
     ) -> Result<KeyIdGuard> {
-        let key_id = db.create_key_entry(domain, namespace)?;
+        let key_id = db.create_key_entry(domain, namespace, &KEYSTORE_UUID)?;
         db.set_blob(&key_id, SubComponentType::KEY_BLOB, Some(TEST_KEY_BLOB))?;
         db.set_blob(&key_id, SubComponentType::CERT, Some(TEST_CERT_BLOB))?;
         db.set_blob(&key_id, SubComponentType::CERT_CHAIN, Some(TEST_CERT_CHAIN_BLOB))?;
@@ -3255,7 +3370,7 @@
             km_blob: Some(TEST_KEY_BLOB.to_vec()),
             cert: Some(TEST_CERT_BLOB.to_vec()),
             cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
-            sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+            km_uuid: KEYSTORE_UUID,
             parameters: params,
             metadata,
             pure_cert: false,
@@ -3264,21 +3379,29 @@
 
     fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
         let mut stmt = db.conn.prepare(
-            "SELECT id, key_type, domain, namespace, alias, state FROM persistent.keyentry;",
+            "SELECT id, key_type, domain, namespace, alias, state, km_uuid FROM persistent.keyentry;",
         )?;
-        let rows = stmt.query_map::<(i64, KeyType, i32, i64, String, KeyLifeCycle), _, _>(
+        let rows = stmt.query_map::<(i64, KeyType, i32, i64, String, KeyLifeCycle, Uuid), _, _>(
             NO_PARAMS,
             |row| {
-                Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?, row.get(5)?))
+                Ok((
+                    row.get(0)?,
+                    row.get(1)?,
+                    row.get(2)?,
+                    row.get(3)?,
+                    row.get(4)?,
+                    row.get(5)?,
+                    row.get(6)?,
+                ))
             },
         )?;
 
         println!("Key entry table rows:");
         for r in rows {
-            let (id, key_type, domain, namespace, alias, state) = r.unwrap();
+            let (id, key_type, domain, namespace, alias, state, km_uuid) = r.unwrap();
             println!(
-                "    id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {} State: {:?}",
-                id, key_type, domain, namespace, alias, state
+                "    id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {} State: {:?} KmUuid: {:?}",
+                id, key_type, domain, namespace, alias, state, km_uuid
             );
         }
         Ok(())
diff --git a/keystore2/src/gc.rs b/keystore2/src/gc.rs
index b5bdd98..692cb7e 100644
--- a/keystore2/src/gc.rs
+++ b/keystore2/src/gc.rs
@@ -18,7 +18,7 @@
 //! optionally dispose of sensitive key material appropriately, and then delete
 //! the key entry from the database.
 
-use crate::globals::{get_keymint_device, DB};
+use crate::globals::{get_keymint_dev_by_uuid, DB};
 use crate::{error::map_km_error, globals::ASYNC_TASK};
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::IKeyMintDevice::IKeyMintDevice;
 use anyhow::Result;
@@ -42,7 +42,9 @@
             if let Some((key_id, mut key_entry)) = db.get_unreferenced_key()? {
                 if let Some(blob) = key_entry.take_km_blob() {
                     let km_dev: Box<dyn IKeyMintDevice> =
-                        get_keymint_device(key_entry.sec_level())?.get_interface()?;
+                        get_keymint_dev_by_uuid(key_entry.km_uuid())
+                            .map(|(dev, _)| dev)?
+                            .get_interface()?;
                     if let Err(e) = map_km_error(km_dev.deleteKey(&blob)) {
                         // Log but ignore error.
                         log::error!("Error trying to delete key. {:?}", e);
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index 50ec26c..c488a18 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -16,7 +16,6 @@
 //! database connections and connections to services that Keystore needs
 //! to talk to.
 
-use crate::enforcements::Enforcements;
 use crate::gc::Gc;
 use crate::legacy_blob::LegacyBlobLoader;
 use crate::super_key::SuperKeyManager;
@@ -24,9 +23,13 @@
 use crate::{async_task::AsyncTask, database::MonotonicRawTime};
 use crate::{
     database::KeystoreDB,
+    database::Uuid,
     error::{map_binder_status, map_binder_status_code, Error, ErrorCode},
 };
-use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
+use crate::{enforcements::Enforcements, error::map_km_error};
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    KeyMintHardwareInfo::KeyMintHardwareInfo, SecurityLevel::SecurityLevel,
+};
 use android_hardware_security_keymint::binder::StatusCode;
 use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
 use anyhow::{Context, Result};
@@ -77,11 +80,43 @@
             RefCell::new(create_thread_local_db());
 }
 
+#[derive(Default)]
+struct DevicesMap {
+    devices_by_uuid: HashMap<Uuid, (Asp, KeyMintHardwareInfo)>,
+    uuid_by_sec_level: HashMap<SecurityLevel, Uuid>,
+}
+
+impl DevicesMap {
+    fn dev_by_sec_level(
+        &self,
+        sec_level: &SecurityLevel,
+    ) -> Option<(Asp, KeyMintHardwareInfo, Uuid)> {
+        self.uuid_by_sec_level.get(sec_level).and_then(|uuid| self.dev_by_uuid(uuid))
+    }
+
+    fn dev_by_uuid(&self, uuid: &Uuid) -> Option<(Asp, KeyMintHardwareInfo, Uuid)> {
+        self.devices_by_uuid
+            .get(uuid)
+            .map(|(dev, hw_info)| ((*dev).clone(), (*hw_info).clone(), *uuid))
+    }
+
+    /// The requested security level and the security level of the actual implementation may
+    /// differ. So we map the requested security level to the uuid of the implementation
+    /// so that there cannot be any confusion as to which KeyMint instance is requested.
+    fn insert(&mut self, sec_level: SecurityLevel, dev: Asp, hw_info: KeyMintHardwareInfo) {
+        // For now we use the reported security level of the KM instance as UUID.
+        // TODO update this section once UUID was added to the KM hardware info.
+        let uuid: Uuid = sec_level.into();
+        self.devices_by_uuid.insert(uuid, (dev, hw_info));
+        self.uuid_by_sec_level.insert(sec_level, uuid);
+    }
+}
+
 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 ref KEY_MINT_DEVICES: Mutex<DevicesMap> = 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
@@ -100,8 +135,8 @@
 /// Make a new connection to a KeyMint device of the given security level.
 /// If no native KeyMint device can be found this function also brings
 /// up the compatibility service and attempts to connect to the legacy wrapper.
-fn connect_keymint(security_level: SecurityLevel) -> Result<Asp> {
-    let service_name = match security_level {
+fn connect_keymint(security_level: &SecurityLevel) -> Result<(Asp, KeyMintHardwareInfo)> {
+    let service_name = match *security_level {
         SecurityLevel::TRUSTED_ENVIRONMENT => format!("{}/default", KEYMINT_SERVICE_NAME),
         SecurityLevel::STRONGBOX => format!("{}/strongbox", KEYMINT_SERVICE_NAME),
         _ => {
@@ -121,32 +156,52 @@
                     let keystore_compat_service: Box<dyn IKeystoreCompatService> =
                         map_binder_status_code(binder::get_interface("android.security.compat"))
                             .context("In connect_keymint: Trying to connect to compat service.")?;
-                    map_binder_status(keystore_compat_service.getKeyMintDevice(security_level))
+                    map_binder_status(keystore_compat_service.getKeyMintDevice(*security_level))
                         .map_err(|e| match e {
                             Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => {
                                 Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)
                             }
                             e => e,
                         })
-                        .context("In connext_keymint: Trying to get Legacy wrapper.")
+                        .context("In connect_keymint: Trying to get Legacy wrapper.")
                 }
                 _ => Err(e),
             }
         })?;
 
-    Ok(Asp::new(keymint.as_binder()))
+    let hw_info = map_km_error(keymint.getHardwareInfo())
+        .context("In connect_keymint: Failed to get hardware info.")?;
+
+    Ok((Asp::new(keymint.as_binder()), hw_info))
 }
 
 /// 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> {
+/// by making a new connection. Returns the device, the hardware info and the uuid.
+/// TODO the latter can be removed when the uuid is part of the hardware info.
+pub fn get_keymint_device(
+    security_level: &SecurityLevel,
+) -> Result<(Asp, KeyMintHardwareInfo, Uuid)> {
     let mut devices_map = KEY_MINT_DEVICES.lock().unwrap();
-    if let Some(dev) = devices_map.get(&security_level) {
-        Ok(dev.clone())
+    if let Some((dev, hw_info, uuid)) = devices_map.dev_by_sec_level(&security_level) {
+        Ok((dev, hw_info, uuid))
     } else {
-        let dev = connect_keymint(security_level).context("In get_keymint_device.")?;
-        devices_map.insert(security_level, dev.clone());
-        Ok(dev)
+        let (dev, hw_info) = connect_keymint(security_level).context("In get_keymint_device.")?;
+        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())
+    }
+}
+
+/// Get a keymint device for the given uuid. This will only access the cache, but will not
+/// attempt to establish a new connection. It is assumed that the cache is already populated
+/// when this is called. This is a fair assumption, because service.rs iterates through all
+/// security levels when it gets instantiated.
+pub fn get_keymint_dev_by_uuid(uuid: &Uuid) -> Result<(Asp, KeyMintHardwareInfo)> {
+    let devices_map = KEY_MINT_DEVICES.lock().unwrap();
+    if let Some((dev, hw_info, _)) = devices_map.dev_by_uuid(uuid) {
+        Ok((dev, hw_info))
+    } else {
+        Err(Error::sys()).context("In get_keymint_dev_by_uuid: No KeyMint instance found.")
     }
 }
 
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 994b2c8..f6d8108 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -16,12 +16,12 @@
 
 //! This crate implements the IKeystoreSecurityLevel interface.
 
-use crate::gc::Gc;
+use crate::{database::Uuid, gc::Gc, globals::get_keymint_device};
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     Algorithm::Algorithm, HardwareAuthenticatorType::HardwareAuthenticatorType,
     IKeyMintDevice::IKeyMintDevice, KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat,
-    KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel,
-    Tag::Tag,
+    KeyMintHardwareInfo::KeyMintHardwareInfo, KeyParameter::KeyParameter,
+    KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel, Tag::Tag,
 };
 use android_system_keystore2::aidl::android::system::keystore2::{
     AuthenticatorSpec::AuthenticatorSpec, CreateOperationResponse::CreateOperationResponse,
@@ -35,7 +35,10 @@
 use crate::key_parameter::KeyParameter as KsKeyParam;
 use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
 use crate::utils::{check_key_permission, uid_to_android_user, Asp};
-use crate::{database::KeyIdGuard, globals::DB};
+use crate::{
+    database::{CertificateInfo, KeyIdGuard},
+    globals::DB,
+};
 use crate::{
     database::{DateTime, KeyMetaData, KeyMetaEntry, KeyType},
     permission::KeyPerm,
@@ -56,6 +59,9 @@
 pub struct KeystoreSecurityLevel {
     security_level: SecurityLevel,
     keymint: Asp,
+    #[allow(dead_code)]
+    hw_info: KeyMintHardwareInfo,
+    km_uuid: Uuid,
     operation_db: OperationDb,
 }
 
@@ -69,15 +75,18 @@
     /// we need it for checking keystore permissions.
     pub fn new_native_binder(
         security_level: SecurityLevel,
-    ) -> Result<impl IKeystoreSecurityLevel + Send> {
+    ) -> Result<(impl IKeystoreSecurityLevel + Send, Uuid)> {
+        let (dev, hw_info, km_uuid) = get_keymint_device(&security_level)
+            .context("In KeystoreSecurityLevel::new_native_binder.")?;
         let result = BnKeystoreSecurityLevel::new_binder(Self {
             security_level,
-            keymint: crate::globals::get_keymint_device(security_level)
-                .context("In KeystoreSecurityLevel::new_native_binder.")?,
+            keymint: dev,
+            hw_info,
+            km_uuid,
             operation_db: OperationDb::new(),
         });
         result.as_binder().set_requesting_sid(true);
-        Ok(result)
+        Ok((result, km_uuid))
     }
 
     fn store_new_key(
@@ -92,7 +101,7 @@
             certificateChain: mut certificate_chain,
         } = creation_result;
 
-        let (cert, cert_chain): (Option<Vec<u8>>, Option<Vec<u8>>) = (
+        let mut cert_info: CertificateInfo = CertificateInfo::new(
             match certificate_chain.len() {
                 0 => None,
                 _ => Some(certificate_chain.remove(0).encodedCertificate),
@@ -134,9 +143,9 @@
                             key,
                             &key_parameters,
                             &key_blob,
-                            cert.as_deref(),
-                            cert_chain.as_deref(),
+                            &cert_info,
                             &metadata,
+                            &self.km_uuid,
                         )
                         .context("In store_new_key.")?;
                     if need_gc {
@@ -154,8 +163,8 @@
         Ok(KeyMetadata {
             key,
             keySecurityLevel: self.security_level,
-            certificate: cert,
-            certificateChain: cert_chain,
+            certificate: cert_info.take_cert(),
+            certificateChain: cert_info.take_cert_chain(),
             authorizations: crate::utils::key_parameters_to_authorizations(key_parameters),
             modificationTimeMs: creation_date.to_millis_epoch(),
         })
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index e57a9b7..72671c6 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -18,14 +18,16 @@
 //! This crate implement the core Keystore 2.0 service API as defined by the Keystore 2.0
 //! AIDL spec.
 
-use crate::globals::DB;
-use crate::permission;
+use std::collections::HashMap;
+
 use crate::permission::{KeyPerm, KeystorePerm};
 use crate::security_level::KeystoreSecurityLevel;
 use crate::utils::{
     check_grant_permission, check_key_permission, check_keystore_permission,
     key_parameters_to_authorizations, Asp,
 };
+use crate::{database::Uuid, globals::DB};
+use crate::{database::KEYSTORE_UUID, permission};
 use crate::{
     database::{KeyEntryLoadBits, KeyType, SubComponentType},
     error::ResponseCode,
@@ -40,62 +42,76 @@
     IKeystoreService::BnKeystoreService, IKeystoreService::IKeystoreService,
     KeyDescriptor::KeyDescriptor, KeyEntryResponse::KeyEntryResponse, KeyMetadata::KeyMetadata,
 };
-use anyhow::{anyhow, Context, Result};
+use anyhow::{Context, Result};
 use binder::{IBinder, Interface, ThreadState};
 use error::Error;
 use keystore2_selinux as selinux;
 
 /// Implementation of the IKeystoreService.
+#[derive(Default)]
 pub struct KeystoreService {
-    sec_level_tee: Asp,
-    sec_level_strongbox: Option<Asp>,
+    i_sec_level_by_uuid: HashMap<Uuid, Asp>,
+    uuid_by_sec_level: HashMap<SecurityLevel, Uuid>,
 }
 
 impl KeystoreService {
     /// Create a new instance of the Keystore 2.0 service.
     pub fn new_native_binder() -> Result<impl IKeystoreService> {
-        let tee = KeystoreSecurityLevel::new_native_binder(SecurityLevel::TRUSTED_ENVIRONMENT)
-            .map(|tee| Asp::new(tee.as_binder()))
-            .context(concat!(
-                "In KeystoreService::new_native_binder: ",
-                "Trying to construct mendatory security level TEE."
-            ))?;
-        // Strongbox is optional, so we ignore errors and turn the result into an Option.
-        let strongbox =
+        let mut result: Self = Default::default();
+        let (dev, uuid) =
             KeystoreSecurityLevel::new_native_binder(SecurityLevel::TRUSTED_ENVIRONMENT)
-                .map(|tee| Asp::new(tee.as_binder()))
-                .ok();
+                .context(concat!(
+                    "In KeystoreService::new_native_binder: ",
+                    "Trying to construct mandatory security level TEE."
+                ))
+                .map(|(dev, uuid)| (Asp::new(dev.as_binder()), uuid))?;
+        result.i_sec_level_by_uuid.insert(uuid, dev);
+        result.uuid_by_sec_level.insert(SecurityLevel::TRUSTED_ENVIRONMENT, uuid);
 
-        let result = BnKeystoreService::new_binder(Self {
-            sec_level_tee: tee,
-            sec_level_strongbox: strongbox,
-        });
+        // Strongbox is optional, so we ignore errors and turn the result into an Option.
+        if let Ok((dev, uuid)) = KeystoreSecurityLevel::new_native_binder(SecurityLevel::STRONGBOX)
+            .map(|(dev, uuid)| (Asp::new(dev.as_binder()), uuid))
+        {
+            result.i_sec_level_by_uuid.insert(uuid, dev);
+            result.uuid_by_sec_level.insert(SecurityLevel::STRONGBOX, uuid);
+        }
+
+        let result = BnKeystoreService::new_binder(result);
         result.as_binder().set_requesting_sid(true);
         Ok(result)
     }
 
-    fn get_security_level_internal(
-        &self,
-        security_level: SecurityLevel,
-    ) -> Result<Option<Box<dyn IKeystoreSecurityLevel>>> {
-        Ok(match (security_level, &self.sec_level_strongbox) {
-            (SecurityLevel::TRUSTED_ENVIRONMENT, _) => Some(self.sec_level_tee.get_interface().context(
-                "In get_security_level_internal: Failed to get IKeystoreSecurityLevel (TEE).",
-            )?),
-            (SecurityLevel::STRONGBOX, Some(strongbox)) => Some(strongbox.get_interface().context(
-                "In get_security_level_internal: Failed to get IKeystoreSecurityLevel (Strongbox).",
-            )?),
-            _ => None,
-        })
+    fn uuid_to_sec_level(&self, uuid: &Uuid) -> SecurityLevel {
+        self.uuid_by_sec_level
+            .iter()
+            .find(|(_, v)| **v == *uuid)
+            .map(|(s, _)| *s)
+            .unwrap_or(SecurityLevel::SOFTWARE)
+    }
+
+    fn get_i_sec_level_by_uuid(&self, uuid: &Uuid) -> Result<Box<dyn IKeystoreSecurityLevel>> {
+        if let Some(dev) = self.i_sec_level_by_uuid.get(uuid) {
+            dev.get_interface().context("In get_i_sec_level_by_uuid.")
+        } else {
+            Err(error::Error::sys())
+                .context("In get_i_sec_level_by_uuid: KeyMint instance for key not found.")
+        }
     }
 
     fn get_security_level(
         &self,
-        security_level: SecurityLevel,
+        sec_level: SecurityLevel,
     ) -> Result<Box<dyn IKeystoreSecurityLevel>> {
-        self.get_security_level_internal(security_level)
-            .context("In get_security_level.")?
-            .ok_or_else(|| anyhow!(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)))
+        if let Some(dev) = self
+            .uuid_by_sec_level
+            .get(&sec_level)
+            .and_then(|uuid| self.i_sec_level_by_uuid.get(uuid))
+        {
+            dev.get_interface().context("In get_security_level.")
+        } else {
+            Err(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
+                .context("In get_security_level: No such security level.")
+        }
     }
 
     fn get_key_entry(&self, key: &KeyDescriptor) -> Result<KeyEntryResponse> {
@@ -113,17 +129,8 @@
 
         let i_sec_level = if !key_entry.pure_cert() {
             Some(
-                self.get_security_level_internal(key_entry.sec_level())
-                    .context("In get_key_entry.")?
-                    .ok_or_else(|| {
-                        anyhow!(error::Error::sys()).context(format!(
-                            concat!(
-                                "Found key with security level {:?} ",
-                                "but no KeyMint instance of that security level."
-                            ),
-                            key_entry.sec_level()
-                        ))
-                    })?,
+                self.get_i_sec_level_by_uuid(key_entry.km_uuid())
+                    .context("In get_key_entry: Trying to get security level proxy.")?,
             )
         } else {
             None
@@ -137,7 +144,7 @@
                     nspace: key_id_guard.id(),
                     ..Default::default()
                 },
-                keySecurityLevel: key_entry.sec_level(),
+                keySecurityLevel: self.uuid_to_sec_level(key_entry.km_uuid()),
                 certificate: key_entry.take_cert(),
                 certificateChain: key_entry.take_cert_chain(),
                 modificationTimeMs: key_entry
@@ -212,7 +219,7 @@
             check_key_permission(KeyPerm::rebind(), &key, &None)
                 .context("Caller does not have permission to insert this certificate.")?;
 
-            db.store_new_certificate(key, certificate_chain.unwrap())
+            db.store_new_certificate(key, certificate_chain.unwrap(), &KEYSTORE_UUID)
                 .context("Failed to insert new certificate.")?;
             Ok(())
         })
@@ -315,7 +322,7 @@
         &self,
         security_level: SecurityLevel,
     ) -> binder::public_api::Result<Box<dyn IKeystoreSecurityLevel>> {
-        map_or_log_err(self.get_security_level(SecurityLevel(security_level.0)), Ok)
+        map_or_log_err(self.get_security_level(security_level), Ok)
     }
     fn getKeyEntry(&self, key: &KeyDescriptor) -> binder::public_api::Result<KeyEntryResponse> {
         map_or_log_err(self.get_key_entry(key), Ok)
diff --git a/keystore2/src/super_key.rs b/keystore2/src/super_key.rs
index 4ffe897..9872513 100644
--- a/keystore2/src/super_key.rs
+++ b/keystore2/src/super_key.rs
@@ -115,36 +115,42 @@
         legacy_blob_loader: &LegacyBlobLoader,
     ) -> Result<()> {
         let (_, entry) = db
-            .get_or_create_key_with(Domain::APP, user as u64 as i64, &"USER_SUPER_KEY", || {
-                // For backward compatibility we need to check if there is a super key present.
-                let super_key = legacy_blob_loader
-                    .load_super_key(user, pw)
-                    .context("In create_new_key: Failed to load legacy key blob.")?;
-                let super_key = match super_key {
-                    None => {
-                        // No legacy file was found. So we generate a new key.
-                        keystore2_crypto::generate_aes256_key()
-                            .context("In create_new_key: Failed to generate AES 256 key.")?
-                    }
-                    Some(key) => key,
-                };
-                // Regardless of whether we loaded an old AES128 key or a new AES256 key,
-                // we derive a AES256 key and re-encrypt the key before we insert it in the
-                // database. The length of the key is preserved by the encryption so we don't
-                // need any extra flags to inform us which algorithm to use it with.
-                let salt =
-                    generate_salt().context("In create_new_key: Failed to generate salt.")?;
-                let derived_key = derive_key_from_password(pw, Some(&salt), AES_256_KEY_LENGTH)
-                    .context("In create_new_key: Failed to derive password.")?;
-                let mut metadata = KeyMetaData::new();
-                metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
-                metadata.add(KeyMetaEntry::Salt(salt));
-                let (encrypted_key, iv, tag) = aes_gcm_encrypt(&super_key, &derived_key)
-                    .context("In create_new_key: Failed to encrypt new super key.")?;
-                metadata.add(KeyMetaEntry::Iv(iv));
-                metadata.add(KeyMetaEntry::AeadTag(tag));
-                Ok((encrypted_key, metadata))
-            })
+            .get_or_create_key_with(
+                Domain::APP,
+                user as u64 as i64,
+                &"USER_SUPER_KEY",
+                crate::database::KEYSTORE_UUID,
+                || {
+                    // For backward compatibility we need to check if there is a super key present.
+                    let super_key = legacy_blob_loader
+                        .load_super_key(user, pw)
+                        .context("In create_new_key: Failed to load legacy key blob.")?;
+                    let super_key = match super_key {
+                        None => {
+                            // No legacy file was found. So we generate a new key.
+                            keystore2_crypto::generate_aes256_key()
+                                .context("In create_new_key: Failed to generate AES 256 key.")?
+                        }
+                        Some(key) => key,
+                    };
+                    // Regardless of whether we loaded an old AES128 key or a new AES256 key,
+                    // we derive a AES256 key and re-encrypt the key before we insert it in the
+                    // database. The length of the key is preserved by the encryption so we don't
+                    // need any extra flags to inform us which algorithm to use it with.
+                    let salt =
+                        generate_salt().context("In create_new_key: Failed to generate salt.")?;
+                    let derived_key = derive_key_from_password(pw, Some(&salt), AES_256_KEY_LENGTH)
+                        .context("In create_new_key: Failed to derive password.")?;
+                    let mut metadata = KeyMetaData::new();
+                    metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
+                    metadata.add(KeyMetaEntry::Salt(salt));
+                    let (encrypted_key, iv, tag) = aes_gcm_encrypt(&super_key, &derived_key)
+                        .context("In create_new_key: Failed to encrypt new super key.")?;
+                    metadata.add(KeyMetaEntry::Iv(iv));
+                    metadata.add(KeyMetaEntry::AeadTag(tag));
+                    Ok((encrypted_key, metadata))
+                },
+            )
             .context("In unlock_user_key: Failed to get key id.")?;
 
         let metadata = entry.metadata();
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 870b7fc..bada2c9 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -19,7 +19,7 @@
 use crate::permission;
 use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-    KeyCharacteristics::KeyCharacteristics, SecurityLevel::SecurityLevel, Tag::Tag,
+    KeyCharacteristics::KeyCharacteristics,
 };
 use android_security_apc::aidl::android::security::apc::{
     IProtectedConfirmation::{FLAG_UI_OPTION_INVERTED, FLAG_UI_OPTION_MAGNIFIED},
@@ -131,10 +131,6 @@
         .flat_map(|aidl_key_char| {
             let sec_level = aidl_key_char.securityLevel;
             aidl_key_char.authorizations.into_iter().map(move |aidl_kp| {
-                let sec_level = match (aidl_kp.tag, sec_level) {
-                    (Tag::ORIGIN, SecurityLevel::SOFTWARE) => SecurityLevel::TRUSTED_ENVIRONMENT,
-                    _ => sec_level,
-                };
                 crate::key_parameter::KeyParameter::new(aidl_kp.into(), sec_level)
             })
         })