Skip ab/6749736 in stage.

Merged-In: I3c023063eff938812d7001d621d027b81572f4c8
Change-Id: Ied5cd2adff15c89a895bf751cecb047267931ce4
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 68df61f..9b96f36 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,7 +4,7 @@
 
 [Builtin Hooks Options]
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
-rustfmt = --check --config-path=rustfmt.toml ${PREUPLOAD_FILES}
+rustfmt = --config-path=rustfmt.toml
 
 [Hook Scripts]
 aosp_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "."
diff --git a/keystore/KeyStore.cpp b/keystore/KeyStore.cpp
index 7545397..1f80899 100644
--- a/keystore/KeyStore.cpp
+++ b/keystore/KeyStore.cpp
@@ -60,8 +60,8 @@
                   "KmasterDevices and KeymasterWorkers must have the same size");
     for (size_t i = 0; i < kmDevices.size(); ++i) {
         if (kmDevices[SecurityLevel(i)]) {
-            mKmDevices[SecurityLevel(i)] =
-                std::make_shared<KeymasterWorker>(kmDevices[SecurityLevel(i)], this);
+            mKmDevices[SecurityLevel(i)] = std::make_shared<KeymasterWorker>(
+                kmDevices[SecurityLevel(i)], this, SecurityLevel(i));
         }
     }
 }
diff --git a/keystore/TEST_MAPPING b/keystore/TEST_MAPPING
new file mode 100644
index 0000000..0511967
--- /dev/null
+++ b/keystore/TEST_MAPPING
@@ -0,0 +1,74 @@
+{
+  "presubmit": [
+    {
+      "name": "CtsKeystoreTestCases",
+      "options": [
+        {
+          "include-annotation": "android.platform.test.annotations.RequiresDevice"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.SignatureTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.RsaSignaturePerformanceTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.RsaKeyGenPerformanceTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.RsaCipherPerformanceTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.MacTest#testLargeMsgKat"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.KeyPairGeneratorTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.KeyGeneratorTest#testHmacKeySupportedSizes"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.HmacMacPerformanceTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.EcdsaSignaturePerformanceTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.EcKeyGenPerformanceTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.DesCipherPerformanceTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.CipherTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.AttestationPerformanceTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.AndroidKeyStoreTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.AesCipherPerformanceTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.AESCipherNistCavpKatTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.DESedeECBPKCS7PaddingCipherTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.DESedeECBNoPaddingCipherTest"
+        },
+        {
+          "exclude-filter": "android.keystore.cts.DESedeECBPKCS7PaddingCipherTest"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsKeystoreTestCases"
+    }
+  ]
+}
diff --git a/keystore/key_attestation_log_handler.cpp b/keystore/key_attestation_log_handler.cpp
index 34c76a3..c3278cb 100644
--- a/keystore/key_attestation_log_handler.cpp
+++ b/keystore/key_attestation_log_handler.cpp
@@ -17,7 +17,11 @@
 namespace keystore {
 
 void logKeystoreKeyAttestationEvent(bool wasSuccessful, int32_t errorCode) {
-    android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED,
+    // Due to a requirement in stats-write() method, the optional fields
+    // which are not required for attestation logging, are marked with -1 for
+    // non-repeated fields and 0 for repeated fields.
+    android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED, -1, -1, -1, -1, -1, 0, 0,
+                               0, 0, -1, -1,
                                android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_ATTESTATION,
                                wasSuccessful, errorCode);
 }
diff --git a/keystore/keymaster_worker.cpp b/keystore/keymaster_worker.cpp
index 7481a1e..cbb184c 100644
--- a/keystore/keymaster_worker.cpp
+++ b/keystore/keymaster_worker.cpp
@@ -83,8 +83,10 @@
     }
 }
 
-KeymasterWorker::KeymasterWorker(sp<Keymaster> keymasterDevice, KeyStore* keyStore)
-    : keymasterDevice_(std::move(keymasterDevice)), operationMap_(keyStore), keyStore_(keyStore) {
+KeymasterWorker::KeymasterWorker(sp<Keymaster> keymasterDevice, KeyStore* keyStore,
+                                 SecurityLevel internalSecurityLevel)
+    : keymasterDevice_(std::move(keymasterDevice)), operationMap_(keyStore), keyStore_(keyStore),
+      internalSecurityLevel_(internalSecurityLevel) {
     // make sure that hal version is cached.
     if (keymasterDevice_) keymasterDevice_->halVersion();
 }
@@ -821,7 +823,7 @@
             outCharacteristics = keyCharacteristics;
 
             Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10);
-            keyBlob.setSecurityLevel(securityLevel);
+            keyBlob.setSecurityLevel(internalSecurityLevel_);
             keyBlob.setCriticalToDeviceEncryption(flags &
                                                   KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
             if (isAuthenticationBound(keyParams) && !keyBlob.isCriticalToDeviceEncryption()) {
@@ -929,7 +931,7 @@
             outCharacteristics = keyCharacteristics;
 
             Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10);
-            keyBlob.setSecurityLevel(securityLevel);
+            keyBlob.setSecurityLevel(internalSecurityLevel_);
             keyBlob.setCriticalToDeviceEncryption(flags &
                                                   KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
             if (isAuthenticationBound(keyParams) && !keyBlob.isCriticalToDeviceEncryption()) {
@@ -1004,8 +1006,6 @@
                         CAPTURE_MOVE(worker_cb)]() mutable {
         auto hidlWrappingKey = blob2hidlVec(wrappingBlob);
 
-        SecurityLevel securityLevel = keymasterDevice_->halVersion().securityLevel;
-
         KeyCharacteristics outCharacteristics;
         KeyStoreServiceReturnCode error;
 
@@ -1019,7 +1019,7 @@
             outCharacteristics = keyCharacteristics;
 
             Blob keyBlob(hidlKeyBlob.data(), hidlKeyBlob.size(), nullptr, 0, ::TYPE_KEYMASTER_10);
-            keyBlob.setSecurityLevel(securityLevel);
+            keyBlob.setSecurityLevel(internalSecurityLevel_);
             if (isAuthenticationBound(keyCharacteristics.hardwareEnforced)) {
                 keyBlob.setSuperEncrypted(true);
             }
diff --git a/keystore/keymaster_worker.h b/keystore/keymaster_worker.h
index f11af29..fbd52b4 100644
--- a/keystore/keymaster_worker.h
+++ b/keystore/keymaster_worker.h
@@ -135,6 +135,19 @@
     OperationMap operationMap_;
     KeyStore* keyStore_;
 
+    /**
+     * Models the security level of this worker internal to KeyStore.
+     *
+     * When the device has only a software Keymaster, KeyStore will set it on the TEE slot and
+     * instantiate a new in-process software Keymaster. In that case there is a mismatch between the
+     * security level used by KeyStore and what is reported from the HAL. This represents the level
+     * used internally by KeyStore.
+     *
+     * This value is used to associate blobs to the corresponding Keymaster backend. It does not
+     * indicate an actual Keymaster HAL security level and should never be exposed to users.
+     */
+    SecurityLevel internalSecurityLevel_;
+
     template <typename KMFn, typename ErrorType, typename... Args, size_t... I>
     void unwrap_tuple(KMFn kmfn, std::function<void(ErrorType)> cb,
                       const std::tuple<Args...>& tuple, std::index_sequence<I...>) {
@@ -200,7 +213,8 @@
                                          hidl_vec<KeyParameter>* params);
 
   public:
-    KeymasterWorker(sp<Keymaster> keymasterDevice, KeyStore* keyStore);
+    KeymasterWorker(sp<Keymaster> keymasterDevice, KeyStore* keyStore,
+                    SecurityLevel internalSecurityLevel);
 
     void logIfKeymasterVendorError(ErrorCode ec) const;
 
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index bf78574..f4b153c 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -18,24 +18,37 @@
     srcs: ["src/lib.rs"],
 
     rustlibs: [
+        "android.system.keystore2-rust",
+        "libandroid_hardware_keymint",
         "libanyhow",
-        "libkeystore_aidl_generated",
+        "libbinder_rs",
+        "libkeystore2_selinux",
+        "liblazy_static",
+        "liblibsqlite3_sys",
         "liblog_rust",
+        "librand",
+        "librusqlite",
         "libthiserror",
     ],
 }
 
 rust_test {
     name: "keystore2_test",
-    crate_name: "keystore2_test",
+    crate_name: "keystore2",
     srcs: ["src/lib.rs"],
     test_suites: ["general-tests"],
     auto_gen_config: true,
     rustlibs: [
+        "android.system.keystore2-rust",
         "libandroid_logger",
+        "libandroid_hardware_keymint",
         "libanyhow",
-        "libkeystore_aidl_generated",
+        "libbinder_rs",
+        "libkeystore2_selinux",
+        "liblazy_static",
+        "liblibsqlite3_sys",
         "liblog_rust",
+        "librusqlite",
         "libthiserror",
     ],
 }
@@ -43,8 +56,13 @@
 // This is a placeholder for the libraries that will be generated from the AIDL specs
 // eventually.
 rust_library {
-    name: "libkeystore_aidl_generated",
-    crate_name: "keystore_aidl_generated",
+    name: "libandroid_hardware_keymint",
+    crate_name: "android_hardware_keymint",
 
-    srcs: ["src/aidl_generated.rs"],
+    srcs: ["src/android_hardware_keymint.rs"],
+
+    rustlibs: [
+        "libbinder_rs",
+        "liblazy_static",
+    ],
 }
diff --git a/keystore2/selinux/Android.bp b/keystore2/selinux/Android.bp
new file mode 100644
index 0000000..acbf5ef
--- /dev/null
+++ b/keystore2/selinux/Android.bp
@@ -0,0 +1,54 @@
+// 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.
+
+rust_library {
+    name: "libkeystore2_selinux",
+    crate_name: "keystore2_selinux",
+    srcs: [
+        "src/lib.rs",
+    ],
+
+    shared_libs: [
+        "libselinux",
+    ],
+
+    rustlibs: [
+        "libanyhow",
+        "liblog_rust",
+        "libselinux_bindgen",
+        "libthiserror",
+    ],
+}
+
+rust_test {
+    name: "keystore2_selinux_test",
+    srcs: [
+        "src/lib.rs",
+    ],
+    crate_name: "keystore2_selinux_test",
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+
+    shared_libs: [
+        "libselinux",
+    ],
+
+    rustlibs: [
+        "libandroid_logger",
+        "libanyhow",
+        "liblog_rust",
+        "libselinux_bindgen",
+        "libthiserror",
+    ],
+}
diff --git a/keystore2/selinux/TEST_MAPPING b/keystore2/selinux/TEST_MAPPING
new file mode 100644
index 0000000..0e68257
--- /dev/null
+++ b/keystore2/selinux/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "keystore2_selinux_test"
+    }
+  ]
+}
diff --git a/keystore2/selinux/src/lib.rs b/keystore2/selinux/src/lib.rs
new file mode 100644
index 0000000..932c30e
--- /dev/null
+++ b/keystore2/selinux/src/lib.rs
@@ -0,0 +1,473 @@
+// 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.
+
+// #![allow(missing_docs)]
+
+//! This crate provides some safe wrappers around the libselinux API. It is currently limited
+//! to the API surface that Keystore 2.0 requires to perform permission checks against
+//! the SEPolicy. Notably, it provides wrappers for:
+//!  * getcon
+//!  * selinux_check_access
+//!  * selabel_lookup for the keystore2_key backend.
+//! And it provides an owning wrapper around context strings `Context`.
+
+use std::ffi::{CStr, CString};
+use std::fmt;
+use std::io;
+use std::marker::{Send, Sync};
+pub use std::ops::Deref;
+use std::os::raw::c_char;
+use std::ptr;
+use std::sync;
+
+use selinux_bindgen as selinux;
+
+use anyhow::Context as AnyhowContext;
+use anyhow::{anyhow, Result};
+
+use selinux::SELABEL_CTX_ANDROID_KEYSTORE2_KEY;
+use selinux::SELINUX_CB_LOG;
+
+pub use selinux::pid_t;
+
+static SELINUX_LOG_INIT: sync::Once = sync::Once::new();
+
+fn redirect_selinux_logs_to_logcat() {
+    // `selinux_set_callback` assigns the static lifetime function pointer
+    // `selinux_log_callback` to a static lifetime variable.
+    let cb = selinux::selinux_callback { func_log: Some(selinux::selinux_log_callback) };
+    unsafe {
+        selinux::selinux_set_callback(SELINUX_CB_LOG as i32, cb);
+    }
+}
+
+// This function must be called before any entry point into lib selinux.
+// Or leave a comment reasoning why calling this macro is not necessary
+// for a given entry point.
+fn init_logger_once() {
+    SELINUX_LOG_INIT.call_once(redirect_selinux_logs_to_logcat)
+}
+
+/// Selinux Error code.
+#[derive(thiserror::Error, Debug, PartialEq)]
+pub enum Error {
+    /// Indicates that an access check yielded no access.
+    #[error("Permission Denied")]
+    PermissionDenied,
+    /// Indicates an unexpected system error. Nested string provides some details.
+    #[error("Selinux SystemError: {0}")]
+    SystemError(String),
+}
+
+impl Error {
+    /// Constructs a `PermissionDenied` error.
+    pub fn perm() -> Self {
+        Error::PermissionDenied
+    }
+    fn sys<T: Into<String>>(s: T) -> Self {
+        Error::SystemError(s.into())
+    }
+}
+
+/// Context represents an SELinux context string. It can take ownership of a raw
+/// s-string as allocated by `getcon` or `selabel_lookup`. In this case it uses
+/// `freecon` to free the resources when dropped. In its second variant it stores
+/// an `std::ffi::CString` that can be initialized from a Rust string slice.
+#[derive(Debug)]
+pub enum Context {
+    /// Wraps a raw context c-string as returned by libselinux.
+    Raw(*mut ::std::os::raw::c_char),
+    /// Stores a context string as `std::ffi::CString`.
+    CString(CString),
+}
+
+impl PartialEq for Context {
+    fn eq(&self, other: &Self) -> bool {
+        // We dereference both and thereby delegate the comparison
+        // to `CStr`'s implementation of `PartialEq`.
+        **self == **other
+    }
+}
+
+impl Eq for Context {}
+
+impl fmt::Display for Context {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", (**self).to_str().unwrap_or("Invalid context"))
+    }
+}
+
+impl Drop for Context {
+    fn drop(&mut self) {
+        if let Self::Raw(p) = self {
+            // No need to initialize the logger here, because
+            // `freecon` cannot run unless `Backend::lookup` or `getcon`
+            // has run.
+            unsafe { selinux::freecon(*p) };
+        }
+    }
+}
+
+impl Deref for Context {
+    type Target = CStr;
+
+    fn deref(&self) -> &Self::Target {
+        match self {
+            Self::Raw(p) => unsafe { CStr::from_ptr(*p) },
+            Self::CString(cstr) => &cstr,
+        }
+    }
+}
+
+impl Context {
+    /// Initializes the `Context::CString` variant from a Rust string slice.
+    pub fn new(con: &str) -> Result<Self> {
+        Ok(Self::CString(
+            CString::new(con)
+                .with_context(|| format!("Failed to create Context with \"{}\"", con))?,
+        ))
+    }
+}
+
+/// The backend trait provides a uniform interface to all libselinux context backends.
+/// Currently, we only implement the KeystoreKeyBackend though.
+pub trait Backend {
+    /// Implementers use libselinux `selabel_lookup` to lookup the context for the given `key`.
+    fn lookup(&self, key: &str) -> Result<Context>;
+}
+
+/// Keystore key backend takes onwnership of the SELinux context handle returned by
+/// `selinux_android_keystore2_key_context_handle` and uses `selabel_close` to free
+/// the handle when dropped.
+/// It implements `Backend` to provide keystore_key label lookup functionality.
+pub struct KeystoreKeyBackend {
+    handle: *mut selinux::selabel_handle,
+}
+
+// KeystoreKeyBackend is Sync because selabel_lookup is thread safe.
+unsafe impl Sync for KeystoreKeyBackend {}
+unsafe impl Send for KeystoreKeyBackend {}
+
+impl KeystoreKeyBackend {
+    const BACKEND_TYPE: i32 = SELABEL_CTX_ANDROID_KEYSTORE2_KEY as i32;
+
+    /// Creates a new instance representing an SELinux context handle as returned by
+    /// `selinux_android_keystore2_key_context_handle`.
+    pub fn new() -> Result<Self> {
+        init_logger_once();
+        let handle = unsafe { selinux::selinux_android_keystore2_key_context_handle() };
+        if handle.is_null() {
+            return Err(anyhow!(Error::sys("Failed to open KeystoreKeyBackend")));
+        }
+        Ok(KeystoreKeyBackend { handle })
+    }
+}
+
+impl Drop for KeystoreKeyBackend {
+    fn drop(&mut self) {
+        // No need to initialize the logger here because it cannot be called unless
+        // KeystoreKeyBackend::new has run.
+        unsafe { selinux::selabel_close(self.handle) };
+    }
+}
+
+// Because KeystoreKeyBackend is Sync and Send, member function must never call
+// non thread safe libselinux functions. As of this writing no non thread safe
+// functions exist that could be called on a label backend handle.
+impl Backend for KeystoreKeyBackend {
+    fn lookup(&self, key: &str) -> Result<Context> {
+        let mut con: *mut c_char = ptr::null_mut();
+        let c_key = CString::new(key).with_context(|| {
+            format!("selabel_lookup: Failed to convert key \"{}\" to CString.", key)
+        })?;
+        match unsafe {
+            // No need to initialize the logger here because it cannot run unless
+            // KeystoreKeyBackend::new has run.
+            selinux::selabel_lookup(self.handle, &mut con, c_key.as_ptr(), Self::BACKEND_TYPE)
+        } {
+            0 => {
+                if !con.is_null() {
+                    Ok(Context::Raw(con))
+                } else {
+                    Err(anyhow!(Error::sys(format!(
+                        "selabel_lookup returned a NULL context for key \"{}\"",
+                        key
+                    ))))
+                }
+            }
+            _ => Err(anyhow!(io::Error::last_os_error()))
+                .with_context(|| format!("selabel_lookup failed for key \"{}\"", key)),
+        }
+    }
+}
+
+/// Safe wrapper around libselinux `getcon`. It initializes the `Context::Raw` variant of the
+/// returned `Context`.
+///
+/// ## Return
+///  * Ok(Context::Raw()) if successful.
+///  * Err(Error::sys()) if getcon succeeded but returned a NULL pointer.
+///  * Err(io::Error::last_os_error()) if getcon failed.
+pub fn getcon() -> Result<Context> {
+    init_logger_once();
+    let mut con: *mut c_char = ptr::null_mut();
+    match unsafe { selinux::getcon(&mut con) } {
+        0 => {
+            if !con.is_null() {
+                Ok(Context::Raw(con))
+            } else {
+                Err(anyhow!(Error::sys("getcon returned a NULL context")))
+            }
+        }
+        _ => Err(anyhow!(io::Error::last_os_error())).context("getcon failed"),
+    }
+}
+
+/// Safe wrapper around libselinux `getpidcon`. It initializes the `Context::Raw` variant of the
+/// returned `Context`.
+///
+/// ## Return
+///  * Ok(Context::Raw()) if successful.
+///  * Err(Error::sys()) if getpidcon succeeded but returned a NULL pointer.
+///  * Err(io::Error::last_os_error()) if getpidcon failed.
+pub fn getpidcon(pid: selinux::pid_t) -> Result<Context> {
+    init_logger_once();
+    let mut con: *mut c_char = ptr::null_mut();
+    match unsafe { selinux::getpidcon(pid, &mut con) } {
+        0 => {
+            if !con.is_null() {
+                Ok(Context::Raw(con))
+            } else {
+                Err(anyhow!(Error::sys(format!(
+                    "getpidcon returned a NULL context for pid {}",
+                    pid
+                ))))
+            }
+        }
+        _ => Err(anyhow!(io::Error::last_os_error()))
+            .context(format!("getpidcon failed for pid {}", pid)),
+    }
+}
+
+/// Safe wrapper around selinux_check_access.
+///
+/// ## Return
+///  * Ok(()) iff the requested access was granted.
+///  * Err(anyhow!(Error::perm()))) if the permission was denied.
+///  * Err(anyhow!(ioError::last_os_error())) if any other error occurred while performing
+///            the access check.
+pub fn check_access(source: &CStr, target: &CStr, tclass: &str, perm: &str) -> Result<()> {
+    init_logger_once();
+    let c_tclass = CString::new(tclass).with_context(|| {
+        format!("check_access: Failed to convert tclass \"{}\" to CString.", tclass)
+    })?;
+    let c_perm = CString::new(perm).with_context(|| {
+        format!("check_access: Failed to convert perm \"{}\" to CString.", perm)
+    })?;
+
+    match unsafe {
+        selinux::selinux_check_access(
+            source.as_ptr(),
+            target.as_ptr(),
+            c_tclass.as_ptr(),
+            c_perm.as_ptr(),
+            ptr::null_mut(),
+        )
+    } {
+        0 => Ok(()),
+        _ => {
+            let e = io::Error::last_os_error();
+            match e.kind() {
+                io::ErrorKind::PermissionDenied => Err(anyhow!(Error::perm())),
+                _ => Err(anyhow!(e)),
+            }
+            .with_context(|| {
+                format!(
+                    concat!(
+                        "check_access: Failed with sctx: {:?} tctx: {:?}",
+                        " with target class: \"{}\" perm: \"{}\""
+                    ),
+                    source, target, tclass, perm
+                )
+            })
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use anyhow::Result;
+
+    /// The su_key namespace as defined in su.te and keystore_key_contexts of the
+    /// SePolicy (system/sepolicy).
+    static SU_KEY_NAMESPACE: &str = "0";
+    /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
+    /// SePolicy (system/sepolicy).
+    static SHELL_KEY_NAMESPACE: &str = "1";
+
+    fn check_context() -> Result<(Context, &'static str, bool)> {
+        let context = getcon()?;
+        match context.to_str().unwrap() {
+            "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
+            "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
+            c => Err(anyhow!(format!(
+                "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
+                c
+            ))),
+        }
+    }
+
+    #[test]
+    fn test_getcon() -> Result<()> {
+        check_context()?;
+        Ok(())
+    }
+
+    #[test]
+    fn test_label_lookup() -> Result<()> {
+        let (_context, namespace, is_su) = check_context()?;
+        let backend = crate::KeystoreKeyBackend::new()?;
+        let context = backend.lookup(namespace)?;
+        if is_su {
+            assert_eq!(context.to_str(), Ok("u:object_r:su_key:s0"));
+        } else {
+            assert_eq!(context.to_str(), Ok("u:object_r:shell_key:s0"));
+        }
+        Ok(())
+    }
+
+    #[test]
+    fn context_from_string() -> Result<()> {
+        let tctx = Context::new("u:object_r:keystore:s0").unwrap();
+        let sctx = Context::new("u:r:system_server:s0").unwrap();
+        check_access(&sctx, &tctx, "keystore2_key", "use")?;
+        Ok(())
+    }
+
+    mod perm {
+        use super::super::*;
+        use super::*;
+        use anyhow::Result;
+
+        /// check_key_perm(perm, privileged, priv_domain)
+        /// `perm` is a permission of the keystore2_key class and `privileged` is a boolean
+        /// indicating whether the permission is considered privileged.
+        /// Privileged permissions are expected to be denied to `shell` users but granted
+        /// to the given priv_domain.
+        macro_rules! check_key_perm {
+            // "use" is a keyword and cannot be used as an identifier, but we must keep
+            // the permission string intact. So we map the identifier name on use_ while using
+            // the permission string "use". In all other cases we can simply use the stringified
+            // identifier as permission string.
+            (use, $privileged:expr) => {
+                check_key_perm!(use_, $privileged, "use");
+            };
+            ($perm:ident, $privileged:expr) => {
+                check_key_perm!($perm, $privileged, stringify!($perm));
+            };
+            ($perm:ident, $privileged:expr, $p_str:expr) => {
+                #[test]
+                fn $perm() -> Result<()> {
+                    android_logger::init_once(
+                        android_logger::Config::default()
+                            .with_tag("keystore_selinux_tests")
+                            .with_min_level(log::Level::Debug),
+                    );
+                    let scontext = Context::new("u:r:shell:s0")?;
+                    let backend = KeystoreKeyBackend::new()?;
+                    let tcontext = backend.lookup(SHELL_KEY_NAMESPACE)?;
+
+                    if $privileged {
+                        assert_eq!(
+                            Some(&Error::perm()),
+                            check_access(
+                                &scontext,
+                                &tcontext,
+                                "keystore2_key",
+                                $p_str
+                            )
+                            .err()
+                            .unwrap()
+                            .root_cause()
+                            .downcast_ref::<Error>()
+                        );
+                    } else {
+                        assert!(check_access(
+                            &scontext,
+                            &tcontext,
+                            "keystore2_key",
+                            $p_str
+                        )
+                        .is_ok());
+                    }
+                    Ok(())
+                }
+            };
+        }
+
+        check_key_perm!(manage_blob, true);
+        check_key_perm!(delete, false);
+        check_key_perm!(use_dev_id, true);
+        check_key_perm!(req_forced_op, true);
+        check_key_perm!(gen_unique_id, true);
+        check_key_perm!(grant, true);
+        check_key_perm!(get_info, false);
+        check_key_perm!(rebind, false);
+        check_key_perm!(update, false);
+        check_key_perm!(use, false);
+
+        macro_rules! check_keystore_perm {
+            ($perm:ident) => {
+                #[test]
+                fn $perm() -> Result<()> {
+                    let ks_context = Context::new("u:object_r:keystore:s0")?;
+                    let priv_context = Context::new("u:r:system_server:s0")?;
+                    let unpriv_context = Context::new("u:r:shell:s0")?;
+                    assert!(check_access(
+                        &priv_context,
+                        &ks_context,
+                        "keystore2",
+                        stringify!($perm)
+                    )
+                    .is_ok());
+                    assert_eq!(
+                        Some(&Error::perm()),
+                        check_access(&unpriv_context, &ks_context, "keystore2", stringify!($perm))
+                            .err()
+                            .unwrap()
+                            .root_cause()
+                            .downcast_ref::<Error>()
+                    );
+                    Ok(())
+                }
+            };
+        }
+
+        check_keystore_perm!(add_auth);
+        check_keystore_perm!(clear_ns);
+        check_keystore_perm!(get_state);
+        check_keystore_perm!(lock);
+        check_keystore_perm!(reset);
+        check_keystore_perm!(unlock);
+    }
+
+    #[test]
+    fn test_getpidcon() {
+        // Check that `getpidcon` of our pid is equal to what `getcon` returns.
+        // And by using `unwrap` we make sure that both also have to return successfully
+        // fully to pass the test.
+        assert_eq!(getpidcon(std::process::id() as i32).unwrap(), getcon().unwrap());
+    }
+}
diff --git a/keystore2/src/aidl_generated.rs b/keystore2/src/aidl_generated.rs
deleted file mode 100644
index 4b6a844..0000000
--- a/keystore2/src/aidl_generated.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-// 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.
-
-#![allow(missing_docs)]
-
-//! This crate holds types that we are depending on and will be generated by the AIDL
-//! compiler.
-
-use std::cmp::PartialEq;
-use std::fmt;
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct Result {
-    pub rc: ResponseCode,
-    pub km_error_code: i32,
-}
-
-impl fmt::Display for Result {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self)
-    }
-}
-
-#[repr(i32)]
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum ResponseCode {
-    Ok = 0,
-    // 1 Reserved - formerly NO_ERROR
-    Locked = 2,
-    Uninitialized = 3,
-    SystemError = 4,
-    // 5 Reserved - formerly "protocol error" was never used
-    PermissionDenied = 6,
-    KeyNotFound = 7,
-    ValueCorrupted = 8,
-    // 9 Reserved - formerly "undefined action" was never used
-    WrongPassword = 10,
-    // 11 - 13 Reserved - formerly password retry count indicators: obsolete
-    //
-    // 14 Reserved - formerly SIGNATURE_INVALID: Keystore does not perform public key
-    //               operations any more.
-
-    // Indicates to the caller that user authorization is required before the operation may
-    // commence.
-    OpAuthNeeded = 15,
-    // 16 Reserved
-    KeyPermanentlyInvalidated = 17,
-    NoSuchSecurityLevel = 18,
-    KeymintErrorCode = 19,
-    BackendBusy = 20,
-}
-
-pub type ErrorCode = i32;
-
-#[repr(i32)]
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum KeyPermission {
-    None = 0,
-    Delete = 1,
-    GenUniqueId = 2,
-    GetInfo = 4,
-    Grant = 8,
-    List = 0x10,
-    ManageBlob = 0x20,
-    Rebind = 0x40,
-    ReqForcedOp = 0x80,
-    Update = 0x100,
-    Use = 0x200,
-    UseDevId = 0x400,
-}
-
-#[repr(i32)]
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum Domain {
-    App = 0,
-    Grant = 1,
-    SELinux = 2,
-    Blob = 3,
-    KeyId = 4,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct KeyDescriptor {
-    pub domain: Domain,
-    pub namespace_: i64,
-    pub alias: Option<String>,
-    pub blob: Option<Vec<u8>>,
-}
diff --git a/keystore2/src/android_hardware_keymint.rs b/keystore2/src/android_hardware_keymint.rs
new file mode 100644
index 0000000..103b9b9
--- /dev/null
+++ b/keystore2/src/android_hardware_keymint.rs
@@ -0,0 +1,1656 @@
+#![allow(non_snake_case)]
+#![allow(missing_docs)]
+#![allow(clippy::identity_op)]
+#![allow(clippy::excessive_precision)]
+#![allow(clippy::too_many_arguments)]
+pub use binder::public_api as binder;
+pub mod aidl {
+  pub mod android {
+    pub mod hardware {
+      pub mod keymint {
+        pub mod Algorithm {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { Algorithm : i32 {
+            RSA = 1,
+            EC = 3,
+            AES = 32,
+            TRIPLE_DES = 33,
+            HMAC = 128,
+          } }
+          pub(crate) mod mangled { pub use super::Algorithm as _7_android_8_hardware_7_keymint_9_Algorithm; }
+        }
+        pub mod BeginResult {
+          #[derive(Debug)]
+          pub struct BeginResult {
+            pub challenge: i64, 
+            pub params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
+            pub operation: Option<Box<dyn crate::mangled::_7_android_8_hardware_7_keymint_17_IKeyMintOperation>>, 
+          }
+          pub(crate) mod mangled { pub use super::BeginResult as _7_android_8_hardware_7_keymint_11_BeginResult; }
+          impl Default for BeginResult {
+            fn default() -> Self {
+              Self {
+                challenge: 0,
+                params: Default::default(),
+                operation: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for BeginResult {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for BeginResult {}
+          impl binder::parcel::SerializeOption for BeginResult {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.challenge)?;
+              parcel.write(&this.params)?;
+              let __field_ref = this.operation.as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;
+              parcel.write(__field_ref)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for BeginResult {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for BeginResult {}
+          impl binder::parcel::DeserializeOption for BeginResult {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.challenge = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.params = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.operation = Some(parcel.read()?);
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod BlockMode {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { BlockMode : i32 {
+            ECB = 1,
+            CBC = 2,
+            CTR = 3,
+            GCM = 32,
+          } }
+          pub(crate) mod mangled { pub use super::BlockMode as _7_android_8_hardware_7_keymint_9_BlockMode; }
+        }
+        pub mod Certificate {
+          #[derive(Debug)]
+          pub struct Certificate {
+            pub encodedCertificate: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::Certificate as _7_android_8_hardware_7_keymint_11_Certificate; }
+          impl Default for Certificate {
+            fn default() -> Self {
+              Self {
+                encodedCertificate: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for Certificate {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for Certificate {}
+          impl binder::parcel::SerializeOption for Certificate {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.encodedCertificate)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for Certificate {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for Certificate {}
+          impl binder::parcel::DeserializeOption for Certificate {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.encodedCertificate = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod Constants {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { Constants : i32 {
+            AUTH_TOKEN_MAC_LENGTH = 32,
+          } }
+          pub(crate) mod mangled { pub use super::Constants as _7_android_8_hardware_7_keymint_9_Constants; }
+        }
+        pub mod Digest {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { Digest : i32 {
+            NONE = 0,
+            MD5 = 1,
+            SHA1 = 2,
+            SHA_2_224 = 3,
+            SHA_2_256 = 4,
+            SHA_2_384 = 5,
+            SHA_2_512 = 6,
+          } }
+          pub(crate) mod mangled { pub use super::Digest as _7_android_8_hardware_7_keymint_6_Digest; }
+        }
+        pub mod EcCurve {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { EcCurve : i32 {
+            P_224 = 0,
+            P_256 = 1,
+            P_384 = 2,
+            P_521 = 3,
+          } }
+          pub(crate) mod mangled { pub use super::EcCurve as _7_android_8_hardware_7_keymint_7_EcCurve; }
+        }
+        pub mod ErrorCode {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { ErrorCode : i32 {
+            OK = 0,
+            ROOT_OF_TRUST_ALREADY_SET = -1,
+            UNSUPPORTED_PURPOSE = -2,
+            INCOMPATIBLE_PURPOSE = -3,
+            UNSUPPORTED_ALGORITHM = -4,
+            INCOMPATIBLE_ALGORITHM = -5,
+            UNSUPPORTED_KEY_SIZE = -6,
+            UNSUPPORTED_BLOCK_MODE = -7,
+            INCOMPATIBLE_BLOCK_MODE = -8,
+            UNSUPPORTED_MAC_LENGTH = -9,
+            UNSUPPORTED_PADDING_MODE = -10,
+            INCOMPATIBLE_PADDING_MODE = -11,
+            UNSUPPORTED_DIGEST = -12,
+            INCOMPATIBLE_DIGEST = -13,
+            INVALID_EXPIRATION_TIME = -14,
+            INVALID_USER_ID = -15,
+            INVALID_AUTHORIZATION_TIMEOUT = -16,
+            UNSUPPORTED_KEY_FORMAT = -17,
+            INCOMPATIBLE_KEY_FORMAT = -18,
+            UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19,
+            UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20,
+            INVALID_INPUT_LENGTH = -21,
+            KEY_EXPORT_OPTIONS_INVALID = -22,
+            DELEGATION_NOT_ALLOWED = -23,
+            KEY_NOT_YET_VALID = -24,
+            KEY_EXPIRED = -25,
+            KEY_USER_NOT_AUTHENTICATED = -26,
+            OUTPUT_PARAMETER_NULL = -27,
+            INVALID_OPERATION_HANDLE = -28,
+            INSUFFICIENT_BUFFER_SPACE = -29,
+            VERIFICATION_FAILED = -30,
+            TOO_MANY_OPERATIONS = -31,
+            UNEXPECTED_NULL_POINTER = -32,
+            INVALID_KEY_BLOB = -33,
+            IMPORTED_KEY_NOT_ENCRYPTED = -34,
+            IMPORTED_KEY_DECRYPTION_FAILED = -35,
+            IMPORTED_KEY_NOT_SIGNED = -36,
+            IMPORTED_KEY_VERIFICATION_FAILED = -37,
+            INVALID_ARGUMENT = -38,
+            UNSUPPORTED_TAG = -39,
+            INVALID_TAG = -40,
+            MEMORY_ALLOCATION_FAILED = -41,
+            IMPORT_PARAMETER_MISMATCH = -44,
+            SECURE_HW_ACCESS_DENIED = -45,
+            OPERATION_CANCELLED = -46,
+            CONCURRENT_ACCESS_CONFLICT = -47,
+            SECURE_HW_BUSY = -48,
+            SECURE_HW_COMMUNICATION_FAILED = -49,
+            UNSUPPORTED_EC_FIELD = -50,
+            MISSING_NONCE = -51,
+            INVALID_NONCE = -52,
+            MISSING_MAC_LENGTH = -53,
+            KEY_RATE_LIMIT_EXCEEDED = -54,
+            CALLER_NONCE_PROHIBITED = -55,
+            KEY_MAX_OPS_EXCEEDED = -56,
+            INVALID_MAC_LENGTH = -57,
+            MISSING_MIN_MAC_LENGTH = -58,
+            UNSUPPORTED_MIN_MAC_LENGTH = -59,
+            UNSUPPORTED_KDF = -60,
+            UNSUPPORTED_EC_CURVE = -61,
+            KEY_REQUIRES_UPGRADE = -62,
+            ATTESTATION_CHALLENGE_MISSING = -63,
+            KEYMINT_NOT_CONFIGURED = -64,
+            ATTESTATION_APPLICATION_ID_MISSING = -65,
+            CANNOT_ATTEST_IDS = -66,
+            ROLLBACK_RESISTANCE_UNAVAILABLE = -67,
+            HARDWARE_TYPE_UNAVAILABLE = -68,
+            PROOF_OF_PRESENCE_REQUIRED = -69,
+            CONCURRENT_PROOF_OF_PRESENCE_REQUESTED = -70,
+            NO_USER_CONFIRMATION = -71,
+            DEVICE_LOCKED = -72,
+            EARLY_BOOT_ENDED = -73,
+            ATTESTATION_KEYS_NOT_PROVISIONED = -74,
+            ATTESTATION_IDS_NOT_PROVISIONED = -75,
+            INVALID_OPERATION = -76,
+            STORAGE_KEY_UNSUPPORTED = -77,
+            UNIMPLEMENTED = -100,
+            VERSION_MISMATCH = -101,
+            UNKNOWN_ERROR = -1000,
+          } }
+          pub(crate) mod mangled { pub use super::ErrorCode as _7_android_8_hardware_7_keymint_9_ErrorCode; }
+        }
+        pub mod HardwareAuthToken {
+          #[derive(Debug)]
+          pub struct HardwareAuthToken {
+            pub challenge: i64, 
+            pub userId: i64, 
+            pub authenticatorId: i64, 
+            pub authenticatorType: crate::mangled::_7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType, 
+            pub timestamp: crate::mangled::_7_android_8_hardware_7_keymint_9_Timestamp, 
+            pub mac: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::HardwareAuthToken as _7_android_8_hardware_7_keymint_17_HardwareAuthToken; }
+          impl Default for HardwareAuthToken {
+            fn default() -> Self {
+              Self {
+                challenge: 0,
+                userId: 0,
+                authenticatorId: 0,
+                authenticatorType: Default::default(),
+                timestamp: Default::default(),
+                mac: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for HardwareAuthToken {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for HardwareAuthToken {}
+          impl binder::parcel::SerializeOption for HardwareAuthToken {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.challenge)?;
+              parcel.write(&this.userId)?;
+              parcel.write(&this.authenticatorId)?;
+              parcel.write(&this.authenticatorType)?;
+              parcel.write(&this.timestamp)?;
+              parcel.write(&this.mac)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for HardwareAuthToken {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for HardwareAuthToken {}
+          impl binder::parcel::DeserializeOption for HardwareAuthToken {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.challenge = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.userId = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.authenticatorId = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.authenticatorType = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.timestamp = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.mac = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod HardwareAuthenticatorType {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { HardwareAuthenticatorType : i32 {
+            NONE = 0,
+            PASSWORD = 1,
+            FINGERPRINT = 2,
+            ANY = -1,
+          } }
+          pub(crate) mod mangled { pub use super::HardwareAuthenticatorType as _7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType; }
+        }
+        pub mod HmacSharingParameters {
+          #[derive(Debug)]
+          pub struct HmacSharingParameters {
+            pub seed: Vec<u8>, 
+            pub nonce: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::HmacSharingParameters as _7_android_8_hardware_7_keymint_21_HmacSharingParameters; }
+          impl Default for HmacSharingParameters {
+            fn default() -> Self {
+              Self {
+                seed: Default::default(),
+                nonce: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for HmacSharingParameters {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for HmacSharingParameters {}
+          impl binder::parcel::SerializeOption for HmacSharingParameters {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.seed)?;
+              parcel.write(&this.nonce)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for HmacSharingParameters {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for HmacSharingParameters {}
+          impl binder::parcel::DeserializeOption for HmacSharingParameters {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.seed = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.nonce = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod IKeyMintDevice {
+          #![allow(non_upper_case_globals)]
+          #![allow(non_snake_case)]
+          #[allow(unused_imports)] use binder::IBinder;
+          use binder::declare_binder_interface;
+          declare_binder_interface! {
+            IKeyMintDevice["android.hardware.keymint.IKeyMintDevice"] {
+              native: BnKeyMintDevice(on_transact),
+              proxy: BpKeyMintDevice {
+              },
+            }
+          }
+          pub trait IKeyMintDevice: binder::Interface + Send {
+            fn get_descriptor() -> &'static str where Self: Sized { "android.hardware.keymint.IKeyMintDevice" }
+            fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn deleteAllKeys(&self) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn destroyAttestationIds(&self) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn getDefaultImpl() -> IKeyMintDeviceDefault where Self: Sized {
+              DEFAULT_IMPL.lock().unwrap().clone()
+            }
+            fn setDefaultImpl(d: IKeyMintDeviceDefault) -> IKeyMintDeviceDefault where Self: Sized {
+              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+            }
+          }
+          pub mod transactions {
+            #[allow(unused_imports)] use binder::IBinder;
+            pub const getHardwareInfo: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
+            pub const verifyAuthorization: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
+            pub const addRngEntropy: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
+            pub const generateKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
+            pub const importKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
+            pub const importWrappedKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 5;
+            pub const upgradeKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 6;
+            pub const deleteKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 7;
+            pub const deleteAllKeys: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 8;
+            pub const destroyAttestationIds: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 9;
+            pub const begin: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 10;
+          }
+          pub type IKeyMintDeviceDefault = Option<std::sync::Arc<dyn IKeyMintDevice + Sync>>;
+          use lazy_static::lazy_static;
+          lazy_static! {
+            static ref DEFAULT_IMPL: std::sync::Mutex<IKeyMintDeviceDefault> = std::sync::Mutex::new(None);
+          }
+          pub(crate) mod mangled { pub use super::IKeyMintDevice as _7_android_8_hardware_7_keymint_14_IKeyMintDevice; }
+          impl IKeyMintDevice for BpKeyMintDevice {
+            fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> {
+              let _aidl_reply = self.binder.transact(transactions::getHardwareInfo, 0, |_aidl_data| {
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.getHardwareInfo();
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> {
+              let _aidl_reply = self.binder.transact(transactions::verifyAuthorization, 0, |_aidl_data| {
+                _aidl_data.write(&_arg_challenge)?;
+                _aidl_data.write(_arg_parametersToVerify)?;
+                _aidl_data.write(_arg_token)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.verifyAuthorization(_arg_challenge, _arg_parametersToVerify, _arg_token);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(transactions::addRngEntropy, 0, |_aidl_data| {
+                _aidl_data.write(_arg_data)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.addRngEntropy(_arg_data);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+            fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(transactions::generateKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_keyParams)?;
+                _aidl_data.write_slice_size(Some(_arg_generatedKeyBlob))?;
+                _aidl_data.write_slice_size(Some(_arg_outCertChain))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.generateKey(_arg_keyParams, _arg_generatedKeyBlob, _arg_generatedKeyCharacteristics, _arg_outCertChain);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              *_arg_generatedKeyBlob = _aidl_reply.read()?;
+              *_arg_generatedKeyCharacteristics = _aidl_reply.read()?;
+              *_arg_outCertChain = _aidl_reply.read()?;
+              Ok(())
+            }
+            fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(transactions::importKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inKeyParams)?;
+                _aidl_data.write(&_arg_inKeyFormat)?;
+                _aidl_data.write(_arg_inKeyData)?;
+                _aidl_data.write_slice_size(Some(_arg_outImportedKeyBlob))?;
+                _aidl_data.write_slice_size(Some(_arg_outCertChain))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.importKey(_arg_inKeyParams, _arg_inKeyFormat, _arg_inKeyData, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics, _arg_outCertChain);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              *_arg_outImportedKeyBlob = _aidl_reply.read()?;
+              *_arg_outImportedKeyCharacteristics = _aidl_reply.read()?;
+              *_arg_outCertChain = _aidl_reply.read()?;
+              Ok(())
+            }
+            fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(transactions::importWrappedKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inWrappedKeyData)?;
+                _aidl_data.write(_arg_inWrappingKeyBlob)?;
+                _aidl_data.write(_arg_inMaskingKey)?;
+                _aidl_data.write(_arg_inUnwrappingParams)?;
+                _aidl_data.write(&_arg_inPasswordSid)?;
+                _aidl_data.write(&_arg_inBiometricSid)?;
+                _aidl_data.write_slice_size(Some(_arg_outImportedKeyBlob))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.importWrappedKey(_arg_inWrappedKeyData, _arg_inWrappingKeyBlob, _arg_inMaskingKey, _arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              *_arg_outImportedKeyBlob = _aidl_reply.read()?;
+              *_arg_outImportedKeyCharacteristics = _aidl_reply.read()?;
+              Ok(())
+            }
+            fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> {
+              let _aidl_reply = self.binder.transact(transactions::upgradeKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inKeyBlobToUpgrade)?;
+                _aidl_data.write(_arg_inUpgradeParams)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.upgradeKey(_arg_inKeyBlobToUpgrade, _arg_inUpgradeParams);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: Vec<u8> = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(transactions::deleteKey, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inKeyBlob)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.deleteKey(_arg_inKeyBlob);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+            fn deleteAllKeys(&self) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(transactions::deleteAllKeys, 0, |_aidl_data| {
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.deleteAllKeys();
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+            fn destroyAttestationIds(&self) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(transactions::destroyAttestationIds, 0, |_aidl_data| {
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.destroyAttestationIds();
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+            fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> {
+              let _aidl_reply = self.binder.transact(transactions::begin, 0, |_aidl_data| {
+                _aidl_data.write(&_arg_inPurpose)?;
+                _aidl_data.write(_arg_inKeyBlob)?;
+                _aidl_data.write(_arg_inParams)?;
+                _aidl_data.write(_arg_inAuthToken)?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
+                  return _aidl_default_impl.begin(_arg_inPurpose, _arg_inKeyBlob, _arg_inParams, _arg_inAuthToken);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+          }
+          impl IKeyMintDevice for binder::Binder<BnKeyMintDevice> {
+            fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> { self.0.getHardwareInfo() }
+            fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> { self.0.verifyAuthorization(_arg_challenge, _arg_parametersToVerify, _arg_token) }
+            fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> { self.0.addRngEntropy(_arg_data) }
+            fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> { self.0.generateKey(_arg_keyParams, _arg_generatedKeyBlob, _arg_generatedKeyCharacteristics, _arg_outCertChain) }
+            fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> { self.0.importKey(_arg_inKeyParams, _arg_inKeyFormat, _arg_inKeyData, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics, _arg_outCertChain) }
+            fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> { self.0.importWrappedKey(_arg_inWrappedKeyData, _arg_inWrappingKeyBlob, _arg_inMaskingKey, _arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics) }
+            fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> { self.0.upgradeKey(_arg_inKeyBlobToUpgrade, _arg_inUpgradeParams) }
+            fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> { self.0.deleteKey(_arg_inKeyBlob) }
+            fn deleteAllKeys(&self) -> binder::public_api::Result<()> { self.0.deleteAllKeys() }
+            fn destroyAttestationIds(&self) -> binder::public_api::Result<()> { self.0.destroyAttestationIds() }
+            fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> { self.0.begin(_arg_inPurpose, _arg_inKeyBlob, _arg_inParams, _arg_inAuthToken) }
+          }
+          fn on_transact(_aidl_service: &dyn IKeyMintDevice, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+            match _aidl_code {
+              transactions::getHardwareInfo => {
+                let _aidl_return = _aidl_service.getHardwareInfo();
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::verifyAuthorization => {
+                let _arg_challenge: i64 = _aidl_data.read()?;
+                let _arg_parametersToVerify: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_token: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.verifyAuthorization(_arg_challenge, &_arg_parametersToVerify, &_arg_token);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::addRngEntropy => {
+                let _arg_data: Vec<u8> = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.addRngEntropy(&_arg_data);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::generateKey => {
+                let _arg_keyParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let mut _arg_generatedKeyBlob: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_generatedKeyBlob)?;
+                let mut _arg_generatedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
+                let mut _arg_outCertChain: Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outCertChain)?;
+                let _aidl_return = _aidl_service.generateKey(&_arg_keyParams, &mut _arg_generatedKeyBlob, &mut _arg_generatedKeyCharacteristics, &mut _arg_outCertChain);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(&_arg_generatedKeyBlob)?;
+                    _aidl_reply.write(&_arg_generatedKeyCharacteristics)?;
+                    _aidl_reply.write(&_arg_outCertChain)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::importKey => {
+                let _arg_inKeyParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat = _aidl_data.read()?;
+                let _arg_inKeyData: Vec<u8> = _aidl_data.read()?;
+                let mut _arg_outImportedKeyBlob: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outImportedKeyBlob)?;
+                let mut _arg_outImportedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
+                let mut _arg_outCertChain: Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outCertChain)?;
+                let _aidl_return = _aidl_service.importKey(&_arg_inKeyParams, _arg_inKeyFormat, &_arg_inKeyData, &mut _arg_outImportedKeyBlob, &mut _arg_outImportedKeyCharacteristics, &mut _arg_outCertChain);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(&_arg_outImportedKeyBlob)?;
+                    _aidl_reply.write(&_arg_outImportedKeyCharacteristics)?;
+                    _aidl_reply.write(&_arg_outCertChain)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::importWrappedKey => {
+                let _arg_inWrappedKeyData: Vec<u8> = _aidl_data.read()?;
+                let _arg_inWrappingKeyBlob: Vec<u8> = _aidl_data.read()?;
+                let _arg_inMaskingKey: Vec<u8> = _aidl_data.read()?;
+                let _arg_inUnwrappingParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_inPasswordSid: i64 = _aidl_data.read()?;
+                let _arg_inBiometricSid: i64 = _aidl_data.read()?;
+                let mut _arg_outImportedKeyBlob: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outImportedKeyBlob)?;
+                let mut _arg_outImportedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
+                let _aidl_return = _aidl_service.importWrappedKey(&_arg_inWrappedKeyData, &_arg_inWrappingKeyBlob, &_arg_inMaskingKey, &_arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, &mut _arg_outImportedKeyBlob, &mut _arg_outImportedKeyCharacteristics);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(&_arg_outImportedKeyBlob)?;
+                    _aidl_reply.write(&_arg_outImportedKeyCharacteristics)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::upgradeKey => {
+                let _arg_inKeyBlobToUpgrade: Vec<u8> = _aidl_data.read()?;
+                let _arg_inUpgradeParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.upgradeKey(&_arg_inKeyBlobToUpgrade, &_arg_inUpgradeParams);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::deleteKey => {
+                let _arg_inKeyBlob: Vec<u8> = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.deleteKey(&_arg_inKeyBlob);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::deleteAllKeys => {
+                let _aidl_return = _aidl_service.deleteAllKeys();
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::destroyAttestationIds => {
+                let _aidl_return = _aidl_service.destroyAttestationIds();
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::begin => {
+                let _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose = _aidl_data.read()?;
+                let _arg_inKeyBlob: Vec<u8> = _aidl_data.read()?;
+                let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_inAuthToken: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
+                let _aidl_return = _aidl_service.begin(_arg_inPurpose, &_arg_inKeyBlob, &_arg_inParams, &_arg_inAuthToken);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+            }
+          }
+        }
+        pub mod IKeyMintOperation {
+          #![allow(non_upper_case_globals)]
+          #![allow(non_snake_case)]
+          #[allow(unused_imports)] use binder::IBinder;
+          use binder::declare_binder_interface;
+          declare_binder_interface! {
+            IKeyMintOperation["android.hardware.keymint.IKeyMintOperation"] {
+              native: BnKeyMintOperation(on_transact),
+              proxy: BpKeyMintOperation {
+              },
+            }
+          }
+          pub trait IKeyMintOperation: binder::Interface + Send {
+            fn get_descriptor() -> &'static str where Self: Sized { "android.hardware.keymint.IKeyMintOperation" }
+            fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn abort(&self) -> binder::public_api::Result<()> {
+              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+            }
+            fn getDefaultImpl() -> IKeyMintOperationDefault where Self: Sized {
+              DEFAULT_IMPL.lock().unwrap().clone()
+            }
+            fn setDefaultImpl(d: IKeyMintOperationDefault) -> IKeyMintOperationDefault where Self: Sized {
+              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+            }
+          }
+          pub mod transactions {
+            #[allow(unused_imports)] use binder::IBinder;
+            pub const update: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
+            pub const finish: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
+            pub const abort: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
+          }
+          pub type IKeyMintOperationDefault = Option<std::sync::Arc<dyn IKeyMintOperation + Sync>>;
+          use lazy_static::lazy_static;
+          lazy_static! {
+            static ref DEFAULT_IMPL: std::sync::Mutex<IKeyMintOperationDefault> = std::sync::Mutex::new(None);
+          }
+          pub(crate) mod mangled { pub use super::IKeyMintOperation as _7_android_8_hardware_7_keymint_17_IKeyMintOperation; }
+          impl IKeyMintOperation for BpKeyMintOperation {
+            fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> {
+              let _aidl_reply = self.binder.transact(transactions::update, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inParams)?;
+                _aidl_data.write(_arg_input)?;
+                _aidl_data.write(_arg_inVerificationToken)?;
+                _aidl_data.write_slice_size(Some(_arg_outParams))?;
+                _aidl_data.write_slice_size(Some(_arg_output))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
+                  return _aidl_default_impl.update(_arg_inParams, _arg_input, _arg_inVerificationToken, _arg_outParams, _arg_output);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              let _aidl_return: i32 = _aidl_reply.read()?;
+              *_arg_outParams = _aidl_reply.read()?;
+              *_arg_output = _aidl_reply.read()?;
+              Ok(_aidl_return)
+            }
+            fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(transactions::finish, 0, |_aidl_data| {
+                _aidl_data.write(_arg_inParams)?;
+                _aidl_data.write(_arg_input)?;
+                _aidl_data.write(_arg_inSignature)?;
+                _aidl_data.write(_arg_authToken)?;
+                _aidl_data.write(_arg_inVerificationToken)?;
+                _aidl_data.write_slice_size(Some(_arg_outParams))?;
+                _aidl_data.write_slice_size(Some(_arg_output))?;
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
+                  return _aidl_default_impl.finish(_arg_inParams, _arg_input, _arg_inSignature, _arg_authToken, _arg_inVerificationToken, _arg_outParams, _arg_output);
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              *_arg_outParams = _aidl_reply.read()?;
+              *_arg_output = _aidl_reply.read()?;
+              Ok(())
+            }
+            fn abort(&self) -> binder::public_api::Result<()> {
+              let _aidl_reply = self.binder.transact(transactions::abort, 0, |_aidl_data| {
+                Ok(())
+              });
+              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+                if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
+                  return _aidl_default_impl.abort();
+                }
+              }
+              let _aidl_reply = _aidl_reply?;
+              let _aidl_status: binder::Status = _aidl_reply.read()?;
+              if !_aidl_status.is_ok() { return Err(_aidl_status); }
+              Ok(())
+            }
+          }
+          impl IKeyMintOperation for binder::Binder<BnKeyMintOperation> {
+            fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> { self.0.update(_arg_inParams, _arg_input, _arg_inVerificationToken, _arg_outParams, _arg_output) }
+            fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> { self.0.finish(_arg_inParams, _arg_input, _arg_inSignature, _arg_authToken, _arg_inVerificationToken, _arg_outParams, _arg_output) }
+            fn abort(&self) -> binder::public_api::Result<()> { self.0.abort() }
+          }
+          fn on_transact(_aidl_service: &dyn IKeyMintOperation, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+            match _aidl_code {
+              transactions::update => {
+                let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_input: Vec<u8> = _aidl_data.read()?;
+                let _arg_inVerificationToken: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_data.read()?;
+                let mut _arg_outParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outParams)?;
+                let mut _arg_output: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_output)?;
+                let _aidl_return = _aidl_service.update(&_arg_inParams, &_arg_input, &_arg_inVerificationToken, &mut _arg_outParams, &mut _arg_output);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(_aidl_return)?;
+                    _aidl_reply.write(&_arg_outParams)?;
+                    _aidl_reply.write(&_arg_output)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::finish => {
+                let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
+                let _arg_input: Vec<u8> = _aidl_data.read()?;
+                let _arg_inSignature: Vec<u8> = _aidl_data.read()?;
+                let _arg_authToken: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
+                let _arg_inVerificationToken: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_data.read()?;
+                let mut _arg_outParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_outParams)?;
+                let mut _arg_output: Vec<u8> = Default::default();
+                _aidl_data.resize_out_vec(&mut _arg_output)?;
+                let _aidl_return = _aidl_service.finish(&_arg_inParams, &_arg_input, &_arg_inSignature, &_arg_authToken, &_arg_inVerificationToken, &mut _arg_outParams, &mut _arg_output);
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                    _aidl_reply.write(&_arg_outParams)?;
+                    _aidl_reply.write(&_arg_output)?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              transactions::abort => {
+                let _aidl_return = _aidl_service.abort();
+                match &_aidl_return {
+                  Ok(_aidl_return) => {
+                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+                  }
+                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+                }
+                Ok(())
+              }
+              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+            }
+          }
+        }
+        pub mod KeyCharacteristics {
+          #[derive(Debug)]
+          pub struct KeyCharacteristics {
+            pub softwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
+            pub hardwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
+          }
+          pub(crate) mod mangled { pub use super::KeyCharacteristics as _7_android_8_hardware_7_keymint_18_KeyCharacteristics; }
+          impl Default for KeyCharacteristics {
+            fn default() -> Self {
+              Self {
+                softwareEnforced: Default::default(),
+                hardwareEnforced: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for KeyCharacteristics {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for KeyCharacteristics {}
+          impl binder::parcel::SerializeOption for KeyCharacteristics {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.softwareEnforced)?;
+              parcel.write(&this.hardwareEnforced)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for KeyCharacteristics {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for KeyCharacteristics {}
+          impl binder::parcel::DeserializeOption for KeyCharacteristics {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.softwareEnforced = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.hardwareEnforced = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod KeyDerivationFunction {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { KeyDerivationFunction : i32 {
+            NONE = 0,
+            RFC5869_SHA256 = 1,
+            ISO18033_2_KDF1_SHA1 = 2,
+            ISO18033_2_KDF1_SHA256 = 3,
+            ISO18033_2_KDF2_SHA1 = 4,
+            ISO18033_2_KDF2_SHA256 = 5,
+          } }
+          pub(crate) mod mangled { pub use super::KeyDerivationFunction as _7_android_8_hardware_7_keymint_21_KeyDerivationFunction; }
+        }
+        pub mod KeyFormat {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { KeyFormat : i32 {
+            X509 = 0,
+            PKCS8 = 1,
+            RAW = 3,
+          } }
+          pub(crate) mod mangled { pub use super::KeyFormat as _7_android_8_hardware_7_keymint_9_KeyFormat; }
+        }
+        pub mod KeyMintHardwareInfo {
+          #[derive(Debug)]
+          pub struct KeyMintHardwareInfo {
+            pub versionNumber: i32, 
+            pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, 
+            pub keyMintName: String, 
+            pub keyMintAuthorName: String, 
+          }
+          pub(crate) mod mangled { pub use super::KeyMintHardwareInfo as _7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo; }
+          impl Default for KeyMintHardwareInfo {
+            fn default() -> Self {
+              Self {
+                versionNumber: 0,
+                securityLevel: Default::default(),
+                keyMintName: Default::default(),
+                keyMintAuthorName: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for KeyMintHardwareInfo {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for KeyMintHardwareInfo {}
+          impl binder::parcel::SerializeOption for KeyMintHardwareInfo {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.versionNumber)?;
+              parcel.write(&this.securityLevel)?;
+              parcel.write(&this.keyMintName)?;
+              parcel.write(&this.keyMintAuthorName)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for KeyMintHardwareInfo {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for KeyMintHardwareInfo {}
+          impl binder::parcel::DeserializeOption for KeyMintHardwareInfo {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.versionNumber = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.securityLevel = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.keyMintName = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.keyMintAuthorName = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod KeyOrigin {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { KeyOrigin : i32 {
+            GENERATED = 0,
+            DERIVED = 1,
+            IMPORTED = 2,
+            RESERVED = 3,
+            SECURELY_IMPORTED = 4,
+          } }
+          pub(crate) mod mangled { pub use super::KeyOrigin as _7_android_8_hardware_7_keymint_9_KeyOrigin; }
+        }
+        pub mod KeyParameter {
+          #[derive(Debug)]
+          pub struct KeyParameter {
+            pub tag: crate::mangled::_7_android_8_hardware_7_keymint_3_Tag, 
+            pub boolValue: bool, 
+            pub integer: i32, 
+            pub longInteger: i64, 
+            pub dateTime: i64, 
+            pub blob: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::KeyParameter as _7_android_8_hardware_7_keymint_12_KeyParameter; }
+          impl Default for KeyParameter {
+            fn default() -> Self {
+              Self {
+                tag: Default::default(),
+                boolValue: false,
+                integer: 0,
+                longInteger: 0,
+                dateTime: 0,
+                blob: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for KeyParameter {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for KeyParameter {}
+          impl binder::parcel::SerializeOption for KeyParameter {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.tag)?;
+              parcel.write(&this.boolValue)?;
+              parcel.write(&this.integer)?;
+              parcel.write(&this.longInteger)?;
+              parcel.write(&this.dateTime)?;
+              parcel.write(&this.blob)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for KeyParameter {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for KeyParameter {}
+          impl binder::parcel::DeserializeOption for KeyParameter {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.tag = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.boolValue = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.integer = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.longInteger = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.dateTime = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.blob = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod KeyPurpose {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { KeyPurpose : i32 {
+            ENCRYPT = 0,
+            DECRYPT = 1,
+            SIGN = 2,
+            VERIFY = 3,
+            WRAP_KEY = 5,
+          } }
+          pub(crate) mod mangled { pub use super::KeyPurpose as _7_android_8_hardware_7_keymint_10_KeyPurpose; }
+        }
+        pub mod PaddingMode {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { PaddingMode : i32 {
+            NONE = 1,
+            RSA_OAEP = 2,
+            RSA_PSS = 3,
+            RSA_PKCS1_1_5_ENCRYPT = 4,
+            RSA_PKCS1_1_5_SIGN = 5,
+            PKCS7 = 64,
+          } }
+          pub(crate) mod mangled { pub use super::PaddingMode as _7_android_8_hardware_7_keymint_11_PaddingMode; }
+        }
+        pub mod SecurityLevel {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { SecurityLevel : i32 {
+            SOFTWARE = 0,
+            TRUSTED_ENVIRONMENT = 1,
+            STRONGBOX = 2,
+          } }
+          pub(crate) mod mangled { pub use super::SecurityLevel as _7_android_8_hardware_7_keymint_13_SecurityLevel; }
+        }
+        pub mod Tag {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { Tag : i32 {
+            INVALID = 0,
+            PURPOSE = 536870913,
+            ALGORITHM = 268435458,
+            KEY_SIZE = 805306371,
+            BLOCK_MODE = 536870916,
+            DIGEST = 536870917,
+            PADDING = 536870918,
+            CALLER_NONCE = 1879048199,
+            MIN_MAC_LENGTH = 805306376,
+            EC_CURVE = 268435466,
+            RSA_PUBLIC_EXPONENT = 1342177480,
+            INCLUDE_UNIQUE_ID = 1879048394,
+            BLOB_USAGE_REQUIREMENTS = 268435757,
+            BOOTLOADER_ONLY = 1879048494,
+            ROLLBACK_RESISTANCE = 1879048495,
+            HARDWARE_TYPE = 268435760,
+            EARLY_BOOT_ONLY = 1879048497,
+            ACTIVE_DATETIME = 1610613136,
+            ORIGINATION_EXPIRE_DATETIME = 1610613137,
+            USAGE_EXPIRE_DATETIME = 1610613138,
+            MIN_SECONDS_BETWEEN_OPS = 805306771,
+            MAX_USES_PER_BOOT = 805306772,
+            USER_ID = 805306869,
+            USER_SECURE_ID = 1073742326,
+            NO_AUTH_REQUIRED = 1879048695,
+            USER_AUTH_TYPE = 268435960,
+            AUTH_TIMEOUT = 805306873,
+            ALLOW_WHILE_ON_BODY = 1879048698,
+            TRUSTED_USER_PRESENCE_REQUIRED = 1879048699,
+            TRUSTED_CONFIRMATION_REQUIRED = 1879048700,
+            UNLOCKED_DEVICE_REQUIRED = 1879048701,
+            APPLICATION_ID = -1879047591,
+            APPLICATION_DATA = -1879047492,
+            CREATION_DATETIME = 1610613437,
+            ORIGIN = 268436158,
+            ROOT_OF_TRUST = -1879047488,
+            OS_VERSION = 805307073,
+            OS_PATCHLEVEL = 805307074,
+            UNIQUE_ID = -1879047485,
+            ATTESTATION_CHALLENGE = -1879047484,
+            ATTESTATION_APPLICATION_ID = -1879047483,
+            ATTESTATION_ID_BRAND = -1879047482,
+            ATTESTATION_ID_DEVICE = -1879047481,
+            ATTESTATION_ID_PRODUCT = -1879047480,
+            ATTESTATION_ID_SERIAL = -1879047479,
+            ATTESTATION_ID_IMEI = -1879047478,
+            ATTESTATION_ID_MEID = -1879047477,
+            ATTESTATION_ID_MANUFACTURER = -1879047476,
+            ATTESTATION_ID_MODEL = -1879047475,
+            VENDOR_PATCHLEVEL = 805307086,
+            BOOT_PATCHLEVEL = 805307087,
+            DEVICE_UNIQUE_ATTESTATION = 1879048912,
+            IDENTITY_CREDENTIAL_KEY = 1879048913,
+            STORAGE_KEY = 1879048914,
+            ASSOCIATED_DATA = -1879047192,
+            NONCE = -1879047191,
+            MAC_LENGTH = 805307371,
+            RESET_SINCE_ID_ROTATION = 1879049196,
+            CONFIRMATION_TOKEN = -1879047187,
+          } }
+          pub(crate) mod mangled { pub use super::Tag as _7_android_8_hardware_7_keymint_3_Tag; }
+        }
+        pub mod TagType {
+          #![allow(non_upper_case_globals)]
+          use binder::declare_binder_enum;
+          declare_binder_enum! { TagType : i32 {
+            INVALID = 0,
+            ENUM = 268435456,
+            ENUM_REP = 536870912,
+            UINT = 805306368,
+            UINT_REP = 1073741824,
+            ULONG = 1342177280,
+            DATE = 1610612736,
+            BOOL = 1879048192,
+            BIGNUM = -2147483648,
+            BYTES = -1879048192,
+            ULONG_REP = -1610612736,
+          } }
+          pub(crate) mod mangled { pub use super::TagType as _7_android_8_hardware_7_keymint_7_TagType; }
+        }
+        pub mod Timestamp {
+          #[derive(Debug)]
+          pub struct Timestamp {
+            pub milliSeconds: i64, 
+          }
+          pub(crate) mod mangled { pub use super::Timestamp as _7_android_8_hardware_7_keymint_9_Timestamp; }
+          impl Default for Timestamp {
+            fn default() -> Self {
+              Self {
+                milliSeconds: 0,
+              }
+            }
+          }
+          impl binder::parcel::Serialize for Timestamp {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for Timestamp {}
+          impl binder::parcel::SerializeOption for Timestamp {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.milliSeconds)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for Timestamp {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for Timestamp {}
+          impl binder::parcel::DeserializeOption for Timestamp {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.milliSeconds = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+        pub mod VerificationToken {
+          #[derive(Debug)]
+          pub struct VerificationToken {
+            pub challenge: i64, 
+            pub timestamp: crate::mangled::_7_android_8_hardware_7_keymint_9_Timestamp, 
+            pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, 
+            pub mac: Vec<u8>, 
+          }
+          pub(crate) mod mangled { pub use super::VerificationToken as _7_android_8_hardware_7_keymint_17_VerificationToken; }
+          impl Default for VerificationToken {
+            fn default() -> Self {
+              Self {
+                challenge: 0,
+                timestamp: Default::default(),
+                securityLevel: Default::default(),
+                mac: Default::default(),
+              }
+            }
+          }
+          impl binder::parcel::Serialize for VerificationToken {
+            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
+            }
+          }
+          impl binder::parcel::SerializeArray for VerificationToken {}
+          impl binder::parcel::SerializeOption for VerificationToken {
+            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+              let this = if let Some(this) = this {
+                parcel.write(&1i32)?;
+                this
+              } else {
+                return parcel.write(&0i32);
+              };
+              let start_pos = parcel.get_data_position();
+              parcel.write(&0i32)?;
+              parcel.write(&this.challenge)?;
+              parcel.write(&this.timestamp)?;
+              parcel.write(&this.securityLevel)?;
+              parcel.write(&this.mac)?;
+              let end_pos = parcel.get_data_position();
+              let parcelable_size = (end_pos - start_pos) as i32;
+              unsafe { parcel.set_data_position(start_pos)?; }
+              parcel.write(&parcelable_size)?;
+              unsafe { parcel.set_data_position(end_pos)?; }
+              Ok(())
+            }
+          }
+          impl binder::parcel::Deserialize for VerificationToken {
+            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
+              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
+                 .transpose()
+                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+            }
+          }
+          impl binder::parcel::DeserializeArray for VerificationToken {}
+          impl binder::parcel::DeserializeOption for VerificationToken {
+            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
+              let status: i32 = parcel.read()?;
+              if status == 0 { return Ok(None); }
+              let start_pos = parcel.get_data_position();
+              let parcelable_size: i32 = parcel.read()?;
+              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
+              let mut result = Self::default();
+              result.challenge = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.timestamp = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.securityLevel = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              result.mac = parcel.read()?;
+              if (parcel.get_data_position() - start_pos) == parcelable_size {
+                return Ok(Some(result));
+              }
+              Ok(Some(result))
+            }
+          }
+        }
+      }
+    }
+  }
+}
+pub mod mangled {
+  pub use super::aidl::android::hardware::keymint::Algorithm::mangled::*;
+  pub use super::aidl::android::hardware::keymint::BeginResult::mangled::*;
+  pub use super::aidl::android::hardware::keymint::BlockMode::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Certificate::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Constants::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Digest::mangled::*;
+  pub use super::aidl::android::hardware::keymint::EcCurve::mangled::*;
+  pub use super::aidl::android::hardware::keymint::ErrorCode::mangled::*;
+  pub use super::aidl::android::hardware::keymint::HardwareAuthToken::mangled::*;
+  pub use super::aidl::android::hardware::keymint::HardwareAuthenticatorType::mangled::*;
+  pub use super::aidl::android::hardware::keymint::HmacSharingParameters::mangled::*;
+  pub use super::aidl::android::hardware::keymint::IKeyMintDevice::mangled::*;
+  pub use super::aidl::android::hardware::keymint::IKeyMintOperation::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyCharacteristics::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyDerivationFunction::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyFormat::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyMintHardwareInfo::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyOrigin::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyParameter::mangled::*;
+  pub use super::aidl::android::hardware::keymint::KeyPurpose::mangled::*;
+  pub use super::aidl::android::hardware::keymint::PaddingMode::mangled::*;
+  pub use super::aidl::android::hardware::keymint::SecurityLevel::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Tag::mangled::*;
+  pub use super::aidl::android::hardware::keymint::TagType::mangled::*;
+  pub use super::aidl::android::hardware::keymint::Timestamp::mangled::*;
+  pub use super::aidl::android::hardware::keymint::VerificationToken::mangled::*;
+}
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
new file mode 100644
index 0000000..df71d94
--- /dev/null
+++ b/keystore2/src/database.rs
@@ -0,0 +1,1654 @@
+// 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 Keystore 2.0 database module.
+//! The database module provides a connection to the backing SQLite store.
+//! We have two databases one for persistent key blob storage and one for
+//! items that have a per boot life cycle.
+//!
+//! ## Persistent database
+//! The persistent database has tables for key blobs. They are organized
+//! as follows:
+//! The `keyentry` table is the primary table for key entries. It is
+//! accompanied by two tables for blobs and parameters.
+//! Each key entry occupies exactly one row in the `keyentry` table and
+//! zero or more rows in the tables `blobentry` and `keyparameter`.
+//!
+//! ## Per boot database
+//! The per boot database stores items with a per boot lifecycle.
+//! Currently, there is only the `grant` table in this database.
+//! Grants are references to a key that can be used to access a key by
+//! clients that don't own that key. Grants can only be created by the
+//! owner of a key. And only certain components can create grants.
+//! This is governed by SEPolicy.
+//!
+//! ## Access control
+//! Some database functions that load keys or create grants perform
+//! access control. This is because in some cases access control
+//! can only be performed after some information about the designated
+//! key was loaded from the database. To decouple the permission checks
+//! from the database module these functions take permission check
+//! callbacks.
+
+use crate::error::{Error as KsError, ResponseCode};
+use crate::key_parameter::{KeyParameter, SqlField, Tag};
+use crate::permission::KeyPermSet;
+use anyhow::{anyhow, Context, Result};
+
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, KeyDescriptor::KeyDescriptor, SecurityLevel::SecurityLevel,
+};
+
+#[cfg(not(test))]
+use rand::prelude::random;
+use rusqlite::{
+    params, types::FromSql, types::FromSqlResult, types::ToSqlOutput, types::ValueRef, Connection,
+    OptionalExtension, Row, Rows, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
+};
+use std::sync::Once;
+#[cfg(test)]
+use tests::random;
+
+/// Keys have a KeyMint blob component and optional public certificate and
+/// 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)]
+pub struct KeyEntryLoadBits(u32);
+
+impl KeyEntryLoadBits {
+    /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded.
+    pub const NONE: KeyEntryLoadBits = Self(0);
+    /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded.
+    pub const KM: KeyEntryLoadBits = Self(1);
+    /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded.
+    pub const PUBLIC: KeyEntryLoadBits = Self(2);
+    /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded.
+    pub const BOTH: KeyEntryLoadBits = Self(3);
+
+    /// Returns true if this object indicates that the public components shall be loaded.
+    pub const fn load_public(&self) -> bool {
+        self.0 & Self::PUBLIC.0 != 0
+    }
+
+    /// Returns true if the object indicates that the KeyMint component shall be loaded.
+    pub const fn load_km(&self) -> bool {
+        self.0 & Self::KM.0 != 0
+    }
+}
+
+/// 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
+/// for the KeyMint blob, public certificate and a public certificate chain.
+#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd)]
+pub struct KeyEntry {
+    id: i64,
+    km_blob: Option<Vec<u8>>,
+    cert: Option<Vec<u8>>,
+    cert_chain: Option<Vec<u8>>,
+    sec_level: SecurityLevel,
+    parameters: Vec<KeyParameter>,
+}
+
+impl KeyEntry {
+    /// Returns the unique id of the Key entry.
+    pub fn id(&self) -> i64 {
+        self.id
+    }
+    /// Exposes the optional KeyMint blob.
+    pub fn km_blob(&self) -> &Option<Vec<u8>> {
+        &self.km_blob
+    }
+    /// Extracts the Optional KeyMint blob.
+    pub fn take_km_blob(&mut self) -> Option<Vec<u8>> {
+        self.km_blob.take()
+    }
+    /// Exposes the optional public certificate.
+    pub fn cert(&self) -> &Option<Vec<u8>> {
+        &self.cert
+    }
+    /// Extracts the optional public certificate.
+    pub fn take_cert(&mut self) -> Option<Vec<u8>> {
+        self.cert.take()
+    }
+    /// Exposes the optional public certificate chain.
+    pub fn cert_chain(&self) -> &Option<Vec<u8>> {
+        &self.cert_chain
+    }
+    /// Extracts the optional public certificate_chain.
+    pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
+        self.cert_chain.take()
+    }
+    /// Returns the security level of the key entry.
+    pub fn sec_level(&self) -> SecurityLevel {
+        self.sec_level
+    }
+}
+
+/// Indicates the sub component of a key entry for persistent storage.
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub struct SubComponentType(u32);
+impl SubComponentType {
+    /// Persistent identifier for a KeyMint blob.
+    pub const KM_BLOB: SubComponentType = Self(0);
+    /// Persistent identifier for a certificate blob.
+    pub const CERT: SubComponentType = Self(1);
+    /// Persistent identifier for a certificate chain blob.
+    pub const CERT_CHAIN: SubComponentType = Self(2);
+}
+
+impl ToSql for SubComponentType {
+    fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
+        self.0.to_sql()
+    }
+}
+
+impl FromSql for SubComponentType {
+    fn column_result(value: ValueRef) -> FromSqlResult<Self> {
+        Ok(Self(u32::column_result(value)?))
+    }
+}
+
+static INIT_TABLES: Once = Once::new();
+
+/// KeystoreDB wraps a connection to an SQLite database and tracks its
+/// ownership. It also implements all of Keystore 2.0's database functionality.
+pub struct KeystoreDB {
+    conn: Connection,
+}
+
+impl KeystoreDB {
+    /// This will create a new database connection connecting the two
+    /// files persistent.sqlite and perboot.sqlite in the current working
+    /// directory, which is usually `/data/misc/keystore/`.
+    /// It also attempts to initialize all of the tables on the first instantiation
+    /// per service startup. KeystoreDB cannot be used by multiple threads.
+    /// Each thread should open their own connection using `thread_local!`.
+    pub fn new() -> Result<Self> {
+        let conn = Self::make_connection("file:persistent.sqlite", "file:perboot.sqlite")?;
+
+        INIT_TABLES.call_once(|| Self::init_tables(&conn).expect("Failed to initialize tables."));
+        Ok(Self { conn })
+    }
+
+    fn init_tables(conn: &Connection) -> Result<()> {
+        conn.execute(
+            "CREATE TABLE IF NOT EXISTS persistent.keyentry (
+                     id INTEGER UNIQUE,
+                     creation_date DATETIME,
+                     domain INTEGER,
+                     namespace INTEGER,
+                     alias TEXT);",
+            NO_PARAMS,
+        )
+        .context("Failed to initialize \"keyentry\" table.")?;
+
+        conn.execute(
+            "CREATE VIEW IF NOT EXISTS persistent.orphaned AS
+                    SELECT id FROM persistent.keyentry WHERE domain IS NULL;",
+            NO_PARAMS,
+        )
+        .context("Failed to initialize \"orphaned\" view")?;
+
+        conn.execute(
+            "CREATE TABLE IF NOT EXISTS persistent.blobentry (
+                    id INTEGER PRIMARY KEY,
+                    subcomponent_type INTEGER,
+                    keyentryid INTEGER,
+                    blob BLOB,
+                    sec_level INTEGER);",
+            NO_PARAMS,
+        )
+        .context("Failed to initialize \"blobentry\" table.")?;
+
+        conn.execute(
+            "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
+                     keyentryid INTEGER,
+                     tag INTEGER,
+                     data ANY,
+                     security_level INTEGER);",
+            NO_PARAMS,
+        )
+        .context("Failed to initialize \"keyparameter\" table.")?;
+
+        // TODO only drop the perboot table if we start up for the first time per boot.
+        // Right now this is done once per startup which will lose some information
+        // upon a crash.
+        // Note: This is no regression with respect to the legacy Keystore.
+        conn.execute("DROP TABLE IF EXISTS perboot.grant;", NO_PARAMS)
+            .context("Failed to drop perboot.grant table")?;
+        conn.execute(
+            "CREATE TABLE perboot.grant (
+                    id INTEGER UNIQUE,
+                    grantee INTEGER,
+                    keyentryid INTEGER,
+                    access_vector INTEGER);",
+            NO_PARAMS,
+        )
+        .context("Failed to initialize \"grant\" table.")?;
+
+        Ok(())
+    }
+
+    fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
+        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.")?;
+
+        Ok(conn)
+    }
+
+    /// Creates a new key entry and allocates a new randomized id for the new key.
+    /// The key id gets associated with a domain and namespace but not with an alias.
+    /// To complete key generation `rebind_alias` should be called after all of the
+    /// key artifacts, i.e., blobs and parameters have been associated with the new
+    /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
+    /// atomic even if key generation is not.
+    pub fn create_key_entry(&self, domain: Domain, namespace: i64) -> Result<i64> {
+        match domain {
+            Domain::APP | Domain::SELINUX => {}
+            _ => {
+                return Err(KsError::sys())
+                    .context(format!("Domain {:?} must be either App or SELinux.", domain));
+            }
+        }
+        Self::insert_with_retry(|id| {
+            self.conn.execute(
+                "INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
+                     VALUES(?, datetime('now'), ?, ?, NULL);",
+                params![id, domain.0 as u32, namespace],
+            )
+        })
+        .context("In create_key_entry")
+    }
+
+    /// Inserts a new blob and associates it with the given key id. Each blob
+    /// has a sub component type and a security level.
+    /// Each key can have one of each sub component type associated. If more
+    /// are added only the most recent can be retrieved, and superseded blobs
+    /// will get garbage collected. The security level field of components
+    /// other than `SubComponentType::KM_BLOB` are ignored.
+    pub fn insert_blob(
+        &mut self,
+        key_id: i64,
+        sc_type: SubComponentType,
+        blob: &[u8],
+        sec_level: SecurityLevel,
+    ) -> Result<()> {
+        self.conn
+            .execute(
+                "INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob, sec_level)
+                    VALUES (?, ?, ?, ?);",
+                params![sc_type, key_id, blob, sec_level.0],
+            )
+            .context("Failed to insert blob.")?;
+        Ok(())
+    }
+
+    /// Inserts a collection of key parameters into the `persistent.keyparameter` table
+    /// and associates them with the given `key_id`.
+    pub fn insert_keyparameter<'a>(
+        &mut self,
+        key_id: i64,
+        params: impl IntoIterator<Item = &'a KeyParameter>,
+    ) -> Result<()> {
+        let mut stmt = self
+            .conn
+            .prepare(
+                "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
+                    VALUES (?, ?, ?, ?);",
+            )
+            .context("In insert_keyparameter: Failed to prepare statement.")?;
+
+        let iter = params.into_iter();
+        for p in iter {
+            stmt.insert(params![
+                key_id,
+                p.get_tag().0,
+                p.key_parameter_value(),
+                p.security_level().0
+            ])
+            .with_context(|| format!("In insert_keyparameter: Failed to insert {:?}", p))?;
+        }
+        Ok(())
+    }
+
+    /// 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.
+    pub fn rebind_alias(
+        &mut self,
+        newid: i64,
+        alias: &str,
+        domain: Domain,
+        namespace: i64,
+    ) -> Result<()> {
+        match domain {
+            Domain::APP | Domain::SELINUX => {}
+            _ => {
+                return Err(KsError::sys()).context(format!(
+                    "In rebind_alias: Domain {:?} must be either App or SELinux.",
+                    domain
+                ));
+            }
+        }
+        let tx = self
+            .conn
+            .transaction_with_behavior(TransactionBehavior::Immediate)
+            .context("In rebind_alias: Failed to initialize transaction.")?;
+        tx.execute(
+            "UPDATE persistent.keyentry
+                 SET alias = NULL, domain = NULL, namespace = NULL
+                 WHERE alias = ? AND domain = ? AND namespace = ?;",
+            params![alias, domain.0 as u32, namespace],
+        )
+        .context("In rebind_alias: Failed to rebind existing entry.")?;
+        let result = tx
+            .execute(
+                "UPDATE persistent.keyentry
+                    SET alias = ?
+                    WHERE id = ? AND domain = ? AND namespace = ?;",
+                params![alias, newid, domain.0 as u32, namespace],
+            )
+            .context("In rebind_alias: Failed to set alias.")?;
+        if result != 1 {
+            // Note that this explicit rollback is not required, as
+            // the transaction should rollback if we do not commit it.
+            // We leave it here for readability.
+            tx.rollback().context("In rebind_alias: Failed to rollback a failed transaction.")?;
+            return Err(KsError::sys()).context(format!(
+                "In rebind_alias: Expected to update a single entry but instead updated {}.",
+                result
+            ));
+        }
+        tx.commit().context("In rebind_alias: Failed to commit transaction.")
+    }
+
+    // Helper function loading the key_id given the key descriptor
+    // tuple comprising domain, namespace, and alias.
+    // Requires a valid transaction.
+    fn load_key_entry_id(key: &KeyDescriptor, tx: &Transaction) -> Result<i64> {
+        let alias = key
+            .alias
+            .as_ref()
+            .map_or_else(|| Err(KsError::sys()), Ok)
+            .context("In load_key_entry_id: Alias must be specified.")?;
+        let mut stmt = tx
+            .prepare(
+                "SELECT id FROM persistent.keyentry
+                    WHERE
+                    domain = ?
+                    AND namespace = ?
+                    AND alias = ?;",
+            )
+            .context("In load_key_entry_id: Failed to select from keyentry table.")?;
+        let mut rows = stmt
+            .query(params![key.domain.0 as u32, key.nspace, alias])
+            .context("In load_key_entry_id: Failed to read from keyentry table.")?;
+        Self::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("In load_key_entry_id.")
+    }
+
+    /// This helper function completes the access tuple of a key, which is required
+    /// to perform access control. The strategy depends on the `domain` field in the
+    /// key descriptor.
+    /// * Domain::SELINUX: The access tuple is complete and this function only loads
+    ///       the key_id for further processing.
+    /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
+    ///       which serves as the namespace.
+    /// * Domain::GRANT: The grant table is queried for the `key_id` and the
+    ///       `access_vector`.
+    /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
+    ///       `namespace`.
+    /// In each case the information returned is sufficient to perform the access
+    /// check and the key id can be used to load further key artifacts.
+    fn load_access_tuple(
+        tx: &Transaction,
+        key: KeyDescriptor,
+        caller_uid: u32,
+    ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
+        match key.domain {
+            // Domain App or SELinux. In this case we load the key_id from
+            // the keyentry database for further loading of key components.
+            // We already have the full access tuple to perform access control.
+            // The only distinction is that we use the caller_uid instead
+            // of the caller supplied namespace if the domain field is
+            // Domain::APP.
+            Domain::APP | Domain::SELINUX => {
+                let mut access_key = key;
+                if access_key.domain == Domain::APP {
+                    access_key.nspace = caller_uid as i64;
+                }
+                let key_id = Self::load_key_entry_id(&access_key, &tx)
+                    .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
+
+                Ok((key_id, access_key, None))
+            }
+
+            // Domain::GRANT. In this case we load the key_id and the access_vector
+            // from the grant table.
+            Domain::GRANT => {
+                let mut stmt = tx
+                    .prepare(
+                        "SELECT keyentryid, access_vector FROM perboot.grant
+                            WHERE grantee = ? AND id = ?;",
+                    )
+                    .context("Domain::GRANT prepare statement failed")?;
+                let mut rows = stmt
+                    .query(params![caller_uid as i64, key.nspace])
+                    .context("Domain:Grant: query failed.")?;
+                let (key_id, access_vector): (i64, i32) =
+                    Self::with_rows_extract_one(&mut rows, |row| {
+                        let r =
+                            row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
+                        Ok((
+                            r.get(0).context("Failed to unpack key_id.")?,
+                            r.get(1).context("Failed to unpack access_vector.")?,
+                        ))
+                    })
+                    .context("Domain::GRANT.")?;
+                Ok((key_id, key, Some(access_vector.into())))
+            }
+
+            // Domain::KEY_ID. In this case we load the domain and namespace from the
+            // keyentry database because we need them for access control.
+            Domain::KEY_ID => {
+                let mut stmt = tx
+                    .prepare(
+                        "SELECT domain, namespace FROM persistent.keyentry
+                            WHERE
+                            id = ?;",
+                    )
+                    .context("Domain::KEY_ID: prepare statement failed")?;
+                let mut rows =
+                    stmt.query(params![key.nspace]).context("Domain::KEY_ID: query failed.")?;
+                let (domain, namespace): (Domain, i64) =
+                    Self::with_rows_extract_one(&mut rows, |row| {
+                        let r =
+                            row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
+                        Ok((
+                            Domain(r.get(0).context("Failed to unpack domain.")?),
+                            r.get(1).context("Failed to unpack namespace.")?,
+                        ))
+                    })
+                    .context("Domain::KEY_ID.")?;
+                let key_id = key.nspace;
+                let mut access_key = key;
+                access_key.domain = domain;
+                access_key.nspace = namespace;
+
+                Ok((key_id, access_key, None))
+            }
+            _ => Err(anyhow!(KsError::sys())),
+        }
+    }
+
+    fn load_blob_components(
+        key_id: i64,
+        load_bits: KeyEntryLoadBits,
+        tx: &Transaction,
+    ) -> Result<(SecurityLevel, Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
+        let mut stmt = tx
+            .prepare(
+                "SELECT MAX(id), sec_level, subcomponent_type, blob FROM persistent.blobentry
+                    WHERE keyentryid = ? GROUP BY subcomponent_type;",
+            )
+            .context("In load_blob_components: prepare statement failed.")?;
+
+        let mut rows =
+            stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
+
+        let mut sec_level: SecurityLevel = Default::default();
+        let mut km_blob: Option<Vec<u8>> = None;
+        let mut cert_blob: Option<Vec<u8>> = None;
+        let mut cert_chain_blob: Option<Vec<u8>> = None;
+        Self::with_rows_extract_all(&mut rows, |row| {
+            let sub_type: SubComponentType =
+                row.get(2).context("Failed to extract subcomponent_type.")?;
+            match (sub_type, load_bits.load_public()) {
+                (SubComponentType::KM_BLOB, _) => {
+                    sec_level =
+                        SecurityLevel(row.get(1).context("Failed to extract security level.")?);
+                    if load_bits.load_km() {
+                        km_blob = Some(row.get(3).context("Failed to extract KM blob.")?);
+                    }
+                }
+                (SubComponentType::CERT, true) => {
+                    cert_blob =
+                        Some(row.get(3).context("Failed to extract public certificate blob.")?);
+                }
+                (SubComponentType::CERT_CHAIN, true) => {
+                    cert_chain_blob =
+                        Some(row.get(3).context("Failed to extract certificate chain blob.")?);
+                }
+                (SubComponentType::CERT, _) | (SubComponentType::CERT_CHAIN, _) => {}
+                _ => Err(KsError::sys()).context("Unknown subcomponent type.")?,
+            }
+            Ok(())
+        })
+        .context("In load_blob_components.")?;
+
+        Ok((sec_level, km_blob, cert_blob, cert_chain_blob))
+    }
+
+    fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> {
+        let mut stmt = tx
+            .prepare(
+                "SELECT tag, data, security_level from persistent.keyparameter
+                    WHERE keyentryid = ?;",
+            )
+            .context("In load_key_parameters: prepare statement failed.")?;
+
+        let mut parameters: Vec<KeyParameter> = Vec::new();
+
+        let mut rows =
+            stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
+        Self::with_rows_extract_all(&mut rows, |row| {
+            let tag = Tag(row.get(0).context("Failed to read tag.")?);
+            let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
+            parameters.push(
+                KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
+                    .context("Failed to read KeyParameter.")?,
+            );
+            Ok(())
+        })
+        .context("In load_key_parameters.")?;
+
+        Ok(parameters)
+    }
+
+    /// Load a key entry by the given key descriptor.
+    /// It uses the `check_permission` callback to verify if the access is allowed
+    /// given the key access tuple read from the database using `load_access_tuple`.
+    /// With `load_bits` the caller may specify which blobs shall be loaded from
+    /// the blob database.
+    pub fn load_key_entry(
+        &mut self,
+        key: KeyDescriptor,
+        load_bits: KeyEntryLoadBits,
+        caller_uid: u32,
+        check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
+    ) -> Result<KeyEntry> {
+        let tx = self
+            .conn
+            .transaction_with_behavior(TransactionBehavior::Deferred)
+            .context("In load_key_entry: Failed to initialize transaction.")?;
+
+        // Load the key_id and complete the access control tuple.
+        let (key_id, access_key_descriptor, access_vector) =
+            Self::load_access_tuple(&tx, key, caller_uid).context("In load_key_entry.")?;
+
+        // Perform access control. It is vital that we return here if the permission is denied.
+        // So do not touch that '?' at the end.
+        check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
+
+        let (sec_level, km_blob, cert_blob, cert_chain_blob) =
+            Self::load_blob_components(key_id, load_bits, &tx).context("In load_key_entry.")?;
+
+        let parameters = Self::load_key_parameters(key_id, &tx).context("In load_key_entry.")?;
+
+        tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
+
+        Ok(KeyEntry {
+            id: key_id,
+            km_blob,
+            cert: cert_blob,
+            cert_chain: cert_chain_blob,
+            sec_level,
+            parameters,
+        })
+    }
+
+    /// Adds a grant to the grant table.
+    /// Like `load_key_entry` this function loads the access tuple before
+    /// it uses the callback for a permission check. Upon success,
+    /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the
+    /// grant table. The new row will have a randomized id, which is used as
+    /// grant id in the namespace field of the resulting KeyDescriptor.
+    pub fn grant(
+        &mut self,
+        key: KeyDescriptor,
+        caller_uid: u32,
+        grantee_uid: u32,
+        access_vector: KeyPermSet,
+        check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
+    ) -> Result<KeyDescriptor> {
+        let tx = self
+            .conn
+            .transaction_with_behavior(TransactionBehavior::Immediate)
+            .context("In grant: Failed to initialize transaction.")?;
+
+        // 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, 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.")?;
+
+        let grant_id = if let Some(grant_id) = tx
+            .query_row(
+                "SELECT id FROM perboot.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 perboot.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 perboot.grant (id, grantee, keyentryid, access_vector)
+                        VALUES (?, ?, ?, ?);",
+                    params![id, grantee_uid, key_id, i32::from(access_vector)],
+                )
+            })
+            .context("In grant")?
+        };
+        tx.commit().context("In grant: failed to commit transaction.")?;
+
+        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,
+        caller_uid: u32,
+        grantee_uid: u32,
+        check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
+    ) -> Result<()> {
+        let tx = self
+            .conn
+            .transaction_with_behavior(TransactionBehavior::Immediate)
+            .context("In ungrant: Failed to initialize transaction.")?;
+
+        // 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, 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.")?;
+
+        tx.execute(
+            "DELETE FROM perboot.grant
+                WHERE keyentryid = ? AND grantee = ?;",
+            params![key_id, grantee_uid],
+        )
+        .context("Failed to delete grant.")?;
+
+        tx.commit().context("In ungrant: failed to commit transaction.")?;
+
+        Ok(())
+    }
+
+    // Generates a random id and passes it to the given function, which will
+    // try to insert it into a database.  If that insertion fails, retry;
+    // otherwise return the id.
+    fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
+        loop {
+            let newid: i64 = random();
+            match inserter(newid) {
+                // If the id already existed, try again.
+                Err(rusqlite::Error::SqliteFailure(
+                    libsqlite3_sys::Error {
+                        code: libsqlite3_sys::ErrorCode::ConstraintViolation,
+                        extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
+                    },
+                    _,
+                )) => (),
+                Err(e) => {
+                    return Err(e).context("In insert_with_retry: failed to insert into database.")
+                }
+                _ => return Ok(newid),
+            }
+        }
+    }
+
+    // Takes Rows as returned by a query call on prepared statement.
+    // Extracts exactly one row with the `row_extractor` and fails if more
+    // rows are available.
+    // If no row was found, `None` is passed to the `row_extractor`.
+    // This allows the row extractor to decide on an error condition or
+    // a different default behavior.
+    fn with_rows_extract_one<'a, T, F>(rows: &mut Rows<'a>, row_extractor: F) -> Result<T>
+    where
+        F: FnOnce(Option<&Row<'a>>) -> Result<T>,
+    {
+        let result =
+            row_extractor(rows.next().context("with_rows_extract_one: Failed to unpack row.")?);
+
+        rows.next()
+            .context("In with_rows_extract_one: Failed to unpack unexpected row.")?
+            .map_or_else(|| Ok(()), |_| Err(KsError::sys()))
+            .context("In with_rows_extract_one: Unexpected row.")?;
+
+        result
+    }
+
+    fn with_rows_extract_all<'a, F>(rows: &mut Rows<'a>, mut row_extractor: F) -> Result<()>
+    where
+        F: FnMut(&Row<'a>) -> Result<()>,
+    {
+        loop {
+            match rows.next().context("In with_rows_extract_all: Failed to unpack row")? {
+                Some(row) => {
+                    row_extractor(&row).context("In with_rows_extract_all.")?;
+                }
+                None => break Ok(()),
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+    use crate::key_parameter::{
+        Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
+        KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
+    };
+    use crate::key_perm_set;
+    use crate::permission::{KeyPerm, KeyPermSet};
+    use rusqlite::NO_PARAMS;
+    use std::cell::RefCell;
+
+    static PERSISTENT_TEST_SQL: &str = "/data/local/tmp/persistent.sqlite";
+    static PERBOOT_TEST_SQL: &str = "/data/local/tmp/perboot.sqlite";
+
+    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 })
+    }
+
+    fn new_test_db_with_persistent_file() -> Result<KeystoreDB> {
+        let conn = KeystoreDB::make_connection(PERSISTENT_TEST_SQL, PERBOOT_TEST_SQL)?;
+
+        KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
+        Ok(KeystoreDB { conn })
+    }
+
+    // Ensure that we're using the "injected" random function, not the real one.
+    #[test]
+    fn test_mocked_random() {
+        let rand1 = random();
+        let rand2 = random();
+        let rand3 = random();
+        if rand1 == rand2 {
+            assert_eq!(rand2 + 1, rand3);
+        } else {
+            assert_eq!(rand1 + 1, rand2);
+            assert_eq!(rand2, rand3);
+        }
+    }
+
+    // Test that we have the correct tables.
+    #[test]
+    fn test_tables() -> Result<()> {
+        let db = new_test_db()?;
+        let tables = db
+            .conn
+            .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
+            .query_map(params![], |row| row.get(0))?
+            .collect::<rusqlite::Result<Vec<String>>>()?;
+        assert_eq!(tables.len(), 3);
+        assert_eq!(tables[0], "blobentry");
+        assert_eq!(tables[1], "keyentry");
+        assert_eq!(tables[2], "keyparameter");
+        let tables = db
+            .conn
+            .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
+            .query_map(params![], |row| row.get(0))?
+            .collect::<rusqlite::Result<Vec<String>>>()?;
+        assert_eq!(tables.len(), 1);
+        assert_eq!(tables[0], "grant");
+        Ok(())
+    }
+
+    #[test]
+    fn test_no_persistence_for_tests() -> Result<()> {
+        let db = new_test_db()?;
+
+        db.create_key_entry(Domain::APP, 100)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 1);
+        let db = new_test_db()?;
+
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 0);
+        Ok(())
+    }
+
+    #[test]
+    fn test_persistence_for_files() -> Result<()> {
+        let _file_guard_persistent = TempFile { filename: PERSISTENT_TEST_SQL };
+        let _file_guard_perboot = TempFile { filename: PERBOOT_TEST_SQL };
+        let db = new_test_db_with_persistent_file()?;
+
+        db.create_key_entry(Domain::APP, 100)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 1);
+        let db = new_test_db_with_persistent_file()?;
+
+        let entries_new = get_keyentry(&db)?;
+        assert_eq!(entries, entries_new);
+        Ok(())
+    }
+
+    #[test]
+    fn test_create_key_entry() -> Result<()> {
+        fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
+            (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
+        }
+
+        let db = new_test_db()?;
+
+        db.create_key_entry(Domain::APP, 100)?;
+        db.create_key_entry(Domain::SELINUX, 101)?;
+
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
+        assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
+
+        // Test that we must pass in a valid Domain.
+        check_result_is_error_containing_string(
+            db.create_key_entry(Domain::GRANT, 102),
+            "Domain Domain(1) must be either App or SELinux.",
+        );
+        check_result_is_error_containing_string(
+            db.create_key_entry(Domain::BLOB, 103),
+            "Domain Domain(3) must be either App or SELinux.",
+        );
+        check_result_is_error_containing_string(
+            db.create_key_entry(Domain::KEY_ID, 104),
+            "Domain Domain(4) must be either App or SELinux.",
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_rebind_alias() -> Result<()> {
+        fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
+            (ke.domain, ke.namespace, ke.alias.as_deref())
+        }
+
+        let mut db = new_test_db()?;
+        db.create_key_entry(Domain::APP, 42)?;
+        db.create_key_entry(Domain::APP, 42)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
+
+        // Test that the first call to rebind_alias sets the alias.
+        db.rebind_alias(entries[0].id, "foo", Domain::APP, 42)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
+
+        // Test that the second call to rebind_alias also empties the old one.
+        db.rebind_alias(entries[1].id, "foo", Domain::APP, 42)?;
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (None, None, None));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
+
+        // Test that we must pass in a valid Domain.
+        check_result_is_error_containing_string(
+            db.rebind_alias(0, "foo", Domain::GRANT, 42),
+            "Domain Domain(1) must be either App or SELinux.",
+        );
+        check_result_is_error_containing_string(
+            db.rebind_alias(0, "foo", Domain::BLOB, 42),
+            "Domain Domain(3) must be either App or SELinux.",
+        );
+        check_result_is_error_containing_string(
+            db.rebind_alias(0, "foo", Domain::KEY_ID, 42),
+            "Domain Domain(4) must be either App or SELinux.",
+        );
+
+        // Test that we correctly handle setting an alias for something that does not exist.
+        check_result_is_error_containing_string(
+            db.rebind_alias(0, "foo", Domain::SELINUX, 42),
+            "Expected to update a single entry but instead updated 0",
+        );
+        // Test that we correctly abort the transaction in this case.
+        let entries = get_keyentry(&db)?;
+        assert_eq!(entries.len(), 2);
+        assert_eq!(extractor(&entries[0]), (None, None, None));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_grant_ungrant() -> Result<()> {
+        const CALLER_UID: u32 = 15;
+        const GRANTEE_UID: u32 = 12;
+        const SELINUX_NAMESPACE: i64 = 7;
+
+        let mut db = new_test_db()?;
+        db.conn.execute(
+            "INSERT INTO persistent.keyentry (id, creation_date, domain, namespace, alias)
+                VALUES (1, '1980', 0, 15, 'key'), (2, '1980', 2, 7, 'yek');",
+            NO_PARAMS,
+        )?;
+        let app_key = KeyDescriptor {
+            domain: super::Domain::APP,
+            nspace: 0,
+            alias: Some("key".to_string()),
+            blob: None,
+        };
+        const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()];
+        const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()];
+
+        // Reset totally predictable random number generator in case we
+        // are not the first test running on this thread.
+        reset_random();
+        let next_random = 0i64;
+
+        let app_granted_key =
+            db.grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
+                assert_eq!(*a, PVEC1);
+                assert_eq!(
+                    *k,
+                    KeyDescriptor {
+                        domain: super::Domain::APP,
+                        // namespace must be set to the caller_uid.
+                        nspace: CALLER_UID as i64,
+                        alias: Some("key".to_string()),
+                        blob: None,
+                    }
+                );
+                Ok(())
+            })?;
+
+        assert_eq!(
+            app_granted_key,
+            KeyDescriptor {
+                domain: super::Domain::GRANT,
+                // The grantid is next_random due to the mock random number generator.
+                nspace: next_random,
+                alias: None,
+                blob: None,
+            }
+        );
+
+        let selinux_key = KeyDescriptor {
+            domain: super::Domain::SELINUX,
+            nspace: SELINUX_NAMESPACE,
+            alias: Some("yek".to_string()),
+            blob: None,
+        };
+
+        let selinux_granted_key =
+            db.grant(selinux_key.clone(), CALLER_UID, 12, PVEC1, |k, a| {
+                assert_eq!(*a, PVEC1);
+                assert_eq!(
+                    *k,
+                    KeyDescriptor {
+                        domain: super::Domain::SELINUX,
+                        // namespace must be the supplied SELinux
+                        // namespace.
+                        nspace: SELINUX_NAMESPACE,
+                        alias: Some("yek".to_string()),
+                        blob: None,
+                    }
+                );
+                Ok(())
+            })?;
+
+        assert_eq!(
+            selinux_granted_key,
+            KeyDescriptor {
+                domain: super::Domain::GRANT,
+                // The grantid is next_random + 1 due to the mock random number generator.
+                nspace: next_random + 1,
+                alias: None,
+                blob: None,
+            }
+        );
+
+        // This should update the existing grant with PVEC2.
+        let selinux_granted_key =
+            db.grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
+                assert_eq!(*a, PVEC2);
+                assert_eq!(
+                    *k,
+                    KeyDescriptor {
+                        domain: super::Domain::SELINUX,
+                        // namespace must be the supplied SELinux
+                        // namespace.
+                        nspace: SELINUX_NAMESPACE,
+                        alias: Some("yek".to_string()),
+                        blob: None,
+                    }
+                );
+                Ok(())
+            })?;
+
+        assert_eq!(
+            selinux_granted_key,
+            KeyDescriptor {
+                domain: super::Domain::GRANT,
+                // Same grant id as before. The entry was only updated.
+                nspace: next_random + 1,
+                alias: None,
+                blob: None,
+            }
+        );
+
+        {
+            // Limiting scope of stmt, because it borrows db.
+            let mut stmt = db
+                .conn
+                .prepare("SELECT id, grantee, keyentryid, access_vector FROM perboot.grant;")?;
+            let mut rows =
+                stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| {
+                    Ok((
+                        row.get(0)?,
+                        row.get(1)?,
+                        row.get(2)?,
+                        KeyPermSet::from(row.get::<_, i32>(3)?),
+                    ))
+                })?;
+
+            let r = rows.next().unwrap().unwrap();
+            assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
+            let r = rows.next().unwrap().unwrap();
+            assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
+            assert!(rows.next().is_none());
+        }
+
+        debug_dump_keyentry_table(&mut db)?;
+        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(()))?;
+
+        Ok(())
+    }
+
+    static TEST_KM_BLOB: &[u8] = b"my test blob";
+    static TEST_CERT_BLOB: &[u8] = b"my test cert";
+    static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
+
+    #[test]
+    fn test_insert_blob() -> Result<()> {
+        let mut db = new_test_db()?;
+        db.insert_blob(1, SubComponentType::KM_BLOB, TEST_KM_BLOB, SecurityLevel::SOFTWARE)?;
+        db.insert_blob(
+            1,
+            SubComponentType::CERT,
+            TEST_CERT_BLOB,
+            SecurityLevel::TRUSTED_ENVIRONMENT,
+        )?;
+        db.insert_blob(
+            1,
+            SubComponentType::CERT_CHAIN,
+            TEST_CERT_CHAIN_BLOB,
+            SecurityLevel::STRONGBOX,
+        )?;
+
+        let mut stmt = db.conn.prepare(
+            "SELECT subcomponent_type, keyentryid, blob, sec_level FROM persistent.blobentry
+                ORDER BY sec_level ASC;",
+        )?;
+        let mut rows = stmt
+            .query_map::<(SubComponentType, i64, Vec<u8>, i64), _, _>(NO_PARAMS, |row| {
+                Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
+            })?;
+        let r = rows.next().unwrap().unwrap();
+        assert_eq!(r, (SubComponentType::KM_BLOB, 1, TEST_KM_BLOB.to_vec(), 0));
+        let r = rows.next().unwrap().unwrap();
+        assert_eq!(r, (SubComponentType::CERT, 1, TEST_CERT_BLOB.to_vec(), 1));
+        let r = rows.next().unwrap().unwrap();
+        assert_eq!(r, (SubComponentType::CERT_CHAIN, 1, TEST_CERT_CHAIN_BLOB.to_vec(), 2));
+
+        Ok(())
+    }
+
+    static TEST_ALIAS: &str = "my super duper key";
+
+    #[test]
+    fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
+        let mut db = new_test_db()?;
+        let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
+            .context("test_insert_and_load_full_keyentry_domain_app")?;
+        let key_entry = db.load_key_entry(
+            KeyDescriptor {
+                domain: Domain::APP,
+                nspace: 0,
+                alias: Some(TEST_ALIAS.to_string()),
+                blob: None,
+            },
+            KeyEntryLoadBits::BOTH,
+            1,
+            |_k, _av| Ok(()),
+        )?;
+        assert_eq!(
+            key_entry,
+            KeyEntry {
+                id: key_id,
+                km_blob: Some(TEST_KM_BLOB.to_vec()),
+                cert: Some(TEST_CERT_BLOB.to_vec()),
+                cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
+                sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+                parameters: make_test_params()
+            }
+        );
+        Ok(())
+    }
+
+    #[test]
+    fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
+        let mut db = new_test_db()?;
+        let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
+            .context("test_insert_and_load_full_keyentry_domain_selinux")?;
+        let key_entry = db.load_key_entry(
+            KeyDescriptor {
+                domain: Domain::SELINUX,
+                nspace: 1,
+                alias: Some(TEST_ALIAS.to_string()),
+                blob: None,
+            },
+            KeyEntryLoadBits::BOTH,
+            1,
+            |_k, _av| Ok(()),
+        )?;
+        assert_eq!(
+            key_entry,
+            KeyEntry {
+                id: key_id,
+                km_blob: Some(TEST_KM_BLOB.to_vec()),
+                cert: Some(TEST_CERT_BLOB.to_vec()),
+                cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
+                sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+                parameters: make_test_params()
+            }
+        );
+        Ok(())
+    }
+
+    #[test]
+    fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
+        let mut db = new_test_db()?;
+        let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
+            .context("test_insert_and_load_full_keyentry_domain_key_id")?;
+        let key_entry = db.load_key_entry(
+            KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
+            KeyEntryLoadBits::BOTH,
+            1,
+            |_k, _av| Ok(()),
+        )?;
+        assert_eq!(
+            key_entry,
+            KeyEntry {
+                id: key_id,
+                km_blob: Some(TEST_KM_BLOB.to_vec()),
+                cert: Some(TEST_CERT_BLOB.to_vec()),
+                cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
+                sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+                parameters: make_test_params()
+            }
+        );
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
+        let mut db = new_test_db()?;
+        let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
+            .context("test_insert_and_load_full_keyentry_from_grant")?;
+
+        let granted_key = db.grant(
+            KeyDescriptor {
+                domain: Domain::APP,
+                nspace: 0,
+                alias: Some(TEST_ALIAS.to_string()),
+                blob: None,
+            },
+            1,
+            2,
+            key_perm_set![KeyPerm::use_()],
+            |_k, _av| Ok(()),
+        )?;
+
+        debug_dump_grant_table(&mut db)?;
+
+        let key_entry = db.load_key_entry(granted_key, KeyEntryLoadBits::BOTH, 2, |k, av| {
+            assert_eq!(Domain::GRANT, k.domain);
+            assert!(av.unwrap().includes(KeyPerm::use_()));
+            Ok(())
+        })?;
+
+        assert_eq!(
+            key_entry,
+            KeyEntry {
+                id: key_id,
+                km_blob: Some(TEST_KM_BLOB.to_vec()),
+                cert: Some(TEST_CERT_BLOB.to_vec()),
+                cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
+                sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+                parameters: make_test_params()
+            }
+        );
+        Ok(())
+    }
+
+    // Helpers
+
+    // Checks that the given result is an error containing the given string.
+    fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
+        let error_str = format!(
+            "{:#?}",
+            result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
+        );
+        assert!(
+            error_str.contains(target),
+            "The string \"{}\" should contain \"{}\"",
+            error_str,
+            target
+        );
+    }
+
+    #[derive(Debug, PartialEq)]
+    #[allow(dead_code)]
+    struct KeyEntryRow {
+        id: i64,
+        creation_date: String,
+        domain: Option<Domain>,
+        namespace: Option<i64>,
+        alias: Option<String>,
+    }
+
+    fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
+        db.conn
+            .prepare("SELECT * FROM persistent.keyentry;")?
+            .query_map(NO_PARAMS, |row| {
+                Ok(KeyEntryRow {
+                    id: row.get(0)?,
+                    creation_date: row.get(1)?,
+                    domain: match row.get(2)? {
+                        Some(i) => Some(Domain(i)),
+                        None => None,
+                    },
+                    namespace: row.get(3)?,
+                    alias: row.get(4)?,
+                })
+            })?
+            .map(|r| r.context("Could not read keyentry row."))
+            .collect::<Result<Vec<_>>>()
+    }
+
+    // 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.
+    fn make_test_params() -> Vec<KeyParameter> {
+        vec![
+            KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
+            KeyParameter::new(
+                KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::Algorithm(Algorithm::RSA),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
+            KeyParameter::new(
+                KeyParameterValue::BlockMode(BlockMode::ECB),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::BlockMode(BlockMode::GCM),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
+            KeyParameter::new(
+                KeyParameterValue::Digest(Digest::MD5),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::Digest(Digest::SHA_2_224),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::Digest(Digest::SHA_2_256),
+                SecurityLevel::STRONGBOX,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::PaddingMode(PaddingMode::NONE),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
+                SecurityLevel::STRONGBOX,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
+            KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
+            KeyParameter::new(
+                KeyParameterValue::EcCurve(EcCurve::P_224),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
+            KeyParameter::new(
+                KeyParameterValue::EcCurve(EcCurve::P_384),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::EcCurve(EcCurve::P_521),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::RSAPublicExponent(3),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::IncludeUniqueID,
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
+            KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
+            KeyParameter::new(
+                KeyParameterValue::ActiveDateTime(1234567890),
+                SecurityLevel::STRONGBOX,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::OriginationExpireDateTime(1234567890),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::UsageExpireDateTime(1234567890),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::MinSecondsBetweenOps(1234567890),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::MaxUsesPerBoot(1234567890),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
+            KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX),
+            KeyParameter::new(
+                KeyParameterValue::NoAuthRequired,
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
+            KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
+            KeyParameter::new(
+                KeyParameterValue::TrustedUserPresenceRequired,
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::TrustedConfirmationRequired,
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::UnlockedDeviceRequired,
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
+                SecurityLevel::SOFTWARE,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
+                SecurityLevel::SOFTWARE,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::CreationDateTime(12345677890),
+                SecurityLevel::SOFTWARE,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
+            KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
+            KeyParameter::new(
+                KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::SOFTWARE,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::VendorPatchLevel(3),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::BootPatchLevel(4),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::MacLength(256),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::ResetSinceIdRotation,
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+            KeyParameter::new(
+                KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
+                SecurityLevel::TRUSTED_ENVIRONMENT,
+            ),
+        ]
+    }
+
+    fn make_test_key_entry(
+        db: &mut KeystoreDB,
+        domain: Domain,
+        namespace: i64,
+        alias: &str,
+    ) -> Result<i64> {
+        let key_id = db.create_key_entry(domain, namespace)?;
+        db.insert_blob(
+            key_id,
+            SubComponentType::KM_BLOB,
+            TEST_KM_BLOB,
+            SecurityLevel::TRUSTED_ENVIRONMENT,
+        )?;
+        db.insert_blob(
+            key_id,
+            SubComponentType::CERT,
+            TEST_CERT_BLOB,
+            SecurityLevel::TRUSTED_ENVIRONMENT,
+        )?;
+        db.insert_blob(
+            key_id,
+            SubComponentType::CERT_CHAIN,
+            TEST_CERT_CHAIN_BLOB,
+            SecurityLevel::TRUSTED_ENVIRONMENT,
+        )?;
+        db.insert_keyparameter(key_id, &make_test_params())?;
+        db.rebind_alias(key_id, alias, domain, namespace)?;
+        Ok(key_id)
+    }
+
+    fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
+        let mut stmt = db.conn.prepare(
+            "SELECT id, creation_date, domain, namespace, alias FROM persistent.keyentry;",
+        )?;
+        let rows = stmt.query_map::<(i64, i64, i32, i64, String), _, _>(NO_PARAMS, |row| {
+            Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?))
+        })?;
+
+        println!("Key entry table rows:");
+        for r in rows {
+            let (id, cdate, domain, namespace, alias) = r.unwrap();
+            println!(
+                "    id: {} Creation date: {} Domain: {} Namespace: {} Alias: {}",
+                id, cdate, domain, namespace, alias
+            );
+        }
+        Ok(())
+    }
+
+    fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
+        let mut stmt =
+            db.conn.prepare("SELECT id, grantee, keyentryid, access_vector FROM perboot.grant;")?;
+        let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| {
+            Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
+        })?;
+
+        println!("Grant table rows:");
+        for r in rows {
+            let (id, gt, ki, av) = r.unwrap();
+            println!("    id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
+        }
+        Ok(())
+    }
+
+    // A class that deletes a file when it is dropped.
+    // TODO: If we ever add a crate that does this, we can use it instead.
+    struct TempFile {
+        filename: &'static str,
+    }
+
+    impl Drop for TempFile {
+        fn drop(&mut self) {
+            std::fs::remove_file(self.filename).expect("Cannot delete temporary file");
+        }
+    }
+
+    // Use a custom random number generator that repeats each number once.
+    // This allows us to test repeated elements.
+
+    thread_local! {
+        static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
+    }
+
+    fn reset_random() {
+        RANDOM_COUNTER.with(|counter| {
+            *counter.borrow_mut() = 0;
+        })
+    }
+
+    pub fn random() -> i64 {
+        RANDOM_COUNTER.with(|counter| {
+            let result = *counter.borrow() / 2;
+            *counter.borrow_mut() += 1;
+            result
+        })
+    }
+}
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index e58d3ce..63ebe62 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -25,39 +25,21 @@
 //! This crate provides the convenience method `map_or_log_err` to convert `anyhow::Error`
 //! into this wire type. In addition to handling the conversion of `Error`
 //! to the `Result` wire type it handles any other error by mapping it to
-//! `ResponseCode::SystemError` and logs any error condition.
+//! `ResponseCode::SYSTEM_ERROR` and logs any error condition.
 //!
 //! Keystore functions should use `anyhow::Result` to return error conditions, and
 //! context should be added every time an error is forwarded.
 
 use std::cmp::PartialEq;
-use std::convert::From;
 
-use keystore_aidl_generated as aidl;
-use keystore_aidl_generated::ResponseCode as AidlRc;
+pub use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode::ErrorCode;
+pub use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
 
-pub use aidl::ResponseCode;
+use keystore2_selinux as selinux;
 
-/// AidlResult wraps the `android.security.keystore2.Result` generated from AIDL
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct AidlResult(aidl::Result);
-
-impl AidlResult {
-    /// Creates an instance of AidlResult indicating no error has occurred.
-    pub fn ok() -> Self {
-        Self(aidl::Result { rc: AidlRc::Ok, km_error_code: 0 })
-    }
-
-    /// Creates an instance of AidlResult indicating the given ResponseCode.
-    pub fn rc(rc: AidlRc) -> Self {
-        Self(aidl::Result { rc, km_error_code: 0 })
-    }
-
-    /// Creates an instance of AidlResult indicating the given KM ErrorCode.
-    pub fn ec(ec: aidl::ErrorCode) -> Self {
-        Self(aidl::Result { rc: AidlRc::KeymintErrorCode, km_error_code: ec })
-    }
-}
+use android_system_keystore2::binder::{
+    ExceptionCode, Result as BinderResult, Status as BinderStatus,
+};
 
 /// This is the main Keystore error type. It wraps the Keystore `ResponseCode` generated
 /// from AIDL in the `Rc` variant and Keymint `ErrorCode` in the Km variant.
@@ -65,45 +47,68 @@
 pub enum Error {
     /// Wraps a Keystore `ResponseCode` as defined by the Keystore AIDL interface specification.
     #[error("Error::Rc({0:?})")]
-    Rc(AidlRc),
+    Rc(ResponseCode),
     /// Wraps a Keymint `ErrorCode` as defined by the Keymint AIDL interface specification.
     #[error("Error::Km({0:?})")]
-    Km(aidl::ErrorCode), // TODO Keymint ErrorCode is a generated AIDL type.
+    Km(ErrorCode),
+    /// Wraps a Binder exception code other than a service specific exception.
+    #[error("Binder exception code {0:?}, {1:?}")]
+    Binder(ExceptionCode, i32),
 }
 
 impl Error {
-    /// Short hand for `Error::Rc(ResponseCode::SystemError)`
+    /// Short hand for `Error::Rc(ResponseCode::SYSTEM_ERROR)`
     pub fn sys() -> Self {
-        Error::Rc(AidlRc::SystemError)
+        Error::Rc(ResponseCode::SYSTEM_ERROR)
     }
 
-    /// Short hand for `Error::Rc(ResponseCode::PermissionDenied`
+    /// Short hand for `Error::Rc(ResponseCode::PERMISSION_DENIED`
     pub fn perm() -> Self {
-        Error::Rc(AidlRc::PermissionDenied)
+        Error::Rc(ResponseCode::PERMISSION_DENIED)
     }
 }
 
-impl From<anyhow::Error> for AidlResult {
-    fn from(error: anyhow::Error) -> Self {
-        let root_cause = error.root_cause();
-        match root_cause.downcast_ref::<Error>() {
-            Some(Error::Rc(rcode)) => AidlResult::rc(*rcode),
-            Some(Error::Km(ec)) => AidlResult::ec(*ec),
-            None => AidlResult::rc(AidlRc::SystemError),
+/// Helper function to map the binder status we get from calls into KeyMint
+/// to a Keystore Error. We don't create an anyhow error here to make
+/// it easier to evaluate KeyMint errors, which we must do in some cases, e.g.,
+/// when diagnosing authentication requirements, update requirements, and running
+/// out of operation slots.
+pub fn map_km_error<T>(r: BinderResult<T>) -> Result<T, Error> {
+    r.map_err(|s| {
+        match s.exception_code() {
+            ExceptionCode::SERVICE_SPECIFIC => {
+                let se = s.service_specific_error();
+                if se < 0 {
+                    // Negative service specific errors are KM error codes.
+                    Error::Km(ErrorCode(s.service_specific_error()))
+                } else {
+                    // Non negative error codes cannot be KM error codes.
+                    // So we create an `Error::Binder` variant to preserve
+                    // the service specific error code for logging.
+                    // `map_or_log_err` will map this on a system error,
+                    // but not before logging the details to logcat.
+                    Error::Binder(ExceptionCode::SERVICE_SPECIFIC, se)
+                }
+            }
+            // We create `Error::Binder` to preserve the exception code
+            // for logging.
+            // `map_or_log_err` will map this on a system error.
+            e_code => Error::Binder(e_code, 0),
         }
-    }
+    })
 }
 
 /// This function should be used by Keystore service calls to translate error conditions
-/// into `android.security.keystore2.Result` which is imported here as `aidl::Result`
+/// into `android.system.keystore2.Result` which is imported here as `aidl::Result`
 /// and newtyped as AidlResult.
 /// All error conditions get logged by this function.
 /// All `Error::Rc(x)` variants get mapped onto `aidl::Result{x, 0}`.
 /// All `Error::Km(x)` variants get mapped onto
 /// `aidl::Result{aidl::ResponseCode::KeymintErrorCode, x}`.
+/// `selinux::Error::perm()` is mapped on `aidl::Result{aidl::ResponseCode::PERMISSION_DENIED, 0}`.
 ///
 /// All non `Error` error conditions get mapped onto
-/// `aidl::Result{aidl::ResponseCode::SystemError}`.
+/// `aidl::Result{aidl::ResponseCode::SYSTEM_ERROR}`.
 ///
 /// `handle_ok` will be called if `result` is `Ok(value)` where `value` will be passed
 /// as argument to `handle_ok`. `handle_ok` must generate an `AidlResult`, typically
@@ -117,38 +122,52 @@
 ///     if (good_but_auth_required) {
 ///         Ok(aidl::ResponseCode::OpAuthRequired)
 ///     } else {
-///         Err(anyhow!(Error::Rc(aidl::ResponseCode::KeyNotFound)))
+///         Err(anyhow!(Error::Rc(aidl::ResponseCode::KEY_NOT_FOUND)))
 ///     }
 /// }
 ///
 /// aidl_result_ = map_or_log_err(loadKey(), |r| { some_side_effect(); AidlResult::rc(r) });
 /// ```
-pub fn map_or_log_err<T>(
-    result: anyhow::Result<T>,
-    handle_ok: impl FnOnce(T) -> AidlResult,
-) -> AidlResult {
+pub fn map_or_log_err<T, U, F>(result: anyhow::Result<U>, handle_ok: F) -> BinderResult<T>
+where
+    F: FnOnce(U) -> BinderResult<T>,
+{
     result.map_or_else(
         |e| {
             log::error!("{:?}", e);
-            e.into()
+            let root_cause = e.root_cause();
+            let rc = match root_cause.downcast_ref::<Error>() {
+                Some(Error::Rc(rcode)) => rcode.0,
+                Some(Error::Km(ec)) => ec.0,
+                // If an Error::Binder reaches this stage we report a system error.
+                // The exception code and possible service specific error will be
+                // printed in the error log above.
+                Some(Error::Binder(_, _)) => ResponseCode::SYSTEM_ERROR.0,
+                None => match root_cause.downcast_ref::<selinux::Error>() {
+                    Some(selinux::Error::PermissionDenied) => ResponseCode::PERMISSION_DENIED.0,
+                    _ => ResponseCode::SYSTEM_ERROR.0,
+                },
+            };
+            Err(BinderStatus::new_service_specific_error(rc, None))
         },
         handle_ok,
     )
 }
 
 #[cfg(test)]
-mod tests {
+pub mod tests {
 
+    use super::*;
+    use android_system_keystore2::binder::{
+        ExceptionCode, Result as BinderResult, Status as BinderStatus,
+    };
     use anyhow::{anyhow, Context};
 
-    use super::aidl::ErrorCode;
-    use super::*;
-
-    fn nested_nested_rc(rc: AidlRc) -> anyhow::Result<()> {
+    fn nested_nested_rc(rc: ResponseCode) -> anyhow::Result<()> {
         Err(anyhow!(Error::Rc(rc))).context("nested nested rc")
     }
 
-    fn nested_rc(rc: AidlRc) -> anyhow::Result<()> {
+    fn nested_rc(rc: ResponseCode) -> anyhow::Result<()> {
         nested_nested_rc(rc).context("nested rc")
     }
 
@@ -160,14 +179,22 @@
         nested_nested_ec(ec).context("nested ec")
     }
 
-    fn nested_nested_ok(rc: AidlRc) -> anyhow::Result<AidlRc> {
+    fn nested_nested_ok(rc: ResponseCode) -> anyhow::Result<ResponseCode> {
         Ok(rc)
     }
 
-    fn nested_ok(rc: AidlRc) -> anyhow::Result<AidlRc> {
+    fn nested_ok(rc: ResponseCode) -> anyhow::Result<ResponseCode> {
         nested_nested_ok(rc).context("nested ok")
     }
 
+    fn nested_nested_selinux_perm() -> anyhow::Result<()> {
+        Err(anyhow!(selinux::Error::perm())).context("nested nexted selinux permission denied")
+    }
+
+    fn nested_selinux_perm() -> anyhow::Result<()> {
+        nested_nested_selinux_perm().context("nested selinux permission denied")
+    }
+
     #[derive(Debug, thiserror::Error)]
     enum TestError {
         #[error("TestError::Fail")]
@@ -182,6 +209,14 @@
         nested_nested_other_error().context("nested other error")
     }
 
+    fn binder_sse_error(sse: i32) -> BinderResult<()> {
+        Err(BinderStatus::new_service_specific_error(sse, None))
+    }
+
+    fn binder_exception(ex: ExceptionCode) -> BinderResult<()> {
+        Err(BinderStatus::new_exception(ex, None))
+    }
+
     #[test]
     fn keystore_error_test() -> anyhow::Result<(), String> {
         android_logger::init_once(
@@ -189,80 +224,104 @@
                 .with_tag("keystore_error_tests")
                 .with_min_level(log::Level::Debug),
         );
-        // All Error::Rc(x) get mapped on aidl::Result{x, 0}
+        // All Error::Rc(x) get mapped on a service specific error
+        // code of x.
+        for rc in ResponseCode::LOCKED.0..ResponseCode::BACKEND_BUSY.0 {
+            assert_eq!(
+                Result::<(), i32>::Err(rc),
+                map_or_log_err(nested_rc(ResponseCode(rc)), |_| Err(BinderStatus::ok()))
+                    .map_err(|s| s.service_specific_error())
+            );
+        }
+
+        // All Keystore Error::Km(x) get mapped on a service
+        // specific error of x.
+        for ec in ErrorCode::UNKNOWN_ERROR.0..ErrorCode::ROOT_OF_TRUST_ALREADY_SET.0 {
+            assert_eq!(
+                Result::<(), i32>::Err(ec),
+                map_or_log_err(nested_ec(ErrorCode(ec)), |_| Err(BinderStatus::ok()))
+                    .map_err(|s| s.service_specific_error())
+            );
+        }
+
+        // All Keymint errors x received through a Binder Result get mapped on
+        // a service specific error of x.
+        for ec in ErrorCode::UNKNOWN_ERROR.0..ErrorCode::ROOT_OF_TRUST_ALREADY_SET.0 {
+            assert_eq!(
+                Result::<(), i32>::Err(ec),
+                map_or_log_err(
+                    map_km_error(binder_sse_error(ec))
+                        .with_context(|| format!("Km error code: {}.", ec)),
+                    |_| Err(BinderStatus::ok())
+                )
+                .map_err(|s| s.service_specific_error())
+            );
+        }
+
+        // map_km_error creates an Error::Binder variant storing
+        // ExceptionCode::SERVICE_SPECIFIC and the given
+        // service specific error.
+        let sse = map_km_error(binder_sse_error(1));
+        assert_eq!(Err(Error::Binder(ExceptionCode::SERVICE_SPECIFIC, 1)), sse);
+        // map_or_log_err then maps it on a service specific error of ResponseCode::SYSTEM_ERROR.
         assert_eq!(
-            AidlResult::rc(AidlRc::Ok),
-            map_or_log_err(nested_rc(AidlRc::Ok), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::Locked),
-            map_or_log_err(nested_rc(AidlRc::Locked), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::Uninitialized),
-            map_or_log_err(nested_rc(AidlRc::Uninitialized), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::SystemError),
-            map_or_log_err(nested_rc(AidlRc::SystemError), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::PermissionDenied),
-            map_or_log_err(nested_rc(AidlRc::PermissionDenied), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::KeyNotFound),
-            map_or_log_err(nested_rc(AidlRc::KeyNotFound), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::ValueCorrupted),
-            map_or_log_err(nested_rc(AidlRc::ValueCorrupted), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::WrongPassword),
-            map_or_log_err(nested_rc(AidlRc::WrongPassword), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::OpAuthNeeded),
-            map_or_log_err(nested_rc(AidlRc::OpAuthNeeded), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::KeyPermanentlyInvalidated),
-            map_or_log_err(nested_rc(AidlRc::KeyPermanentlyInvalidated), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::NoSuchSecurityLevel),
-            map_or_log_err(nested_rc(AidlRc::NoSuchSecurityLevel), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::KeymintErrorCode),
-            map_or_log_err(nested_rc(AidlRc::KeymintErrorCode), |_| AidlResult::ec(0))
-        );
-        assert_eq!(
-            AidlResult::rc(AidlRc::BackendBusy),
-            map_or_log_err(nested_rc(AidlRc::BackendBusy), |_| AidlResult::ec(0))
+            Result::<(), ResponseCode>::Err(ResponseCode::SYSTEM_ERROR),
+            map_or_log_err(sse.context("Non negative service specific error."), |_| Err(
+                BinderStatus::ok()
+            ))
+            .map_err(|s| ResponseCode(s.service_specific_error()))
         );
 
-        // All KeystoreKerror::Km(x) get mapped on
-        // aidl::Result{AidlRc::KeymintErrorCode, x}
+        // map_km_error creates a Error::Binder variant storing the given exception code.
+        let binder_exception = map_km_error(binder_exception(ExceptionCode::TRANSACTION_FAILED));
+        assert_eq!(Err(Error::Binder(ExceptionCode::TRANSACTION_FAILED, 0)), binder_exception);
+        // map_or_log_err then maps it on a service specific error of ResponseCode::SYSTEM_ERROR.
         assert_eq!(
-            AidlResult::ec(-7),
-            map_or_log_err(nested_ec(-7), |_| AidlResult::rc(AidlRc::SystemError))
+            Result::<(), ResponseCode>::Err(ResponseCode::SYSTEM_ERROR),
+            map_or_log_err(binder_exception.context("Binder Exception."), |_| Err(
+                BinderStatus::ok()
+            ))
+            .map_err(|s| ResponseCode(s.service_specific_error()))
         );
 
-        // All other get mapped on System Error.
+        // selinux::Error::Perm() needs to be mapped to ResponseCode::PERMISSION_DENIED
         assert_eq!(
-            AidlResult::rc(AidlRc::SystemError),
-            map_or_log_err(nested_other_error(), |_| AidlResult::ec(0))
+            Result::<(), ResponseCode>::Err(ResponseCode::PERMISSION_DENIED),
+            map_or_log_err(nested_selinux_perm(), |_| Err(BinderStatus::ok()))
+                .map_err(|s| ResponseCode(s.service_specific_error()))
+        );
+
+        // All other errors get mapped on System Error.
+        assert_eq!(
+            Result::<(), ResponseCode>::Err(ResponseCode::SYSTEM_ERROR),
+            map_or_log_err(nested_other_error(), |_| Err(BinderStatus::ok()))
+                .map_err(|s| ResponseCode(s.service_specific_error()))
         );
 
         // Result::Ok variants get passed to the ok handler.
+        assert_eq!(Ok(ResponseCode::LOCKED), map_or_log_err(nested_ok(ResponseCode::LOCKED), Ok));
         assert_eq!(
-            AidlResult::rc(AidlRc::OpAuthNeeded),
-            map_or_log_err(nested_ok(AidlRc::OpAuthNeeded), AidlResult::rc)
+            Ok(ResponseCode::SYSTEM_ERROR),
+            map_or_log_err(nested_ok(ResponseCode::SYSTEM_ERROR), Ok)
         );
-        assert_eq!(AidlResult::ok(), map_or_log_err(nested_ok(AidlRc::Ok), AidlResult::rc));
 
         Ok(())
     }
+
+    //Helper function to test whether error cases are handled as expected.
+    pub fn check_result_contains_error_string<T>(
+        result: anyhow::Result<T>,
+        expected_error_string: &str,
+    ) {
+        let error_str = format!(
+            "{:#?}",
+            result.err().unwrap_or_else(|| panic!("Expected the error: {}", expected_error_string))
+        );
+        assert!(
+            error_str.contains(expected_error_string),
+            "The string \"{}\" should contain \"{}\"",
+            error_str,
+            expected_error_string
+        );
+    }
 } // mod tests
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
new file mode 100644
index 0000000..0654b29
--- /dev/null
+++ b/keystore2/src/globals.rs
@@ -0,0 +1,29 @@
+// 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 module holds global state of Keystore such as the thread local
+//! database connections and connections to services that Keystore needs
+//! to talk to.
+
+use crate::database::KeystoreDB;
+use std::cell::RefCell;
+
+thread_local! {
+    /// Database connections are not thread safe, but connecting to the
+    /// same database multiple times is safe as long as each connection is
+    /// used by only one thread. So we store one database connection per
+    /// thread in this thread local key.
+    pub static DB: RefCell<KeystoreDB> =
+            RefCell::new(KeystoreDB::new().expect("Failed to open database."));
+}
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
new file mode 100644
index 0000000..8825fc9
--- /dev/null
+++ b/keystore2/src/key_parameter.rs
@@ -0,0 +1,1363 @@
+// 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.
+
+//! KeyParameter is used to express different characteristics of a key requested by the user
+//! and enforced by the OEMs. This module implements the internal representation of KeyParameter
+//! and the methods to work with KeyParameter.
+
+use crate::error::Error as KeystoreError;
+use crate::error::ResponseCode;
+
+pub use android_hardware_keymint::aidl::android::hardware::keymint::{
+    Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
+    HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
+    KeyParameter::KeyParameter as KmKeyParameter, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
+    Tag::Tag,
+};
+pub use android_system_keystore2::aidl::android::system::keystore2::SecurityLevel::SecurityLevel;
+use anyhow::{Context, Result};
+use rusqlite::types::{FromSql, Null, ToSql, ToSqlOutput};
+use rusqlite::{Result as SqlResult, Row};
+
+/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
+#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
+pub struct KeyParameter {
+    key_parameter_value: KeyParameterValue,
+    security_level: SecurityLevel,
+}
+
+/// KeyParameterValue holds a value corresponding to one of the Tags defined in
+/// the AIDL spec at hardware/interfaces/keymint
+#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
+pub enum KeyParameterValue {
+    /// Associated with Tag:INVALID
+    Invalid,
+    /// Set of purposes for which the key may be used
+    KeyPurpose(KeyPurpose),
+    /// Cryptographic algorithm with which the key is used
+    Algorithm(Algorithm),
+    /// Size of the key , in bits
+    KeySize(i32),
+    /// Block cipher mode(s) with which the key may be used
+    BlockMode(BlockMode),
+    /// Digest algorithms that may be used with the key to perform signing and verification
+    Digest(Digest),
+    /// Padding modes that may be used with the key.  Relevant to RSA, AES and 3DES keys.
+    PaddingMode(PaddingMode),
+    /// Can the caller provide a nonce for nonce-requiring operations
+    CallerNonce,
+    /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
+    MinMacLength(i32),
+    /// The elliptic curve
+    EcCurve(EcCurve),
+    /// Value of the public exponent for an RSA key pair
+    RSAPublicExponent(i64),
+    /// An attestation certificate for the generated key should contain an application-scoped
+    /// and time-bounded device-unique ID
+    IncludeUniqueID,
+    //TODO: find out about this
+    // /// Necessary system environment conditions for the generated key to be used
+    // KeyBlobUsageRequirements(KeyBlobUsageRequirements),
+    /// Only the boot loader can use the key
+    BootLoaderOnly,
+    /// When deleted, the key is guaranteed to be permanently deleted and unusable
+    RollbackResistance,
+    /// The date and time at which the key becomes active
+    ActiveDateTime(i64),
+    /// The date and time at which the key expires for signing and encryption
+    OriginationExpireDateTime(i64),
+    /// The date and time at which the key expires for verification and decryption
+    UsageExpireDateTime(i64),
+    /// Minimum amount of time that elapses between allowed operations
+    MinSecondsBetweenOps(i32),
+    /// Maximum number of times that a key may be used between system reboots
+    MaxUsesPerBoot(i32),
+    /// ID of the Android user that is permitted to use the key
+    UserID(i32),
+    /// A key may only be used under a particular secure user authentication state
+    UserSecureID(i64),
+    /// No authentication is required to use this key
+    NoAuthRequired,
+    /// The types of user authenticators that may be used to authorize this key
+    HardwareAuthenticatorType(HardwareAuthenticatorType),
+    /// The time in seconds for which the key is authorized for use, after user authentication
+    AuthTimeout(i32),
+    /// The key may be used after authentication timeout if device is still on-body
+    AllowWhileOnBody,
+    /// The key must be unusable except when the user has provided proof of physical presence
+    TrustedUserPresenceRequired,
+    /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
+    /// unless the user provides confirmation of the data to be signed
+    TrustedConfirmationRequired,
+    /// The key may only be used when the device is unlocked
+    UnlockedDeviceRequired,
+    /// When provided to generateKey or importKey, this tag specifies data
+    /// that is necessary during all uses of the key
+    ApplicationID(Vec<u8>),
+    /// When provided to generateKey or importKey, this tag specifies data
+    /// that is necessary during all uses of the key
+    ApplicationData(Vec<u8>),
+    /// Specifies the date and time the key was created
+    CreationDateTime(i64),
+    /// Specifies where the key was created, if known
+    KeyOrigin(KeyOrigin),
+    /// The key used by verified boot to validate the operating system booted
+    RootOfTrust(Vec<u8>),
+    /// System OS version with which the key may be used
+    OSVersion(i32),
+    /// Specifies the system security patch level with which the key may be used
+    OSPatchLevel(i32),
+    /// Specifies a unique, time-based identifier
+    UniqueID(Vec<u8>),
+    /// Used to deliver a "challenge" value to the attestKey() method
+    AttestationChallenge(Vec<u8>),
+    /// The set of applications which may use a key, used only with attestKey()
+    AttestationApplicationID(Vec<u8>),
+    /// Provides the device's brand name, to attestKey()
+    AttestationIdBrand(Vec<u8>),
+    /// Provides the device's device name, to attestKey()
+    AttestationIdDevice(Vec<u8>),
+    /// Provides the device's product name, to attestKey()
+    AttestationIdProduct(Vec<u8>),
+    /// Provides the device's serial number, to attestKey()
+    AttestationIdSerial(Vec<u8>),
+    /// Provides the IMEIs for all radios on the device, to attestKey()
+    AttestationIdIMEI(Vec<u8>),
+    /// Provides the MEIDs for all radios on the device, to attestKey()
+    AttestationIdMEID(Vec<u8>),
+    /// Provides the device's manufacturer name, to attestKey()
+    AttestationIdManufacturer(Vec<u8>),
+    /// Provides the device's model name, to attestKey()
+    AttestationIdModel(Vec<u8>),
+    /// Specifies the vendor image security patch level with which the key may be used
+    VendorPatchLevel(i32),
+    /// Specifies the boot image (kernel) security patch level with which the key may be used
+    BootPatchLevel(i32),
+    /// Provides "associated data" for AES-GCM encryption or decryption
+    AssociatedData(Vec<u8>),
+    /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
+    /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
+    Nonce(Vec<u8>),
+    /// Provides the requested length of a MAC or GCM authentication tag, in bits
+    MacLength(i32),
+    /// Specifies whether the device has been factory reset since the
+    /// last unique ID rotation.  Used for key attestation
+    ResetSinceIdRotation,
+    /// Used to deliver a cryptographic token proving that the user
+    ///  confirmed a signing request
+    ConfirmationToken(Vec<u8>),
+}
+
+impl KeyParameter {
+    /// Create an instance of KeyParameter, given the value and the security level.
+    pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> Self {
+        KeyParameter { key_parameter_value, security_level }
+    }
+
+    /// Returns the tag given the KeyParameter instance.
+    pub fn get_tag(&self) -> Tag {
+        match self.key_parameter_value {
+            KeyParameterValue::Invalid => Tag::INVALID,
+            KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
+            KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
+            KeyParameterValue::KeySize(_) => Tag::KEY_SIZE,
+            KeyParameterValue::BlockMode(_) => Tag::BLOCK_MODE,
+            KeyParameterValue::Digest(_) => Tag::DIGEST,
+            KeyParameterValue::PaddingMode(_) => Tag::PADDING,
+            KeyParameterValue::CallerNonce => Tag::CALLER_NONCE,
+            KeyParameterValue::MinMacLength(_) => Tag::MIN_MAC_LENGTH,
+            KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
+            KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
+            KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
+            KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
+            KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
+            KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
+            KeyParameterValue::OriginationExpireDateTime(_) => Tag::ORIGINATION_EXPIRE_DATETIME,
+            KeyParameterValue::UsageExpireDateTime(_) => Tag::USAGE_EXPIRE_DATETIME,
+            KeyParameterValue::MinSecondsBetweenOps(_) => Tag::MIN_SECONDS_BETWEEN_OPS,
+            KeyParameterValue::MaxUsesPerBoot(_) => Tag::MAX_USES_PER_BOOT,
+            KeyParameterValue::UserID(_) => Tag::USER_ID,
+            KeyParameterValue::UserSecureID(_) => Tag::USER_SECURE_ID,
+            KeyParameterValue::NoAuthRequired => Tag::NO_AUTH_REQUIRED,
+            KeyParameterValue::HardwareAuthenticatorType(_) => Tag::USER_AUTH_TYPE,
+            KeyParameterValue::AuthTimeout(_) => Tag::AUTH_TIMEOUT,
+            KeyParameterValue::AllowWhileOnBody => Tag::ALLOW_WHILE_ON_BODY,
+            KeyParameterValue::TrustedUserPresenceRequired => Tag::TRUSTED_USER_PRESENCE_REQUIRED,
+            KeyParameterValue::TrustedConfirmationRequired => Tag::TRUSTED_CONFIRMATION_REQUIRED,
+            KeyParameterValue::UnlockedDeviceRequired => Tag::UNLOCKED_DEVICE_REQUIRED,
+            KeyParameterValue::ApplicationID(_) => Tag::APPLICATION_ID,
+            KeyParameterValue::ApplicationData(_) => Tag::APPLICATION_DATA,
+            KeyParameterValue::CreationDateTime(_) => Tag::CREATION_DATETIME,
+            KeyParameterValue::KeyOrigin(_) => Tag::ORIGIN,
+            KeyParameterValue::RootOfTrust(_) => Tag::ROOT_OF_TRUST,
+            KeyParameterValue::OSVersion(_) => Tag::OS_VERSION,
+            KeyParameterValue::OSPatchLevel(_) => Tag::OS_PATCHLEVEL,
+            KeyParameterValue::UniqueID(_) => Tag::UNIQUE_ID,
+            KeyParameterValue::AttestationChallenge(_) => Tag::ATTESTATION_CHALLENGE,
+            KeyParameterValue::AttestationApplicationID(_) => Tag::ATTESTATION_APPLICATION_ID,
+            KeyParameterValue::AttestationIdBrand(_) => Tag::ATTESTATION_ID_BRAND,
+            KeyParameterValue::AttestationIdDevice(_) => Tag::ATTESTATION_ID_DEVICE,
+            KeyParameterValue::AttestationIdProduct(_) => Tag::ATTESTATION_ID_PRODUCT,
+            KeyParameterValue::AttestationIdSerial(_) => Tag::ATTESTATION_ID_SERIAL,
+            KeyParameterValue::AttestationIdIMEI(_) => Tag::ATTESTATION_ID_IMEI,
+            KeyParameterValue::AttestationIdMEID(_) => Tag::ATTESTATION_ID_MEID,
+            KeyParameterValue::AttestationIdManufacturer(_) => Tag::ATTESTATION_ID_MANUFACTURER,
+            KeyParameterValue::AttestationIdModel(_) => Tag::ATTESTATION_ID_MODEL,
+            KeyParameterValue::VendorPatchLevel(_) => Tag::VENDOR_PATCHLEVEL,
+            KeyParameterValue::BootPatchLevel(_) => Tag::BOOT_PATCHLEVEL,
+            KeyParameterValue::AssociatedData(_) => Tag::ASSOCIATED_DATA,
+            KeyParameterValue::Nonce(_) => Tag::NONCE,
+            KeyParameterValue::MacLength(_) => Tag::MAC_LENGTH,
+            KeyParameterValue::ResetSinceIdRotation => Tag::RESET_SINCE_ID_ROTATION,
+            KeyParameterValue::ConfirmationToken(_) => Tag::CONFIRMATION_TOKEN,
+        }
+    }
+
+    /// Returns key parameter value.
+    pub fn key_parameter_value(&self) -> &KeyParameterValue {
+        &self.key_parameter_value
+    }
+
+    /// Returns the security level of a KeyParameter.
+    pub fn security_level(&self) -> &SecurityLevel {
+        &self.security_level
+    }
+}
+
+/// This struct is defined to postpone converting rusqlite column value to the
+/// appropriate key parameter value until we know the corresponding tag value.
+/// Wraps the column index and a rusqlite row.
+pub struct SqlField<'a>(usize, &'a Row<'a>);
+
+impl<'a> SqlField<'a> {
+    /// Creates a new SqlField with the given index and row.
+    pub fn new(index: usize, row: &'a Row<'a>) -> Self {
+        Self(index, row)
+    }
+    /// Returns the column value from the row, when we know the expected type.
+    pub fn get<T: FromSql>(&self) -> SqlResult<T> {
+        self.1.get(self.0)
+    }
+}
+
+impl ToSql for KeyParameterValue {
+    /// Converts KeyParameterValue to be stored in rusqlite database.
+    /// Note that following variants of KeyParameterValue should not be stored:
+    /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
+    /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
+    /// This filtering is enforced at a higher level (i.e. enforcement module) and here we support
+    /// conversion for all the variants, to keep error handling simple.
+    fn to_sql(&self) -> SqlResult<ToSqlOutput> {
+        match self {
+            KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
+            KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
+            KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
+            KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
+            KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
+            KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
+            KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
+            KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
+            KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
+            KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::RollbackResistance => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::ActiveDateTime(a) => Ok(ToSqlOutput::from(*a as i64)),
+            KeyParameterValue::OriginationExpireDateTime(o) => Ok(ToSqlOutput::from(*o as i64)),
+            KeyParameterValue::UsageExpireDateTime(u) => Ok(ToSqlOutput::from(*u as i64)),
+            KeyParameterValue::MinSecondsBetweenOps(m) => Ok(ToSqlOutput::from(*m)),
+            KeyParameterValue::MaxUsesPerBoot(m) => Ok(ToSqlOutput::from(*m)),
+            KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
+            KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
+            KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
+            KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
+            KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::TrustedConfirmationRequired => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::UnlockedDeviceRequired => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
+            KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
+            KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
+            KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
+            KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
+            KeyParameterValue::UniqueID(u) => Ok(ToSqlOutput::from(u.to_vec())),
+            KeyParameterValue::AttestationChallenge(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::AttestationApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::AttestationIdBrand(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::AttestationIdDevice(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::AttestationIdProduct(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::AttestationIdSerial(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::AttestationIdIMEI(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::AttestationIdMEID(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::AttestationIdManufacturer(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::AttestationIdModel(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::VendorPatchLevel(v) => Ok(ToSqlOutput::from(*v)),
+            KeyParameterValue::BootPatchLevel(b) => Ok(ToSqlOutput::from(*b)),
+            KeyParameterValue::AssociatedData(a) => Ok(ToSqlOutput::from(a.to_vec())),
+            KeyParameterValue::Nonce(n) => Ok(ToSqlOutput::from(n.to_vec())),
+            KeyParameterValue::MacLength(m) => Ok(ToSqlOutput::from(*m)),
+            KeyParameterValue::ResetSinceIdRotation => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::ConfirmationToken(c) => Ok(ToSqlOutput::from(c.to_vec())),
+        }
+    }
+}
+
+impl KeyParameter {
+    /// Construct a KeyParameter from the data from a rusqlite row.
+    /// Note that following variants of KeyParameterValue should not be stored:
+    /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
+    /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
+    /// This filtering is enforced at a higher level and here we support conversion for all the
+    /// variants.
+    pub fn new_from_sql(
+        tag_val: Tag,
+        data: &SqlField,
+        security_level_val: SecurityLevel,
+    ) -> Result<Self> {
+        let key_param_value = match tag_val {
+            Tag::INVALID => KeyParameterValue::Invalid,
+            Tag::PURPOSE => {
+                let key_purpose: i32 = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+                    .context("Failed to read sql data for tag: PURPOSE.")?;
+                KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
+            }
+            Tag::ALGORITHM => {
+                let algorithm: i32 = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+                    .context("Failed to read sql data for tag: ALGORITHM.")?;
+                KeyParameterValue::Algorithm(Algorithm(algorithm))
+            }
+            Tag::KEY_SIZE => {
+                let key_size: i32 =
+                    data.get().context("Failed to read sql data for tag: KEY_SIZE.")?;
+                KeyParameterValue::KeySize(key_size)
+            }
+            Tag::BLOCK_MODE => {
+                let block_mode: i32 = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+                    .context("Failed to read sql data for tag: BLOCK_MODE.")?;
+                KeyParameterValue::BlockMode(BlockMode(block_mode))
+            }
+            Tag::DIGEST => {
+                let digest: i32 = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+                    .context("Failed to read sql data for tag: DIGEST.")?;
+                KeyParameterValue::Digest(Digest(digest))
+            }
+            Tag::PADDING => {
+                let padding: i32 = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+                    .context("Failed to read sql data for tag: PADDING.")?;
+                KeyParameterValue::PaddingMode(PaddingMode(padding))
+            }
+            Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
+            Tag::MIN_MAC_LENGTH => {
+                let min_mac_length: i32 =
+                    data.get().context("Failed to read sql data for tag: MIN_MAC_LENGTH.")?;
+                KeyParameterValue::MinMacLength(min_mac_length)
+            }
+            Tag::EC_CURVE => {
+                let ec_curve: i32 = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+                    .context("Failed to read sql data for tag: EC_CURVE.")?;
+                KeyParameterValue::EcCurve(EcCurve(ec_curve))
+            }
+            Tag::RSA_PUBLIC_EXPONENT => {
+                let rsa_pub_exponent: i64 =
+                    data.get().context("Failed to read sql data for tag: RSA_PUBLIC_EXPONENT.")?;
+
+                KeyParameterValue::RSAPublicExponent(rsa_pub_exponent)
+            }
+            Tag::INCLUDE_UNIQUE_ID => KeyParameterValue::IncludeUniqueID,
+            Tag::BOOTLOADER_ONLY => KeyParameterValue::BootLoaderOnly,
+            Tag::ROLLBACK_RESISTANCE => KeyParameterValue::RollbackResistance,
+            Tag::ACTIVE_DATETIME => {
+                let active_datetime: i64 =
+                    data.get().context("Failed to read sql data for tag: ACTIVE_DATETIME.")?;
+                KeyParameterValue::ActiveDateTime(active_datetime)
+            }
+            Tag::ORIGINATION_EXPIRE_DATETIME => {
+                let origination_expire_datetime: i64 = data
+                    .get()
+                    .context("Failed to read sql data for tag: ORIGINATION_EXPIRE_DATETIME.")?;
+                KeyParameterValue::OriginationExpireDateTime(origination_expire_datetime)
+            }
+            Tag::USAGE_EXPIRE_DATETIME => {
+                let usage_expire_datetime: i64 = data
+                    .get()
+                    .context("Failed to read sql data for tag: USAGE_EXPIRE_DATETIME.")?;
+                KeyParameterValue::UsageExpireDateTime(usage_expire_datetime)
+            }
+            Tag::MIN_SECONDS_BETWEEN_OPS => {
+                let min_secs_between_ops: i32 = data
+                    .get()
+                    .context("Failed to read sql data for tag: MIN_SECONDS_BETWEEN_OPS.")?;
+                KeyParameterValue::MinSecondsBetweenOps(min_secs_between_ops)
+            }
+            Tag::MAX_USES_PER_BOOT => {
+                let max_uses_per_boot: i32 =
+                    data.get().context("Failed to read sql data for tag: MAX_USES_PER_BOOT.")?;
+                KeyParameterValue::MaxUsesPerBoot(max_uses_per_boot)
+            }
+            Tag::USER_ID => {
+                let user_id: i32 =
+                    data.get().context("Failed to read sql data for tag: USER_ID.")?;
+                KeyParameterValue::UserID(user_id)
+            }
+            Tag::USER_SECURE_ID => {
+                let user_secure_id: i64 =
+                    data.get().context("Failed to read sql data for tag: USER_SECURE_ID.")?;
+                KeyParameterValue::UserSecureID(user_secure_id)
+            }
+            Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
+            Tag::USER_AUTH_TYPE => {
+                let user_auth_type: i32 = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+                    .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
+                KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
+                    user_auth_type,
+                ))
+            }
+            Tag::AUTH_TIMEOUT => {
+                let auth_timeout: i32 =
+                    data.get().context("Failed to read sql data for tag: AUTH_TIMEOUT.")?;
+                KeyParameterValue::AuthTimeout(auth_timeout)
+            }
+            Tag::ALLOW_WHILE_ON_BODY => KeyParameterValue::AllowWhileOnBody,
+            Tag::TRUSTED_USER_PRESENCE_REQUIRED => KeyParameterValue::TrustedUserPresenceRequired,
+            Tag::TRUSTED_CONFIRMATION_REQUIRED => KeyParameterValue::TrustedConfirmationRequired,
+            Tag::UNLOCKED_DEVICE_REQUIRED => KeyParameterValue::UnlockedDeviceRequired,
+            Tag::APPLICATION_ID => {
+                let app_id: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: APPLICATION_ID.")?;
+                KeyParameterValue::ApplicationID(app_id)
+            }
+            Tag::APPLICATION_DATA => {
+                let app_data: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: APPLICATION_DATA.")?;
+                KeyParameterValue::ApplicationData(app_data)
+            }
+            Tag::CREATION_DATETIME => {
+                let creation_datetime: i64 =
+                    data.get().context("Failed to read sql data for tag: CREATION_DATETIME.")?;
+                KeyParameterValue::CreationDateTime(creation_datetime)
+            }
+            Tag::ORIGIN => {
+                let origin: i32 = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+                    .context("Failed to read sql data for tag: ORIGIN.")?;
+                KeyParameterValue::KeyOrigin(KeyOrigin(origin))
+            }
+            Tag::ROOT_OF_TRUST => {
+                let root_of_trust: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: ROOT_OF_TRUST.")?;
+                KeyParameterValue::RootOfTrust(root_of_trust)
+            }
+            Tag::OS_VERSION => {
+                let os_version: i32 =
+                    data.get().context("Failed to read sql data for tag: OS_VERSION.")?;
+                KeyParameterValue::OSVersion(os_version)
+            }
+            Tag::OS_PATCHLEVEL => {
+                let os_patch_level: i32 =
+                    data.get().context("Failed to read sql data for tag: OS_PATCHLEVEL.")?;
+                KeyParameterValue::OSPatchLevel(os_patch_level)
+            }
+            Tag::UNIQUE_ID => {
+                let unique_id: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: UNIQUE_ID.")?;
+                KeyParameterValue::UniqueID(unique_id)
+            }
+            Tag::ATTESTATION_CHALLENGE => {
+                let attestation_challenge: Vec<u8> = data
+                    .get()
+                    .context("Failed to read sql data for tag: ATTESTATION_CHALLENGE.")?;
+                KeyParameterValue::AttestationChallenge(attestation_challenge)
+            }
+            Tag::ATTESTATION_APPLICATION_ID => {
+                let attestation_app_id: Vec<u8> = data
+                    .get()
+                    .context("Failed to read sql data for tag: ATTESTATION_APPLICATION_ID.")?;
+                KeyParameterValue::AttestationApplicationID(attestation_app_id)
+            }
+            Tag::ATTESTATION_ID_BRAND => {
+                let attestation_id_brand: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: ATTESTATION_ID_BRAND.")?;
+                KeyParameterValue::AttestationIdBrand(attestation_id_brand)
+            }
+            Tag::ATTESTATION_ID_DEVICE => {
+                let attestation_id_device: Vec<u8> = data
+                    .get()
+                    .context("Failed to read sql data for tag: ATTESTATION_ID_DEVICE.")?;
+                KeyParameterValue::AttestationIdDevice(attestation_id_device)
+            }
+            Tag::ATTESTATION_ID_PRODUCT => {
+                let attestation_id_product: Vec<u8> = data
+                    .get()
+                    .context("Failed to read sql data for tag: ATTESTATION_ID_PRODUCT.")?;
+                KeyParameterValue::AttestationIdProduct(attestation_id_product)
+            }
+            Tag::ATTESTATION_ID_SERIAL => {
+                let attestation_id_serial: Vec<u8> = data
+                    .get()
+                    .context("Failed to read sql data for tag: ATTESTATION_ID_SERIAL.")?;
+                KeyParameterValue::AttestationIdSerial(attestation_id_serial)
+            }
+            Tag::ATTESTATION_ID_IMEI => {
+                let attestation_id_imei: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: ATTESTATION_ID_IMEI.")?;
+                KeyParameterValue::AttestationIdIMEI(attestation_id_imei)
+            }
+            Tag::ATTESTATION_ID_MEID => {
+                let attestation_id_meid: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MEID.")?;
+                KeyParameterValue::AttestationIdMEID(attestation_id_meid)
+            }
+            Tag::ATTESTATION_ID_MANUFACTURER => {
+                let attestation_id_manufacturer: Vec<u8> = data
+                    .get()
+                    .context("Failed to read sql data for tag: ATTESTATION_ID_MANUFACTURER.")?;
+                KeyParameterValue::AttestationIdManufacturer(attestation_id_manufacturer)
+            }
+            Tag::ATTESTATION_ID_MODEL => {
+                let attestation_id_model: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MODEL.")?;
+                KeyParameterValue::AttestationIdModel(attestation_id_model)
+            }
+            Tag::VENDOR_PATCHLEVEL => {
+                let vendor_patch_level: i32 =
+                    data.get().context("Failed to read sql data for tag: VENDOR_PATCHLEVEL.")?;
+                KeyParameterValue::VendorPatchLevel(vendor_patch_level)
+            }
+            Tag::BOOT_PATCHLEVEL => {
+                let boot_patch_level: i32 =
+                    data.get().context("Failed to read sql data for tag: BOOT_PATCHLEVEL.")?;
+                KeyParameterValue::BootPatchLevel(boot_patch_level)
+            }
+            Tag::ASSOCIATED_DATA => {
+                let associated_data: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: ASSOCIATED_DATA.")?;
+                KeyParameterValue::AssociatedData(associated_data)
+            }
+            Tag::NONCE => {
+                let nonce: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: NONCE.")?;
+                KeyParameterValue::Nonce(nonce)
+            }
+            Tag::MAC_LENGTH => {
+                let mac_length: i32 =
+                    data.get().context("Failed to read sql data for tag: MAC_LENGTH.")?;
+                KeyParameterValue::MacLength(mac_length)
+            }
+            Tag::RESET_SINCE_ID_ROTATION => KeyParameterValue::ResetSinceIdRotation,
+            Tag::CONFIRMATION_TOKEN => {
+                let confirmation_token: Vec<u8> =
+                    data.get().context("Failed to read sql data for tag: CONFIRMATION_TOKEN.")?;
+                KeyParameterValue::ConfirmationToken(confirmation_token)
+            }
+            _ => {
+                return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+                    .context("Failed to decode Tag enum from value.")?
+            }
+        };
+        Ok(KeyParameter::new(key_param_value, security_level_val))
+    }
+}
+
+/// Macro rules for converting key parameter to/from wire type.
+/// This macro takes between three and four different pieces of information about each
+/// of the KeyParameterValue variants:
+/// 1. The KeyParameterValue variant name,
+/// 2. the tag name corresponding to the variant,
+/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
+///    stored when converted, and
+/// 4. an optional enum type name when the nested value is of enum type.
+/// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
+/// the two conversion methods: convert_to_wire() and convert_from_wire().
+/// ## Example
+/// ```
+/// implement_key_parameter_conversion_to_from_wire! {
+///         Invalid, INVALID, na;
+///         KeyPurpose, PURPOSE, integer, KeyPurpose;
+///         CallerNonce, CALLER_NONCE, boolValue;
+///         UserSecureID, USER_SECURE_ID, longInteger;
+///         ApplicationID, APPLICATION_ID, blob;
+///         ActiveDateTime, ACTIVE_DATETIME, dateTime;
+/// }
+/// ```
+/// expands to:
+/// ```
+/// pub fn convert_to_wire(self) -> KmKeyParameter {
+///         match self {
+///                 KeyParameterValue::Invalid => KmKeyParameter {
+///                         tag: Tag::INVALID,
+///                         ..Default::default()
+///                 },
+///                 KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
+///                         tag: Tag::PURPOSE,
+///                         integer: v.0,
+///                         ..Default::default()
+///                 },
+///                 KeyParameterValue::CallerNonce => KmKeyParameter {
+///                         tag: Tag::CALLER_NONCE,
+///                         boolValue: true,
+///                         ..Default::default()
+///                 },
+///                 KeyParameterValue::UserSecureID(v) => KmKeyParameter {
+///                         tag: Tag::USER_SECURE_ID,
+///                         longInteger: v,
+///                         ..Default::default()
+///                 },
+///                 KeyParameterValue::ApplicationID(v) => KmKeyParameter {
+///                         tag: Tag::APPLICATION_ID,
+///                         blob: v,
+///                         ..Default::default()
+///                 },
+///                 KeyParameterValue::ActiveDateTime(v) => KmKeyParameter {
+///                         tag: Tag::ACTIVE_DATETIME,
+///                         dateTime: v,
+///                         ..Default::default()
+///                 },
+///         }
+/// }
+/// ```
+/// and
+/// ```
+/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
+///         match aidl_kp {
+///                 KmKeyParameter {
+///                         tag: Tag::INVALID,
+///                         ..
+///                 } => KeyParameterValue::Invalid,
+///                 KmKeyParameter {
+///                         tag: Tag::PURPOSE,
+///                         integer: v,
+///                         ..
+///                 } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
+///                 KmKeyParameter {
+///                         tag: Tag::CALLER_NONCE,
+///                         boolValue: true,
+///                         ..
+///                 } => KeyParameterValue::CallerNonce,
+///                 KmKeyParameter {
+///                          tag: Tag::USER_SECURE_ID,
+///                          longInteger: v,
+///                          ..
+///                 } => KeyParameterValue::UserSecureID(v),
+///                 KmKeyParameter {
+///                          tag: Tag::APPLICATION_ID,
+///                          blob: v,
+///                          ..
+///                 } => KeyParameterValue::ApplicationID(v),
+///                 KmKeyParameter {
+///                          tag: Tag::ACTIVE_DATETIME,
+///                          dateTime: v,
+///                          ..
+///                 } => KeyParameterValue::ActiveDateTime(v),
+///                 _ => KeyParameterValue::Invalid,
+///         }
+/// }
+///
+macro_rules! implement_key_parameter_conversion_to_from_wire {
+    // There are three groups of rules in this macro.
+    // 1. The first group contains the rule which acts as the public interface. It takes the input
+    //    given to this macro and prepares it to be given as input to the two groups of rules
+    //    mentioned below.
+    // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
+    // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
+    //
+    // Input to this macro is first handled by the first macro rule (belonging to the first
+    // group above), which pre-processes the input such that rules in the other two groups
+    // generate the code for the two methods, when called recursively.
+    // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
+    // four macro rules in the second two groups. These four rules intend to do the following
+    // tasks respectively:
+    // i) generates match arms related to Invalid KeyParameterValue variant.
+    // ii) generates match arms related to boolValue field in KmKeyParameter struct.
+    // iii) generates match arms related to all the other fields in KmKeyParameter struct.
+    // iv) generates the method definition including the match arms generated from the above
+    // three recursive macro rules.
+
+    // This rule is applied on the input given to the macro invocations from outside the macro.
+    ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
+        // pre-processes input to target the rules that generate convert_to_wire() method.
+        implement_key_parameter_conversion_to_from_wire! {@to
+            [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
+        }
+        // pre-processes input to target the rules that generate convert_from_wire() method.
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
+        }
+    };
+
+    // Following four rules (belonging to the aforementioned second group) generate
+    // convert_to_wire() conversion method.
+    // -----------------------------------------------------------------------
+    // This rule handles Invalid variant.
+    // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
+    // KeyParameterValue::Invalid => KmKeyParameter {
+    //                                   tag: Tag::INVALID,
+    //                                   ..Default::default()
+    //                               },
+    (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@to
+            [$($out)*
+                KeyParameterValue::Invalid => KmKeyParameter {
+                    tag: Tag::INVALID,
+                    ..Default::default()
+                },
+            ], $($in)*
+        }
+    };
+    // This rule handles all variants that correspond to bool values.
+    // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
+    // a match arm like:
+    // KeyParameterValue::CallerNonce => KmKeyParameter {
+    //                                       tag: Tag::CALLER_NONCE,
+    //                                       boolValue: true,
+    //                                       ..Default::default()
+    //                                   },
+    (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@to
+            [$($out)*
+                KeyParameterValue::$variant => KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    boolValue: true,
+                    ..Default::default()
+                },
+            ], $($in)*
+        }
+    };
+    // This rule handles all enum variants.
+    // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
+    // like: KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
+    //                                               tag: Tag::PURPOSE,
+    //                                               integer: v.0,
+    //                                               ..Default::default(),
+    //                                           },
+    (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
+       implement_key_parameter_conversion_to_from_wire! {@to
+           [$($out)*
+               KeyParameterValue::$variant(v) => KmKeyParameter {
+                   tag: Tag::$tag_val,
+                   $field: v.0,
+                   ..Default::default()
+               },
+           ], $($in)*
+       }
+    };
+    // This rule handles all variants that are neither invalid nor bool values nor enums
+    // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
+    // KmKeyParameter).
+    // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
+    // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
+    //                                                      tag: Tag::CONFIRMATION_TOKEN,
+    //                                                      blob: v,
+    //                                                      ..Default::default(),
+    //                                                  },
+    (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@to
+            [$($out)*
+                KeyParameterValue::$variant(v) => KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    $field: v,
+                    ..Default::default()
+                },
+            ], $($in)*
+        }
+    };
+    // After all the match arms are generated by the above three rules, this rule combines them
+    // into the convert_to_wire() method.
+    (@to [$($out:tt)*], ) => {
+        /// Conversion of key parameter to wire type
+        pub fn convert_to_wire(self) -> KmKeyParameter {
+            match self {
+                $($out)*
+            }
+        }
+    };
+
+    // Following four rules (belonging to the aforementioned third group) generate
+    // convert_from_wire() conversion method.
+    // ------------------------------------------------------------------------
+    // This rule handles Invalid variant.
+    // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
+    // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
+    (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [$($out)*
+                KmKeyParameter {
+                    tag: Tag::INVALID,
+                    ..
+                } => KeyParameterValue::Invalid,
+            ], $($in)*
+        }
+    };
+    // This rule handles all variants that correspond to bool values.
+    // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
+    // KmKeyParameter {
+    //      tag: Tag::CALLER_NONCE,
+    //      boolValue: true,
+    //      ..
+    // } => KeyParameterValue::CallerNonce,
+    (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [$($out)*
+                KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    boolValue: true,
+                    ..
+                } => KeyParameterValue::$variant,
+            ], $($in)*
+        }
+    };
+    // This rule handles all enum variants.
+    // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
+    // like:
+    // KmKeyParameter {
+    //         tag: Tag::PURPOSE,
+    //         integer: v,
+    //         ..,
+    // } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
+    (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [$($out)*
+                KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    $field: v,
+                    ..
+                } => KeyParameterValue::$variant($enum_type(v)),
+            ], $($in)*
+        }
+    };
+    // This rule handles all variants that are neither invalid nor bool values nor enums
+    // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
+    // KmKeyParameter).
+    // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
+    // like:
+    // KmKeyParameter {
+    //         tag: Tag::CONFIRMATION_TOKEN,
+    //         blob: v,
+    //         ..,
+    // } => KeyParameterValue::ConfirmationToken(v),
+    (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [$($out)*
+                KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    $field: v,
+                    ..
+                } => KeyParameterValue::$variant(v),
+            ], $($in)*
+        }
+    };
+    // After all the match arms are generated by the above three rules, this rule combines them
+    // into the convert_from_wire() method.
+    (@from [$($out:tt)*], ) => {
+        /// Conversion of key parameter from wire type
+        pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
+            match aidl_kp {
+                $($out)*
+                _ => KeyParameterValue::Invalid,
+            }
+        }
+    };
+}
+
+impl KeyParameterValue {
+    // Invoke the macro that generates the code for key parameter conversion to/from wire type
+    // with all possible variants of KeyParameterValue. Each line corresponding to a variant
+    // contains: variant identifier, tag value, and the related field name (i.e.
+    // boolValue/integer/longInteger/dateTime/blob) in the KmKeyParameter.
+    implement_key_parameter_conversion_to_from_wire! {
+        Invalid, INVALID, na;
+        KeyPurpose, PURPOSE, integer, KeyPurpose;
+        Algorithm, ALGORITHM, integer, Algorithm;
+        KeySize, KEY_SIZE, integer;
+        BlockMode, BLOCK_MODE, integer, BlockMode;
+        Digest, DIGEST, integer, Digest;
+        PaddingMode, PADDING, integer, PaddingMode;
+        CallerNonce, CALLER_NONCE, boolValue;
+        MinMacLength, MIN_MAC_LENGTH, integer;
+        EcCurve, EC_CURVE, integer, EcCurve;
+        RSAPublicExponent, RSA_PUBLIC_EXPONENT, longInteger;
+        IncludeUniqueID, INCLUDE_UNIQUE_ID, boolValue;
+        BootLoaderOnly, BOOTLOADER_ONLY, boolValue;
+        RollbackResistance, ROLLBACK_RESISTANCE, boolValue;
+        ActiveDateTime, ACTIVE_DATETIME, dateTime;
+        OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, dateTime;
+        UsageExpireDateTime, USAGE_EXPIRE_DATETIME, dateTime;
+        MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, integer;
+        MaxUsesPerBoot, MAX_USES_PER_BOOT, integer;
+        UserID, USER_ID, integer;
+        UserSecureID, USER_SECURE_ID, longInteger;
+        NoAuthRequired, NO_AUTH_REQUIRED, boolValue;
+        HardwareAuthenticatorType, USER_AUTH_TYPE, integer, HardwareAuthenticatorType;
+        AuthTimeout, AUTH_TIMEOUT, integer;
+        AllowWhileOnBody, ALLOW_WHILE_ON_BODY, boolValue;
+        TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, boolValue;
+        TrustedConfirmationRequired, TRUSTED_CONFIRMATION_REQUIRED, boolValue;
+        UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, boolValue;
+        ApplicationID, APPLICATION_ID, blob;
+        ApplicationData, APPLICATION_DATA, blob;
+        CreationDateTime, CREATION_DATETIME, dateTime;
+        KeyOrigin, ORIGIN, integer, KeyOrigin;
+        RootOfTrust, ROOT_OF_TRUST, blob;
+        OSVersion, OS_VERSION, integer;
+        OSPatchLevel, OS_PATCHLEVEL, integer;
+        UniqueID, UNIQUE_ID, blob;
+        AttestationChallenge, ATTESTATION_CHALLENGE, blob;
+        AttestationApplicationID, ATTESTATION_APPLICATION_ID, blob;
+        AttestationIdBrand, ATTESTATION_ID_BRAND, blob;
+        AttestationIdDevice, ATTESTATION_ID_DEVICE, blob;
+        AttestationIdProduct, ATTESTATION_ID_PRODUCT, blob;
+        AttestationIdSerial, ATTESTATION_ID_SERIAL, blob;
+        AttestationIdIMEI, ATTESTATION_ID_IMEI, blob;
+        AttestationIdMEID, ATTESTATION_ID_MEID, blob;
+        AttestationIdManufacturer, ATTESTATION_ID_MANUFACTURER, blob;
+        AttestationIdModel, ATTESTATION_ID_MODEL, blob;
+        VendorPatchLevel, VENDOR_PATCHLEVEL, integer;
+        BootPatchLevel, BOOT_PATCHLEVEL, integer;
+        AssociatedData, ASSOCIATED_DATA, blob;
+        Nonce, NONCE, blob;
+        MacLength, MAC_LENGTH, integer;
+        ResetSinceIdRotation, RESET_SINCE_ID_ROTATION, boolValue;
+        ConfirmationToken, CONFIRMATION_TOKEN, blob;
+    }
+}
+
+#[cfg(test)]
+mod basic_tests {
+    use crate::key_parameter::*;
+
+    // Test basic functionality of KeyParameter.
+    #[test]
+    fn test_key_parameter() {
+        let key_parameter = KeyParameter::new(
+            KeyParameterValue::Algorithm(Algorithm::RSA),
+            SecurityLevel::STRONGBOX,
+        );
+
+        assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
+
+        assert_eq!(
+            *key_parameter.key_parameter_value(),
+            KeyParameterValue::Algorithm(Algorithm::RSA)
+        );
+
+        assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
+    }
+}
+
+/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
+/// data types and then tests 'to_sql' method for KeyParameters of those
+/// different data types. The five different data types for KeyParameter values are:
+/// i) enums of u32
+/// ii) u32
+/// iii) u64
+/// iv) Vec<u8>
+/// v) bool
+#[cfg(test)]
+mod storage_tests {
+    use crate::error::*;
+    use crate::key_parameter::*;
+    use anyhow::Result;
+    use rusqlite::types::ToSql;
+    use rusqlite::{params, Connection, NO_PARAMS};
+
+    /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
+    /// from a database table row.
+    #[test]
+    fn test_new_from_sql_enum_i32() -> Result<()> {
+        let db = init_db()?;
+        insert_into_keyparameter(
+            &db,
+            1,
+            Tag::ALGORITHM.0,
+            &Algorithm::RSA.0,
+            SecurityLevel::STRONGBOX.0,
+        )?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(Tag::ALGORITHM, key_param.get_tag());
+        assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
+        assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
+        Ok(())
+    }
+
+    /// Test initializing a KeyParameter (with key parameter value which is of i32)
+    /// from a database table row.
+    #[test]
+    fn test_new_from_sql_i32() -> Result<()> {
+        let db = init_db()?;
+        insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
+        assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
+        Ok(())
+    }
+
+    /// Test initializing a KeyParameter (with key parameter value which is of i64)
+    /// from a database table row.
+    #[test]
+    fn test_new_from_sql_i64() -> Result<()> {
+        let db = init_db()?;
+        // max value for i64, just to test corner cases
+        insert_into_keyparameter(
+            &db,
+            1,
+            Tag::RSA_PUBLIC_EXPONENT.0,
+            &(i64::MAX),
+            SecurityLevel::STRONGBOX.0,
+        )?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
+        assert_eq!(
+            *key_param.key_parameter_value(),
+            KeyParameterValue::RSAPublicExponent(i64::MAX)
+        );
+        Ok(())
+    }
+
+    /// Test initializing a KeyParameter (with key parameter value which is of bool)
+    /// from a database table row.
+    #[test]
+    fn test_new_from_sql_bool() -> Result<()> {
+        let db = init_db()?;
+        insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
+        assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
+        Ok(())
+    }
+
+    /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
+    /// from a database table row.
+    #[test]
+    fn test_new_from_sql_vec_u8() -> Result<()> {
+        let db = init_db()?;
+        let app_id = String::from("MyAppID");
+        let app_id_bytes = app_id.into_bytes();
+        insert_into_keyparameter(
+            &db,
+            1,
+            Tag::APPLICATION_ID.0,
+            &app_id_bytes,
+            SecurityLevel::STRONGBOX.0,
+        )?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
+        assert_eq!(
+            *key_param.key_parameter_value(),
+            KeyParameterValue::ApplicationID(app_id_bytes)
+        );
+        Ok(())
+    }
+
+    /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
+    /// in the database
+    #[test]
+    fn test_to_sql_enum_i32() -> Result<()> {
+        let db = init_db()?;
+        let kp = KeyParameter::new(
+            KeyParameterValue::Algorithm(Algorithm::RSA),
+            SecurityLevel::STRONGBOX,
+        );
+        store_keyparameter(&db, 1, &kp)?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(kp.get_tag(), key_param.get_tag());
+        assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
+        assert_eq!(kp.security_level(), key_param.security_level());
+        Ok(())
+    }
+
+    /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
+    #[test]
+    fn test_to_sql_i32() -> Result<()> {
+        let db = init_db()?;
+        let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
+        store_keyparameter(&db, 1, &kp)?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(kp.get_tag(), key_param.get_tag());
+        assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
+        assert_eq!(kp.security_level(), key_param.security_level());
+        Ok(())
+    }
+
+    /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
+    #[test]
+    fn test_to_sql_i64() -> Result<()> {
+        let db = init_db()?;
+        // max value for i64, just to test corner cases
+        let kp = KeyParameter::new(
+            KeyParameterValue::RSAPublicExponent(i64::MAX),
+            SecurityLevel::STRONGBOX,
+        );
+        store_keyparameter(&db, 1, &kp)?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(kp.get_tag(), key_param.get_tag());
+        assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
+        assert_eq!(kp.security_level(), key_param.security_level());
+        Ok(())
+    }
+
+    /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
+    #[test]
+    fn test_to_sql_vec_u8() -> Result<()> {
+        let db = init_db()?;
+        let kp = KeyParameter::new(
+            KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
+            SecurityLevel::STRONGBOX,
+        );
+        store_keyparameter(&db, 1, &kp)?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(kp.get_tag(), key_param.get_tag());
+        assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
+        assert_eq!(kp.security_level(), key_param.security_level());
+        Ok(())
+    }
+
+    /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
+    #[test]
+    fn test_to_sql_bool() -> Result<()> {
+        let db = init_db()?;
+        let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
+        store_keyparameter(&db, 1, &kp)?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(kp.get_tag(), key_param.get_tag());
+        assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
+        assert_eq!(kp.security_level(), key_param.security_level());
+        Ok(())
+    }
+
+    #[test]
+    /// Test Tag::Invalid
+    fn test_invalid_tag() -> Result<()> {
+        let db = init_db()?;
+        insert_into_keyparameter(&db, 1, 0, &123, 1)?;
+        let key_param = query_from_keyparameter(&db)?;
+        assert_eq!(Tag::INVALID, key_param.get_tag());
+        Ok(())
+    }
+
+    #[test]
+    fn test_non_existing_enum_variant() -> Result<()> {
+        let db = init_db()?;
+        insert_into_keyparameter(&db, 1, 100, &123, 1)?;
+        tests::check_result_contains_error_string(
+            query_from_keyparameter(&db),
+            "Failed to decode Tag enum from value.",
+        );
+        Ok(())
+    }
+
+    #[test]
+    fn test_invalid_conversion_from_sql() -> Result<()> {
+        let db = init_db()?;
+        insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
+        tests::check_result_contains_error_string(
+            query_from_keyparameter(&db),
+            "Failed to read sql data for tag: ALGORITHM.",
+        );
+        Ok(())
+    }
+
+    /// Helper method to init database table for key parameter
+    fn init_db() -> Result<Connection> {
+        let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
+        db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
+            .context("Failed to attach databases.")?;
+        db.execute(
+            "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
+                                keyentryid INTEGER,
+                                tag INTEGER,
+                                data ANY,
+                                security_level INTEGER);",
+            NO_PARAMS,
+        )
+        .context("Failed to initialize \"keyparameter\" table.")?;
+        Ok(db)
+    }
+
+    /// Helper method to insert an entry into key parameter table, with individual parameters
+    fn insert_into_keyparameter<T: ToSql>(
+        db: &Connection,
+        key_id: i64,
+        tag: i32,
+        value: &T,
+        security_level: i32,
+    ) -> Result<()> {
+        db.execute(
+            "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
+                VALUES(?, ?, ?, ?);",
+            params![key_id, tag, *value, security_level],
+        )?;
+        Ok(())
+    }
+
+    /// Helper method to store a key parameter instance.
+    fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
+        db.execute(
+            "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
+                VALUES(?, ?, ?, ?);",
+            params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
+        )?;
+        Ok(())
+    }
+
+    /// Helper method to query a row from keyparameter table
+    fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
+        let mut stmt =
+            db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
+        let mut rows = stmt.query(NO_PARAMS)?;
+        let row = rows.next()?.unwrap();
+        Ok(KeyParameter::new_from_sql(
+            Tag(row.get(0)?),
+            &SqlField(1, row),
+            SecurityLevel(row.get(2)?),
+        )?)
+    }
+}
+
+/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
+/// KeyParameter, for the five different types used in KmKeyParameter, in addition to Invalid
+/// key parameter.
+/// i) bool
+/// ii) integer
+/// iii) longInteger
+/// iv) dateTime
+/// v) blob
+#[cfg(test)]
+mod wire_tests {
+    use crate::key_parameter::*;
+    /// unit tests for to conversions
+    #[test]
+    fn test_convert_to_wire_invalid() {
+        let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
+        let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
+        assert_eq!(Tag::INVALID, actual.tag);
+    }
+    #[test]
+    fn test_convert_to_wire_bool() {
+        let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
+        let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
+        assert_eq!(Tag::CALLER_NONCE, actual.tag);
+        assert_eq!(true, actual.boolValue);
+    }
+    #[test]
+    fn test_convert_to_wire_integer() {
+        let kp = KeyParameter::new(
+            KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
+            SecurityLevel::STRONGBOX,
+        );
+        let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
+        assert_eq!(Tag::PURPOSE, actual.tag);
+        assert_eq!(KeyPurpose::ENCRYPT.0, actual.integer);
+    }
+    #[test]
+    fn test_convert_to_wire_long_integer() {
+        let kp =
+            KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
+        let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
+        assert_eq!(Tag::USER_SECURE_ID, actual.tag);
+        assert_eq!(i64::MAX, actual.longInteger);
+    }
+    #[test]
+    fn test_convert_to_wire_date_time() {
+        let kp = KeyParameter::new(
+            KeyParameterValue::ActiveDateTime(i64::MAX),
+            SecurityLevel::STRONGBOX,
+        );
+        let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
+        assert_eq!(Tag::ACTIVE_DATETIME, actual.tag);
+        assert_eq!(i64::MAX, actual.dateTime);
+    }
+    #[test]
+    fn test_convert_to_wire_blob() {
+        let kp = KeyParameter::new(
+            KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
+            SecurityLevel::STRONGBOX,
+        );
+        let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
+        assert_eq!(Tag::CONFIRMATION_TOKEN, actual.tag);
+        assert_eq!(String::from("ConfirmationToken").into_bytes(), actual.blob);
+    }
+
+    /// unit tests for from conversion
+    #[test]
+    fn test_convert_from_wire_invalid() {
+        let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
+        let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+        assert_eq!(KeyParameterValue::Invalid, actual);
+    }
+    #[test]
+    fn test_convert_from_wire_bool() {
+        let aidl_kp =
+            KmKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
+        let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+        assert_eq!(KeyParameterValue::CallerNonce, actual);
+    }
+    #[test]
+    fn test_convert_from_wire_integer() {
+        let aidl_kp = KmKeyParameter {
+            tag: Tag::PURPOSE,
+            integer: KeyPurpose::ENCRYPT.0,
+            ..Default::default()
+        };
+        let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+        assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
+    }
+    #[test]
+    fn test_convert_from_wire_long_integer() {
+        let aidl_kp = KmKeyParameter {
+            tag: Tag::USER_SECURE_ID,
+            longInteger: i64::MAX,
+            ..Default::default()
+        };
+        let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+        assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
+    }
+    #[test]
+    fn test_convert_from_wire_date_time() {
+        let aidl_kp =
+            KmKeyParameter { tag: Tag::ACTIVE_DATETIME, dateTime: i64::MAX, ..Default::default() };
+        let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+        assert_eq!(KeyParameterValue::ActiveDateTime(i64::MAX), actual);
+    }
+    #[test]
+    fn test_convert_from_wire_blob() {
+        let aidl_kp = KmKeyParameter {
+            tag: Tag::CONFIRMATION_TOKEN,
+            blob: String::from("ConfirmationToken").into_bytes(),
+            ..Default::default()
+        };
+        let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+        assert_eq!(
+            KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
+            actual
+        );
+    }
+}
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
index d2c55a7..7439a5b 100644
--- a/keystore2/src/lib.rs
+++ b/keystore2/src/lib.rs
@@ -14,4 +14,10 @@
 
 //! This crate implements the Android Keystore 2.0 service.
 
+pub mod database;
 pub mod error;
+pub mod globals;
+/// Internal Representation of Key Parameter and convenience functions.
+pub mod key_parameter;
+pub mod permission;
+pub mod utils;
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
new file mode 100644
index 0000000..0917256
--- /dev/null
+++ b/keystore2/src/permission.rs
@@ -0,0 +1,945 @@
+// 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 crate provides access control primitives for Keystore 2.0.
+//! It provides high level functions for checking permissions in the keystore2 and keystore2_key
+//! SELinux classes based on the keystore2_selinux backend.
+//! It also provides KeystorePerm and KeyPerm as convenience wrappers for the SELinux permission
+//! defined by keystore2 and keystore2_key respectively.
+
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
+};
+
+use std::cmp::PartialEq;
+use std::convert::From;
+use std::ffi::CStr;
+
+use crate::error::Error as KsError;
+use keystore2_selinux as selinux;
+
+use anyhow::Context as AnyhowContext;
+
+use selinux::Backend;
+
+use lazy_static::lazy_static;
+
+// Replace getcon with a mock in the test situation
+#[cfg(not(test))]
+use selinux::getcon;
+#[cfg(test)]
+use tests::test_getcon as getcon;
+
+lazy_static! {
+    // Panicking here is allowed because keystore cannot function without this backend
+    // and it would happen early and indicate a gross misconfiguration of the device.
+    static ref KEYSTORE2_KEY_LABEL_BACKEND: selinux::KeystoreKeyBackend =
+            selinux::KeystoreKeyBackend::new().unwrap();
+}
+
+fn lookup_keystore2_key_context(namespace: i64) -> anyhow::Result<selinux::Context> {
+    KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
+}
+
+/// ## Background
+///
+/// AIDL enums are represented as constants of the form:
+/// ```
+/// mod EnumName {
+///     pub type EnumName = i32;
+///     pub const Variant1: EnumName = <value1>;
+///     pub const Variant2: EnumName = <value2>;
+///     ...
+/// }
+///```
+/// This macro wraps the enum in a new type, e.g., `MyPerm` and maps each variant to an SELinux
+/// permission while providing the following interface:
+///  * From<EnumName> and Into<EnumName> are implemented. Where the implementation of From maps
+///    any variant not specified to the default.
+///  * Every variant has a constructor with a name corresponding to its lower case SELinux string
+///    representation.
+///  * `MyPerm.to_selinux(&self)` returns the SELinux string representation of the
+///    represented permission.
+///
+/// ## Special behavior
+/// If the keyword `use` appears as an selinux name `use_` is used as identifier for the
+/// constructor function (e.g. `MePerm::use_()`) but the string returned by `to_selinux` will
+/// still be `"use"`.
+///
+/// ## Example
+/// ```
+///
+/// implement_permission!(
+///     /// MyPerm documentation.
+///     #[derive(Clone, Copy, Debug, PartialEq)]
+///     MyPerm from EnumName with default (None, none) {}
+///         Variant1,    selinux name: variant1;
+///         Variant2,    selinux name: variant1;
+///     }
+/// );
+/// ```
+macro_rules! implement_permission_aidl {
+    // This rule provides the public interface of the macro. And starts the preprocessing
+    // recursion (see below).
+    ($(#[$m:meta])* $name:ident from $aidl_name:ident with default ($($def:tt)*)
+        { $($element:tt)* })
+    => {
+        implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*), [],
+            $($element)*);
+    };
+
+    // The following three rules recurse through the elements of the form
+    // `<enum variant>, selinux name: <selinux_name>;`
+    // preprocessing the input.
+
+    // The first rule terminates the recursion and passes the processed arguments to the final
+    // rule that spills out the implementation.
+    (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*], ) => {
+        implement_permission_aidl!(@end $($m)*, $name, $aidl_name, ($($def)*) { $($out)* } );
+    };
+
+    // The second rule is triggered if the selinux name of an element is literally `use`.
+    // It produces the tuple `<enum variant>, use_, use;`
+    // and appends it to the out list.
+    (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*],
+        $e_name:ident, selinux name: use; $($element:tt)*)
+    => {
+        implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*),
+                              [$($out)* $e_name, use_, use;], $($element)*);
+    };
+
+    // The third rule is the default rule which replaces every input tuple with
+    // `<enum variant>, <selinux_name>, <selinux_name>;`
+    // and appends the result to the out list.
+    (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*],
+        $e_name:ident, selinux name: $e_str:ident; $($element:tt)*)
+    => {
+        implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*),
+                              [$($out)* $e_name, $e_str, $e_str;], $($element)*);
+    };
+
+    (@end $($m:meta)*, $name:ident, $aidl_name:ident,
+        ($def_name:ident, $def_selinux_name:ident) {
+            $($element_name:ident, $element_identifier:ident,
+                $selinux_name:ident;)*
+        })
+    =>
+    {
+        $(#[$m])*
+        pub struct $name(pub $aidl_name);
+
+        impl From<$aidl_name> for $name {
+            fn from (p: $aidl_name) -> Self {
+                match p {
+                    $aidl_name::$def_name => Self($aidl_name::$def_name),
+                    $($aidl_name::$element_name => Self($aidl_name::$element_name),)*
+                    _ => Self($aidl_name::$def_name),
+                }
+            }
+        }
+
+        impl Into<$aidl_name> for $name {
+            fn into(self) -> $aidl_name {
+                self.0
+            }
+        }
+
+        impl $name {
+            /// Returns a string representation of the permission as required by
+            /// `selinux::check_access`.
+            pub fn to_selinux(&self) -> &'static str {
+                match self {
+                    Self($aidl_name::$def_name) => stringify!($def_selinux_name),
+                    $(Self($aidl_name::$element_name) => stringify!($selinux_name),)*
+                    _ => stringify!($def_selinux_name),
+                }
+            }
+
+            /// Creates an instance representing a permission with the same name.
+            pub const fn $def_selinux_name() -> Self { Self($aidl_name::$def_name) }
+            $(
+                /// Creates an instance representing a permission with the same name.
+                pub const fn $element_identifier() -> Self { Self($aidl_name::$element_name) }
+            )*
+        }
+    };
+}
+
+implement_permission_aidl!(
+    /// KeyPerm provides a convenient abstraction from the SELinux class `keystore2_key`.
+    /// At the same time it maps `KeyPermissions` from the Keystore 2.0 AIDL Grant interface to
+    /// the SELinux permissions. With the implement_permission macro, we conveniently
+    /// provide mappings between the wire type bit field values, the rust enum and the SELinux
+    /// string representation.
+    ///
+    /// ## Example
+    ///
+    /// In this access check `KeyPerm::get_info().to_selinux()` would return the SELinux representation
+    /// "info".
+    /// ```
+    /// selinux::check_access(source_context, target_context, "keystore2_key",
+    ///                       KeyPerm::get_info().to_selinux());
+    /// ```
+    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+    KeyPerm from KeyPermission with default (NONE, none) {
+        DELETE,         selinux name: delete;
+        GEN_UNIQUE_ID,  selinux name: gen_unique_id;
+        GET_INFO,       selinux name: get_info;
+        GRANT,          selinux name: grant;
+        MANAGE_BLOB,    selinux name: manage_blob;
+        REBIND,         selinux name: rebind;
+        REQ_FORCED_OP,  selinux name: req_forced_op;
+        UPDATE,         selinux name: update;
+        USE,            selinux name: use;
+        USE_DEV_ID,     selinux name: use_dev_id;
+    }
+);
+
+/// This macro implements an enum with values mapped to SELinux permission names.
+/// The below example wraps the enum MyPermission in the tuple struct `MyPerm` and implements
+///  * From<i32> and Into<i32> are implemented. Where the implementation of From maps
+///    any variant not specified to the default.
+///  * Every variant has a constructor with a name corresponding to its lower case SELinux string
+///    representation.
+///  * `MyPerm.to_selinux(&self)` returns the SELinux string representation of the
+///    represented permission.
+///
+/// ## Example
+/// ```
+/// implement_permission!(
+///     /// MyPerm documentation.
+///     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+///     MyPerm with default (None = 0, none) {
+///         Foo = 1,           selinux name: foo;
+///         Bar = 2,           selinux name: bar;
+///     }
+/// );
+/// ```
+macro_rules! implement_permission {
+    // This rule provides the public interface of the macro. And starts the preprocessing
+    // recursion (see below).
+    ($(#[$m:meta])* $name:ident with default
+        ($def_name:ident = $def_val:expr, $def_selinux_name:ident)
+        {
+            $($(#[$element_meta:meta])*
+            $element_name:ident = $element_val:expr, selinux name: $selinux_name:ident;)*
+        })
+    => {
+        $(#[$m])*
+        pub enum $name {
+            /// The default variant of an enum.
+            $def_name = $def_val,
+            $(
+                $(#[$element_meta])*
+                $element_name = $element_val,
+            )*
+        }
+
+        impl From<i32> for $name {
+            fn from (p: i32) -> Self {
+                match p {
+                    $def_val => Self::$def_name,
+                    $($element_val => Self::$element_name,)*
+                    _ => Self::$def_name,
+                }
+            }
+        }
+
+        impl Into<i32> for $name {
+            fn into(self) -> i32 {
+                self as i32
+            }
+        }
+
+        impl $name {
+            /// Returns a string representation of the permission as required by
+            /// `selinux::check_access`.
+            pub fn to_selinux(&self) -> &'static str {
+                match self {
+                    Self::$def_name => stringify!($def_selinux_name),
+                    $(Self::$element_name => stringify!($selinux_name),)*
+                }
+            }
+
+            /// Creates an instance representing a permission with the same name.
+            pub const fn $def_selinux_name() -> Self { Self::$def_name }
+            $(
+                /// Creates an instance representing a permission with the same name.
+                pub const fn $selinux_name() -> Self { Self::$element_name }
+            )*
+        }
+    };
+}
+
+implement_permission!(
+    /// KeystorePerm provides a convenient abstraction from the SELinux class `keystore2`.
+    /// Using the implement_permission macro we get the same features as `KeyPerm`.
+    #[derive(Clone, Copy, Debug, PartialEq)]
+    KeystorePerm with default (None = 0, none) {
+        /// Checked when a new auth token is installed.
+        AddAuth = 1,    selinux name: add_auth;
+        /// Checked when an app is uninstalled or wiped.
+        ClearNs = 2,    selinux name: clear_ns;
+        /// Checked when Keystore 2.0 gets locked.
+        GetState = 4,   selinux name: get_state;
+        /// Checked when Keystore 2.0 is asked to list a namespace that the caller
+        /// does not have the get_info permission for.
+        List = 8,       selinux name: list;
+        /// Checked when Keystore 2.0 gets locked.
+        Lock = 0x10,       selinux name: lock;
+        /// Checked when Keystore 2.0 shall be reset.
+        Reset = 0x20,   selinux name: reset;
+        /// Checked when Keystore 2.0 shall be unlocked.
+        Unlock = 0x40,  selinux name: unlock;
+    }
+);
+
+/// Represents a set of `KeyPerm` permissions.
+/// `IntoIterator` is implemented for this struct allowing the iteration through all the
+/// permissions in the set.
+/// It also implements a function `includes(self, other)` that checks if the permissions
+/// in `other` are included in `self`.
+///
+/// KeyPermSet can be created with the macro `key_perm_set![]`.
+///
+/// ## Example
+/// ```
+/// let perms1 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob(), KeyPerm::grant()];
+/// let perms2 = key_perm_set![KeyPerm::use_(), KeyPerm::manage_blob()];
+///
+/// assert!(perms1.includes(perms2))
+/// assert!(!perms2.includes(perms1))
+///
+/// let i = perms1.into_iter();
+/// // iteration in ascending order of the permission's numeric representation.
+/// assert_eq(Some(KeyPerm::manage_blob()), i.next());
+/// assert_eq(Some(KeyPerm::grant()), i.next());
+/// assert_eq(Some(KeyPerm::use_()), i.next());
+/// assert_eq(None, i.next());
+/// ```
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub struct KeyPermSet(pub i32);
+
+mod perm {
+    use super::*;
+
+    pub struct IntoIter {
+        vec: KeyPermSet,
+        pos: u8,
+    }
+
+    impl IntoIter {
+        pub fn new(v: KeyPermSet) -> Self {
+            Self { vec: v, pos: 0 }
+        }
+    }
+
+    impl std::iter::Iterator for IntoIter {
+        type Item = KeyPerm;
+
+        fn next(&mut self) -> Option<Self::Item> {
+            loop {
+                if self.pos == 32 {
+                    return None;
+                }
+                let p = self.vec.0 & (1 << self.pos);
+                self.pos += 1;
+                if p != 0 {
+                    return Some(KeyPerm::from(KeyPermission(p)));
+                }
+            }
+        }
+    }
+}
+
+impl From<KeyPerm> for KeyPermSet {
+    fn from(p: KeyPerm) -> Self {
+        Self((p.0).0 as i32)
+    }
+}
+
+/// allow conversion from the AIDL wire type i32 to a permission set.
+impl From<i32> for KeyPermSet {
+    fn from(p: i32) -> Self {
+        Self(p)
+    }
+}
+
+impl From<KeyPermSet> for i32 {
+    fn from(p: KeyPermSet) -> i32 {
+        p.0
+    }
+}
+
+impl KeyPermSet {
+    /// Returns true iff this permission set has all of the permissions that are in `other`.
+    pub fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
+        let o: KeyPermSet = other.into();
+        (self.0 & o.0) == o.0
+    }
+}
+
+/// This macro can be used to create a `KeyPermSet` from a list of `KeyPerm` values.
+///
+/// ## Example
+/// ```
+/// let v = key_perm_set![Perm::delete(), Perm::manage_blob()];
+/// ```
+#[macro_export]
+macro_rules! key_perm_set {
+    () => { KeyPermSet(0) };
+    ($head:expr $(, $tail:expr)* $(,)?) => {
+        KeyPermSet(($head.0).0 $(| ($tail.0).0)*)
+    };
+}
+
+impl IntoIterator for KeyPermSet {
+    type Item = KeyPerm;
+    type IntoIter = perm::IntoIter;
+
+    fn into_iter(self) -> Self::IntoIter {
+        Self::IntoIter::new(self)
+    }
+}
+
+/// Uses `selinux::check_access` to check if the given caller context `caller_cxt` may access
+/// the given permision `perm` of the `keystore2` security class.
+pub fn check_keystore_permission(caller_ctx: &CStr, perm: KeystorePerm) -> anyhow::Result<()> {
+    let target_context = getcon().context("check_keystore_permission: getcon failed.")?;
+    selinux::check_access(caller_ctx, &target_context, "keystore2", perm.to_selinux())
+}
+
+/// Uses `selinux::check_access` to check if the given caller context `caller_cxt` has
+/// all the permissions indicated in `access_vec` for the target domain indicated by the key
+/// descriptor `key` in the security class `keystore2_key`.
+///
+/// Also checks if the caller has the grant permission for the given target domain.
+///
+/// Attempts to grant the grant permission are always denied.
+///
+/// The only viable target domains are
+///  * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
+///  * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
+///                      SELinux keystore key backend, and the result is used
+///                      as target context.
+pub fn check_grant_permission(
+    caller_ctx: &CStr,
+    access_vec: KeyPermSet,
+    key: &KeyDescriptor,
+) -> anyhow::Result<()> {
+    let target_context = match key.domain {
+        Domain::APP => getcon().context("check_grant_permission: getcon failed.")?,
+        Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
+            .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
+        _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
+    };
+
+    selinux::check_access(caller_ctx, &target_context, "keystore2_key", "grant")
+        .context("Grant permission is required when granting.")?;
+
+    if access_vec.includes(KeyPerm::grant()) {
+        return Err(selinux::Error::perm()).context("Grant permission cannot be granted.");
+    }
+
+    for p in access_vec.into_iter() {
+        selinux::check_access(caller_ctx, &target_context, "keystore2_key", p.to_selinux())
+            .context(concat!(
+                "check_grant_permission: check_access failed. ",
+                "The caller may have tried to grant a permission that they don't possess."
+            ))?
+    }
+    Ok(())
+}
+
+/// Uses `selinux::check_access` to check if the given caller context `caller_cxt`
+/// has the permissions indicated by `perm` for the target domain indicated by the key
+/// descriptor `key` in the security class `keystore2_key`.
+///
+/// The behavior differs slightly depending on the selected target domain:
+///  * `Domain::APP` u:r:keystore:s0 is used as target context.
+///  * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
+///                      backend, and the result is used as target context.
+///  * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
+///                   to the one supplied in `perm`.
+///  * `Domain::GRANT` Does not use selinux::check_access. Instead the `access_vector`
+///                    parameter is queried for permission, which must be supplied in this case.
+///
+/// ## Return values.
+///  * Ok(()) If the requested permissions were granted.
+///  * Err(selinux::Error::perm()) If the requested permissions were denied.
+///  * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
+///                      was supplied. It is also produced if `Domain::KEY_ID` was selected, and
+///                      on various unexpected backend failures.
+pub fn check_key_permission(
+    caller_ctx: &CStr,
+    perm: KeyPerm,
+    key: &KeyDescriptor,
+    access_vector: &Option<KeyPermSet>,
+) -> anyhow::Result<()> {
+    let target_context = match key.domain {
+        // apps get the default keystore context
+        Domain::APP => getcon().context("check_key_permission: getcon failed.")?,
+        Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
+            .context("check_key_permission: Domain::SELINUX: Failed to lookup namespace.")?,
+        Domain::GRANT => {
+            match access_vector {
+                Some(pv) => {
+                    if pv.includes(perm) {
+                        return Ok(());
+                    } else {
+                        return Err(selinux::Error::perm())
+                            .context(format!("\"{}\" not granted", perm.to_selinux()));
+                    }
+                }
+                None => {
+                    // If DOMAIN_GRANT was selected an access vector must be supplied.
+                    return Err(KsError::sys()).context(
+                        "Cannot check permission for Domain::GRANT without access vector.",
+                    );
+                }
+            }
+        }
+        Domain::KEY_ID => {
+            // We should never be called with `Domain::KEY_ID. The database
+            // lookup should have converted this into one of `Domain::APP`
+            // or `Domain::SELINUX`.
+            return Err(KsError::sys()).context("Cannot check permission for Domain::KEY_ID.");
+        }
+        Domain::BLOB => {
+            let tctx = lookup_keystore2_key_context(key.nspace)
+                .context("Domain::BLOB: Failed to lookup namespace.")?;
+            // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
+            // permission in addition to the requested permission.
+            selinux::check_access(
+                caller_ctx,
+                &tctx,
+                "keystore2_key",
+                KeyPerm::manage_blob().to_selinux(),
+            )?;
+
+            tctx
+        }
+        _ => {
+            return Err(KsError::sys())
+                .context(format!("Unknown domain value: \"{:?}\".", key.domain))
+        }
+    };
+
+    selinux::check_access(caller_ctx, &target_context, "keystore2_key", perm.to_selinux())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use anyhow::anyhow;
+    use anyhow::Result;
+    use keystore2_selinux::*;
+
+    const ALL_PERMS: KeyPermSet = key_perm_set![
+        KeyPerm::manage_blob(),
+        KeyPerm::delete(),
+        KeyPerm::use_dev_id(),
+        KeyPerm::req_forced_op(),
+        KeyPerm::gen_unique_id(),
+        KeyPerm::grant(),
+        KeyPerm::get_info(),
+        KeyPerm::rebind(),
+        KeyPerm::update(),
+        KeyPerm::use_(),
+    ];
+
+    const NOT_GRANT_PERMS: KeyPermSet = key_perm_set![
+        KeyPerm::manage_blob(),
+        KeyPerm::delete(),
+        KeyPerm::use_dev_id(),
+        KeyPerm::req_forced_op(),
+        KeyPerm::gen_unique_id(),
+        // No KeyPerm::grant()
+        KeyPerm::get_info(),
+        KeyPerm::rebind(),
+        KeyPerm::update(),
+        KeyPerm::use_(),
+    ];
+
+    const UNPRIV_PERMS: KeyPermSet = key_perm_set![
+        KeyPerm::delete(),
+        KeyPerm::get_info(),
+        KeyPerm::rebind(),
+        KeyPerm::update(),
+        KeyPerm::use_(),
+    ];
+
+    /// The su_key namespace as defined in su.te and keystore_key_contexts of the
+    /// SePolicy (system/sepolicy).
+    const SU_KEY_NAMESPACE: i32 = 0;
+    /// The shell_key namespace as defined in shell.te and keystore_key_contexts of the
+    /// SePolicy (system/sepolicy).
+    const SHELL_KEY_NAMESPACE: i32 = 1;
+
+    pub fn test_getcon() -> Result<Context> {
+        Context::new("u:object_r:keystore:s0")
+    }
+
+    // This macro evaluates the given expression and checks that
+    // a) evaluated to Result::Err() and that
+    // b) the wrapped error is selinux::Error::perm() (permission denied).
+    // We use a macro here because a function would mask which invocation caused the failure.
+    //
+    // TODO b/164121720 Replace this macro with a function when `track_caller` is available.
+    macro_rules! assert_perm_failed {
+        ($test_function:expr) => {
+            let result = $test_function;
+            assert!(result.is_err(), "Permission check should have failed.");
+            assert_eq!(
+                Some(&selinux::Error::perm()),
+                result.err().unwrap().root_cause().downcast_ref::<selinux::Error>()
+            );
+        };
+    }
+
+    fn check_context() -> Result<(selinux::Context, i32, bool)> {
+        // Calling the non mocked selinux::getcon here intended.
+        let context = selinux::getcon()?;
+        match context.to_str().unwrap() {
+            "u:r:su:s0" => Ok((context, SU_KEY_NAMESPACE, true)),
+            "u:r:shell:s0" => Ok((context, SHELL_KEY_NAMESPACE, false)),
+            c => Err(anyhow!(format!(
+                "This test must be run as \"su\" or \"shell\". Current context: \"{}\"",
+                c
+            ))),
+        }
+    }
+
+    #[test]
+    fn check_keystore_permission_test() -> Result<()> {
+        let system_server_ctx = Context::new("u:r:system_server:s0")?;
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::add_auth()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::clear_ns()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::get_state()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::list()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::lock()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::reset()).is_ok());
+        assert!(check_keystore_permission(&system_server_ctx, KeystorePerm::unlock()).is_ok());
+        let shell_ctx = Context::new("u:r:shell:s0")?;
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::add_auth()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::clear_ns()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::get_state()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::list()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::lock()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::reset()));
+        assert_perm_failed!(check_keystore_permission(&shell_ctx, KeystorePerm::unlock()));
+        Ok(())
+    }
+
+    #[test]
+    fn check_grant_permission_app() -> Result<()> {
+        let system_server_ctx = Context::new("u:r:system_server:s0")?;
+        let shell_ctx = Context::new("u:r:shell:s0")?;
+        let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
+        assert!(check_grant_permission(&system_server_ctx, NOT_GRANT_PERMS, &key).is_ok());
+        // attempts to grant the grant permission must always fail even when privileged.
+
+        assert_perm_failed!(check_grant_permission(
+            &system_server_ctx,
+            KeyPerm::grant().into(),
+            &key
+        ));
+        // unprivileged grant attempts always fail. shell does not have the grant permission.
+        assert_perm_failed!(check_grant_permission(&shell_ctx, UNPRIV_PERMS, &key));
+        Ok(())
+    }
+
+    #[test]
+    fn check_grant_permission_selinux() -> Result<()> {
+        let (sctx, namespace, is_su) = check_context()?;
+        let key = KeyDescriptor {
+            domain: Domain::SELINUX,
+            nspace: namespace as i64,
+            alias: None,
+            blob: None,
+        };
+        if is_su {
+            assert!(check_grant_permission(&sctx, NOT_GRANT_PERMS, &key).is_ok());
+            // attempts to grant the grant permission must always fail even when privileged.
+            assert_perm_failed!(check_grant_permission(&sctx, KeyPerm::grant().into(), &key));
+        } else {
+            // unprivileged grant attempts always fail. shell does not have the grant permission.
+            assert_perm_failed!(check_grant_permission(&sctx, UNPRIV_PERMS, &key));
+        }
+        Ok(())
+    }
+
+    #[test]
+    fn check_key_permission_domain_grant() -> Result<()> {
+        let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
+
+        assert_perm_failed!(check_key_permission(
+            &selinux::Context::new("ignored").unwrap(),
+            KeyPerm::grant(),
+            &key,
+            &Some(UNPRIV_PERMS)
+        ));
+
+        check_key_permission(
+            &selinux::Context::new("ignored").unwrap(),
+            KeyPerm::use_(),
+            &key,
+            &Some(ALL_PERMS),
+        )
+    }
+
+    #[test]
+    fn check_key_permission_domain_app() -> Result<()> {
+        let system_server_ctx = Context::new("u:r:system_server:s0")?;
+        let shell_ctx = Context::new("u:r:shell:s0")?;
+        let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
+
+        let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
+
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::use_(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::delete(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::get_info(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::rebind(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::update(), &key, &None).is_ok());
+        assert!(check_key_permission(&system_server_ctx, KeyPerm::grant(), &key, &None).is_ok());
+        assert!(
+            check_key_permission(&system_server_ctx, KeyPerm::use_dev_id(), &key, &None).is_ok()
+        );
+        assert!(check_key_permission(&gmscore_app, KeyPerm::gen_unique_id(), &key, &None).is_ok());
+
+        assert!(check_key_permission(&shell_ctx, KeyPerm::use_(), &key, &None).is_ok());
+        assert!(check_key_permission(&shell_ctx, KeyPerm::delete(), &key, &None).is_ok());
+        assert!(check_key_permission(&shell_ctx, KeyPerm::get_info(), &key, &None).is_ok());
+        assert!(check_key_permission(&shell_ctx, KeyPerm::rebind(), &key, &None).is_ok());
+        assert!(check_key_permission(&shell_ctx, KeyPerm::update(), &key, &None).is_ok());
+        assert_perm_failed!(check_key_permission(&shell_ctx, KeyPerm::grant(), &key, &None));
+        assert_perm_failed!(check_key_permission(
+            &shell_ctx,
+            KeyPerm::req_forced_op(),
+            &key,
+            &None
+        ));
+        assert_perm_failed!(check_key_permission(&shell_ctx, KeyPerm::manage_blob(), &key, &None));
+        assert_perm_failed!(check_key_permission(&shell_ctx, KeyPerm::use_dev_id(), &key, &None));
+        assert_perm_failed!(check_key_permission(
+            &shell_ctx,
+            KeyPerm::gen_unique_id(),
+            &key,
+            &None
+        ));
+
+        Ok(())
+    }
+
+    #[test]
+    fn check_key_permission_domain_selinux() -> Result<()> {
+        let (sctx, namespace, is_su) = check_context()?;
+        let key = KeyDescriptor {
+            domain: Domain::SELINUX,
+            nspace: namespace as i64,
+            alias: None,
+            blob: None,
+        };
+
+        if is_su {
+            assert!(check_key_permission(&sctx, KeyPerm::use_(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::delete(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::get_info(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::rebind(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::update(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::grant(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::manage_blob(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::use_dev_id(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::gen_unique_id(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::req_forced_op(), &key, &None).is_ok());
+        } else {
+            assert!(check_key_permission(&sctx, KeyPerm::use_(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::delete(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::get_info(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::rebind(), &key, &None).is_ok());
+            assert!(check_key_permission(&sctx, KeyPerm::update(), &key, &None).is_ok());
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::grant(), &key, &None));
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::req_forced_op(), &key, &None));
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::manage_blob(), &key, &None));
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::use_dev_id(), &key, &None));
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::gen_unique_id(), &key, &None));
+        }
+        Ok(())
+    }
+
+    #[test]
+    fn check_key_permission_domain_blob() -> Result<()> {
+        let (sctx, namespace, is_su) = check_context()?;
+        let key = KeyDescriptor {
+            domain: Domain::BLOB,
+            nspace: namespace as i64,
+            alias: None,
+            blob: None,
+        };
+
+        if is_su {
+            check_key_permission(&sctx, KeyPerm::use_(), &key, &None)
+        } else {
+            assert_perm_failed!(check_key_permission(&sctx, KeyPerm::use_(), &key, &None));
+            Ok(())
+        }
+    }
+
+    #[test]
+    fn check_key_permission_domain_key_id() -> Result<()> {
+        let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
+
+        assert_eq!(
+            Some(&KsError::sys()),
+            check_key_permission(
+                &selinux::Context::new("ignored").unwrap(),
+                KeyPerm::use_(),
+                &key,
+                &None
+            )
+            .err()
+            .unwrap()
+            .root_cause()
+            .downcast_ref::<KsError>()
+        );
+        Ok(())
+    }
+
+    #[test]
+    fn key_perm_set_all_test() {
+        let v = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::use_dev_id(),
+            KeyPerm::req_forced_op(),
+            KeyPerm::gen_unique_id(),
+            KeyPerm::grant(),
+            KeyPerm::get_info(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_() // Test if the macro accepts missing comma at the end of the list.
+        ];
+        let mut i = v.into_iter();
+        assert_eq!(i.next().unwrap().to_selinux(), "delete");
+        assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
+        assert_eq!(i.next().unwrap().to_selinux(), "get_info");
+        assert_eq!(i.next().unwrap().to_selinux(), "grant");
+        assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
+        assert_eq!(i.next().unwrap().to_selinux(), "rebind");
+        assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
+        assert_eq!(i.next().unwrap().to_selinux(), "update");
+        assert_eq!(i.next().unwrap().to_selinux(), "use");
+        assert_eq!(i.next().unwrap().to_selinux(), "use_dev_id");
+        assert_eq!(None, i.next());
+    }
+    #[test]
+    fn key_perm_set_sparse_test() {
+        let v = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::req_forced_op(),
+            KeyPerm::gen_unique_id(),
+            KeyPerm::update(),
+            KeyPerm::use_(), // Test if macro accepts the comma at the end of the list.
+        ];
+        let mut i = v.into_iter();
+        assert_eq!(i.next().unwrap().to_selinux(), "gen_unique_id");
+        assert_eq!(i.next().unwrap().to_selinux(), "manage_blob");
+        assert_eq!(i.next().unwrap().to_selinux(), "req_forced_op");
+        assert_eq!(i.next().unwrap().to_selinux(), "update");
+        assert_eq!(i.next().unwrap().to_selinux(), "use");
+        assert_eq!(None, i.next());
+    }
+    #[test]
+    fn key_perm_set_empty_test() {
+        let v = key_perm_set![];
+        let mut i = v.into_iter();
+        assert_eq!(None, i.next());
+    }
+    #[test]
+    fn key_perm_set_include_subset_test() {
+        let v1 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::use_dev_id(),
+            KeyPerm::req_forced_op(),
+            KeyPerm::gen_unique_id(),
+            KeyPerm::grant(),
+            KeyPerm::get_info(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        let v2 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        assert!(v1.includes(v2));
+        assert!(!v2.includes(v1));
+    }
+    #[test]
+    fn key_perm_set_include_equal_test() {
+        let v1 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        let v2 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        assert!(v1.includes(v2));
+        assert!(v2.includes(v1));
+    }
+    #[test]
+    fn key_perm_set_include_overlap_test() {
+        let v1 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::grant(), // only in v1
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        let v2 = key_perm_set![
+            KeyPerm::manage_blob(),
+            KeyPerm::delete(),
+            KeyPerm::req_forced_op(), // only in v2
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        assert!(!v1.includes(v2));
+        assert!(!v2.includes(v1));
+    }
+    #[test]
+    fn key_perm_set_include_no_overlap_test() {
+        let v1 = key_perm_set![KeyPerm::manage_blob(), KeyPerm::delete(), KeyPerm::grant(),];
+        let v2 = key_perm_set![
+            KeyPerm::req_forced_op(),
+            KeyPerm::rebind(),
+            KeyPerm::update(),
+            KeyPerm::use_(),
+        ];
+        assert!(!v1.includes(v2));
+        assert!(!v2.includes(v1));
+    }
+}
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
new file mode 100644
index 0000000..825b34a
--- /dev/null
+++ b/keystore2/src/utils.rs
@@ -0,0 +1,122 @@
+// 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 module implements utility functions used by the Keystore 2.0 service
+//! implementation.
+
+use crate::error::Error;
+use crate::permission;
+use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
+use android_hardware_keymint::aidl::android::hardware::keymint::{
+    KeyParameter::KeyParameter as KmParam, Tag::Tag,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    KeyDescriptor::KeyDescriptor, KeyParameter::KeyParameter,
+};
+use anyhow::{anyhow, Context};
+use binder::{FromIBinder, SpIBinder, ThreadState};
+use std::sync::Mutex;
+
+/// This function uses its namesake in the permission module and in
+/// combination with with_calling_sid from the binder crate to check
+/// if the caller has the given keystore permission.
+pub fn check_keystore_permission(perm: KeystorePerm) -> anyhow::Result<()> {
+    ThreadState::with_calling_sid(|calling_sid| {
+        permission::check_keystore_permission(
+            &calling_sid.ok_or_else(Error::sys).context(
+                "In check_keystore_permission: Cannot check permission without calling_sid.",
+            )?,
+            perm,
+        )
+    })
+}
+
+/// This function uses its namesake in the permission module and in
+/// combination with with_calling_sid from the binder crate to check
+/// if the caller has the given grant permission.
+pub fn check_grant_permission(access_vec: KeyPermSet, key: &KeyDescriptor) -> anyhow::Result<()> {
+    ThreadState::with_calling_sid(|calling_sid| {
+        permission::check_grant_permission(
+            &calling_sid.ok_or_else(Error::sys).context(
+                "In check_grant_permission: Cannot check permission without calling_sid.",
+            )?,
+            access_vec,
+            key,
+        )
+    })
+}
+
+/// This function uses its namesake in the permission module and in
+/// combination with with_calling_sid from the binder crate to check
+/// if the caller has the given key permission.
+pub fn check_key_permission(
+    perm: KeyPerm,
+    key: &KeyDescriptor,
+    access_vector: &Option<KeyPermSet>,
+) -> anyhow::Result<()> {
+    ThreadState::with_calling_sid(|calling_sid| {
+        permission::check_key_permission(
+            &calling_sid
+                .ok_or_else(Error::sys)
+                .context("In check_key_permission: Cannot check permission without calling_sid.")?,
+            perm,
+            key,
+            access_vector,
+        )
+    })
+}
+
+/// This function converts a `KeyParameter` from the keystore2 AIDL
+/// bindings into a `KeyParameter` from the keymint AIDL bindings.
+/// TODO This is a temporary workaround until the keymint AIDL spec
+/// lands.
+pub fn keyparam_ks_to_km(p: &KeyParameter) -> KmParam {
+    KmParam {
+        tag: Tag(p.tag),
+        boolValue: p.boolValue,
+        integer: p.integer,
+        longInteger: p.longInteger,
+        dateTime: p.dateTime,
+        blob: match &p.blob {
+            Some(b) => b.clone(),
+            None => vec![],
+        },
+    }
+}
+
+/// Thread safe wrapper around SpIBinder. It is safe to have SpIBinder smart pointers to the
+/// same object in multiple threads, but cloning a SpIBinder is not thread safe.
+/// Keystore frequently hands out binder tokens to the security level interface. If this
+/// is to happen from a multi threaded thread pool, the SpIBinder needs to be protected by a
+/// Mutex.
+#[derive(Debug)]
+pub struct Asp(Mutex<SpIBinder>);
+
+impl Asp {
+    /// Creates a new instance owning a SpIBinder wrapped in a Mutex.
+    pub fn new(i: SpIBinder) -> Self {
+        Self(Mutex::new(i))
+    }
+
+    /// Clones the owned SpIBinder and attempts to convert it into the requested interface.
+    pub fn get_interface<T: FromIBinder + ?Sized>(&self) -> anyhow::Result<Box<T>> {
+        // We can use unwrap here because we never panic when locked, so the mutex
+        // can never be poisoned.
+        let lock = self.0.lock().unwrap();
+        (*lock)
+            .clone()
+            .into_interface()
+            .map_err(|e| anyhow!(format!("get_interface failed with error code {:?}", e)))
+    }
+}