Merge "Use shared libutils instead of static for keystore fuzzers"
diff --git a/diced/src/lib.rs b/diced/src/lib.rs
index 9594977..50e0e96 100644
--- a/diced/src/lib.rs
+++ b/diced/src/lib.rs
@@ -100,7 +100,7 @@
     Ok(BinderInputValues {
         codeHash: [0; dice::HASH_SIZE],
         config: BinderConfig {
-            desc: dice::bcc::format_config_descriptor(Some(&format!("{}", uid)), None, true)
+            desc: dice::bcc::format_config_descriptor(Some(&format!("{}", uid)), None, false)
                 .context("In client_input_values: failed to format config descriptor")?,
         },
         authorityHash: [0; dice::HASH_SIZE],
diff --git a/keystore/tests/confirmationui_invocation_test.cpp b/keystore/tests/confirmationui_invocation_test.cpp
index 7f8a373..822e6a4 100644
--- a/keystore/tests/confirmationui_invocation_test.cpp
+++ b/keystore/tests/confirmationui_invocation_test.cpp
@@ -55,7 +55,7 @@
     std::string locale("en");
     std::vector<uint8_t> extraData{0xaa, 0xff, 0x00, 0x55};
 
-    auto listener = std::make_shared<ConfirmationListener>();
+    auto listener = ndk::SharedRefBase::make<ConfirmationListener>();
 
     auto future = listener->get_future();
 
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index 2027af4..e7c2752 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -79,7 +79,10 @@
     name: "libkeystore2_test_utils",
     crate_name: "keystore2_test_utils",
     srcs: ["test_utils/lib.rs"],
+    defaults: ["keymint_use_latest_hal_aidl_rust"],
     rustlibs: [
+        "android.system.keystore2-V2-rust",
+        "libbinder_rs",
         "libkeystore2_selinux",
         "liblog_rust",
         "libnix",
@@ -89,14 +92,30 @@
     ],
 }
 
+rust_library {
+    name: "libkeystore2_with_test_utils",
+    defaults: ["libkeystore2_defaults"],
+    features: [
+        "keystore2_blob_test_utils",
+    ],
+    rustlibs: [
+        "liblibsqlite3_sys",
+        "librusqlite",
+        "libkeystore2_test_utils",
+    ],
+}
+
 rust_test {
     name: "keystore2_test_utils_test",
     srcs: ["test_utils/lib.rs"],
+    defaults: ["keymint_use_latest_hal_aidl_rust"],
     test_suites: ["general-tests"],
     require_root: true,
     auto_gen_config: true,
     compile_multilib: "first",
     rustlibs: [
+        "android.system.keystore2-V2-rust",
+        "libbinder_rs",
         "libkeystore2_selinux",
         "liblog_rust",
         "libnix",
@@ -119,10 +138,12 @@
         "liblibsqlite3_sys",
         "libnix",
         "librusqlite",
+        "libkeystore2_with_test_utils",
     ],
     // The test should always include watchdog.
     features: [
         "watchdog",
+        "keystore2_blob_test_utils",
     ],
 }
 
diff --git a/keystore2/TEST_MAPPING b/keystore2/TEST_MAPPING
index 049adc7..5d0a7dd 100644
--- a/keystore2/TEST_MAPPING
+++ b/keystore2/TEST_MAPPING
@@ -13,6 +13,9 @@
       "name": "keystore2_test_utils_test"
     },
     {
+      "name": "keystore2_legacy_blobs_test"
+    },
+    {
       "name": "CtsIdentityTestCases"
     },
     {
diff --git a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
index 3df5936..6a37c78 100644
--- a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
+++ b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
@@ -23,15 +23,10 @@
  * user's password.
  * @hide
  */
-@SensitiveData
+ @SensitiveData
 interface IKeystoreMaintenance {
 
     /**
-     * Special value indicating the callers uid.
-     */
-    const int UID_SELF = -1;
-
-    /**
      * Allows LockSettingsService to inform keystore about adding a new user.
      * Callers require 'AddUser' permission.
      *
@@ -120,10 +115,6 @@
      * The source may be specified by Domain::APP, Domain::SELINUX, or Domain::KEY_ID. The target
      * may be specified by Domain::APP or Domain::SELINUX.
      *
-     * If Domain::APP is selected in either source or destination, nspace must be set to UID_SELF,
-     * implying the caller's UID. If the caller has the MIGRATE_ANY_KEY permission, Domain::APP may
-     * be used with other nspace values which then indicates the UID of a different application.
-     *
      * ## Error conditions:
      * `ResponseCode::PERMISSION_DENIED` - If the caller lacks any of the required permissions.
      * `ResponseCode::KEY_NOT_FOUND` - If the source did not exist.
@@ -140,22 +131,4 @@
      * Tag::ROLLBACK_RESISTANCE may or may not be rendered unusable.
      */
     void deleteAllKeys();
-
-    /**
-     * List all entries accessible by the caller in the given `domain` and `nspace`.
-     *
-     * Callers either has to have the `GET_INFO` permission for the requested namespace or `LIST`
-     * permission to list all the entries.
-     *
-     * ## Error conditions
-     * `ResponseCode::INVALID_ARGUMENT` if `domain` is other than `Domain::APP` or `Domain::SELINUX`
-     * `ResponseCode::PERMISSION_DENIED` if the caller does not have the permission
-     *
-     * @param domain `Domain::APP` or `Domain::SELINUX`.
-     *
-     * @param nspace The SELinux keystore2_key namespace.
-     *
-     * @return List of KeyDescriptors.
-     */
-    KeyDescriptor[] listEntries(in Domain domain, in long nspace);
 }
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
index 771d609..9854974 100644
--- a/keystore2/src/key_parameter.rs
+++ b/keystore2/src/key_parameter.rs
@@ -107,6 +107,9 @@
 use anyhow::{Context, Result};
 use rusqlite::types::{Null, ToSql, ToSqlOutput};
 use rusqlite::Result as SqlResult;
+use serde::de::Deserializer;
+use serde::ser::Serializer;
+use serde::{Deserialize, Serialize};
 
 /// This trait is used to associate a primitive to any type that can be stored inside a
 /// KeyParameterValue, especially the AIDL enum types, e.g., keymint::{Algorithm, Digest, ...}.
@@ -121,7 +124,7 @@
 /// there is no wrapped type):
 /// `KeyParameterValue::$vname(<$vtype>::from_primitive(row.get(0)))`
 trait AssociatePrimitive {
-    type Primitive;
+    type Primitive: Into<Primitive> + TryFrom<Primitive>;
 
     fn from_primitive(v: Self::Primitive) -> Self;
     fn to_primitive(&self) -> Self::Primitive;
@@ -177,6 +180,7 @@
 /// This enum allows passing a primitive value to `KeyParameterValue::new_from_tag_primitive_pair`
 /// Usually, it is not necessary to use this type directly because the function uses
 /// `Into<Primitive>` as a trait bound.
+#[derive(Deserialize, Serialize)]
 pub enum Primitive {
     /// Wraps an i64.
     I64(i64),
@@ -213,37 +217,57 @@
     UnknownTag,
 }
 
-impl TryInto<i64> for Primitive {
+impl TryFrom<Primitive> for i64 {
     type Error = PrimitiveError;
 
-    fn try_into(self) -> Result<i64, Self::Error> {
-        match self {
-            Self::I64(v) => Ok(v),
+    fn try_from(p: Primitive) -> Result<i64, Self::Error> {
+        match p {
+            Primitive::I64(v) => Ok(v),
             _ => Err(Self::Error::TypeMismatch),
         }
     }
 }
-impl TryInto<i32> for Primitive {
+impl TryFrom<Primitive> for i32 {
     type Error = PrimitiveError;
 
-    fn try_into(self) -> Result<i32, Self::Error> {
-        match self {
-            Self::I32(v) => Ok(v),
+    fn try_from(p: Primitive) -> Result<i32, Self::Error> {
+        match p {
+            Primitive::I32(v) => Ok(v),
             _ => Err(Self::Error::TypeMismatch),
         }
     }
 }
-impl TryInto<Vec<u8>> for Primitive {
+impl TryFrom<Primitive> for Vec<u8> {
     type Error = PrimitiveError;
 
-    fn try_into(self) -> Result<Vec<u8>, Self::Error> {
-        match self {
-            Self::Vec(v) => Ok(v),
+    fn try_from(p: Primitive) -> Result<Vec<u8>, Self::Error> {
+        match p {
+            Primitive::Vec(v) => Ok(v),
             _ => Err(Self::Error::TypeMismatch),
         }
     }
 }
 
+fn serialize_primitive<S, P>(v: &P, serializer: S) -> Result<S::Ok, S::Error>
+where
+    S: Serializer,
+    P: AssociatePrimitive,
+{
+    let primitive: Primitive = v.to_primitive().into();
+    primitive.serialize(serializer)
+}
+
+fn deserialize_primitive<'de, D, T>(deserializer: D) -> Result<T, D::Error>
+where
+    D: Deserializer<'de>,
+    T: AssociatePrimitive,
+{
+    let primitive: Primitive = serde::de::Deserialize::deserialize(deserializer)?;
+    Ok(T::from_primitive(
+        primitive.try_into().map_err(|_| serde::de::Error::custom("Type Mismatch"))?,
+    ))
+}
+
 /// Expands the list of KeyParameterValue variants as follows:
 ///
 /// Input:
@@ -763,6 +787,14 @@
                     value: KmKeyParameterValue::$field_name(Default::default())}
                 ),*]
             }
+
+            #[cfg(test)]
+            fn make_key_parameter_defaults_vector() -> Vec<KeyParameter> {
+                vec![$(KeyParameter{
+                    value: KeyParameterValue::$vname$((<$vtype as Default>::default()))?,
+                    security_level: SecurityLevel(100),
+                }),*]
+            }
         }
 
         implement_try_from_to_km_parameter!(
@@ -777,27 +809,37 @@
 implement_key_parameter_value! {
 /// KeyParameterValue holds a value corresponding to one of the Tags defined in
 /// the AIDL spec at hardware/interfaces/security/keymint
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize)]
 pub enum KeyParameterValue {
     /// Associated with Tag:INVALID
     #[key_param(tag = INVALID, field = Invalid)]
     Invalid,
     /// Set of purposes for which the key may be used
+    #[serde(deserialize_with = "deserialize_primitive")]
+    #[serde(serialize_with = "serialize_primitive")]
     #[key_param(tag = PURPOSE, field = KeyPurpose)]
     KeyPurpose(KeyPurpose),
     /// Cryptographic algorithm with which the key is used
+    #[serde(deserialize_with = "deserialize_primitive")]
+    #[serde(serialize_with = "serialize_primitive")]
     #[key_param(tag = ALGORITHM, field = Algorithm)]
     Algorithm(Algorithm),
     /// Size of the key , in bits
     #[key_param(tag = KEY_SIZE, field = Integer)]
     KeySize(i32),
     /// Block cipher mode(s) with which the key may be used
+    #[serde(deserialize_with = "deserialize_primitive")]
+    #[serde(serialize_with = "serialize_primitive")]
     #[key_param(tag = BLOCK_MODE, field = BlockMode)]
     BlockMode(BlockMode),
     /// Digest algorithms that may be used with the key to perform signing and verification
+    #[serde(deserialize_with = "deserialize_primitive")]
+    #[serde(serialize_with = "serialize_primitive")]
     #[key_param(tag = DIGEST, field = Digest)]
     Digest(Digest),
     /// Padding modes that may be used with the key.  Relevant to RSA, AES and 3DES keys.
+    #[serde(deserialize_with = "deserialize_primitive")]
+    #[serde(serialize_with = "serialize_primitive")]
     #[key_param(tag = PADDING, field = PaddingMode)]
     PaddingMode(PaddingMode),
     /// Can the caller provide a nonce for nonce-requiring operations
@@ -807,6 +849,8 @@
     #[key_param(tag = MIN_MAC_LENGTH, field = Integer)]
     MinMacLength(i32),
     /// The elliptic curve
+    #[serde(deserialize_with = "deserialize_primitive")]
+    #[serde(serialize_with = "serialize_primitive")]
     #[key_param(tag = EC_CURVE, field = EcCurve)]
     EcCurve(EcCurve),
     /// Value of the public exponent for an RSA key pair
@@ -856,6 +900,8 @@
     #[key_param(tag = NO_AUTH_REQUIRED, field = BoolValue)]
     NoAuthRequired,
     /// The types of user authenticators that may be used to authorize this key
+    #[serde(deserialize_with = "deserialize_primitive")]
+    #[serde(serialize_with = "serialize_primitive")]
     #[key_param(tag = USER_AUTH_TYPE, field = HardwareAuthenticatorType)]
     HardwareAuthenticatorType(HardwareAuthenticatorType),
     /// The time in seconds for which the key is authorized for use, after user authentication
@@ -886,6 +932,8 @@
     #[key_param(tag = CREATION_DATETIME, field = DateTime)]
     CreationDateTime(i64),
     /// Specifies where the key was created, if known
+    #[serde(deserialize_with = "deserialize_primitive")]
+    #[serde(serialize_with = "serialize_primitive")]
     #[key_param(tag = ORIGIN, field = Origin)]
     KeyOrigin(KeyOrigin),
     /// The key used by verified boot to validate the operating system booted
@@ -981,9 +1029,11 @@
 }
 
 /// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
 pub struct KeyParameter {
     value: KeyParameterValue,
+    #[serde(deserialize_with = "deserialize_primitive")]
+    #[serde(serialize_with = "serialize_primitive")]
     security_level: SecurityLevel,
 }
 
@@ -1106,6 +1156,18 @@
     fn key_parameter_value_field_matches_tag_type() {
         check_field_matches_tag_type(&KeyParameterValue::make_field_matches_tag_type_test_vector());
     }
+
+    #[test]
+    fn key_parameter_serialization_test() {
+        let params = KeyParameterValue::make_key_parameter_defaults_vector();
+        let mut out_buffer: Vec<u8> = Default::default();
+        serde_cbor::to_writer(&mut out_buffer, &params)
+            .expect("Failed to serialize key parameters.");
+        let deserialized_params: Vec<KeyParameter> =
+            serde_cbor::from_reader(&mut out_buffer.as_slice())
+                .expect("Failed to deserialize key parameters.");
+        assert_eq!(params, deserialized_params);
+    }
 }
 
 #[cfg(test)]
diff --git a/keystore2/src/legacy_blob.rs b/keystore2/src/legacy_blob.rs
index cbc680d..d75bfd2 100644
--- a/keystore2/src/legacy_blob.rs
+++ b/keystore2/src/legacy_blob.rs
@@ -1387,25 +1387,24 @@
     }
 }
 
-#[cfg(test)]
-mod test {
+/// This module implements utility apis for creating legacy blob files.
+#[cfg(feature = "keystore2_blob_test_utils")]
+pub mod test_utils {
     #![allow(dead_code)]
-    use super::*;
-    use keystore2_crypto::{aes_gcm_decrypt, aes_gcm_encrypt};
-    use rand::Rng;
-    use std::string::FromUtf8Error;
-    mod legacy_blob_test_vectors;
+
+    /// test vectors for legacy key blobs
+    pub mod legacy_blob_test_vectors;
+
     use crate::legacy_blob::blob_types::{
         GENERIC, KEY_CHARACTERISTICS, KEY_CHARACTERISTICS_CACHE, KM_BLOB, SUPER_KEY,
         SUPER_KEY_AES256,
     };
-    use crate::legacy_blob::test::legacy_blob_test_vectors::*;
+    use crate::legacy_blob::*;
     use anyhow::{anyhow, Result};
-    use keystore2_test_utils::TempDir;
+    use keystore2_crypto::{aes_gcm_decrypt, aes_gcm_encrypt};
     use std::convert::TryInto;
     use std::fs::OpenOptions;
     use std::io::Write;
-    use std::ops::Deref;
 
     /// This function takes a blob and synchronizes the encrypted/super encrypted flags
     /// with the blob type for the pairs Generic/EncryptedGeneric,
@@ -1414,7 +1413,7 @@
     /// or flags::ENCRYPTED is set, the payload is encrypted and the corresponding
     /// encrypted variant is returned, and vice versa. All other variants remain untouched
     /// even if flags and BlobValue variant are inconsistent.
-    fn prepare_blob(blob: Blob, key: &[u8]) -> Result<Blob> {
+    pub fn prepare_blob(blob: Blob, key: &[u8]) -> Result<Blob> {
         match blob {
             Blob { value: BlobValue::Generic(data), flags } if blob.is_encrypted() => {
                 let (ciphertext, iv, tag) = aes_gcm_encrypt(&data, key).unwrap();
@@ -1453,7 +1452,8 @@
         }
     }
 
-    struct LegacyBlobHeader {
+    /// Legacy blob header structure.
+    pub struct LegacyBlobHeader {
         version: u8,
         blob_type: u8,
         flags: u8,
@@ -1467,7 +1467,7 @@
     /// version 3. Note that the flags field and the values field may be
     /// inconsistent and could be sanitized by this function. It is intentionally
     /// not done to enable tests to construct malformed blobs.
-    fn write_legacy_blob(out: &mut dyn Write, blob: Blob) -> Result<usize> {
+    pub fn write_legacy_blob(out: &mut dyn Write, blob: Blob) -> Result<usize> {
         let (header, data, salt) = match blob {
             Blob { value: BlobValue::Generic(data), flags } => (
                 LegacyBlobHeader {
@@ -1581,7 +1581,9 @@
         write_legacy_blob_helper(out, &header, &data, salt.as_deref())
     }
 
-    fn write_legacy_blob_helper(
+    /// This function takes LegacyBlobHeader, blob payload and writes it to out as a legacy blob file
+    /// version 3.
+    pub fn write_legacy_blob_helper(
         out: &mut dyn Write,
         header: &LegacyBlobHeader,
         data: &[u8],
@@ -1622,10 +1624,51 @@
         Ok(40 + data.len() + info.map(|v| v.len()).unwrap_or(0))
     }
 
-    fn make_encrypted_characteristics_file<P: AsRef<Path>>(path: P, key: &[u8]) -> Result<()> {
+    /// Create encrypted characteristics file using given key.
+    pub fn make_encrypted_characteristics_file<P: AsRef<Path>>(
+        path: P,
+        key: &[u8],
+        data: &[u8],
+    ) -> Result<()> {
+        let mut file = OpenOptions::new().write(true).create_new(true).open(path).unwrap();
+        let blob =
+            Blob { value: BlobValue::Characteristics(data.to_vec()), flags: flags::ENCRYPTED };
+        let blob = prepare_blob(blob, key).unwrap();
+        write_legacy_blob(&mut file, blob).unwrap();
+        Ok(())
+    }
+
+    /// Create encrypted user certificate file using given key.
+    pub fn make_encrypted_usr_cert_file<P: AsRef<Path>>(
+        path: P,
+        key: &[u8],
+        data: &[u8],
+    ) -> Result<()> {
+        let mut file = OpenOptions::new().write(true).create_new(true).open(path).unwrap();
+        let blob = Blob { value: BlobValue::Generic(data.to_vec()), flags: flags::ENCRYPTED };
+        let blob = prepare_blob(blob, key).unwrap();
+        write_legacy_blob(&mut file, blob).unwrap();
+        Ok(())
+    }
+
+    /// Create encrypted CA certificate file using given key.
+    pub fn make_encrypted_ca_cert_file<P: AsRef<Path>>(
+        path: P,
+        key: &[u8],
+        data: &[u8],
+    ) -> Result<()> {
+        let mut file = OpenOptions::new().write(true).create_new(true).open(path).unwrap();
+        let blob = Blob { value: BlobValue::Generic(data.to_vec()), flags: flags::ENCRYPTED };
+        let blob = prepare_blob(blob, key).unwrap();
+        write_legacy_blob(&mut file, blob).unwrap();
+        Ok(())
+    }
+
+    /// Create encrypted user key file using given key.
+    pub fn make_encrypted_key_file<P: AsRef<Path>>(path: P, key: &[u8], data: &[u8]) -> Result<()> {
         let mut file = OpenOptions::new().write(true).create_new(true).open(path).unwrap();
         let blob = Blob {
-            value: BlobValue::Characteristics(KEY_PARAMETERS.to_vec()),
+            value: BlobValue::Decrypted(ZVec::try_from(data).unwrap()),
             flags: flags::ENCRYPTED,
         };
         let blob = prepare_blob(blob, key).unwrap();
@@ -1633,27 +1676,29 @@
         Ok(())
     }
 
-    fn make_encrypted_usr_cert_file<P: AsRef<Path>>(path: P, key: &[u8]) -> Result<()> {
+    /// Create user or ca cert blob file.
+    pub fn make_cert_blob_file<P: AsRef<Path>>(path: P, data: &[u8]) -> Result<()> {
         let mut file = OpenOptions::new().write(true).create_new(true).open(path).unwrap();
-        let blob = Blob {
-            value: BlobValue::Generic(LOADED_CERT_AUTHBOUND.to_vec()),
-            flags: flags::ENCRYPTED,
-        };
-        let blob = prepare_blob(blob, key).unwrap();
+        let blob = Blob { value: BlobValue::Generic(data.to_vec()), flags: 0 };
+        let blob = prepare_blob(blob, &[]).unwrap();
         write_legacy_blob(&mut file, blob).unwrap();
         Ok(())
     }
+}
 
-    fn make_encrypted_ca_cert_file<P: AsRef<Path>>(path: P, key: &[u8]) -> Result<()> {
-        let mut file = OpenOptions::new().write(true).create_new(true).open(path).unwrap();
-        let blob = Blob {
-            value: BlobValue::Generic(LOADED_CACERT_AUTHBOUND.to_vec()),
-            flags: flags::ENCRYPTED,
-        };
-        let blob = prepare_blob(blob, key).unwrap();
-        write_legacy_blob(&mut file, blob).unwrap();
-        Ok(())
-    }
+#[cfg(test)]
+mod test {
+    #![allow(dead_code)]
+    use super::*;
+    use crate::legacy_blob::test_utils::legacy_blob_test_vectors::*;
+    use crate::legacy_blob::test_utils::*;
+    use anyhow::{anyhow, Result};
+    use keystore2_crypto::aes_gcm_decrypt;
+    use keystore2_test_utils::TempDir;
+    use rand::Rng;
+    use std::convert::TryInto;
+    use std::ops::Deref;
+    use std::string::FromUtf8Error;
 
     #[test]
     fn decode_encode_alias_test() {
@@ -1962,6 +2007,7 @@
         make_encrypted_characteristics_file(
             &*temp_dir.build().push("user_0").push(".10223_chr_USRPKEY_authbound"),
             &super_key,
+            KEY_PARAMETERS,
         )
         .unwrap();
         std::fs::write(
@@ -2053,11 +2099,13 @@
         make_encrypted_usr_cert_file(
             &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
             &super_key,
+            LOADED_CERT_AUTHBOUND,
         )
         .unwrap();
         make_encrypted_ca_cert_file(
             &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
             &super_key,
+            LOADED_CACERT_AUTHBOUND,
         )
         .unwrap();
 
@@ -2139,11 +2187,13 @@
         make_encrypted_usr_cert_file(
             &*temp_dir.build().push("user_0").push("10223_USRCERT_authbound"),
             &super_key,
+            LOADED_CERT_AUTHBOUND,
         )
         .unwrap();
         make_encrypted_ca_cert_file(
             &*temp_dir.build().push("user_0").push("10223_CACERT_authbound"),
             &super_key,
+            LOADED_CACERT_AUTHBOUND,
         )
         .unwrap();
 
diff --git a/keystore2/src/legacy_blob/test/legacy_blob_test_vectors.rs b/keystore2/src/legacy_blob/test_utils/legacy_blob_test_vectors.rs
similarity index 98%
rename from keystore2/src/legacy_blob/test/legacy_blob_test_vectors.rs
rename to keystore2/src/legacy_blob/test_utils/legacy_blob_test_vectors.rs
index 2049ac2..3eecee0 100644
--- a/keystore2/src/legacy_blob/test/legacy_blob_test_vectors.rs
+++ b/keystore2/src/legacy_blob/test_utils/legacy_blob_test_vectors.rs
@@ -20,6 +20,7 @@
     KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
 };
 
+/// Holds Blob structure.
 pub static BLOB: &[u8] = &[
     3, // version
     1, // type
@@ -31,6 +32,7 @@
     0xde, 0xed, 0xbe, 0xef, // payload
 ];
 
+/// Creates LegacyKeyCharacteristics with security level KEYSTORE.
 pub fn structured_test_params() -> LegacyKeyCharacteristics {
     LegacyKeyCharacteristics::File(vec![
         KeyParameter::new(KeyParameterValue::KeyPurpose(KeyPurpose::SIGN), SecurityLevel::KEYSTORE),
@@ -61,6 +63,7 @@
     ])
 }
 
+/// Creates LegacyKeyCharacteristics with security level TRUSTED_ENVIRONMENT.
 pub fn structured_test_params_cache() -> LegacyKeyCharacteristics {
     LegacyKeyCharacteristics::Cache(vec![
         KeyParameter::new(
@@ -117,7 +120,7 @@
     ])
 }
 
-// One encoded list of key parameters.
+/// One encoded list of key parameters.
 pub static KEY_PARAMETERS: &[u8] = &[
     0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20,
     0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x20,
@@ -130,6 +133,7 @@
     0x30, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
 ];
 
+/// Real legacy blob.
 pub static REAL_LEGACY_BLOB: &[u8] = &[
     0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -161,6 +165,7 @@
     0xda, 0x40, 0x2b, 0x75, 0xd0, 0xd2, 0x81, 0x7f, 0xe2, 0x2b, 0xef, 0x64,
 ];
 
+/// Real legacy blob payload.
 pub static REAL_LEGACY_BLOB_PAYLOAD: &[u8] = &[
     0x6c, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x25, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x72, 0x00, 0x00,
     0x00, 0x06, 0x00, 0x80, 0x00, 0x43, 0x00, 0x20, 0x85, 0x42, 0x9e, 0xe9, 0x34, 0x85, 0x2a, 0x00,
@@ -190,11 +195,13 @@
     0xe2, 0x2b, 0xef, 0x64,
 ];
 
+/// AES key blob.
 pub static AES_KEY: &[u8] = &[
     0x48, 0xe4, 0xb5, 0xff, 0xcd, 0x9c, 0x41, 0x1e, 0x20, 0x41, 0xf2, 0x65, 0xa0, 0x4f, 0xf6, 0x57,
     0xc6, 0x58, 0xca, 0xbf, 0x28, 0xa3, 0x01, 0x98, 0x01, 0x76, 0x10, 0xc0, 0x30, 0x4e, 0x35, 0x6e,
 ];
 
+/// AES-GCM encrypted blob.
 pub static AES_GCM_ENCRYPTED_BLOB: &[u8] = &[
     0x03, 0x04, 0x04, 0x00, 0xbd, 0xdb, 0x8d, 0x69, 0x72, 0x56, 0xf0, 0xf5, 0xa4, 0x02, 0x88, 0x7f,
     0x00, 0x00, 0x00, 0x00, 0x50, 0xd9, 0x97, 0x95, 0x37, 0x6e, 0x28, 0x6a, 0x28, 0x9d, 0x51, 0xb9,
@@ -227,6 +234,7 @@
     0x2e, 0x0c, 0xc7, 0xbf, 0x29, 0x1e, 0x31, 0xdc, 0x0e, 0x85, 0x96, 0x7b,
 ];
 
+/// Decrypted payload.
 pub static DECRYPTED_PAYLOAD: &[u8] = &[
     0x7c, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x25, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x72, 0x00, 0x00,
     0x00, 0x06, 0x00, 0x80, 0x00, 0x43, 0x00, 0x20, 0xa4, 0xee, 0xdc, 0x1f, 0x9e, 0xba, 0x42, 0xd6,
@@ -257,6 +265,7 @@
     0xf6, 0x0b, 0x81, 0x07,
 ];
 
+/// Password blob.
 pub static PASSWORD: &[u8] = &[
     0x42, 0x39, 0x30, 0x37, 0x44, 0x37, 0x32, 0x37, 0x39, 0x39, 0x43, 0x42, 0x39, 0x41, 0x42, 0x30,
     0x34, 0x31, 0x30, 0x38, 0x46, 0x44, 0x33, 0x45, 0x39, 0x42, 0x32, 0x38, 0x36, 0x35, 0x41, 0x36,
@@ -264,6 +273,7 @@
     0x32, 0x45, 0x31, 0x35, 0x43, 0x43, 0x46, 0x32, 0x39, 0x36, 0x33, 0x34, 0x31, 0x32, 0x41, 0x39,
 ];
 
+/// Super key blob.
 pub static SUPERKEY: &[u8] = &[
     0x03, 0x07, 0x01, 0x10, 0x9a, 0x81, 0x56, 0x7d, 0xf5, 0x86, 0x7c, 0x62, 0xd7, 0xf9, 0x26, 0x06,
     0x00, 0x00, 0x00, 0x00, 0xde, 0x2a, 0xcb, 0xac, 0x98, 0x57, 0x2b, 0xe5, 0x57, 0x18, 0x78, 0x57,
@@ -273,23 +283,28 @@
     0x94, 0xb6, 0x67, 0x7b, 0x39, 0x85, 0x28, 0x11,
 ];
 
+/// Super key IV.
 pub static SUPERKEY_IV: &[u8] = &[
     0x9a, 0x81, 0x56, 0x7d, 0xf5, 0x86, 0x7c, 0x62, 0xd7, 0xf9, 0x26, 0x06, 0x00, 0x00, 0x00, 0x00,
 ];
 
+/// Super key tag.
 pub static SUPERKEY_TAG: &[u8] = &[
     0xde, 0x2a, 0xcb, 0xac, 0x98, 0x57, 0x2b, 0xe5, 0x57, 0x18, 0x78, 0x57, 0x6e, 0x10, 0x09, 0x84,
 ];
 
+/// Super key salt.
 pub static SUPERKEY_SALT: &[u8] = &[
     0x04, 0x5b, 0xb4, 0x8a, 0x09, 0x22, 0x13, 0x0c, 0x94, 0xb6, 0x67, 0x7b, 0x39, 0x85, 0x28, 0x11,
 ];
 
+/// Super key payload.
 pub static SUPERKEY_PAYLOAD: &[u8] = &[
     0xac, 0x6d, 0x13, 0xe6, 0xad, 0x2c, 0x89, 0x53, 0x1a, 0x99, 0xa5, 0x6c, 0x88, 0xe9, 0xeb, 0x5c,
     0xef, 0x68, 0x5e, 0x5b, 0x53, 0xa8, 0xe7, 0xa2, 0x76, 0x04, 0x2a, 0x48, 0xd1, 0xa7, 0x59, 0xd1,
 ];
 
+/// user key blob.
 pub static USRPKEY_AUTHBOUND: &[u8] = &[
     0x03, 0x04, 0x04, 0x00, 0x1c, 0x34, 0x87, 0x6f, 0xc8, 0x35, 0x0d, 0x34, 0x88, 0x59, 0xbc, 0xf5,
     0x00, 0x00, 0x00, 0x00, 0x62, 0xe3, 0x38, 0x2d, 0xd0, 0x58, 0x40, 0xc1, 0xb0, 0xf2, 0x4a, 0xdd,
@@ -330,14 +345,17 @@
     0x83, 0x42, 0xdd, 0x4e, 0x6d,
 ];
 
+/// Authbound IV.
 pub static USRPKEY_AUTHBOUND_IV: &[u8] = &[
     0x1c, 0x34, 0x87, 0x6f, 0xc8, 0x35, 0x0d, 0x34, 0x88, 0x59, 0xbc, 0xf5, 0x00, 0x00, 0x00, 0x00,
 ];
 
+/// Authbond IV Tag.
 pub static USRPKEY_AUTHBOUND_TAG: &[u8] = &[
     0x62, 0xe3, 0x38, 0x2d, 0xd0, 0x58, 0x40, 0xc1, 0xb0, 0xf2, 0x4a, 0xdd, 0xf7, 0x81, 0x67, 0x0b,
 ];
 
+/// Encrypted use key payload.
 pub static USRPKEY_AUTHBOUND_ENC_PAYLOAD: &[u8] = &[
     0x05, 0xb2, 0x5a, 0x1d, 0x1b, 0x25, 0x19, 0x48, 0xbf, 0x76, 0x0b, 0x37, 0x8c, 0x60, 0x52, 0xea,
     0x30, 0x2a, 0x2c, 0x89, 0x99, 0x95, 0x57, 0x5c, 0xec, 0x62, 0x3c, 0x08, 0x1a, 0xc6, 0x65, 0xf9,
@@ -375,6 +393,7 @@
     0x73, 0x08, 0x50, 0xb2, 0x19, 0xe8, 0x23, 0x1b, 0x83, 0x42, 0xdd, 0x4e, 0x6d,
 ];
 
+/// User key characterstics blob.
 pub static USRPKEY_AUTHBOUND_CHR: &[u8] = &[
     0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -390,6 +409,8 @@
     0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xbd, 0x02, 0x00, 0x60,
     0x10, 0x9d, 0x8b, 0x31, 0x76, 0x01, 0x00, 0x00, 0xf5, 0x01, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
 ];
+
+/// User certificate blob.
 pub static USRCERT_AUTHBOUND: &[u8] = &[
     0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -436,6 +457,8 @@
     0x39, 0x58, 0xe9, 0x89, 0x1a, 0x14, 0x41, 0x8d, 0xe0, 0xdc, 0x3d, 0x88, 0xf4, 0x2c, 0x7c, 0xda,
     0xa1, 0x84, 0xfa, 0x7f, 0xf9, 0x07, 0x97, 0xfb, 0xb5, 0xb7, 0x28, 0x28, 0x00, 0x7c, 0xa7,
 ];
+
+/// CA certificate blob.
 pub static CACERT_AUTHBOUND: &[u8] = &[
     0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -624,6 +647,7 @@
     0xab, 0xae, 0x24, 0xe2, 0x44, 0x35, 0x16, 0x8d, 0x55, 0x3c, 0xe4,
 ];
 
+/// User non-authbond-key blob.
 pub static USRPKEY_NON_AUTHBOUND: &[u8] = &[
     0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -663,6 +687,8 @@
     0x46, 0xf0, 0xee, 0x50, 0x73, 0x6a, 0x7b, 0xa3, 0xe9, 0xb1, 0x08, 0x81, 0x00, 0xdf, 0x0e, 0xc9,
     0xc3, 0x2c, 0x13, 0x64, 0xa1,
 ];
+
+/// User non-authbond-key characteristics blob.
 pub static USRPKEY_NON_AUTHBOUND_CHR: &[u8] = &[
     0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -678,6 +704,7 @@
     0x60, 0x60, 0x60, 0x8c, 0x31, 0x76, 0x01, 0x00, 0x00, 0xf5, 0x01, 0x00, 0x30, 0x00, 0x00, 0x00,
     0x00,
 ];
+/// User non-authbond-key certificate blob.
 pub static USRCERT_NON_AUTHBOUND: &[u8] = &[
     0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -725,6 +752,7 @@
     0xd8, 0xd5, 0xd1, 0x64, 0x4c, 0x05, 0xdd, 0x13, 0x0e, 0xa4, 0xf3, 0x38, 0xbf, 0x18, 0xd5,
 ];
 
+/// User non-authbond-key ca-certs blob.
 pub static CACERT_NON_AUTHBOUND: &[u8] = &[
     0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -913,6 +941,7 @@
     0xab, 0xae, 0x24, 0xe2, 0x44, 0x35, 0x16, 0x8d, 0x55, 0x3c, 0xe4,
 ];
 
+/// User decrypted authbond-key blob.
 pub static _DECRYPTED_USRPKEY_AUTHBOUND: &[u8] = &[
     0x44, 0x4b, 0x4d, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
     0xc6, 0x15, 0x3a, 0x08, 0x1e, 0x43, 0xba, 0x7a, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
@@ -950,6 +979,7 @@
     0x60, 0x5e, 0xcd, 0xce, 0x3a, 0xd8, 0x09, 0xeb, 0x9d, 0x40, 0xdb, 0x58, 0x53,
 ];
 
+/// User loaded authbond certs blob.
 pub static LOADED_CERT_AUTHBOUND: &[u8] = &[
     0x30, 0x82, 0x02, 0x93, 0x30, 0x82, 0x02, 0x3A, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01,
     0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x29, 0x31, 0x19,
@@ -994,6 +1024,8 @@
     0xE0, 0xDC, 0x3D, 0x88, 0xF4, 0x2C, 0x7C, 0xDA, 0xA1, 0x84, 0xFA, 0x7F, 0xF9, 0x07, 0x97, 0xFB,
     0xB5, 0xB7, 0x28, 0x28, 0x00, 0x7C, 0xA7,
 ];
+
+/// User loaded authbond ca-certs blob.
 pub static LOADED_CACERT_AUTHBOUND: &[u8] = &[
     0x30, 0x82, 0x02, 0x26, 0x30, 0x82, 0x01, 0xAB, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x05,
     0x84, 0x20, 0x26, 0x90, 0x76, 0x23, 0x58, 0x71, 0x77, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
@@ -1180,6 +1212,7 @@
     0x55, 0x3C, 0xE4,
 ];
 
+/// User loaded non-authbond user key blob.
 pub static LOADED_USRPKEY_NON_AUTHBOUND: &[u8] = &[
     0x44, 0x4b, 0x4d, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
     0x8a, 0xc1, 0x08, 0x13, 0x7c, 0x47, 0xba, 0x09, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
@@ -1217,6 +1250,7 @@
     0xe9, 0xb1, 0x08, 0x81, 0x00, 0xdf, 0x0e, 0xc9, 0xc3, 0x2c, 0x13, 0x64, 0xa1,
 ];
 
+/// User loaded non-authbond certificate blob.
 pub static LOADED_CERT_NON_AUTHBOUND: &[u8] = &[
     0x30, 0x82, 0x02, 0x93, 0x30, 0x82, 0x02, 0x39, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01,
     0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x29, 0x31, 0x19,
@@ -1262,6 +1296,7 @@
     0x0e, 0xa4, 0xf3, 0x38, 0xbf, 0x18, 0xd5,
 ];
 
+/// User loaded non-authbond ca-certificates blob.
 pub static LOADED_CACERT_NON_AUTHBOUND: &[u8] = &[
     0x30, 0x82, 0x02, 0x26, 0x30, 0x82, 0x01, 0xab, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x05,
     0x84, 0x20, 0x26, 0x90, 0x76, 0x23, 0x58, 0x71, 0x77, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
diff --git a/keystore2/src/legacy_importer.rs b/keystore2/src/legacy_importer.rs
index 5a64020..93e1735 100644
--- a/keystore2/src/legacy_importer.rs
+++ b/keystore2/src/legacy_importer.rs
@@ -280,116 +280,6 @@
         result
     }
 
-    /// This function behaves exactly like with_try_import unless the src_key has an encrypted
-    /// component (other than the key blob itself [1]) and super_key is None.
-    /// In that case the files belonging to the src_key will be renamed to be moved to the
-    /// namespace indicated by dst_key. The destination domain must be in Domain::APP.
-    ///
-    /// [1] Components that cannot be encrypted with the super key in keystore2 include the
-    /// characteristics file, which was encrypted before Android Q, and certificate entries
-    /// added by KeyChain before Android Q.
-    pub fn with_try_import_or_migrate_namespaces<F, T>(
-        &self,
-        src: (u32, &KeyDescriptor),
-        dest: (u32, &KeyDescriptor),
-        super_key: Option<Arc<dyn AesGcm + Send + Sync>>,
-        has_migrate_any_permission: bool,
-        key_accessor: F,
-    ) -> Result<Option<T>>
-    where
-        F: Fn() -> Result<T>,
-    {
-        let _wp = wd::watch_millis("LegacyImporter::with_try_import_or_migrate_namespaces", 500);
-
-        let (src_uid, src_key) = src;
-        let (dest_uid, dest_key) = dest;
-
-        // Access the key and return on success.
-        match key_accessor() {
-            Ok(result) => return Ok(Some(result)),
-            Err(e) => {
-                if e.root_cause().downcast_ref::<Error>()
-                    != Some(&Error::Rc(ResponseCode::KEY_NOT_FOUND))
-                {
-                    return Err(e);
-                }
-            }
-        }
-
-        // Filter inputs. We can only load legacy app domain keys as well
-        // as the SELINUX WIFI_NAMESPACE, which will be populated from AID_WIFI.
-        let src_uid = match src_key {
-            KeyDescriptor { domain: Domain::APP, alias: Some(_), .. } => src_uid,
-            KeyDescriptor { domain: Domain::SELINUX, nspace, alias: Some(_), .. } => {
-                match *nspace {
-                    Self::WIFI_NAMESPACE => Self::AID_WIFI,
-                    _ => {
-                        return Err(Error::Rc(ResponseCode::KEY_NOT_FOUND))
-                            .context(format!("No legacy keys for namespace {}", nspace))
-                    }
-                }
-            }
-            _ => {
-                return Err(Error::Rc(ResponseCode::KEY_NOT_FOUND))
-                    .context("No legacy keys for key descriptor.")
-            }
-        };
-
-        let dest_uid = match dest_key {
-            KeyDescriptor { domain: Domain::APP, alias: Some(_), .. } => Some(dest_uid),
-            KeyDescriptor { domain: Domain::SELINUX, alias: Some(_), .. } => {
-                // Domain::SELINUX cannot be migrated in place, but we cannot fail at this point
-                // because the import may succeed at which point the actual migration will
-                // be performed by the caller.
-                None
-            }
-            _ => {
-                return Err(Error::Rc(ResponseCode::KEY_NOT_FOUND))
-                    .context("No legacy keys for key descriptor.")
-            }
-        };
-
-        let src_key_clone = src_key.clone();
-        let dest_key_clone = dest_key.clone();
-        let result = self.do_serialized(move |importer_state| {
-            let super_key = super_key.map(|sk| -> Arc<dyn AesGcm> { sk });
-            match (
-                importer_state.check_and_import(src_uid, src_key_clone.clone(), super_key),
-                dest_uid,
-            ) {
-                // The import into the database was successful. Return Ok(true)
-                (Ok(()), _) => Ok(true),
-                // The import failed because a certificate and/or characteristics
-                // file was encrypted and no super_key was available. Migration within the
-                // legacy database is attempted and Ok(false) is returned on success.
-                (Err(e), Some(dest_uid))
-                    if has_migrate_any_permission
-                        && e.root_cause().downcast_ref::<Error>()
-                            == Some(&Error::Rc(ResponseCode::LOCKED)) =>
-                {
-                    importer_state
-                        .migrate_namespaces(src_uid, dest_uid, src_key_clone, dest_key_clone)
-                        .map(|_| false)
-                }
-                (Err(e), _) => Err(e),
-            }
-        });
-
-        match result {
-            None => {
-                Err(Error::Rc(ResponseCode::KEY_NOT_FOUND)).context("Legacy database is empty.")
-            }
-
-            Some(Ok(true)) => {
-                // After successful import try again.
-                key_accessor().map(|v| Some(v))
-            }
-            // The entry was successfully migrated within the legacy database.
-            Some(Ok(false)) => Ok(None),
-            Some(Err(e)) => Err(e),
-        }
-    }
-
     /// Runs the key_accessor function and returns its result. If it returns an error and the
     /// root cause was KEY_NOT_FOUND, tries to import a key with the given parameters from
     /// the legacy database to the new database and runs the key_accessor function again if
@@ -544,39 +434,6 @@
             .context("In list_uid: Trying to list legacy entries.")
     }
 
-    fn migrate_namespaces(
-        &mut self,
-        src_uid: u32,
-        dest_uid: u32,
-        src_key: KeyDescriptor,
-        dest_key: KeyDescriptor,
-    ) -> Result<()> {
-        let src_alias = src_key.alias.ok_or_else(|| {
-            anyhow::anyhow!(Error::sys()).context(
-                "In legacy_migrator::migrate_namespace: src_key.alias must be Some because \
-                 our caller must not have called us otherwise.",
-            )
-        })?;
-
-        if dest_key.domain != Domain::APP {
-            return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
-                "In legacy_migrator::migrate_namespace: \
-                 Legacy in-place migration to SELinux namespace is not supported.",
-            );
-        }
-
-        let dest_alias = dest_key.alias.ok_or_else(|| {
-            anyhow::anyhow!(Error::sys()).context(concat!(
-                "In legacy_migrator::migrate_namespace: dest_key.alias must be Some because ",
-                "our caller must not have called us otherwise."
-            ))
-        })?;
-
-        self.legacy_loader
-            .move_keystore_entry(src_uid, dest_uid, &src_alias, &dest_alias)
-            .context("In legacy_migrator::migrate_namespace: Moving key entry files.")
-    }
-
     /// Checks if the key can potentially be unlocked. And deletes the key entry otherwise.
     /// If the super_key has already been imported, the super key database id is returned.
     fn get_super_key_id_check_unlockable_or_delete(
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 0d637d8..1fca5d9 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -23,14 +23,13 @@
 use crate::permission::{KeyPerm, KeystorePerm};
 use crate::super_key::{SuperKeyManager, UserState};
 use crate::utils::{
-    check_key_permission, check_keystore_permission, list_key_entries, uid_to_android_user,
-    watchdog as wd,
+    check_key_permission, check_keystore_permission, uid_to_android_user, watchdog as wd,
 };
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     IKeyMintDevice::IKeyMintDevice, SecurityLevel::SecurityLevel,
 };
 use android_security_maintenance::aidl::android::security::maintenance::{
-    IKeystoreMaintenance::{BnKeystoreMaintenance, IKeystoreMaintenance, UID_SELF},
+    IKeystoreMaintenance::{BnKeystoreMaintenance, IKeystoreMaintenance},
     UserState::UserState as AidlUserState,
 };
 use android_security_maintenance::binder::{
@@ -40,7 +39,6 @@
 use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
 use anyhow::{Context, Result};
 use keystore2_crypto::Password;
-use keystore2_selinux as selinux;
 
 /// Reexport Domain for the benefit of DeleteListener
 pub use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
@@ -225,15 +223,10 @@
     }
 
     fn migrate_key_namespace(source: &KeyDescriptor, destination: &KeyDescriptor) -> Result<()> {
-        let migrate_any_key_permission =
-            check_keystore_permission(KeystorePerm::MigrateAnyKey).is_ok();
+        let calling_uid = ThreadState::get_calling_uid();
 
-        let src_uid = match source.domain {
-            Domain::SELINUX | Domain::KEY_ID => ThreadState::get_calling_uid(),
-            Domain::APP if source.nspace == UID_SELF.into() => ThreadState::get_calling_uid(),
-            Domain::APP if source.nspace != UID_SELF.into() && migrate_any_key_permission => {
-                source.nspace as u32
-            }
+        match source.domain {
+            Domain::SELINUX | Domain::KEY_ID | Domain::APP => (),
             _ => {
                 return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
                     "In migrate_key_namespace: \
@@ -242,12 +235,8 @@
             }
         };
 
-        let dest_uid = match destination.domain {
-            Domain::SELINUX => ThreadState::get_calling_uid(),
-            Domain::APP if destination.nspace == UID_SELF.into() => ThreadState::get_calling_uid(),
-            Domain::APP if destination.nspace != UID_SELF.into() && migrate_any_key_permission => {
-                destination.nspace as u32
-            }
+        match destination.domain {
+            Domain::SELINUX | Domain::APP => (),
             _ => {
                 return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
                     "In migrate_key_namespace: \
@@ -256,54 +245,30 @@
             }
         };
 
-        let user_id = uid_to_android_user(dest_uid);
-
-        if user_id != uid_to_android_user(src_uid)
-            && (source.domain == Domain::APP || destination.domain == Domain::APP)
-        {
-            return Err(Error::sys()).context(
-                "In migrate_key_namespace: Keys cannot be migrated across android users.",
-            );
-        }
+        let user_id = uid_to_android_user(calling_uid);
 
         let super_key = SUPER_KEY.read().unwrap().get_per_boot_key_by_user_id(user_id);
 
         DB.with(|db| {
-            if let Some((key_id_guard, _)) = LEGACY_IMPORTER
-                .with_try_import_or_migrate_namespaces(
-                    (src_uid, source),
-                    (dest_uid, destination),
-                    super_key,
-                    migrate_any_key_permission,
-                    || {
-                        db.borrow_mut().load_key_entry(
-                            source,
-                            KeyType::Client,
-                            KeyEntryLoadBits::NONE,
-                            src_uid,
-                            |k, av| {
-                                if migrate_any_key_permission {
-                                    Ok(())
-                                } else {
-                                    check_key_permission(KeyPerm::Use, k, &av)?;
-                                    check_key_permission(KeyPerm::Delete, k, &av)?;
-                                    check_key_permission(KeyPerm::Grant, k, &av)
-                                }
-                            },
-                        )
-                    },
-                )
-                .context("In migrate_key_namespace: Failed to load key blob.")?
-            {
-                db.borrow_mut().migrate_key_namespace(key_id_guard, destination, dest_uid, |k| {
-                    if migrate_any_key_permission {
-                        Ok(())
-                    } else {
-                        check_key_permission(KeyPerm::Rebind, k, &None)
-                    }
+            let (key_id_guard, _) = LEGACY_IMPORTER
+                .with_try_import(source, calling_uid, super_key, || {
+                    db.borrow_mut().load_key_entry(
+                        source,
+                        KeyType::Client,
+                        KeyEntryLoadBits::NONE,
+                        calling_uid,
+                        |k, av| {
+                            check_key_permission(KeyPerm::Use, k, &av)?;
+                            check_key_permission(KeyPerm::Delete, k, &av)?;
+                            check_key_permission(KeyPerm::Grant, k, &av)
+                        },
+                    )
                 })
-            } else {
-                Ok(())
+                .context("In migrate_key_namespace: Failed to load key blob.")?;
+            {
+                db.borrow_mut().migrate_key_namespace(key_id_guard, destination, calling_uid, |k| {
+                    check_key_permission(KeyPerm::Rebind, k, &None)
+                })
             }
         })
     }
@@ -316,30 +281,6 @@
 
         Maintenance::call_on_all_security_levels("deleteAllKeys", |dev| dev.deleteAllKeys())
     }
-
-    fn list_entries(domain: Domain, nspace: i64) -> Result<Vec<KeyDescriptor>> {
-        let k = match domain {
-            Domain::APP | Domain::SELINUX => KeyDescriptor{domain, nspace, ..Default::default()},
-            _ => return Err(Error::perm()).context(
-                "In list_entries: List entries is only supported for Domain::APP and Domain::SELINUX."
-            ),
-        };
-
-        // The caller has to have either GetInfo for the namespace or List permission
-        check_key_permission(KeyPerm::GetInfo, &k, &None)
-            .or_else(|e| {
-                if Some(&selinux::Error::PermissionDenied)
-                    == e.root_cause().downcast_ref::<selinux::Error>()
-                {
-                    check_keystore_permission(KeystorePerm::List)
-                } else {
-                    Err(e)
-                }
-            })
-            .context("In list_entries: While checking key and keystore permission.")?;
-
-        DB.with(|db| list_key_entries(&mut db.borrow_mut(), domain, nspace))
-    }
 }
 
 impl Interface for Maintenance {}
@@ -389,11 +330,6 @@
         map_or_log_err(Self::migrate_key_namespace(source, destination), Ok)
     }
 
-    fn listEntries(&self, domain: Domain, namespace: i64) -> BinderResult<Vec<KeyDescriptor>> {
-        let _wp = wd::watch_millis("IKeystoreMaintenance::listEntries", 500);
-        map_or_log_err(Self::list_entries(domain, namespace), Ok)
-    }
-
     fn deleteAllKeys(&self) -> BinderResult<()> {
         let _wp = wd::watch_millis("IKeystoreMaintenance::deleteAllKeys", 500);
         map_or_log_err(Self::delete_all_keys(), Ok)
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
index 1e6f10a..22509c4 100644
--- a/keystore2/src/permission.rs
+++ b/keystore2/src/permission.rs
@@ -145,10 +145,6 @@
         /// Checked when IKeystoreMaintenance::deleteAllKeys is called.
         #[selinux(name = delete_all_keys)]
         DeleteAllKeys,
-        /// Checked when migrating any key from any namespace to any other namespace. It was
-        /// introduced for migrating keys when an app leaves a sharedUserId.
-        #[selinux(name = migrate_any_key)]
-        MigrateAnyKey,
         /// Checked on calls to IRemotelyProvisionedKeyPool::getAttestationKey
         #[selinux(name = get_attestation_key)]
         GetAttestationKey,
diff --git a/keystore2/test_utils/authorizations.rs b/keystore2/test_utils/authorizations.rs
new file mode 100644
index 0000000..4fbe124
--- /dev/null
+++ b/keystore2/test_utils/authorizations.rs
@@ -0,0 +1,88 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module implements test utils to create Autherizations.
+
+use std::ops::Deref;
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    Algorithm::Algorithm, Digest::Digest, EcCurve::EcCurve, KeyParameter::KeyParameter,
+    KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, Tag::Tag,
+};
+
+/// Helper struct to create set of Authorizations.
+pub struct AuthSetBuilder(Vec<KeyParameter>);
+
+impl Default for AuthSetBuilder {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl AuthSetBuilder {
+    /// Creates new Authorizations list.
+    pub fn new() -> Self {
+        Self(Vec::new())
+    }
+
+    /// Add Purpose.
+    pub fn purpose(mut self, p: KeyPurpose) -> Self {
+        self.0.push(KeyParameter { tag: Tag::PURPOSE, value: KeyParameterValue::KeyPurpose(p) });
+        self
+    }
+
+    /// Add Digest.
+    pub fn digest(mut self, d: Digest) -> Self {
+        self.0.push(KeyParameter { tag: Tag::DIGEST, value: KeyParameterValue::Digest(d) });
+        self
+    }
+
+    /// Add Algorithm.
+    pub fn algorithm(mut self, a: Algorithm) -> Self {
+        self.0.push(KeyParameter { tag: Tag::ALGORITHM, value: KeyParameterValue::Algorithm(a) });
+        self
+    }
+
+    /// Add EC-Curve.
+    pub fn ec_curve(mut self, e: EcCurve) -> Self {
+        self.0.push(KeyParameter { tag: Tag::EC_CURVE, value: KeyParameterValue::EcCurve(e) });
+        self
+    }
+
+    /// Add Attestation-Challenge.
+    pub fn attestation_challenge(mut self, b: Vec<u8>) -> Self {
+        self.0.push(KeyParameter {
+            tag: Tag::ATTESTATION_CHALLENGE,
+            value: KeyParameterValue::Blob(b),
+        });
+        self
+    }
+
+    /// Add Attestation-ID.
+    pub fn attestation_app_id(mut self, b: Vec<u8>) -> Self {
+        self.0.push(KeyParameter {
+            tag: Tag::ATTESTATION_APPLICATION_ID,
+            value: KeyParameterValue::Blob(b),
+        });
+        self
+    }
+}
+
+impl Deref for AuthSetBuilder {
+    type Target = Vec<KeyParameter>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs
new file mode 100644
index 0000000..f49aa9f
--- /dev/null
+++ b/keystore2/test_utils/key_generations.rs
@@ -0,0 +1,68 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module implements test utils to generate various types of keys.
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    Algorithm::Algorithm, Digest::Digest, EcCurve::EcCurve, KeyPurpose::KeyPurpose,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+    KeyMetadata::KeyMetadata,
+};
+
+use crate::authorizations::AuthSetBuilder;
+
+const SELINUX_SHELL_NAMESPACE: i64 = 1;
+
+/// Generate attested EC Key blob using given security level with below key parameters -
+///     Purposes: SIGN and VERIFY
+///     Digest: SHA_2_256
+///     Curve: P_256
+pub fn generate_ec_p256_signing_key_with_attestation(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+) -> binder::Result<KeyMetadata> {
+    let att_challenge: &[u8] = b"foo";
+    let att_app_id: &[u8] = b"bar";
+    let gen_params = AuthSetBuilder::new()
+        .algorithm(Algorithm::EC)
+        .purpose(KeyPurpose::SIGN)
+        .purpose(KeyPurpose::VERIFY)
+        .digest(Digest::SHA_2_256)
+        .ec_curve(EcCurve::P_256)
+        .attestation_challenge(att_challenge.to_vec())
+        .attestation_app_id(att_app_id.to_vec());
+
+    match sec_level.generateKey(
+        &KeyDescriptor {
+            domain: Domain::BLOB,
+            nspace: SELINUX_SHELL_NAMESPACE,
+            alias: None,
+            blob: None,
+        },
+        None,
+        &gen_params,
+        0,
+        b"entropy",
+    ) {
+        Ok(key_metadata) => {
+            assert!(key_metadata.certificate.is_some());
+            assert!(key_metadata.certificateChain.is_some());
+            assert!(key_metadata.key.blob.is_some());
+
+            Ok(key_metadata)
+        }
+        Err(e) => Err(e),
+    }
+}
diff --git a/keystore2/test_utils/lib.rs b/keystore2/test_utils/lib.rs
index a355544..c63bfac 100644
--- a/keystore2/test_utils/lib.rs
+++ b/keystore2/test_utils/lib.rs
@@ -19,8 +19,14 @@
 use std::path::{Path, PathBuf};
 use std::{env::temp_dir, ops::Deref};
 
+use android_system_keystore2::aidl::android::system::keystore2::IKeystoreService::IKeystoreService;
+
+pub mod authorizations;
+pub mod key_generations;
 pub mod run_as;
 
+static KS2_SERVICE_NAME: &str = "android.system.keystore2.IKeystoreService/default";
+
 /// Represents the lifecycle of a temporary directory for testing.
 #[derive(Debug)]
 pub struct TempDir {
@@ -104,3 +110,8 @@
         &self.0
     }
 }
+
+/// Get Keystore2 service.
+pub fn get_keystore_service() -> binder::Strong<dyn IKeystoreService> {
+    binder::get_interface(KS2_SERVICE_NAME).unwrap()
+}
diff --git a/keystore2/tests/legacy_blobs/Android.bp b/keystore2/tests/legacy_blobs/Android.bp
new file mode 100644
index 0000000..2f48d7f
--- /dev/null
+++ b/keystore2/tests/legacy_blobs/Android.bp
@@ -0,0 +1,42 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+rust_test {
+    name: "keystore2_legacy_blobs_test",
+    srcs: ["keystore2_legacy_blob_tests.rs"],
+    test_suites: [
+        "general-tests",
+    ],
+    // auto_gen_config: true,
+    test_config: "AndroidTest.xml",
+
+    rustlibs: [
+        "libkeystore2_with_test_utils",
+        "libkeystore2_crypto_rust",
+        "android.system.keystore2-V2-rust",
+        "android.hardware.security.keymint-V2-rust",
+        "android.security.maintenance-rust",
+        "android.security.authorization-rust",
+        "librustutils",
+        "libkeystore2_test_utils",
+        "libnix",
+        "libanyhow",
+        "libbinder_rs",
+        "liblazy_static",
+        "liblibc",
+        "libserde",
+        "libthiserror",
+    ],
+    require_root: true,
+}
diff --git a/keystore2/tests/legacy_blobs/AndroidTest.xml b/keystore2/tests/legacy_blobs/AndroidTest.xml
new file mode 100644
index 0000000..ea83fbf
--- /dev/null
+++ b/keystore2/tests/legacy_blobs/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<configuration description="Config to run keystore2_legacy_blobs_test device tests.">
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option
+            name="push"
+            value="keystore2_legacy_blobs_test->/data/local/tmp/keystore2_legacy_blobs_test"
+        />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
+        <option name="test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="keystore2_legacy_blobs_test" />
+        <option name="native-test-flag" value="--test-threads=1" />
+    </test>
+</configuration>
diff --git a/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs b/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
new file mode 100644
index 0000000..6def39e
--- /dev/null
+++ b/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
@@ -0,0 +1,579 @@
+// Copyright 2022, 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.
+
+use nix::unistd::{getuid, Gid, Uid};
+use rustutils::users::AID_USER_OFFSET;
+use serde::{Deserialize, Serialize};
+
+use std::ops::Deref;
+use std::path::PathBuf;
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel;
+
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, KeyDescriptor::KeyDescriptor,
+};
+
+use android_security_maintenance::aidl::android::security::maintenance::{
+    IKeystoreMaintenance::IKeystoreMaintenance, UserState::UserState,
+};
+
+use android_security_authorization::aidl::android::security::authorization::{
+    IKeystoreAuthorization::IKeystoreAuthorization, LockScreenEvent::LockScreenEvent,
+};
+
+use keystore2::key_parameter::KeyParameter as KsKeyparameter;
+use keystore2::legacy_blob::test_utils::legacy_blob_test_vectors::*;
+use keystore2::legacy_blob::test_utils::*;
+use keystore2::legacy_blob::LegacyKeyCharacteristics;
+use keystore2::utils::AesGcm;
+use keystore2_crypto::{Password, ZVec};
+
+use keystore2_test_utils::get_keystore_service;
+use keystore2_test_utils::key_generations;
+use keystore2_test_utils::run_as;
+
+static USER_MANAGER_SERVICE_NAME: &str = "android.security.maintenance";
+static AUTH_SERVICE_NAME: &str = "android.security.authorization";
+const SELINUX_SHELL_NAMESPACE: i64 = 1;
+
+fn get_maintenance() -> binder::Strong<dyn IKeystoreMaintenance> {
+    binder::get_interface(USER_MANAGER_SERVICE_NAME).unwrap()
+}
+
+fn get_authorization() -> binder::Strong<dyn IKeystoreAuthorization> {
+    binder::get_interface(AUTH_SERVICE_NAME).unwrap()
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
+struct KeygenResult {
+    cert: Vec<u8>,
+    cert_chain: Vec<u8>,
+    key_parameters: Vec<KsKeyparameter>,
+}
+
+struct TestKey(ZVec);
+
+impl keystore2::utils::AesGcmKey for TestKey {
+    fn key(&self) -> &[u8] {
+        &self.0
+    }
+}
+
+impl Deref for TestKey {
+    type Target = [u8];
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+fn keystore2_restart_service() {
+    let output = std::process::Command::new("pidof")
+        .arg("keystore2")
+        .output()
+        .expect("failed to execute pidof keystore2");
+
+    let id = String::from_utf8(output.stdout).unwrap();
+    let id: String = id.chars().filter(|c| c.is_digit(10)).collect();
+
+    let _status = std::process::Command::new("kill").arg("-9").arg(id).status().unwrap();
+
+    // Loop till we find keystore2 service up and running.
+    loop {
+        let output = std::process::Command::new("pidof")
+            .arg("keystore2")
+            .output()
+            .expect("failed to execute pidof keystore2");
+
+        if output.status.code() == Some(0) {
+            break;
+        }
+    }
+}
+
+/// Create legacy blobs file layout for a user with user-id 99 and app-id 10001 with
+/// user-cert, ca-certs and encrypted key-characteristics files and tries to import
+/// these legacy blobs under user context.
+///
+/// Expected File layout for user with user-id "98" and app-id "10001" and key-alias
+/// "authbound":
+///     /data/misc/keystore/user_99/.masterkey
+///     /data/misc/keystore/user_99/9910001_USRPKEY_authbound
+///     /data/misc/keystore/user_99/.9910001_chr_USRPKEY_authbound
+///     /data/misc/keystore/user_99/9910001_USRCERT_authbound
+///     /data/misc/keystore/user_99/9910001_CACERT_authbound
+///
+/// Test performs below tasks -
+/// With su context it performs following tasks -
+///     1. Remove this user if already exist.
+///     2. Generate a key-blob, user cert-blob and ca-cert-blob to store it in legacy blobs file
+///        layout.
+///     3. Prepare file layout using generated key-blob, user cert and ca certs.
+///     4. Restart the keystore2 service to make it detect the populated legacy blobs.
+///     5. Inform the keystore2 service about the user and unlock the user.
+/// With user-99 context it performs following tasks -
+///     6. To load and import the legacy key using its alias.
+///     7. After successful key import validate the user cert and cert-chain with initially
+///        generated blobs.
+///     8. Validate imported key perameters. Imported key parameters list should be the combination
+///        of the key-parameters in characteristics file and the characteristics according to
+///        the augmentation rules. There might be duplicate entries with different values for the
+///        parameters like OS_VERSION, OS_VERSION, BOOT_PATCHLEVEL, VENDOR_PATCHLEVEL etc.
+///     9. Confirm keystore2 service cleanup the legacy blobs after successful import.
+#[test]
+fn keystore2_encrypted_characteristics() -> anyhow::Result<()> {
+    let auid = 99 * AID_USER_OFFSET + 10001;
+    let agid = 99 * AID_USER_OFFSET + 10001;
+    static TARGET_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+    static TARGET_SU_CTX: &str = "u:r:su:s0";
+
+    // Cleanup user directory if it exists
+    let path_buf = PathBuf::from("/data/misc/keystore/user_99");
+    if path_buf.as_path().is_dir() {
+        std::fs::remove_dir_all(path_buf.as_path()).unwrap();
+    }
+
+    // Safety: run_as must be called from a single threaded process.
+    // This device test is run as a separate single threaded process.
+    let mut gen_key_result = unsafe {
+        run_as::run_as(TARGET_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            // Remove user if already exist.
+            let maint_service = get_maintenance();
+            match maint_service.onUserRemoved(99) {
+                Ok(_) => {
+                    println!("User was existed, deleted successfully");
+                }
+                Err(e) => {
+                    println!("onUserRemoved error: {:#?}", e);
+                }
+            }
+
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2
+                .getSecurityLevel(SecurityLevel::SecurityLevel::TRUSTED_ENVIRONMENT)
+                .unwrap();
+            // Generate Key BLOB and prepare legacy keystore blob files.
+            let key_metadata =
+                key_generations::generate_ec_p256_signing_key_with_attestation(&sec_level)
+                    .expect("Failed to generate key blob");
+
+            // Create keystore file layout for user_99.
+            let pw: Password = PASSWORD.into();
+            let pw_key = TestKey(pw.derive_key(Some(SUPERKEY_SALT), 32).unwrap());
+            let super_key =
+                TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap());
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_99");
+            if !path_buf.as_path().is_dir() {
+                std::fs::create_dir(path_buf.as_path()).unwrap();
+            }
+            path_buf.push(".masterkey");
+            if !path_buf.as_path().is_file() {
+                std::fs::write(path_buf.as_path(), SUPERKEY).unwrap();
+            }
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_99");
+            path_buf.push("9910001_USRPKEY_authbound");
+            if !path_buf.as_path().is_file() {
+                make_encrypted_key_file(
+                    path_buf.as_path(),
+                    &super_key,
+                    &key_metadata.key.blob.unwrap(),
+                )
+                .unwrap();
+            }
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_99");
+            path_buf.push(".9910001_chr_USRPKEY_authbound");
+            if !path_buf.as_path().is_file() {
+                make_encrypted_characteristics_file(path_buf.as_path(), &super_key, KEY_PARAMETERS)
+                    .unwrap();
+            }
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_99");
+            path_buf.push("9910001_USRCERT_authbound");
+            if !path_buf.as_path().is_file() {
+                make_cert_blob_file(path_buf.as_path(), key_metadata.certificate.as_ref().unwrap())
+                    .unwrap();
+            }
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_99");
+            path_buf.push("9910001_CACERT_authbound");
+            if !path_buf.as_path().is_file() {
+                make_cert_blob_file(
+                    path_buf.as_path(),
+                    key_metadata.certificateChain.as_ref().unwrap(),
+                )
+                .unwrap();
+            }
+
+            // Keystore2 disables the legacy importer when it finds the legacy database empty.
+            // However, if the device boots with an empty legacy database, the optimization kicks in
+            // and keystore2 never checks the legacy file system layout.
+            // So, restart keystore2 service to detect populated legacy database.
+            keystore2_restart_service();
+
+            let auth_service = get_authorization();
+            match auth_service.onLockScreenEvent(LockScreenEvent::UNLOCK, 99, Some(PASSWORD), None)
+            {
+                Ok(result) => {
+                    println!("Unlock Result: {:?}", result);
+                }
+                Err(e) => {
+                    panic!("Unlock should have succeeded: {:?}", e);
+                }
+            }
+
+            let maint_service = get_maintenance();
+            assert_eq!(Ok(UserState(1)), maint_service.getState(99));
+
+            let mut key_params: Vec<KsKeyparameter> = Vec::new();
+            for param in key_metadata.authorizations {
+                let key_param = KsKeyparameter::new(param.keyParameter.into(), param.securityLevel);
+                key_params.push(key_param);
+            }
+
+            KeygenResult {
+                cert: key_metadata.certificate.unwrap(),
+                cert_chain: key_metadata.certificateChain.unwrap(),
+                key_parameters: key_params,
+            }
+        })
+    };
+
+    // Safety: run_as must be called from a single threaded process.
+    // This device test is run as a separate single threaded process.
+    unsafe {
+        run_as::run_as(TARGET_CTX, Uid::from_raw(auid), Gid::from_raw(agid), move || {
+            println!("UID: {}", getuid());
+            println!("Android User ID: {}", rustutils::users::multiuser_get_user_id(9910001));
+            println!("Android app ID: {}", rustutils::users::multiuser_get_app_id(9910001));
+
+            let test_alias = "authbound";
+            let keystore2 = get_keystore_service();
+
+            match keystore2.getKeyEntry(&KeyDescriptor {
+                domain: Domain::APP,
+                nspace: SELINUX_SHELL_NAMESPACE,
+                alias: Some(test_alias.to_string()),
+                blob: None,
+            }) {
+                Ok(key_entry_response) => {
+                    assert_eq!(
+                        key_entry_response.metadata.certificate.unwrap(),
+                        gen_key_result.cert
+                    );
+                    assert_eq!(
+                        key_entry_response.metadata.certificateChain.unwrap(),
+                        gen_key_result.cert_chain
+                    );
+                    assert_eq!(key_entry_response.metadata.key.domain, Domain::KEY_ID);
+                    assert_ne!(key_entry_response.metadata.key.nspace, 0);
+                    assert_eq!(
+                        key_entry_response.metadata.keySecurityLevel,
+                        SecurityLevel::SecurityLevel::TRUSTED_ENVIRONMENT
+                    );
+
+                    // Preapare KsKeyParameter list from getKeEntry response Authorizations.
+                    let mut key_params: Vec<KsKeyparameter> = Vec::new();
+                    for param in key_entry_response.metadata.authorizations {
+                        let key_param =
+                            KsKeyparameter::new(param.keyParameter.into(), param.securityLevel);
+                        key_params.push(key_param);
+                    }
+
+                    // Combine keyparameters from gen_key_result and keyparameters
+                    // from legacy key-char file.
+                    let mut legacy_file_key_params: Vec<KsKeyparameter> = Vec::new();
+                    match structured_test_params() {
+                        LegacyKeyCharacteristics::File(legacy_key_params) => {
+                            for param in &legacy_key_params {
+                                let mut present_in_gen_params = false;
+                                for gen_param in &gen_key_result.key_parameters {
+                                    if param.get_tag() == gen_param.get_tag() {
+                                        present_in_gen_params = true;
+                                    }
+                                }
+                                if !present_in_gen_params {
+                                    legacy_file_key_params.push(param.clone());
+                                }
+                            }
+                        }
+                        _ => {
+                            panic!("Expecting file characteristics");
+                        }
+                    }
+
+                    // Remove Key-Params which have security levels other than TRUSTED_ENVIRONMENT
+                    gen_key_result.key_parameters.retain(|in_element| {
+                        *in_element.security_level()
+                            == SecurityLevel::SecurityLevel::TRUSTED_ENVIRONMENT
+                    });
+
+                    println!("GetKeyEntry response key params: {:#?}", key_params);
+                    println!("Generated key params: {:#?}", gen_key_result.key_parameters);
+
+                    gen_key_result.key_parameters.append(&mut legacy_file_key_params);
+
+                    println!("Combined key params: {:#?}", gen_key_result.key_parameters);
+
+                    // Validate all keyparameters present in getKeyEntry response.
+                    for param in &key_params {
+                        gen_key_result.key_parameters.retain(|in_element| *in_element != *param);
+                    }
+
+                    println!(
+                        "GetKeyEntry response unmatched key params: {:#?}",
+                        gen_key_result.key_parameters
+                    );
+                    assert_eq!(gen_key_result.key_parameters.len(), 0);
+                }
+                Err(s) => {
+                    panic!("getKeyEntry should have succeeded. {:?}", s);
+                }
+            };
+        })
+    };
+
+    // Make sure keystore2 clean up imported legacy db.
+    let path_buf = PathBuf::from("/data/misc/keystore/user_99");
+    if path_buf.as_path().is_dir() {
+        panic!("Keystore service should have deleted this dir {:?}", path_buf);
+    }
+    Ok(())
+}
+
+/// Create legacy blobs file layout for a user with user-id 98 and app-id 10001 with encrypted
+/// user-cert and ca-certs files and tries to import these legacy blobs under user context.
+///
+/// Expected File layout for user with user-id "98" and app-id "10001" and key-alias
+/// "authboundcertenc":
+///     /data/misc/keystore/user_98/.masterkey
+///     /data/misc/keystore/user_98/9810001_USRPKEY_authboundcertenc
+///     /data/misc/keystore/user_98/.9810001_chr_USRPKEY_authboundcertenc
+///     /data/misc/keystore/user_98/9810001_USRCERT_authboundcertenc
+///     /data/misc/keystore/user_98/9810001_CACERT_authboundcertenc
+///
+/// Test performs below tasks -
+/// With su context it performs following tasks -
+///     1. Remove this user if already exist.
+///     2. Generate a key-blob, user cert-blob and ca-cert-blob to store it in legacy blobs file
+///        layout.
+///     3. Prepare file layout using generated key-blob, user cert and ca certs.
+///     4. Restart the keystore2 service to make it detect the populated legacy blobs.
+///     5. Inform the keystore2 service about the user and unlock the user.
+/// With user-98 context it performs following tasks -
+///     6. To load and import the legacy key using its alias.
+///     7. After successful key import validate the user cert and cert-chain with initially
+///        generated blobs.
+///     8. Validate imported key perameters. Imported key parameters list should be the combination
+///        of the key-parameters in characteristics file and the characteristics according to
+///        the augmentation rules. There might be duplicate entries with different values for the
+///        parameters like OS_VERSION, OS_VERSION, BOOT_PATCHLEVEL, VENDOR_PATCHLEVEL etc.
+///     9. Confirm keystore2 service cleanup the legacy blobs after successful import.
+#[test]
+fn keystore2_encrypted_certificates() -> anyhow::Result<()> {
+    let auid = 98 * AID_USER_OFFSET + 10001;
+    let agid = 98 * AID_USER_OFFSET + 10001;
+    static TARGET_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+    static TARGET_SU_CTX: &str = "u:r:su:s0";
+
+    // Cleanup user directory if it exists
+    let path_buf = PathBuf::from("/data/misc/keystore/user_98");
+    if path_buf.as_path().is_dir() {
+        std::fs::remove_dir_all(path_buf.as_path()).unwrap();
+    }
+
+    // Safety: run_as must be called from a single threaded process.
+    // This device test is run as a separate single threaded process.
+    let gen_key_result = unsafe {
+        run_as::run_as(TARGET_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            // Remove user if already exist.
+            let maint_service = get_maintenance();
+            match maint_service.onUserRemoved(98) {
+                Ok(_) => {
+                    println!("User was existed, deleted successfully");
+                }
+                Err(e) => {
+                    println!("onUserRemoved error: {:#?}", e);
+                }
+            }
+
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2
+                .getSecurityLevel(SecurityLevel::SecurityLevel::TRUSTED_ENVIRONMENT)
+                .unwrap();
+            // Generate Key BLOB and prepare legacy keystore blob files.
+            let key_metadata =
+                key_generations::generate_ec_p256_signing_key_with_attestation(&sec_level)
+                    .expect("Failed to generate key blob");
+
+            // Create keystore file layout for user_98.
+            let pw: Password = PASSWORD.into();
+            let pw_key = TestKey(pw.derive_key(Some(SUPERKEY_SALT), 32).unwrap());
+            let super_key =
+                TestKey(pw_key.decrypt(SUPERKEY_PAYLOAD, SUPERKEY_IV, SUPERKEY_TAG).unwrap());
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_98");
+            if !path_buf.as_path().is_dir() {
+                std::fs::create_dir(path_buf.as_path()).unwrap();
+            }
+            path_buf.push(".masterkey");
+            if !path_buf.as_path().is_file() {
+                std::fs::write(path_buf.as_path(), SUPERKEY).unwrap();
+            }
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_98");
+            path_buf.push("9810001_USRPKEY_authboundcertenc");
+            if !path_buf.as_path().is_file() {
+                make_encrypted_key_file(
+                    path_buf.as_path(),
+                    &super_key,
+                    &key_metadata.key.blob.unwrap(),
+                )
+                .unwrap();
+            }
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_98");
+            path_buf.push(".9810001_chr_USRPKEY_authboundcertenc");
+            if !path_buf.as_path().is_file() {
+                std::fs::write(path_buf.as_path(), USRPKEY_AUTHBOUND_CHR).unwrap();
+            }
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_98");
+            path_buf.push("9810001_USRCERT_authboundcertenc");
+            if !path_buf.as_path().is_file() {
+                make_encrypted_usr_cert_file(
+                    path_buf.as_path(),
+                    &super_key,
+                    key_metadata.certificate.as_ref().unwrap(),
+                )
+                .unwrap();
+            }
+
+            let mut path_buf = PathBuf::from("/data/misc/keystore/user_98");
+            path_buf.push("9810001_CACERT_authboundcertenc");
+            if !path_buf.as_path().is_file() {
+                make_encrypted_ca_cert_file(
+                    path_buf.as_path(),
+                    &super_key,
+                    key_metadata.certificateChain.as_ref().unwrap(),
+                )
+                .unwrap();
+            }
+
+            // Keystore2 disables the legacy importer when it finds the legacy database empty.
+            // However, if the device boots with an empty legacy database, the optimization kicks in
+            // and keystore2 never checks the legacy file system layout.
+            // So, restart keystore2 service to detect populated legacy database.
+            keystore2_restart_service();
+
+            let auth_service = get_authorization();
+            match auth_service.onLockScreenEvent(LockScreenEvent::UNLOCK, 98, Some(PASSWORD), None)
+            {
+                Ok(result) => {
+                    println!("Unlock Result: {:?}", result);
+                }
+                Err(e) => {
+                    panic!("Unlock should have succeeded: {:?}", e);
+                }
+            }
+
+            let maint_service = get_maintenance();
+            assert_eq!(Ok(UserState(1)), maint_service.getState(98));
+
+            let mut key_params: Vec<KsKeyparameter> = Vec::new();
+            for param in key_metadata.authorizations {
+                let key_param = KsKeyparameter::new(param.keyParameter.into(), param.securityLevel);
+                key_params.push(key_param);
+            }
+
+            KeygenResult {
+                cert: key_metadata.certificate.unwrap(),
+                cert_chain: key_metadata.certificateChain.unwrap(),
+                key_parameters: key_params,
+            }
+        })
+    };
+
+    // Safety: run_as must be called from a single threaded process.
+    // This device test is run as a separate single threaded process.
+    unsafe {
+        run_as::run_as(TARGET_CTX, Uid::from_raw(auid), Gid::from_raw(agid), move || {
+            println!("UID: {}", getuid());
+            println!("Android User ID: {}", rustutils::users::multiuser_get_user_id(9810001));
+            println!("Android app ID: {}", rustutils::users::multiuser_get_app_id(9810001));
+
+            let test_alias = "authboundcertenc";
+            let keystore2 = get_keystore_service();
+
+            match keystore2.getKeyEntry(&KeyDescriptor {
+                domain: Domain::APP,
+                nspace: SELINUX_SHELL_NAMESPACE,
+                alias: Some(test_alias.to_string()),
+                blob: None,
+            }) {
+                Ok(key_entry_response) => {
+                    assert_eq!(
+                        key_entry_response.metadata.certificate.unwrap(),
+                        gen_key_result.cert
+                    );
+                    assert_eq!(
+                        key_entry_response.metadata.certificateChain.unwrap(),
+                        gen_key_result.cert_chain
+                    );
+
+                    // Preapare KsKeyParameter list from getKeEntry response Authorizations.
+                    let mut key_params: Vec<KsKeyparameter> = Vec::new();
+                    for param in key_entry_response.metadata.authorizations {
+                        let key_param =
+                            KsKeyparameter::new(param.keyParameter.into(), param.securityLevel);
+                        key_params.push(key_param);
+                    }
+
+                    println!("GetKeyEntry response key params: {:#?}", key_params);
+                    println!("Generated key params: {:#?}", gen_key_result.key_parameters);
+                    match structured_test_params_cache() {
+                        LegacyKeyCharacteristics::Cache(legacy_key_params) => {
+                            println!("Legacy key-char cache: {:#?}", legacy_key_params);
+                            // Validate all keyparameters present in getKeyEntry response.
+                            for param in &legacy_key_params {
+                                key_params.retain(|in_element| *in_element != *param);
+                            }
+
+                            println!(
+                                "GetKeyEntry response unmatched key params: {:#?}",
+                                key_params
+                            );
+                            assert_eq!(key_params.len(), 0);
+                        }
+                        _ => {
+                            panic!("Expecting file characteristics");
+                        }
+                    }
+                }
+                Err(s) => {
+                    panic!("getKeyEntry should have succeeded. {:?}", s);
+                }
+            };
+        })
+    };
+
+    // Make sure keystore2 clean up imported legacy db.
+    let path_buf = PathBuf::from("/data/misc/keystore/user_98");
+    if path_buf.as_path().is_dir() {
+        panic!("Keystore service should have deleted this dir {:?}", path_buf);
+    }
+    Ok(())
+}