Merge "Remove custom AndroidTest.xml"
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index bd08bc8..cf37fca 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -19,7 +19,9 @@
 
     rustlibs: [
         "android.hardware.security.keymint-rust",
+        "android.hardware.security.secureclock-rust",
         "android.security.apc-rust",
+        "android.security.authorization-rust",
         "android.security.compat-rust",
         "android.system.keystore2-rust",
         "libanyhow",
@@ -46,10 +48,11 @@
     auto_gen_config: true,
     rustlibs: [
         "android.hardware.security.keymint-rust",
+        "android.hardware.security.secureclock-rust",
         "android.security.apc-rust",
+        "android.security.authorization-rust",
         "android.security.compat-rust",
         "android.system.keystore2-rust",
-        "android.hardware.security.keymint-rust",
         "libandroid_logger",
         "libanyhow",
         "libbinder_rs",
diff --git a/keystore2/aidl/Android.bp b/keystore2/aidl/Android.bp
index 0d05dfe..fac36e5 100644
--- a/keystore2/aidl/Android.bp
+++ b/keystore2/aidl/Android.bp
@@ -28,9 +28,12 @@
 }
 
 aidl_interface {
-    name: "android.security.authorizations",
-    srcs: [ "android/security/authorizations/*.aidl" ],
-    imports: [ "android.hardware.security.keymint" ],
+    name: "android.security.authorization",
+    srcs: [ "android/security/authorization/*.aidl" ],
+    imports: [
+        "android.hardware.security.keymint",
+        "android.hardware.security.secureclock",
+    ],
     unstable: true,
     backend: {
         java: {
@@ -62,7 +65,11 @@
 aidl_interface {
     name: "android.security.compat",
     srcs: [ "android/security/compat/*.aidl" ],
-    imports: [ "android.hardware.security.keymint" ],
+    imports: [
+        "android.hardware.security.keymint",
+        "android.hardware.security.secureclock",
+        "android.hardware.security.sharedsecret",
+    ],
     unstable: true,
     backend: {
         java: {
diff --git a/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
new file mode 100644
index 0000000..df64401
--- /dev/null
+++ b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
@@ -0,0 +1,59 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android.security.authorization;
+
+import android.hardware.security.keymint.HardwareAuthToken;
+import android.security.authorization.LockScreenEvent;
+
+// TODO: mark the interface with @SensitiveData when the annotation is ready (b/176110256).
+
+/**
+ * IKeystoreAuthorization interface exposes the methods for other system components to
+ * provide keystore with the information required to enforce authorizations on key usage.
+ */
+interface IKeystoreAuthorization {
+
+    /**
+     * Allows the Android authenticators to hand over an auth token to Keystore.
+     * Callers require 'AddAuth' permission.
+     * ## Error conditions:
+     * `ResponseCode::PERMISSION_DENIED` - if the callers do not have the 'AddAuth' permission.
+     * `ResponseCode::SYSTEM_ERROR` - if failed to store the auth token in the database or if failed
+     * to add the auth token to the operation, if it is a per-op auth token.
+     *
+     * @param authToken The auth token created by an authenticator, upon user authentication.
+     */
+    void addAuthToken(in HardwareAuthToken authToken);
+
+    /**
+     * 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.
+     *
+     * ## Error conditions:
+     * `ResponseCode::PERMISSION_DENIED` - if the callers do not have the 'Unlock' permission.
+     * `ResponseCode::SYSTEM_ERROR` - if failed to perform lock/unlock operations due to various
+     *
+     * @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
+     */
+    void onLockScreenEvent(in LockScreenEvent lockScreenEvent, in int userId,
+                           in @nullable byte[] password);
+}
diff --git a/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl b/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl
new file mode 100644
index 0000000..877a916
--- /dev/null
+++ b/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl
@@ -0,0 +1,21 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android.security.authorization;
+
+@Backing(type="int")
+enum LockScreenEvent {
+    UNLOCK = 0,
+    LOCK = 1,
+}
diff --git a/keystore2/aidl/android/security/authorizations/IKeystoreAuthorization.aidl b/keystore2/aidl/android/security/authorizations/IKeystoreAuthorization.aidl
deleted file mode 100644
index d3e80ee..0000000
--- a/keystore2/aidl/android/security/authorizations/IKeystoreAuthorization.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2020, The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package android.security.authorizations;
-
-import android.hardware.security.keymint.HardwareAuthToken;
-
-/**
-* IKeystoreAuthorization interface exposes the methods for other system components to
-* provide keystore with the information required to enforce authorizations on key usage.
-*/
-interface IKeystoreAuthorization {
-
-    /**
-    * Allows the Android authenticators to hand over an auth token to Keystore.
-    * Callers require 'AddAuth' permission.
-    * ## Error conditions:
-    * `ResponseCode::SYSTEM_ERROR` - if failed to store the auth token in the database or if failed
-    * to add the auth token to the operation, if it is a per-op auth token.
-    *
-    * @param authToken The auth token created by an authenticator, upon user authentication.
-    */
-    void addAuthToken(in HardwareAuthToken authToken);
-}
diff --git a/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl b/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl
index 6a72c75..4b6a93b 100644
--- a/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl
+++ b/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl
@@ -18,11 +18,30 @@
 
 import android.hardware.security.keymint.IKeyMintDevice;
 import android.hardware.security.keymint.SecurityLevel;
+import android.hardware.security.secureclock.ISecureClock;
+import android.hardware.security.sharedsecret.ISharedSecret;
 
 /**
+ * The compatibility service allows Keystore 2.0 to connect to legacy wrapper implementations that
+ * it hosts itself without registering them as a service. Keystore 2.0 would not be allowed to
+ * register a HAL service, so instead it registers this service which it can then connect to.
  */
 interface IKeystoreCompatService {
     /**
+     * Return an implementation of IKeyMintDevice, that it implemented by Keystore 2.0 itself
+     * by means of Keymaster 4.1 or lower.
      */
     IKeyMintDevice getKeyMintDevice (SecurityLevel securityLevel);
+
+    /**
+     * Returns an implementation of ISecureClock, that is implemented by Keystore 2.0 itself
+     * by means of Keymaster 4.x.
+     */
+    ISecureClock getSecureClock ();
+
+    /**
+     * Returns an implementation of ISharedSecret, that is implemented by Keystore 2.0 itself
+     * by means of Keymaster 4.x.
+     */
+    ISharedSecret getSharedSecret (SecurityLevel securityLevel);
 }
diff --git a/keystore2/src/auth_token_handler.rs b/keystore2/src/auth_token_handler.rs
index 8c10442..bedec50 100644
--- a/keystore2/src/auth_token_handler.rs
+++ b/keystore2/src/auth_token_handler.rs
@@ -13,17 +13,21 @@
 // limitations under the License.
 
 //! This module defines the AuthTokenHandler enum and its methods. AuthTokenHandler enum represents
-//! the different states an auth token and an associated verification token can be expressed during
+//! the different states an auth token and an associated timestamp token can be expressed during
 //! the operation life cycle.
-use crate::error::Error as KeystoreError;
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-    HardwareAuthToken::HardwareAuthToken, VerificationToken::VerificationToken,
+    HardwareAuthToken::HardwareAuthToken,
 };
+use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
+    TimeStampToken::TimeStampToken,
+};
+
 use anyhow::{Context, Result};
 use std::sync::mpsc::Receiver;
 
 /// AuthTokenHandler enum has five different variants which are described by the comments above
-// each variant.
+// each variant, as follows.
+#[derive(Debug)]
 pub enum AuthTokenHandler {
     /// Used when an operation does not require an auth token for authorization.
     NoAuthRequired,
@@ -32,52 +36,50 @@
     OpAuthRequired,
     /// Used to represent the intermediate state between the time the operation is found to be
     /// using a time_out key with STRONGBOX keymint, and the time a verficiation token is requested
-    /// from the worker thread which obtains verification tokens from the TEE KeyMint.
-    VerificationRequired(HardwareAuthToken),
-    /// Used to represent the intermediate state between the time a verification token is requested
-    /// from the worker thread which obtains verification tokens from the TEE KeyMint and the time
-    /// the verification token is received from the worker thread.
-    Channel(Receiver<(HardwareAuthToken, VerificationToken)>),
+    /// from the worker thread which obtains timestamp tokens from the TEE KeyMint.
+    TimestampRequired(HardwareAuthToken),
+    /// Used to represent the intermediate state between the time a timestamp token is requested
+    /// from the worker thread which obtains timestamp tokens from the TEE KeyMint and the time
+    /// the timestamp token is received from the worker thread.
+    Channel(Receiver<(HardwareAuthToken, TimeStampToken)>),
     /// Used to represent the final state for all operations requiring an auth token for
-    /// authorization, after the matching auth token (and the associated verification token if
+    /// authorization, after the matching auth token (and the associated timestamp token if
     /// required) is found.
-    Token(HardwareAuthToken, Option<VerificationToken>),
+    Token(HardwareAuthToken, Option<TimeStampToken>),
 }
 
 impl AuthTokenHandler {
-    /// Retrieve auth token and verification token from the Token variant of an AuthTokenHandler
-    /// instance
-    pub fn get_auth_and_verification_tokens(
-        &self,
-    ) -> Option<(&HardwareAuthToken, &VerificationToken)> {
-        if let AuthTokenHandler::Token(auth_token, Some(verification_token)) = self {
-            Some((auth_token, verification_token))
-        } else {
-            None
-        }
-    }
-
-    /// Retrieve auth token from the Token variant of an AuthTokenHandler instance
-    pub fn get_auth_token(&self) -> Option<&HardwareAuthToken> {
-        if let AuthTokenHandler::Token(auth_token, _) = self {
-            Some(auth_token)
-        } else {
-            None
-        }
-    }
-
-    /// If Channel variant, block on it until the verification token is sent by the
-    /// keystore2 worker thread which obtains verification tokens from TEE Keymint
-    pub fn receive_verification_token(&mut self) -> Result<()> {
+    /// If Channel variant, block on it until the timestamp token is sent by the
+    /// keystore2 worker thread which obtains timestamp tokens from TEE Keymint and converts the
+    /// object from Channel variant to Token variant.
+    /// Retrieve auth token and timestamp token from the Token variant of an AuthTokenHandler
+    /// instance.
+    pub fn retrieve_auth_and_timestamp_tokens(
+        &mut self,
+    ) -> Result<(Option<&HardwareAuthToken>, Option<&TimeStampToken>)> {
+        // Converts to Token variant if Channel variant found, after retrieving the
+        // TimeStampToken
         if let AuthTokenHandler::Channel(recv) = self {
-            let (auth_token, verification_token) =
-                recv.recv().context("In receive_verification_token: sender disconnected.")?;
-            *self = AuthTokenHandler::Token(auth_token, Some(verification_token));
-            Ok(())
+            let (auth_token, timestamp_token) =
+                recv.recv().context("In receive_timestamp_token: sender disconnected.")?;
+            *self = AuthTokenHandler::Token(auth_token, Some(timestamp_token));
+        }
+        // get the tokens from the Token variant
+        if let AuthTokenHandler::Token(auth_token, optional_time_stamp_token) = self {
+            Ok((Some(auth_token), optional_time_stamp_token.as_ref()))
         } else {
-            Err(KeystoreError::sys()).context(
-                "In receive_verification_token: Wrong variant found in the authorization object.",
-            )
+            Ok((None, None))
+        }
+    }
+
+    /// Retrieve auth token from TimestampRequired and Token variants of an
+    /// AuthTokenHandler instance. This method is useful when we only expect an auth token and
+    /// do not expect a timestamp token.
+    pub fn get_auth_token(&self) -> Option<&HardwareAuthToken> {
+        match self {
+            AuthTokenHandler::TimestampRequired(auth_token) => Some(auth_token),
+            AuthTokenHandler::Token(auth_token, _) => Some(auth_token),
+            _ => None,
         }
     }
 }
diff --git a/keystore2/src/authorization.rs b/keystore2/src/authorization.rs
new file mode 100644
index 0000000..ba27df8
--- /dev/null
+++ b/keystore2/src/authorization.rs
@@ -0,0 +1,135 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module implements IKeyAuthorization AIDL interface.
+
+use crate::error::Error as KeystoreError;
+use crate::error::map_or_log_err;
+use crate::globals::{DB, ENFORCEMENTS, LEGACY_BLOB_LOADER, SUPER_KEY};
+use crate::permission::KeystorePerm;
+use crate::utils::check_keystore_permission;
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    HardwareAuthToken::HardwareAuthToken, HardwareAuthenticatorType::HardwareAuthenticatorType,
+};
+use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
+    Timestamp::Timestamp,
+};
+use android_security_authorization::binder::{Interface, Result as BinderResult};
+use android_security_authorization:: aidl::android::security::authorization::IKeystoreAuthorization::{
+        BnKeystoreAuthorization, IKeystoreAuthorization,
+};
+use android_security_authorization:: aidl::android::security::authorization::LockScreenEvent::LockScreenEvent;
+use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
+use anyhow::{Context, Result};
+use binder::IBinder;
+
+/// This struct is defined to implement the aforementioned AIDL interface.
+/// As of now, it is an empty struct.
+pub struct AuthorizationManager;
+
+impl AuthorizationManager {
+    /// Create a new instance of Keystore Authorization service.
+    pub fn new_native_binder() -> Result<impl IKeystoreAuthorization> {
+        let result = BnKeystoreAuthorization::new_binder(Self);
+        result.as_binder().set_requesting_sid(true);
+        Ok(result)
+    }
+
+    fn add_auth_token(&self, auth_token: &HardwareAuthToken) -> Result<()> {
+        //check keystore permission
+        check_keystore_permission(KeystorePerm::add_auth()).context("In add_auth_token.")?;
+
+        //TODO: Keymint's HardwareAuthToken aidl needs to implement Copy/Clone
+        let auth_token_copy = HardwareAuthToken {
+            challenge: auth_token.challenge,
+            userId: auth_token.userId,
+            authenticatorId: auth_token.authenticatorId,
+            authenticatorType: HardwareAuthenticatorType(auth_token.authenticatorType.0),
+            timestamp: Timestamp { milliSeconds: auth_token.timestamp.milliSeconds },
+            mac: auth_token.mac.clone(),
+        };
+        ENFORCEMENTS.add_auth_token(auth_token_copy)?;
+        Ok(())
+    }
+
+    fn on_lock_screen_event(
+        &self,
+        lock_screen_event: LockScreenEvent,
+        user_id: i32,
+        password: Option<&[u8]>,
+    ) -> Result<()> {
+        match (lock_screen_event, password) {
+            (LockScreenEvent::UNLOCK, Some(user_password)) => {
+                //This corresponds to the unlock() method in legacy keystore API.
+                //check permission
+                check_keystore_permission(KeystorePerm::unlock())
+                    .context("In on_lock_screen_event: Unlock with password.")?;
+                ENFORCEMENTS.set_device_locked(user_id, false);
+                // Unlock super key.
+                DB.with::<_, Result<()>>(|db| {
+                    let mut db = db.borrow_mut();
+                    //TODO - b/176123105 - Once the user management API is implemented, unlock is
+                    //allowed only if the user is added. Then the two tasks handled by the
+                    //unlock_user_key will be split into two methods. For now, unlock_user_key
+                    //method is used as it is, which created a super key for the user if one does
+                    //not exists, in addition to unlocking the existing super key of the user/
+                    SUPER_KEY.unlock_user_key(
+                        user_id as u32,
+                        user_password,
+                        &mut db,
+                        &LEGACY_BLOB_LOADER,
+                    )?;
+                    Ok(())
+                })
+                .context("In on_lock_screen_event.")?;
+
+                Ok(())
+            }
+            (LockScreenEvent::UNLOCK, None) => {
+                check_keystore_permission(KeystorePerm::unlock())
+                    .context("In on_lock_screen_event: Unlock.")?;
+                ENFORCEMENTS.set_device_locked(user_id, false);
+                Ok(())
+            }
+            (LockScreenEvent::LOCK, None) => {
+                check_keystore_permission(KeystorePerm::lock())
+                    .context("In on_lock_screen_event: Lock")?;
+                ENFORCEMENTS.set_device_locked(user_id, true);
+                Ok(())
+            }
+            _ => {
+                // Any other combination is not supported.
+                Err(KeystoreError::Rc(ResponseCode::INVALID_ARGUMENT))
+                    .context("In on_lock_screen_event: Unknown event.")
+            }
+        }
+    }
+}
+
+impl Interface for AuthorizationManager {}
+
+impl IKeystoreAuthorization for AuthorizationManager {
+    fn addAuthToken(&self, auth_token: &HardwareAuthToken) -> BinderResult<()> {
+        map_or_log_err(self.add_auth_token(auth_token), Ok)
+    }
+
+    fn onLockScreenEvent(
+        &self,
+        lock_screen_event: LockScreenEvent,
+        user_id: i32,
+        password: Option<&[u8]>,
+    ) -> BinderResult<()> {
+        map_or_log_err(self.on_lock_screen_event(lock_screen_event, user_id, password), Ok)
+    }
+}
diff --git a/keystore2/src/background_task_handler.rs b/keystore2/src/background_task_handler.rs
new file mode 100644
index 0000000..b039506
--- /dev/null
+++ b/keystore2/src/background_task_handler.rs
@@ -0,0 +1,148 @@
+// Copyright 2020, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! This module implements the handling of background tasks such as obtaining timestamp tokens from
+//! the timestamp service (or TEE KeyMint in legacy devices), via a separate thread.
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    HardwareAuthToken::HardwareAuthToken,
+};
+use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
+    ISecureClock::ISecureClock, TimeStampToken::TimeStampToken,
+};
+use android_system_keystore2::aidl::android::system::keystore2::OperationChallenge::OperationChallenge;
+use anyhow::Result;
+use log::error;
+use std::sync::mpsc::{Receiver, Sender};
+use std::sync::Mutex;
+use std::thread::{spawn, JoinHandle};
+
+use crate::globals::get_timestamp_service;
+
+/// This is the struct encapsulating the thread which handles background tasks such as
+/// obtaining timestamp tokens.
+pub struct BackgroundTaskHandler {
+    task_handler: Mutex<Option<JoinHandle<()>>>,
+}
+
+/// This enum defines the two variants of a message that can be passed down to the
+/// BackgroundTaskHandler via the channel.
+pub enum Message {
+    ///This variant represents a message sent down the channel when requesting a timestamp token.
+    Inputs((HardwareAuthToken, OperationChallenge, Sender<(HardwareAuthToken, TimeStampToken)>)),
+    ///This variant represents a message sent down the channel when signalling the thread to stop.
+    Shutdown,
+}
+
+impl BackgroundTaskHandler {
+    /// Initialize the BackgroundTaskHandler with the task_handler field set to None.
+    /// The thread is not started during initialization, as it needs the receiver end of a channel
+    /// to function.
+    pub fn new() -> Self {
+        BackgroundTaskHandler { task_handler: Mutex::new(None) }
+    }
+
+    /// Start the background task handler (bth) by passing in the receiver end of a channel, through
+    /// which the enforcement module can send messages to the bth thread.
+    pub fn start_bth(&self, receiver: Receiver<Message>) -> Result<()> {
+        let task_handler = Self::start_thread(receiver)?;
+        // it is ok to unwrap here because there is no way that this lock can get poisoned.
+        let mut thread_guard = self.task_handler.lock().unwrap();
+        *thread_guard = Some(task_handler);
+        Ok(())
+    }
+
+    fn start_thread(receiver: Receiver<Message>) -> Result<JoinHandle<()>> {
+        // TODO: initialize timestamp service/keymint instances.
+        // First lookup timestamp token service, if this is not a legacy device.
+        // Otherwise, lookup keymaster 4.1 or 4.0 (previous ones are not relevant, because strongbox
+        // was introduced with keymaster 4.0).
+        // If either a timestamp service or a keymint instance is expected to be found and neither
+        // is found, an error is returned.
+        // If neither is expected to be found, make timestamp_service field None, and in the thread,
+        // send a default timestamp token down the channel to the operation.
+        // Until timestamp service is available and proper probing of legacy keymaster devices are
+        // done, the keymint service is initialized here as it is done in security_level module.
+        Ok(spawn(move || {
+            while let Message::Inputs((auth_token, op_challenge, op_sender)) =
+                receiver.recv().expect(
+                    "In background task handler thread. Failed to
+                receive message over the channel.",
+                )
+            {
+                let dev: Box<dyn ISecureClock> = get_timestamp_service()
+                    .expect(concat!(
+                        "Secure Clock service must be present ",
+                        "if TimeStampTokens are required."
+                    ))
+                    .get_interface()
+                    .expect("Fatal: Timestamp service does not implement ISecureClock.");
+                let result = dev.generateTimeStamp(op_challenge.challenge);
+                match result {
+                    Ok(timestamp_token) => {
+                        // this can fail if the operation is dropped and hence the channel
+                        // is hung up.
+                        op_sender.send((auth_token, timestamp_token)).unwrap_or_else(|e| {
+                            error!(
+                                "In background task handler thread. Failed to send
+                                         timestamp token to operation {} due to error {:?}.",
+                                op_challenge.challenge, e
+                            )
+                        });
+                    }
+                    Err(e) => {
+                        // log error
+                        error!(
+                            "In background task handler thread. Failed to receive
+                                     timestamp token for operation {} due to error {:?}.",
+                            op_challenge.challenge, e
+                        );
+                        // send default timestamp token
+                        // this can fail if the operation is dropped and the channel is
+                        // hung up.
+                        op_sender.send((auth_token, TimeStampToken::default())).unwrap_or_else(
+                            |e| {
+                                error!(
+                                    "In background task handler thread. Failed to send default
+                                         timestamp token to operation {} due to error {:?}.",
+                                    op_challenge.challenge, e
+                                )
+                            },
+                        );
+                    }
+                }
+            }
+        }))
+    }
+}
+
+impl Default for BackgroundTaskHandler {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+// TODO: Verify if we want the thread to finish the requests they are working on, during drop.
+impl Drop for BackgroundTaskHandler {
+    fn drop(&mut self) {
+        // it is ok to unwrap here as there is no way this lock can get poisoned.
+        let mut thread_guard = self.task_handler.lock().unwrap();
+        if let Some(thread) = (*thread_guard).take() {
+            // TODO: Verify how best to handle the error in this case.
+            thread.join().unwrap_or_else(|e| {
+                panic!("Failed to join the background task handling thread because of {:?}.", e);
+            });
+        }
+    }
+}
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index df1c24c..e25fea2 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -12,9 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//TODO: remove this in the future CLs in the stack.
-#![allow(dead_code)]
-
 //! This is the Keystore 2.0 database module.
 //! The database module provides a connection to the backing SQLite store.
 //! We have two databases one for persistent key blob storage and one for
@@ -59,14 +56,17 @@
 use std::{convert::TryFrom, convert::TryInto, time::SystemTimeError};
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-    HardwareAuthToken::HardwareAuthToken, HardwareAuthenticatorType::HardwareAuthenticatorType,
-    SecurityLevel::SecurityLevel,
+    ErrorCode::ErrorCode as Ec, HardwareAuthToken::HardwareAuthToken,
+    HardwareAuthenticatorType::HardwareAuthenticatorType, SecurityLevel::SecurityLevel,
+};
+use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
+    Timestamp::Timestamp,
 };
 use android_system_keystore2::aidl::android::system::keystore2::{
     Domain::Domain, KeyDescriptor::KeyDescriptor,
 };
-
 use lazy_static::lazy_static;
+use log::error;
 #[cfg(not(test))]
 use rand::prelude::random;
 use rusqlite::{
@@ -75,7 +75,7 @@
     types::FromSqlResult,
     types::ToSqlOutput,
     types::{FromSqlError, Value, ValueRef},
-    Connection, OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
+    Connection, Error, OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
 };
 use std::{
     collections::{HashMap, HashSet},
@@ -585,12 +585,6 @@
         })
     }
 
-    fn is_newer_than(&self, other: &AuthTokenEntry) -> bool {
-        // NOTE: Although in legacy keystore both timestamp and time_received are involved in this
-        // check, we decided to only consider time_received in keystore2 code.
-        self.time_received.seconds() > other.time_received.seconds()
-    }
-
     /// Returns the auth token wrapped by the AuthTokenEntry
     pub fn get_auth_token(self) -> HardwareAuthToken {
         self.auth_token
@@ -705,7 +699,9 @@
             NO_PARAMS,
         )
         .context("Failed to initialize \"metadata\" table.")?;
-
+        // TODO: Add the initial entry on last_off_body to the metadata table during the boot of the
+        // device (i.e. during the first startup of the keystore during a boot cycle).
+        Self::insert_last_off_body(conn, MonotonicRawTime::now()).context("In init-tables.")?;
         Ok(())
     }
 
@@ -1686,6 +1682,121 @@
             .context("In insert_auth_token: failed to insert auth token into the database")?;
         Ok(())
     }
+
+    /// find the auth token entry issued for a time-out token
+    pub fn find_timed_auth_token_entry(
+        &mut self,
+        user_secure_ids: &[i64],
+        auth_type: HardwareAuthenticatorType,
+        key_time_out: i64,
+        allow_while_on_body: bool,
+    ) -> Result<AuthTokenEntry> {
+        let tx = self
+            .conn
+            .transaction_with_behavior(TransactionBehavior::Immediate)
+            .context("In find_timed_auth_token_entry: failed to initialize transaction.")?;
+        let auth_token_entries =
+            Self::load_auth_token_entries(&tx).context("In find_timed_auth_token_entry.")?;
+        // NOTE: Although in legacy keystore both timestamp and time_received are used when finding
+        // the newest match, we decided to only consider time_received in keystore2 code.
+        // TODO: verify that the iter().find() preserves the order.
+        let newest_match: Option<AuthTokenEntry> = auth_token_entries.into_iter().find(|entry| {
+            AuthTokenEntry::satisfies_auth(&entry.auth_token, user_secure_ids, auth_type)
+        });
+
+        // Tag::ALLOW_WHILE_ON_BODY specifies that the key may be used after authentication
+        // timeout if device is still on-body. So we return error only if both checks fail.
+        if let Some(newest_match_entry) = newest_match {
+            let current_time = MonotonicRawTime::now();
+            let time_since_received_plus_time_out =
+                match newest_match_entry.time_received.seconds().checked_add(key_time_out) {
+                    Some(t) => t,
+                    None => {
+                        // we do not expect this behavior, so we need to log this error if it ever
+                        // happens.
+                        error!("In find_timed_auth_token_entry: overflow occurred.");
+                        return Err(KsError::Km(Ec::KEY_USER_NOT_AUTHENTICATED)).context(
+                            "In find_timed_auth_token_entry: matching auth token is expired.",
+                        );
+                    }
+                };
+            if (time_since_received_plus_time_out < current_time.seconds())
+                && (!allow_while_on_body
+                    || (newest_match_entry.time_received.seconds()
+                        < Self::get_last_off_body(&tx)?.seconds()))
+            {
+                return Err(KsError::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
+                    .context("In find_timed_auth_token_entry: matching auth token is expired.");
+            }
+            tx.commit().context("In find_timed_auth_token_entry, failed to commit transaction.")?;
+            Ok(newest_match_entry)
+        } else {
+            Err(KsError::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
+                .context("In find_timed_auth_token_entry: no matching auth token found.")
+        }
+    }
+
+    /// load the existing auth token entries in perboot.authtoken table into a vector.
+    /// return None if the table is empty.
+    fn load_auth_token_entries(tx: &Transaction) -> Result<Vec<AuthTokenEntry>> {
+        let mut stmt = tx
+            .prepare("SELECT * from perboot.authtoken ORDER BY time_received DESC;")
+            .context("In load_auth_token_entries: select prepare statement failed.")?;
+
+        let auth_token_entries: Vec<AuthTokenEntry> = stmt
+            .query_map(NO_PARAMS, |row| {
+                Ok(AuthTokenEntry::new(
+                    HardwareAuthToken {
+                        challenge: row.get(1)?,
+                        userId: row.get(2)?,
+                        authenticatorId: row.get(3)?,
+                        authenticatorType: HardwareAuthenticatorType(row.get(4)?),
+                        timestamp: Timestamp { milliSeconds: row.get(5)? },
+                        mac: row.get(6)?,
+                    },
+                    row.get(7)?,
+                ))
+            })
+            .context("In load_auth_token_entries: query_map failed.")?
+            .collect::<Result<Vec<AuthTokenEntry>, Error>>()
+            .context(
+                "In load_auth_token_entries: failed to create a vector of auth token entries
+                from mapped rows.",
+            )?;
+        Ok(auth_token_entries)
+    }
+
+    /// insert last_off_body into the metadata table at the initialization of auth token table
+    pub fn insert_last_off_body(conn: &Connection, last_off_body: MonotonicRawTime) -> Result<()> {
+        conn.execute(
+            "INSERT OR REPLACE INTO perboot.metadata (key, value) VALUES (?, ?);",
+            params!["last_off_body", last_off_body],
+        )
+        .context("In insert_last_off_body: failed to insert.")?;
+        Ok(())
+    }
+
+    /// update last_off_body when on_device_off_body is called
+    pub fn update_last_off_body(&self, last_off_body: MonotonicRawTime) -> Result<()> {
+        self.conn
+            .execute(
+                "UPDATE perboot.metadata SET value = ? WHERE key = ?;",
+                params![last_off_body, "last_off_body"],
+            )
+            .context("In update_last_off_body: failed to update.")?;
+        Ok(())
+    }
+
+    /// get last_off_body time when finding auth tokens
+    fn get_last_off_body(tx: &Transaction) -> Result<MonotonicRawTime> {
+        let mut stmt = tx
+            .prepare("SELECT value from perboot.metadata WHERE key = ?;")
+            .context("In get_last_off_body: select prepare statement failed.")?;
+        let last_off_body: Result<MonotonicRawTime> = stmt
+            .query_row(params!["last_off_body"], |row| Ok(row.get(0)?))
+            .context("In get_last_off_body: query_row failed.");
+        last_off_body
+    }
 }
 
 #[cfg(test)]
@@ -1702,15 +1813,17 @@
     use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
         HardwareAuthToken::HardwareAuthToken,
         HardwareAuthenticatorType::HardwareAuthenticatorType as kmhw_authenticator_type,
+    };
+    use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
         Timestamp::Timestamp,
     };
-    use rusqlite::Error;
     use rusqlite::NO_PARAMS;
+    use rusqlite::{Error, TransactionBehavior};
     use std::cell::RefCell;
     use std::sync::atomic::{AtomicU8, Ordering};
     use std::sync::Arc;
     use std::thread;
-    use std::time::SystemTime;
+    use std::time::{Duration, SystemTime};
 
     fn new_test_db() -> Result<KeystoreDB> {
         let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
@@ -2896,4 +3009,21 @@
             result
         })
     }
+
+    #[test]
+    fn test_last_off_body() -> Result<()> {
+        let mut db = new_test_db()?;
+        KeystoreDB::insert_last_off_body(&db.conn, MonotonicRawTime::now())?;
+        let tx = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
+        let last_off_body_1 = KeystoreDB::get_last_off_body(&tx)?;
+        tx.commit()?;
+        let one_second = Duration::from_secs(1);
+        thread::sleep(one_second);
+        db.update_last_off_body(MonotonicRawTime::now())?;
+        let tx2 = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
+        let last_off_body_2 = KeystoreDB::get_last_off_body(&tx2)?;
+        tx2.commit()?;
+        assert!(last_off_body_1.seconds() < last_off_body_2.seconds());
+        Ok(())
+    }
 }
diff --git a/keystore2/src/enforcements.rs b/keystore2/src/enforcements.rs
index 473686c..4ff3950 100644
--- a/keystore2/src/enforcements.rs
+++ b/keystore2/src/enforcements.rs
@@ -12,12 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//TODO: remove this after implementing the methods.
-#![allow(dead_code)]
-
 //! This is the Keystore 2.0 Enforcements module.
 // TODO: more description to follow.
 use crate::auth_token_handler::AuthTokenHandler;
+use crate::background_task_handler::Message;
 use crate::database::AuthTokenEntry;
 use crate::error::Error as KeystoreError;
 use crate::globals::DB;
@@ -25,11 +23,15 @@
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     Algorithm::Algorithm, ErrorCode::ErrorCode as Ec, HardwareAuthToken::HardwareAuthToken,
     HardwareAuthenticatorType::HardwareAuthenticatorType, KeyPurpose::KeyPurpose,
-    SecurityLevel::SecurityLevel, Tag::Tag, Timestamp::Timestamp,
+    SecurityLevel::SecurityLevel, Tag::Tag,
+};
+use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
+    TimeStampToken::TimeStampToken, Timestamp::Timestamp,
 };
 use android_system_keystore2::aidl::android::system::keystore2::OperationChallenge::OperationChallenge;
 use anyhow::{Context, Result};
 use std::collections::{HashMap, HashSet};
+use std::sync::mpsc::{channel, Sender};
 use std::sync::Mutex;
 use std::time::SystemTime;
 
@@ -41,25 +43,40 @@
     // This maps the operation challenge to an optional auth token, to maintain op-auth tokens
     // in-memory, until they are picked up and given to the operation by authorise_update_finish().
     op_auth_map: Mutex<HashMap<i64, Option<HardwareAuthToken>>>,
+    // sender end of the channel via which the enforcement module communicates with the
+    // background task handler (bth). This is of type Mutex in an Option because it is initialized
+    // after the global enforcement object is created.
+    sender_to_bth: Mutex<Option<Sender<Message>>>,
 }
 
 impl Enforcements {
-    /// Creates an enforcement object with the two data structures it holds.
+    /// Creates an enforcement object with the two data structures it holds and the sender as None.
     pub fn new() -> Self {
         Enforcements {
             device_unlocked_set: Mutex::new(HashSet::new()),
             op_auth_map: Mutex::new(HashMap::new()),
+            sender_to_bth: Mutex::new(None),
         }
     }
 
+    /// Initialize the sender_to_bth field, using the given sender end of a channel.
+    pub fn set_sender_to_bth(&self, sender: Sender<Message>) {
+        // It is ok to unwrap here because there is no chance of poisoning this mutex.
+        let mut sender_guard = self.sender_to_bth.lock().unwrap();
+        *sender_guard = Some(sender);
+    }
+
     /// Checks if update or finish calls are authorized. If the operation is based on per-op key,
     /// try to receive the auth token from the op_auth_map. We assume that by the time update/finish
     /// is called, the auth token has been delivered to keystore. Therefore, we do not wait for it
     /// and if the auth token is not found in the map, an error is returned.
+    /// This method is called only during the first call to update or if finish is called right
+    /// after create operation, because the operation caches the authorization decisions and tokens
+    /// from previous calls to enforcement module.
     pub fn authorize_update_or_finish(
         &self,
         key_params: &[KeyParameter],
-        op_challenge: Option<OperationChallenge>,
+        op_challenge: Option<&OperationChallenge>,
     ) -> Result<AuthTokenHandler> {
         let mut user_auth_type: Option<HardwareAuthenticatorType> = None;
         let mut user_secure_ids = Vec::<i64>::new();
@@ -137,8 +154,8 @@
     /// With regard to auth tokens, the following steps are taken:
     /// If the key is time-bound, find a matching auth token from the database.
     /// If the above step is successful, and if the security level is STRONGBOX, return a
-    /// VerificationRequired variant of the AuthTokenHandler with the found auth token to signal
-    /// the operation that it may need to obtain a verification token from TEE KeyMint.
+    /// TimestampRequired variant of the AuthTokenHandler with the found auth token to signal
+    /// the operation that it may need to obtain a timestamp token from TEE KeyMint.
     /// If the security level is not STRONGBOX, return a Token variant of the AuthTokenHandler with
     /// the found auth token to signal the operation that no more authorization required.
     /// If the key is per-op, return an OpAuthRequired variant of the AuthTokenHandler to signal
@@ -150,8 +167,7 @@
         purpose: KeyPurpose,
         key_params: &[KeyParameter],
         op_params: &[KeyParameter],
-        // security_level will be used in the next CL
-        _security_level: SecurityLevel,
+        security_level: SecurityLevel,
     ) -> Result<AuthTokenHandler> {
         match purpose {
             // Allow SIGN, DECRYPT for both symmetric and asymmetric keys.
@@ -188,11 +204,14 @@
         // reduce the number of for loops on key parameters from 3 to 1, compared to legacy keystore
         let mut key_purpose_authorized: bool = false;
         let mut is_time_out_key: bool = false;
-        let mut auth_type: Option<HardwareAuthenticatorType> = None;
+        let mut user_auth_type: Option<HardwareAuthenticatorType> = None;
         let mut no_auth_required: bool = false;
         let mut caller_nonce_allowed = false;
         let mut user_id: i32 = -1;
         let mut user_secure_ids = Vec::<i64>::new();
+        let mut key_time_out: Option<i64> = None;
+        let mut allow_while_on_body = false;
+        let mut unlocked_device_required = false;
 
         // iterate through key parameters, recording information we need for authorization
         // enforcements later, or enforcing authorizations in place, where applicable
@@ -201,11 +220,12 @@
                 KeyParameterValue::NoAuthRequired => {
                     no_auth_required = true;
                 }
-                KeyParameterValue::AuthTimeout(_) => {
+                KeyParameterValue::AuthTimeout(t) => {
                     is_time_out_key = true;
+                    key_time_out = Some(*t as i64);
                 }
                 KeyParameterValue::HardwareAuthenticatorType(a) => {
-                    auth_type = Some(*a);
+                    user_auth_type = Some(*a);
                 }
                 KeyParameterValue::KeyPurpose(p) => {
                     // Note: if there can be multiple KeyPurpose key parameters (TODO: confirm this),
@@ -248,12 +268,10 @@
                     user_id = *u;
                 }
                 KeyParameterValue::UnlockedDeviceRequired => {
-                    // check the device locked status. If locked, operations on the key are not
-                    // allowed.
-                    if self.is_device_locked(user_id) {
-                        return Err(KeystoreError::Km(Ec::DEVICE_LOCKED))
-                            .context("In authorize_create: device is locked.");
-                    }
+                    unlocked_device_required = true;
+                }
+                KeyParameterValue::AllowWhileOnBody => {
+                    allow_while_on_body = true;
                 }
                 // NOTE: as per offline discussion, sanitizing key parameters and rejecting
                 // create operation if any non-allowed tags are present, is not done in
@@ -279,8 +297,8 @@
         }
 
         // if either of auth_type or secure_id is present and the other is not present, return error
-        if (auth_type.is_some() && user_secure_ids.is_empty())
-            || (auth_type.is_none() && !user_secure_ids.is_empty())
+        if (user_auth_type.is_some() && user_secure_ids.is_empty())
+            || (user_auth_type.is_none() && !user_secure_ids.is_empty())
         {
             return Err(KeystoreError::Km(Ec::KEY_USER_NOT_AUTHENTICATED)).context(
                 "In authorize_create: Auth required, but either auth type or secure ids
@@ -298,14 +316,48 @@
             );
         }
 
+        if unlocked_device_required {
+            // check the device locked status. If locked, operations on the key are not
+            // allowed.
+            log::info!("Checking for lockd device of user {}.", user_id);
+            if self.is_device_locked(user_id) {
+                return Err(KeystoreError::Km(Ec::DEVICE_LOCKED))
+                    .context("In authorize_create: device is locked.");
+            }
+        }
+
         if !user_secure_ids.is_empty() {
-            // per op auth token
+            // key requiring authentication per operation
             if !is_time_out_key {
                 return Ok(AuthTokenHandler::OpAuthRequired);
             } else {
-                //time out token
-                // TODO: retrieve it from the database
-                // - in an upcoming CL
+                // key requiring time-out based authentication
+                let auth_token = DB
+                    .with::<_, Result<HardwareAuthToken>>(|db| {
+                        let mut db = db.borrow_mut();
+                        match (user_auth_type, key_time_out) {
+                            (Some(auth_type), Some(key_time_out)) => {
+                                let matching_entry = db
+                                    .find_timed_auth_token_entry(
+                                        &user_secure_ids,
+                                        auth_type,
+                                        key_time_out,
+                                        allow_while_on_body,
+                                    )
+                                    .context("Failed to find timed auth token.")?;
+                                Ok(matching_entry.get_auth_token())
+                            }
+                            (_, _) => Err(KeystoreError::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
+                                .context("Authenticator type and/or key time out is not given."),
+                        }
+                    })
+                    .context("In authorize_create.")?;
+
+                if security_level == SecurityLevel::STRONGBOX {
+                    return Ok(AuthTokenHandler::TimestampRequired(auth_token));
+                } else {
+                    return Ok(AuthTokenHandler::Token(auth_token, None));
+                }
             }
         }
 
@@ -377,6 +429,43 @@
             .context("In add_auth_token.")?;
         Ok(())
     }
+
+    /// This allows adding an entry to the op_auth_map, indexed by the operation challenge.
+    /// This is to be called by create_operation, once it has received the operation challenge
+    /// from keymint for an operation whose authorization decision is OpAuthRequired, as signalled
+    /// by the AuthTokenHandler.
+    pub fn insert_to_op_auth_map(&self, op_challenge: i64) {
+        let mut op_auth_map_guard = self.op_auth_map.lock().unwrap();
+        op_auth_map_guard.insert(op_challenge, None);
+    }
+
+    /// Requests a timestamp token from the background task handler which will retrieve it from
+    /// Timestamp Service or TEE KeyMint.
+    /// Once the create_operation receives an operation challenge from KeyMint, if it has
+    /// previously received a TimestampRequired variant of AuthTokenHandler during
+    /// authorize_create_operation, it calls this method to obtain a TimeStampToken.
+    pub fn request_timestamp_token(
+        &self,
+        auth_token: HardwareAuthToken,
+        op_challenge: OperationChallenge,
+    ) -> Result<AuthTokenHandler> {
+        // create a channel for this particular operation
+        let (op_sender, op_receiver) = channel::<(HardwareAuthToken, TimeStampToken)>();
+        // it is ok to unwrap here because there is no way this mutex gets poisoned.
+        let sender_guard = self.sender_to_bth.lock().unwrap();
+        if let Some(sender) = &*sender_guard {
+            let sender_cloned = sender.clone();
+            drop(sender_guard);
+            sender_cloned
+                .send(Message::Inputs((auth_token, op_challenge, op_sender)))
+                .map_err(|_| KeystoreError::sys())
+                .context(
+                    "In request_timestamp_token. Sending a request for a timestamp token
+             failed.",
+                )?;
+        }
+        Ok(AuthTokenHandler::Channel(op_receiver))
+    }
 }
 
 impl Default for Enforcements {
@@ -385,4 +474,21 @@
     }
 }
 
+impl Drop for Enforcements {
+    fn drop(&mut self) {
+        let sender_guard = self.sender_to_bth.lock().unwrap();
+        if let Some(sender) = &*sender_guard {
+            let sender_cloned = sender.clone();
+            drop(sender_guard);
+            // TODO: Verify how best to handle the error in this case.
+            sender_cloned.send(Message::Shutdown).unwrap_or_else(|e| {
+                panic!(
+                    "Failed to send shutdown message to background task handler because of {:?}.",
+                    e
+                );
+            });
+        }
+    }
+}
+
 // TODO: Add tests to enforcement module (b/175578618).
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index 18bed9a..7ceff26 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -17,7 +17,10 @@
 //! to talk to.
 
 use crate::async_task::AsyncTask;
+use crate::background_task_handler::BackgroundTaskHandler;
+use crate::enforcements::Enforcements;
 use crate::gc::Gc;
+use crate::legacy_blob::LegacyBlobLoader;
 use crate::super_key::SuperKeyManager;
 use crate::utils::Asp;
 use crate::{
@@ -78,9 +81,21 @@
     pub static ref SUPER_KEY: SuperKeyManager = Default::default();
     /// Map of KeyMint devices.
     static ref KEY_MINT_DEVICES: Mutex<HashMap<SecurityLevel, Asp>> = Default::default();
+    /// Timestamp service.
+    static ref TIME_STAMP_DEVICE: Mutex<Option<Asp>> = Default::default();
     /// A single on-demand worker thread that handles deferred tasks with two different
     /// priorities.
     pub static ref ASYNC_TASK: AsyncTask = Default::default();
+    /// Singeleton for enforcements.
+    pub static ref ENFORCEMENTS: Enforcements = Enforcements::new();
+    /// Background task handler is initialized and exists globally.
+    /// The other modules (e.g. enforcements) communicate with it via a channel initialized during
+    /// keystore startup.
+    pub static ref BACKGROUND_TASK_HANDLER: BackgroundTaskHandler = BackgroundTaskHandler::new();
+    /// LegacyBlobLoader is initialized and exists globally.
+    /// The same directory used by the database is used by the LegacyBlobLoader as well.
+    pub static ref LEGACY_BLOB_LOADER: LegacyBlobLoader = LegacyBlobLoader::new(
+        &std::env::current_dir().expect("Could not get the current working directory."));
 }
 
 static KEYMINT_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice";
@@ -132,11 +147,58 @@
     if let Some(dev) = devices_map.get(&security_level) {
         Ok(dev.clone())
     } else {
-        let dev = connect_keymint(security_level).map_err(|e| {
-            anyhow::anyhow!(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
-                .context(format!("In get_keymint_device: {:?}", e))
-        })?;
+        let dev = connect_keymint(security_level).context("In get_keymint_device.")?;
         devices_map.insert(security_level, dev.clone());
         Ok(dev)
     }
 }
+
+static TIME_STAMP_SERVICE_NAME: &str = "android.hardware.security.secureclock.ISecureClock";
+
+/// Make a new connection to a secure clock service.
+/// If no native SecureClock device can be found brings up the compatibility service and attempts
+/// to connect to the legacy wrapper.
+fn connect_secureclock() -> Result<Asp> {
+    let secureclock = map_binder_status_code(binder::get_interface(TIME_STAMP_SERVICE_NAME))
+        .context("In connect_secureclock: Trying to connect to genuine secure clock service.")
+        .or_else(|e| {
+            match e.root_cause().downcast_ref::<Error>() {
+                Some(Error::BinderTransaction(StatusCode::NAME_NOT_FOUND)) => {
+                    // This is a no-op if it was called before.
+                    keystore2_km_compat::add_keymint_device_service();
+
+                    let keystore_compat_service: Box<dyn IKeystoreCompatService> =
+                        map_binder_status_code(binder::get_interface("android.security.compat"))
+                            .context(
+                                "In connect_secureclock: Trying to connect to compat service.",
+                            )?;
+
+                    // Legacy secure clock services were only implemented by TEE.
+                    map_binder_status(keystore_compat_service.getSecureClock())
+                        .map_err(|e| match e {
+                            Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => {
+                                Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)
+                            }
+                            e => e,
+                        })
+                        .context("In connect_secureclock: Trying to get Legacy wrapper.")
+                }
+                _ => Err(e),
+            }
+        })?;
+
+    Ok(Asp::new(secureclock.as_binder()))
+}
+
+/// Get the timestamp service that verifies auth token timeliness towards security levels with
+/// different clocks.
+pub fn get_timestamp_service() -> Result<Asp> {
+    let mut ts_device = TIME_STAMP_DEVICE.lock().unwrap();
+    if let Some(dev) = &*ts_device {
+        Ok(dev.clone())
+    } else {
+        let dev = connect_secureclock().context("In get_timestamp_service.")?;
+        *ts_device = Some(dev.clone());
+        Ok(dev)
+    }
+}
diff --git a/keystore2/src/keystore2_main.rs b/keystore2/src/keystore2_main.rs
index 7391f37..c75cfc8 100644
--- a/keystore2/src/keystore2_main.rs
+++ b/keystore2/src/keystore2_main.rs
@@ -16,12 +16,17 @@
 
 use binder::Interface;
 use keystore2::apc::ApcManager;
+use keystore2::authorization::AuthorizationManager;
+use keystore2::background_task_handler::Message;
+use keystore2::globals::{BACKGROUND_TASK_HANDLER, ENFORCEMENTS};
 use keystore2::service::KeystoreService;
 use log::{error, info};
 use std::panic;
+use std::sync::mpsc::channel;
 
 static KS2_SERVICE_NAME: &str = "android.system.keystore2";
 static APC_SERVICE_NAME: &str = "android.security.apc";
+static AUTHORIZATION_SERVICE_NAME: &str = "android.security.authorization";
 
 /// Keystore 2.0 takes one argument which is a path indicating its designated working directory.
 fn main() {
@@ -50,6 +55,14 @@
         panic!("Must specify a working directory.");
     }
 
+    // initialize the channel via which the enforcement module and background task handler module
+    // communicate, and hand over the sender and receiver ends to the respective objects.
+    let (sender, receiver) = channel::<Message>();
+    ENFORCEMENTS.set_sender_to_bth(sender);
+    BACKGROUND_TASK_HANDLER.start_bth(receiver).unwrap_or_else(|e| {
+        panic!("Failed to start background task handler because of {:?}.", e);
+    });
+
     info!("Starting thread pool now.");
     binder::ProcessState::start_thread_pool();
 
@@ -67,6 +80,14 @@
         panic!("Failed to register service {} because of {:?}.", APC_SERVICE_NAME, e);
     });
 
+    let authorization_service = AuthorizationManager::new_native_binder().unwrap_or_else(|e| {
+        panic!("Failed to create service {} because of {:?}.", AUTHORIZATION_SERVICE_NAME, e);
+    });
+    binder::add_service(AUTHORIZATION_SERVICE_NAME, authorization_service.as_binder())
+        .unwrap_or_else(|e| {
+            panic!("Failed to register service {} because of {:?}.", AUTHORIZATION_SERVICE_NAME, e);
+        });
+
     info!("Successfully registered Keystore 2.0 service.");
 
     info!("Joining thread pool now.");
diff --git a/keystore2/src/km_compat/Android.bp b/keystore2/src/km_compat/Android.bp
index 7ca6a63..a5da5a6 100644
--- a/keystore2/src/km_compat/Android.bp
+++ b/keystore2/src/km_compat/Android.bp
@@ -49,6 +49,8 @@
         "android.hardware.keymaster@4.0",
         "android.hardware.keymaster@4.1",
         "android.hardware.security.keymint-unstable-ndk_platform",
+        "android.hardware.security.secureclock-unstable-ndk_platform",
+        "android.hardware.security.sharedsecret-unstable-ndk_platform",
         "android.security.compat-ndk_platform",
         "android.system.keystore2-ndk_platform",
         "libbase",
@@ -66,6 +68,9 @@
     name: "libkm_compat_service",
     srcs: ["km_compat_service.cpp"],
     shared_libs: [
+        "android.hardware.security.keymint-unstable-ndk_platform",
+        "android.hardware.security.secureclock-unstable-ndk_platform",
+        "android.hardware.security.sharedsecret-unstable-ndk_platform",
         "android.security.compat-ndk_platform",
         "libbinder_ndk",
         "libcrypto",
@@ -93,6 +98,8 @@
         "android.hardware.keymaster@4.0",
         "android.hardware.keymaster@4.1",
         "android.hardware.security.keymint-unstable-ndk_platform",
+        "android.hardware.security.secureclock-unstable-ndk_platform",
+        "android.hardware.security.sharedsecret-unstable-ndk_platform",
         "android.security.compat-ndk_platform",
         "android.system.keystore2-ndk_platform",
         "libbase",
diff --git a/keystore2/src/km_compat/certificate_test.cpp b/keystore2/src/km_compat/certificate_test.cpp
index 9307569..d6bece7 100644
--- a/keystore2/src/km_compat/certificate_test.cpp
+++ b/keystore2/src/km_compat/certificate_test.cpp
@@ -49,14 +49,12 @@
     if (!device) {
         return ScopedAStatus::fromStatus(STATUS_NAME_NOT_FOUND);
     }
-    ByteArray blob;
-    KeyCharacteristics characteristics;
-    std::vector<Certificate> certChain;
-    auto status = device->generateKey(keyParams, &blob, &characteristics, &certChain);
+    KeyCreationResult creationResult;
+    auto status = device->generateKey(keyParams, &creationResult);
     if (!status.isOk()) {
         return status;
     }
-    return certChain;
+    return creationResult.certificateChain;
 }
 
 static void ensureCertChainSize(const std::variant<std::vector<Certificate>, ScopedAStatus>& result,
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index c9af80d..d965922 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -35,12 +35,12 @@
 using ::aidl::android::hardware::security::keymint::Digest;
 using ::aidl::android::hardware::security::keymint::PaddingMode;
 using ::aidl::android::hardware::security::keymint::Tag;
-using ::aidl::android::hardware::security::keymint::VerificationToken;
 using ::aidl::android::system::keystore2::ResponseCode;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::keymaster::V4_0::TagType;
 using ::android::hidl::manager::V1_2::IServiceManager;
 using V4_0_HardwareAuthToken = ::android::hardware::keymaster::V4_0::HardwareAuthToken;
+using V4_0_HmacSharingParameters = ::android::hardware::keymaster::V4_0::HmacSharingParameters;
 using V4_0_KeyCharacteristics = ::android::hardware::keymaster::V4_0::KeyCharacteristics;
 using V4_0_KeyFormat = ::android::hardware::keymaster::V4_0::KeyFormat;
 using V4_0_KeyParameter = ::android::hardware::keymaster::V4_0::KeyParameter;
@@ -73,12 +73,13 @@
     return kps;
 }
 
-static KeyCharacteristics
-convertKeyCharacteristicsFromLegacy(const V4_0_KeyCharacteristics& legacyKc) {
+static std::vector<KeyCharacteristics>
+convertKeyCharacteristicsFromLegacy(KeyMintSecurityLevel securityLevel,
+                                    const V4_0_KeyCharacteristics& legacyKc) {
     KeyCharacteristics kc;
-    kc.softwareEnforced = convertKeyParametersFromLegacy(legacyKc.softwareEnforced);
-    kc.hardwareEnforced = convertKeyParametersFromLegacy(legacyKc.hardwareEnforced);
-    return kc;
+    kc.securityLevel = securityLevel;
+    kc.authorizations = convertKeyParametersFromLegacy(legacyKc.hardwareEnforced);
+    return {kc};
 }
 
 static V4_0_KeyFormat convertKeyFormatToLegacy(const KeyFormat& kf) {
@@ -98,16 +99,32 @@
     return legacyAt;
 }
 
-static V4_0_VerificationToken convertVerificationTokenToLegacy(const VerificationToken& vt) {
+static V4_0_VerificationToken convertTimestampTokenToLegacy(const TimeStampToken& tst) {
     V4_0_VerificationToken legacyVt;
-    legacyVt.challenge = vt.challenge;
-    legacyVt.timestamp = vt.timestamp.milliSeconds;
-    legacyVt.securityLevel =
-        static_cast<::android::hardware::keymaster::V4_0::SecurityLevel>(vt.securityLevel);
-    legacyVt.mac = vt.mac;
+    legacyVt.challenge = tst.challenge;
+    legacyVt.timestamp = tst.timestamp.milliSeconds;
+    // Legacy verification tokens were always minted by TEE.
+    legacyVt.securityLevel = V4_0::SecurityLevel::TRUSTED_ENVIRONMENT;
+    legacyVt.mac = tst.mac;
     return legacyVt;
 }
 
+static V4_0_HmacSharingParameters
+convertSharedSecretParameterToLegacy(const SharedSecretParameters& ssp) {
+    V4_0_HmacSharingParameters legacyHsp;
+    legacyHsp.seed = ssp.seed;
+    std::copy(ssp.nonce.begin(), ssp.nonce.end(), legacyHsp.nonce.data());
+    return legacyHsp;
+}
+
+static std::vector<V4_0_HmacSharingParameters>
+convertSharedSecretParametersToLegacy(const std::vector<SharedSecretParameters>& legacySsps) {
+    std::vector<V4_0_HmacSharingParameters> ssps(legacySsps.size());
+    std::transform(legacySsps.begin(), legacySsps.end(), ssps.begin(),
+                   convertSharedSecretParameterToLegacy);
+    return ssps;
+}
+
 void OperationSlots::setNumFreeSlots(uint8_t numFreeSlots) {
     std::lock_guard<std::mutex> lock(mNumFreeSlotsMutex);
     mNumFreeSlots = numFreeSlots;
@@ -140,8 +157,10 @@
     // TODO: What do I do about the version number?  Is it the version of the device I get?
     auto result = mDevice->getHardwareInfo([&](auto securityLevel, const auto& keymasterName,
                                                const auto& keymasterAuthorName) {
-        _aidl_return->securityLevel =
+        securityLevel_ =
             static_cast<::aidl::android::hardware::security::keymint::SecurityLevel>(securityLevel);
+
+        _aidl_return->securityLevel = securityLevel_;
         _aidl_return->keyMintName = keymasterName;
         _aidl_return->keyMintAuthorName = keymasterAuthorName;
     });
@@ -152,48 +171,38 @@
     return ScopedAStatus::ok();
 }
 
-// We're not implementing this.
-ScopedAStatus KeyMintDevice::verifyAuthorization(int64_t in_challenge ATTRIBUTE_UNUSED,
-                                                 const HardwareAuthToken& in_token ATTRIBUTE_UNUSED,
-                                                 VerificationToken* _aidl_return ATTRIBUTE_UNUSED) {
-    return ScopedAStatus::fromServiceSpecificError(
-        static_cast<int32_t>(V4_0_ErrorCode::UNIMPLEMENTED));
-}
-
 ScopedAStatus KeyMintDevice::addRngEntropy(const std::vector<uint8_t>& in_data) {
     V4_0_ErrorCode errorCode = mDevice->addRngEntropy(in_data);
     return convertErrorCode(errorCode);
 }
 
 ScopedAStatus KeyMintDevice::generateKey(const std::vector<KeyParameter>& in_keyParams,
-                                         ByteArray* out_generatedKeyBlob,
-                                         KeyCharacteristics* out_generatedKeyCharacteristics,
-                                         std::vector<Certificate>* out_outCertChain) {
+                                         KeyCreationResult* out_creationResult) {
     auto legacyKeyParams = convertKeyParametersToLegacy(in_keyParams);
     V4_0_ErrorCode errorCode;
     auto result = mDevice->generateKey(
         legacyKeyParams, [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
                              const V4_0_KeyCharacteristics& keyCharacteristics) {
             errorCode = error;
-            out_generatedKeyBlob->data = keyBlob;
-            *out_generatedKeyCharacteristics =
-                convertKeyCharacteristicsFromLegacy(keyCharacteristics);
+            out_creationResult->keyBlob = keyBlob;
+            out_creationResult->keyCharacteristics =
+                convertKeyCharacteristicsFromLegacy(securityLevel_, keyCharacteristics);
         });
     if (!result.isOk()) {
         return ScopedAStatus::fromServiceSpecificError(
             static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
     }
     if (errorCode == V4_0_ErrorCode::OK) {
-        auto cert = getCertificate(in_keyParams, out_generatedKeyBlob->data);
+        auto cert = getCertificate(in_keyParams, out_creationResult->keyBlob);
         if (std::holds_alternative<V4_0_ErrorCode>(cert)) {
             auto code = std::get<V4_0_ErrorCode>(cert);
             // We return OK in successful cases that do not generate a certificate.
             if (code != V4_0_ErrorCode::OK) {
                 errorCode = code;
-                deleteKey(out_generatedKeyBlob->data);
+                deleteKey(out_creationResult->keyBlob);
             }
         } else {
-            *out_outCertChain = std::get<std::vector<Certificate>>(cert);
+            out_creationResult->certificateChain = std::get<std::vector<Certificate>>(cert);
         }
     }
     return convertErrorCode(errorCode);
@@ -202,36 +211,34 @@
 ScopedAStatus KeyMintDevice::importKey(const std::vector<KeyParameter>& in_inKeyParams,
                                        KeyFormat in_inKeyFormat,
                                        const std::vector<uint8_t>& in_inKeyData,
-                                       ByteArray* out_outImportedKeyBlob,
-                                       KeyCharacteristics* out_outImportedKeyCharacteristics,
-                                       std::vector<Certificate>* out_outCertChain) {
+                                       KeyCreationResult* out_creationResult) {
     auto legacyKeyParams = convertKeyParametersToLegacy(in_inKeyParams);
     auto legacyKeyFormat = convertKeyFormatToLegacy(in_inKeyFormat);
     V4_0_ErrorCode errorCode;
-    auto result =
-        mDevice->importKey(legacyKeyParams, legacyKeyFormat, in_inKeyData,
-                           [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
-                               const V4_0_KeyCharacteristics& keyCharacteristics) {
-                               errorCode = error;
-                               out_outImportedKeyBlob->data = keyBlob;
-                               *out_outImportedKeyCharacteristics =
-                                   convertKeyCharacteristicsFromLegacy(keyCharacteristics);
-                           });
+    auto result = mDevice->importKey(legacyKeyParams, legacyKeyFormat, in_inKeyData,
+                                     [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
+                                         const V4_0_KeyCharacteristics& keyCharacteristics) {
+                                         errorCode = error;
+                                         out_creationResult->keyBlob = keyBlob;
+                                         out_creationResult->keyCharacteristics =
+                                             convertKeyCharacteristicsFromLegacy(
+                                                 securityLevel_, keyCharacteristics);
+                                     });
     if (!result.isOk()) {
         return ScopedAStatus::fromServiceSpecificError(
             static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
     }
     if (errorCode == V4_0_ErrorCode::OK) {
-        auto cert = getCertificate(in_inKeyParams, out_outImportedKeyBlob->data);
+        auto cert = getCertificate(in_inKeyParams, out_creationResult->keyBlob);
         if (std::holds_alternative<V4_0_ErrorCode>(cert)) {
             auto code = std::get<V4_0_ErrorCode>(cert);
             // We return OK in successful cases that do not generate a certificate.
             if (code != V4_0_ErrorCode::OK) {
                 errorCode = code;
-                deleteKey(out_outImportedKeyBlob->data);
+                deleteKey(out_creationResult->keyBlob);
             }
         } else {
-            *out_outCertChain = std::get<std::vector<Certificate>>(cert);
+            out_creationResult->certificateChain = std::get<std::vector<Certificate>>(cert);
         }
     }
     return convertErrorCode(errorCode);
@@ -241,20 +248,19 @@
     const std::vector<uint8_t>& in_inWrappedKeyData,
     const std::vector<uint8_t>& in_inWrappingKeyBlob, const std::vector<uint8_t>& in_inMaskingKey,
     const std::vector<KeyParameter>& in_inUnwrappingParams, int64_t in_inPasswordSid,
-    int64_t in_inBiometricSid, ByteArray* out_outImportedKeyBlob,
-    KeyCharacteristics* out_outImportedKeyCharacteristics) {
+    int64_t in_inBiometricSid, KeyCreationResult* out_creationResult) {
     auto legacyUnwrappingParams = convertKeyParametersToLegacy(in_inUnwrappingParams);
     V4_0_ErrorCode errorCode;
-    auto result =
-        mDevice->importWrappedKey(in_inWrappedKeyData, in_inWrappingKeyBlob, in_inMaskingKey,
-                                  legacyUnwrappingParams, in_inPasswordSid, in_inBiometricSid,
-                                  [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
-                                      const V4_0_KeyCharacteristics& keyCharacteristics) {
-                                      errorCode = error;
-                                      out_outImportedKeyBlob->data = keyBlob;
-                                      *out_outImportedKeyCharacteristics =
-                                          convertKeyCharacteristicsFromLegacy(keyCharacteristics);
-                                  });
+    auto result = mDevice->importWrappedKey(
+        in_inWrappedKeyData, in_inWrappingKeyBlob, in_inMaskingKey, legacyUnwrappingParams,
+        in_inPasswordSid, in_inBiometricSid,
+        [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
+            const V4_0_KeyCharacteristics& keyCharacteristics) {
+            errorCode = error;
+            out_creationResult->keyBlob = keyBlob;
+            out_creationResult->keyCharacteristics =
+                convertKeyCharacteristicsFromLegacy(securityLevel_, keyCharacteristics);
+        });
     if (!result.isOk()) {
         return ScopedAStatus::fromServiceSpecificError(
             static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
@@ -331,13 +337,13 @@
     return convertErrorCode(errorCode);
 }
 
-ScopedAStatus
-KeyMintOperation::update(const std::optional<KeyParameterArray>& in_inParams,
-                         const std::optional<std::vector<uint8_t>>& in_input,
-                         const std::optional<HardwareAuthToken>& in_inAuthToken,
-                         const std::optional<VerificationToken>& in_inVerificationToken,
-                         std::optional<KeyParameterArray>* out_outParams,
-                         std::optional<ByteArray>* out_output, int32_t* _aidl_return) {
+ScopedAStatus KeyMintOperation::update(const std::optional<KeyParameterArray>& in_inParams,
+                                       const std::optional<std::vector<uint8_t>>& in_input,
+                                       const std::optional<HardwareAuthToken>& in_inAuthToken,
+                                       const std::optional<TimeStampToken>& in_inTimeStampToken,
+                                       std::optional<KeyParameterArray>* out_outParams,
+                                       std::optional<ByteArray>* out_output,
+                                       int32_t* _aidl_return) {
     std::vector<V4_0_KeyParameter> legacyParams;
     if (in_inParams.has_value()) {
         legacyParams = convertKeyParametersToLegacy(in_inParams.value().params);
@@ -348,8 +354,8 @@
         authToken = convertAuthTokenToLegacy(in_inAuthToken.value());
     }
     V4_0_VerificationToken verificationToken;
-    if (in_inVerificationToken.has_value()) {
-        verificationToken = convertVerificationTokenToLegacy(in_inVerificationToken.value());
+    if (in_inTimeStampToken.has_value()) {
+        verificationToken = convertTimestampTokenToLegacy(in_inTimeStampToken.value());
     }
     V4_0_ErrorCode errorCode;
     auto result = mDevice->update(
@@ -374,14 +380,13 @@
     return convertErrorCode(errorCode);
 }
 
-ScopedAStatus
-KeyMintOperation::finish(const std::optional<KeyParameterArray>& in_inParams,
-                         const std::optional<std::vector<uint8_t>>& in_input,
-                         const std::optional<std::vector<uint8_t>>& in_inSignature,
-                         const std::optional<HardwareAuthToken>& in_authToken,
-                         const std::optional<VerificationToken>& in_inVerificationToken,
-                         std::optional<KeyParameterArray>* out_outParams,
-                         std::vector<uint8_t>* _aidl_return) {
+ScopedAStatus KeyMintOperation::finish(const std::optional<KeyParameterArray>& in_inParams,
+                                       const std::optional<std::vector<uint8_t>>& in_input,
+                                       const std::optional<std::vector<uint8_t>>& in_inSignature,
+                                       const std::optional<HardwareAuthToken>& in_authToken,
+                                       const std::optional<TimeStampToken>& in_inTimeStampToken,
+                                       std::optional<KeyParameterArray>* out_outParams,
+                                       std::vector<uint8_t>* _aidl_return) {
     V4_0_ErrorCode errorCode;
     std::vector<V4_0_KeyParameter> legacyParams;
     if (in_inParams.has_value()) {
@@ -394,8 +399,8 @@
         authToken = convertAuthTokenToLegacy(in_authToken.value());
     }
     V4_0_VerificationToken verificationToken;
-    if (in_inVerificationToken.has_value()) {
-        verificationToken = convertVerificationTokenToLegacy(in_inVerificationToken.value());
+    if (in_inTimeStampToken.has_value()) {
+        verificationToken = convertTimestampTokenToLegacy(in_inTimeStampToken.value());
     }
     auto result = mDevice->finish(
         mOperationHandle, legacyParams, input, signature, authToken, verificationToken,
@@ -429,6 +434,60 @@
     }
 }
 
+// SecureClock implementation
+
+ScopedAStatus SecureClock::generateTimeStamp(int64_t in_challenge, TimeStampToken* _aidl_return) {
+    V4_0_ErrorCode errorCode;
+    auto result = mDevice->verifyAuthorization(
+        in_challenge, {}, V4_0_HardwareAuthToken(),
+        [&](V4_0_ErrorCode error, const V4_0_VerificationToken& token) {
+            errorCode = error;
+            _aidl_return->challenge = token.challenge;
+            _aidl_return->timestamp.milliSeconds = token.timestamp;
+            _aidl_return->mac = token.mac;
+        });
+    if (!result.isOk()) {
+        return ScopedAStatus::fromServiceSpecificError(
+            static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
+    }
+    return convertErrorCode(errorCode);
+}
+
+// SharedSecret implementation
+
+ScopedAStatus SharedSecret::getSharedSecretParameters(SharedSecretParameters* _aidl_return) {
+    V4_0_ErrorCode errorCode;
+    auto result = mDevice->getHmacSharingParameters(
+        [&](V4_0_ErrorCode error, const V4_0_HmacSharingParameters& params) {
+            errorCode = error;
+            _aidl_return->seed = params.seed;
+            std::copy(params.nonce.data(), params.nonce.data() + params.nonce.elementCount(),
+                      std::back_inserter(_aidl_return->nonce));
+        });
+    if (!result.isOk()) {
+        return ScopedAStatus::fromServiceSpecificError(
+            static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
+    }
+    return convertErrorCode(errorCode);
+}
+
+ScopedAStatus
+SharedSecret::computeSharedSecret(const std::vector<SharedSecretParameters>& in_params,
+                                  std::vector<uint8_t>* _aidl_return) {
+    V4_0_ErrorCode errorCode;
+    auto legacyParams = convertSharedSecretParametersToLegacy(in_params);
+    auto result = mDevice->computeSharedHmac(
+        legacyParams, [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& sharingCheck) {
+            errorCode = error;
+            *_aidl_return = sharingCheck;
+        });
+    if (!result.isOk()) {
+        return ScopedAStatus::fromServiceSpecificError(
+            static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
+    }
+    return convertErrorCode(errorCode);
+}
+
 // Certificate implementation
 
 template <KMV1::Tag tag, KMV1::TagType type>
@@ -607,8 +666,8 @@
             std::optional<KeyParameterArray> outParams;
             std::optional<ByteArray> outByte;
             int32_t status;
-            beginResult.operation->update(std::nullopt, dataVec, HardwareAuthToken(),
-                                          VerificationToken(), &outParams, &outByte, &status);
+            beginResult.operation->update(std::nullopt, dataVec, std::nullopt, std::nullopt,
+                                          &outParams, &outByte, &status);
             if (!status) {
                 return std::vector<uint8_t>();
             }
@@ -832,7 +891,11 @@
     return result;
 }
 
-// KeyMintDevice implementation
+void KeyMintDevice::setNumFreeSlots(uint8_t numFreeSlots) {
+    mOperationSlots.setNumFreeSlots(numFreeSlots);
+}
+
+// Constructors and helpers.
 
 KeyMintDevice::KeyMintDevice(sp<Keymaster> device, KeyMintSecurityLevel securityLevel)
     : mDevice(device) {
@@ -843,37 +906,88 @@
     }
 }
 
-void KeyMintDevice::setNumFreeSlots(uint8_t numFreeSlots) {
-    mOperationSlots.setNumFreeSlots(numFreeSlots);
+sp<Keymaster> getDevice(KeyMintSecurityLevel securityLevel) {
+    static std::mutex mutex;
+    static sp<Keymaster> teeDevice;
+    static sp<Keymaster> sbDevice;
+    std::lock_guard<std::mutex> lock(mutex);
+    if (!teeDevice) {
+        auto devices = initializeKeymasters();
+        teeDevice = devices[V4_0::SecurityLevel::TRUSTED_ENVIRONMENT];
+        sbDevice = devices[V4_0::SecurityLevel::STRONGBOX];
+    }
+    switch (securityLevel) {
+    case KeyMintSecurityLevel::TRUSTED_ENVIRONMENT:
+        return teeDevice;
+    case KeyMintSecurityLevel::STRONGBOX:
+        return sbDevice;
+    default:
+        return {};
+    }
 }
 
 std::shared_ptr<KeyMintDevice>
 KeyMintDevice::createKeyMintDevice(KeyMintSecurityLevel securityLevel) {
-    static std::mutex mutex;
-    std::lock_guard<std::mutex> lock(mutex);
-    static std::shared_ptr<KeyMintDevice> device_ptr;
-    if (!device_ptr) {
-        auto secLevel = static_cast<SecurityLevel>(securityLevel);
-        auto devices = initializeKeymasters();
-        auto device = devices[secLevel];
-        if (!device) {
-            return {};
-        }
-        device_ptr = ndk::SharedRefBase::make<KeyMintDevice>(std::move(device), securityLevel);
+    if (auto dev = getDevice(securityLevel)) {
+        return ndk::SharedRefBase::make<KeyMintDevice>(std::move(dev), securityLevel);
     }
-    return device_ptr;
+    return {};
+}
+
+std::shared_ptr<SharedSecret> SharedSecret::createSharedSecret(KeyMintSecurityLevel securityLevel) {
+    auto device = getDevice(securityLevel);
+    if (!device) {
+        return {};
+    }
+    return ndk::SharedRefBase::make<SharedSecret>(std::move(device));
+}
+
+std::shared_ptr<SecureClock> SecureClock::createSecureClock(KeyMintSecurityLevel securityLevel) {
+    auto device = getDevice(securityLevel);
+    if (!device) {
+        return {};
+    }
+    return ndk::SharedRefBase::make<SecureClock>(std::move(device));
 }
 
 ScopedAStatus
 KeystoreCompatService::getKeyMintDevice(KeyMintSecurityLevel in_securityLevel,
                                         std::shared_ptr<IKeyMintDevice>* _aidl_return) {
-    if (mDeviceCache.find(in_securityLevel) == mDeviceCache.end()) {
+    auto i = mDeviceCache.find(in_securityLevel);
+    if (i == mDeviceCache.end()) {
         auto device = KeyMintDevice::createKeyMintDevice(in_securityLevel);
         if (!device) {
             return ScopedAStatus::fromStatus(STATUS_NAME_NOT_FOUND);
         }
-        mDeviceCache[in_securityLevel] = std::move(device);
+        bool inserted = false;
+        std::tie(i, inserted) = mDeviceCache.insert({in_securityLevel, std::move(device)});
     }
-    *_aidl_return = mDeviceCache[in_securityLevel];
+    *_aidl_return = i->second;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus KeystoreCompatService::getSharedSecret(KeyMintSecurityLevel in_securityLevel,
+                                                     std::shared_ptr<ISharedSecret>* _aidl_return) {
+    if (!mSharedSecret) {
+        auto secret = SharedSecret::createSharedSecret(in_securityLevel);
+        if (!secret) {
+            return ScopedAStatus::fromStatus(STATUS_NAME_NOT_FOUND);
+        }
+        mSharedSecret = std::move(secret);
+    }
+    *_aidl_return = mSharedSecret;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus KeystoreCompatService::getSecureClock(std::shared_ptr<ISecureClock>* _aidl_return) {
+    if (!mSharedSecret) {
+        // The legacy verification service was always provided by the TEE variant.
+        auto clock = SecureClock::createSecureClock(KeyMintSecurityLevel::TRUSTED_ENVIRONMENT);
+        if (!clock) {
+            return ScopedAStatus::fromStatus(STATUS_NAME_NOT_FOUND);
+        }
+        mSecureClock = std::move(clock);
+    }
+    *_aidl_return = mSecureClock;
     return ScopedAStatus::ok();
 }
diff --git a/keystore2/src/km_compat/km_compat.h b/keystore2/src/km_compat/km_compat.h
index 904d391..481481a 100644
--- a/keystore2/src/km_compat/km_compat.h
+++ b/keystore2/src/km_compat/km_compat.h
@@ -18,6 +18,8 @@
 
 #include <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
 #include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/security/secureclock/BnSecureClock.h>
+#include <aidl/android/hardware/security/sharedsecret/BnSharedSecret.h>
 #include <aidl/android/security/compat/BnKeystoreCompatService.h>
 #include <keymasterV4_1/Keymaster4.h>
 #include <unordered_map>
@@ -30,15 +32,19 @@
 using ::aidl::android::hardware::security::keymint::Certificate;
 using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
 using ::aidl::android::hardware::security::keymint::KeyCharacteristics;
+using ::aidl::android::hardware::security::keymint::KeyCreationResult;
 using ::aidl::android::hardware::security::keymint::KeyFormat;
 using ::aidl::android::hardware::security::keymint::KeyMintHardwareInfo;
 using ::aidl::android::hardware::security::keymint::KeyParameter;
 using ::aidl::android::hardware::security::keymint::KeyParameterArray;
 using ::aidl::android::hardware::security::keymint::KeyPurpose;
-using ::aidl::android::hardware::security::keymint::VerificationToken;
 using KeyMintSecurityLevel = ::aidl::android::hardware::security::keymint::SecurityLevel;
 using V4_0_ErrorCode = ::android::hardware::keymaster::V4_0::ErrorCode;
 using ::aidl::android::hardware::security::keymint::IKeyMintDevice;
+using ::aidl::android::hardware::security::secureclock::ISecureClock;
+using ::aidl::android::hardware::security::secureclock::TimeStampToken;
+using ::aidl::android::hardware::security::sharedsecret::ISharedSecret;
+using ::aidl::android::hardware::security::sharedsecret::SharedSecretParameters;
 using ::aidl::android::security::compat::BnKeystoreCompatService;
 using ::android::hardware::keymaster::V4_1::support::Keymaster;
 using ::ndk::ScopedAStatus;
@@ -80,25 +86,18 @@
     static std::shared_ptr<KeyMintDevice> createKeyMintDevice(KeyMintSecurityLevel securityLevel);
 
     ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* _aidl_return) override;
-    ScopedAStatus verifyAuthorization(int64_t in_challenge, const HardwareAuthToken& in_token,
-                                      VerificationToken* _aidl_return) override;
     ScopedAStatus addRngEntropy(const std::vector<uint8_t>& in_data) override;
     ScopedAStatus generateKey(const std::vector<KeyParameter>& in_keyParams,
-                              ByteArray* out_generatedKeyBlob,
-                              KeyCharacteristics* out_generatedKeyCharacteristics,
-                              std::vector<Certificate>* out_outCertChain) override;
+                              KeyCreationResult* out_creationResult) override;
     ScopedAStatus importKey(const std::vector<KeyParameter>& in_inKeyParams,
                             KeyFormat in_inKeyFormat, const std::vector<uint8_t>& in_inKeyData,
-                            ByteArray* out_outImportedKeyBlob,
-                            KeyCharacteristics* out_outImportedKeyCharacteristics,
-                            std::vector<Certificate>* out_outCertChain) override;
+                            KeyCreationResult* out_creationResult) override;
     ScopedAStatus importWrappedKey(const std::vector<uint8_t>& in_inWrappedKeyData,
                                    const std::vector<uint8_t>& in_inWrappingKeyBlob,
                                    const std::vector<uint8_t>& in_inMaskingKey,
                                    const std::vector<KeyParameter>& in_inUnwrappingParams,
                                    int64_t in_inPasswordSid, int64_t in_inBiometricSid,
-                                   ByteArray* out_outImportedKeyBlob,
-                                   KeyCharacteristics* out_outImportedKeyCharacteristics) override;
+                                   KeyCreationResult* out_creationResult) override;
     ScopedAStatus upgradeKey(const std::vector<uint8_t>& in_inKeyBlobToUpgrade,
                              const std::vector<KeyParameter>& in_inUpgradeParams,
                              std::vector<uint8_t>* _aidl_return) override;
@@ -121,6 +120,7 @@
   private:
     std::optional<V4_0_ErrorCode> signCertificate(const std::vector<KeyParameter>& keyParams,
                                                   const std::vector<uint8_t>& keyBlob, X509* cert);
+    KeyMintSecurityLevel securityLevel_;
 };
 
 class KeyMintOperation : public aidl::android::hardware::security::keymint::BnKeyMintOperation {
@@ -138,25 +138,54 @@
     ScopedAStatus update(const std::optional<KeyParameterArray>& in_inParams,
                          const std::optional<std::vector<uint8_t>>& in_input,
                          const std::optional<HardwareAuthToken>& in_inAuthToken,
-                         const std::optional<VerificationToken>& in_inVerificationToken,
+                         const std::optional<TimeStampToken>& in_inTimestampToken,
                          std::optional<KeyParameterArray>* out_outParams,
                          std::optional<ByteArray>* out_output, int32_t* _aidl_return);
     ScopedAStatus finish(const std::optional<KeyParameterArray>& in_inParams,
                          const std::optional<std::vector<uint8_t>>& in_input,
                          const std::optional<std::vector<uint8_t>>& in_inSignature,
                          const std::optional<HardwareAuthToken>& in_authToken,
-                         const std::optional<VerificationToken>& in_inVerificationToken,
+                         const std::optional<TimeStampToken>& in_inTimestampToken,
                          std::optional<KeyParameterArray>* out_outParams,
                          std::vector<uint8_t>* _aidl_return);
     ScopedAStatus abort();
 };
 
+class SharedSecret : public aidl::android::hardware::security::sharedsecret::BnSharedSecret {
+  private:
+    ::android::sp<Keymaster> mDevice;
+
+  public:
+    SharedSecret(::android::sp<Keymaster> device) : mDevice(device) {}
+    static std::shared_ptr<SharedSecret> createSharedSecret(KeyMintSecurityLevel securityLevel);
+
+    virtual ScopedAStatus getSharedSecretParameters(SharedSecretParameters* _aidl_return) override;
+    virtual ScopedAStatus computeSharedSecret(const std::vector<SharedSecretParameters>& in_params,
+                                              std::vector<uint8_t>* _aidl_return) override;
+};
+
+class SecureClock : public aidl::android::hardware::security::secureclock::BnSecureClock {
+  private:
+    ::android::sp<Keymaster> mDevice;
+
+  public:
+    SecureClock(::android::sp<Keymaster> device) : mDevice(device) {}
+    static std::shared_ptr<SecureClock> createSecureClock(KeyMintSecurityLevel securityLevel);
+
+    ScopedAStatus generateTimeStamp(int64_t in_challenge, TimeStampToken* _aidl_return) override;
+};
+
 class KeystoreCompatService : public BnKeystoreCompatService {
   private:
     std::unordered_map<KeyMintSecurityLevel, std::shared_ptr<IKeyMintDevice>> mDeviceCache;
+    std::shared_ptr<ISharedSecret> mSharedSecret;
+    std::shared_ptr<ISecureClock> mSecureClock;
 
   public:
     KeystoreCompatService() {}
     ScopedAStatus getKeyMintDevice(KeyMintSecurityLevel in_securityLevel,
                                    std::shared_ptr<IKeyMintDevice>* _aidl_return) override;
+    ScopedAStatus getSharedSecret(KeyMintSecurityLevel in_securityLevel,
+                                  std::shared_ptr<ISharedSecret>* _aidl_return) override;
+    ScopedAStatus getSecureClock(std::shared_ptr<ISecureClock>* _aidl_return) override;
 };
diff --git a/keystore2/src/km_compat/lib.rs b/keystore2/src/km_compat/lib.rs
index 36f1303..aed0e7e 100644
--- a/keystore2/src/km_compat/lib.rs
+++ b/keystore2/src/km_compat/lib.rs
@@ -28,20 +28,21 @@
 
     use super::*;
     use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-        Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, ByteArray::ByteArray,
-        Certificate::Certificate, Digest::Digest, ErrorCode::ErrorCode,
-        HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
-        KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
+        Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, Digest::Digest,
+        ErrorCode::ErrorCode, HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
+        KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
         KeyParameterArray::KeyParameterArray, KeyParameterValue::KeyParameterValue,
         KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
     };
     use android_hardware_security_keymint::binder;
     use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
 
+    static COMPAT_NAME: &str = "android.security.compat";
+
     fn get_device() -> Box<dyn IKeyMintDevice> {
         add_keymint_device_service();
         let compat_service: Box<dyn IKeystoreCompatService> =
-            binder::get_interface("android.security.compat").unwrap();
+            binder::get_interface(COMPAT_NAME).unwrap();
         compat_service.getKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap()
     }
 
@@ -56,15 +57,6 @@
     }
 
     #[test]
-    fn test_verify_authorization() {
-        use android_hardware_security_keymint::aidl::android::hardware::security::keymint::HardwareAuthToken::HardwareAuthToken;
-        let legacy = get_device();
-        let result = legacy.verifyAuthorization(0, &HardwareAuthToken::default());
-        assert!(result.is_err());
-        assert_eq!(result.unwrap_err().service_specific_error(), ErrorCode::UNIMPLEMENTED.0,);
-    }
-
-    #[test]
     fn test_add_rng_entropy() {
         let legacy = get_device();
         let result = legacy.addRngEntropy(&[42; 16]);
@@ -72,17 +64,10 @@
     }
 
     // TODO: If I only need the key itself, don't return the other things.
-    fn generate_key(
-        legacy: &dyn IKeyMintDevice,
-        kps: Vec<KeyParameter>,
-    ) -> (ByteArray, KeyCharacteristics, Vec<Certificate>) {
-        let mut blob = ByteArray { data: vec![] };
-        let mut characteristics = KeyCharacteristics::default();
-        let mut cert_chain = vec![];
-        let result = legacy.generateKey(&kps, &mut blob, &mut characteristics, &mut cert_chain);
-        assert!(result.is_ok(), "{:?}", result);
-        assert_ne!(blob.data.len(), 0);
-        (blob, characteristics, cert_chain)
+    fn generate_key(legacy: &dyn IKeyMintDevice, kps: Vec<KeyParameter>) -> KeyCreationResult {
+        let creation_result = legacy.generateKey(&kps).expect("Failed to generate key");
+        assert_ne!(creation_result.keyBlob.len(), 0);
+        creation_result
     }
 
     fn generate_rsa_key(legacy: &dyn IKeyMintDevice, encrypt: bool, attest: bool) -> Vec<u8> {
@@ -123,14 +108,14 @@
                 value: KeyParameterValue::Blob(vec![42; 8]),
             });
         }
-        let (blob, _, cert_chain) = generate_key(legacy, kps);
+        let creation_result = generate_key(legacy, kps);
         if attest {
             // TODO: Will this always be greater than 1?
-            assert!(cert_chain.len() > 1);
+            assert!(creation_result.certificateChain.len() > 1);
         } else {
-            assert_eq!(cert_chain.len(), 1);
+            assert_eq!(creation_result.certificateChain.len(), 1);
         }
-        blob.data
+        creation_result.keyBlob
     }
 
     #[test]
@@ -160,23 +145,15 @@
         }];
         let kf = KeyFormat::RAW;
         let kd = [0; 16];
-        let mut blob = ByteArray { data: vec![] };
-        let mut characteristics = KeyCharacteristics::default();
-        let mut cert_chain = vec![];
-        let result =
-            legacy.importKey(&kps, kf, &kd, &mut blob, &mut characteristics, &mut cert_chain);
-        assert!(result.is_ok(), "{:?}", result);
-        assert_ne!(blob.data.len(), 0);
-        assert_eq!(cert_chain.len(), 0);
+        let creation_result = legacy.importKey(&kps, kf, &kd).expect("Failed to import key");
+        assert_ne!(creation_result.keyBlob.len(), 0);
+        assert_eq!(creation_result.certificateChain.len(), 0);
     }
 
     #[test]
     fn test_import_wrapped_key() {
         let legacy = get_device();
-        let mut blob = ByteArray { data: vec![] };
-        let mut characteristics = KeyCharacteristics::default();
-        let result =
-            legacy.importWrappedKey(&[], &[], &[], &[], 0, 0, &mut blob, &mut characteristics);
+        let result = legacy.importWrappedKey(&[], &[], &[], &[], 0, 0);
         // TODO: This test seems to fail on cuttlefish.  How should I test it?
         assert!(result.is_err());
     }
@@ -238,9 +215,9 @@
                 value: KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
             },
         ];
-        let (blob, _, cert_chain) = generate_key(legacy, kps);
-        assert_eq!(cert_chain.len(), 0);
-        blob.data
+        let creation_result = generate_key(legacy, kps);
+        assert_eq!(creation_result.certificateChain.len(), 0);
+        creation_result.keyBlob
     }
 
     fn begin(
@@ -322,4 +299,36 @@
         assert!(result.is_ok(), "{:?}", result);
         assert!(out_params.is_some());
     }
+
+    #[test]
+    fn test_secure_clock() {
+        add_keymint_device_service();
+        let compat_service: Box<dyn IKeystoreCompatService> =
+            binder::get_interface(COMPAT_NAME).unwrap();
+        let secure_clock = compat_service.getSecureClock().unwrap();
+
+        let challenge = 42;
+        let result = secure_clock.generateTimeStamp(challenge);
+        assert!(result.is_ok(), "{:?}", result);
+        let result = result.unwrap();
+        assert_eq!(result.challenge, challenge);
+        assert_eq!(result.mac.len(), 32);
+    }
+
+    #[test]
+    fn test_shared_secret() {
+        add_keymint_device_service();
+        let compat_service: Box<dyn IKeystoreCompatService> =
+            binder::get_interface(COMPAT_NAME).unwrap();
+        let shared_secret =
+            compat_service.getSharedSecret(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+        let result = shared_secret.getSharedSecretParameters();
+        assert!(result.is_ok(), "{:?}", result);
+        let params = result.unwrap();
+
+        let result = shared_secret.computeSharedSecret(&[params]);
+        assert!(result.is_ok(), "{:?}", result);
+        assert_ne!(result.unwrap().len(), 0);
+    }
 }
diff --git a/keystore2/src/km_compat/slot_test.cpp b/keystore2/src/km_compat/slot_test.cpp
index e56fb37..0859ddf 100644
--- a/keystore2/src/km_compat/slot_test.cpp
+++ b/keystore2/src/km_compat/slot_test.cpp
@@ -46,14 +46,12 @@
         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::ENCRYPT),
         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::DECRYPT),
     });
-    ByteArray blob;
-    KeyCharacteristics characteristics;
-    std::vector<Certificate> cert;
-    auto status = device->generateKey(keyParams, &blob, &characteristics, &cert);
+    KeyCreationResult creationResult;
+    auto status = device->generateKey(keyParams, &creationResult);
     if (!status.isOk()) {
         return {};
     }
-    return blob.data;
+    return creationResult.keyBlob;
 }
 
 static std::variant<BeginResult, ScopedAStatus> begin(std::shared_ptr<KeyMintDevice> device,
@@ -151,16 +149,14 @@
         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
         KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
     });
-    ByteArray blob;
-    KeyCharacteristics characteristics;
-    std::vector<Certificate> cert;
-    status = device->generateKey(kps, &blob, &characteristics, &cert);
+    KeyCreationResult creationResult;
+    status = device->generateKey(kps, &creationResult);
     ASSERT_TRUE(!status.isOk());
     ASSERT_EQ(status.getServiceSpecificError(),
               static_cast<int32_t>(ErrorCode::TOO_MANY_OPERATIONS));
     // But generating a certificate with signCert does not use a slot.
     kps.pop_back();
-    status = device->generateKey(kps, &blob, &characteristics, &cert);
+    status = device->generateKey(kps, &creationResult);
     ASSERT_TRUE(status.isOk());
 
     // Destructing operations should free up their slots.
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
index 29b3992..240998e 100644
--- a/keystore2/src/lib.rs
+++ b/keystore2/src/lib.rs
@@ -17,6 +17,8 @@
 
 pub mod apc;
 pub mod auth_token_handler;
+pub mod authorization;
+pub mod background_task_handler;
 pub mod database;
 pub mod enforcements;
 pub mod error;
diff --git a/keystore2/src/operation.rs b/keystore2/src/operation.rs
index 9a35154..8e4f800 100644
--- a/keystore2/src/operation.rs
+++ b/keystore2/src/operation.rs
@@ -125,6 +125,26 @@
 //! or it transitions to its end-of-life, which means we may get a free slot.
 //! Either way, we have to revaluate the pruning scores.
 
+use crate::auth_token_handler::AuthTokenHandler;
+use crate::error::{map_km_error, map_or_log_err, Error, ErrorCode, ResponseCode};
+use crate::globals::ENFORCEMENTS;
+use crate::key_parameter::KeyParameter;
+use crate::utils::Asp;
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    ByteArray::ByteArray, HardwareAuthToken::HardwareAuthToken,
+    IKeyMintOperation::IKeyMintOperation, KeyParameter::KeyParameter as KmParam,
+    KeyParameterArray::KeyParameterArray, KeyParameterValue::KeyParameterValue as KmParamValue,
+    Tag::Tag,
+};
+use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
+    TimeStampToken::TimeStampToken,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    IKeystoreOperation::BnKeystoreOperation, IKeystoreOperation::IKeystoreOperation,
+    OperationChallenge::OperationChallenge,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface};
 use std::{
     collections::HashMap,
     sync::{Arc, Mutex, MutexGuard, Weak},
@@ -132,19 +152,6 @@
     time::Instant,
 };
 
-use crate::error::{map_km_error, map_or_log_err, Error, ErrorCode, ResponseCode};
-use crate::utils::Asp;
-use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-    ByteArray::ByteArray, IKeyMintOperation::IKeyMintOperation,
-    KeyParameter::KeyParameter as KmParam, KeyParameterArray::KeyParameterArray,
-    KeyParameterValue::KeyParameterValue as KmParamValue, Tag::Tag,
-};
-use android_system_keystore2::aidl::android::system::keystore2::{
-    IKeystoreOperation::BnKeystoreOperation, IKeystoreOperation::IKeystoreOperation,
-};
-use anyhow::{anyhow, Context, Result};
-use binder::{IBinder, Interface};
-
 /// Operations have `Outcome::Unknown` as long as they are active. They transition
 /// to one of the other variants exactly once. The distinction in outcome is mainly
 /// for the statistic.
@@ -168,6 +175,11 @@
     last_usage: Mutex<Instant>,
     outcome: Mutex<Outcome>,
     owner: u32, // Uid of the operation's owner.
+    auth_token_handler: Mutex<AuthTokenHandler>,
+    // optional because in create_operation, there is a case in which we might not load
+    // key parameters
+    key_params: Option<Vec<KeyParameter>>,
+    op_challenge: Option<OperationChallenge>,
 }
 
 struct PruningInfo {
@@ -181,13 +193,23 @@
 
 impl Operation {
     /// Constructor
-    pub fn new(index: usize, km_op: Box<dyn IKeyMintOperation>, owner: u32) -> Self {
+    pub fn new(
+        index: usize,
+        km_op: Box<dyn IKeyMintOperation>,
+        owner: u32,
+        auth_token_handler: AuthTokenHandler,
+        key_params: Option<Vec<KeyParameter>>,
+        op_challenge: Option<OperationChallenge>,
+    ) -> Self {
         Self {
             index,
             km_op: Asp::new(km_op.as_binder()),
             last_usage: Mutex::new(Instant::now()),
             outcome: Mutex::new(Outcome::Unknown),
             owner,
+            auth_token_handler: Mutex::new(auth_token_handler),
+            key_params,
+            op_challenge,
         }
     }
 
@@ -337,7 +359,7 @@
                 None,
                 // TODO Get auth token from enforcement module if required.
                 None,
-                // TODO Get verification token from enforcement module if required.
+                // TODO Get timestamp token from enforcement module if required.
                 None,
                 &mut out_params,
                 &mut output,
@@ -348,6 +370,43 @@
         Ok(())
     }
 
+    /// Based on the authorization information stored in the operation during create_operation(),
+    /// and any previous calls to update(), this function returns appropriate auth token and
+    /// timestamp token to be passed to keymint.
+    /// Note that the call to the global enforcement object happens only during the first call to
+    /// update or if finish() is called right after create_opertation.
+    fn handle_authorization<'a>(
+        auth_token_handler: &'a mut AuthTokenHandler,
+        key_params: Option<&Vec<KeyParameter>>,
+        op_challenge: Option<&OperationChallenge>,
+    ) -> Result<(Option<&'a HardwareAuthToken>, Option<&'a TimeStampToken>)> {
+        // keystore performs authorization only if key parameters have been loaded during
+        // create_operation()
+        if let Some(key_parameters) = key_params {
+            match *auth_token_handler {
+                // this variant is found only in a first call to update or if finish is called
+                // right after create_operation.
+                AuthTokenHandler::OpAuthRequired => {
+                    *auth_token_handler = ENFORCEMENTS
+                        .authorize_update_or_finish(key_parameters.as_slice(), op_challenge)
+                        .context("In handle_authorization.")?;
+                    Ok((auth_token_handler.get_auth_token(), None))
+                }
+                // this variant is found only in a first call to update or if finish is called
+                // right after create_operation.
+                AuthTokenHandler::Channel(_)|
+                // this variant is found in every subsequent call to update/finish,
+                // unless the authorization is not required for the key
+                AuthTokenHandler::Token(_, _) => {
+                    auth_token_handler.retrieve_auth_and_timestamp_tokens()
+                }
+                _ => Ok((None, None))
+            }
+        } else {
+            Ok((None, None))
+        }
+    }
+
     /// Implementation of `IKeystoreOperation::update`.
     /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
     fn update(&self, input: &[u8]) -> Result<Option<Vec<u8>>> {
@@ -361,15 +420,21 @@
         let km_op: Box<dyn IKeyMintOperation> =
             self.km_op.get_interface().context("In update: Failed to get KeyMintOperation.")?;
 
+        let mut auth_handler = self.auth_token_handler.lock().unwrap();
+        let (auth_token_for_km, timestamp_token_for_km) = Self::handle_authorization(
+            &mut auth_handler,
+            self.key_params.as_ref(),
+            self.op_challenge.as_ref(),
+        )
+        .context("In update.")?;
+
         self.update_outcome(
             &mut *outcome,
             map_km_error(km_op.update(
                 None,
                 Some(input),
-                // TODO Get auth token from enforcement module if required.
-                None,
-                // TODO Get verification token from enforcement module if required.
-                None,
+                auth_token_for_km,
+                timestamp_token_for_km,
                 &mut out_params,
                 &mut output,
             )),
@@ -402,6 +467,14 @@
         let km_op: Box<dyn IKeyMintOperation> =
             self.km_op.get_interface().context("In finish: Failed to get KeyMintOperation.")?;
 
+        let mut auth_handler = self.auth_token_handler.lock().unwrap();
+        let (auth_token_for_km, timestamp_token_for_km) = Self::handle_authorization(
+            &mut auth_handler,
+            self.key_params.as_ref(),
+            self.op_challenge.as_ref(),
+        )
+        .context("In finish.")?;
+
         let output = self
             .update_outcome(
                 &mut *outcome,
@@ -409,10 +482,8 @@
                     None,
                     input,
                     signature,
-                    // TODO Get auth token from enforcement module if required.
-                    None,
-                    // TODO Get verification token from enforcement module if required.
-                    None,
+                    auth_token_for_km,
+                    timestamp_token_for_km,
                     &mut out_params,
                 )),
             )
@@ -475,6 +546,9 @@
         &self,
         km_op: Box<dyn IKeyMintOperation>,
         owner: u32,
+        auth_token_handler: AuthTokenHandler,
+        key_params: Option<Vec<KeyParameter>>,
+        op_challenge: Option<OperationChallenge>,
     ) -> Arc<Operation> {
         // We use unwrap because we don't allow code that can panic while locked.
         let mut operations = self.operations.lock().expect("In create_operation.");
@@ -487,12 +561,26 @@
             s.upgrade().is_none()
         }) {
             Some(free_slot) => {
-                let new_op = Arc::new(Operation::new(index - 1, km_op, owner));
+                let new_op = Arc::new(Operation::new(
+                    index - 1,
+                    km_op,
+                    owner,
+                    auth_token_handler,
+                    key_params,
+                    op_challenge,
+                ));
                 *free_slot = Arc::downgrade(&new_op);
                 new_op
             }
             None => {
-                let new_op = Arc::new(Operation::new(operations.len(), km_op, owner));
+                let new_op = Arc::new(Operation::new(
+                    operations.len(),
+                    km_op,
+                    owner,
+                    auth_token_handler,
+                    key_params,
+                    op_challenge,
+                ));
                 operations.push(Arc::downgrade(&new_op));
                 new_op
             }
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index af59f79..943f69f 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -17,9 +17,9 @@
 //! This crate implements the IKeystoreSecurityLevel interface.
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-    Algorithm::Algorithm, ByteArray::ByteArray, Certificate::Certificate as KmCertificate,
+    Algorithm::Algorithm, HardwareAuthToken::HardwareAuthToken,
     HardwareAuthenticatorType::HardwareAuthenticatorType, IKeyMintDevice::IKeyMintDevice,
-    KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
+    KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
     KeyParameterValue::KeyParameterValue, SecurityLevel::SecurityLevel, Tag::Tag,
 };
 use android_system_keystore2::aidl::android::system::keystore2::{
@@ -27,9 +27,13 @@
     Domain::Domain, IKeystoreOperation::IKeystoreOperation,
     IKeystoreSecurityLevel::BnKeystoreSecurityLevel,
     IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
-    KeyMetadata::KeyMetadata, KeyParameters::KeyParameters,
+    KeyMetadata::KeyMetadata, KeyParameters::KeyParameters, OperationChallenge::OperationChallenge,
 };
 
+use crate::auth_token_handler::AuthTokenHandler;
+use crate::globals::ENFORCEMENTS;
+use crate::key_parameter::KeyParameter as KsKeyParam;
+use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
 use crate::utils::{check_key_permission, Asp};
 use crate::{database::KeyIdGuard, globals::DB};
 use crate::{
@@ -44,6 +48,7 @@
 use crate::{
     error::{self, map_km_error, map_or_log_err, Error, ErrorCode},
     utils::key_characteristics_to_internal,
+    utils::uid_to_android_user,
 };
 use anyhow::{Context, Result};
 use binder::{IBinder, Interface, ThreadState};
@@ -79,39 +84,45 @@
     fn store_new_key(
         &self,
         key: KeyDescriptor,
-        key_characteristics: KeyCharacteristics,
-        km_cert_chain: Option<Vec<KmCertificate>>,
-        blob: ByteArray,
+        creation_result: KeyCreationResult,
+        user_id: u32,
     ) -> Result<KeyMetadata> {
-        let (cert, cert_chain): (Option<Vec<u8>>, Option<Vec<u8>>) = match km_cert_chain {
-            Some(mut chain) => (
-                match chain.len() {
-                    0 => None,
-                    _ => Some(chain.remove(0).encodedCertificate),
-                },
-                match chain.len() {
-                    0 => None,
-                    _ => Some(
-                        chain
-                            .iter()
-                            .map(|c| c.encodedCertificate.iter())
-                            .flatten()
-                            .copied()
-                            .collect(),
-                    ),
-                },
-            ),
-            None => (None, None),
-        };
+        let KeyCreationResult {
+            keyBlob: key_blob,
+            keyCharacteristics: key_characteristics,
+            certificateChain: mut certificate_chain,
+        } = creation_result;
 
-        let key_parameters =
-            key_characteristics_to_internal(key_characteristics, self.security_level);
+        let (cert, cert_chain): (Option<Vec<u8>>, Option<Vec<u8>>) = (
+            match certificate_chain.len() {
+                0 => None,
+                _ => Some(certificate_chain.remove(0).encodedCertificate),
+            },
+            match certificate_chain.len() {
+                0 => None,
+                _ => Some(
+                    certificate_chain
+                        .iter()
+                        .map(|c| c.encodedCertificate.iter())
+                        .flatten()
+                        .copied()
+                        .collect(),
+                ),
+            },
+        );
+
+        let mut key_parameters = key_characteristics_to_internal(key_characteristics);
+
+        key_parameters.push(KsKeyParam::new(
+            KsKeyParamValue::UserID(user_id as i32),
+            SecurityLevel::SOFTWARE,
+        ));
 
         let creation_date = DateTime::now().context("Trying to make creation time.")?;
 
         let key = match key.domain {
             Domain::BLOB => {
-                KeyDescriptor { domain: Domain::BLOB, blob: Some(blob.data), ..Default::default() }
+                KeyDescriptor { domain: Domain::BLOB, blob: Some(key_blob), ..Default::default() }
             }
             _ => DB
                 .with::<_, Result<KeyDescriptor>>(|db| {
@@ -123,7 +134,7 @@
                         .store_new_key(
                             key,
                             &key_parameters,
-                            &blob.data,
+                            &key_blob,
                             cert.as_deref(),
                             cert_chain.as_deref(),
                             &metadata,
@@ -159,7 +170,7 @@
         // so that we can use it by reference like the blob provided by the key descriptor.
         // Otherwise, we would have to clone the blob from the key descriptor.
         let scoping_blob: Vec<u8>;
-        let (km_blob, key_id_guard) = match key.domain {
+        let (km_blob, key_id_guard, key_parameters) = match key.domain {
             Domain::BLOB => {
                 check_key_permission(KeyPerm::use_(), key, &None)
                     .context("In create_operation: checking use permission for Domain::BLOB.")?;
@@ -174,6 +185,7 @@
                         }
                     },
                     None,
+                    None,
                 )
             }
             _ => {
@@ -197,14 +209,10 @@
                         ))
                     }
                 };
-                (&scoping_blob, Some(key_id_guard))
+                (&scoping_blob, Some(key_id_guard), Some(key_entry.into_key_parameters()))
             }
         };
 
-        // TODO Authorize begin operation.
-        // Check if we need an authorization token.
-        // Lookup authorization token and request VerificationToken if required.
-
         let purpose = operation_parameters.iter().find(|p| p.tag == Tag::PURPOSE).map_or(
             Err(Error::Km(ErrorCode::INVALID_ARGUMENT))
                 .context("In create_operation: No operation purpose specified."),
@@ -215,6 +223,35 @@
             },
         )?;
 
+        let mut auth_token_for_km: &HardwareAuthToken = &Default::default();
+        let mut auth_token_handler = AuthTokenHandler::NoAuthRequired;
+
+        // keystore performs authorizations only if the key parameters are loaded above
+        if let Some(ref key_params) = key_parameters {
+            // Note: although currently only one operation parameter is checked in authorizing the
+            // operation, the whole operation_parameter vector is converted into the internal
+            // representation of key parameter because we might need to sanitize operation
+            // parameters (b/175792701)
+            let mut op_params: Vec<KsKeyParam> = Vec::new();
+            for op_param in operation_parameters.iter() {
+                op_params.push(KsKeyParam::new(op_param.into(), self.security_level));
+            }
+            // authorize the operation, and receive an AuthTokenHandler, if authorized, else
+            // propagate the error
+            auth_token_handler = ENFORCEMENTS
+                .authorize_create(
+                    purpose,
+                    key_params.as_slice(),
+                    op_params.as_slice(),
+                    self.security_level,
+                )
+                .context("In create_operation.")?;
+            // if an auth token was found, pass it to keymint
+            if let Some(auth_token) = auth_token_handler.get_auth_token() {
+                auth_token_for_km = auth_token;
+            }
+        }
+
         let km_dev: Box<dyn IKeyMintDevice> = self
             .keymint
             .get_interface()
@@ -231,7 +268,7 @@
                         purpose,
                         blob,
                         &operation_parameters,
-                        &Default::default(),
+                        auth_token_for_km,
                     )) {
                         Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
                             self.operation_db.prune(caller_uid)?;
@@ -243,8 +280,36 @@
             )
             .context("In create_operation: Failed to begin operation.")?;
 
+        let mut operation_challenge: Option<OperationChallenge> = None;
+
+        // take actions based on the authorization decision (if any) received via auth token handler
+        match auth_token_handler {
+            AuthTokenHandler::OpAuthRequired => {
+                operation_challenge =
+                    Some(OperationChallenge { challenge: begin_result.challenge });
+                ENFORCEMENTS.insert_to_op_auth_map(begin_result.challenge);
+            }
+            AuthTokenHandler::TimestampRequired(auth_token) => {
+                //request a timestamp token, given the auth token and the challenge
+                auth_token_handler = ENFORCEMENTS
+                    .request_timestamp_token(
+                        auth_token,
+                        OperationChallenge { challenge: begin_result.challenge },
+                    )
+                    .context("In create_operation.")?;
+            }
+            _ => {}
+        }
+
         let operation = match begin_result.operation {
-            Some(km_op) => self.operation_db.create_operation(km_op, caller_uid),
+            Some(km_op) => {
+                let mut op_challenge_copy: Option<OperationChallenge> = None;
+                if let Some(ref op_challenge) = operation_challenge {
+                    op_challenge_copy = Some(OperationChallenge{challenge: op_challenge.challenge});
+                }
+                self.operation_db.create_operation(km_op, caller_uid,
+                 auth_token_handler, key_parameters, op_challenge_copy)
+            },
             None => return Err(Error::sys()).context("In create_operation: Begin operation returned successfully, but did not return a valid operation."),
         };
 
@@ -258,7 +323,7 @@
         // We return None for now because we don't support auth bound keys yet.
         Ok(CreateOperationResponse {
             iOperation: Some(op_binder),
-            operationChallenge: None,
+            operationChallenge: operation_challenge,
             parameters: match begin_result.params.len() {
                 0 => None,
                 _ => Some(KeyParameters { keyParameter: begin_result.params }),
@@ -278,11 +343,12 @@
             return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
                 .context("In generate_key: Alias must be specified");
         }
+        let caller_uid = ThreadState::get_calling_uid();
 
         let key = match key.domain {
             Domain::APP => KeyDescriptor {
                 domain: key.domain,
-                nspace: ThreadState::get_calling_uid() as i64,
+                nspace: caller_uid as i64,
                 alias: key.alias.clone(),
                 blob: None,
             },
@@ -294,18 +360,10 @@
 
         let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
         map_km_error(km_dev.addRngEntropy(entropy))?;
-        let mut blob: ByteArray = Default::default();
-        let mut key_characteristics: KeyCharacteristics = Default::default();
-        let mut certificate_chain: Vec<KmCertificate> = Default::default();
-        map_km_error(km_dev.generateKey(
-            &params,
-            &mut blob,
-            &mut key_characteristics,
-            &mut certificate_chain,
-        ))?;
+        let creation_result = map_km_error(km_dev.generateKey(&params))?;
 
-        self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
-            .context("In generate_key.")
+        let user_id = uid_to_android_user(caller_uid);
+        self.store_new_key(key, creation_result, user_id).context("In generate_key.")
     }
 
     fn import_key(
@@ -320,11 +378,12 @@
             return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
                 .context("In import_key: Alias must be specified");
         }
+        let caller_uid = ThreadState::get_calling_uid();
 
         let key = match key.domain {
             Domain::APP => KeyDescriptor {
                 domain: key.domain,
-                nspace: ThreadState::get_calling_uid() as i64,
+                nspace: caller_uid as i64,
                 alias: key.alias.clone(),
                 blob: None,
             },
@@ -334,10 +393,6 @@
         // import_key requires the rebind permission.
         check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_key.")?;
 
-        let mut blob: ByteArray = Default::default();
-        let mut key_characteristics: KeyCharacteristics = Default::default();
-        let mut certificate_chain: Vec<KmCertificate> = Default::default();
-
         let format = params
             .iter()
             .find(|p| p.tag == Tag::ALGORITHM)
@@ -355,17 +410,10 @@
             .context("In import_key.")?;
 
         let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
-        map_km_error(km_dev.importKey(
-            &params,
-            format,
-            key_data,
-            &mut blob,
-            &mut key_characteristics,
-            &mut certificate_chain,
-        ))?;
+        let creation_result = map_km_error(km_dev.importKey(&params, format, key_data))?;
 
-        self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
-            .context("In import_key.")
+        let user_id = uid_to_android_user(caller_uid);
+        self.store_new_key(key, creation_result, user_id).context("In import_key.")
     }
 
     fn import_wrapped_key(
@@ -396,10 +444,11 @@
             }
         };
 
+        let caller_uid = ThreadState::get_calling_uid();
         let key = match key.domain {
             Domain::APP => KeyDescriptor {
                 domain: key.domain,
-                nspace: ThreadState::get_calling_uid() as i64,
+                nspace: caller_uid as i64,
                 alias: key.alias.clone(),
                 blob: None,
             },
@@ -415,7 +464,7 @@
                     wrapping_key.clone(),
                     KeyType::Client,
                     KeyEntryLoadBits::KM,
-                    ThreadState::get_calling_uid(),
+                    caller_uid,
                     |k, av| check_key_permission(KeyPerm::use_(), k, &av),
                 )
             })
@@ -455,29 +504,26 @@
         let masking_key = masking_key.unwrap_or(ZERO_BLOB_32);
 
         let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
-        let ((blob, key_characteristics), _) = self.upgrade_keyblob_if_required_with(
+        let (creation_result, _) = self.upgrade_keyblob_if_required_with(
             &*km_dev,
             Some(wrapping_key_id_guard),
             wrapping_key_blob,
             &[],
             |wrapping_blob| {
-                let mut blob: ByteArray = Default::default();
-                let mut key_characteristics: KeyCharacteristics = Default::default();
-                map_km_error(km_dev.importWrappedKey(
+                let creation_result = map_km_error(km_dev.importWrappedKey(
                     wrapped_data,
                     wrapping_key_blob,
                     masking_key,
                     &params,
                     pw_sid,
                     fp_sid,
-                    &mut blob,
-                    &mut key_characteristics,
                 ))?;
-                Ok((blob, key_characteristics))
+                Ok(creation_result)
             },
         )?;
 
-        self.store_new_key(key, key_characteristics, None, blob).context("In import_wrapped_key.")
+        let user_id = uid_to_android_user(caller_uid);
+        self.store_new_key(key, creation_result, user_id).context("In import_wrapped_key.")
     }
 
     fn upgrade_keyblob_if_required_with<T, F>(
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 86a86dd..080348c 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -12,10 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// This suppresses the compiler's complaint about converting tv_sec to i64 in method
-// get_current_time_in_seconds.
-#![allow(clippy::useless_conversion)]
-
 //! This module implements utility functions used by the Keystore 2.0 service
 //! implementation.
 
@@ -23,7 +19,7 @@
 use crate::permission;
 use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
-    KeyCharacteristics::KeyCharacteristics, SecurityLevel::SecurityLevel,
+    KeyCharacteristics::KeyCharacteristics, SecurityLevel::SecurityLevel, Tag::Tag,
 };
 use android_security_apc::aidl::android::security::apc::{
     IProtectedConfirmation::{FLAG_UI_OPTION_INVERTED, FLAG_UI_OPTION_MAGNIFIED},
@@ -126,19 +122,21 @@
 
 /// Converts a set of key characteristics as returned from KeyMint into the internal
 /// representation of the keystore service.
-/// The parameter `hw_security_level` indicates which security level shall be used for
-/// parameters found in the hardware enforced parameter list.
 pub fn key_characteristics_to_internal(
-    key_characteristics: KeyCharacteristics,
-    hw_security_level: SecurityLevel,
+    key_characteristics: Vec<KeyCharacteristics>,
 ) -> Vec<crate::key_parameter::KeyParameter> {
     key_characteristics
-        .hardwareEnforced
         .into_iter()
-        .map(|aidl_kp| crate::key_parameter::KeyParameter::new(aidl_kp.into(), hw_security_level))
-        .chain(key_characteristics.softwareEnforced.into_iter().map(|aidl_kp| {
-            crate::key_parameter::KeyParameter::new(aidl_kp.into(), SecurityLevel::SOFTWARE)
-        }))
+        .flat_map(|aidl_key_char| {
+            let sec_level = aidl_key_char.securityLevel;
+            aidl_key_char.authorizations.into_iter().map(move |aidl_kp| {
+                let sec_level = match (aidl_kp.tag, sec_level) {
+                    (Tag::ORIGIN, SecurityLevel::SOFTWARE) => SecurityLevel::TRUSTED_ENVIRONMENT,
+                    _ => sec_level,
+                };
+                crate::key_parameter::KeyParameter::new(aidl_kp.into(), sec_level)
+            })
+        })
         .collect()
 }
 
@@ -159,6 +157,9 @@
     unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_RAW, &mut current_time) };
     // It is safe to unwrap here because try_from() returns std::convert::Infallible, which is
     // defined to be an error that can never happen (i.e. the result is always ok).
+    // This suppresses the compiler's complaint about converting tv_sec to i64 in method
+    // get_current_time_in_seconds.
+    #[allow(clippy::useless_conversion)]
     i64::try_from(current_time.tv_sec).unwrap()
 }