Merge "Keystore 2.0: Rename keystore2 enable property."
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index f9295ca..0a5fb29 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -23,6 +23,7 @@
         "android.security.apc-rust",
         "android.security.authorization-rust",
         "android.security.compat-rust",
+        "android.security.remoteprovisioning-rust",
         "android.system.keystore2-V1-rust",
         "libanyhow",
         "libbinder_rs",
@@ -57,12 +58,14 @@
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
+    compile_multilib: "first",
     rustlibs: [
         "android.hardware.security.keymint-V1-rust",
         "android.hardware.security.secureclock-V1-rust",
         "android.security.apc-rust",
         "android.security.authorization-rust",
         "android.security.compat-rust",
+        "android.security.remoteprovisioning-rust",
         "android.system.keystore2-V1-rust",
         "libandroid_logger",
         "libanyhow",
diff --git a/keystore2/aidl/Android.bp b/keystore2/aidl/Android.bp
index fac36e5..36cff16 100644
--- a/keystore2/aidl/Android.bp
+++ b/keystore2/aidl/Android.bp
@@ -83,3 +83,25 @@
         }
     },
 }
+
+aidl_interface {
+    name: "android.security.remoteprovisioning",
+    srcs: [ "android/security/remoteprovisioning/*.aidl" ],
+    imports: [
+        "android.hardware.security.keymint",
+    ],
+    unstable: true,
+    backend: {
+        java: {
+            enabled: true,
+            sdk_version: "module_current",
+            platform_apis: true,
+        },
+        ndk: {
+            enabled: true,
+        },
+        rust: {
+            enabled: true,
+        },
+    },
+}
diff --git a/keystore2/aidl/android/security/remoteprovisioning/AttestationPoolStatus.aidl b/keystore2/aidl/android/security/remoteprovisioning/AttestationPoolStatus.aidl
new file mode 100644
index 0000000..3528b42
--- /dev/null
+++ b/keystore2/aidl/android/security/remoteprovisioning/AttestationPoolStatus.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.remoteprovisioning;
+
+/**
+ * This parcelable provides information about the state of the attestation key pool.
+ * @hide
+ */
+parcelable AttestationPoolStatus {
+    /**
+     * The number of signed attestation certificate chains which will expire when the date provided
+     * to keystore to check against is reached.
+     */
+    int expiring;
+    /**
+     * The number of signed attestation certificate chains which have not yet been assigned to an
+     * app. This should be less than or equal to signed keys. The remainder of `signed` -
+     * `unassigned` gives the number of signed keys that have been assigned to an app.
+     */
+    int unassigned;
+    /**
+     * The number of signed attestation keys. This should be less than or equal to `total`. The
+     * remainder of `total` - `attested` gives the number of keypairs available to be sent off to
+     * the server for signing.
+     */
+    int attested;
+    /**
+     * The total number of attestation keys.
+     */
+    int total;
+}
diff --git a/keystore2/aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl b/keystore2/aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
new file mode 100644
index 0000000..d045345
--- /dev/null
+++ b/keystore2/aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.remoteprovisioning;
+
+import android.hardware.security.keymint.SecurityLevel;
+import android.security.remoteprovisioning.AttestationPoolStatus;
+
+/**
+ * `IRemoteProvisioning` is the interface provided to use the remote provisioning functionality
+ * provided through KeyStore. The intent is for a higher level system component to use these
+ * functions in order to drive the process through which the device can receive functioning
+ * attestation certificates.
+ *
+ * ## Error conditions
+ * Error conditions are reported as service specific errors.
+ * Positive codes correspond to `android.security.remoteprovisioning.ResponseCode`
+ * and indicate error conditions diagnosed by the Keystore 2.0 service.
+ * TODO: Remote Provisioning HAL error code info
+ *
+ * `ResponseCode::PERMISSION_DENIED` if the caller does not have the permissions
+ * to use the RemoteProvisioning API. This permission is defined under access_vectors in SEPolicy
+ * in the keystore2 class: remotely_provision
+ *
+ * `ResponseCode::SYSTEM_ERROR` for any unexpected errors like IO or IPC failures.
+ *
+ * @hide
+ */
+interface IRemoteProvisioning {
+
+    /**
+     * Returns the status of the attestation key pool in the database.
+     *
+     * @param expiredBy The date as seconds since epoch by which to judge expiration status of
+     *                        certificates.
+     *
+     * @param secLevel The security level to specify which KM instance to get the pool for.
+     *
+     * @return The `AttestationPoolStatus` parcelable contains fields communicating information
+     *                        relevant to making decisions about when to generate and provision
+     *                        more attestation keys.
+     */
+    AttestationPoolStatus getPoolStatus(in long expiredBy, in SecurityLevel secLevel);
+
+    /**
+     * This is the primary entry point for beginning a remote provisioning flow. The caller
+     * specifies how many CSRs should be generated and provides an X25519 ECDH public key along
+     * with a challenge to encrypt privacy sensitive portions of the returned CBOR blob and
+     * guarantee freshness of the request to the certifying third party.
+     *
+     * ## Error conditions
+     * `ResponseCode::NO_UNSIGNED_KEYS` if there are no unsigned keypairs in the database that can
+     *                         be used for the CSRs.
+     *
+     * A RemoteProvisioning HAL response code may indicate backend errors such as failed EEK
+     *                         verification.
+     *
+     * @param testMode Whether or not the TA implementing the Remote Provisioning HAL should accept
+     *                         any EEK (Endpoint Encryption Key), or only one signed by a chain
+     *                         that verifies back to the Root of Trust baked into the TA. True
+     *                         means that any key is accepted.
+     *
+     * @param numCsr How many certificate signing requests should be generated.
+     *
+     * @param eek A chain of certificates terminating in an X25519 public key, the Endpoint
+     *                         Encryption Key.
+     *
+     * @param challenge A challenge to be included and MACed in the returned CBOR blob.
+     *
+     * @param secLevel The security level to specify which KM instance from which to generate a
+     *                         CSR.
+     *
+     * @return A CBOR blob composed of various encrypted/signed elements from the TA in a byte[]
+     */
+    byte[] generateCsr(in boolean testMode, in int numCsr, in byte[] eek, in byte[] challenge,
+        in SecurityLevel secLevel);
+
+    /**
+     * This method provides a way for the returned attestation certificate chains to be provisioned
+     * to the attestation key database. When an app requests an attesation key, it will be assigned
+     * one of these certificate chains along with the corresponding private key.
+     *
+     * @param publicKey The raw public key encoded in the leaf certificate.
+     *
+     * @param cert An X.509, DER encoded certificate chain.
+     *
+     * @param expirationDate The expiration date on the certificate chain, provided by the caller
+     *                          for convenience.
+     *
+     * @param secLevel The security level representing the KM instance containing the key that this
+     *                          chain corresponds to.
+     */
+    void provisionCertChain(in byte[] publicKey, in byte[] certs, in long expirationDate,
+        in SecurityLevel secLevel);
+
+    /**
+     * This method allows the caller to instruct KeyStore to generate and store a key pair to be
+     * used for attestation in the `generateCsr` method. The caller should handle spacing out these
+     * requests so as not to jam up the KeyStore work queue.
+     *
+     * @param is_test_mode Instructs the underlying HAL interface to mark the generated key with a
+     *                        tag to indicate that it's for testing.
+     *
+     * @param secLevel The security level to specify which KM instance should generate a key pair.
+     */
+    void generateKeyPair(in boolean is_test_mode, in SecurityLevel secLevel);
+}
diff --git a/keystore2/aidl/android/security/remoteprovisioning/ResponseCode.aidl b/keystore2/aidl/android/security/remoteprovisioning/ResponseCode.aidl
new file mode 100644
index 0000000..c9877db
--- /dev/null
+++ b/keystore2/aidl/android/security/remoteprovisioning/ResponseCode.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.remoteprovisioning;
+
+@Backing(type="int")
+/** @hide */
+enum ResponseCode {
+    /**
+     * Returned if there are no keys available in the database to be used in a CSR
+     */
+    NO_UNSIGNED_KEYS = 1,
+    /**
+     * The caller has imrproper SELinux permissions to access the Remote Provisioning API.
+     */
+    PERMISSION_DENIED = 2,
+    /**
+     * An unexpected error occurred, likely with IO or IPC.
+     */
+    SYSTEM_ERROR = 3,
+}
diff --git a/keystore2/src/crypto/certificate_utils.cpp b/keystore2/src/crypto/certificate_utils.cpp
index 4b0dca4..4aed224 100644
--- a/keystore2/src/crypto/certificate_utils.cpp
+++ b/keystore2/src/crypto/certificate_utils.cpp
@@ -42,17 +42,30 @@
 DEFINE_OPENSSL_OBJECT_POINTER(AUTHORITY_KEYID);
 DEFINE_OPENSSL_OBJECT_POINTER(BASIC_CONSTRAINTS);
 DEFINE_OPENSSL_OBJECT_POINTER(X509_ALGOR);
+DEFINE_OPENSSL_OBJECT_POINTER(BIGNUM);
 
 }  // namespace
 
-std::variant<CertUtilsError, X509_NAME_Ptr> makeCommonName(const std::string& name) {
+constexpr const char kDefaultCommonName[] = "Default Common Name";
+
+std::variant<CertUtilsError, X509_NAME_Ptr>
+makeCommonName(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> name) {
+    if (name) {
+        const uint8_t* p = name->get().data();
+        X509_NAME_Ptr x509_name(d2i_X509_NAME(nullptr, &p, name->get().size()));
+        if (!x509_name) {
+            return CertUtilsError::MemoryAllocation;
+        }
+        return x509_name;
+    }
+
     X509_NAME_Ptr x509_name(X509_NAME_new());
     if (!x509_name) {
-        return CertUtilsError::BoringSsl;
+        return CertUtilsError::MemoryAllocation;
     }
     if (!X509_NAME_add_entry_by_txt(x509_name.get(), "CN", MBSTRING_ASC,
-                                    reinterpret_cast<const uint8_t*>(name.c_str()), name.length(),
-                                    -1 /* loc */, 0 /* set */)) {
+                                    reinterpret_cast<const uint8_t*>(kDefaultCommonName),
+                                    sizeof(kDefaultCommonName) - 1, -1 /* loc */, 0 /* set */)) {
         return CertUtilsError::BoringSsl;
     }
     return x509_name;
@@ -159,14 +172,11 @@
 // Callers should pass an empty X509_Ptr and check the return value for CertUtilsError::Ok (0)
 // before accessing the result.
 std::variant<CertUtilsError, X509_Ptr>
-makeCertRump(const uint32_t serial, const char subject[], const uint64_t activeDateTimeMilliSeconds,
+makeCertRump(std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
+             std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
+             const uint64_t activeDateTimeMilliSeconds,
              const uint64_t usageExpireDateTimeMilliSeconds) {
 
-    // Sanitize pointer arguments.
-    if (!subject || strlen(subject) == 0) {
-        return CertUtilsError::InvalidArgument;
-    }
-
     // Create certificate structure.
     X509_Ptr certificate(X509_new());
     if (!certificate) {
@@ -178,9 +188,23 @@
         return CertUtilsError::BoringSsl;
     }
 
+    BIGNUM_Ptr bn_serial;
+    if (serial) {
+        bn_serial = BIGNUM_Ptr(BN_bin2bn(serial->get().data(), serial->get().size(), nullptr));
+        if (!bn_serial) {
+            return CertUtilsError::MemoryAllocation;
+        }
+    } else {
+        bn_serial = BIGNUM_Ptr(BN_new());
+        if (!bn_serial) {
+            return CertUtilsError::MemoryAllocation;
+        }
+        BN_zero(bn_serial.get());
+    }
+
     // Set the certificate serialNumber
     ASN1_INTEGER_Ptr serialNumber(ASN1_INTEGER_new());
-    if (!serialNumber || !ASN1_INTEGER_set(serialNumber.get(), serial) ||
+    if (!serialNumber || !BN_to_ASN1_INTEGER(bn_serial.get(), serialNumber.get()) ||
         !X509_set_serialNumber(certificate.get(), serialNumber.get() /* Don't release; copied */))
         return CertUtilsError::BoringSsl;
 
@@ -215,7 +239,9 @@
 }
 
 std::variant<CertUtilsError, X509_Ptr>
-makeCert(const EVP_PKEY* evp_pkey, const uint32_t serial, const char subject[],
+makeCert(const EVP_PKEY* evp_pkey,
+         std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,
+         std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,
          const uint64_t activeDateTimeMilliSeconds, const uint64_t usageExpireDateTimeMilliSeconds,
          bool addSubjectKeyIdEx, std::optional<KeyUsageExtension> keyUsageEx,
          std::optional<BasicConstraintsExtension> basicConstraints) {
diff --git a/keystore2/src/crypto/include/certificate_utils.h b/keystore2/src/crypto/include/certificate_utils.h
index 1e80d80..e31ebc4 100644
--- a/keystore2/src/crypto/include/certificate_utils.h
+++ b/keystore2/src/crypto/include/certificate_utils.h
@@ -80,7 +80,7 @@
  * `signCert` or `signCertWith`.
  * @param evp_pkey The public key that the certificate is issued for.
  * @param serial The certificate serial number.
- * @param subject The subject common name.
+ * @param subject The X509 name encoded subject common name.
  * @param activeDateTimeMilliSeconds The not before date in epoch milliseconds.
  * @param usageExpireDateTimeMilliSeconds The not after date in epoch milliseconds.
  * @param addSubjectKeyIdEx If true, adds the subject key id extension.
@@ -89,14 +89,14 @@
  * @return CertUtilsError::Ok on success.
  */
 std::variant<CertUtilsError, X509_Ptr>
-makeCert(const EVP_PKEY* evp_pkey,                                    //
-         const uint32_t serial,                                       //
-         const char subject[],                                        //
-         const uint64_t activeDateTimeMilliSeconds,                   //
-         const uint64_t usageExpireDateTimeMilliSeconds,              //
-         bool addSubjectKeyIdEx,                                      //
-         std::optional<KeyUsageExtension> keyUsageEx,                 //
-         std::optional<BasicConstraintsExtension> basicConstraints);  //
+makeCert(const EVP_PKEY* evp_pkey,                                                   //
+         std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial,   //
+         std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject,  //
+         const uint64_t activeDateTimeMilliSeconds,                                  //
+         const uint64_t usageExpireDateTimeMilliSeconds,                             //
+         bool addSubjectKeyIdEx,                                                     //
+         std::optional<KeyUsageExtension> keyUsageEx,                                //
+         std::optional<BasicConstraintsExtension> basicConstraints);                 //
 
 /**
  * Takes the subject name from `signingCert` and sets it as issuer name in `cert`.
diff --git a/keystore2/src/crypto/tests/certificate_utils_test.cpp b/keystore2/src/crypto/tests/certificate_utils_test.cpp
index 2df9ce5..119c3fa 100644
--- a/keystore2/src/crypto/tests/certificate_utils_test.cpp
+++ b/keystore2/src/crypto/tests/certificate_utils_test.cpp
@@ -173,8 +173,8 @@
         .isCertificationKey = true,
     };
 
-    auto certV = makeCert(pkey.get(), 1, "Me", now_ms - kValidity, now_ms + kValidity,
-                          true /* subject key id extension */, keyUsage, bcons);
+    auto certV = makeCert(pkey.get(), std::nullopt, std::nullopt, now_ms - kValidity,
+                          now_ms + kValidity, true /* subject key id extension */, keyUsage, bcons);
     ASSERT_TRUE(std::holds_alternative<X509_Ptr>(certV));
     auto& cert = std::get<X509_Ptr>(certV);
     ASSERT_TRUE(!setIssuer(cert.get(), cert.get(), true));
@@ -272,8 +272,8 @@
         .isCertificationKey = true,
     };
 
-    auto certV = makeCert(pkey.get(), 1, "Me", now_ms - kValidity, now_ms + kValidity,
-                          true /* subject key id extension */, keyUsage, bcons);
+    auto certV = makeCert(pkey.get(), std::nullopt, std::nullopt, now_ms - kValidity,
+                          now_ms + kValidity, true /* subject key id extension */, keyUsage, bcons);
     ASSERT_TRUE(std::holds_alternative<X509_Ptr>(certV));
     auto& cert = std::get<X509_Ptr>(certV);
     ASSERT_TRUE(!setIssuer(cert.get(), cert.get(), true));
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index 0e7a2d2..3789d28 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -60,6 +60,11 @@
 use android_system_keystore2::aidl::android::system::keystore2::{
     Domain::Domain, KeyDescriptor::KeyDescriptor,
 };
+use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{
+    AttestationPoolStatus::AttestationPoolStatus,
+};
+
+use keystore2_crypto::ZVec;
 use lazy_static::lazy_static;
 use log::error;
 #[cfg(not(test))]
@@ -72,12 +77,14 @@
     types::{FromSqlError, Value, ValueRef},
     Connection, OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
 };
+
 use std::{
     collections::{HashMap, HashSet},
     path::Path,
     sync::{Condvar, Mutex},
     time::{Duration, SystemTime},
 };
+
 #[cfg(test)]
 use tests::random;
 
@@ -102,6 +109,12 @@
         CreationDate(DateTime) with accessor creation_date,
         /// Expiration date for attestation keys.
         AttestationExpirationDate(DateTime) with accessor attestation_expiration_date,
+        /// CBOR Blob that represents a COSE_Key and associated metadata needed for remote
+        /// provisioning
+        AttestationMacedPublicKey(Vec<u8>) with accessor attestation_maced_public_key,
+        /// Vector representing the raw public key so results from the server can be matched
+        /// to the right entry
+        AttestationRawPubKey(Vec<u8>) with accessor attestation_raw_pub_key,
         //  --- ADD NEW META DATA FIELDS HERE ---
         // For backwards compatibility add new entries only to
         // end of this list and above this comment.
@@ -393,7 +406,7 @@
 /// certificate chain components.
 /// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry`
 /// which components shall be loaded from the database if present.
-#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
 pub struct KeyEntryLoadBits(u32);
 
 impl KeyEntryLoadBits {
@@ -480,7 +493,7 @@
 }
 
 /// This type represents a certificate and certificate chain entry for a key.
-#[derive(Debug)]
+#[derive(Debug, Default)]
 pub struct CertificateInfo {
     cert: Option<Vec<u8>>,
     cert_chain: Option<Vec<u8>>,
@@ -503,6 +516,14 @@
     }
 }
 
+/// This type represents a certificate chain with a private key corresponding to the leaf
+/// certificate. TODO(jbires): This will be used in a follow-on CL, for now it's used in the tests.
+#[allow(dead_code)]
+pub struct CertificateChain {
+    private_key: ZVec,
+    cert_chain: ZVec,
+}
+
 /// 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
@@ -704,18 +725,19 @@
         persistent_path_str.push_str(&persistent_path.to_string_lossy());
 
         let conn = Self::make_connection(&persistent_path_str, &Self::PERBOOT_DB_FILE_NAME)?;
-        conn.busy_handler(Some(|_| {
-            std::thread::sleep(std::time::Duration::from_micros(50));
-            true
-        }))
-        .context("In KeystoreDB::new: Failed to set busy handler.")?;
 
-        Self::init_tables(&conn)?;
-        Ok(Self { conn })
+        // On busy fail Immediately. It is unlikely to succeed given a bug in sqlite.
+        conn.busy_handler(None).context("In KeystoreDB::new: Failed to set busy handler.")?;
+
+        let mut db = Self { conn };
+        db.with_transaction(TransactionBehavior::Immediate, |tx| {
+            Self::init_tables(tx).context("Trying to initialize tables.")
+        })?;
+        Ok(db)
     }
 
-    fn init_tables(conn: &Connection) -> Result<()> {
-        conn.execute(
+    fn init_tables(tx: &Transaction) -> Result<()> {
+        tx.execute(
             "CREATE TABLE IF NOT EXISTS persistent.keyentry (
                      id INTEGER UNIQUE,
                      key_type INTEGER,
@@ -728,7 +750,21 @@
         )
         .context("Failed to initialize \"keyentry\" table.")?;
 
-        conn.execute(
+        tx.execute(
+            "CREATE INDEX IF NOT EXISTS persistent.keyentry_id_index
+            ON keyentry(id);",
+            NO_PARAMS,
+        )
+        .context("Failed to create index keyentry_id_index.")?;
+
+        tx.execute(
+            "CREATE INDEX IF NOT EXISTS persistent.keyentry_domain_namespace_index
+            ON keyentry(domain, namespace, alias);",
+            NO_PARAMS,
+        )
+        .context("Failed to create index keyentry_domain_namespace_index.")?;
+
+        tx.execute(
             "CREATE TABLE IF NOT EXISTS persistent.blobentry (
                     id INTEGER PRIMARY KEY,
                     subcomponent_type INTEGER,
@@ -738,7 +774,14 @@
         )
         .context("Failed to initialize \"blobentry\" table.")?;
 
-        conn.execute(
+        tx.execute(
+            "CREATE INDEX IF NOT EXISTS persistent.blobentry_keyentryid_index
+            ON blobentry(keyentryid);",
+            NO_PARAMS,
+        )
+        .context("Failed to create index blobentry_keyentryid_index.")?;
+
+        tx.execute(
             "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
                      keyentryid INTEGER,
                      tag INTEGER,
@@ -748,7 +791,14 @@
         )
         .context("Failed to initialize \"keyparameter\" table.")?;
 
-        conn.execute(
+        tx.execute(
+            "CREATE INDEX IF NOT EXISTS persistent.keyparameter_keyentryid_index
+            ON keyparameter(keyentryid);",
+            NO_PARAMS,
+        )
+        .context("Failed to create index keyparameter_keyentryid_index.")?;
+
+        tx.execute(
             "CREATE TABLE IF NOT EXISTS persistent.keymetadata (
                      keyentryid INTEGER,
                      tag INTEGER,
@@ -757,7 +807,14 @@
         )
         .context("Failed to initialize \"keymetadata\" table.")?;
 
-        conn.execute(
+        tx.execute(
+            "CREATE INDEX IF NOT EXISTS persistent.keymetadata_keyentryid_index
+            ON keymetadata(keyentryid);",
+            NO_PARAMS,
+        )
+        .context("Failed to create index keymetadata_keyentryid_index.")?;
+
+        tx.execute(
             "CREATE TABLE IF NOT EXISTS persistent.grant (
                     id INTEGER UNIQUE,
                     grantee INTEGER,
@@ -769,9 +826,9 @@
 
         //TODO: only drop the following two perboot tables if this is the first start up
         //during the boot (b/175716626).
-        // conn.execute("DROP TABLE IF EXISTS perboot.authtoken;", NO_PARAMS)
+        // tx.execute("DROP TABLE IF EXISTS perboot.authtoken;", NO_PARAMS)
         //     .context("Failed to drop perboot.authtoken table")?;
-        conn.execute(
+        tx.execute(
             "CREATE TABLE IF NOT EXISTS perboot.authtoken (
                         id INTEGER PRIMARY KEY,
                         challenge INTEGER,
@@ -786,11 +843,11 @@
         )
         .context("Failed to initialize \"authtoken\" table.")?;
 
-        // conn.execute("DROP TABLE IF EXISTS perboot.metadata;", NO_PARAMS)
+        // tx.execute("DROP TABLE IF EXISTS perboot.metadata;", NO_PARAMS)
         //     .context("Failed to drop perboot.metadata table")?;
         // metadata table stores certain miscellaneous information required for keystore functioning
         // during a boot cycle, as key-value pairs.
-        conn.execute(
+        tx.execute(
             "CREATE TABLE IF NOT EXISTS perboot.metadata (
                         key TEXT,
                         value BLOB,
@@ -805,10 +862,34 @@
         let conn =
             Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
 
-        conn.execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
-            .context("Failed to attach database persistent.")?;
-        conn.execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
-            .context("Failed to attach database perboot.")?;
+        loop {
+            if let Err(e) = conn
+                .execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
+                .context("Failed to attach database persistent.")
+            {
+                if Self::is_locked_error(&e) {
+                    std::thread::sleep(std::time::Duration::from_micros(500));
+                    continue;
+                } else {
+                    return Err(e);
+                }
+            }
+            break;
+        }
+        loop {
+            if let Err(e) = conn
+                .execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
+                .context("Failed to attach database perboot.")
+            {
+                if Self::is_locked_error(&e) {
+                    std::thread::sleep(std::time::Duration::from_micros(500));
+                    continue;
+                } else {
+                    return Err(e);
+                }
+            }
+            break;
+        }
 
         Ok(conn)
     }
@@ -895,12 +976,14 @@
     /// Unlike with `mark_unreferenced`, we don't need to purge grants, because only keys that made
     /// it to `KeyLifeCycle::Live` may have grants.
     pub fn cleanup_leftovers(&mut self) -> Result<usize> {
-        self.conn
-            .execute(
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            tx.execute(
                 "UPDATE persistent.keyentry SET state = ? WHERE state = ?;",
                 params![KeyLifeCycle::Unreferenced, KeyLifeCycle::Existing],
             )
-            .context("In cleanup_leftovers.")
+            .context("Failed to execute query.")
+        })
+        .context("In cleanup_leftovers.")
     }
 
     /// Atomically loads a key entry and associated metadata or creates it using the
@@ -916,98 +999,134 @@
         create_new_key: F,
     ) -> Result<(KeyIdGuard, KeyEntry)>
     where
-        F: FnOnce() -> Result<(Vec<u8>, KeyMetaData)>,
+        F: Fn() -> Result<(Vec<u8>, KeyMetaData)>,
     {
-        let tx = self
-            .conn
-            .transaction_with_behavior(TransactionBehavior::Immediate)
-            .context("In get_or_create_key_with: Failed to initialize transaction.")?;
-
-        let id = {
-            let mut stmt = tx
-                .prepare(
-                    "SELECT id FROM persistent.keyentry
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            let id = {
+                let mut stmt = tx
+                    .prepare(
+                        "SELECT id FROM persistent.keyentry
                     WHERE
                     key_type = ?
                     AND domain = ?
                     AND namespace = ?
                     AND alias = ?
                     AND state = ?;",
-                )
-                .context("In get_or_create_key_with: Failed to select from keyentry table.")?;
-            let mut rows = stmt
-                .query(params![KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live])
-                .context("In get_or_create_key_with: Failed to query from keyentry table.")?;
+                    )
+                    .context("In get_or_create_key_with: Failed to select from keyentry table.")?;
+                let mut rows = stmt
+                    .query(params![KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live])
+                    .context("In get_or_create_key_with: Failed to query from keyentry table.")?;
 
-            db_utils::with_rows_extract_one(&mut rows, |row| {
-                Ok(match row {
-                    Some(r) => r.get(0).context("Failed to unpack id.")?,
-                    None => None,
+                db_utils::with_rows_extract_one(&mut rows, |row| {
+                    Ok(match row {
+                        Some(r) => r.get(0).context("Failed to unpack id.")?,
+                        None => None,
+                    })
                 })
-            })
-            .context("In get_or_create_key_with.")?
-        };
+                .context("In get_or_create_key_with.")?
+            };
 
-        let (id, entry) = match id {
-            Some(id) => (
-                id,
-                Self::load_key_components(&tx, KeyEntryLoadBits::KM, id)
-                    .context("In get_or_create_key_with.")?,
-            ),
+            let (id, entry) = match id {
+                Some(id) => (
+                    id,
+                    Self::load_key_components(&tx, KeyEntryLoadBits::KM, id)
+                        .context("In get_or_create_key_with.")?,
+                ),
 
-            None => {
-                let id = Self::insert_with_retry(|id| {
-                    tx.execute(
-                        "INSERT into persistent.keyentry
+                None => {
+                    let id = Self::insert_with_retry(|id| {
+                        tx.execute(
+                            "INSERT into persistent.keyentry
                         (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.")?;
+                            params![
+                                id,
+                                KeyType::Super,
+                                domain.0,
+                                namespace,
+                                alias,
+                                KeyLifeCycle::Live,
+                                km_uuid,
+                            ],
+                        )
+                    })
+                    .context("In get_or_create_key_with.")?;
 
-                let (blob, metadata) = create_new_key().context("In get_or_create_key_with.")?;
-                Self::set_blob_internal(&tx, id, SubComponentType::KEY_BLOB, Some(&blob))
-                    .context("In get_of_create_key_with.")?;
-                metadata.store_in_db(id, &tx).context("In get_or_create_key_with.")?;
-                (
-                    id,
-                    KeyEntry {
+                    let (blob, metadata) =
+                        create_new_key().context("In get_or_create_key_with.")?;
+                    Self::set_blob_internal(&tx, id, SubComponentType::KEY_BLOB, Some(&blob))
+                        .context("In get_of_create_key_with.")?;
+                    metadata.store_in_db(id, &tx).context("In get_or_create_key_with.")?;
+                    (
                         id,
-                        km_blob: Some(blob),
-                        metadata,
-                        pure_cert: false,
-                        ..Default::default()
-                    },
-                )
-            }
-        };
-        tx.commit().context("In get_or_create_key_with: Failed to commit transaction.")?;
-        Ok((KEY_ID_LOCK.get(id), entry))
+                        KeyEntry {
+                            id,
+                            km_blob: Some(blob),
+                            metadata,
+                            pure_cert: false,
+                            ..Default::default()
+                        },
+                    )
+                }
+            };
+            Ok((KEY_ID_LOCK.get(id), entry))
+        })
+        .context("In get_or_create_key_with.")
     }
 
+    /// SQLite3 seems to hold a shared mutex while running the busy handler when
+    /// waiting for the database file to become available. This makes it
+    /// impossible to successfully recover from a locked database when the
+    /// transaction holding the device busy is in the same process on a
+    /// different connection. As a result the busy handler has to time out and
+    /// fail in order to make progress.
+    ///
+    /// Instead, we set the busy handler to None (return immediately). And catch
+    /// Busy and Locked errors (the latter occur on in memory databases with
+    /// shared cache, e.g., the per-boot database.) and restart the transaction
+    /// after a grace period of half a millisecond.
+    ///
     /// Creates a transaction with the given behavior and executes f with the new transaction.
-    /// The transaction is committed only if f returns Ok.
+    /// The transaction is committed only if f returns Ok and retried if DatabaseBusy
+    /// or DatabaseLocked is encountered.
     fn with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T>
     where
-        F: FnOnce(&Transaction) -> Result<T>,
+        F: Fn(&Transaction) -> Result<T>,
     {
-        let tx = self
-            .conn
-            .transaction_with_behavior(behavior)
-            .context("In with_transaction: Failed to initialize transaction.")?;
-        f(&tx).and_then(|result| {
-            tx.commit().context("In with_transaction: Failed to commit transaction.")?;
-            Ok(result)
+        loop {
+            match self
+                .conn
+                .transaction_with_behavior(behavior)
+                .context("In with_transaction.")
+                .and_then(|tx| f(&tx).map(|result| (result, tx)))
+                .and_then(|(result, tx)| {
+                    tx.commit().context("In with_transaction: Failed to commit transaction.")?;
+                    Ok(result)
+                }) {
+                Ok(result) => break Ok(result),
+                Err(e) => {
+                    if Self::is_locked_error(&e) {
+                        std::thread::sleep(std::time::Duration::from_micros(500));
+                        continue;
+                    } else {
+                        return Err(e).context("In with_transaction.");
+                    }
+                }
+            }
+        }
+    }
+
+    fn is_locked_error(e: &anyhow::Error) -> bool {
+        matches!(e.root_cause().downcast_ref::<rusqlite::ffi::Error>(),
+        Some(rusqlite::ffi::Error {
+            code: rusqlite::ErrorCode::DatabaseBusy,
+            ..
         })
+        | Some(rusqlite::ffi::Error {
+            code: rusqlite::ErrorCode::DatabaseLocked,
+            ..
+        }))
     }
 
     /// Creates a new key entry and allocates a new randomized id for the new key.
@@ -1018,8 +1137,8 @@
     /// atomic even if key generation is not.
     pub fn create_key_entry(
         &mut self,
-        domain: Domain,
-        namespace: i64,
+        domain: &Domain,
+        namespace: &i64,
         km_uuid: &Uuid,
     ) -> Result<KeyIdGuard> {
         self.with_transaction(TransactionBehavior::Immediate, |tx| {
@@ -1030,11 +1149,11 @@
 
     fn create_key_entry_internal(
         tx: &Transaction,
-        domain: Domain,
-        namespace: i64,
+        domain: &Domain,
+        namespace: &i64,
         km_uuid: &Uuid,
     ) -> Result<KeyIdGuard> {
-        match domain {
+        match *domain {
             Domain::APP | Domain::SELINUX => {}
             _ => {
                 return Err(KsError::sys())
@@ -1051,7 +1170,7 @@
                         id,
                         KeyType::Client,
                         domain.0 as u32,
-                        namespace,
+                        *namespace,
                         KeyLifeCycle::Existing,
                         km_uuid,
                     ],
@@ -1061,6 +1180,40 @@
         ))
     }
 
+    /// Creates a new attestation key entry and allocates a new randomized id for the new key.
+    /// The key id gets associated with a domain and namespace later but not with an alias. The
+    /// alias will be used to denote if a key has been signed as each key can only be bound to one
+    /// domain and namespace pairing so there is no need to use them as a value for indexing into
+    /// a key.
+    pub fn create_attestation_key_entry(
+        &mut self,
+        maced_public_key: &[u8],
+        raw_public_key: &[u8],
+        private_key: &[u8],
+        km_uuid: &Uuid,
+    ) -> Result<()> {
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            let key_id = KEY_ID_LOCK.get(
+                Self::insert_with_retry(|id| {
+                    tx.execute(
+                        "INSERT into persistent.keyentry
+                            (id, key_type, domain, namespace, alias, state, km_uuid)
+                            VALUES(?, ?, NULL, NULL, NULL, ?, ?);",
+                        params![id, KeyType::Attestation, KeyLifeCycle::Live, km_uuid],
+                    )
+                })
+                .context("In create_key_entry")?,
+            );
+            Self::set_blob_internal(&tx, key_id.0, SubComponentType::KEY_BLOB, Some(private_key))?;
+            let mut metadata = KeyMetaData::new();
+            metadata.add(KeyMetaEntry::AttestationMacedPublicKey(maced_public_key.to_vec()));
+            metadata.add(KeyMetaEntry::AttestationRawPubKey(raw_public_key.to_vec()));
+            metadata.store_in_db(key_id.0, &tx)?;
+            Ok(())
+        })
+        .context("In create_attestation_key_entry")
+    }
+
     /// Set a new blob and associates it with the given key id. Each blob
     /// has a sub component type.
     /// Each key can have one of each sub component type associated. If more
@@ -1113,10 +1266,10 @@
 
     /// Inserts a collection of key parameters into the `persistent.keyparameter` table
     /// and associates them with the given `key_id`.
-    pub fn insert_keyparameter<'a>(
+    pub fn insert_keyparameter(
         &mut self,
         key_id: &KeyIdGuard,
-        params: impl IntoIterator<Item = &'a KeyParameter>,
+        params: &[KeyParameter],
     ) -> Result<()> {
         self.with_transaction(TransactionBehavior::Immediate, |tx| {
             Self::insert_keyparameter_internal(tx, key_id, params)
@@ -1124,10 +1277,10 @@
         .context("In insert_keyparameter.")
     }
 
-    fn insert_keyparameter_internal<'a>(
+    fn insert_keyparameter_internal(
         tx: &Transaction,
         key_id: &KeyIdGuard,
-        params: impl IntoIterator<Item = &'a KeyParameter>,
+        params: &[KeyParameter],
     ) -> Result<()> {
         let mut stmt = tx
             .prepare(
@@ -1136,8 +1289,7 @@
             )
             .context("In insert_keyparameter_internal: Failed to prepare statement.")?;
 
-        let iter = params.into_iter();
-        for p in iter {
+        for p in params.iter() {
             stmt.insert(params![
                 key_id.0,
                 p.get_tag().0,
@@ -1163,6 +1315,343 @@
         .context("In insert_key_metadata.")
     }
 
+    /// Stores a signed certificate chain signed by a remote provisioning server, keyed
+    /// on the public key.
+    pub fn store_signed_attestation_certificate_chain(
+        &mut self,
+        raw_public_key: &[u8],
+        cert_chain: &[u8],
+        expiration_date: i64,
+        km_uuid: &Uuid,
+    ) -> Result<()> {
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            let mut stmt = tx
+                .prepare(
+                    "SELECT keyentryid
+                    FROM persistent.keymetadata
+                    WHERE tag = ? AND data = ? AND keyentryid IN
+                    (SELECT id
+                     FROM persistent.keyentry
+                     WHERE
+                        alias IS NULL AND
+                        domain IS NULL AND
+                        namespace IS NULL AND
+                        key_type = ? AND
+                        km_uuid = ?);",
+                )
+                .context("Failed to store attestation certificate chain.")?;
+            let mut rows = stmt
+                .query(params![
+                    KeyMetaData::AttestationRawPubKey,
+                    raw_public_key,
+                    KeyType::Attestation,
+                    km_uuid
+                ])
+                .context("Failed to fetch keyid")?;
+            let key_id = db_utils::with_rows_extract_one(&mut rows, |row| {
+                row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
+                    .get(0)
+                    .context("Failed to unpack id.")
+            })
+            .context("Failed to get key_id.")?;
+            let num_updated = tx
+                .execute(
+                    "UPDATE persistent.keyentry
+                    SET alias = ?
+                    WHERE id = ?;",
+                    params!["signed", key_id],
+                )
+                .context("Failed to update alias.")?;
+            if num_updated != 1 {
+                return Err(KsError::sys()).context("Alias not updated for the key.");
+            }
+            let mut metadata = KeyMetaData::new();
+            metadata.add(KeyMetaEntry::AttestationExpirationDate(DateTime::from_millis_epoch(
+                expiration_date,
+            )));
+            metadata.store_in_db(key_id, &tx).context("Failed to insert key metadata.")?;
+            Self::set_blob_internal(&tx, key_id, SubComponentType::CERT_CHAIN, Some(cert_chain))
+                .context("Failed to insert cert chain")?;
+            Ok(())
+        })
+        .context("In store_signed_attestation_certificate_chain: ")
+    }
+
+    /// Assigns the next unassigned attestation key to a domain/namespace combo that does not
+    /// currently have a key assigned to it.
+    pub fn assign_attestation_key(
+        &mut self,
+        domain: Domain,
+        namespace: i64,
+        km_uuid: &Uuid,
+    ) -> Result<()> {
+        match domain {
+            Domain::APP | Domain::SELINUX => {}
+            _ => {
+                return Err(KsError::sys()).context(format!(
+                    concat!(
+                        "In assign_attestation_key: Domain {:?} ",
+                        "must be either App or SELinux.",
+                    ),
+                    domain
+                ));
+            }
+        }
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            let result = tx
+                .execute(
+                    "UPDATE persistent.keyentry
+                        SET domain=?1, namespace=?2
+                        WHERE
+                            id =
+                                (SELECT MIN(id)
+                                FROM persistent.keyentry
+                                WHERE ALIAS IS NOT NULL
+                                    AND domain IS NULL
+                                    AND key_type IS ?3
+                                    AND state IS ?4
+                                    AND km_uuid IS ?5)
+                            AND
+                                (SELECT COUNT(*)
+                                FROM persistent.keyentry
+                                WHERE domain=?1
+                                    AND namespace=?2
+                                    AND key_type IS ?3
+                                    AND state IS ?4
+                                    AND km_uuid IS ?5) = 0;",
+                    params![
+                        domain.0 as u32,
+                        namespace,
+                        KeyType::Attestation,
+                        KeyLifeCycle::Live,
+                        km_uuid,
+                    ],
+                )
+                .context("Failed to assign attestation key")?;
+            if result != 1 {
+                return Err(KsError::sys()).context(format!(
+                    "Expected to update a single entry but instead updated {}.",
+                    result
+                ));
+            }
+            Ok(())
+        })
+        .context("In assign_attestation_key: ")
+    }
+
+    /// Retrieves num_keys number of attestation keys that have not yet been signed by a remote
+    /// provisioning server, or the maximum number available if there are not num_keys number of
+    /// entries in the table.
+    pub fn fetch_unsigned_attestation_keys(
+        &mut self,
+        num_keys: i32,
+        km_uuid: &Uuid,
+    ) -> Result<Vec<Vec<u8>>> {
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            let mut stmt = tx
+                .prepare(
+                    "SELECT data
+                    FROM persistent.keymetadata
+                    WHERE tag = ? AND keyentryid IN
+                        (SELECT id
+                        FROM persistent.keyentry
+                        WHERE
+                            alias IS NULL AND
+                            domain IS NULL AND
+                            namespace IS NULL AND
+                            key_type = ? AND
+                            km_uuid = ?
+                        LIMIT ?);",
+                )
+                .context("Failed to prepare statement")?;
+            let rows = stmt
+                .query_map(
+                    params![
+                        KeyMetaData::AttestationMacedPublicKey,
+                        KeyType::Attestation,
+                        km_uuid,
+                        num_keys
+                    ],
+                    |row| Ok(row.get(0)?),
+                )?
+                .collect::<rusqlite::Result<Vec<Vec<u8>>>>()
+                .context("Failed to execute statement")?;
+            Ok(rows)
+        })
+        .context("In fetch_unsigned_attestation_keys")
+    }
+
+    /// Removes any keys that have expired as of the current time. Returns the number of keys
+    /// marked unreferenced that are bound to be garbage collected.
+    pub fn delete_expired_attestation_keys(&mut self) -> Result<i32> {
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            let mut stmt = tx
+                .prepare(
+                    "SELECT keyentryid, data
+                     FROM persistent.keymetadata
+                     WHERE tag = ? AND keyentryid IN
+                         (SELECT id
+                         FROM persistent.keyentry
+                         WHERE key_type = ?);",
+                )
+                .context("Failed to prepare query")?;
+            let key_ids_to_check = stmt
+                .query_map(
+                    params![KeyMetaData::AttestationExpirationDate, KeyType::Attestation],
+                    |row| Ok((row.get(0)?, row.get(1)?)),
+                )?
+                .collect::<rusqlite::Result<Vec<(i64, DateTime)>>>()
+                .context("Failed to get date metadata")?;
+            let curr_time = DateTime::from_millis_epoch(
+                SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as i64,
+            );
+            let mut num_deleted = 0;
+            for id in key_ids_to_check.iter().filter(|kt| kt.1 < curr_time).map(|kt| kt.0) {
+                if Self::mark_unreferenced(&tx, id)? {
+                    num_deleted += 1;
+                }
+            }
+            Ok(num_deleted)
+        })
+        .context("In delete_expired_attestation_keys: ")
+    }
+
+    /// Counts the number of keys that will expire by the provided epoch date and the number of
+    /// keys not currently assigned to a domain.
+    pub fn get_attestation_pool_status(
+        &mut self,
+        date: i64,
+        km_uuid: &Uuid,
+    ) -> Result<AttestationPoolStatus> {
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            let mut stmt = tx.prepare(
+                "SELECT data
+                 FROM persistent.keymetadata
+                 WHERE tag = ? AND keyentryid IN
+                     (SELECT id
+                      FROM persistent.keyentry
+                      WHERE alias IS NOT NULL
+                            AND key_type = ?
+                            AND km_uuid = ?
+                            AND state = ?);",
+            )?;
+            let times = stmt
+                .query_map(
+                    params![
+                        KeyMetaData::AttestationExpirationDate,
+                        KeyType::Attestation,
+                        km_uuid,
+                        KeyLifeCycle::Live
+                    ],
+                    |row| Ok(row.get(0)?),
+                )?
+                .collect::<rusqlite::Result<Vec<DateTime>>>()
+                .context("Failed to execute metadata statement")?;
+            let expiring =
+                times.iter().filter(|time| time < &&DateTime::from_millis_epoch(date)).count()
+                    as i32;
+            stmt = tx.prepare(
+                "SELECT alias, domain
+                 FROM persistent.keyentry
+                 WHERE key_type = ? AND km_uuid = ? AND state = ?;",
+            )?;
+            let rows = stmt
+                .query_map(params![KeyType::Attestation, km_uuid, KeyLifeCycle::Live], |row| {
+                    Ok((row.get(0)?, row.get(1)?))
+                })?
+                .collect::<rusqlite::Result<Vec<(Option<String>, Option<u32>)>>>()
+                .context("Failed to execute keyentry statement")?;
+            let mut unassigned = 0i32;
+            let mut attested = 0i32;
+            let total = rows.len() as i32;
+            for (alias, domain) in rows {
+                match (alias, domain) {
+                    (Some(_alias), None) => {
+                        attested += 1;
+                        unassigned += 1;
+                    }
+                    (Some(_alias), Some(_domain)) => {
+                        attested += 1;
+                    }
+                    _ => {}
+                }
+            }
+            Ok(AttestationPoolStatus { expiring, unassigned, attested, total })
+        })
+        .context("In get_attestation_pool_status: ")
+    }
+
+    /// Fetches the private key and corresponding certificate chain assigned to a
+    /// domain/namespace pair. Will either return nothing if the domain/namespace is
+    /// not assigned, or one CertificateChain.
+    pub fn retrieve_attestation_key_and_cert_chain(
+        &mut self,
+        domain: Domain,
+        namespace: i64,
+        km_uuid: &Uuid,
+    ) -> Result<Option<CertificateChain>> {
+        match domain {
+            Domain::APP | Domain::SELINUX => {}
+            _ => {
+                return Err(KsError::sys())
+                    .context(format!("Domain {:?} must be either App or SELinux.", domain));
+            }
+        }
+        let mut stmt = self.conn.prepare(
+            "SELECT subcomponent_type, blob
+             FROM persistent.blobentry
+             WHERE keyentryid IN
+                (SELECT id
+                 FROM persistent.keyentry
+                 WHERE key_type = ?
+                       AND domain = ?
+                       AND namespace = ?
+                       AND state = ?
+                       AND km_uuid = ?);",
+        )?;
+        let rows = stmt
+            .query_map(
+                params![
+                    KeyType::Attestation,
+                    domain.0 as u32,
+                    namespace,
+                    KeyLifeCycle::Live,
+                    km_uuid
+                ],
+                |row| Ok((row.get(0)?, row.get(1)?)),
+            )?
+            .collect::<rusqlite::Result<Vec<(SubComponentType, Vec<u8>)>>>()
+            .context("In retrieve_attestation_key_and_cert_chain: query failed.")?;
+        if rows.is_empty() {
+            return Ok(None);
+        } else if rows.len() != 2 {
+            return Err(KsError::sys()).context(format!(
+                concat!(
+                "In retrieve_attestation_key_and_cert_chain: Expected to get a single attestation",
+                "key chain but instead got {}."),
+                rows.len()
+            ));
+        }
+        let mut km_blob: Vec<u8> = Vec::new();
+        let mut cert_chain_blob: Vec<u8> = Vec::new();
+        for row in rows {
+            let sub_type: SubComponentType = row.0;
+            match sub_type {
+                SubComponentType::KEY_BLOB => {
+                    km_blob = row.1;
+                }
+                SubComponentType::CERT_CHAIN => {
+                    cert_chain_blob = row.1;
+                }
+                _ => Err(KsError::sys()).context("Unknown or incorrect subcomponent type.")?,
+            }
+        }
+        Ok(Some(CertificateChain {
+            private_key: ZVec::try_from(km_blob)?,
+            cert_chain: ZVec::try_from(cert_chain_blob)?,
+        }))
+    }
+
     /// Updates the alias column of the given key id `newid` with the given alias,
     /// and atomically, removes the alias, domain, and namespace from another row
     /// with the same alias-domain-namespace tuple if such row exits.
@@ -1172,10 +1661,10 @@
         tx: &Transaction,
         newid: &KeyIdGuard,
         alias: &str,
-        domain: Domain,
-        namespace: i64,
+        domain: &Domain,
+        namespace: &i64,
     ) -> Result<bool> {
-        match domain {
+        match *domain {
             Domain::APP | Domain::SELINUX => {}
             _ => {
                 return Err(KsError::sys()).context(format!(
@@ -1202,7 +1691,7 @@
                     KeyLifeCycle::Live,
                     newid.0,
                     domain.0 as u32,
-                    namespace,
+                    *namespace,
                     KeyLifeCycle::Existing,
                 ],
             )
@@ -1221,10 +1710,10 @@
     /// fields, and rebinds the given alias to the new key.
     /// The boolean returned is a hint for the garbage collector. If true, a key was replaced,
     /// is now unreferenced and needs to be collected.
-    pub fn store_new_key<'a>(
+    pub fn store_new_key(
         &mut self,
-        key: KeyDescriptor,
-        params: impl IntoIterator<Item = &'a KeyParameter>,
+        key: &KeyDescriptor,
+        params: &[KeyParameter],
         blob: &[u8],
         cert_info: &CertificateInfo,
         metadata: &KeyMetaData,
@@ -1241,7 +1730,7 @@
             }
         };
         self.with_transaction(TransactionBehavior::Immediate, |tx| {
-            let key_id = Self::create_key_entry_internal(tx, domain, namespace, km_uuid)
+            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.")?;
@@ -1261,7 +1750,7 @@
             Self::insert_keyparameter_internal(tx, &key_id, params)
                 .context("Trying to insert key parameters.")?;
             metadata.store_in_db(key_id.id(), tx).context("Trying to insert key metadata.")?;
-            let need_gc = Self::rebind_alias(tx, &key_id, &alias, domain, namespace)
+            let need_gc = Self::rebind_alias(tx, &key_id, &alias, &domain, namespace)
                 .context("Trying to rebind alias.")?;
             Ok((need_gc, key_id))
         })
@@ -1273,7 +1762,7 @@
     /// the given alias to the new cert.
     pub fn store_new_certificate(
         &mut self,
-        key: KeyDescriptor,
+        key: &KeyDescriptor,
         cert: &[u8],
         km_uuid: &Uuid,
     ) -> Result<KeyIdGuard> {
@@ -1289,7 +1778,7 @@
             }
         };
         self.with_transaction(TransactionBehavior::Immediate, |tx| {
-            let key_id = Self::create_key_entry_internal(tx, domain, namespace, km_uuid)
+            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))
@@ -1302,7 +1791,7 @@
 
             metadata.store_in_db(key_id.id(), tx).context("Trying to insert key metadata.")?;
 
-            Self::rebind_alias(tx, &key_id, &alias, domain, namespace)
+            Self::rebind_alias(tx, &key_id, &alias, &domain, namespace)
                 .context("Trying to rebind alias.")?;
             Ok(key_id)
         })
@@ -1355,7 +1844,7 @@
     /// check and the key id can be used to load further key artifacts.
     fn load_access_tuple(
         tx: &Transaction,
-        key: KeyDescriptor,
+        key: &KeyDescriptor,
         key_type: KeyType,
         caller_uid: u32,
     ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
@@ -1367,7 +1856,7 @@
             // of the caller supplied namespace if the domain field is
             // Domain::APP.
             Domain::APP | Domain::SELINUX => {
-                let mut access_key = key;
+                let mut access_key = key.clone();
                 if access_key.domain == Domain::APP {
                     access_key.nspace = caller_uid as i64;
                 }
@@ -1399,7 +1888,7 @@
                         ))
                     })
                     .context("Domain::GRANT.")?;
-                Ok((key_id, key, Some(access_vector.into())))
+                Ok((key_id, key.clone(), Some(access_vector.into())))
             }
 
             // Domain::KEY_ID. In this case we load the domain and namespace from the
@@ -1451,7 +1940,7 @@
                     };
 
                 let key_id = key.nspace;
-                let mut access_key = key;
+                let mut access_key: KeyDescriptor = key.clone();
                 access_key.domain = domain;
                 access_key.nspace = namespace;
 
@@ -1578,11 +2067,40 @@
     /// the blob database.
     pub fn load_key_entry(
         &mut self,
-        key: KeyDescriptor,
+        key: &KeyDescriptor,
         key_type: KeyType,
         load_bits: KeyEntryLoadBits,
         caller_uid: u32,
-        check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
+        check_permission: impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
+    ) -> Result<(KeyIdGuard, KeyEntry)> {
+        loop {
+            match self.load_key_entry_internal(
+                key,
+                key_type,
+                load_bits,
+                caller_uid,
+                &check_permission,
+            ) {
+                Ok(result) => break Ok(result),
+                Err(e) => {
+                    if Self::is_locked_error(&e) {
+                        std::thread::sleep(std::time::Duration::from_micros(500));
+                        continue;
+                    } else {
+                        return Err(e).context("In load_key_entry.");
+                    }
+                }
+            }
+        }
+    }
+
+    fn load_key_entry_internal(
+        &mut self,
+        key: &KeyDescriptor,
+        key_type: KeyType,
+        load_bits: KeyEntryLoadBits,
+        caller_uid: u32,
+        check_permission: &impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
     ) -> Result<(KeyIdGuard, KeyEntry)> {
         // KEY ID LOCK 1/2
         // If we got a key descriptor with a key id we can get the lock right away.
@@ -1627,15 +2145,16 @@
                     let key_id_guard = KEY_ID_LOCK.get(key_id);
 
                     // Create a new transaction.
-                    let tx = self.conn.unchecked_transaction().context(
-                        "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
-                    )?;
+                    let tx = self
+                        .conn
+                        .unchecked_transaction()
+                        .context("In load_key_entry: Failed to initialize transaction.")?;
 
                     Self::load_access_tuple(
                         &tx,
                         // This time we have to load the key by the retrieved key id, because the
                         // alias may have been rebound after we rolled back the transaction.
-                        KeyDescriptor {
+                        &KeyDescriptor {
                             domain: Domain::KEY_ID,
                             nspace: key_id,
                             ..Default::default()
@@ -1675,10 +2194,10 @@
     /// Returns Ok(true) if a key was marked unreferenced as a hint for the garbage collector.
     pub fn unbind_key(
         &mut self,
-        key: KeyDescriptor,
+        key: &KeyDescriptor,
         key_type: KeyType,
         caller_uid: u32,
-        check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
+        check_permission: impl Fn(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
     ) -> Result<bool> {
         self.with_transaction(TransactionBehavior::Immediate, |tx| {
             let (key_id, access_key_descriptor, access_vector) =
@@ -1737,30 +2256,31 @@
     /// The key descriptors will have the domain, nspace, and alias field set.
     /// Domain must be APP or SELINUX, the caller must make sure of that.
     pub fn list(&mut self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
-        let mut stmt = self
-            .conn
-            .prepare(
-                "SELECT alias FROM persistent.keyentry
+        self.with_transaction(TransactionBehavior::Deferred, |tx| {
+            let mut stmt = tx
+                .prepare(
+                    "SELECT alias FROM persistent.keyentry
              WHERE domain = ? AND namespace = ? AND alias IS NOT NULL AND state = ?;",
-            )
-            .context("In list: Failed to prepare.")?;
+                )
+                .context("In list: Failed to prepare.")?;
 
-        let mut rows = stmt
-            .query(params![domain.0 as u32, namespace, KeyLifeCycle::Live])
-            .context("In list: Failed to query.")?;
+            let mut rows = stmt
+                .query(params![domain.0 as u32, namespace, KeyLifeCycle::Live])
+                .context("In list: Failed to query.")?;
 
-        let mut descriptors: Vec<KeyDescriptor> = Vec::new();
-        db_utils::with_rows_extract_all(&mut rows, |row| {
-            descriptors.push(KeyDescriptor {
-                domain,
-                nspace: namespace,
-                alias: Some(row.get(0).context("Trying to extract alias.")?),
-                blob: None,
-            });
-            Ok(())
+            let mut descriptors: Vec<KeyDescriptor> = Vec::new();
+            db_utils::with_rows_extract_all(&mut rows, |row| {
+                descriptors.push(KeyDescriptor {
+                    domain,
+                    nspace: namespace,
+                    alias: Some(row.get(0).context("Trying to extract alias.")?),
+                    blob: None,
+                });
+                Ok(())
+            })
+            .context("In list: Failed to extract rows.")?;
+            Ok(descriptors)
         })
-        .context("In list.")?;
-        Ok(descriptors)
     }
 
     /// Adds a grant to the grant table.
@@ -1771,104 +2291,97 @@
     /// grant id in the namespace field of the resulting KeyDescriptor.
     pub fn grant(
         &mut self,
-        key: KeyDescriptor,
+        key: &KeyDescriptor,
         caller_uid: u32,
         grantee_uid: u32,
         access_vector: KeyPermSet,
-        check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
+        check_permission: impl Fn(&KeyDescriptor, &KeyPermSet) -> Result<()>,
     ) -> Result<KeyDescriptor> {
-        let tx = self
-            .conn
-            .transaction_with_behavior(TransactionBehavior::Immediate)
-            .context("In grant: Failed to initialize transaction.")?;
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            // Load the key_id and complete the access control tuple.
+            // We ignore the access vector here because grants cannot be granted.
+            // The access vector returned here expresses the permissions the
+            // grantee has if key.domain == Domain::GRANT. But this vector
+            // cannot include the grant permission by design, so there is no way the
+            // subsequent permission check can pass.
+            // We could check key.domain == Domain::GRANT and fail early.
+            // But even if we load the access tuple by grant here, the permission
+            // check denies the attempt to create a grant by grant descriptor.
+            let (key_id, access_key_descriptor, _) =
+                Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid)
+                    .context("In grant")?;
 
-        // Load the key_id and complete the access control tuple.
-        // We ignore the access vector here because grants cannot be granted.
-        // The access vector returned here expresses the permissions the
-        // grantee has if key.domain == Domain::GRANT. But this vector
-        // cannot include the grant permission by design, so there is no way the
-        // subsequent permission check can pass.
-        // We could check key.domain == Domain::GRANT and fail early.
-        // But even if we load the access tuple by grant here, the permission
-        // check denies the attempt to create a grant by grant descriptor.
-        let (key_id, access_key_descriptor, _) =
-            Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid).context("In grant")?;
+            // Perform access control. It is vital that we return here if the permission
+            // was denied. So do not touch that '?' at the end of the line.
+            // This permission check checks if the caller has the grant permission
+            // for the given key and in addition to all of the permissions
+            // expressed in `access_vector`.
+            check_permission(&access_key_descriptor, &access_vector)
+                .context("In grant: check_permission failed.")?;
 
-        // Perform access control. It is vital that we return here if the permission
-        // was denied. So do not touch that '?' at the end of the line.
-        // This permission check checks if the caller has the grant permission
-        // for the given key and in addition to all of the permissions
-        // expressed in `access_vector`.
-        check_permission(&access_key_descriptor, &access_vector)
-            .context("In grant: check_permission failed.")?;
-
-        let grant_id = if let Some(grant_id) = tx
-            .query_row(
-                "SELECT id FROM persistent.grant
+            let grant_id = if let Some(grant_id) = tx
+                .query_row(
+                    "SELECT id FROM persistent.grant
                 WHERE keyentryid = ? AND grantee = ?;",
-                params![key_id, grantee_uid],
-                |row| row.get(0),
-            )
-            .optional()
-            .context("In grant: Failed get optional existing grant id.")?
-        {
-            tx.execute(
-                "UPDATE persistent.grant
+                    params![key_id, grantee_uid],
+                    |row| row.get(0),
+                )
+                .optional()
+                .context("In grant: Failed get optional existing grant id.")?
+            {
+                tx.execute(
+                    "UPDATE persistent.grant
                     SET access_vector = ?
                     WHERE id = ?;",
-                params![i32::from(access_vector), grant_id],
-            )
-            .context("In grant: Failed to update existing grant.")?;
-            grant_id
-        } else {
-            Self::insert_with_retry(|id| {
-                tx.execute(
-                    "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector)
-                        VALUES (?, ?, ?, ?);",
-                    params![id, grantee_uid, key_id, i32::from(access_vector)],
+                    params![i32::from(access_vector), grant_id],
                 )
-            })
-            .context("In grant")?
-        };
-        tx.commit().context("In grant: failed to commit transaction.")?;
+                .context("In grant: Failed to update existing grant.")?;
+                grant_id
+            } else {
+                Self::insert_with_retry(|id| {
+                    tx.execute(
+                        "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector)
+                        VALUES (?, ?, ?, ?);",
+                        params![id, grantee_uid, key_id, i32::from(access_vector)],
+                    )
+                })
+                .context("In grant")?
+            };
 
-        Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
+            Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
+        })
     }
 
     /// This function checks permissions like `grant` and `load_key_entry`
     /// before removing a grant from the grant table.
     pub fn ungrant(
         &mut self,
-        key: KeyDescriptor,
+        key: &KeyDescriptor,
         caller_uid: u32,
         grantee_uid: u32,
-        check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
+        check_permission: impl Fn(&KeyDescriptor) -> Result<()>,
     ) -> Result<()> {
-        let tx = self
-            .conn
-            .transaction_with_behavior(TransactionBehavior::Immediate)
-            .context("In ungrant: Failed to initialize transaction.")?;
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            // Load the key_id and complete the access control tuple.
+            // We ignore the access vector here because grants cannot be granted.
+            let (key_id, access_key_descriptor, _) =
+                Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid)
+                    .context("In ungrant.")?;
 
-        // Load the key_id and complete the access control tuple.
-        // We ignore the access vector here because grants cannot be granted.
-        let (key_id, access_key_descriptor, _) =
-            Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid)
-                .context("In ungrant.")?;
+            // Perform access control. We must return here if the permission
+            // was denied. So do not touch the '?' at the end of this line.
+            check_permission(&access_key_descriptor)
+                .context("In grant: check_permission failed.")?;
 
-        // Perform access control. We must return here if the permission
-        // was denied. So do not touch the '?' at the end of this line.
-        check_permission(&access_key_descriptor).context("In grant: check_permission failed.")?;
-
-        tx.execute(
-            "DELETE FROM persistent.grant
+            tx.execute(
+                "DELETE FROM persistent.grant
                 WHERE keyentryid = ? AND grantee = ?;",
-            params![key_id, grantee_uid],
-        )
-        .context("Failed to delete grant.")?;
+                params![key_id, grantee_uid],
+            )
+            .context("Failed to delete grant.")?;
 
-        tx.commit().context("In ungrant: failed to commit transaction.")?;
-
-        Ok(())
+            Ok(())
+        })
     }
 
     // Generates a random id and passes it to the given function, which will
@@ -1896,8 +2409,8 @@
 
     /// Insert or replace the auth token based on the UNIQUE constraint of the auth token table
     pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) -> Result<()> {
-        self.conn
-            .execute(
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            tx.execute(
                 "INSERT OR REPLACE INTO perboot.authtoken (challenge, user_id, auth_id,
             authenticator_type, timestamp, mac, time_received) VALUES(?, ?, ?, ?, ?, ?, ?);",
                 params![
@@ -1911,7 +2424,8 @@
                 ],
             )
             .context("In insert_auth_token: failed to insert auth token into the database")?;
-        Ok(())
+            Ok(())
+        })
     }
 
     /// Find the newest auth token matching the given predicate.
@@ -1955,25 +2469,27 @@
     }
 
     /// Insert last_off_body into the metadata table at the initialization of auth token table
-    pub fn insert_last_off_body(&self, last_off_body: MonotonicRawTime) -> Result<()> {
-        self.conn
-            .execute(
+    pub fn insert_last_off_body(&mut self, last_off_body: MonotonicRawTime) -> Result<()> {
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            tx.execute(
                 "INSERT OR REPLACE INTO perboot.metadata (key, value) VALUES (?, ?);",
                 params!["last_off_body", last_off_body],
             )
             .context("In insert_last_off_body: failed to insert.")?;
-        Ok(())
+            Ok(())
+        })
     }
 
     /// Update last_off_body when on_device_off_body is called
-    pub fn update_last_off_body(&self, last_off_body: MonotonicRawTime) -> Result<()> {
-        self.conn
-            .execute(
+    pub fn update_last_off_body(&mut self, last_off_body: MonotonicRawTime) -> Result<()> {
+        self.with_transaction(TransactionBehavior::Immediate, |tx| {
+            tx.execute(
                 "UPDATE perboot.metadata SET value = ? WHERE key = ?;",
                 params![last_off_body, "last_off_body"],
             )
             .context("In update_last_off_body: failed to update.")?;
-        Ok(())
+            Ok(())
+        })
     }
 
     /// Get last_off_body time when finding auth tokens
@@ -2012,12 +2528,17 @@
     use std::sync::Arc;
     use std::thread;
     use std::time::{Duration, SystemTime};
+    #[cfg(disabled)]
+    use std::time::Instant;
 
     fn new_test_db() -> Result<KeystoreDB> {
         let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
 
-        KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
-        Ok(KeystoreDB { conn })
+        let mut db = KeystoreDB { conn };
+        db.with_transaction(TransactionBehavior::Immediate, |tx| {
+            KeystoreDB::init_tables(tx).context("Failed to initialize tables.")
+        })?;
+        Ok(db)
     }
 
     fn rebind_alias(
@@ -2028,7 +2549,7 @@
         namespace: i64,
     ) -> Result<bool> {
         db.with_transaction(TransactionBehavior::Immediate, |tx| {
-            KeystoreDB::rebind_alias(tx, newid, alias, domain, namespace)
+            KeystoreDB::rebind_alias(tx, newid, alias, &domain, &namespace)
         })
         .context("In rebind_alias.")
     }
@@ -2177,7 +2698,7 @@
         let temp_dir = TempDir::new("persistent_db_test")?;
         let mut db = KeystoreDB::new(temp_dir.path())?;
 
-        db.create_key_entry(Domain::APP, 100, &KEYSTORE_UUID)?;
+        db.create_key_entry(&Domain::APP, &100, &KEYSTORE_UUID)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 1);
 
@@ -2196,8 +2717,8 @@
 
         let mut db = new_test_db()?;
 
-        db.create_key_entry(Domain::APP, 100, &KEYSTORE_UUID)?;
-        db.create_key_entry(Domain::SELINUX, 101, &KEYSTORE_UUID)?;
+        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);
@@ -2206,15 +2727,15 @@
 
         // Test that we must pass in a valid Domain.
         check_result_is_error_containing_string(
-            db.create_key_entry(Domain::GRANT, 102, &KEYSTORE_UUID),
+            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, &KEYSTORE_UUID),
+            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, &KEYSTORE_UUID),
+            db.create_key_entry(&Domain::KEY_ID, &104, &KEYSTORE_UUID),
             "Domain Domain(4) must be either App or SELinux.",
         );
 
@@ -2222,6 +2743,148 @@
     }
 
     #[test]
+    fn test_add_unsigned_key() -> Result<()> {
+        let mut db = new_test_db()?;
+        let public_key: Vec<u8> = vec![0x01, 0x02, 0x03];
+        let private_key: Vec<u8> = vec![0x04, 0x05, 0x06];
+        let raw_public_key: Vec<u8> = vec![0x07, 0x08, 0x09];
+        db.create_attestation_key_entry(
+            &public_key,
+            &raw_public_key,
+            &private_key,
+            &KEYSTORE_UUID,
+        )?;
+        let keys = db.fetch_unsigned_attestation_keys(5, &KEYSTORE_UUID)?;
+        assert_eq!(keys.len(), 1);
+        assert_eq!(keys[0], public_key);
+        Ok(())
+    }
+
+    #[test]
+    fn test_store_signed_attestation_certificate_chain() -> Result<()> {
+        let mut db = new_test_db()?;
+        let expiration_date: i64 = 20;
+        let namespace: i64 = 30;
+        let base_byte: u8 = 1;
+        let loaded_values =
+            load_attestation_key_pool(&mut db, expiration_date, namespace, base_byte)?;
+        let chain =
+            db.retrieve_attestation_key_and_cert_chain(Domain::APP, namespace, &KEYSTORE_UUID)?;
+        assert_eq!(true, chain.is_some());
+        let cert_chain = chain.unwrap();
+        assert_eq!(cert_chain.private_key.to_vec(), loaded_values[2]);
+        assert_eq!(cert_chain.cert_chain.to_vec(), loaded_values[1]);
+        Ok(())
+    }
+
+    #[test]
+    fn test_get_attestation_pool_status() -> Result<()> {
+        let mut db = new_test_db()?;
+        let namespace: i64 = 30;
+        load_attestation_key_pool(
+            &mut db, 10, /* expiration */
+            namespace, 0x01, /* base_byte */
+        )?;
+        load_attestation_key_pool(&mut db, 20 /* expiration */, namespace + 1, 0x02)?;
+        load_attestation_key_pool(&mut db, 40 /* expiration */, namespace + 2, 0x03)?;
+        let mut status = db.get_attestation_pool_status(9 /* expiration */, &KEYSTORE_UUID)?;
+        assert_eq!(status.expiring, 0);
+        assert_eq!(status.attested, 3);
+        assert_eq!(status.unassigned, 0);
+        assert_eq!(status.total, 3);
+        assert_eq!(
+            db.get_attestation_pool_status(15 /* expiration */, &KEYSTORE_UUID)?.expiring,
+            1
+        );
+        assert_eq!(
+            db.get_attestation_pool_status(25 /* expiration */, &KEYSTORE_UUID)?.expiring,
+            2
+        );
+        assert_eq!(
+            db.get_attestation_pool_status(60 /* expiration */, &KEYSTORE_UUID)?.expiring,
+            3
+        );
+        let public_key: Vec<u8> = vec![0x01, 0x02, 0x03];
+        let private_key: Vec<u8> = vec![0x04, 0x05, 0x06];
+        let raw_public_key: Vec<u8> = vec![0x07, 0x08, 0x09];
+        let cert_chain: Vec<u8> = vec![0x0a, 0x0b, 0x0c];
+        db.create_attestation_key_entry(
+            &public_key,
+            &raw_public_key,
+            &private_key,
+            &KEYSTORE_UUID,
+        )?;
+        status = db.get_attestation_pool_status(0 /* expiration */, &KEYSTORE_UUID)?;
+        assert_eq!(status.attested, 3);
+        assert_eq!(status.unassigned, 0);
+        assert_eq!(status.total, 4);
+        db.store_signed_attestation_certificate_chain(
+            &raw_public_key,
+            &cert_chain,
+            20,
+            &KEYSTORE_UUID,
+        )?;
+        status = db.get_attestation_pool_status(0 /* expiration */, &KEYSTORE_UUID)?;
+        assert_eq!(status.attested, 4);
+        assert_eq!(status.unassigned, 1);
+        assert_eq!(status.total, 4);
+        Ok(())
+    }
+
+    #[test]
+    fn test_remove_expired_certs() -> Result<()> {
+        let mut db = new_test_db()?;
+        let expiration_date: i64 =
+            SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as i64 + 10000;
+        let namespace: i64 = 30;
+        let namespace_del1: i64 = 45;
+        let namespace_del2: i64 = 60;
+        let entry_values = load_attestation_key_pool(
+            &mut db,
+            expiration_date,
+            namespace,
+            0x01, /* base_byte */
+        )?;
+        load_attestation_key_pool(&mut db, 45, namespace_del1, 0x02)?;
+        load_attestation_key_pool(&mut db, 60, namespace_del2, 0x03)?;
+        assert_eq!(db.delete_expired_attestation_keys()?, 2);
+
+        let mut cert_chain =
+            db.retrieve_attestation_key_and_cert_chain(Domain::APP, namespace, &KEYSTORE_UUID)?;
+        assert_eq!(true, cert_chain.is_some());
+        let value = cert_chain.unwrap();
+        assert_eq!(entry_values[1], value.cert_chain.to_vec());
+        assert_eq!(entry_values[2], value.private_key.to_vec());
+
+        cert_chain = db.retrieve_attestation_key_and_cert_chain(
+            Domain::APP,
+            namespace_del1,
+            &KEYSTORE_UUID,
+        )?;
+        assert_eq!(false, cert_chain.is_some());
+        cert_chain = db.retrieve_attestation_key_and_cert_chain(
+            Domain::APP,
+            namespace_del2,
+            &KEYSTORE_UUID,
+        )?;
+        assert_eq!(false, cert_chain.is_some());
+
+        let mut option_entry = db.get_unreferenced_key()?;
+        assert_eq!(true, option_entry.is_some());
+        let (key_guard, _) = option_entry.unwrap();
+        db.purge_key_entry(key_guard)?;
+
+        option_entry = db.get_unreferenced_key()?;
+        assert_eq!(true, option_entry.is_some());
+        let (key_guard, _) = option_entry.unwrap();
+        db.purge_key_entry(key_guard)?;
+
+        option_entry = db.get_unreferenced_key()?;
+        assert_eq!(false, option_entry.is_some());
+        Ok(())
+    }
+
+    #[test]
     fn test_rebind_alias() -> Result<()> {
         fn extractor(
             ke: &KeyEntryRow,
@@ -2230,8 +2893,8 @@
         }
 
         let mut db = new_test_db()?;
-        db.create_key_entry(Domain::APP, 42, &KEYSTORE_UUID)?;
-        db.create_key_entry(Domain::APP, 42, &KEYSTORE_UUID)?;
+        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!(
@@ -2324,7 +2987,7 @@
         let next_random = 0i64;
 
         let app_granted_key = db
-            .grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
+            .grant(&app_key, CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
                 assert_eq!(*a, PVEC1);
                 assert_eq!(
                     *k,
@@ -2359,7 +3022,7 @@
         };
 
         let selinux_granted_key = db
-            .grant(selinux_key.clone(), CALLER_UID, 12, PVEC1, |k, a| {
+            .grant(&selinux_key, CALLER_UID, 12, PVEC1, |k, a| {
                 assert_eq!(*a, PVEC1);
                 assert_eq!(
                     *k,
@@ -2389,7 +3052,7 @@
 
         // This should update the existing grant with PVEC2.
         let selinux_granted_key = db
-            .grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
+            .grant(&selinux_key, CALLER_UID, 12, PVEC2, |k, a| {
                 assert_eq!(*a, PVEC2);
                 assert_eq!(
                     *k,
@@ -2443,8 +3106,8 @@
         println!("app_key {:?}", app_key);
         println!("selinux_key {:?}", selinux_key);
 
-        db.ungrant(app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
-        db.ungrant(selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
+        db.ungrant(&app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
+        db.ungrant(&selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
 
         Ok(())
     }
@@ -2490,7 +3153,7 @@
             .0;
         let (_key_guard, key_entry) = db
             .load_key_entry(
-                KeyDescriptor {
+                &KeyDescriptor {
                     domain: Domain::APP,
                     nspace: 0,
                     alias: Some(TEST_ALIAS.to_string()),
@@ -2505,7 +3168,7 @@
         assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
 
         db.unbind_key(
-            KeyDescriptor {
+            &KeyDescriptor {
                 domain: Domain::APP,
                 nspace: 0,
                 alias: Some(TEST_ALIAS.to_string()),
@@ -2520,7 +3183,7 @@
         assert_eq!(
             Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
             db.load_key_entry(
-                KeyDescriptor {
+                &KeyDescriptor {
                     domain: Domain::APP,
                     nspace: 0,
                     alias: Some(TEST_ALIAS.to_string()),
@@ -2544,7 +3207,7 @@
         let mut db = new_test_db()?;
 
         db.store_new_certificate(
-            KeyDescriptor {
+            &KeyDescriptor {
                 domain: Domain::APP,
                 nspace: 1,
                 alias: Some(TEST_ALIAS.to_string()),
@@ -2557,7 +3220,7 @@
 
         let (_key_guard, mut key_entry) = db
             .load_key_entry(
-                KeyDescriptor {
+                &KeyDescriptor {
                     domain: Domain::APP,
                     nspace: 1,
                     alias: Some(TEST_ALIAS.to_string()),
@@ -2575,7 +3238,7 @@
         assert_eq!(key_entry.take_cert_chain(), Some(TEST_CERT_BLOB.to_vec()));
 
         db.unbind_key(
-            KeyDescriptor {
+            &KeyDescriptor {
                 domain: Domain::APP,
                 nspace: 1,
                 alias: Some(TEST_ALIAS.to_string()),
@@ -2590,7 +3253,7 @@
         assert_eq!(
             Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
             db.load_key_entry(
-                KeyDescriptor {
+                &KeyDescriptor {
                     domain: Domain::APP,
                     nspace: 1,
                     alias: Some(TEST_ALIAS.to_string()),
@@ -2617,7 +3280,7 @@
             .0;
         let (_key_guard, key_entry) = db
             .load_key_entry(
-                KeyDescriptor {
+                &KeyDescriptor {
                     domain: Domain::SELINUX,
                     nspace: 1,
                     alias: Some(TEST_ALIAS.to_string()),
@@ -2632,7 +3295,7 @@
         assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
 
         db.unbind_key(
-            KeyDescriptor {
+            &KeyDescriptor {
                 domain: Domain::SELINUX,
                 nspace: 1,
                 alias: Some(TEST_ALIAS.to_string()),
@@ -2647,7 +3310,7 @@
         assert_eq!(
             Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
             db.load_key_entry(
-                KeyDescriptor {
+                &KeyDescriptor {
                     domain: Domain::SELINUX,
                     nspace: 1,
                     alias: Some(TEST_ALIAS.to_string()),
@@ -2674,7 +3337,7 @@
             .0;
         let (_, key_entry) = db
             .load_key_entry(
-                KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
+                &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
                 KeyType::Client,
                 KeyEntryLoadBits::BOTH,
                 1,
@@ -2685,7 +3348,7 @@
         assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
 
         db.unbind_key(
-            KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
+            &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
             KeyType::Client,
             1,
             |_, _| Ok(()),
@@ -2695,7 +3358,7 @@
         assert_eq!(
             Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
             db.load_key_entry(
-                KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
+                &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
                 KeyType::Client,
                 KeyEntryLoadBits::NONE,
                 1,
@@ -2719,7 +3382,7 @@
         db.check_and_update_key_usage_count(key_id)?;
 
         let (_key_guard, key_entry) = db.load_key_entry(
-            KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
+            &KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
             KeyType::Client,
             KeyEntryLoadBits::BOTH,
             1,
@@ -2766,7 +3429,7 @@
 
         let granted_key = db
             .grant(
-                KeyDescriptor {
+                &KeyDescriptor {
                     domain: Domain::APP,
                     nspace: 0,
                     alias: Some(TEST_ALIAS.to_string()),
@@ -2782,27 +3445,21 @@
         debug_dump_grant_table(&mut db)?;
 
         let (_key_guard, key_entry) = db
-            .load_key_entry(
-                granted_key.clone(),
-                KeyType::Client,
-                KeyEntryLoadBits::BOTH,
-                2,
-                |k, av| {
-                    assert_eq!(Domain::GRANT, k.domain);
-                    assert!(av.unwrap().includes(KeyPerm::use_()));
-                    Ok(())
-                },
-            )
+            .load_key_entry(&granted_key, KeyType::Client, KeyEntryLoadBits::BOTH, 2, |k, av| {
+                assert_eq!(Domain::GRANT, k.domain);
+                assert!(av.unwrap().includes(KeyPerm::use_()));
+                Ok(())
+            })
             .unwrap();
 
         assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
 
-        db.unbind_key(granted_key.clone(), KeyType::Client, 2, |_, _| Ok(())).unwrap();
+        db.unbind_key(&granted_key, KeyType::Client, 2, |_, _| Ok(())).unwrap();
 
         assert_eq!(
             Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
             db.load_key_entry(
-                granted_key,
+                &granted_key,
                 KeyType::Client,
                 KeyEntryLoadBits::NONE,
                 2,
@@ -2829,7 +3486,7 @@
             .0;
 
         db.grant(
-            KeyDescriptor {
+            &KeyDescriptor {
                 domain: Domain::APP,
                 nspace: 0,
                 alias: Some(TEST_ALIAS.to_string()),
@@ -2849,7 +3506,7 @@
 
         let (_, key_entry) = db
             .load_key_entry(
-                id_descriptor.clone(),
+                &id_descriptor,
                 KeyType::Client,
                 KeyEntryLoadBits::BOTH,
                 GRANTEE_UID,
@@ -2866,7 +3523,7 @@
 
         let (_, key_entry) = db
             .load_key_entry(
-                id_descriptor.clone(),
+                &id_descriptor,
                 KeyType::Client,
                 KeyEntryLoadBits::BOTH,
                 SOMEONE_ELSE_UID,
@@ -2881,12 +3538,12 @@
 
         assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
 
-        db.unbind_key(id_descriptor.clone(), KeyType::Client, OWNER_UID, |_, _| Ok(())).unwrap();
+        db.unbind_key(&id_descriptor, KeyType::Client, OWNER_UID, |_, _| Ok(())).unwrap();
 
         assert_eq!(
             Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
             db.load_key_entry(
-                id_descriptor,
+                &id_descriptor,
                 KeyType::Client,
                 KeyEntryLoadBits::NONE,
                 GRANTEE_UID,
@@ -2913,7 +3570,7 @@
                 .0;
             let (_key_guard, key_entry) = db
                 .load_key_entry(
-                    KeyDescriptor {
+                    &KeyDescriptor {
                         domain: Domain::APP,
                         nspace: 0,
                         alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
@@ -2941,7 +3598,7 @@
                 let mut db = KeystoreDB::new(temp_dir.path()).unwrap();
                 assert!(db
                     .load_key_entry(
-                        KeyDescriptor {
+                        &KeyDescriptor {
                             domain: Domain::APP,
                             nspace: 0,
                             alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
@@ -2977,6 +3634,169 @@
     }
 
     #[test]
+    fn teset_database_busy_error_code() {
+        let temp_dir =
+            TempDir::new("test_database_busy_error_code_").expect("Failed to create temp dir.");
+
+        let mut db1 = KeystoreDB::new(temp_dir.path()).expect("Failed to open database1.");
+        let mut db2 = KeystoreDB::new(temp_dir.path()).expect("Failed to open database2.");
+
+        let _tx1 = db1
+            .conn
+            .transaction_with_behavior(TransactionBehavior::Immediate)
+            .expect("Failed to create first transaction.");
+
+        let error = db2
+            .conn
+            .transaction_with_behavior(TransactionBehavior::Immediate)
+            .context("Transaction begin failed.")
+            .expect_err("This should fail.");
+        let root_cause = error.root_cause();
+        if let Some(rusqlite::ffi::Error { code: rusqlite::ErrorCode::DatabaseBusy, .. }) =
+            root_cause.downcast_ref::<rusqlite::ffi::Error>()
+        {
+            return;
+        }
+        panic!(
+            "Unexpected error {:?} \n{:?} \n{:?}",
+            error,
+            root_cause,
+            root_cause.downcast_ref::<rusqlite::ffi::Error>()
+        )
+    }
+
+    #[cfg(disabled)]
+    #[test]
+    fn test_large_number_of_concurrent_db_manipulations() -> Result<()> {
+        let temp_dir = Arc::new(
+            TempDir::new("test_large_number_of_concurrent_db_manipulations_")
+                .expect("Failed to create temp dir."),
+        );
+
+        let test_begin = Instant::now();
+
+        let mut db = KeystoreDB::new(temp_dir.path()).expect("Failed to open database.");
+        const KEY_COUNT: u32 = 500u32;
+        const OPEN_DB_COUNT: u32 = 50u32;
+
+        let mut actual_key_count = KEY_COUNT;
+        // First insert KEY_COUNT keys.
+        for count in 0..KEY_COUNT {
+            if Instant::now().duration_since(test_begin) >= Duration::from_secs(15) {
+                actual_key_count = count;
+                break;
+            }
+            let alias = format!("test_alias_{}", count);
+            make_test_key_entry(&mut db, Domain::APP, 1, &alias, None)
+                .expect("Failed to make key entry.");
+        }
+
+        // Insert more keys from a different thread and into a different namespace.
+        let temp_dir1 = temp_dir.clone();
+        let handle1 = thread::spawn(move || {
+            let mut db = KeystoreDB::new(temp_dir1.path()).expect("Failed to open database.");
+
+            for count in 0..actual_key_count {
+                if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) {
+                    return;
+                }
+                let alias = format!("test_alias_{}", count);
+                make_test_key_entry(&mut db, Domain::APP, 2, &alias, None)
+                    .expect("Failed to make key entry.");
+            }
+
+            // then unbind them again.
+            for count in 0..actual_key_count {
+                if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) {
+                    return;
+                }
+                let key = KeyDescriptor {
+                    domain: Domain::APP,
+                    nspace: -1,
+                    alias: Some(format!("test_alias_{}", count)),
+                    blob: None,
+                };
+                db.unbind_key(&key, KeyType::Client, 2, |_, _| Ok(())).expect("Unbind Failed.");
+            }
+        });
+
+        // And start unbinding the first set of keys.
+        let temp_dir2 = temp_dir.clone();
+        let handle2 = thread::spawn(move || {
+            let mut db = KeystoreDB::new(temp_dir2.path()).expect("Failed to open database.");
+
+            for count in 0..actual_key_count {
+                if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) {
+                    return;
+                }
+                let key = KeyDescriptor {
+                    domain: Domain::APP,
+                    nspace: -1,
+                    alias: Some(format!("test_alias_{}", count)),
+                    blob: None,
+                };
+                db.unbind_key(&key, KeyType::Client, 1, |_, _| Ok(())).expect("Unbind Failed.");
+            }
+        });
+
+        let stop_deleting = Arc::new(AtomicU8::new(0));
+        let stop_deleting2 = stop_deleting.clone();
+
+        // And delete anything that is unreferenced keys.
+        let temp_dir3 = temp_dir.clone();
+        let handle3 = thread::spawn(move || {
+            let mut db = KeystoreDB::new(temp_dir3.path()).expect("Failed to open database.");
+
+            while stop_deleting2.load(Ordering::Relaxed) != 1 {
+                while let Some((key_guard, _key)) =
+                    db.get_unreferenced_key().expect("Failed to get unreferenced Key.")
+                {
+                    if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) {
+                        return;
+                    }
+                    db.purge_key_entry(key_guard).expect("Failed to purge key.");
+                }
+                std::thread::sleep(std::time::Duration::from_millis(100));
+            }
+        });
+
+        // While a lot of inserting and deleting is going on we have to open database connections
+        // successfully and use them.
+        // This clone is not redundant, because temp_dir needs to be kept alive until db goes
+        // out of scope.
+        #[allow(clippy::redundant_clone)]
+        let temp_dir4 = temp_dir.clone();
+        let handle4 = thread::spawn(move || {
+            for count in 0..OPEN_DB_COUNT {
+                if Instant::now().duration_since(test_begin) >= Duration::from_secs(40) {
+                    return;
+                }
+                let mut db = KeystoreDB::new(temp_dir4.path()).expect("Failed to open database.");
+
+                let alias = format!("test_alias_{}", count);
+                make_test_key_entry(&mut db, Domain::APP, 3, &alias, None)
+                    .expect("Failed to make key entry.");
+                let key = KeyDescriptor {
+                    domain: Domain::APP,
+                    nspace: -1,
+                    alias: Some(alias),
+                    blob: None,
+                };
+                db.unbind_key(&key, KeyType::Client, 3, |_, _| Ok(())).expect("Unbind Failed.");
+            }
+        });
+
+        handle1.join().expect("Thread 1 panicked.");
+        handle2.join().expect("Thread 2 panicked.");
+        handle4.join().expect("Thread 4 panicked.");
+
+        stop_deleting.store(1, Ordering::Relaxed);
+        handle3.join().expect("Thread 3 panicked.");
+
+        Ok(())
+    }
+
+    #[test]
     fn list() -> Result<()> {
         let temp_dir = TempDir::new("list_test")?;
         let mut db = KeystoreDB::new(temp_dir.path())?;
@@ -3040,7 +3860,7 @@
                 .map(|d| {
                     let (_, entry) = db
                         .load_key_entry(
-                            d,
+                            &d,
                             KeyType::Client,
                             KeyEntryLoadBits::NONE,
                             *namespace as u32,
@@ -3115,6 +3935,32 @@
             .collect::<Result<Vec<_>>>()
     }
 
+    fn load_attestation_key_pool(
+        db: &mut KeystoreDB,
+        expiration_date: i64,
+        namespace: i64,
+        base_byte: u8,
+    ) -> Result<Vec<Vec<u8>>> {
+        let mut chain: Vec<Vec<u8>> = Vec::new();
+        let public_key: Vec<u8> = vec![base_byte, 0x02 * base_byte];
+        let cert_chain: Vec<u8> = vec![0x03 * base_byte, 0x04 * base_byte];
+        let priv_key: Vec<u8> = vec![0x05 * base_byte, 0x06 * base_byte];
+        let raw_public_key: Vec<u8> = vec![0x0b * base_byte, 0x0c * base_byte];
+        db.create_attestation_key_entry(&public_key, &raw_public_key, &priv_key, &KEYSTORE_UUID)?;
+        db.store_signed_attestation_certificate_chain(
+            &raw_public_key,
+            &cert_chain,
+            expiration_date,
+            &KEYSTORE_UUID,
+        )?;
+        db.assign_attestation_key(Domain::APP, namespace, &KEYSTORE_UUID)?;
+        chain.push(public_key);
+        chain.push(cert_chain);
+        chain.push(priv_key);
+        chain.push(raw_public_key);
+        Ok(chain)
+    }
+
     // Note: The parameters and SecurityLevel associations are nonsensical. This
     // collection is only used to check if the parameters are preserved as expected by the
     // database.
@@ -3351,7 +4197,7 @@
         alias: &str,
         max_usage_count: Option<i32>,
     ) -> Result<KeyIdGuard> {
-        let key_id = db.create_key_entry(domain, namespace, &KEYSTORE_UUID)?;
+        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))?;
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
index 93de6f2..117dea8 100644
--- a/keystore2/src/key_parameter.rs
+++ b/keystore2/src/key_parameter.rs
@@ -948,9 +948,23 @@
     #[key_param(tag = RESET_SINCE_ID_ROTATION, field = BoolValue)]
     ResetSinceIdRotation,
     /// Used to deliver a cryptographic token proving that the user
-    ///  confirmed a signing request
+    /// confirmed a signing request
     #[key_param(tag = CONFIRMATION_TOKEN, field = Blob)]
     ConfirmationToken(Vec<u8>),
+    /// Used to deliver the certificate serial number to the KeyMint instance
+    /// certificate generation.
+    #[key_param(tag = CERTIFICATE_SERIAL, field = Blob)]
+    CertificateSerial(Vec<u8>),
+    /// Used to deliver the certificate subject to the KeyMint instance
+    /// certificate generation. This must be DER encoded X509 name.
+    #[key_param(tag = CERTIFICATE_SUBJECT, field = Blob)]
+    CertificateSubject(Vec<u8>),
+    /// Used to deliver the not before date in milliseconds to KeyMint during key generation/import.
+    #[key_param(tag = CERTIFICATE_NOT_BEFORE, field = DateTime)]
+    CertificateNotBefore(i64),
+    /// Used to deliver the not after date in milliseconds to KeyMint during key generation/import.
+    #[key_param(tag = CERTIFICATE_NOT_AFTER, field = DateTime)]
+    CertificateNotAfter(i64),
 }
 }
 
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index 601baf1..93a8b70 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -30,6 +30,8 @@
 #include <keymasterV4_1/Keymaster3.h>
 #include <keymasterV4_1/Keymaster4.h>
 
+#include <chrono>
+
 #include "certificate_utils.h"
 
 using ::aidl::android::hardware::security::keymint::Algorithm;
@@ -50,6 +52,9 @@
 namespace V4_1 = ::android::hardware::keymaster::V4_1;
 namespace KMV1 = ::aidl::android::hardware::security::keymint;
 
+using namespace std::chrono_literals;
+using std::chrono::duration_cast;
+
 // Utility functions
 
 ScopedAStatus convertErrorCode(KMV1::ErrorCode result) {
@@ -579,21 +584,34 @@
     CBS cbs;
     CBS_init(&cbs, key.data(), key.size());
     auto pkey = EVP_parse_public_key(&cbs);
+
     // makeCert
-    // TODO: Get the serial and subject from key params once the tags are added.  Also use new tags
-    // for the two datetime parameters once we get those.
+    std::optional<std::reference_wrapper<const std::vector<uint8_t>>> subject;
+    if (auto blob = getParam(keyParams, KMV1::TAG_CERTIFICATE_SUBJECT)) {
+        subject = *blob;
+    }
+
+    std::optional<std::reference_wrapper<const std::vector<uint8_t>>> serial;
+    if (auto blob = getParam(keyParams, KMV1::TAG_CERTIFICATE_SERIAL)) {
+        serial = *blob;
+    }
 
     uint64_t activation = 0;
-    if (auto date = getParam(keyParams, KMV1::TAG_ACTIVE_DATETIME)) {
+    if (auto date = getParam(keyParams, KMV1::TAG_CERTIFICATE_NOT_BEFORE)) {
         activation = *date;
+    } else {
+        return KMV1::ErrorCode::MISSING_NOT_BEFORE;
     }
-    uint64_t expiration = std::numeric_limits<uint64_t>::max();
-    if (auto date = getParam(keyParams, KMV1::TAG_USAGE_EXPIRE_DATETIME)) {
+
+    uint64_t expiration;
+    if (auto date = getParam(keyParams, KMV1::TAG_CERTIFICATE_NOT_AFTER)) {
         expiration = *date;
+    } else {
+        return KMV1::ErrorCode::MISSING_NOT_AFTER;
     }
 
     auto certOrError = keystore::makeCert(
-        pkey, 42, "TODO", activation, expiration, false /* intentionally left blank */,
+        pkey, serial, subject, activation, expiration, false /* intentionally left blank */,
         std::nullopt /* intentionally left blank */, std::nullopt /* intentionally left blank */);
     if (std::holds_alternative<keystore::CertUtilsError>(certOrError)) {
         LOG(ERROR) << __func__ << ": Failed to make certificate";
diff --git a/keystore2/src/km_compat/km_compat_type_conversion.h b/keystore2/src/km_compat/km_compat_type_conversion.h
index 5fdca91..b36b78a 100644
--- a/keystore2/src/km_compat/km_compat_type_conversion.h
+++ b/keystore2/src/km_compat/km_compat_type_conversion.h
@@ -734,7 +734,11 @@
         }
         break;
     case KMV1::Tag::RSA_OAEP_MGF_DIGEST:
-        // Does not exist in KM < KeyMint 1.0.
+    case KMV1::Tag::CERTIFICATE_SERIAL:
+    case KMV1::Tag::CERTIFICATE_SUBJECT:
+    case KMV1::Tag::CERTIFICATE_NOT_BEFORE:
+    case KMV1::Tag::CERTIFICATE_NOT_AFTER:
+        // These tags do not exist in KM < KeyMint 1.0.
         break;
     }
     return V4_0::KeyParameter{.tag = V4_0::Tag::INVALID};
diff --git a/keystore2/src/km_compat/lib.rs b/keystore2/src/km_compat/lib.rs
index d264e7a..097e6d4 100644
--- a/keystore2/src/km_compat/lib.rs
+++ b/keystore2/src/km_compat/lib.rs
@@ -76,6 +76,10 @@
         creation_result
     }
 
+    // Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to GeneralizedTime
+    // 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
+    const UNDEFINED_NOT_AFTER: i64 = 253402300799000i64;
+
     fn generate_rsa_key(legacy: &dyn IKeyMintDevice, encrypt: bool, attest: bool) -> Vec<u8> {
         let mut kps = vec![
             KeyParameter {
@@ -97,6 +101,14 @@
                 tag: Tag::PURPOSE,
                 value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
             },
+            KeyParameter {
+                tag: Tag::CERTIFICATE_NOT_BEFORE,
+                value: KeyParameterValue::DateTime(0),
+            },
+            KeyParameter {
+                tag: Tag::CERTIFICATE_NOT_AFTER,
+                value: KeyParameterValue::DateTime(UNDEFINED_NOT_AFTER),
+            },
         ];
         if encrypt {
             kps.push(KeyParameter {
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
index 811db91..f9554ea 100644
--- a/keystore2/src/lib.rs
+++ b/keystore2/src/lib.rs
@@ -26,6 +26,7 @@
 pub mod legacy_blob;
 pub mod operation;
 pub mod permission;
+pub mod remote_provisioning;
 pub mod security_level;
 pub mod service;
 pub mod utils;
diff --git a/keystore2/src/remote_provisioning.rs b/keystore2/src/remote_provisioning.rs
new file mode 100644
index 0000000..eb21671
--- /dev/null
+++ b/keystore2/src/remote_provisioning.rs
@@ -0,0 +1,155 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This is the implementation for the remote provisioning AIDL interface between
+//! the network providers for remote provisioning and the system. This interface
+//! allows the caller to prompt the Remote Provisioning HAL to generate keys and
+//! CBOR blobs that can be ferried to a provisioning server that will return
+//! certificate chains signed by some root authority and stored in a keystore SQLite
+//! DB.
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
+
+use android_security_remoteprovisioning::aidl::android::security::remoteprovisioning::{
+    AttestationPoolStatus::AttestationPoolStatus, IRemoteProvisioning::BnRemoteProvisioning,
+    IRemoteProvisioning::IRemoteProvisioning,
+};
+use anyhow::Result;
+
+use crate::error::map_or_log_err;
+use crate::globals::{get_keymint_device, DB};
+
+/// Implementation of the IRemoteProvisioning service.
+pub struct RemoteProvisioningService {
+    // TODO(b/179222809): Add the remote provisioner hal aidl interface when available
+}
+
+impl RemoteProvisioningService {
+    /// Creates a new instance of the remote provisioning service
+    pub fn new_native_binder() -> Result<impl IRemoteProvisioning> {
+        let result = BnRemoteProvisioning::new_binder(Self {});
+        Ok(result)
+    }
+
+    /// Populates the AttestationPoolStatus parcelable with information about how many
+    /// certs will be expiring by the date provided in `expired_by` along with how many
+    /// keys have not yet been assigned.
+    pub fn get_pool_status(
+        &self,
+        expired_by: i64,
+        sec_level: SecurityLevel,
+    ) -> Result<AttestationPoolStatus> {
+        let (_, _, uuid) = get_keymint_device(&sec_level)?;
+        DB.with::<_, Result<AttestationPoolStatus>>(|db| {
+            let mut db = db.borrow_mut();
+            Ok(db.get_attestation_pool_status(expired_by, &uuid)?)
+        })
+    }
+
+    /// Generates a CBOR blob which will be assembled by the calling code into a larger
+    /// CBOR blob intended for delivery to a provisioning serever. This blob will contain
+    /// `num_csr` certificate signing requests for attestation keys generated in the TEE,
+    /// along with a server provided `eek` and `challenge`. The endpoint encryption key will
+    /// be used to encrypt the sensitive contents being transmitted to the server, and the
+    /// challenge will ensure freshness. A `test_mode` flag will instruct the remote provisioning
+    /// HAL if it is okay to accept EEKs that aren't signed by something that chains back to the
+    /// baked in root of trust in the underlying IRemotelyProvisionedComponent instance.
+    pub fn generate_csr(
+        &self,
+        _test_mode: bool,
+        _num_csr: i32,
+        _eek: &[u8],
+        _challenge: &[u8],
+        _sec_level: SecurityLevel,
+    ) -> Result<Vec<u8>> {
+        // TODO(b/179222809): implement with actual remote provisioner AIDL when available. For now
+        //       it isnice to have some junk values
+        Ok(vec![0, 1, 3, 3])
+    }
+
+    /// Provisions a certificate chain for a key whose CSR was included in generate_csr. The
+    /// `public_key` is used to index into the SQL database in order to insert the `certs` blob
+    /// which represents a PEM encoded X.509 certificate chain. The `expiration_date` is provided
+    /// as a convenience from the caller to avoid having to parse the certificates semantically
+    /// here.
+    pub fn provision_cert_chain(
+        &self,
+        public_key: &[u8],
+        certs: &[u8],
+        expiration_date: i64,
+        sec_level: SecurityLevel,
+    ) -> Result<()> {
+        DB.with::<_, Result<()>>(|db| {
+            let mut db = db.borrow_mut();
+            let (_, _, uuid) = get_keymint_device(&sec_level)?;
+            Ok(db.store_signed_attestation_certificate_chain(
+                public_key,
+                certs, /* DER encoded certificate chain */
+                expiration_date,
+                &uuid,
+            )?)
+        })
+    }
+
+    /// Submits a request to the Remote Provisioner HAL to generate a signing key pair.
+    /// `is_test_mode` indicates whether or not the returned public key should be marked as being
+    /// for testing in order to differentiate them from private keys. If the call is successful,
+    /// the key pair is then added to the database.
+    pub fn generate_key_pair(&self, _is_test_mode: bool, _sec_level: SecurityLevel) -> Result<()> {
+        Ok(())
+    }
+}
+
+impl binder::Interface for RemoteProvisioningService {}
+
+// Implementation of IRemoteProvisioning. See AIDL spec at
+// :aidl/android/security/remoteprovisioning/IRemoteProvisioning.aidl
+impl IRemoteProvisioning for RemoteProvisioningService {
+    fn getPoolStatus(
+        &self,
+        expired_by: i64,
+        sec_level: SecurityLevel,
+    ) -> binder::public_api::Result<AttestationPoolStatus> {
+        map_or_log_err(self.get_pool_status(expired_by, sec_level), Ok)
+    }
+
+    fn generateCsr(
+        &self,
+        test_mode: bool,
+        num_csr: i32,
+        eek: &[u8],
+        challenge: &[u8],
+        sec_level: SecurityLevel,
+    ) -> binder::public_api::Result<Vec<u8>> {
+        map_or_log_err(self.generate_csr(test_mode, num_csr, eek, challenge, sec_level), Ok)
+    }
+
+    fn provisionCertChain(
+        &self,
+        public_key: &[u8],
+        certs: &[u8],
+        expiration_date: i64,
+        sec_level: SecurityLevel,
+    ) -> binder::public_api::Result<()> {
+        map_or_log_err(self.provision_cert_chain(public_key, certs, expiration_date, sec_level), Ok)
+    }
+
+    fn generateKeyPair(
+        &self,
+        is_test_mode: bool,
+        sec_level: SecurityLevel,
+    ) -> binder::public_api::Result<()> {
+        map_or_log_err(self.generate_key_pair(is_test_mode, sec_level), Ok)
+    }
+}
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index f6d8108..cc1da98 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -68,6 +68,10 @@
 // Blob of 32 zeroes used as empty masking key.
 static ZERO_BLOB_32: &[u8] = &[0; 32];
 
+// Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set to GeneralizedTime
+// 999912312359559, which is 253402300799000 ms from Jan 1, 1970.
+const UNDEFINED_NOT_AFTER: i64 = 253402300799000i64;
+
 impl KeystoreSecurityLevel {
     /// Creates a new security level instance wrapped in a
     /// BnKeystoreSecurityLevel proxy object. It also
@@ -140,7 +144,7 @@
                     let mut db = db.borrow_mut();
                     let (need_gc, key_id) = db
                         .store_new_key(
-                            key,
+                            &key,
                             &key_parameters,
                             &key_blob,
                             &cert_info,
@@ -203,7 +207,7 @@
                 let (key_id_guard, mut key_entry) = DB
                     .with::<_, Result<(KeyIdGuard, KeyEntry)>>(|db| {
                         db.borrow_mut().load_key_entry(
-                            key.clone(),
+                            &key,
                             KeyType::Client,
                             KeyEntryLoadBits::KM,
                             caller_uid,
@@ -305,17 +309,39 @@
         })
     }
 
-    fn add_attestation_parameters(uid: u32, params: &[KeyParameter]) -> Result<Vec<KeyParameter>> {
+    fn add_certificate_parameters(uid: u32, params: &[KeyParameter]) -> Result<Vec<KeyParameter>> {
         let mut result = params.to_vec();
+        // If there is an attestation challenge we need to get an application id.
         if params.iter().any(|kp| kp.tag == Tag::ATTESTATION_CHALLENGE) {
             let aaid = keystore2_aaid::get_aaid(uid).map_err(|e| {
-                anyhow!(format!("In add_attestation_parameters: get_aaid returned status {}.", e))
+                anyhow!(format!("In add_certificate_parameters: get_aaid returned status {}.", e))
             })?;
             result.push(KeyParameter {
                 tag: Tag::ATTESTATION_APPLICATION_ID,
                 value: KeyParameterValue::Blob(aaid),
             });
         }
+
+        // If we are generating/importing an asymmetric key, we need to make sure
+        // that NOT_BEFORE and NOT_AFTER are present.
+        match params.iter().find(|kp| kp.tag == Tag::ALGORITHM) {
+            Some(KeyParameter { tag: _, value: KeyParameterValue::Algorithm(Algorithm::RSA) })
+            | Some(KeyParameter { tag: _, value: KeyParameterValue::Algorithm(Algorithm::EC) }) => {
+                if !params.iter().any(|kp| kp.tag == Tag::CERTIFICATE_NOT_BEFORE) {
+                    result.push(KeyParameter {
+                        tag: Tag::CERTIFICATE_NOT_BEFORE,
+                        value: KeyParameterValue::DateTime(0),
+                    })
+                }
+                if !params.iter().any(|kp| kp.tag == Tag::CERTIFICATE_NOT_AFTER) {
+                    result.push(KeyParameter {
+                        tag: Tag::CERTIFICATE_NOT_AFTER,
+                        value: KeyParameterValue::DateTime(UNDEFINED_NOT_AFTER),
+                    })
+                }
+            }
+            _ => {}
+        }
         Ok(result)
     }
 
@@ -346,7 +372,7 @@
         // generate_key requires the rebind permission.
         check_key_permission(KeyPerm::rebind(), &key, &None).context("In generate_key.")?;
 
-        let params = Self::add_attestation_parameters(caller_uid, params)
+        let params = Self::add_certificate_parameters(caller_uid, params)
             .context("In generate_key: Trying to get aaid.")?;
 
         let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
@@ -386,7 +412,7 @@
         // import_key requires the rebind permission.
         check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_key.")?;
 
-        let params = Self::add_attestation_parameters(caller_uid, params)
+        let params = Self::add_certificate_parameters(caller_uid, params)
             .context("In import_key: Trying to get aaid.")?;
 
         let format = params
@@ -459,7 +485,7 @@
         let (wrapping_key_id_guard, wrapping_key_entry) = DB
             .with(|db| {
                 db.borrow_mut().load_key_entry(
-                    wrapping_key.clone(),
+                    &wrapping_key,
                     KeyType::Client,
                     KeyEntryLoadBits::KM,
                     caller_uid,
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index 72671c6..ab6d621 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -118,7 +118,7 @@
         let (key_id_guard, mut key_entry) = DB
             .with(|db| {
                 db.borrow_mut().load_key_entry(
-                    key.clone(),
+                    &key,
                     KeyType::Client,
                     KeyEntryLoadBits::PUBLIC,
                     ThreadState::get_calling_uid(),
@@ -167,7 +167,7 @@
         DB.with::<_, Result<()>>(|db| {
             let mut db = db.borrow_mut();
             let entry = match db.load_key_entry(
-                key.clone(),
+                &key,
                 KeyType::Client,
                 KeyEntryLoadBits::NONE,
                 ThreadState::get_calling_uid(),
@@ -219,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(), &KEYSTORE_UUID)
+            db.store_new_certificate(&key, certificate_chain.unwrap(), &KEYSTORE_UUID)
                 .context("Failed to insert new certificate.")?;
             Ok(())
         })
@@ -271,7 +271,7 @@
         let caller_uid = ThreadState::get_calling_uid();
         let need_gc = DB
             .with(|db| {
-                db.borrow_mut().unbind_key(key.clone(), KeyType::Client, caller_uid, |k, av| {
+                db.borrow_mut().unbind_key(&key, KeyType::Client, caller_uid, |k, av| {
                     check_key_permission(KeyPerm::delete(), k, &av).context("During delete_key.")
                 })
             })
@@ -290,7 +290,7 @@
     ) -> Result<KeyDescriptor> {
         DB.with(|db| {
             db.borrow_mut().grant(
-                key.clone(),
+                &key,
                 ThreadState::get_calling_uid(),
                 grantee_uid as u32,
                 access_vector,
@@ -302,12 +302,9 @@
 
     fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> Result<()> {
         DB.with(|db| {
-            db.borrow_mut().ungrant(
-                key.clone(),
-                ThreadState::get_calling_uid(),
-                grantee_uid as u32,
-                |k| check_key_permission(KeyPerm::grant(), k, &None),
-            )
+            db.borrow_mut().ungrant(&key, ThreadState::get_calling_uid(), grantee_uid as u32, |k| {
+                check_key_permission(KeyPerm::grant(), k, &None)
+            })
         })
         .context("In KeystoreService::ungrant.")
     }