Merge "Limit the number of key descriptors sent back"
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index d01c67d..ab3e22c 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -59,6 +59,16 @@
 
 constexpr const char keystore2_service_name[] = "android.system.keystore2.IKeystoreService/default";
 
+std::string string_replace_all(std::string str, const std::string& from,
+                                      const std::string& to) {
+    size_t start = 0;
+    while ((start = str.find(from, start)) != std::string::npos) {
+        str.replace(start, from.length(), to);
+        start += to.length();
+    }
+    return str;
+}
+
 int unwrapError(const ndk::ScopedAStatus& status) {
     if (status.isOk()) return 0;
     if (status.getExceptionCode() == EX_SERVICE_SPECIFIC) {
@@ -1028,7 +1038,8 @@
     auto listener = ndk::SharedRefBase::make<ConfirmationListener>();
 
     auto future = listener->get_future();
-    auto rc = apcService->presentPrompt(listener, promptText, extraData, locale, uiOptionsAsFlags);
+    auto rc = apcService->presentPrompt(listener, string_replace_all(promptText, "\\n", "\n"),
+                                        extraData, locale, uiOptionsAsFlags);
 
     if (!rc.isOk()) {
         std::cerr << "Presenting confirmation prompt failed: " << rc.getDescription() << std::endl;
diff --git a/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
index 3f33431..e3b7d11 100644
--- a/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
+++ b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
@@ -41,8 +41,26 @@
 
     /**
      * Unlocks the keystore for the given user id.
+     *
      * Callers require 'Unlock' permission.
-     * If a password was set, a password must be given on unlock or the operation fails.
+     *
+     * Super-Encryption Key:
+     * When the device is unlocked (and password is non-null), Keystore stores in memory
+     * a super-encryption key derived from the password that protects UNLOCKED_DEVICE_REQUIRED
+     * keys; this key is wiped from memory when the device is locked.
+     *
+     * If unlockingSids is non-empty on lock, then before the super-encryption key is wiped from
+     * memory, a copy of it is stored in memory encrypted with a fresh AES key. This key is then
+     * imported into KM, tagged such that it can be used given a valid, recent auth token for any
+     * of the unlockingSids.
+     *
+     * Options for unlock:
+     *  - If the password is non-null, the super-encryption key is re-derived as above.
+     *  - If the password is null, then if a suitable auth token to access the encrypted
+     *    Super-encryption key stored in KM has been sent to keystore (via addAuthToken), the
+     *    encrypted super-encryption key is recovered so that UNLOCKED_DEVICE_REQUIRED keys can
+     *    be used once again.
+     *  - If neither of these are met, then the operation fails.
      *
      * ## Error conditions:
      * `ResponseCode::PERMISSION_DENIED` - if the callers do not have the 'Unlock' permission.
@@ -50,33 +68,10 @@
      * `ResponseCode::VALUE_CORRUPTED` - if the super key can not be decrypted.
      * `ResponseCode::KEY_NOT_FOUND` - if the super key is not found.
      *
-     * @lockScreenEvent - Indicates what happened.
-     *                    * LockScreenEvent.UNLOCK if the screen was unlocked.
-     *                    * LockScreenEvent.LOCK if the screen was locked.
-     *
-     * @param userId - Android user id
-     *
-     * @param password - synthetic password derived by the user denoted by the user id
-     *
-     * @param unlockingSids - list of biometric SIDs for this user. This will be null when
-     *                        lockScreenEvent is UNLOCK, but may be non-null when
-     *                        lockScreenEvent is LOCK.
-     *
-     *                        When the device is unlocked, Keystore stores in memory
-     *                        a super-encryption key that protects UNLOCKED_DEVICE_REQUIRED
-     *                        keys; this key is wiped from memory when the device is locked.
-     *
-     *                        If unlockingSids is non-empty on lock, then before the
-     *                        super-encryption key is wiped from memory, a copy of it
-     *                        is stored in memory encrypted with a fresh AES key.
-     *                        This key is then imported into KM, tagged such that it can be
-     *                        used given a valid, recent auth token for any of the
-     *                        unlockingSids.
-     *
-     *                        Then, when the device is unlocked again, if a suitable auth token
-     *                        has been sent to keystore, it is used to recover the
-     *                        super-encryption key, so that UNLOCKED_DEVICE_REQUIRED keys can
-     *                        be used once again.
+     * @param lockScreenEvent whether the lock screen locked or unlocked
+     * @param userId android user id
+     * @param password synthetic password derived from the user's LSKF, must be null on lock
+     * @param unlockingSids list of biometric SIDs for this user, ignored on unlock
      */
     void onLockScreenEvent(in LockScreenEvent lockScreenEvent, in int userId,
                            in @nullable byte[] password, in @nullable long[] unlockingSids);
diff --git a/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
index 4c2419a..1a385e7 100644
--- a/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
+++ b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
@@ -16,8 +16,6 @@
 
 #![feature(slice_internals)]
 #![no_main]
-#[macro_use]
-extern crate libfuzzer_sys;
 
 use core::slice::memchr;
 use keystore2::{legacy_blob::LegacyBlobLoader, utils::ui_opts_2_compat};
@@ -31,7 +29,7 @@
 };
 use keystore2_selinux::{check_access, getpidcon, setcon, Backend, Context, KeystoreKeyBackend};
 use keystore2_vintf::{get_aidl_instances, get_hidl_instances};
-use libfuzzer_sys::arbitrary::Arbitrary;
+use libfuzzer_sys::{arbitrary::Arbitrary, fuzz_target};
 use std::{ffi::CString, sync::Arc};
 
 // Avoid allocating too much memory and crashing the fuzzer.
diff --git a/keystore2/src/rkpd_client.rs b/keystore2/src/rkpd_client.rs
index 2d1b23b..d611678 100644
--- a/keystore2/src/rkpd_client.rs
+++ b/keystore2/src/rkpd_client.rs
@@ -14,7 +14,7 @@
 
 //! Helper wrapper around RKPD interface.
 
-use crate::error::{map_binder_status_code, map_or_log_err, Error, ErrorCode};
+use crate::error::{map_binder_status_code, Error, ErrorCode};
 use crate::globals::get_remotely_provisioned_component_name;
 use crate::ks_err;
 use crate::utils::watchdog as wd;
@@ -23,7 +23,10 @@
     IGetKeyCallback::BnGetKeyCallback, IGetKeyCallback::IGetKeyCallback,
     IGetRegistrationCallback::BnGetRegistrationCallback,
     IGetRegistrationCallback::IGetRegistrationCallback, IRegistration::IRegistration,
-    IRemoteProvisioning::IRemoteProvisioning, RemotelyProvisionedKey::RemotelyProvisionedKey,
+    IRemoteProvisioning::IRemoteProvisioning,
+    IStoreUpgradedKeyCallback::BnStoreUpgradedKeyCallback,
+    IStoreUpgradedKeyCallback::IStoreUpgradedKeyCallback,
+    RemotelyProvisionedKey::RemotelyProvisionedKey,
 };
 use android_security_rkp_aidl::binder::{BinderFeatures, Interface, Strong};
 use anyhow::{Context, Result};
@@ -31,45 +34,36 @@
 use futures::executor::block_on;
 use std::sync::Mutex;
 
-type RegistrationSender = oneshot::Sender<Result<binder::Strong<dyn IRegistration>>>;
+/// Thread-safe channel for sending a value once and only once. If a value has
+/// already been send, subsequent calls to send will noop.
+struct SafeSender<T> {
+    inner: Mutex<Option<oneshot::Sender<T>>>,
+}
+
+impl<T> SafeSender<T> {
+    fn new(sender: oneshot::Sender<T>) -> Self {
+        Self { inner: Mutex::new(Some(sender)) }
+    }
+
+    fn send(&self, value: T) {
+        if let Some(inner) = self.inner.lock().unwrap().take() {
+            // assert instead of unwrap, because on failure send returns Err(value)
+            assert!(inner.send(value).is_ok(), "thread state is terminally broken");
+        }
+    }
+}
 
 struct GetRegistrationCallback {
-    registration_tx: Mutex<Option<RegistrationSender>>,
+    registration_tx: SafeSender<Result<binder::Strong<dyn IRegistration>>>,
 }
 
 impl GetRegistrationCallback {
     pub fn new_native_binder(
-        registration_tx: RegistrationSender,
-    ) -> Result<Strong<dyn IGetRegistrationCallback>> {
+        registration_tx: oneshot::Sender<Result<binder::Strong<dyn IRegistration>>>,
+    ) -> Strong<dyn IGetRegistrationCallback> {
         let result: Self =
-            GetRegistrationCallback { registration_tx: Mutex::new(Some(registration_tx)) };
-        Ok(BnGetRegistrationCallback::new_binder(result, BinderFeatures::default()))
-    }
-    fn on_success(&self, registration: &binder::Strong<dyn IRegistration>) -> Result<()> {
-        if let Some(tx) = self.registration_tx.lock().unwrap().take() {
-            tx.send(Ok(registration.clone())).unwrap();
-        }
-        Ok(())
-    }
-    fn on_cancel(&self) -> Result<()> {
-        if let Some(tx) = self.registration_tx.lock().unwrap().take() {
-            tx.send(
-                Err(Error::Km(ErrorCode::OPERATION_CANCELLED))
-                    .context(ks_err!("GetRegistrationCallback cancelled.")),
-            )
-            .unwrap();
-        }
-        Ok(())
-    }
-    fn on_error(&self, error: &str) -> Result<()> {
-        if let Some(tx) = self.registration_tx.lock().unwrap().take() {
-            tx.send(
-                Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
-                    .context(ks_err!("GetRegistrationCallback failed: {:?}", error)),
-            )
-            .unwrap();
-        }
-        Ok(())
+            GetRegistrationCallback { registration_tx: SafeSender::new(registration_tx) };
+        BnGetRegistrationCallback::new_binder(result, BinderFeatures::default())
     }
 }
 
@@ -78,15 +72,26 @@
 impl IGetRegistrationCallback for GetRegistrationCallback {
     fn onSuccess(&self, registration: &Strong<dyn IRegistration>) -> binder::Result<()> {
         let _wp = wd::watch_millis("IGetRegistrationCallback::onSuccess", 500);
-        map_or_log_err(self.on_success(registration), Ok)
+        self.registration_tx.send(Ok(registration.clone()));
+        Ok(())
     }
     fn onCancel(&self) -> binder::Result<()> {
         let _wp = wd::watch_millis("IGetRegistrationCallback::onCancel", 500);
-        map_or_log_err(self.on_cancel(), Ok)
+        log::warn!("IGetRegistrationCallback cancelled");
+        self.registration_tx.send(
+            Err(Error::Km(ErrorCode::OPERATION_CANCELLED))
+                .context(ks_err!("GetRegistrationCallback cancelled.")),
+        );
+        Ok(())
     }
     fn onError(&self, error: &str) -> binder::Result<()> {
         let _wp = wd::watch_millis("IGetRegistrationCallback::onError", 500);
-        map_or_log_err(self.on_error(error), Ok)
+        log::error!("IGetRegistrationCallback failed: '{error}'");
+        self.registration_tx.send(
+            Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
+                .context(ks_err!("GetRegistrationCallback failed: {:?}", error)),
+        );
+        Ok(())
     }
 }
 
@@ -102,8 +107,7 @@
         .context(ks_err!("Trying to get IRPC name."))?;
 
     let (tx, rx) = oneshot::channel();
-    let cb = GetRegistrationCallback::new_native_binder(tx)
-        .context(ks_err!("Trying to create a IGetRegistrationCallback."))?;
+    let cb = GetRegistrationCallback::new_native_binder(tx);
 
     remote_provisioning
         .getRegistration(&rpc_name, &cb)
@@ -112,46 +116,16 @@
     rx.await.unwrap()
 }
 
-type KeySender = oneshot::Sender<Result<RemotelyProvisionedKey>>;
-
 struct GetKeyCallback {
-    key_tx: Mutex<Option<KeySender>>,
+    key_tx: SafeSender<Result<RemotelyProvisionedKey>>,
 }
 
 impl GetKeyCallback {
-    pub fn new_native_binder(key_tx: KeySender) -> Result<Strong<dyn IGetKeyCallback>> {
-        let result: Self = GetKeyCallback { key_tx: Mutex::new(Some(key_tx)) };
-        Ok(BnGetKeyCallback::new_binder(result, BinderFeatures::default()))
-    }
-    fn on_success(&self, key: &RemotelyProvisionedKey) -> Result<()> {
-        if let Some(tx) = self.key_tx.lock().unwrap().take() {
-            tx.send(Ok(RemotelyProvisionedKey {
-                keyBlob: key.keyBlob.clone(),
-                encodedCertChain: key.encodedCertChain.clone(),
-            }))
-            .unwrap();
-        }
-        Ok(())
-    }
-    fn on_cancel(&self) -> Result<()> {
-        if let Some(tx) = self.key_tx.lock().unwrap().take() {
-            tx.send(
-                Err(Error::Km(ErrorCode::OPERATION_CANCELLED))
-                    .context(ks_err!("GetKeyCallback cancelled.")),
-            )
-            .unwrap();
-        }
-        Ok(())
-    }
-    fn on_error(&self, error: &str) -> Result<()> {
-        if let Some(tx) = self.key_tx.lock().unwrap().take() {
-            tx.send(
-                Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
-                    .context(ks_err!("GetKeyCallback failed: {:?}", error)),
-            )
-            .unwrap();
-        }
-        Ok(())
+    pub fn new_native_binder(
+        key_tx: oneshot::Sender<Result<RemotelyProvisionedKey>>,
+    ) -> Strong<dyn IGetKeyCallback> {
+        let result: Self = GetKeyCallback { key_tx: SafeSender::new(key_tx) };
+        BnGetKeyCallback::new_binder(result, BinderFeatures::default())
     }
 }
 
@@ -160,15 +134,29 @@
 impl IGetKeyCallback for GetKeyCallback {
     fn onSuccess(&self, key: &RemotelyProvisionedKey) -> binder::Result<()> {
         let _wp = wd::watch_millis("IGetKeyCallback::onSuccess", 500);
-        map_or_log_err(self.on_success(key), Ok)
+        self.key_tx.send(Ok(RemotelyProvisionedKey {
+            keyBlob: key.keyBlob.clone(),
+            encodedCertChain: key.encodedCertChain.clone(),
+        }));
+        Ok(())
     }
     fn onCancel(&self) -> binder::Result<()> {
         let _wp = wd::watch_millis("IGetKeyCallback::onCancel", 500);
-        map_or_log_err(self.on_cancel(), Ok)
+        log::warn!("IGetKeyCallback cancelled");
+        self.key_tx.send(
+            Err(Error::Km(ErrorCode::OPERATION_CANCELLED))
+                .context(ks_err!("GetKeyCallback cancelled.")),
+        );
+        Ok(())
     }
     fn onError(&self, error: &str) -> binder::Result<()> {
         let _wp = wd::watch_millis("IGetKeyCallback::onError", 500);
-        map_or_log_err(self.on_error(error), Ok)
+        log::error!("IGetKeyCallback failed: {error}");
+        self.key_tx.send(
+            Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
+                .context(ks_err!("GetKeyCallback failed: {:?}", error)),
+        );
+        Ok(())
     }
 }
 
@@ -181,8 +169,7 @@
         .context(ks_err!("Trying to get to IRegistration service."))?;
 
     let (tx, rx) = oneshot::channel();
-    let cb = GetKeyCallback::new_native_binder(tx)
-        .context(ks_err!("Trying to create a IGetKeyCallback."))?;
+    let cb = GetKeyCallback::new_native_binder(tx);
 
     registration
         .getKey(caller_uid.try_into().unwrap(), &cb)
@@ -191,6 +178,39 @@
     rx.await.unwrap()
 }
 
+struct StoreUpgradedKeyCallback {
+    completer: SafeSender<Result<()>>,
+}
+
+impl StoreUpgradedKeyCallback {
+    pub fn new_native_binder(
+        completer: oneshot::Sender<Result<()>>,
+    ) -> Strong<dyn IStoreUpgradedKeyCallback> {
+        let result: Self = StoreUpgradedKeyCallback { completer: SafeSender::new(completer) };
+        BnStoreUpgradedKeyCallback::new_binder(result, BinderFeatures::default())
+    }
+}
+
+impl Interface for StoreUpgradedKeyCallback {}
+
+impl IStoreUpgradedKeyCallback for StoreUpgradedKeyCallback {
+    fn onSuccess(&self) -> binder::Result<()> {
+        let _wp = wd::watch_millis("IGetRegistrationCallback::onSuccess", 500);
+        self.completer.send(Ok(()));
+        Ok(())
+    }
+
+    fn onError(&self, error: &str) -> binder::Result<()> {
+        let _wp = wd::watch_millis("IGetRegistrationCallback::onError", 500);
+        log::error!("IGetRegistrationCallback failed: {error}");
+        self.completer.send(
+            Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
+                .context(ks_err!("Failed to store upgraded key: {:?}", error)),
+        );
+        Ok(())
+    }
+}
+
 async fn store_rkpd_attestation_key_async(
     security_level: &SecurityLevel,
     key_blob: &[u8],
@@ -200,10 +220,14 @@
         .await
         .context(ks_err!("Trying to get to IRegistration service."))?;
 
+    let (tx, rx) = oneshot::channel();
+    let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
+
     registration
-        .storeUpgradedKey(key_blob, upgraded_blob)
+        .storeUpgradedKeyAsync(key_blob, upgraded_blob, &cb)
         .context(ks_err!("Failed to store upgraded blob with RKPD."))?;
-    Ok(())
+
+    rx.await.unwrap()
 }
 
 /// Get attestation key from RKPD.
@@ -229,6 +253,7 @@
 mod tests {
     use super::*;
     use android_security_rkp_aidl::aidl::android::security::rkp::IRegistration::BnRegistration;
+    use std::sync::atomic::{AtomicU32, Ordering};
     use std::sync::Arc;
 
     #[derive(Default)]
@@ -257,20 +282,32 @@
             todo!()
         }
 
-        fn storeUpgradedKey(&self, _: &[u8], _: &[u8]) -> binder::Result<()> {
+        fn storeUpgradedKeyAsync(
+            &self,
+            _: &[u8],
+            _: &[u8],
+            _: &Strong<dyn IStoreUpgradedKeyCallback>,
+        ) -> binder::Result<()> {
             todo!()
         }
     }
 
     fn get_mock_registration() -> Result<binder::Strong<dyn IRegistration>> {
         let (tx, rx) = oneshot::channel();
-        let cb = GetRegistrationCallback::new_native_binder(tx).unwrap();
+        let cb = GetRegistrationCallback::new_native_binder(tx);
         let mock_registration = MockRegistration::new_native_binder();
 
         assert!(cb.onSuccess(&mock_registration).is_ok());
         block_on(rx).unwrap()
     }
 
+    // Using the same key ID makes test cases race with each other. So, we use separate key IDs for
+    // different test cases.
+    fn get_next_key_id() -> u32 {
+        static ID: AtomicU32 = AtomicU32::new(0);
+        ID.fetch_add(1, Ordering::Relaxed)
+    }
+
     #[test]
     fn test_get_registration_cb_success() {
         let registration = get_mock_registration();
@@ -280,7 +317,7 @@
     #[test]
     fn test_get_registration_cb_cancel() {
         let (tx, rx) = oneshot::channel();
-        let cb = GetRegistrationCallback::new_native_binder(tx).unwrap();
+        let cb = GetRegistrationCallback::new_native_binder(tx);
         assert!(cb.onCancel().is_ok());
 
         let result = block_on(rx).unwrap();
@@ -293,7 +330,7 @@
     #[test]
     fn test_get_registration_cb_error() {
         let (tx, rx) = oneshot::channel();
-        let cb = GetRegistrationCallback::new_native_binder(tx).unwrap();
+        let cb = GetRegistrationCallback::new_native_binder(tx);
         assert!(cb.onError("error").is_ok());
 
         let result = block_on(rx).unwrap();
@@ -308,7 +345,7 @@
         let mock_key =
             RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
         let (tx, rx) = oneshot::channel();
-        let cb = GetKeyCallback::new_native_binder(tx).unwrap();
+        let cb = GetKeyCallback::new_native_binder(tx);
         assert!(cb.onSuccess(&mock_key).is_ok());
 
         let key = block_on(rx).unwrap().unwrap();
@@ -318,7 +355,7 @@
     #[test]
     fn test_get_key_cb_cancel() {
         let (tx, rx) = oneshot::channel();
-        let cb = GetKeyCallback::new_native_binder(tx).unwrap();
+        let cb = GetKeyCallback::new_native_binder(tx);
         assert!(cb.onCancel().is_ok());
 
         let result = block_on(rx).unwrap();
@@ -331,7 +368,7 @@
     #[test]
     fn test_get_key_cb_error() {
         let (tx, rx) = oneshot::channel();
-        let cb = GetKeyCallback::new_native_binder(tx).unwrap();
+        let cb = GetKeyCallback::new_native_binder(tx);
         assert!(cb.onError("error").is_ok());
 
         let result = block_on(rx).unwrap();
@@ -342,46 +379,81 @@
     }
 
     #[test]
-    #[ignore]
+    fn test_store_upgraded_cb_success() {
+        let (tx, rx) = oneshot::channel();
+        let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
+        assert!(cb.onSuccess().is_ok());
+
+        block_on(rx).unwrap().unwrap();
+    }
+
+    #[test]
+    fn test_store_upgraded_key_cb_error() {
+        let (tx, rx) = oneshot::channel();
+        let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
+        assert!(cb.onError("oh no! it failed").is_ok());
+
+        let result = block_on(rx).unwrap();
+        assert_eq!(
+            result.unwrap_err().downcast::<Error>().unwrap(),
+            Error::Km(ErrorCode::UNKNOWN_ERROR)
+        );
+    }
+
+    #[test]
     fn test_get_rkpd_attestation_key() {
+        binder::ProcessState::start_thread_pool();
         let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, 0).unwrap();
         assert!(!key.keyBlob.is_empty());
         assert!(!key.encodedCertChain.is_empty());
     }
 
     #[test]
-    #[ignore]
     fn test_get_rkpd_attestation_key_same_caller() {
+        binder::ProcessState::start_thread_pool();
         let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
-        let caller_uid = 0;
+        let key_id = get_next_key_id();
 
         // Multiple calls should return the same key.
-        let first_key = get_rkpd_attestation_key(&sec_level, caller_uid).unwrap();
-        let second_key = get_rkpd_attestation_key(&sec_level, caller_uid).unwrap();
+        let first_key = get_rkpd_attestation_key(&sec_level, key_id).unwrap();
+        let second_key = get_rkpd_attestation_key(&sec_level, key_id).unwrap();
 
         assert_eq!(first_key.keyBlob, second_key.keyBlob);
         assert_eq!(first_key.encodedCertChain, second_key.encodedCertChain);
     }
 
     #[test]
-    #[ignore]
     fn test_get_rkpd_attestation_key_different_caller() {
+        binder::ProcessState::start_thread_pool();
         let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
+        let first_key_id = get_next_key_id();
+        let second_key_id = get_next_key_id();
 
         // Different callers should be getting different keys.
-        let first_key = get_rkpd_attestation_key(&sec_level, 1).unwrap();
-        let second_key = get_rkpd_attestation_key(&sec_level, 2).unwrap();
+        let first_key = get_rkpd_attestation_key(&sec_level, first_key_id).unwrap();
+        let second_key = get_rkpd_attestation_key(&sec_level, second_key_id).unwrap();
 
         assert_ne!(first_key.keyBlob, second_key.keyBlob);
         assert_ne!(first_key.encodedCertChain, second_key.encodedCertChain);
     }
 
     #[test]
-    #[ignore]
+    // Couple of things to note:
+    // 1. This test must never run with UID of keystore. Otherwise, it can mess up keys stored by
+    //    keystore.
+    // 2. Storing and reading the stored key is prone to race condition. So, we only do this in one
+    //    test case.
     fn test_store_rkpd_attestation_key() {
+        binder::ProcessState::start_thread_pool();
         let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
-        let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, 0).unwrap();
+        let key_id = get_next_key_id();
+        let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id).unwrap();
+        let new_blob: [u8; 8] = rand::random();
 
-        assert!(store_rkpd_attestation_key(&sec_level, &key.keyBlob, &key.keyBlob).is_ok());
+        assert!(store_rkpd_attestation_key(&sec_level, &key.keyBlob, &new_blob).is_ok());
+
+        let new_key =
+            get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id).unwrap();
+        assert_eq!(new_key.keyBlob, new_blob);
     }
 }
diff --git a/keystore2/test_utils/authorizations.rs b/keystore2/test_utils/authorizations.rs
index c2f0279..4608bc5 100644
--- a/keystore2/test_utils/authorizations.rs
+++ b/keystore2/test_utils/authorizations.rs
@@ -71,15 +71,6 @@
         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
-    }
-
     /// Add No_auth_required.
     pub fn no_auth_required(mut self) -> Self {
         self.0.push(KeyParameter {
@@ -149,6 +140,15 @@
         self
     }
 
+    /// Add CALLER_NONCE.
+    pub fn caller_nonce(mut self) -> Self {
+        self.0.push(KeyParameter {
+            tag: Tag::CALLER_NONCE,
+            value: KeyParameterValue::BoolValue(true),
+        });
+        self
+    }
+
     /// Add MAC length.
     pub fn mac_length(mut self, l: i32) -> Self {
         self.0.push(KeyParameter { tag: Tag::MAC_LENGTH, value: KeyParameterValue::Integer(l) });
diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs
index 175d8bb..f9aaabb 100644
--- a/keystore2/test_utils/key_generations.rs
+++ b/keystore2/test_utils/key_generations.rs
@@ -18,13 +18,14 @@
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
-    ErrorCode::ErrorCode, KeyOrigin::KeyOrigin, KeyParameter::KeyParameter,
-    KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
-    Tag::Tag,
+    ErrorCode::ErrorCode, HardwareAuthenticatorType::HardwareAuthenticatorType,
+    KeyOrigin::KeyOrigin, KeyParameter::KeyParameter, KeyParameterValue::KeyParameterValue,
+    KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, Tag::Tag,
 };
 use android_system_keystore2::aidl::android::system::keystore2::{
-    Authorization::Authorization, Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
-    KeyDescriptor::KeyDescriptor, KeyMetadata::KeyMetadata, ResponseCode::ResponseCode,
+    AuthenticatorSpec::AuthenticatorSpec, Authorization::Authorization, Domain::Domain,
+    IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+    KeyMetadata::KeyMetadata, ResponseCode::ResponseCode,
 };
 
 use crate::authorizations::AuthSetBuilder;
@@ -57,8 +58,6 @@
     pub block_mode: Option<BlockMode>,
     /// Attestation challenge.
     pub att_challenge: Option<Vec<u8>>,
-    /// Attestation app id.
-    pub att_app_id: Option<Vec<u8>>,
 }
 
 /// DER-encoded PKCS#8 format RSA key. Generated using:
@@ -157,6 +156,131 @@
     0xD6, 0x84, 0x98, 0xEA, 0x96, 0x91, 0xFB, 0x78, 0xED, 0x86,
 ];
 
+/// DER-encoded PKCS#8 format RSA key -
+///     Size: 2048
+///     Public Exponent: 65537
+///     Purpose: WRAP_KEY, ENCRYPT, DECRYPT
+///     Encryption scheme: RSAES-PKCS1-v1_5
+///         Digest: SHA_2_256
+///         Padding: RSA_OAEP
+/// This sample wrapping_key is taken from KeyMint tests
+/// (see hardware/interfaces/security/keymint/aidl/vts/functional/KeyMintTest.cpp).
+/// Similarly more test keys can be generated with below command -
+/// openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -outform der | hexdump -e '30/1  "%02X" "\n"'
+pub static WRAPPING_KEY: &[u8] = &[
+    0x30, 0x82, 0x04, 0xbe, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x04, 0xa8, 0x30, 0x82, 0x04, 0xa4, 0x02, 0x01,
+    0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xae, 0xc3, 0x67, 0x93, 0x1d, 0x89, 0x00, 0xce, 0x56, 0xb0,
+    0x06, 0x7f, 0x7d, 0x70, 0xe1, 0xfc, 0x65, 0x3f, 0x3f, 0x34, 0xd1, 0x94, 0xc1, 0xfe, 0xd5, 0x00,
+    0x18, 0xfb, 0x43, 0xdb, 0x93, 0x7b, 0x06, 0xe6, 0x73, 0xa8, 0x37, 0x31, 0x3d, 0x56, 0xb1, 0xc7,
+    0x25, 0x15, 0x0a, 0x3f, 0xef, 0x86, 0xac, 0xbd, 0xdc, 0x41, 0xbb, 0x75, 0x9c, 0x28, 0x54, 0xea,
+    0xe3, 0x2d, 0x35, 0x84, 0x1e, 0xfb, 0x5c, 0x18, 0xd8, 0x2b, 0xc9, 0x0a, 0x1c, 0xb5, 0xc1, 0xd5,
+    0x5a, 0xdf, 0x24, 0x5b, 0x02, 0x91, 0x1f, 0x0b, 0x7c, 0xda, 0x88, 0xc4, 0x21, 0xff, 0x0e, 0xba,
+    0xfe, 0x7c, 0x0d, 0x23, 0xbe, 0x31, 0x2d, 0x7b, 0xd5, 0x92, 0x1f, 0xfa, 0xea, 0x13, 0x47, 0xc1,
+    0x57, 0x40, 0x6f, 0xef, 0x71, 0x8f, 0x68, 0x26, 0x43, 0xe4, 0xe5, 0xd3, 0x3c, 0x67, 0x03, 0xd6,
+    0x1c, 0x0c, 0xf7, 0xac, 0x0b, 0xf4, 0x64, 0x5c, 0x11, 0xf5, 0xc1, 0x37, 0x4c, 0x38, 0x86, 0x42,
+    0x74, 0x11, 0xc4, 0x49, 0x79, 0x67, 0x92, 0xe0, 0xbe, 0xf7, 0x5d, 0xec, 0x85, 0x8a, 0x21, 0x23,
+    0xc3, 0x67, 0x53, 0xe0, 0x2a, 0x95, 0xa9, 0x6d, 0x7c, 0x45, 0x4b, 0x50, 0x4d, 0xe3, 0x85, 0xa6,
+    0x42, 0xe0, 0xdf, 0xc3, 0xe6, 0x0a, 0xc3, 0xa7, 0xee, 0x49, 0x91, 0xd0, 0xd4, 0x8b, 0x01, 0x72,
+    0xa9, 0x5f, 0x95, 0x36, 0xf0, 0x2b, 0xa1, 0x3c, 0xec, 0xcc, 0xb9, 0x2b, 0x72, 0x7d, 0xb5, 0xc2,
+    0x7e, 0x5b, 0x2f, 0x5c, 0xec, 0x09, 0x60, 0x0b, 0x28, 0x6a, 0xf5, 0xcf, 0x14, 0xc4, 0x20, 0x24,
+    0xc6, 0x1d, 0xdf, 0xe7, 0x1c, 0x2a, 0x8d, 0x74, 0x58, 0xf1, 0x85, 0x23, 0x4c, 0xb0, 0x0e, 0x01,
+    0xd2, 0x82, 0xf1, 0x0f, 0x8f, 0xc6, 0x72, 0x1d, 0x2a, 0xed, 0x3f, 0x48, 0x33, 0xcc, 0xa2, 0xbd,
+    0x8f, 0xa6, 0x28, 0x21, 0xdd, 0x55, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x43,
+    0x14, 0x47, 0xb6, 0x25, 0x19, 0x08, 0x11, 0x2b, 0x1e, 0xe7, 0x6f, 0x99, 0xf3, 0x71, 0x1a, 0x52,
+    0xb6, 0x63, 0x09, 0x60, 0x04, 0x6c, 0x2d, 0xe7, 0x0d, 0xe1, 0x88, 0xd8, 0x33, 0xf8, 0xb8, 0xb9,
+    0x1e, 0x4d, 0x78, 0x5c, 0xae, 0xee, 0xaf, 0x4f, 0x0f, 0x74, 0x41, 0x4e, 0x2c, 0xda, 0x40, 0x64,
+    0x1f, 0x7f, 0xe2, 0x4f, 0x14, 0xc6, 0x7a, 0x88, 0x95, 0x9b, 0xdb, 0x27, 0x76, 0x6d, 0xf9, 0xe7,
+    0x10, 0xb6, 0x30, 0xa0, 0x3a, 0xdc, 0x68, 0x3b, 0x5d, 0x2c, 0x43, 0x08, 0x0e, 0x52, 0xbe, 0xe7,
+    0x1e, 0x9e, 0xae, 0xb6, 0xde, 0x29, 0x7a, 0x5f, 0xea, 0x10, 0x72, 0x07, 0x0d, 0x18, 0x1c, 0x82,
+    0x2b, 0xcc, 0xff, 0x08, 0x7d, 0x63, 0xc9, 0x40, 0xba, 0x8a, 0x45, 0xf6, 0x70, 0xfe, 0xb2, 0x9f,
+    0xb4, 0x48, 0x4d, 0x1c, 0x95, 0xe6, 0xd2, 0x57, 0x9b, 0xa0, 0x2a, 0xae, 0x0a, 0x00, 0x90, 0x0c,
+    0x3e, 0xbf, 0x49, 0x0e, 0x3d, 0x2c, 0xd7, 0xee, 0x8d, 0x0e, 0x20, 0xc5, 0x36, 0xe4, 0xdc, 0x5a,
+    0x50, 0x97, 0x27, 0x28, 0x88, 0xcd, 0xdd, 0x7e, 0x91, 0xf2, 0x28, 0xb1, 0xc4, 0xd7, 0x47, 0x4c,
+    0x55, 0xb8, 0xfc, 0xd6, 0x18, 0xc4, 0xa9, 0x57, 0xbb, 0xdd, 0xd5, 0xad, 0x74, 0x07, 0xcc, 0x31,
+    0x2d, 0x8d, 0x98, 0xa5, 0xca, 0xf7, 0xe0, 0x8f, 0x4a, 0x0d, 0x6b, 0x45, 0xbb, 0x41, 0xc6, 0x52,
+    0x65, 0x9d, 0x5a, 0x5b, 0xa0, 0x5b, 0x66, 0x37, 0x37, 0xa8, 0x69, 0x62, 0x81, 0x86, 0x5b, 0xa2,
+    0x0f, 0xbd, 0xd7, 0xf8, 0x51, 0xe6, 0xc5, 0x6e, 0x8c, 0xbe, 0x0d, 0xdb, 0xbf, 0x24, 0xdc, 0x03,
+    0xb2, 0xd2, 0xcb, 0x4c, 0x3d, 0x54, 0x0f, 0xb0, 0xaf, 0x52, 0xe0, 0x34, 0xa2, 0xd0, 0x66, 0x98,
+    0xb1, 0x28, 0xe5, 0xf1, 0x01, 0xe3, 0xb5, 0x1a, 0x34, 0xf8, 0xd8, 0xb4, 0xf8, 0x61, 0x81, 0x02,
+    0x81, 0x81, 0x00, 0xde, 0x39, 0x2e, 0x18, 0xd6, 0x82, 0xc8, 0x29, 0x26, 0x6c, 0xc3, 0x45, 0x4e,
+    0x1d, 0x61, 0x66, 0x24, 0x2f, 0x32, 0xd9, 0xa1, 0xd1, 0x05, 0x77, 0x75, 0x3e, 0x90, 0x4e, 0xa7,
+    0xd0, 0x8b, 0xff, 0x84, 0x1b, 0xe5, 0xba, 0xc8, 0x2a, 0x16, 0x4c, 0x59, 0x70, 0x00, 0x70, 0x47,
+    0xb8, 0xc5, 0x17, 0xdb, 0x8f, 0x8f, 0x84, 0xe3, 0x7b, 0xd5, 0x98, 0x85, 0x61, 0xbd, 0xf5, 0x03,
+    0xd4, 0xdc, 0x2b, 0xdb, 0x38, 0xf8, 0x85, 0x43, 0x4a, 0xe4, 0x2c, 0x35, 0x5f, 0x72, 0x5c, 0x9a,
+    0x60, 0xf9, 0x1f, 0x07, 0x88, 0xe1, 0xf1, 0xa9, 0x72, 0x23, 0xb5, 0x24, 0xb5, 0x35, 0x7f, 0xdf,
+    0x72, 0xe2, 0xf6, 0x96, 0xba, 0xb7, 0xd7, 0x8e, 0x32, 0xbf, 0x92, 0xba, 0x8e, 0x18, 0x64, 0xea,
+    0xb1, 0x22, 0x9e, 0x91, 0x34, 0x61, 0x30, 0x74, 0x8a, 0x6e, 0x3c, 0x12, 0x4f, 0x91, 0x49, 0xd7,
+    0x1c, 0x74, 0x35, 0x02, 0x81, 0x81, 0x00, 0xc9, 0x53, 0x87, 0xc0, 0xf9, 0xd3, 0x5f, 0x13, 0x7b,
+    0x57, 0xd0, 0xd6, 0x5c, 0x39, 0x7c, 0x5e, 0x21, 0xcc, 0x25, 0x1e, 0x47, 0x00, 0x8e, 0xd6, 0x2a,
+    0x54, 0x24, 0x09, 0xc8, 0xb6, 0xb6, 0xac, 0x7f, 0x89, 0x67, 0xb3, 0x86, 0x3c, 0xa6, 0x45, 0xfc,
+    0xce, 0x49, 0x58, 0x2a, 0x9a, 0xa1, 0x73, 0x49, 0xdb, 0x6c, 0x4a, 0x95, 0xaf, 0xfd, 0xae, 0x0d,
+    0xae, 0x61, 0x2e, 0x1a, 0xfa, 0xc9, 0x9e, 0xd3, 0x9a, 0x2d, 0x93, 0x4c, 0x88, 0x04, 0x40, 0xae,
+    0xd8, 0x83, 0x2f, 0x98, 0x43, 0x16, 0x3a, 0x47, 0xf2, 0x7f, 0x39, 0x21, 0x99, 0xdc, 0x12, 0x02,
+    0xf9, 0xa0, 0xf9, 0xbd, 0x08, 0x30, 0x80, 0x07, 0xcb, 0x1e, 0x4e, 0x7f, 0x58, 0x30, 0x93, 0x66,
+    0xa7, 0xde, 0x25, 0xf7, 0xc3, 0xc9, 0xb8, 0x80, 0x67, 0x7c, 0x06, 0x8e, 0x1b, 0xe9, 0x36, 0xe8,
+    0x12, 0x88, 0x81, 0x52, 0x52, 0xa8, 0xa1, 0x02, 0x81, 0x80, 0x57, 0xff, 0x8c, 0xa1, 0x89, 0x50,
+    0x80, 0xb2, 0xca, 0xe4, 0x86, 0xef, 0x0a, 0xdf, 0xd7, 0x91, 0xfb, 0x02, 0x35, 0xc0, 0xb8, 0xb3,
+    0x6c, 0xd6, 0xc1, 0x36, 0xe5, 0x2e, 0x40, 0x85, 0xf4, 0xea, 0x5a, 0x06, 0x32, 0x12, 0xa4, 0xf1,
+    0x05, 0xa3, 0x76, 0x47, 0x43, 0xe5, 0x32, 0x81, 0x98, 0x8a, 0xba, 0x07, 0x3f, 0x6e, 0x00, 0x27,
+    0x29, 0x8e, 0x1c, 0x43, 0x78, 0x55, 0x6e, 0x0e, 0xfc, 0xa0, 0xe1, 0x4e, 0xce, 0x1a, 0xf7, 0x6a,
+    0xd0, 0xb0, 0x30, 0xf2, 0x7a, 0xf6, 0xf0, 0xab, 0x35, 0xfb, 0x73, 0xa0, 0x60, 0xd8, 0xb1, 0xa0,
+    0xe1, 0x42, 0xfa, 0x26, 0x47, 0xe9, 0x3b, 0x32, 0xe3, 0x6d, 0x82, 0x82, 0xae, 0x0a, 0x4d, 0xe5,
+    0x0a, 0xb7, 0xaf, 0xe8, 0x55, 0x00, 0xa1, 0x6f, 0x43, 0xa6, 0x47, 0x19, 0xd6, 0xe2, 0xb9, 0x43,
+    0x98, 0x23, 0x71, 0x9c, 0xd0, 0x8b, 0xcd, 0x03, 0x17, 0x81, 0x02, 0x81, 0x81, 0x00, 0xba, 0x73,
+    0xb0, 0xbb, 0x28, 0xe3, 0xf8, 0x1e, 0x9b, 0xd1, 0xc5, 0x68, 0x71, 0x3b, 0x10, 0x12, 0x41, 0xac,
+    0xc6, 0x07, 0x97, 0x6c, 0x4d, 0xdc, 0xcc, 0x90, 0xe6, 0x5b, 0x65, 0x56, 0xca, 0x31, 0x51, 0x60,
+    0x58, 0xf9, 0x2b, 0x6e, 0x09, 0xf3, 0xb1, 0x60, 0xff, 0x0e, 0x37, 0x4e, 0xc4, 0x0d, 0x78, 0xae,
+    0x4d, 0x49, 0x79, 0xfd, 0xe6, 0xac, 0x06, 0xa1, 0xa4, 0x00, 0xc6, 0x1d, 0xd3, 0x12, 0x54, 0x18,
+    0x6a, 0xf3, 0x0b, 0x22, 0xc1, 0x05, 0x82, 0xa8, 0xa4, 0x3e, 0x34, 0xfe, 0x94, 0x9c, 0x5f, 0x3b,
+    0x97, 0x55, 0xba, 0xe7, 0xba, 0xa7, 0xb7, 0xb7, 0xa6, 0xbd, 0x03, 0xb3, 0x8c, 0xef, 0x55, 0xc8,
+    0x68, 0x85, 0xfc, 0x6c, 0x19, 0x78, 0xb9, 0xce, 0xe7, 0xef, 0x33, 0xda, 0x50, 0x7c, 0x9d, 0xf6,
+    0xb9, 0x27, 0x7c, 0xff, 0x1e, 0x6a, 0xaa, 0x5d, 0x57, 0xac, 0xa5, 0x28, 0x46, 0x61, 0x02, 0x81,
+    0x81, 0x00, 0xc9, 0x31, 0x61, 0x7c, 0x77, 0x82, 0x9d, 0xfb, 0x12, 0x70, 0x50, 0x2b, 0xe9, 0x19,
+    0x5c, 0x8f, 0x28, 0x30, 0x88, 0x5f, 0x57, 0xdb, 0xa8, 0x69, 0x53, 0x68, 0x11, 0xe6, 0x86, 0x42,
+    0x36, 0xd0, 0xc4, 0x73, 0x6a, 0x00, 0x08, 0xa1, 0x45, 0xaf, 0x36, 0xb8, 0x35, 0x7a, 0x7c, 0x3d,
+    0x13, 0x99, 0x66, 0xd0, 0x4c, 0x4e, 0x00, 0x93, 0x4e, 0xa1, 0xae, 0xde, 0x3b, 0xb6, 0xb8, 0xec,
+    0x84, 0x1d, 0xc9, 0x5e, 0x3f, 0x57, 0x97, 0x51, 0xe2, 0xbf, 0xdf, 0xe2, 0x7a, 0xe7, 0x78, 0x98,
+    0x3f, 0x95, 0x93, 0x56, 0x21, 0x07, 0x23, 0x28, 0x7b, 0x0a, 0xff, 0xcc, 0x9f, 0x72, 0x70, 0x44,
+    0xd4, 0x8c, 0x37, 0x3f, 0x1b, 0xab, 0xde, 0x07, 0x24, 0xfa, 0x17, 0xa4, 0xfd, 0x4d, 0xa0, 0x90,
+    0x2c, 0x7c, 0x9b, 0x9b, 0xf2, 0x7b, 0xa6, 0x1b, 0xe6, 0xad, 0x02, 0xdf, 0xdd, 0xda, 0x8f, 0x4e,
+    0x68, 0x22,
+];
+
+/// WrappedKeyData as ASN.1 DER-encoded data corresponding to the `SecureKeyWrapper` schema
+/// specified in IKeyMintDevice.aidl. Wrapped key parameters are -
+///     Algorithm: AES
+///     Key size: 256
+///     Block mode: ECB
+///     Padding mode: PKCS7
+/// This sample wrapped_key is taken from KeyMint tests (see KeyMintTest.cpp).
+pub static WRAPPED_KEY: &[u8] = &[
+    0x30, 0x82, 0x01, 0x79, 0x02, 0x01, 0x00, 0x04, 0x82, 0x01, 0x00, 0x93, 0x4b, 0xf9, 0x4e, 0x2a,
+    0xa2, 0x8a, 0x3f, 0x83, 0xc9, 0xf7, 0x92, 0x97, 0x25, 0x02, 0x62, 0xfb, 0xe3, 0x27, 0x6b, 0x5a,
+    0x1c, 0x91, 0x15, 0x9b, 0xbf, 0xa3, 0xef, 0x89, 0x57, 0xaa, 0xc8, 0x4b, 0x59, 0xb3, 0x0b, 0x45,
+    0x5a, 0x79, 0xc2, 0x97, 0x34, 0x80, 0x82, 0x3d, 0x8b, 0x38, 0x63, 0xc3, 0xde, 0xef, 0x4a, 0x8e,
+    0x24, 0x35, 0x90, 0x26, 0x8d, 0x80, 0xe1, 0x87, 0x51, 0xa0, 0xe1, 0x30, 0xf6, 0x7c, 0xe6, 0xa1,
+    0xac, 0xe9, 0xf7, 0x9b, 0x95, 0xe0, 0x97, 0x47, 0x4f, 0xeb, 0xc9, 0x81, 0x19, 0x5b, 0x1d, 0x13,
+    0xa6, 0x90, 0x86, 0xc0, 0x86, 0x3f, 0x66, 0xa7, 0xb7, 0xfd, 0xb4, 0x87, 0x92, 0x22, 0x7b, 0x1a,
+    0xc5, 0xe2, 0x48, 0x9f, 0xeb, 0xdf, 0x08, 0x7a, 0xb5, 0x48, 0x64, 0x83, 0x03, 0x3a, 0x6f, 0x00,
+    0x1c, 0xa5, 0xd1, 0xec, 0x1e, 0x27, 0xf5, 0xc3, 0x0f, 0x4c, 0xec, 0x26, 0x42, 0x07, 0x4a, 0x39,
+    0xae, 0x68, 0xae, 0xe5, 0x52, 0xe1, 0x96, 0x62, 0x7a, 0x8e, 0x3d, 0x86, 0x7e, 0x67, 0xa8, 0xc0,
+    0x1b, 0x11, 0xe7, 0x5f, 0x13, 0xcc, 0xa0, 0xa9, 0x7a, 0xb6, 0x68, 0xb5, 0x0c, 0xda, 0x07, 0xa8,
+    0xec, 0xb7, 0xcd, 0x8e, 0x3d, 0xd7, 0x00, 0x9c, 0x96, 0x36, 0x53, 0x4f, 0x6f, 0x23, 0x9c, 0xff,
+    0xe1, 0xfc, 0x8d, 0xaa, 0x46, 0x6f, 0x78, 0xb6, 0x76, 0xc7, 0x11, 0x9e, 0xfb, 0x96, 0xbc, 0xe4,
+    0xe6, 0x9c, 0xa2, 0xa2, 0x5d, 0x0b, 0x34, 0xed, 0x9c, 0x3f, 0xf9, 0x99, 0xb8, 0x01, 0x59, 0x7d,
+    0x52, 0x20, 0xe3, 0x07, 0xea, 0xa5, 0xbe, 0xe5, 0x07, 0xfb, 0x94, 0xd1, 0xfa, 0x69, 0xf9, 0xe5,
+    0x19, 0xb2, 0xde, 0x31, 0x5b, 0xac, 0x92, 0xc3, 0x6f, 0x2e, 0xa1, 0xfa, 0x1d, 0xf4, 0x47, 0x8c,
+    0x0d, 0xde, 0xde, 0xae, 0x8c, 0x70, 0xe0, 0x23, 0x3c, 0xd0, 0x98, 0x04, 0x0c, 0xd7, 0x96, 0xb0,
+    0x2c, 0x37, 0x0f, 0x1f, 0xa4, 0xcc, 0x01, 0x24, 0xf1, 0x30, 0x2e, 0x02, 0x01, 0x03, 0x30, 0x29,
+    0xa1, 0x08, 0x31, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0xa2, 0x03, 0x02, 0x01, 0x20, 0xa3,
+    0x04, 0x02, 0x02, 0x01, 0x00, 0xa4, 0x05, 0x31, 0x03, 0x02, 0x01, 0x01, 0xa6, 0x05, 0x31, 0x03,
+    0x02, 0x01, 0x40, 0xbf, 0x83, 0x77, 0x02, 0x05, 0x00, 0x04, 0x20, 0xcc, 0xd5, 0x40, 0x85, 0x5f,
+    0x83, 0x3a, 0x5e, 0x14, 0x80, 0xbf, 0xd2, 0xd3, 0x6f, 0xaf, 0x3a, 0xee, 0xe1, 0x5d, 0xf5, 0xbe,
+    0xab, 0xe2, 0x69, 0x1b, 0xc8, 0x2d, 0xde, 0x2a, 0x7a, 0xa9, 0x10, 0x04, 0x10, 0x64, 0xc9, 0xf6,
+    0x89, 0xc6, 0x0f, 0xf6, 0x22, 0x3a, 0xb6, 0xe6, 0x99, 0x9e, 0x0e, 0xb6, 0xe5,
+];
+
 /// To map Keystore errors.
 #[derive(thiserror::Error, Debug, Eq, PartialEq)]
 pub enum Error {
@@ -172,6 +296,9 @@
     /// This is returned if the C implementation of extractSubjectFromCertificate failed.
     #[error("Failed to validate certificate chain.")]
     ValidateCertChainFailed,
+    /// Error code to indicate error in ASN.1 DER-encoded data creation.
+    #[error("Failed to create and encode ASN.1 data.")]
+    DerEncodeFailed,
 }
 
 /// Keystore2 error mapping.
@@ -209,7 +336,6 @@
     nspace: i64,
     alias: Option<String>,
     att_challenge: Option<&[u8]>,
-    att_app_id: Option<&[u8]>,
 ) -> binder::Result<KeyMetadata> {
     let mut key_attest = false;
     let mut gen_params = AuthSetBuilder::new()
@@ -225,11 +351,6 @@
         gen_params = gen_params.clone().attestation_challenge(challenge.to_vec());
     }
 
-    if let Some(app_id) = att_app_id {
-        key_attest = true;
-        gen_params = gen_params.clone().attestation_app_id(app_id.to_vec());
-    }
-
     match sec_level.generateKey(
         &KeyDescriptor { domain, nspace, alias, blob: None },
         None,
@@ -324,9 +445,6 @@
     if let Some(value) = &key_params.att_challenge {
         gen_params = gen_params.attestation_challenge(value.to_vec())
     }
-    if let Some(value) = &key_params.att_app_id {
-        gen_params = gen_params.attestation_app_id(value.to_vec())
-    }
 
     let key_metadata = sec_level.generateKey(
         &KeyDescriptor { domain, nspace, alias, blob: None },
@@ -339,8 +457,7 @@
     // Must have a public key.
     assert!(key_metadata.certificate.is_some());
 
-    if attest_key.is_none() && key_params.att_challenge.is_some() && key_params.att_app_id.is_some()
-    {
+    if attest_key.is_none() && key_params.att_challenge.is_some() {
         // Should have an attestation record.
         assert!(key_metadata.certificateChain.is_some());
     } else {
@@ -449,7 +566,6 @@
     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
     algorithm: Algorithm,
     att_challenge: &[u8],
-    att_app_id: &[u8],
 ) -> binder::Result<KeyMetadata> {
     assert!(algorithm == Algorithm::RSA || algorithm == Algorithm::EC);
 
@@ -468,7 +584,6 @@
                 mgf_digest: None,
                 block_mode: None,
                 att_challenge: Some(att_challenge.to_vec()),
-                att_app_id: Some(att_app_id.to_vec()),
             },
             None,
         )
@@ -478,7 +593,6 @@
         let metadata = generate_ec_attestation_key(
             sec_level,
             att_challenge,
-            att_app_id,
             Digest::SHA_2_256,
             EcCurve::P_256,
         )
@@ -493,7 +607,6 @@
 pub fn generate_ec_attestation_key(
     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
     att_challenge: &[u8],
-    att_app_id: &[u8],
     digest: Digest,
     ec_curve: EcCurve,
 ) -> binder::Result<KeyMetadata> {
@@ -504,8 +617,7 @@
         .purpose(KeyPurpose::ATTEST_KEY)
         .ec_curve(ec_curve)
         .digest(digest)
-        .attestation_challenge(att_challenge.to_vec())
-        .attestation_app_id(att_app_id.to_vec());
+        .attestation_challenge(att_challenge.to_vec());
 
     let attestation_key_metadata = sec_level.generateKey(
         &KeyDescriptor {
@@ -533,7 +645,6 @@
     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
     alias: Option<String>,
     att_challenge: &[u8],
-    att_app_id: &[u8],
     attest_key: &KeyDescriptor,
 ) -> binder::Result<KeyMetadata> {
     let ec_gen_params = AuthSetBuilder::new()
@@ -543,8 +654,7 @@
         .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());
+        .attestation_challenge(att_challenge.to_vec());
 
     let ec_key_metadata = sec_level
         .generateKey(
@@ -564,7 +674,8 @@
     Ok(ec_key_metadata)
 }
 
-fn check_key_param(authorizations: &[Authorization], key_param: KeyParameter) -> bool {
+/// Verify that given key param is listed in given authorizations list.
+pub fn check_key_param(authorizations: &[Authorization], key_param: KeyParameter) -> bool {
     for authrization in authorizations {
         if authrization.keyParameter == key_param {
             return true;
@@ -836,3 +947,103 @@
 
     Ok(key_metadata)
 }
+
+/// Imports RSA encryption key with WRAP_KEY purpose.
+pub fn import_wrapping_key(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    wrapping_key_data: &[u8],
+    wrapping_key_alias: Option<String>,
+) -> binder::Result<KeyMetadata> {
+    let wrapping_key_params = AuthSetBuilder::new()
+        .no_auth_required()
+        .algorithm(Algorithm::RSA)
+        .digest(Digest::SHA_2_256)
+        .purpose(KeyPurpose::ENCRYPT)
+        .purpose(KeyPurpose::DECRYPT)
+        .purpose(KeyPurpose::WRAP_KEY)
+        .padding_mode(PaddingMode::RSA_OAEP)
+        .key_size(2048)
+        .rsa_public_exponent(65537)
+        .cert_not_before(0)
+        .cert_not_after(253402300799000);
+
+    sec_level.importKey(
+        &KeyDescriptor { domain: Domain::APP, nspace: -1, alias: wrapping_key_alias, blob: None },
+        None,
+        &wrapping_key_params,
+        0,
+        wrapping_key_data,
+    )
+}
+
+/// Import wrapped key using given wrapping key.
+pub fn import_wrapped_key(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    alias: Option<String>,
+    wrapping_key_metadata: &KeyMetadata,
+    wrapped_key: Option<Vec<u8>>,
+) -> binder::Result<KeyMetadata> {
+    let unwrap_params =
+        AuthSetBuilder::new().digest(Digest::SHA_2_256).padding_mode(PaddingMode::RSA_OAEP);
+
+    let authenticator_spec: &[AuthenticatorSpec] = &[AuthenticatorSpec {
+        authenticatorType: HardwareAuthenticatorType::NONE,
+        authenticatorId: 0,
+    }];
+
+    let key_metadata = sec_level.importWrappedKey(
+        &KeyDescriptor { domain: Domain::APP, nspace: -1, alias, blob: wrapped_key },
+        &wrapping_key_metadata.key,
+        None,
+        &unwrap_params,
+        authenticator_spec,
+    )?;
+
+    Ok(key_metadata)
+}
+
+/// Import wrapping key and then import wrapped key using wrapping key.
+pub fn import_wrapping_key_and_wrapped_key(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    domain: Domain,
+    nspace: i64,
+    alias: Option<String>,
+    wrapping_key_alias: Option<String>,
+    wrapping_key_params: AuthSetBuilder,
+) -> binder::Result<KeyMetadata> {
+    let wrapping_key_metadata = sec_level.importKey(
+        &KeyDescriptor { domain, nspace, alias: wrapping_key_alias, blob: None },
+        None,
+        &wrapping_key_params,
+        0,
+        WRAPPING_KEY,
+    )?;
+
+    import_wrapped_key(sec_level, alias, &wrapping_key_metadata, Some(WRAPPED_KEY.to_vec()))
+}
+
+/// Import given key material as AES-256-GCM-NONE transport key.
+pub fn import_transport_key(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    transport_key_alias: Option<String>,
+    transport_key: &[u8],
+) -> binder::Result<KeyMetadata> {
+    let transport_key_params = AuthSetBuilder::new()
+        .no_auth_required()
+        .algorithm(Algorithm::AES)
+        .block_mode(BlockMode::GCM)
+        .padding_mode(PaddingMode::NONE)
+        .key_size(256)
+        .caller_nonce()
+        .min_mac_length(128)
+        .purpose(KeyPurpose::ENCRYPT)
+        .purpose(KeyPurpose::DECRYPT);
+
+    sec_level.importKey(
+        &KeyDescriptor { domain: Domain::APP, nspace: -1, alias: transport_key_alias, blob: None },
+        None,
+        &transport_key_params,
+        0,
+        transport_key,
+    )
+}
diff --git a/keystore2/tests/Android.bp b/keystore2/tests/Android.bp
index dd5d782..78dd2d7 100644
--- a/keystore2/tests/Android.bp
+++ b/keystore2/tests/Android.bp
@@ -36,7 +36,7 @@
     rustlibs: [
         "librustutils",
         "libkeystore2_test_utils",
-	"packagemanager_aidl-rust",
+        "packagemanager_aidl-rust",
         "libnix",
         "libanyhow",
         "libbinder_rs",
@@ -44,8 +44,8 @@
         "liblibc",
         "libserde",
         "libthiserror",
-	"libcxx",
-	"libopenssl",
+        "libcxx",
+        "libopenssl",
     ],
     static_libs: [
         "libkeystore2_ffi_test_utils",
@@ -54,6 +54,9 @@
     ],
     shared_libs: [
         "libcrypto",
+        "libkeymaster_portable",
+        "libkeymaster_messages",
+        "libcppbor_external",
     ],
     require_root: true,
 }
@@ -67,17 +70,31 @@
     ],
     generated_headers: [
         "cxx-bridge-header",
+        "libkeystore2_ffi_test_utils_bridge_header",
     ],
     generated_sources: ["libkeystore2_ffi_test_utils_bridge_code"],
     static_libs: [
         "libkeymint_vts_test_utils",
     ],
+    shared_libs: [
+        "libkeymaster_portable",
+        "libkeymaster_messages",
+        "libcppbor_external",
+    ],
 }
 
 genrule {
     name: "libkeystore2_ffi_test_utils_bridge_code",
     tools: ["cxxbridge"],
     cmd: "$(location cxxbridge) $(in) >> $(out)",
-    srcs: ["keystore2_client_attest_key_tests.rs"],
+    srcs: ["ffi_test_utils.rs"],
     out: ["libkeystore2_test_utils_cxx_generated.cc"],
 }
+
+genrule {
+    name: "libkeystore2_ffi_test_utils_bridge_header",
+    tools: ["cxxbridge"],
+    cmd: "$(location cxxbridge) $(in) --header >> $(out)",
+    srcs: ["ffi_test_utils.rs"],
+    out: ["ffi_test_utils.rs.h"],
+}
diff --git a/keystore2/tests/ffi_test_utils.cpp b/keystore2/tests/ffi_test_utils.cpp
index fb5a7d2..de20d83 100644
--- a/keystore2/tests/ffi_test_utils.cpp
+++ b/keystore2/tests/ffi_test_utils.cpp
@@ -4,15 +4,86 @@
 
 #include <KeyMintAidlTestBase.h>
 #include <aidl/android/hardware/security/keymint/ErrorCode.h>
+#include <keymaster/UniquePtr.h>
 
+#include <memory>
 #include <vector>
 
+#include <hardware/keymaster_defs.h>
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/keymaster_tags.h>
+
+#include <keymaster/km_openssl/attestation_record.h>
+#include <keymaster/km_openssl/openssl_err.h>
+#include <keymaster/km_openssl/openssl_utils.h>
+#include <openssl/asn1t.h>
+
 using aidl::android::hardware::security::keymint::ErrorCode;
 
 #define TAG_SEQUENCE 0x30
 #define LENGTH_MASK 0x80
 #define LENGTH_VALUE_MASK 0x7F
 
+/**
+ * ASN.1 structure for `KeyDescription` Schema.
+ * See `IKeyMintDevice.aidl` for documentation of the `KeyDescription` schema.
+ *    KeyDescription ::= SEQUENCE(
+ *        keyFormat INTEGER,                   # Values from KeyFormat enum.
+ *        keyParams AuthorizationList,
+ *    )
+ */
+typedef struct key_description {
+    ASN1_INTEGER* key_format;
+    keymaster::KM_AUTH_LIST* key_params;
+} TEST_KEY_DESCRIPTION;
+
+ASN1_SEQUENCE(TEST_KEY_DESCRIPTION) = {
+    ASN1_SIMPLE(TEST_KEY_DESCRIPTION, key_format, ASN1_INTEGER),
+    ASN1_SIMPLE(TEST_KEY_DESCRIPTION, key_params, keymaster::KM_AUTH_LIST),
+} ASN1_SEQUENCE_END(TEST_KEY_DESCRIPTION);
+DECLARE_ASN1_FUNCTIONS(TEST_KEY_DESCRIPTION);
+
+/**
+ * ASN.1 structure for `SecureKeyWrapper` Schema.
+ * See `IKeyMintDevice.aidl` for documentation of the `SecureKeyWrapper` schema.
+ *    SecureKeyWrapper ::= SEQUENCE(
+ *        version INTEGER,                     # Contains value 0
+ *        encryptedTransportKey OCTET_STRING,
+ *        initializationVector OCTET_STRING,
+ *        keyDescription KeyDescription,
+ *        encryptedKey OCTET_STRING,
+ *        tag OCTET_STRING
+ *    )
+ */
+typedef struct secure_key_wrapper {
+    ASN1_INTEGER* version;
+    ASN1_OCTET_STRING* encrypted_transport_key;
+    ASN1_OCTET_STRING* initialization_vector;
+    TEST_KEY_DESCRIPTION* key_desc;
+    ASN1_OCTET_STRING* encrypted_key;
+    ASN1_OCTET_STRING* tag;
+} TEST_SECURE_KEY_WRAPPER;
+
+ASN1_SEQUENCE(TEST_SECURE_KEY_WRAPPER) = {
+    ASN1_SIMPLE(TEST_SECURE_KEY_WRAPPER, version, ASN1_INTEGER),
+    ASN1_SIMPLE(TEST_SECURE_KEY_WRAPPER, encrypted_transport_key, ASN1_OCTET_STRING),
+    ASN1_SIMPLE(TEST_SECURE_KEY_WRAPPER, initialization_vector, ASN1_OCTET_STRING),
+    ASN1_SIMPLE(TEST_SECURE_KEY_WRAPPER, key_desc, TEST_KEY_DESCRIPTION),
+    ASN1_SIMPLE(TEST_SECURE_KEY_WRAPPER, encrypted_key, ASN1_OCTET_STRING),
+    ASN1_SIMPLE(TEST_SECURE_KEY_WRAPPER, tag, ASN1_OCTET_STRING),
+} ASN1_SEQUENCE_END(TEST_SECURE_KEY_WRAPPER);
+DECLARE_ASN1_FUNCTIONS(TEST_SECURE_KEY_WRAPPER);
+
+IMPLEMENT_ASN1_FUNCTIONS(TEST_SECURE_KEY_WRAPPER);
+IMPLEMENT_ASN1_FUNCTIONS(TEST_KEY_DESCRIPTION);
+
+struct TEST_KEY_DESCRIPTION_Delete {
+    void operator()(TEST_KEY_DESCRIPTION* p) { TEST_KEY_DESCRIPTION_free(p); }
+};
+struct TEST_SECURE_KEY_WRAPPER_Delete {
+    void operator()(TEST_SECURE_KEY_WRAPPER* p) { TEST_SECURE_KEY_WRAPPER_free(p); }
+};
+
 /* This function extracts a certificate from the certs_chain_buffer at the given
  * offset. Each DER encoded certificate starts with TAG_SEQUENCE followed by the
  * total length of the certificate. The length of the certificate is determined
@@ -118,3 +189,178 @@
 
     return false;
 }
+
+/**
+ * Below mentioned key parameters are used to create authorization list of
+ * secure key.
+ *    Algorithm: AES-256
+ *    Padding: PKCS7
+ *    Blockmode: ECB
+ *    Purpose: Encrypt, Decrypt
+ */
+keymaster::AuthorizationSet build_wrapped_key_auth_list() {
+    return keymaster::AuthorizationSet(keymaster::AuthorizationSetBuilder()
+                                           .AesEncryptionKey(256)
+                                           .Authorization(keymaster::TAG_BLOCK_MODE, KM_MODE_ECB)
+                                           .Authorization(keymaster::TAG_PADDING, KM_PAD_PKCS7)
+                                           .Authorization(keymaster::TAG_NO_AUTH_REQUIRED));
+}
+
+/**
+ * Creates ASN.1 DER-encoded data corresponding to `KeyDescription` schema as
+ * AAD. See `IKeyMintDevice.aidl` for documentation of the `KeyDescription` schema.
+ */
+CxxResult buildAsn1DerEncodedWrappedKeyDescription() {
+    CxxResult cxx_result{};
+    keymaster_error_t error;
+    cxx_result.error = KM_ERROR_OK;
+
+    keymaster::UniquePtr<TEST_KEY_DESCRIPTION, TEST_KEY_DESCRIPTION_Delete> key_description(
+        TEST_KEY_DESCRIPTION_new());
+    if (!key_description.get()) {
+        cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return cxx_result;
+    }
+
+    // Fill secure key authorizations.
+    keymaster::AuthorizationSet auth_list = build_wrapped_key_auth_list();
+    error = build_auth_list(auth_list, key_description->key_params);
+    if (error != KM_ERROR_OK) {
+        cxx_result.error = error;
+        return cxx_result;
+    }
+
+    // Fill secure key format.
+    if (!ASN1_INTEGER_set(key_description->key_format, KM_KEY_FORMAT_RAW)) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+
+    // Perform ASN.1 DER encoding of KeyDescription.
+    int asn1_data_len = i2d_TEST_KEY_DESCRIPTION(key_description.get(), nullptr);
+    if (asn1_data_len < 0) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+    std::vector<uint8_t> asn1_data(asn1_data_len, 0);
+
+    if (!asn1_data.data()) {
+        cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return cxx_result;
+    }
+
+    uint8_t* p = asn1_data.data();
+    asn1_data_len = i2d_TEST_KEY_DESCRIPTION(key_description.get(), &p);
+    if (asn1_data_len < 0) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+
+    std::move(asn1_data.begin(), asn1_data.end(), std::back_inserter(cxx_result.data));
+
+    return cxx_result;
+}
+
+/**
+ * Creates wrapped key material to import in ASN.1 DER-encoded data corresponding to
+ * `SecureKeyWrapper` schema. See `IKeyMintDevice.aidl` for documentation of the `SecureKeyWrapper`
+ * schema.
+ */
+CxxResult createWrappedKey(rust::Vec<rust::u8> encrypted_secure_key,
+                           rust::Vec<rust::u8> encrypted_transport_key, rust::Vec<rust::u8> iv,
+                           rust::Vec<rust::u8> tag) {
+    CxxResult cxx_result{};
+    keymaster_error_t error;
+    cxx_result.error = KM_ERROR_OK;
+
+    uint8_t* enc_secure_key_data = encrypted_secure_key.data();
+    int enc_secure_key_size = encrypted_secure_key.size();
+
+    uint8_t* iv_data = iv.data();
+    int iv_size = iv.size();
+
+    uint8_t* tag_data = tag.data();
+    int tag_size = tag.size();
+
+    uint8_t* enc_transport_key_data = encrypted_transport_key.data();
+    int enc_transport_key_size = encrypted_transport_key.size();
+
+    keymaster::UniquePtr<TEST_SECURE_KEY_WRAPPER, TEST_SECURE_KEY_WRAPPER_Delete> sec_key_wrapper(
+        TEST_SECURE_KEY_WRAPPER_new());
+    if (!sec_key_wrapper.get()) {
+        cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return cxx_result;
+    }
+
+    // Fill version = 0
+    if (!ASN1_INTEGER_set(sec_key_wrapper->version, 0)) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+
+    // Fill encrypted transport key.
+    if (enc_transport_key_size &&
+        !ASN1_OCTET_STRING_set(sec_key_wrapper->encrypted_transport_key, enc_transport_key_data,
+                               enc_transport_key_size)) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+
+    // Fill encrypted secure key.
+    if (enc_secure_key_size && !ASN1_OCTET_STRING_set(sec_key_wrapper->encrypted_key,
+                                                      enc_secure_key_data, enc_secure_key_size)) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+
+    // Fill secure key authorization list.
+    keymaster::AuthorizationSet auth_list = build_wrapped_key_auth_list();
+    error = build_auth_list(auth_list, sec_key_wrapper->key_desc->key_params);
+    if (error != KM_ERROR_OK) {
+        cxx_result.error = error;
+        return cxx_result;
+    }
+
+    // Fill secure key format.
+    if (!ASN1_INTEGER_set(sec_key_wrapper->key_desc->key_format, KM_KEY_FORMAT_RAW)) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+
+    // Fill initialization vector used for encrypting secure key.
+    if (iv_size &&
+        !ASN1_OCTET_STRING_set(sec_key_wrapper->initialization_vector, iv_data, iv_size)) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+
+    // Fill GCM-tag, extracted during secure key encryption.
+    if (tag_size && !ASN1_OCTET_STRING_set(sec_key_wrapper->tag, tag_data, tag_size)) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+
+    // ASN.1 DER-encoding of secure key wrapper.
+    int asn1_data_len = i2d_TEST_SECURE_KEY_WRAPPER(sec_key_wrapper.get(), nullptr);
+    if (asn1_data_len < 0) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+    std::vector<uint8_t> asn1_data(asn1_data_len, 0);
+
+    if (!asn1_data.data()) {
+        cxx_result.error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
+        return cxx_result;
+    }
+
+    uint8_t* p = asn1_data.data();
+    asn1_data_len = i2d_TEST_SECURE_KEY_WRAPPER(sec_key_wrapper.get(), &p);
+    if (asn1_data_len < 0) {
+        cxx_result.error = keymaster::TranslateLastOpenSslError();
+        return cxx_result;
+    }
+
+    std::move(asn1_data.begin(), asn1_data.end(), std::back_inserter(cxx_result.data));
+
+    return cxx_result;
+}
diff --git a/keystore2/tests/ffi_test_utils.hpp b/keystore2/tests/ffi_test_utils.hpp
index 7f5c3b2..b8c7c48 100644
--- a/keystore2/tests/ffi_test_utils.hpp
+++ b/keystore2/tests/ffi_test_utils.hpp
@@ -1,5 +1,11 @@
 #pragma once
 
 #include "rust/cxx.h"
+#include "ffi_test_utils.rs.h"
 
 bool validateCertChain(rust::Vec<rust::u8> cert_buf, uint32_t cert_len, bool strict_issuer_check);
+CxxResult createWrappedKey(rust::Vec<rust::u8> encrypted_secure_key,
+                              rust::Vec<rust::u8> encrypted_transport_key,
+                              rust::Vec<rust::u8> iv,
+                              rust::Vec<rust::u8> tag);
+CxxResult buildAsn1DerEncodedWrappedKeyDescription();
diff --git a/keystore2/tests/ffi_test_utils.rs b/keystore2/tests/ffi_test_utils.rs
new file mode 100644
index 0000000..066d4a1
--- /dev/null
+++ b/keystore2/tests/ffi_test_utils.rs
@@ -0,0 +1,80 @@
+// 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 keystore2_test_utils::key_generations::Error;
+
+#[cxx::bridge]
+mod ffi {
+    struct CxxResult {
+        data: Vec<u8>,
+        error: i32,
+    }
+
+    unsafe extern "C++" {
+        include!("ffi_test_utils.hpp");
+        fn validateCertChain(cert_buf: Vec<u8>, cert_len: u32, strict_issuer_check: bool) -> bool;
+        fn createWrappedKey(
+            encrypted_secure_key: Vec<u8>,
+            encrypted_transport_key: Vec<u8>,
+            iv: Vec<u8>,
+            tag: Vec<u8>,
+        ) -> CxxResult;
+        fn buildAsn1DerEncodedWrappedKeyDescription() -> CxxResult;
+    }
+}
+
+/// Validate given certificate chain.
+pub fn validate_certchain(cert_buf: &[u8]) -> Result<bool, Error> {
+    if ffi::validateCertChain(cert_buf.to_vec(), cert_buf.len().try_into().unwrap(), true) {
+        return Ok(true);
+    }
+
+    Err(Error::ValidateCertChainFailed)
+}
+
+fn get_result(result: ffi::CxxResult) -> Result<Vec<u8>, Error> {
+    if result.error == 0 && !result.data.is_empty() {
+        Ok(result.data)
+    } else {
+        Err(Error::DerEncodeFailed)
+    }
+}
+
+/// Creates wrapped key material to import in ASN.1 DER-encoded data corresponding to
+/// `SecureKeyWrapper`. See `IKeyMintDevice.aidl` for documentation of the `SecureKeyWrapper`
+/// schema.
+pub fn create_wrapped_key(
+    encrypted_secure_key: &[u8],
+    encrypted_transport_key: &[u8],
+    iv: &[u8],
+    tag: &[u8],
+) -> Result<Vec<u8>, Error> {
+    get_result(ffi::createWrappedKey(
+        encrypted_secure_key.to_vec(),
+        encrypted_transport_key.to_vec(),
+        iv.to_vec(),
+        tag.to_vec(),
+    ))
+}
+
+/// Creates ASN.1 DER-encoded data corresponding to `KeyDescription` schema.
+/// See `IKeyMintDevice.aidl` for documentation of the `KeyDescription` schema.
+/// Below mentioned key parameters are used -
+///     Algorithm: AES-256
+///     Padding: PKCS7
+///     Blockmode: ECB
+///     Purpose: Encrypt, Decrypt
+pub fn create_wrapped_key_additional_auth_data() -> Result<Vec<u8>, Error> {
+    get_result(ffi::buildAsn1DerEncodedWrappedKeyDescription())
+}
diff --git a/keystore2/tests/keystore2_client_aes_key_tests.rs b/keystore2/tests/keystore2_client_aes_key_tests.rs
index 885cbf5..313f596 100644
--- a/keystore2/tests/keystore2_client_aes_key_tests.rs
+++ b/keystore2/tests/keystore2_client_aes_key_tests.rs
@@ -26,8 +26,7 @@
 };
 
 use crate::keystore2_client_test_utils::{
-    has_trusty_keymint, perform_sample_sym_key_decrypt_op, perform_sample_sym_key_encrypt_op,
-    SAMPLE_PLAIN_TEXT,
+    perform_sample_sym_key_decrypt_op, perform_sample_sym_key_encrypt_op, SAMPLE_PLAIN_TEXT,
 };
 
 /// Generate a AES key. Create encrypt and decrypt operations using the generated key.
@@ -393,11 +392,11 @@
     ));
     assert!(result.is_err());
 
-    if has_trusty_keymint() {
-        assert_eq!(result.unwrap_err(), Error::Km(ErrorCode::MISSING_MAC_LENGTH));
-    } else {
-        assert_eq!(result.unwrap_err(), Error::Km(ErrorCode::UNSUPPORTED_MAC_LENGTH));
-    }
+    let e = result.unwrap_err();
+    assert!(
+        e == Error::Km(ErrorCode::MISSING_MAC_LENGTH)
+            || e == Error::Km(ErrorCode::UNSUPPORTED_MAC_LENGTH)
+    );
 }
 
 /// Generate a AES-GCM key with `MIN_MAC_LENGTH`. Try to create an operation using this
diff --git a/keystore2/tests/keystore2_client_attest_key_tests.rs b/keystore2/tests/keystore2_client_attest_key_tests.rs
index fc3148c..4febd9b 100644
--- a/keystore2/tests/keystore2_client_attest_key_tests.rs
+++ b/keystore2/tests/keystore2_client_attest_key_tests.rs
@@ -27,28 +27,13 @@
     authorizations, get_keystore_service, key_generations, key_generations::Error,
 };
 
+use crate::ffi_test_utils::validate_certchain;
+
 use crate::{
     keystore2_client_test_utils::app_attest_key_feature_exists,
     skip_test_if_no_app_attest_key_feature,
 };
 
-#[cxx::bridge]
-mod ffi {
-    unsafe extern "C++" {
-        include!("ffi_test_utils.hpp");
-        fn validateCertChain(cert_buf: Vec<u8>, cert_len: u32, strict_issuer_check: bool) -> bool;
-    }
-}
-
-/// Validate given certificate chain.
-pub fn validate_certchain(cert_buf: &[u8]) -> Result<bool, Error> {
-    if ffi::validateCertChain(cert_buf.to_vec(), cert_buf.len().try_into().unwrap(), true) {
-        return Ok(true);
-    }
-
-    Err(Error::ValidateCertChainFailed)
-}
-
 /// Generate RSA and EC attestation keys and use them for signing RSA-signing keys.
 /// Test should be able to generate attestation keys and use them successfully.
 #[test]
@@ -58,13 +43,11 @@
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let att_challenge: &[u8] = b"foo";
-    let att_app_id: &[u8] = b"bar";
 
     for algo in [Algorithm::RSA, Algorithm::EC] {
         // Create attestation key.
         let attestation_key_metadata =
-            key_generations::generate_attestation_key(&sec_level, algo, att_challenge, att_app_id)
-                .unwrap();
+            key_generations::generate_attestation_key(&sec_level, algo, att_challenge).unwrap();
 
         let mut cert_chain: Vec<u8> = Vec::new();
         cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
@@ -86,7 +69,6 @@
                 mgf_digest: None,
                 block_mode: None,
                 att_challenge: Some(att_challenge.to_vec()),
-                att_app_id: Some(att_app_id.to_vec()),
             },
             Some(&attestation_key_metadata.key),
         )
@@ -109,13 +91,11 @@
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let att_challenge: &[u8] = b"foo";
-    let att_app_id: &[u8] = b"bar";
 
     for algo in [Algorithm::RSA, Algorithm::EC] {
         // Create attestation key.
         let attestation_key_metadata =
-            key_generations::generate_attestation_key(&sec_level, algo, att_challenge, att_app_id)
-                .unwrap();
+            key_generations::generate_attestation_key(&sec_level, algo, att_challenge).unwrap();
 
         let mut cert_chain: Vec<u8> = Vec::new();
         cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
@@ -137,7 +117,6 @@
                 mgf_digest: None,
                 block_mode: None,
                 att_challenge: Some(att_challenge.to_vec()),
-                att_app_id: Some(att_app_id.to_vec()),
             },
             Some(&attestation_key_metadata.key),
         )
@@ -161,13 +140,11 @@
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let att_challenge: &[u8] = b"foo";
-    let att_app_id: &[u8] = b"bar";
 
     for algo in [Algorithm::RSA, Algorithm::EC] {
         // Create attestation key.
         let attestation_key_metadata =
-            key_generations::generate_attestation_key(&sec_level, algo, att_challenge, att_app_id)
-                .unwrap();
+            key_generations::generate_attestation_key(&sec_level, algo, att_challenge).unwrap();
 
         let mut cert_chain: Vec<u8> = Vec::new();
         cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
@@ -180,7 +157,6 @@
             &sec_level,
             Some(ec_key_alias),
             att_challenge,
-            att_app_id,
             &attestation_key_metadata.key,
         )
         .unwrap();
@@ -204,13 +180,11 @@
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let att_challenge: &[u8] = b"foo";
-    let att_app_id: &[u8] = b"bar";
 
     // Create EcCurve::CURVE_25519 attestation key.
     let attestation_key_metadata = key_generations::generate_ec_attestation_key(
         &sec_level,
         att_challenge,
-        att_app_id,
         Digest::NONE,
         EcCurve::CURVE_25519,
     )
@@ -236,7 +210,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: Some(att_challenge.to_vec()),
-            att_app_id: Some(att_app_id.to_vec()),
         },
         Some(&attestation_key_metadata.key),
     )
@@ -338,16 +311,11 @@
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let att_challenge: &[u8] = b"foo";
-    let att_app_id: &[u8] = b"bar";
 
     // Create RSA attestation key.
-    let attestation_key_metadata = key_generations::generate_attestation_key(
-        &sec_level,
-        Algorithm::RSA,
-        att_challenge,
-        att_app_id,
-    )
-    .unwrap();
+    let attestation_key_metadata =
+        key_generations::generate_attestation_key(&sec_level, Algorithm::RSA, att_challenge)
+            .unwrap();
 
     let mut cert_chain: Vec<u8> = Vec::new();
     cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
@@ -369,7 +337,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: Some(att_app_id.to_vec()),
         },
         Some(&attestation_key_metadata.key),
     ));
@@ -387,7 +354,6 @@
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let att_challenge: &[u8] = b"foo";
-    let att_app_id: &[u8] = b"bar";
 
     let alias = format!("non_attest_key_{}", getuid());
     let non_attest_key_metadata = key_generations::generate_ec_p256_signing_key(
@@ -396,7 +362,6 @@
         -1,
         Some(alias),
         None,
-        None,
     )
     .unwrap();
 
@@ -415,7 +380,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: Some(att_challenge.to_vec()),
-            att_app_id: Some(att_app_id.to_vec()),
         },
         Some(&non_attest_key_metadata.key),
     ));
@@ -432,7 +396,6 @@
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let att_challenge: &[u8] = b"foo";
-    let att_app_id: &[u8] = b"bar";
 
     let alias = "aes_attest_key";
     let sym_key_metadata = key_generations::generate_sym_key(
@@ -461,7 +424,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: Some(att_challenge.to_vec()),
-            att_app_id: Some(att_app_id.to_vec()),
         },
         Some(&sym_key_metadata.key),
     ));
@@ -479,16 +441,11 @@
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
     let att_challenge: &[u8] = b"foo";
-    let att_app_id: &[u8] = b"bar";
 
     // Create attestation key.
-    let attestation_key_metadata = key_generations::generate_attestation_key(
-        &sec_level,
-        Algorithm::RSA,
-        att_challenge,
-        att_app_id,
-    )
-    .unwrap();
+    let attestation_key_metadata =
+        key_generations::generate_attestation_key(&sec_level, Algorithm::RSA, att_challenge)
+            .unwrap();
 
     let mut cert_chain: Vec<u8> = Vec::new();
     cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
@@ -504,8 +461,7 @@
         .key_size(128)
         .padding_mode(PaddingMode::NONE)
         .block_mode(BlockMode::ECB)
-        .attestation_challenge(att_challenge.to_vec())
-        .attestation_app_id(att_app_id.to_vec());
+        .attestation_challenge(att_challenge.to_vec());
 
     let alias = format!("ks_test_sym_key_attest_{}", getuid());
     let aes_key_metadata = sec_level
diff --git a/keystore2/tests/keystore2_client_ec_key_tests.rs b/keystore2/tests/keystore2_client_ec_key_tests.rs
index 726d61c..c2034de 100644
--- a/keystore2/tests/keystore2_client_ec_key_tests.rs
+++ b/keystore2/tests/keystore2_client_ec_key_tests.rs
@@ -209,7 +209,6 @@
         key_generations::SELINUX_SHELL_NAMESPACE,
         None,
         None,
-        None,
     )
     .unwrap();
 
diff --git a/keystore2/tests/keystore2_client_grant_key_tests.rs b/keystore2/tests/keystore2_client_grant_key_tests.rs
index 827a0de..7c75734 100644
--- a/keystore2/tests/keystore2_client_grant_key_tests.rs
+++ b/keystore2/tests/keystore2_client_grant_key_tests.rs
@@ -44,7 +44,6 @@
         key_generations::SELINUX_SHELL_NAMESPACE,
         Some(alias),
         None,
-        None,
     )
     .unwrap();
 
diff --git a/keystore2/tests/keystore2_client_import_keys_tests.rs b/keystore2/tests/keystore2_client_import_keys_tests.rs
index abf35b5..ecba402 100644
--- a/keystore2/tests/keystore2_client_import_keys_tests.rs
+++ b/keystore2/tests/keystore2_client_import_keys_tests.rs
@@ -14,21 +14,29 @@
 
 use nix::unistd::getuid;
 
+use openssl::rand::rand_bytes;
+use openssl::x509::X509;
+
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
-    ErrorCode::ErrorCode, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
-    SecurityLevel::SecurityLevel,
+    ErrorCode::ErrorCode, HardwareAuthenticatorType::HardwareAuthenticatorType,
+    KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, SecurityLevel::SecurityLevel,
 };
 use android_system_keystore2::aidl::android::system::keystore2::{
-    Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+    AuthenticatorSpec::AuthenticatorSpec, Domain::Domain,
+    IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+    KeyMetadata::KeyMetadata, ResponseCode::ResponseCode,
 };
 
 use keystore2_test_utils::{
     authorizations, get_keystore_service, key_generations, key_generations::Error,
 };
 
+use crate::ffi_test_utils::{create_wrapped_key, create_wrapped_key_additional_auth_data};
+
 use crate::keystore2_client_test_utils::{
-    has_trusty_keymint, perform_sample_asym_sign_verify_op, perform_sample_hmac_sign_verify_op,
+    encrypt_secure_key, encrypt_transport_key, has_default_keymint,
+    perform_sample_asym_sign_verify_op, perform_sample_hmac_sign_verify_op,
     perform_sample_sym_key_decrypt_op, perform_sample_sym_key_encrypt_op, SAMPLE_PLAIN_TEXT,
 };
 
@@ -51,6 +59,76 @@
     );
 }
 
+fn perform_sym_key_encrypt_decrypt_op(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    key_metadata: &KeyMetadata,
+) {
+    let cipher_text = perform_sample_sym_key_encrypt_op(
+        sec_level,
+        PaddingMode::PKCS7,
+        BlockMode::ECB,
+        &mut None,
+        None,
+        &key_metadata.key,
+    )
+    .unwrap();
+
+    assert!(cipher_text.is_some());
+
+    let plain_text = perform_sample_sym_key_decrypt_op(
+        sec_level,
+        &cipher_text.unwrap(),
+        PaddingMode::PKCS7,
+        BlockMode::ECB,
+        &mut None,
+        None,
+        &key_metadata.key,
+    )
+    .unwrap();
+
+    assert!(plain_text.is_some());
+    assert_eq!(plain_text.unwrap(), SAMPLE_PLAIN_TEXT.to_vec());
+}
+
+fn build_secure_key_wrapper(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    secure_key: &[u8],
+    transport_key: &[u8],
+    nonce: &[u8],
+    aad: &[u8],
+    wrapping_key_metadata: &KeyMetadata,
+) -> Result<Vec<u8>, Error> {
+    // Encrypt secure key with transport key.
+    let transport_key_alias = format!("ks_transport_key_aes_256_key_test_{}", getuid());
+    let transport_key_metadata =
+        key_generations::import_transport_key(sec_level, Some(transport_key_alias), transport_key)
+            .unwrap();
+    let encrypted_secure_key = encrypt_secure_key(
+        sec_level,
+        secure_key,
+        aad,
+        nonce.to_vec(),
+        128,
+        &transport_key_metadata.key,
+    )
+    .unwrap();
+
+    // Extract GCM-tag and encrypted secure key data.
+    let encrypted_secure_key = encrypted_secure_key.unwrap();
+    let gcm_tag: Vec<u8> =
+        encrypted_secure_key[secure_key.len()..(encrypted_secure_key.len())].to_vec();
+    let encrypted_secure_key: Vec<u8> = encrypted_secure_key[0..secure_key.len()].to_vec();
+
+    // Get wrapping key puplic part and encrypt the transport key.
+    let cert_bytes = wrapping_key_metadata.certificate.as_ref().unwrap();
+    let cert = X509::from_der(cert_bytes.as_ref()).unwrap();
+    let public_key = cert.public_key().unwrap();
+    let encrypted_transport_key = encrypt_transport_key(transport_key, &public_key).unwrap();
+
+    // Create `SecureKeyWrapper` ASN.1 DER-encoded data.
+    create_wrapped_key(&encrypted_secure_key, &encrypted_transport_key, nonce, &gcm_tag)
+}
+
 /// Import RSA key and verify imported key parameters. Try to create an operation using the
 /// imported key. Test should be able to create an operation successfully.
 #[test]
@@ -208,7 +286,7 @@
         key_generations::RSA_2048_KEY,
     ));
 
-    if has_trusty_keymint() {
+    if has_default_keymint() {
         assert!(result.is_err());
         assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PURPOSE), result.unwrap_err());
     } else {
@@ -289,31 +367,7 @@
     let key_metadata = key_generations::import_aes_key(&sec_level, Domain::APP, -1, Some(alias))
         .expect("Failed to import AES key.");
 
-    let cipher_text = perform_sample_sym_key_encrypt_op(
-        &sec_level,
-        PaddingMode::PKCS7,
-        BlockMode::ECB,
-        &mut None,
-        None,
-        &key_metadata.key,
-    )
-    .unwrap();
-
-    assert!(cipher_text.is_some());
-
-    let plain_text = perform_sample_sym_key_decrypt_op(
-        &sec_level,
-        &cipher_text.unwrap(),
-        PaddingMode::PKCS7,
-        BlockMode::ECB,
-        &mut None,
-        None,
-        &key_metadata.key,
-    )
-    .unwrap();
-
-    assert!(plain_text.is_some());
-    assert_eq!(plain_text.unwrap(), SAMPLE_PLAIN_TEXT.to_vec());
+    perform_sym_key_encrypt_decrypt_op(&sec_level, &key_metadata);
 }
 
 /// Import 3DES key and verify key parameters. Try to create an operation using the imported key.
@@ -331,31 +385,7 @@
     let key_metadata = key_generations::import_3des_key(&sec_level, Domain::APP, -1, Some(alias))
         .expect("Failed to import 3DES key.");
 
-    let cipher_text = perform_sample_sym_key_encrypt_op(
-        &sec_level,
-        PaddingMode::PKCS7,
-        BlockMode::ECB,
-        &mut None,
-        None,
-        &key_metadata.key,
-    )
-    .unwrap();
-
-    assert!(cipher_text.is_some());
-
-    let plain_text = perform_sample_sym_key_decrypt_op(
-        &sec_level,
-        &cipher_text.unwrap(),
-        PaddingMode::PKCS7,
-        BlockMode::ECB,
-        &mut None,
-        None,
-        &key_metadata.key,
-    )
-    .unwrap();
-
-    assert!(plain_text.is_some());
-    assert_eq!(plain_text.unwrap(), SAMPLE_PLAIN_TEXT.to_vec());
+    perform_sym_key_encrypt_decrypt_op(&sec_level, &key_metadata);
 }
 
 /// Import HMAC key and verify key parameters. Try to create an operation using the imported key.
@@ -372,3 +402,234 @@
 
     perform_sample_hmac_sign_verify_op(&sec_level, &key_metadata.key);
 }
+
+/// This test creates a wrapped key data and imports it. Validates the imported wrapped key.
+///     1. Create a wrapped key material to import, as ASN.1 DER-encoded data corresponding to the
+///        `SecureKeyWrapper` schema defined in IKeyMintDevice.aidl.
+///     2. Import wrapped key and use it for crypto operations.
+/// Test should successfully import the wrapped key and perform crypto operations.
+#[test]
+fn keystore2_create_wrapped_key_and_import_wrapped_key_success() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let mut secure_key = [0; 32];
+    rand_bytes(&mut secure_key).unwrap();
+
+    let mut transport_key = [0; 32];
+    rand_bytes(&mut transport_key).unwrap();
+
+    let mut nonce = [0; 12];
+    rand_bytes(&mut nonce).unwrap();
+
+    // Import wrapping key.
+    let wrapping_key_alias = format!("ks_wrapping_key_test_import_2_{}_2048", getuid());
+    let wrapping_key_metadata = key_generations::import_wrapping_key(
+        &sec_level,
+        key_generations::RSA_2048_KEY,
+        Some(wrapping_key_alias),
+    )
+    .unwrap();
+
+    // Create the DER-encoded representation of `KeyDescription` schema defined in
+    // `IKeyMintDevice.aidl` and use it as additional authenticated data.
+    let aad = create_wrapped_key_additional_auth_data().unwrap();
+
+    // Build ASN.1 DER-encoded wrapped key material as described in `SecureKeyWrapper` schema.
+    let wrapped_key_data = build_secure_key_wrapper(
+        &sec_level,
+        &secure_key,
+        &transport_key,
+        &nonce,
+        &aad,
+        &wrapping_key_metadata,
+    )
+    .unwrap();
+
+    // Unwrap the key. Import wrapped key.
+    let secured_key_alias = format!("ks_wrapped_aes_key_{}", getuid());
+    let secured_key_metadata = key_generations::import_wrapped_key(
+        &sec_level,
+        Some(secured_key_alias),
+        &wrapping_key_metadata,
+        Some(wrapped_key_data.to_vec()),
+    )
+    .unwrap();
+
+    perform_sym_key_encrypt_decrypt_op(&sec_level, &secured_key_metadata);
+}
+
+/// Create a wrapped key data with invalid Additional Authenticated Data (AAD) and
+/// try to import wrapped key.
+///     1. Create a wrapped key material with invalid AAD to import, as ASN.1 DER-encoded
+///        data corresponding to the `SecureKeyWrapper` schema defined in IKeyMintDevice.aidl.
+///     2. Import wrapped key and use it for crypto operations.
+/// Test should fail to import the wrapped key with error code `VERIFICATION_FAILED`.
+#[test]
+fn keystore2_create_wrapped_key_with_invalid_aad_and_import_wrapped_key_fail() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let mut secure_key = [0; 32];
+    rand_bytes(&mut secure_key).unwrap();
+
+    let mut transport_key = [0; 32];
+    rand_bytes(&mut transport_key).unwrap();
+
+    let mut nonce = [0; 12];
+    rand_bytes(&mut nonce).unwrap();
+
+    // Import wrapping key.
+    let wrapping_key_alias = format!("ks_wrapping_key_test_import_2_{}_2048", getuid());
+    let wrapping_key_metadata = key_generations::import_wrapping_key(
+        &sec_level,
+        key_generations::RSA_2048_KEY,
+        Some(wrapping_key_alias),
+    )
+    .unwrap();
+
+    // Use invalid value as the additional authenticated data.
+    let aad = b"foo";
+
+    // Build ASN.1 DER-encoded wrapped key material as described in `SecureKeyWrapper` schema.
+    let wrapped_key_data = build_secure_key_wrapper(
+        &sec_level,
+        &secure_key,
+        &transport_key,
+        &nonce,
+        aad,
+        &wrapping_key_metadata,
+    )
+    .unwrap();
+
+    // Unwrap the key. Import wrapped key.
+    let secured_key_alias = format!("ks_wrapped_aes_key_{}", getuid());
+    let result = key_generations::map_ks_error(key_generations::import_wrapped_key(
+        &sec_level,
+        Some(secured_key_alias),
+        &wrapping_key_metadata,
+        Some(wrapped_key_data.to_vec()),
+    ));
+
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::VERIFICATION_FAILED), result.unwrap_err());
+}
+
+/// Import wrapped AES key and use it for crypto operations. Test should import wrapped key and
+/// perform crypto operations successfully.
+#[test]
+fn keystore2_import_wrapped_key_success() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let alias = format!("ks_wrapped_key_test_import_1_{}_256", getuid());
+    let wrapping_key_alias = format!("ks_wrapping_key_test_import_1_{}_2048", getuid());
+
+    let wrapping_key_params = authorizations::AuthSetBuilder::new()
+        .no_auth_required()
+        .algorithm(Algorithm::RSA)
+        .digest(Digest::SHA_2_256)
+        .purpose(KeyPurpose::ENCRYPT)
+        .purpose(KeyPurpose::DECRYPT)
+        .purpose(KeyPurpose::WRAP_KEY)
+        .padding_mode(PaddingMode::RSA_OAEP)
+        .key_size(2048)
+        .rsa_public_exponent(65537)
+        .cert_not_before(0)
+        .cert_not_after(253402300799000);
+
+    let key_metadata = key_generations::import_wrapping_key_and_wrapped_key(
+        &sec_level,
+        Domain::APP,
+        -1,
+        Some(alias),
+        Some(wrapping_key_alias),
+        wrapping_key_params,
+    )
+    .expect("Failed to import wrapped key.");
+
+    // Try to perform operations using wrapped key.
+    perform_sym_key_encrypt_decrypt_op(&sec_level, &key_metadata);
+}
+
+/// Import wrapping-key without specifying KeyPurpose::WRAP_KEY in import key parameters. Try to
+/// use this as wrapping-key for importing wrapped-key. Test should fail with an error code
+/// `INCOMPATIBLE_PURPOSE` to import wrapped-key using a wrapping-key which doesn't possess
+/// `WRAP_KEY` purpose.
+#[test]
+fn keystore2_import_wrapped_key_fails_with_wrong_purpose() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let wrapping_key_alias = format!("ks_wrapping_key_test_import_2_{}_2048", getuid());
+    let alias = format!("ks_wrapped_key_test_import_2_{}_256", getuid());
+
+    // In this KeyPurpose::WRAP_KEY is missing.
+    let wrapping_key_params = authorizations::AuthSetBuilder::new()
+        .no_auth_required()
+        .algorithm(Algorithm::RSA)
+        .digest(Digest::SHA_2_256)
+        .purpose(KeyPurpose::SIGN)
+        .purpose(KeyPurpose::VERIFY)
+        .padding_mode(PaddingMode::RSA_OAEP)
+        .key_size(2048)
+        .rsa_public_exponent(65537)
+        .cert_not_before(0)
+        .cert_not_after(253402300799000);
+
+    let result =
+        key_generations::map_ks_error(key_generations::import_wrapping_key_and_wrapped_key(
+            &sec_level,
+            Domain::APP,
+            -1,
+            Some(alias),
+            Some(wrapping_key_alias),
+            wrapping_key_params,
+        ));
+
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::INCOMPATIBLE_PURPOSE), result.unwrap_err());
+}
+
+/// Try to import wrapped key whose wrapping key is missing in Android Keystore.
+/// Test should fail to import wrapped key with `ResponseCode::KEY_NOT_FOUND`.
+#[test]
+fn keystore2_import_wrapped_key_fails_with_missing_wrapping_key() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let unwrap_params = authorizations::AuthSetBuilder::new()
+        .digest(Digest::SHA_2_256)
+        .padding_mode(PaddingMode::RSA_OAEP);
+
+    let authenticator_spec: &[AuthenticatorSpec] = &[AuthenticatorSpec {
+        authenticatorType: HardwareAuthenticatorType::NONE,
+        authenticatorId: 0,
+    }];
+
+    let alias = format!("ks_wrapped_key_test_import_3_{}_256", getuid());
+
+    // Wrapping key with this alias doesn't exist.
+    let wrapping_key_alias = format!("ks_wrapping_key_not_exist_{}_2048", getuid());
+
+    let result = key_generations::map_ks_error(sec_level.importWrappedKey(
+        &KeyDescriptor {
+            domain: Domain::APP,
+            nspace: -1,
+            alias: Some(alias),
+            blob: Some(key_generations::WRAPPED_KEY.to_vec()),
+        },
+        &KeyDescriptor {
+            domain: Domain::APP,
+            nspace: -1,
+            alias: Some(wrapping_key_alias),
+            blob: None,
+        },
+        None,
+        &unwrap_params,
+        authenticator_spec,
+    ));
+
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+}
diff --git a/keystore2/tests/keystore2_client_list_entries_tests.rs b/keystore2/tests/keystore2_client_list_entries_tests.rs
index def9d94..62e3dd0 100644
--- a/keystore2/tests/keystore2_client_list_entries_tests.rs
+++ b/keystore2/tests/keystore2_client_list_entries_tests.rs
@@ -89,7 +89,6 @@
                 key_generations::SELINUX_SHELL_NAMESPACE,
                 Some(alias.to_string()),
                 None,
-                None,
             )
             .unwrap();
 
@@ -128,7 +127,6 @@
                     -1,
                     Some(alias.to_string()),
                     None,
-                    None,
                 )
                 .unwrap();
 
diff --git a/keystore2/tests/keystore2_client_operation_tests.rs b/keystore2/tests/keystore2_client_operation_tests.rs
index e1102dd..9714900 100644
--- a/keystore2/tests/keystore2_client_operation_tests.rs
+++ b/keystore2/tests/keystore2_client_operation_tests.rs
@@ -307,7 +307,6 @@
         key_generations::SELINUX_SHELL_NAMESPACE,
         Some(alias),
         None,
-        None,
     )
     .unwrap();
 
diff --git a/keystore2/tests/keystore2_client_rsa_key_tests.rs b/keystore2/tests/keystore2_client_rsa_key_tests.rs
index 3139c2b..ad176a4 100644
--- a/keystore2/tests/keystore2_client_rsa_key_tests.rs
+++ b/keystore2/tests/keystore2_client_rsa_key_tests.rs
@@ -13,8 +13,8 @@
 // limitations under the License.
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-    BlockMode::BlockMode, Digest::Digest, ErrorCode::ErrorCode, KeyPurpose::KeyPurpose,
-    PaddingMode::PaddingMode, SecurityLevel::SecurityLevel,
+    Digest::Digest, ErrorCode::ErrorCode, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
+    SecurityLevel::SecurityLevel,
 };
 use android_system_keystore2::aidl::android::system::keystore2::{
     CreateOperationResponse::CreateOperationResponse, Domain::Domain,
@@ -25,9 +25,7 @@
     authorizations, get_keystore_service, key_generations, key_generations::Error,
 };
 
-use crate::keystore2_client_test_utils::{
-    delete_app_key, has_trusty_keymint, perform_sample_sign_operation, ForcedOp,
-};
+use crate::keystore2_client_test_utils::{delete_app_key, perform_sample_sign_operation, ForcedOp};
 
 /// This macro is used for creating signing key operation tests using digests and paddings
 /// for various key sizes.
@@ -59,7 +57,6 @@
                 stringify!($test_name),
                 $padding,
                 None,
-                None,
             );
         }
     };
@@ -73,7 +70,6 @@
                 stringify!($test_name),
                 $padding,
                 $mgf_digest,
-                Some(BlockMode::ECB),
             );
         }
     };
@@ -133,7 +129,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::SIGN,
         ForcedOp(false),
@@ -170,18 +165,16 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::SIGN,
         ForcedOp(false),
     ));
     assert!(result.is_err());
 
-    if has_trusty_keymint() {
-        assert_eq!(result.unwrap_err(), Error::Km(ErrorCode::UNKNOWN_ERROR));
-    } else {
-        assert_eq!(result.unwrap_err(), Error::Km(ErrorCode::INCOMPATIBLE_DIGEST));
-    }
+    let e = result.unwrap_err();
+    assert!(
+        e == Error::Km(ErrorCode::UNKNOWN_ERROR) || e == Error::Km(ErrorCode::INCOMPATIBLE_DIGEST)
+    );
 
     delete_app_key(&keystore2, alias).unwrap();
 }
@@ -193,7 +186,6 @@
     alias: &str,
     padding: PaddingMode,
     mgf_digest: Option<Digest>,
-    block_mode: Option<BlockMode>,
 ) {
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
@@ -209,9 +201,8 @@
             padding: Some(padding),
             digest,
             mgf_digest,
-            block_mode,
+            block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::DECRYPT,
         ForcedOp(false),
@@ -1559,7 +1550,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::SIGN,
         ForcedOp(false),
@@ -1592,7 +1582,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::DECRYPT,
         ForcedOp(false),
@@ -1624,7 +1613,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::DECRYPT,
         ForcedOp(false),
@@ -1654,7 +1642,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::SIGN,
         ForcedOp(false),
@@ -1684,7 +1671,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::DECRYPT,
         ForcedOp(false),
@@ -1714,7 +1700,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::AGREE_KEY,
         ForcedOp(false),
@@ -1747,7 +1732,6 @@
                 mgf_digest: None,
                 block_mode: None,
                 att_challenge: None,
-                att_app_id: None,
             },
             KeyPurpose::DECRYPT,
             ForcedOp(false),
@@ -1781,7 +1765,6 @@
                 mgf_digest: None,
                 block_mode: None,
                 att_challenge: None,
-                att_app_id: None,
             },
             KeyPurpose::SIGN,
             ForcedOp(false),
@@ -1813,7 +1796,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::ENCRYPT,
         ForcedOp(false),
@@ -1845,7 +1827,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::DECRYPT,
         ForcedOp(false),
@@ -1876,7 +1857,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         KeyPurpose::DECRYPT,
         ForcedOp(false),
@@ -1906,7 +1886,6 @@
             mgf_digest: None,
             block_mode: None,
             att_challenge: None,
-            att_app_id: None,
         },
         None,
     ));
diff --git a/keystore2/tests/keystore2_client_test_utils.rs b/keystore2/tests/keystore2_client_test_utils.rs
index 758e88b..56995e4 100644
--- a/keystore2/tests/keystore2_client_test_utils.rs
+++ b/keystore2/tests/keystore2_client_test_utils.rs
@@ -15,7 +15,11 @@
 use nix::unistd::{Gid, Uid};
 use serde::{Deserialize, Serialize};
 
+use openssl::encrypt::Encrypter;
+use openssl::error::ErrorStack;
 use openssl::hash::MessageDigest;
+use openssl::pkey::PKey;
+use openssl::pkey::Public;
 use openssl::rsa::Padding;
 use openssl::sign::Verifier;
 use openssl::x509::X509;
@@ -80,7 +84,8 @@
     };
 }
 
-pub fn has_trusty_keymint() -> bool {
+/// Indicate whether the default device is KeyMint (rather than Keymaster).
+pub fn has_default_keymint() -> bool {
     binder::is_declared("android.hardware.security.keymint.IKeyMintDevice/default")
         .expect("Could not check for declared keymint interface")
 }
@@ -98,10 +103,9 @@
     let keystore2 = get_keystore_service();
     let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
 
-    let key_metadata = key_generations::generate_ec_p256_signing_key(
-        &sec_level, domain, nspace, alias, None, None,
-    )
-    .unwrap();
+    let key_metadata =
+        key_generations::generate_ec_p256_signing_key(&sec_level, domain, nspace, alias, None)
+            .unwrap();
 
     sec_level.createOperation(
         &key_metadata.key,
@@ -348,3 +352,45 @@
         blob: None,
     })
 }
+
+/// Encrypt the secure key with given transport key.
+pub fn encrypt_secure_key(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    secure_key: &[u8],
+    aad: &[u8],
+    nonce: Vec<u8>,
+    mac_len: i32,
+    key: &KeyDescriptor,
+) -> binder::Result<Option<Vec<u8>>> {
+    let op_params = authorizations::AuthSetBuilder::new()
+        .purpose(KeyPurpose::ENCRYPT)
+        .padding_mode(PaddingMode::NONE)
+        .block_mode(BlockMode::GCM)
+        .nonce(nonce)
+        .mac_length(mac_len);
+
+    let op_response = sec_level.createOperation(key, &op_params, false)?;
+
+    let op = op_response.iOperation.unwrap();
+    op.updateAad(aad)?;
+    op.finish(Some(secure_key), None)
+}
+
+/// Encrypt the transport key with given RSA wrapping key.
+pub fn encrypt_transport_key(
+    transport_key: &[u8],
+    pkey: &PKey<Public>,
+) -> Result<Vec<u8>, ErrorStack> {
+    let mut encrypter = Encrypter::new(pkey).unwrap();
+    encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
+    encrypter.set_rsa_oaep_md(MessageDigest::sha256()).unwrap();
+    encrypter.set_rsa_mgf1_md(MessageDigest::sha1()).unwrap();
+
+    let input = transport_key.to_vec();
+    let buffer_len = encrypter.encrypt_len(&input).unwrap();
+    let mut encoded = vec![0u8; buffer_len];
+    let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
+    let encoded = &encoded[..encoded_len];
+
+    Ok(encoded.to_vec())
+}
diff --git a/keystore2/tests/keystore2_client_tests.rs b/keystore2/tests/keystore2_client_tests.rs
index 41e3e36..d705aa4 100644
--- a/keystore2/tests/keystore2_client_tests.rs
+++ b/keystore2/tests/keystore2_client_tests.rs
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+pub mod ffi_test_utils;
 pub mod keystore2_client_3des_key_tests;
 pub mod keystore2_client_aes_key_tests;
 pub mod keystore2_client_attest_key_tests;
diff --git a/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs b/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
index 32ecd03..63122fe 100644
--- a/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
+++ b/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
@@ -165,14 +165,12 @@
                 .unwrap();
             // Generate Key BLOB and prepare legacy keystore blob files.
             let att_challenge: &[u8] = b"foo";
-            let att_app_id: &[u8] = b"bar";
             let key_metadata = key_generations::generate_ec_p256_signing_key(
                 &sec_level,
                 Domain::BLOB,
                 SELINUX_SHELL_NAMESPACE,
                 None,
                 Some(att_challenge),
-                Some(att_app_id),
             )
             .expect("Failed to generate key blob");
 
@@ -424,14 +422,12 @@
                 .unwrap();
             // Generate Key BLOB and prepare legacy keystore blob files.
             let att_challenge: &[u8] = b"foo";
-            let att_app_id: &[u8] = b"bar";
             let key_metadata = key_generations::generate_ec_p256_signing_key(
                 &sec_level,
                 Domain::BLOB,
                 SELINUX_SHELL_NAMESPACE,
                 None,
                 Some(att_challenge),
-                Some(att_app_id),
             )
             .expect("Failed to generate key blob");