Merge "Model KeyStore security level in keymaster worker"
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index 154b675..b5728a3 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -18,8 +18,10 @@
     srcs: ["src/lib.rs"],
 
     rustlibs: [
+        "libandroid_hardware_keymint",
+        "libandroid_security_keystore2",
         "libanyhow",
-        "libkeystore_aidl_generated",
+        "libbinder_rs",
         "libkeystore2_selinux",
         "liblazy_static",
         "liblibsqlite3_sys",
@@ -38,8 +40,10 @@
     auto_gen_config: true,
     rustlibs: [
         "libandroid_logger",
+        "libandroid_hardware_keymint",
+        "libandroid_security_keystore2",
         "libanyhow",
-        "libkeystore_aidl_generated",
+        "libbinder_rs",
         "libkeystore2_selinux",
         "liblazy_static",
         "liblibsqlite3_sys",
@@ -52,15 +56,6 @@
 // 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",
-
-    srcs: ["src/aidl_generated.rs"],
-}
-
-// This is a placeholder for the libraries that will be generated from the AIDL specs
-// eventually.
-rust_library {
     name: "libandroid_hardware_keymint",
     crate_name: "android_hardware_keymint",
 
diff --git a/keystore2/selinux/src/lib.rs b/keystore2/selinux/src/lib.rs
index 05f9db8..8bc3bc4 100644
--- a/keystore2/selinux/src/lib.rs
+++ b/keystore2/selinux/src/lib.rs
@@ -39,10 +39,12 @@
 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` assigned the static lifetime function pointer
+    // `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 {
@@ -50,7 +52,7 @@
     }
 }
 
-// This function must be called before any entrypoint into lib selinux.
+// 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() {
@@ -82,6 +84,7 @@
 /// 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),
@@ -89,6 +92,16 @@
     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"))
@@ -221,6 +234,32 @@
     }
 }
 
+/// 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
@@ -228,7 +267,7 @@
 ///  * 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: &Context, target: &Context, tclass: &str, perm: &str) -> Result<()> {
+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)
@@ -256,7 +295,7 @@
             .with_context(|| {
                 format!(
                     concat!(
-                        "check_access: Failed with sctx: {} tctx: {}",
+                        "check_access: Failed with sctx: {:?} tctx: {:?}",
                         " with target class: \"{}\" perm: \"{}\""
                     ),
                     source, target, tclass, perm
@@ -325,7 +364,7 @@
         /// 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 expeced to be denied to `shell` users but granted
+        /// 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
@@ -424,4 +463,12 @@
         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/database.rs b/keystore2/src/database.rs
index 394b7be..b1cde6e 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -17,64 +17,72 @@
 
 use crate::error::Error as KsError;
 use anyhow::{Context, Result};
-use keystore_aidl_generated as aidl;
+
+use android_security_keystore2::aidl::android::security::keystore2::{
+    Domain, Domain::Domain as DomainType,
+};
+
 #[cfg(not(test))]
 use rand::prelude::random;
 use rusqlite::{params, Connection, TransactionBehavior, NO_PARAMS};
+use std::sync::Once;
 #[cfg(test)]
 use tests::random;
 
+static INIT_TABLES: Once = Once::new();
+
 pub struct KeystoreDB {
     conn: Connection,
 }
 
 impl KeystoreDB {
-    // TODO(b/160882985): Figure out the location for this file.
-    #[cfg(not(test))]
-    pub fn new() -> Result<KeystoreDB> {
-        KeystoreDB::new_with_filename("persistent.sql")
+    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 })
     }
 
-    #[cfg(test)]
-    pub fn new() -> Result<KeystoreDB> {
-        KeystoreDB::new_with_filename("")
-    }
-
-    fn new_with_filename(persistent_file: &str) -> Result<KeystoreDB> {
-        let db = KeystoreDB {
-            conn: Connection::open_in_memory()
-                .context("Failed to initialize sqlite connection.")?,
-        };
-        db.attach_databases(persistent_file).context("Failed to create KeystoreDB.")?;
-        db.init_tables().context("Failed to create KeystoreDB.")?;
-        Ok(db)
-    }
-
-    fn attach_databases(&self, persistent_file: &str) -> Result<()> {
-        self.conn
-            .execute("ATTACH DATABASE ? as 'persistent';", params![persistent_file])
-            .context("Failed to attach databases.")?;
-        Ok(())
-    }
-
-    fn init_tables(&self) -> Result<()> {
-        self.conn
-            .execute(
-                "CREATE TABLE IF NOT EXISTS persistent.keyentry (
+    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.")?;
+            NO_PARAMS,
+        )
+        .context("Failed to initialize \"keyentry\" 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.")?;
+
         Ok(())
     }
 
-    pub fn create_key_entry(&self, domain: aidl::Domain, namespace: i64) -> Result<i64> {
+    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)
+    }
+
+    pub fn create_key_entry(&self, domain: DomainType, namespace: i64) -> Result<i64> {
         match domain {
-            aidl::Domain::App | aidl::Domain::SELinux => {}
+            Domain::App | Domain::SELinux => {}
             _ => {
                 return Err(KsError::sys())
                     .context(format!("Domain {:?} must be either App or SELinux.", domain));
@@ -106,11 +114,11 @@
         &mut self,
         newid: u32,
         alias: &str,
-        domain: aidl::Domain,
+        domain: DomainType,
         namespace: i64,
     ) -> Result<()> {
         match domain {
-            aidl::Domain::App | aidl::Domain::SELinux => {}
+            Domain::App | Domain::SELinux => {}
             _ => {
                 return Err(KsError::sys())
                     .context(format!("Domain {:?} must be either App or SELinux.", domain));
@@ -155,6 +163,23 @@
     use super::*;
     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() {
@@ -169,35 +194,29 @@
         }
     }
 
-    // Ensure we can initialize the database.
-    #[test]
-    fn test_new() -> Result<()> {
-        KeystoreDB::new()?;
-        Ok(())
-    }
-
     // Test that we have the correct tables.
     #[test]
     fn test_tables() -> Result<()> {
-        let db = KeystoreDB::new()?;
+        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(), 1);
+        assert_eq!(tables.len(), 2);
         assert_eq!(tables[0], "keyentry");
+        assert_eq!(tables[1], "keyparameter");
         Ok(())
     }
 
     #[test]
     fn test_no_persistence_for_tests() -> Result<()> {
-        let db = KeystoreDB::new()?;
+        let db = new_test_db()?;
 
-        db.create_key_entry(aidl::Domain::App, 100)?;
+        db.create_key_entry(Domain::App, 100)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 1);
-        let db = KeystoreDB::new()?;
+        let db = new_test_db()?;
 
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 0);
@@ -206,13 +225,14 @@
 
     #[test]
     fn test_persistence_for_files() -> Result<()> {
-        let persistent = TempFile { filename: "/data/local/tmp/persistent.sql" };
-        let db = KeystoreDB::new_with_filename(persistent.filename)?;
+        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(aidl::Domain::App, 100)?;
+        db.create_key_entry(Domain::App, 100)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 1);
-        let db = KeystoreDB::new_with_filename(persistent.filename)?;
+        let db = new_test_db_with_persistent_file()?;
 
         let entries_new = get_keyentry(&db)?;
         assert_eq!(entries, entries_new);
@@ -221,13 +241,11 @@
 
     #[test]
     fn test_create_key_entry() -> Result<()> {
-        use aidl::Domain;
-
-        fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
+        fn extractor(ke: &KeyEntryRow) -> (DomainType, i64, Option<&str>) {
             (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
         }
 
-        let db = KeystoreDB::new()?;
+        let db = new_test_db()?;
 
         db.create_key_entry(Domain::App, 100)?;
         db.create_key_entry(Domain::SELinux, 101)?;
@@ -240,15 +258,15 @@
         // Test that we must pass in a valid Domain.
         check_result_is_error_containing_string(
             db.create_key_entry(Domain::Grant, 102),
-            "Domain Grant must be either App or SELinux.",
+            "Domain 1 must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
             db.create_key_entry(Domain::Blob, 103),
-            "Domain Blob must be either App or SELinux.",
+            "Domain 3 must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
             db.create_key_entry(Domain::KeyId, 104),
-            "Domain KeyId must be either App or SELinux.",
+            "Domain 4 must be either App or SELinux.",
         );
 
         Ok(())
@@ -256,13 +274,11 @@
 
     #[test]
     fn test_rebind_alias() -> Result<()> {
-        use aidl::Domain;
-
-        fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
+        fn extractor(ke: &KeyEntryRow) -> (Option<DomainType>, Option<i64>, Option<&str>) {
             (ke.domain, ke.namespace, ke.alias.as_deref())
         }
 
-        let mut db = KeystoreDB::new()?;
+        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)?;
@@ -287,15 +303,15 @@
         // Test that we must pass in a valid Domain.
         check_result_is_error_containing_string(
             db.rebind_alias(0, "foo", Domain::Grant, 42),
-            "Domain Grant must be either App or SELinux.",
+            "Domain 1 must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
             db.rebind_alias(0, "foo", Domain::Blob, 42),
-            "Domain Blob must be either App or SELinux.",
+            "Domain 3 must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
             db.rebind_alias(0, "foo", Domain::KeyId, 42),
-            "Domain KeyId must be either App or SELinux.",
+            "Domain 4 must be either App or SELinux.",
         );
 
         // Test that we correctly handle setting an alias for something that does not exist.
@@ -333,7 +349,7 @@
     struct KeyEntryRow {
         id: u32,
         creation_date: String,
-        domain: Option<aidl::Domain>,
+        domain: Option<DomainType>,
         namespace: Option<i64>,
         alias: Option<String>,
     }
@@ -342,11 +358,10 @@
         db.conn
             .prepare("SELECT * FROM persistent.keyentry;")?
             .query_map(NO_PARAMS, |row| {
-                let domain: Option<i32> = row.get(2)?;
                 Ok(KeyEntryRow {
                     id: row.get(0)?,
                     creation_date: row.get(1)?,
-                    domain: domain.map(domain_from_integer),
+                    domain: row.get(2)?,
                     namespace: row.get(3)?,
                     alias: row.get(4)?,
                 })
@@ -355,19 +370,6 @@
             .collect::<Result<Vec<_>>>()
     }
 
-    // TODO: Replace this with num_derive.
-    fn domain_from_integer(value: i32) -> aidl::Domain {
-        use aidl::Domain;
-        match value {
-            x if Domain::App as i32 == x => Domain::App,
-            x if Domain::Grant as i32 == x => Domain::Grant,
-            x if Domain::SELinux as i32 == x => Domain::SELinux,
-            x if Domain::Blob as i32 == x => Domain::Blob,
-            x if Domain::KeyId as i32 == x => Domain::KeyId,
-            _ => panic!("Unexpected domain: {}", value),
-        }
-    }
-
     // 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 {
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index e6443b7..0326610 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -31,35 +31,18 @@
 //! 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 as Ec;
+pub use android_security_keystore2::aidl::android::security::keystore2::ResponseCode as Rc;
+
+use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode::ErrorCode;
+use android_security_keystore2::aidl::android::security::keystore2::ResponseCode::ResponseCode;
 
 use keystore2_selinux as selinux;
 
-pub use aidl::ResponseCode;
-
-/// 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_security_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.
@@ -67,36 +50,55 @@
 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)`
     pub fn sys() -> Self {
-        Error::Rc(AidlRc::SystemError)
+        Error::Rc(Rc::SystemError)
     }
 
     /// Short hand for `Error::Rc(ResponseCode::PermissionDenied`
     pub fn perm() -> Self {
-        Error::Rc(AidlRc::PermissionDenied)
+        Error::Rc(Rc::PermissionDenied)
     }
 }
 
-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 => match root_cause.downcast_ref::<selinux::Error>() {
-                Some(selinux::Error::PermissionDenied) => AidlResult::rc(AidlRc::PermissionDenied),
-                _ => 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(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
@@ -129,32 +131,46 @@
 ///
 /// 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,
+                Some(Error::Km(ec)) => *ec,
+                // 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(_, _)) => Rc::SystemError,
+                None => match root_cause.downcast_ref::<selinux::Error>() {
+                    Some(selinux::Error::PermissionDenied) => Rc::PermissionDenied,
+                    _ => Rc::SystemError,
+                },
+            };
+            Err(BinderStatus::new_service_specific_error(rc, None))
         },
         handle_ok,
     )
 }
 
 #[cfg(test)]
-mod tests {
+pub mod tests {
 
+    use super::*;
+    use android_security_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")
     }
 
@@ -166,11 +182,11 @@
         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")
     }
 
@@ -196,6 +212,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(
@@ -203,85 +227,101 @@
                 .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 Rc::Ok..Rc::BackendBusy {
+            assert_eq!(
+                Result::<(), i32>::Err(rc),
+                map_or_log_err(nested_rc(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 Ec::UNKNOWN_ERROR..Ec::ROOT_OF_TRUST_ALREADY_SET {
+            assert_eq!(
+                Result::<(), i32>::Err(ec),
+                map_or_log_err(nested_ec(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 Ec::UNKNOWN_ERROR..Ec::ROOT_OF_TRUST_ALREADY_SET {
+            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 Rc::SystemError.
         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::<(), i32>::Err(Rc::SystemError),
+            map_or_log_err(sse.context("Non negative service specific error."), |_| Err(
+                BinderStatus::ok()
+            ))
+            .map_err(|s| 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 Rc::SystemError.
         assert_eq!(
-            AidlResult::ec(-7),
-            map_or_log_err(nested_ec(-7), |_| AidlResult::rc(AidlRc::SystemError))
+            Result::<(), i32>::Err(Rc::SystemError),
+            map_or_log_err(binder_exception.context("Binder Exception."), |_| Err(
+                BinderStatus::ok()
+            ))
+            .map_err(|s| s.service_specific_error())
         );
 
-        // All other get mapped on System Error.
+        // selinux::Error::Perm() needs to be mapped to Rc::PermissionDenied
         assert_eq!(
-            AidlResult::rc(AidlRc::SystemError),
-            map_or_log_err(nested_other_error(), |_| AidlResult::ec(0))
+            Result::<(), i32>::Err(Rc::PermissionDenied),
+            map_or_log_err(nested_selinux_perm(), |_| Err(BinderStatus::ok()))
+                .map_err(|s| s.service_specific_error())
+        );
+
+        // All other errors get mapped on System Error.
+        assert_eq!(
+            Result::<(), i32>::Err(Rc::SystemError),
+            map_or_log_err(nested_other_error(), |_| Err(BinderStatus::ok()))
+                .map_err(|s| s.service_specific_error())
         );
 
         // Result::Ok variants get passed to the ok handler.
-        assert_eq!(
-            AidlResult::rc(AidlRc::OpAuthNeeded),
-            map_or_log_err(nested_ok(AidlRc::OpAuthNeeded), AidlResult::rc)
-        );
-        assert_eq!(AidlResult::ok(), map_or_log_err(nested_ok(AidlRc::Ok), AidlResult::rc));
+        assert_eq!(Ok(Rc::OpAuthNeeded), map_or_log_err(nested_ok(Rc::OpAuthNeeded), Ok));
+        assert_eq!(Ok(Rc::Ok), map_or_log_err(nested_ok(Rc::Ok), Ok));
 
-        // selinux::Error::Perm() needs to be mapped to AidlRc::PermissionDenied
-        assert_eq!(
-            AidlResult::rc(AidlRc::PermissionDenied),
-            map_or_log_err(nested_selinux_perm(), |_| AidlResult::ec(0))
-        );
         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/key_parameter.rs b/keystore2/src/key_parameter.rs
index d9ec7f3..5266c28 100644
--- a/keystore2/src/key_parameter.rs
+++ b/keystore2/src/key_parameter.rs
@@ -16,15 +16,26 @@
 //! and enforced by the OEMs. This module implements the internal representation of KeyParameter
 //! and the methods to work with KeyParameter.
 
-use crate::keymint_definitions::{
-    Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyBlobUsageRequirements,
-    KeyOrigin, KeyPurpose, PaddingMode, SecurityLevel, Tag,
+use crate::error::Error as KeystoreError;
+use crate::error::Rc;
+pub use android_hardware_keymint::aidl::android::hardware::keymint::{
+    Algorithm, Algorithm::Algorithm as AlgorithmType, BlockMode,
+    BlockMode::BlockMode as BlockModeType, Digest, Digest::Digest as DigestType, EcCurve,
+    EcCurve::EcCurve as EcCurveType, HardwareAuthenticatorType,
+    HardwareAuthenticatorType::HardwareAuthenticatorType as HardwareAuthenticatorTypeType,
+    KeyOrigin, KeyOrigin::KeyOrigin as KeyOriginType, KeyPurpose,
+    KeyPurpose::KeyPurpose as KeyPurposeType, PaddingMode,
+    PaddingMode::PaddingMode as PaddingModeType, SecurityLevel,
+    SecurityLevel::SecurityLevel as SecurityLevelType, Tag, Tag::Tag as TagType,
 };
+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.
 pub struct KeyParameter {
     key_parameter_value: KeyParameterValue,
-    security_level: SecurityLevel,
+    security_level: SecurityLevelType,
 }
 
 /// KeyParameterValue holds a value corresponding to one of the Tags defined in
@@ -34,55 +45,55 @@
     /// Associated with Tag:INVALID
     Invalid,
     /// Set of purposes for which the key may be used
-    KeyPurpose(KeyPurpose),
+    KeyPurpose(KeyPurposeType),
     /// Cryptographic algorithm with which the key is used
-    Algorithm(Algorithm),
+    Algorithm(AlgorithmType),
     /// Size of the key , in bits
-    KeySize(u32),
+    KeySize(i32),
     /// Block cipher mode(s) with which the key may be used
-    BlockMode(BlockMode),
+    BlockMode(BlockModeType),
     /// Digest algorithms that may be used with the key to perform signing and verification
-    Digest(Digest),
+    Digest(DigestType),
     /// Padding modes that may be used with the key.  Relevant to RSA, AES and 3DES keys.
-    PaddingMode(PaddingMode),
+    PaddingMode(PaddingModeType),
     /// 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(u32),
+    MinMacLength(i32),
     /// The elliptic curve
-    EcCurve(EcCurve),
+    EcCurve(EcCurveType),
     /// Value of the public exponent for an RSA key pair
-    RSAPublicExponent(u64),
+    RSAPublicExponent(i64),
     /// An attestation certificate for the generated key should contain an application-scoped
     /// and time-bounded device-unique ID
     IncludeUniqueID,
-    /// Necessary system environment conditions for the generated key to be used
-    KeyBlobUsageRequirements(KeyBlobUsageRequirements),
+    //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,
-    //TODO: HARDWARE_TYPE reserved for future use
     /// The date and time at which the key becomes active
-    ActiveDateTime(u64),
+    ActiveDateTime(i64),
     /// The date and time at which the key expires for signing and encryption
-    OriginationExpireDateTime(u64),
+    OriginationExpireDateTime(i64),
     /// The date and time at which the key expires for verification and decryption
-    UsageExpireDateTime(u64),
+    UsageExpireDateTime(i64),
     /// Minimum amount of time that elapses between allowed operations
-    MinSecondsBetweenOps(u32),
+    MinSecondsBetweenOps(i32),
     /// Maximum number of times that a key may be used between system reboots
-    MaxUsesPerBoot(u32),
+    MaxUsesPerBoot(i32),
     /// ID of the Android user that is permitted to use the key
-    UserID(u32),
+    UserID(i32),
     /// A key may only be used under a particular secure user authentication state
-    UserSecureID(u64),
+    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),
+    HardwareAuthenticatorType(HardwareAuthenticatorTypeType),
     /// The time in seconds for which the key is authorized for use, after user authentication
-    AuthTimeout(u32),
+    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
@@ -99,15 +110,15 @@
     /// that is necessary during all uses of the key
     ApplicationData(Vec<u8>),
     /// Specifies the date and time the key was created
-    CreationDateTime(u64),
+    CreationDateTime(i64),
     /// Specifies where the key was created, if known
-    KeyOrigin(KeyOrigin),
+    KeyOrigin(KeyOriginType),
     /// 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(u32),
+    OSVersion(i32),
     /// Specifies the system security patch level with which the key may be used
-    OSPatchLevel(u32),
+    OSPatchLevel(i32),
     /// Specifies a unique, time-based identifier
     UniqueID(Vec<u8>),
     /// Used to deliver a "challenge" value to the attestKey() method
@@ -131,16 +142,16 @@
     /// 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(u32),
+    VendorPatchLevel(i32),
     /// Specifies the boot image (kernel) security patch level with which the key may be used
-    BootPatchLevel(u32),
+    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(u32),
+    MacLength(i32),
     /// Specifies whether the device has been factory reset since the
     /// last unique ID rotation.  Used for key attestation
     ResetSinceIdRotation,
@@ -151,12 +162,12 @@
 
 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 {
+    pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevelType) -> Self {
         KeyParameter { key_parameter_value, security_level }
     }
 
     /// Returns the tag given the KeyParameter instance.
-    pub fn get_tag(&self) -> Tag {
+    pub fn get_tag(&self) -> TagType {
         match self.key_parameter_value {
             KeyParameterValue::Invalid => Tag::INVALID,
             KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
@@ -170,7 +181,6 @@
             KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
             KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
             KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
-            KeyParameterValue::KeyBlobUsageRequirements(_) => Tag::BLOB_USAGE_REQUIREMENTS,
             KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
             KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
             KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
@@ -221,7 +231,7 @@
     }
 
     /// Returns the security level of a KeyParameter.
-    pub fn security_level(&self) -> &SecurityLevel {
+    pub fn security_level(&self) -> &SecurityLevelType {
         &self.security_level
     }
 }
@@ -229,7 +239,6 @@
 #[cfg(test)]
 mod basic_tests {
     use crate::key_parameter::*;
-    use crate::keymint_definitions::{SecurityLevel, Tag};
 
     // Test basic functionality of KeyParameter.
     #[test]
@@ -249,3 +258,617 @@
         assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
     }
 }
+
+/// 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> {
+    /// 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 as u32)),
+            KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(*a as u32)),
+            KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
+            KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(*b as u32)),
+            KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(*d as u32)),
+            KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(*p as u32)),
+            KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
+            KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
+            KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(*e 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 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 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: TagType,
+        data: &SqlField,
+        security_level_val: SecurityLevelType,
+    ) -> Result<Self> {
+        let key_param_value = match tag_val {
+            Tag::INVALID => KeyParameterValue::Invalid,
+            Tag::PURPOSE => {
+                let key_purpose: KeyPurposeType = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .context("Failed to read sql data for tag: PURPOSE.")?;
+                KeyParameterValue::KeyPurpose(key_purpose)
+            }
+            Tag::ALGORITHM => {
+                let algorithm: AlgorithmType = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .context("Failed to read sql data for tag: ALGORITHM.")?;
+                KeyParameterValue::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: BlockModeType = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .context("Failed to read sql data for tag: BLOCK_MODE.")?;
+                KeyParameterValue::BlockMode(block_mode)
+            }
+            Tag::DIGEST => {
+                let digest: DigestType = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .context("Failed to read sql data for tag: DIGEST.")?;
+                KeyParameterValue::Digest(digest)
+            }
+            Tag::PADDING => {
+                let padding: PaddingModeType = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .context("Failed to read sql data for tag: PADDING.")?;
+                KeyParameterValue::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: EcCurveType = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .context("Failed to read sql data for tag: EC_CURVE.")?;
+                KeyParameterValue::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: HardwareAuthenticatorTypeType = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
+                KeyParameterValue::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: KeyOriginType = data
+                    .get()
+                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .context("Failed to read sql data for tag: ORIGIN.")?;
+                KeyParameterValue::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(Rc::ValueCorrupted))
+                    .context("Failed to decode Tag enum from value.")?
+            }
+        };
+        Ok(KeyParameter::new(key_param_value, security_level_val))
+    }
+}
+
+/// 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,
+            &Algorithm::RSA,
+            SecurityLevel::STRONGBOX,
+        )?;
+        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, &1024, SecurityLevel::STRONGBOX)?;
+        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,
+            &(i64::MAX),
+            SecurityLevel::STRONGBOX,
+        )?;
+        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, &Null, SecurityLevel::STRONGBOX)?;
+        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,
+            &app_id_bytes,
+            SecurityLevel::STRONGBOX,
+        )?;
+        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, &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(), kp.key_parameter_value(), kp.security_level()],
+        )?;
+        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(row.get(0)?, &SqlField(1, row), row.get(2)?)?)
+    }
+}
diff --git a/keystore2/src/keymint_definitions.rs b/keystore2/src/keymint_definitions.rs
deleted file mode 100644
index 2658a01..0000000
--- a/keystore2/src/keymint_definitions.rs
+++ /dev/null
@@ -1,177 +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(non_camel_case_types)]
-#![allow(missing_docs)]
-
-/// This is the current interface for the code to-be-generated from the keymint AIDL.
-/// The AIDL spec is at" hardware/interfaces/keymint
-#[repr(u32)]
-#[derive(PartialEq, Debug)]
-pub enum TagType {
-    INVALID = 0 << 28,
-    ENUM = 1 << 28,
-    ENUM_REP = 2 << 28,
-    UINT = 3 << 28,
-    UINT_REP = 4 << 28,
-    ULONG = 5 << 28,
-    DATE = 6 << 28,
-    BOOL = 7 << 28,
-    BIGNUM = 8 << 28,
-    BYTES = 9 << 28,
-    ULONG_REP = 10 << 28,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum Tag {
-    INVALID = TagType::INVALID as u32,
-    PURPOSE = TagType::ENUM_REP as u32 | 1,
-    ALGORITHM = TagType::ENUM as u32 | 2,
-    KEY_SIZE = TagType::UINT as u32 | 3,
-    BLOCK_MODE = TagType::ENUM_REP as u32 | 4,
-    DIGEST = TagType::ENUM_REP as u32 | 5,
-    PADDING = TagType::ENUM_REP as u32 | 6,
-    CALLER_NONCE = TagType::BOOL as u32 | 7,
-    MIN_MAC_LENGTH = TagType::UINT as u32 | 8,
-    EC_CURVE = TagType::ENUM as u32 | 10,
-    RSA_PUBLIC_EXPONENT = TagType::ULONG as u32 | 200,
-    INCLUDE_UNIQUE_ID = TagType::BOOL as u32 | 202,
-    BLOB_USAGE_REQUIREMENTS = TagType::ENUM as u32 | 301,
-    BOOTLOADER_ONLY = TagType::BOOL as u32 | 302,
-    ROLLBACK_RESISTANCE = TagType::BOOL as u32 | 303,
-    ACTIVE_DATETIME = TagType::DATE as u32 | 400,
-    ORIGINATION_EXPIRE_DATETIME = TagType::DATE as u32 | 401,
-    USAGE_EXPIRE_DATETIME = TagType::DATE as u32 | 402,
-    MIN_SECONDS_BETWEEN_OPS = TagType::UINT as u32 | 403,
-    MAX_USES_PER_BOOT = TagType::UINT as u32 | 404,
-    USER_ID = TagType::UINT as u32 | 501,
-    USER_SECURE_ID = TagType::ULONG_REP as u32 | 502,
-    NO_AUTH_REQUIRED = TagType::BOOL as u32 | 503,
-    USER_AUTH_TYPE = TagType::ENUM as u32 | 504,
-    AUTH_TIMEOUT = TagType::UINT as u32 | 505,
-    ALLOW_WHILE_ON_BODY = TagType::BOOL as u32 | 506,
-    TRUSTED_USER_PRESENCE_REQUIRED = TagType::BOOL as u32 | 507,
-    TRUSTED_CONFIRMATION_REQUIRED = TagType::BOOL as u32 | 508,
-    UNLOCKED_DEVICE_REQUIRED = TagType::BOOL as u32 | 509,
-    APPLICATION_ID = TagType::BYTES as u32 | 601,
-    APPLICATION_DATA = TagType::BYTES as u32 | 700,
-    CREATION_DATETIME = TagType::DATE as u32 | 701,
-    ORIGIN = TagType::ENUM as u32 | 702,
-    ROOT_OF_TRUST = TagType::BYTES as u32 | 704,
-    OS_VERSION = TagType::UINT as u32 | 705,
-    OS_PATCHLEVEL = TagType::UINT as u32 | 706,
-    UNIQUE_ID = TagType::BYTES as u32 | 707,
-    ATTESTATION_CHALLENGE = TagType::BYTES as u32 | 708,
-    ATTESTATION_APPLICATION_ID = TagType::BYTES as u32 | 709,
-    ATTESTATION_ID_BRAND = TagType::BYTES as u32 | 710,
-    ATTESTATION_ID_DEVICE = TagType::BYTES as u32 | 711,
-    ATTESTATION_ID_PRODUCT = TagType::BYTES as u32 | 712,
-    ATTESTATION_ID_SERIAL = TagType::BYTES as u32 | 713,
-    ATTESTATION_ID_IMEI = TagType::BYTES as u32 | 714,
-    ATTESTATION_ID_MEID = TagType::BYTES as u32 | 715,
-    ATTESTATION_ID_MANUFACTURER = TagType::BYTES as u32 | 716,
-    ATTESTATION_ID_MODEL = TagType::BYTES as u32 | 717,
-    VENDOR_PATCHLEVEL = TagType::UINT as u32 | 718,
-    BOOT_PATCHLEVEL = TagType::UINT as u32 | 719,
-    ASSOCIATED_DATA = TagType::BYTES as u32 | 1000,
-    NONCE = TagType::BYTES as u32 | 1001,
-    MAC_LENGTH = TagType::UINT as u32 | 1003,
-    RESET_SINCE_ID_ROTATION = TagType::BOOL as u32 | 1004,
-    CONFIRMATION_TOKEN = TagType::BYTES as u32 | 1005,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum Algorithm {
-    RSA = 1,
-    EC = 3,
-    AES = 32,
-    TRIPLE_DES = 33,
-    HMAC = 128,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum BlockMode {
-    ECB = 1,
-    CBC = 2,
-    CTR = 3,
-    GCM = 32,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum PaddingMode {
-    NONE = 1,
-    RSA_OAEP = 2,
-    RSA_PSS = 3,
-    RSA_PKCS1_1_5_ENCRYPT = 4,
-    RSA_PKCS1_1_5_SIGN = 5,
-    PKCS7 = 64,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum Digest {
-    NONE = 0,
-    MD5 = 1,
-    SHA1 = 2,
-    SHA_2_224 = 3,
-    SHA_2_256 = 4,
-    SHA_2_384 = 5,
-    SHA_2_512 = 6,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum EcCurve {
-    P_224 = 0,
-    P_256 = 1,
-    P_384 = 2,
-    P_521 = 3,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum KeyOrigin {
-    GENERATED = 0,
-    DERIVED = 1,
-    IMPORTED = 2,
-    UNKNOWN = 3,
-    SECURELY_IMPORTED = 4,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum KeyBlobUsageRequirements {
-    STANDALONE = 0,
-    REQUIRES_FILE_SYSTEM = 1,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum KeyPurpose {
-    ENCRYPT = 0,
-    DECRYPT = 1,
-    SIGN = 2,
-    VERIFY = 3,
-    WRAP_KEY = 5,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum HardwareAuthenticatorType {
-    NONE = 0,
-    PASSWORD = 1,
-    FINGERPRINT = 1 << 1,
-    ANY = (0xFFFFFFFF as u32) as u32,
-}
-#[repr(u32)]
-#[derive(PartialEq, Debug, Copy, Clone)]
-pub enum SecurityLevel {
-    SOFTWARE = 0,
-    TRUSTED_ENVIRONMENT = 1,
-    STRONGBOX = 2,
-}
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
index 13ef87d..b5fef3e 100644
--- a/keystore2/src/lib.rs
+++ b/keystore2/src/lib.rs
@@ -18,6 +18,4 @@
 pub mod error;
 /// Internal Representation of Key Parameter and convenience functions.
 pub mod key_parameter;
-/// Internal interface for the code to-be-generated from the keymint AIDL
-pub mod keymint_definitions;
 pub mod permission;
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
index 0db56dd..df59484 100644
--- a/keystore2/src/permission.rs
+++ b/keystore2/src/permission.rs
@@ -18,10 +18,13 @@
 //! It also provides KeystorePerm and KeyPerm as convenience wrappers for the SELinux permission
 //! defined by keystore2 and keystore2_key respectively.
 
-use keystore_aidl_generated as aidl;
+use android_security_keystore2::aidl::android::security::keystore2::KeyPermission;
+
+use android_security_keystore2::aidl::android::security::keystore2::KeyDescriptor::KeyDescriptor;
 
 use std::cmp::PartialEq;
 use std::convert::From;
+use std::ffi::CStr;
 
 use crate::error::Error as KsError;
 use keystore2_selinux as selinux;
@@ -49,17 +52,25 @@
     KEYSTORE2_KEY_LABEL_BACKEND.lookup(&namespace.to_string())
 }
 
-/// The below example wraps the enum MyPermission in the tuple struct `MyPerm` and implements
-///  * `From<i32> for `MyPerm`, where each unknown numeric value is mapped to the given default,
-///    here `None`
-///  * `Into<MyPermission> for `MyPerm`
-///  * `MyPerm::foo()` and `MyPerm::bar()` which construct MyPerm instances representing
-///    `MyPermission::Foo` and `MyPermission::Bar` respectively.
-///  * `MyPerm.to_selinux(&self)`, which returns the selinux string representation of the
+/// ## 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.
-///  * Tests in the given test namespace for each permision that check that the numeric
-///    representations of MyPermission and MyPerm match. (TODO replace with static assert if
-///    they become available.)
 ///
 /// ## Special behavior
 /// If the keyword `use` appears as an selinux name `use_` is used as identifier for the
@@ -68,85 +79,78 @@
 ///
 /// ## Example
 /// ```
-/// #[i32]
-/// enum MyPermission {
-///     None = 0,
-///     Foo = 1,
-///     Bar = 2,
-/// }
 ///
 /// implement_permission!(
 ///     /// MyPerm documentation.
 ///     #[derive(Clone, Copy, Debug, PartialEq)]
-///     MyPermission as MyPerm with default (None = 0, none)
-///     and test namespace my_perm_tests {
-///         Foo = 1,           selinux name: foo;
-///         Bar = 2,           selinux name: bar;
+///     MyPerm from EnumName with default (None, none) {}
+///         Variant1,    selinux name: variant1;
+///         Variant2,    selinux name: variant1;
 ///     }
 /// );
 /// ```
-macro_rules! implement_permission {
+macro_rules! implement_permission_aidl {
     // This rule provides the public interface of the macro. And starts the preprocessing
     // recursion (see below).
-    ($(#[$m:meta])* $t:ty as $name:ident with default ($($def:tt)*)
-        and test namespace $tn:ident { $($element:tt)* })
+    ($(#[$m:meta])* $name:ident from $aidl_name:ident with default ($($def:tt)*)
+        { $($element:tt)* })
     => {
-        implement_permission!(@replace_use $($m)*, $t, $name, $tn, ($($def)*), [] , $($element)*);
+        implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*), [],
+            $($element)*);
     };
 
-
     // The following three rules recurse through the elements of the form
-    // `<enum variant> = <integer_literal>, selinux name: <selinux_name>;`
+    // `<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)*, $t:ty, $name:ident, $tn:ident, ($($def:tt)*), [$($out:tt)*], ) => {
-        implement_permission!(@end $($m)*, $t, $name, $tn, ($($def)*) { $($out)* } );
+    (@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> = <integer_literal>, use_, use;`
+    // It produces the tuple `<enum variant>, use_, use;`
     // and appends it to the out list.
-    (@replace_use $($m:meta)*, $t:ty, $name:ident, $tn:ident, ($($def:tt)*), [$($out:tt)*],
-        $e_name:ident = $e_val:expr, selinux name: use; $($element:tt)*)
+    (@replace_use $($m:meta)*, $name:ident, $aidl_name:ident, ($($def:tt)*), [$($out:tt)*],
+        $e_name:ident, selinux name: use; $($element:tt)*)
     => {
-        implement_permission!(@replace_use $($m)*, $t, $name, $tn, ($($def)*),
-                              [$($out)* $e_name = $e_val, use_, use;], $($element)*);
+        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> = <integer_literal>, <selinux_name>, <selinux_name>;`
+    // `<enum variant>, <selinux_name>, <selinux_name>;`
     // and appends the result to the out list.
-    (@replace_use $($m:meta)*, $t:ty, $name:ident, $tn:ident, ($($def:tt)*), [$($out:tt)*],
-        $e_name:ident = $e_val:expr, selinux name: $e_str:ident; $($element:tt)*)
+    (@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!(@replace_use $($m)*, $t, $name, $tn, ($($def)*),
-                              [$($out)* $e_name = $e_val, $e_str, $e_str;], $($element)*);
+        implement_permission_aidl!(@replace_use $($m)*, $name, $aidl_name, ($($def)*),
+                              [$($out)* $e_name, $e_str, $e_str;], $($element)*);
     };
 
-    (@end $($m:meta)*, $t:ty, $name:ident, $tn:ident,
-        ($def_name:ident = $def:expr, $def_selinux_name:ident) {
-            $($element_name:ident = $element_val:expr, $element_identifier:ident,
+    (@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($t);
+        pub struct $name(pub $aidl_name::$aidl_name);
 
-        impl From<i32> for $name {
-            fn from (p: i32) -> Self {
+        impl From<$aidl_name::$aidl_name> for $name {
+            fn from (p: $aidl_name::$aidl_name) -> Self {
                 match p {
-                    $def => Self(<$t>::$def_name),
-                    $($element_val => Self(<$t>::$element_name),)*
-                    _ => Self(<$t>::$def_name),
+                    $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<$t> for $name {
-            fn into(self) -> $t {
+        impl Into<$aidl_name::$aidl_name> for $name {
+            fn into(self) -> $aidl_name::$aidl_name {
                 self.0
             }
         }
@@ -156,39 +160,23 @@
             /// `selinux::check_access`.
             pub fn to_selinux(&self) -> &'static str {
                 match self {
-                    Self(<$t>::$def_name) => stringify!($def_selinux_name),
-                    $(Self(<$t>::$element_name) => stringify!($selinux_name),)*
+                    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(<$t>::$def_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(<$t>::$element_name) }
-             )*
-        }
-        #[cfg(test)]
-        mod $tn {
-            use super::*;
-
-            #[test]
-            fn $def_selinux_name() {
-                assert_eq!($name::$def_selinux_name(), (<$t>::$def_name as i32).into());
-            }
-            $(
-                #[test]
-                fn $element_identifier() {
-                    assert_eq!($name::$element_identifier(), (<$t>::$element_name as i32).into());
-                }
+                pub const fn $element_identifier() -> Self { Self($aidl_name::$element_name) }
             )*
         }
     };
-
-
 }
 
-implement_permission!(
+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
@@ -204,56 +192,113 @@
     ///                       KeyPerm::get_info().to_selinux());
     /// ```
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-    aidl::KeyPermission as KeyPerm with default (None = 0, none)
-    and test namespace key_perm_tests {
-        Delete = 1,         selinux name: delete;
-        GenUniqueId = 2,    selinux name: gen_unique_id;
-        GetInfo = 4,        selinux name: get_info;
-        Grant = 8,          selinux name: grant;
-        List = 0x10,        selinux name: list;
-        ManageBlob = 0x20,  selinux name: manage_blob;
-        Rebind = 0x40,      selinux name: rebind;
-        ReqForcedOp = 0x80, selinux name: req_forced_op;
-        Update = 0x100,     selinux name: update;
-        Use = 0x200,        selinux name: use;
-        UseDevId = 0x400,   selinux name: use_dev_id;
+    KeyPerm from KeyPermission with default (None, none) {
+        Delete,         selinux name: delete;
+        GenUniqueId,    selinux name: gen_unique_id;
+        GetInfo,        selinux name: get_info;
+        Grant,          selinux name: grant;
+        List,           selinux name: list;
+        ManageBlob,     selinux name: manage_blob;
+        Rebind,         selinux name: rebind;
+        ReqForcedOp,    selinux name: req_forced_op;
+        Update,         selinux name: update;
+        Use,            selinux name: use;
+        UseDevId,       selinux name: use_dev_id;
     }
 );
 
-/// KeystorePermission defines values for the SELinux `keystore2` security class.
-/// Countrary to `KeyPermission`, this enum is not generated by AIDL and need not be
-/// wrapped by newtype pattern. But we conveniently use the implement_permission macro
-/// to provide the same feature that we did for `KeyPermission` to this set of permissions.
-#[repr(i32)]
-#[derive(Debug, Clone, Copy, Eq, PartialEq)]
-pub enum KeystorePermission {
-    /// `None` is not a permission that can ever be granted. It is not known to the SEPolicy.
-    None = 0,
-    /// Checked when a new auth token is installed.
-    AddAuth = 1,
-    /// Checked when an app is uninstalled or wiped.
-    ClearNs = 2,
-    /// Checked when the locked state of Keystore 2.0 is queried.
-    GetState = 4,
-    /// Checked when Keystore 2.0 gets locked.
-    Lock = 8,
-    /// Checked when Keystore 2.0 shall be reset.
-    Reset = 0x10,
-    /// Checked when Keystore 2.0 shall be unlocked.
-    Unlock = 0x20,
+/// 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)]
-    KeystorePermission as KeystorePerm with default (None = 0, none)
-    and test namespace keystore_perm_tests {
+    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 gets locked.
         Lock = 8,       selinux name: lock;
+        /// Checked when Keystore 2.0 shall be reset.
         Reset = 0x10,   selinux name: reset;
+        /// Checked when Keystore 2.0 shall be unlocked.
         Unlock = 0x20,  selinux name: unlock;
     }
 );
@@ -281,8 +326,8 @@
 /// assert_eq(Some(KeyPerm::use_()), i.next());
 /// assert_eq(None, i.next());
 /// ```
-#[derive(Copy, Clone)]
-pub struct KeyPermSet(i32);
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub struct KeyPermSet(pub i32);
 
 mod perm {
     use super::*;
@@ -322,9 +367,22 @@
     }
 }
 
+/// 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`.
-    fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
+    pub fn includes<T: Into<KeyPermSet>>(&self, other: T) -> bool {
         let o: KeyPermSet = other.into();
         (self.0 & o.0) == o.0
     }
@@ -355,10 +413,7 @@
 
 /// 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: &selinux::Context,
-    perm: KeystorePerm,
-) -> anyhow::Result<()> {
+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())
 }
@@ -377,11 +432,11 @@
 ///                      SELinux keystore key backend, and the result is used
 ///                      as target context.
 pub fn check_grant_permission(
-    caller_ctx: &selinux::Context,
+    caller_ctx: &CStr,
     access_vec: KeyPermSet,
-    key: &aidl::KeyDescriptor,
+    key: &KeyDescriptor,
 ) -> anyhow::Result<()> {
-    use aidl::Domain;
+    use android_security_keystore2::aidl::android::security::keystore2::Domain;
 
     let target_context = match key.domain {
         Domain::App => getcon().context("check_grant_permission: getcon failed.")?,
@@ -427,12 +482,12 @@
 ///                      was supplied. It is also produced if `Domain::KeyId` was selected, and
 ///                      on various unexpected backend failures.
 pub fn check_key_permission(
-    caller_ctx: &selinux::Context,
+    caller_ctx: &CStr,
     perm: KeyPerm,
-    key: &aidl::KeyDescriptor,
+    key: &KeyDescriptor,
     access_vector: &Option<KeyPermSet>,
 ) -> anyhow::Result<()> {
-    use aidl::Domain;
+    use android_security_keystore2::aidl::android::security::keystore2::Domain;
 
     let target_context = match key.domain {
         // apps get the default keystore context
@@ -477,6 +532,10 @@
 
             tctx
         }
+        _ => {
+            return Err(KsError::sys())
+                .context(format!("Unknown domain value: \"{}\".", key.domain))
+        }
     };
 
     selinux::check_access(caller_ctx, &target_context, "keystore2_key", perm.to_selinux())
@@ -488,7 +547,6 @@
     use anyhow::anyhow;
     use anyhow::Result;
     use keystore2_selinux::*;
-    use keystore_aidl_generated as aidl;
 
     const ALL_PERMS: KeyPermSet = key_perm_set![
         KeyPerm::manage_blob(),
@@ -591,9 +649,8 @@
     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")?;
-        use aidl::Domain;
-        let key =
-            aidl::KeyDescriptor { domain: Domain::App, namespace_: 0, alias: None, blob: None };
+        use android_security_keystore2::aidl::android::security::keystore2::Domain;
+        let key = KeyDescriptor { domain: Domain::App, namespace_: 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.
 
@@ -609,9 +666,9 @@
 
     #[test]
     fn check_grant_permission_selinux() -> Result<()> {
-        use aidl::Domain;
+        use android_security_keystore2::aidl::android::security::keystore2::Domain;
         let (sctx, namespace, is_su) = check_context()?;
-        let key = aidl::KeyDescriptor {
+        let key = KeyDescriptor {
             domain: Domain::SELinux,
             namespace_: namespace as i64,
             alias: None,
@@ -630,9 +687,8 @@
 
     #[test]
     fn check_key_permission_domain_grant() -> Result<()> {
-        use aidl::Domain;
-        let key =
-            aidl::KeyDescriptor { domain: Domain::Grant, namespace_: 0, alias: None, blob: None };
+        use android_security_keystore2::aidl::android::security::keystore2::Domain;
+        let key = KeyDescriptor { domain: Domain::Grant, namespace_: 0, alias: None, blob: None };
 
         assert_perm_failed!(check_key_permission(
             &selinux::Context::new("ignored").unwrap(),
@@ -654,10 +710,9 @@
         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")?;
-        use aidl::Domain;
+        use android_security_keystore2::aidl::android::security::keystore2::Domain;
 
-        let key =
-            aidl::KeyDescriptor { domain: Domain::App, namespace_: 0, alias: None, blob: None };
+        let key = KeyDescriptor { domain: Domain::App, namespace_: 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());
@@ -698,9 +753,9 @@
 
     #[test]
     fn check_key_permission_domain_selinux() -> Result<()> {
-        use aidl::Domain;
+        use android_security_keystore2::aidl::android::security::keystore2::Domain;
         let (sctx, namespace, is_su) = check_context()?;
-        let key = aidl::KeyDescriptor {
+        let key = KeyDescriptor {
             domain: Domain::SELinux,
             namespace_: namespace as i64,
             alias: None,
@@ -737,9 +792,9 @@
 
     #[test]
     fn check_key_permission_domain_blob() -> Result<()> {
-        use aidl::Domain;
+        use android_security_keystore2::aidl::android::security::keystore2::Domain;
         let (sctx, namespace, is_su) = check_context()?;
-        let key = aidl::KeyDescriptor {
+        let key = KeyDescriptor {
             domain: Domain::Blob,
             namespace_: namespace as i64,
             alias: None,
@@ -756,9 +811,8 @@
 
     #[test]
     fn check_key_permission_domain_key_id() -> Result<()> {
-        use aidl::Domain;
-        let key =
-            aidl::KeyDescriptor { domain: Domain::KeyId, namespace_: 0, alias: None, blob: None };
+        use android_security_keystore2::aidl::android::security::keystore2::Domain;
+        let key = KeyDescriptor { domain: Domain::KeyId, namespace_: 0, alias: None, blob: None };
 
         assert_eq!(
             Some(&KsError::sys()),