Merge "Keystore 2.0: Fix version binding for user generated attestation keys."
diff --git a/OWNERS b/OWNERS
index fca66f8..7d1fd14 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,5 @@
 swillden@google.com
 cbrubaker@google.com
 jdanis@google.com
-kroot@google.com
\ No newline at end of file
+kroot@google.com
+zeuthen@google.com
\ No newline at end of file
diff --git a/identity/main.cpp b/identity/main.cpp
index 08f2219..9add73c 100644
--- a/identity/main.cpp
+++ b/identity/main.cpp
@@ -53,5 +53,9 @@
     CHECK(ret == ::android::OK) << "Couldn't register binder service";
     LOG(ERROR) << "Registered binder service";
 
+    // Credstore is a single-threaded process. So devote the main thread
+    // to handling binder messages.
+    IPCThreadState::self()->joinThreadPool();
+
     return 0;
 }
diff --git a/keystore2/aidl/Android.bp b/keystore2/aidl/Android.bp
index 69ba0b4..183096c 100644
--- a/keystore2/aidl/Android.bp
+++ b/keystore2/aidl/Android.bp
@@ -28,7 +28,8 @@
     unstable: true,
     backend: {
         java: {
-            sdk_version: "module_current",
+            platform_apis: true,
+            srcs_available: true,
         },
         rust: {
             enabled: true,
@@ -46,7 +47,8 @@
     unstable: true,
     backend: {
         java: {
-            sdk_version: "module_current",
+            platform_apis: true,
+            srcs_available: true,
         },
         rust: {
             enabled: true,
@@ -64,6 +66,7 @@
     backend: {
         java: {
             enabled: true,
+            srcs_available: true,
         },
         rust: {
             enabled: true,
@@ -82,7 +85,8 @@
     unstable: true,
     backend: {
         java: {
-            sdk_version: "module_current",
+            platform_apis: true,
+            srcs_available: true,
         },
         rust: {
             enabled: true,
@@ -102,9 +106,8 @@
     unstable: true,
     backend: {
         java: {
-            enabled: true,
-            sdk_version: "module_current",
             platform_apis: true,
+            srcs_available: true,
         },
         ndk: {
             enabled: true,
@@ -124,7 +127,8 @@
     unstable: true,
     backend: {
         java: {
-            sdk_version: "module_current",
+            platform_apis: true,
+            srcs_available: true,
         },
         rust: {
             enabled: true,
@@ -141,7 +145,8 @@
     unstable: true,
     backend: {
         java: {
-            sdk_version: "module_current",
+            platform_apis: true,
+            srcs_available: true,
         },
         rust: {
             enabled: true,
diff --git a/keystore2/aidl/android/security/apc/IConfirmationCallback.aidl b/keystore2/aidl/android/security/apc/IConfirmationCallback.aidl
index f47d7f5..277b9dd 100644
--- a/keystore2/aidl/android/security/apc/IConfirmationCallback.aidl
+++ b/keystore2/aidl/android/security/apc/IConfirmationCallback.aidl
@@ -21,6 +21,7 @@
 /**
  * This callback interface must be implemented by the client to receive the result of the user
  * confirmation.
+ * @hide
  */
 interface IConfirmationCallback {
     /**
diff --git a/keystore2/aidl/android/security/apc/IProtectedConfirmation.aidl b/keystore2/aidl/android/security/apc/IProtectedConfirmation.aidl
index 26ccf0f..3162224 100644
--- a/keystore2/aidl/android/security/apc/IProtectedConfirmation.aidl
+++ b/keystore2/aidl/android/security/apc/IProtectedConfirmation.aidl
@@ -18,6 +18,7 @@
 
 import android.security.apc.IConfirmationCallback;
 
+/** @hide */
 interface IProtectedConfirmation {
 
     /**
diff --git a/keystore2/aidl/android/security/apc/ResponseCode.aidl b/keystore2/aidl/android/security/apc/ResponseCode.aidl
index 7ae3e1c..9a3619f 100644
--- a/keystore2/aidl/android/security/apc/ResponseCode.aidl
+++ b/keystore2/aidl/android/security/apc/ResponseCode.aidl
@@ -19,6 +19,7 @@
 /**
  * Used as service specific exception code by IProtectedConfirmation and as result
  * code by IConfirmationCallback
+ * @hide
  */
 @Backing(type="int")
 enum ResponseCode {
diff --git a/keystore2/aidl/android/security/attestationmanager/ByteArray.aidl b/keystore2/aidl/android/security/attestationmanager/ByteArray.aidl
index a1592ec..dc37b1b 100644
--- a/keystore2/aidl/android/security/attestationmanager/ByteArray.aidl
+++ b/keystore2/aidl/android/security/attestationmanager/ByteArray.aidl
@@ -18,7 +18,6 @@
 
 /**
  * Simple data holder for a byte array, allowing for multidimensional arrays in AIDL.
- *
  * @hide
  */
 parcelable ByteArray {
diff --git a/keystore2/aidl/android/security/attestationmanager/IAttestationManager.aidl b/keystore2/aidl/android/security/attestationmanager/IAttestationManager.aidl
index 85eee57..e77a21e 100644
--- a/keystore2/aidl/android/security/attestationmanager/IAttestationManager.aidl
+++ b/keystore2/aidl/android/security/attestationmanager/IAttestationManager.aidl
@@ -21,7 +21,6 @@
 
 /**
  * Internal interface for performing device attestation.
- *
  * @hide
  */
 interface IAttestationManager {
diff --git a/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
index 6dc172e..86472eb 100644
--- a/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
+++ b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
@@ -23,6 +23,7 @@
 /**
  * IKeystoreAuthorization interface exposes the methods for other system components to
  * provide keystore with the information required to enforce authorizations on key usage.
+ * @hide
  */
 interface IKeystoreAuthorization {
 
diff --git a/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl b/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl
index 877a916..c7553a2 100644
--- a/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl
+++ b/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl
@@ -14,6 +14,7 @@
 
 package android.security.authorization;
 
+/** @hide */
 @Backing(type="int")
 enum LockScreenEvent {
     UNLOCK = 0,
diff --git a/keystore2/aidl/android/security/authorization/ResponseCode.aidl b/keystore2/aidl/android/security/authorization/ResponseCode.aidl
index 94f1120..169dc7b 100644
--- a/keystore2/aidl/android/security/authorization/ResponseCode.aidl
+++ b/keystore2/aidl/android/security/authorization/ResponseCode.aidl
@@ -16,6 +16,7 @@
 
 /**
  * Used as exception codes by IKeystoreAuthorization.
+ * @hide
  */
 @Backing(type="int")
 enum ResponseCode {
diff --git a/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl b/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl
index 4b6a93b..50bfa19 100644
--- a/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl
+++ b/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl
@@ -25,6 +25,7 @@
  * 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.
+ * @hide
  */
 interface IKeystoreCompatService {
     /**
diff --git a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
index 3115e92..50e674d 100644
--- a/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
+++ b/keystore2/aidl/android/security/maintenance/IKeystoreMaintenance.aidl
@@ -35,7 +35,6 @@
      * user id.
      *
      * @param userId - Android user id
-     * @hide
      */
     void onUserAdded(in int userId);
 
@@ -47,7 +46,6 @@
      * `ResponseCode::SYSTEM_ERROR` - if failed to delete the keys of the user being deleted.
      *
      * @param userId - Android user id
-     * @hide
      */
     void onUserRemoved(in int userId);
 
@@ -62,7 +60,6 @@
      *
      * @param userId - Android user id
      * @param password - a secret derived from the synthetic password of the user
-     * @hide
      */
     void onUserPasswordChanged(in int userId, in @nullable byte[] password);
 
@@ -73,7 +70,6 @@
      * @param domain - One of Domain.APP or Domain.SELINUX.
      * @param nspace - The UID of the app that is to be cleared if domain is Domain.APP or
      *                 the SEPolicy namespace if domain is Domain.SELINUX.
-     * @hide
      */
      void clearNamespace(Domain domain, long nspace);
 
@@ -86,7 +82,6 @@
      * `ResponseCode::SYSTEM_ERROR` - if an error occurred when querying the user state.
      *
      * @param userId - Android user id
-     * @hide
      */
     UserState getState(in int userId);
 }
diff --git a/keystore2/aidl/android/security/maintenance/UserState.aidl b/keystore2/aidl/android/security/maintenance/UserState.aidl
index b6fe278..376f4fb 100644
--- a/keystore2/aidl/android/security/maintenance/UserState.aidl
+++ b/keystore2/aidl/android/security/maintenance/UserState.aidl
@@ -14,6 +14,7 @@
 
 package android.security.maintenance;
 
+/** @hide */
 @Backing(type="int")
 enum UserState {
     UNINITIALIZED = 0,
diff --git a/keystore2/aidl/android/security/vpnprofilestore/IVpnProfileStore.aidl b/keystore2/aidl/android/security/vpnprofilestore/IVpnProfileStore.aidl
index 054a4d7..8375b7b 100644
--- a/keystore2/aidl/android/security/vpnprofilestore/IVpnProfileStore.aidl
+++ b/keystore2/aidl/android/security/vpnprofilestore/IVpnProfileStore.aidl
@@ -18,7 +18,6 @@
 
 /**
  * Internal interface for accessing and storing VPN profiles.
- *
  * @hide
  */
 interface IVpnProfileStore {
diff --git a/keystore2/src/authorization.rs b/keystore2/src/authorization.rs
index 5abb426..553746a 100644
--- a/keystore2/src/authorization.rs
+++ b/keystore2/src/authorization.rs
@@ -33,6 +33,7 @@
     ResponseCode::ResponseCode as KsResponseCode };
 use anyhow::{Context, Result};
 use binder::IBinderInternal;
+use keystore2_crypto::Password;
 use keystore2_selinux as selinux;
 
 /// This is the Authorization error type, it wraps binder exceptions and the
@@ -128,10 +129,10 @@
         &self,
         lock_screen_event: LockScreenEvent,
         user_id: i32,
-        password: Option<&[u8]>,
+        password: Option<Password>,
     ) -> Result<()> {
         match (lock_screen_event, password) {
-            (LockScreenEvent::UNLOCK, Some(user_password)) => {
+            (LockScreenEvent::UNLOCK, Some(password)) => {
                 //This corresponds to the unlock() method in legacy keystore API.
                 //check permission
                 check_keystore_permission(KeystorePerm::unlock())
@@ -145,7 +146,7 @@
                             &LEGACY_MIGRATOR,
                             &SUPER_KEY,
                             user_id as u32,
-                            user_password,
+                            &password,
                         )
                     })
                     .context("In on_lock_screen_event: Unlock with password.")?
@@ -213,7 +214,10 @@
         user_id: i32,
         password: Option<&[u8]>,
     ) -> BinderResult<()> {
-        map_or_log_err(self.on_lock_screen_event(lock_screen_event, user_id, password), Ok)
+        map_or_log_err(
+            self.on_lock_screen_event(lock_screen_event, user_id, password.map(|pw| pw.into())),
+            Ok,
+        )
     }
 
     fn getAuthTokensForCredStore(
diff --git a/keystore2/src/crypto/lib.rs b/keystore2/src/crypto/lib.rs
index bd5906c..98e6eef 100644
--- a/keystore2/src/crypto/lib.rs
+++ b/keystore2/src/crypto/lib.rs
@@ -149,42 +149,68 @@
     }
 }
 
-/// Generates a key from the given password and salt.
-/// The salt must be exactly 16 bytes long.
-/// Two key sizes are accepted: 16 and 32 bytes.
-pub fn derive_key_from_password(
-    pw: &[u8],
-    salt: Option<&[u8]>,
-    key_length: usize,
-) -> Result<ZVec, Error> {
-    let salt: *const u8 = match salt {
-        Some(s) => {
-            if s.len() != SALT_LENGTH {
-                return Err(Error::InvalidSaltLength);
-            }
-            s.as_ptr()
-        }
-        None => std::ptr::null(),
-    };
+/// Represents a "password" that can be used to key the PBKDF2 algorithm.
+pub enum Password<'a> {
+    /// Borrow an existing byte array
+    Ref(&'a [u8]),
+    /// Use an owned ZVec to store the key
+    Owned(ZVec),
+}
 
-    match key_length {
-        AES_128_KEY_LENGTH | AES_256_KEY_LENGTH => {}
-        _ => return Err(Error::InvalidKeyLength),
+impl<'a> From<&'a [u8]> for Password<'a> {
+    fn from(pw: &'a [u8]) -> Self {
+        Self::Ref(pw)
+    }
+}
+
+impl<'a> Password<'a> {
+    fn get_key(&'a self) -> &'a [u8] {
+        match self {
+            Self::Ref(b) => b,
+            Self::Owned(z) => &*z,
+        }
     }
 
-    let mut result = ZVec::new(key_length)?;
+    /// Generate a key from the given password and salt.
+    /// The salt must be exactly 16 bytes long.
+    /// Two key sizes are accepted: 16 and 32 bytes.
+    pub fn derive_key(&self, salt: Option<&[u8]>, key_length: usize) -> Result<ZVec, Error> {
+        let pw = self.get_key();
 
-    unsafe {
-        generateKeyFromPassword(
-            result.as_mut_ptr(),
-            result.len(),
-            pw.as_ptr() as *const std::os::raw::c_char,
-            pw.len(),
-            salt,
-        )
-    };
+        let salt: *const u8 = match salt {
+            Some(s) => {
+                if s.len() != SALT_LENGTH {
+                    return Err(Error::InvalidSaltLength);
+                }
+                s.as_ptr()
+            }
+            None => std::ptr::null(),
+        };
 
-    Ok(result)
+        match key_length {
+            AES_128_KEY_LENGTH | AES_256_KEY_LENGTH => {}
+            _ => return Err(Error::InvalidKeyLength),
+        }
+
+        let mut result = ZVec::new(key_length)?;
+
+        unsafe {
+            generateKeyFromPassword(
+                result.as_mut_ptr(),
+                result.len(),
+                pw.as_ptr() as *const std::os::raw::c_char,
+                pw.len(),
+                salt,
+            )
+        };
+
+        Ok(result)
+    }
+
+    /// Try to make another Password object with the same data.
+    pub fn try_clone(&self) -> Result<Password<'static>, Error> {
+        Ok(Password::Owned(ZVec::try_from(self.get_key())?))
+    }
 }
 
 /// Calls the boringssl HKDF_extract function.
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index 22ab02e..0e8b3d7 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -1357,15 +1357,11 @@
     }
 
     fn is_locked_error(e: &anyhow::Error) -> bool {
-        matches!(e.root_cause().downcast_ref::<rusqlite::ffi::Error>(),
-        Some(rusqlite::ffi::Error {
-            code: rusqlite::ErrorCode::DatabaseBusy,
-            ..
-        })
-        | Some(rusqlite::ffi::Error {
-            code: rusqlite::ErrorCode::DatabaseLocked,
-            ..
-        }))
+        matches!(
+            e.root_cause().downcast_ref::<rusqlite::ffi::Error>(),
+            Some(rusqlite::ffi::Error { code: rusqlite::ErrorCode::DatabaseBusy, .. })
+                | Some(rusqlite::ffi::Error { code: rusqlite::ErrorCode::DatabaseLocked, .. })
+        )
     }
 
     /// Creates a new key entry and allocates a new randomized id for the new key.
@@ -4889,7 +4885,7 @@
     #[test]
     fn test_store_super_key() -> Result<()> {
         let mut db = new_test_db()?;
-        let pw = "xyzabc".as_bytes();
+        let pw: keystore2_crypto::Password = (&b"xyzabc"[..]).into();
         let super_key = keystore2_crypto::generate_aes256_key()?;
         let secret = String::from("keystore2 is great.");
         let secret_bytes = secret.into_bytes();
diff --git a/keystore2/src/legacy_blob.rs b/keystore2/src/legacy_blob.rs
index 3fc77b7..5f40ece 100644
--- a/keystore2/src/legacy_blob.rs
+++ b/keystore2/src/legacy_blob.rs
@@ -26,7 +26,7 @@
     SecurityLevel::SecurityLevel, Tag::Tag, TagType::TagType,
 };
 use anyhow::{Context, Result};
-use keystore2_crypto::{aes_gcm_decrypt, derive_key_from_password, ZVec};
+use keystore2_crypto::{aes_gcm_decrypt, Password, ZVec};
 use std::collections::{HashMap, HashSet};
 use std::{convert::TryInto, fs::File, path::Path, path::PathBuf};
 use std::{
@@ -1036,7 +1036,7 @@
     }
 
     /// Load and decrypt legacy super key blob.
-    pub fn load_super_key(&self, user_id: u32, pw: &[u8]) -> Result<Option<ZVec>> {
+    pub fn load_super_key(&self, user_id: u32, pw: &Password) -> Result<Option<ZVec>> {
         let path = self.make_super_key_filename(user_id);
         let blob = Self::read_generic_blob(&path)
             .context("In load_super_key: While loading super key.")?;
@@ -1046,7 +1046,8 @@
                 Blob {
                     value: BlobValue::PwEncrypted { iv, tag, data, salt, key_size }, ..
                 } => {
-                    let key = derive_key_from_password(pw, Some(&salt), key_size)
+                    let key = pw
+                        .derive_key(Some(&salt), key_size)
                         .context("In load_super_key: Failed to derive key from password.")?;
                     let blob = aes_gcm_decrypt(&data, &iv, &tag, &key).context(
                         "In load_super_key: while trying to decrypt legacy super key blob.",
@@ -1294,7 +1295,7 @@
             Some(&error::Error::Rc(ResponseCode::LOCKED))
         );
 
-        key_manager.unlock_user_key(&mut db, 0, PASSWORD, &legacy_blob_loader)?;
+        key_manager.unlock_user_key(&mut db, 0, &(PASSWORD.into()), &legacy_blob_loader)?;
 
         if let (Some((Blob { flags, value: _ }, _params)), Some(cert), Some(chain)) =
             legacy_blob_loader.load_by_uid_alias(10223, "authbound", Some(&key_manager))?
diff --git a/keystore2/src/legacy_migrator.rs b/keystore2/src/legacy_migrator.rs
index 1ae8719..7567070 100644
--- a/keystore2/src/legacy_migrator.rs
+++ b/keystore2/src/legacy_migrator.rs
@@ -29,9 +29,8 @@
 };
 use anyhow::{Context, Result};
 use core::ops::Deref;
-use keystore2_crypto::ZVec;
+use keystore2_crypto::{Password, ZVec};
 use std::collections::{HashMap, HashSet};
-use std::convert::TryInto;
 use std::sync::atomic::{AtomicU8, Ordering};
 use std::sync::mpsc::channel;
 use std::sync::{Arc, Mutex};
@@ -334,7 +333,7 @@
     pub fn with_try_migrate_super_key<F, T>(
         &self,
         user_id: u32,
-        pw: &[u8],
+        pw: &Password,
         mut key_accessor: F,
     ) -> Result<Option<T>>
     where
@@ -345,12 +344,9 @@
             Ok(None) => {}
             Err(e) => return Err(e),
         }
-
-        let pw: ZVec = pw
-            .try_into()
-            .context("In with_try_migrate_super_key: copying the password into a zvec.")?;
+        let pw = pw.try_clone().context("In with_try_migrate_super_key: Cloning password.")?;
         let result = self.do_serialized(move |migrator_state| {
-            migrator_state.check_and_migrate_super_key(user_id, pw)
+            migrator_state.check_and_migrate_super_key(user_id, &pw)
         });
 
         if let Some(result) = result {
@@ -550,7 +546,7 @@
         }
     }
 
-    fn check_and_migrate_super_key(&mut self, user_id: u32, pw: ZVec) -> Result<()> {
+    fn check_and_migrate_super_key(&mut self, user_id: u32, pw: &Password) -> Result<()> {
         if self.recently_migrated_super_key.contains(&user_id) {
             return Ok(());
         }
@@ -561,7 +557,7 @@
             .context("In check_and_migrate_super_key: Trying to load legacy super key.")?
         {
             let (blob, blob_metadata) =
-                crate::super_key::SuperKeyManager::encrypt_with_password(&super_key, &pw)
+                crate::super_key::SuperKeyManager::encrypt_with_password(&super_key, pw)
                     .context("In check_and_migrate_super_key: Trying to encrypt super key.")?;
 
             self.db.store_super_key(user_id, &(&blob, &blob_metadata)).context(concat!(
diff --git a/keystore2/src/operation.rs b/keystore2/src/operation.rs
index 5cc38cc..0f5bcaf 100644
--- a/keystore2/src/operation.rs
+++ b/keystore2/src/operation.rs
@@ -167,12 +167,14 @@
     outcome: Mutex<Outcome>,
     owner: u32, // Uid of the operation's owner.
     auth_info: Mutex<AuthInfo>,
+    forced: bool,
 }
 
 struct PruningInfo {
     last_usage: Instant,
     owner: u32,
     index: usize,
+    forced: bool,
 }
 
 // We don't except more than 32KiB of data in `update`, `updateAad`, and `finish`.
@@ -185,6 +187,7 @@
         km_op: binder::Strong<dyn IKeyMintOperation>,
         owner: u32,
         auth_info: AuthInfo,
+        forced: bool,
     ) -> Self {
         Self {
             index,
@@ -193,6 +196,7 @@
             outcome: Mutex::new(Outcome::Unknown),
             owner,
             auth_info: Mutex::new(auth_info),
+            forced,
         }
     }
 
@@ -218,6 +222,7 @@
             last_usage: *self.last_usage.lock().expect("In get_pruning_info."),
             owner: self.owner,
             index: self.index,
+            forced: self.forced,
         })
     }
 
@@ -465,6 +470,7 @@
         km_op: binder::public_api::Strong<dyn IKeyMintOperation>,
         owner: u32,
         auth_info: AuthInfo,
+        forced: bool,
     ) -> 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.");
@@ -477,12 +483,13 @@
             s.upgrade().is_none()
         }) {
             Some(free_slot) => {
-                let new_op = Arc::new(Operation::new(index - 1, km_op, owner, auth_info));
+                let new_op = Arc::new(Operation::new(index - 1, km_op, owner, auth_info, forced));
                 *free_slot = Arc::downgrade(&new_op);
                 new_op
             }
             None => {
-                let new_op = Arc::new(Operation::new(operations.len(), km_op, owner, auth_info));
+                let new_op =
+                    Arc::new(Operation::new(operations.len(), km_op, owner, auth_info, forced));
                 operations.push(Arc::downgrade(&new_op));
                 new_op
             }
@@ -565,7 +572,7 @@
     /// ## Update
     /// We also allow callers to cannibalize their own sibling operations if no other
     /// slot can be found. In this case the least recently used sibling is pruned.
-    pub fn prune(&self, caller: u32) -> Result<(), Error> {
+    pub fn prune(&self, caller: u32, forced: bool) -> Result<(), Error> {
         loop {
             // Maps the uid of the owner to the number of operations that owner has
             // (running_siblings). More operations per owner lowers the pruning
@@ -590,7 +597,8 @@
                     }
                 });
 
-            let caller_malus = 1u64 + *owners.entry(caller).or_default();
+            // If the operation is forced, the caller has a malus of 0.
+            let caller_malus = if forced { 0 } else { 1u64 + *owners.entry(caller).or_default() };
 
             // We iterate through all operations computing the malus and finding
             // the candidate with the highest malus which must also be higher
@@ -604,7 +612,7 @@
             let mut oldest_caller_op: Option<CandidateInfo> = None;
             let candidate = pruning_info.iter().fold(
                 None,
-                |acc: Option<CandidateInfo>, &PruningInfo { last_usage, owner, index }| {
+                |acc: Option<CandidateInfo>, &PruningInfo { last_usage, owner, index, forced }| {
                     // Compute the age of the current operation.
                     let age = now
                         .checked_duration_since(last_usage)
@@ -624,12 +632,17 @@
                     }
 
                     // Compute the malus of the current operation.
-                    // Expect safety: Every owner in pruning_info was counted in
-                    // the owners map. So this unwrap cannot panic.
-                    let malus = *owners
-                        .get(&owner)
-                        .expect("This is odd. We should have counted every owner in pruning_info.")
-                        + ((age.as_secs() + 1) as f64).log(6.0).floor() as u64;
+                    let malus = if forced {
+                        // Forced operations have a malus of 0. And cannot even be pruned
+                        // by other forced operations.
+                        0
+                    } else {
+                        // Expect safety: Every owner in pruning_info was counted in
+                        // the owners map. So this unwrap cannot panic.
+                        *owners.get(&owner).expect(
+                            "This is odd. We should have counted every owner in pruning_info.",
+                        ) + ((age.as_secs() + 1) as f64).log(6.0).floor() as u64
+                    };
 
                     // Now check if the current operation is a viable/better candidate
                     // the one currently stored in the accumulator.
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 2af3544..5a776fb 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -209,6 +209,11 @@
             Domain::BLOB => {
                 check_key_permission(KeyPerm::use_(), key, &None)
                     .context("In create_operation: checking use permission for Domain::BLOB.")?;
+                if forced {
+                    check_key_permission(KeyPerm::req_forced_op(), key, &None).context(
+                        "In create_operation: checking forced permission for Domain::BLOB.",
+                    )?;
+                }
                 (
                     match &key.blob {
                         Some(blob) => blob,
@@ -233,7 +238,13 @@
                                 KeyType::Client,
                                 KeyEntryLoadBits::KM,
                                 caller_uid,
-                                |k, av| check_key_permission(KeyPerm::use_(), k, &av),
+                                |k, av| {
+                                    check_key_permission(KeyPerm::use_(), k, &av)?;
+                                    if forced {
+                                        check_key_permission(KeyPerm::req_forced_op(), k, &av)?;
+                                    }
+                                    Ok(())
+                                },
                             )
                         })
                     })
@@ -270,17 +281,12 @@
                 purpose,
                 key_properties.as_ref(),
                 operation_parameters.as_ref(),
-                // TODO b/178222844 Replace this with the configuration returned by
-                //      KeyMintDevice::getHardwareInfo.
-                //      For now we assume that strongbox implementations need secure timestamps.
-                self.security_level == SecurityLevel::STRONGBOX,
+                self.hw_info.timestampTokenRequired,
             )
             .context("In create_operation.")?;
 
         let immediate_hat = immediate_hat.unwrap_or_default();
 
-        let user_id = uid_to_android_user(caller_uid);
-
         let km_blob = SUPER_KEY
             .unwrap_key_if_required(&blob_metadata, km_blob)
             .context("In create_operation. Failed to handle super encryption.")?;
@@ -304,7 +310,7 @@
                         &immediate_hat,
                     )) {
                         Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
-                            self.operation_db.prune(caller_uid)?;
+                            self.operation_db.prune(caller_uid, forced)?;
                             continue;
                         }
                         v => return v,
@@ -317,7 +323,7 @@
 
         let operation = match begin_result.operation {
             Some(km_op) => {
-                self.operation_db.create_operation(km_op, caller_uid, auth_info)
+                self.operation_db.create_operation(km_op, caller_uid, auth_info, forced)
             },
             None => return Err(Error::sys()).context("In create_operation: Begin operation returned successfully, but did not return a valid operation."),
         };
@@ -335,6 +341,10 @@
                 0 => None,
                 _ => Some(KeyParameters { keyParameter: begin_result.params }),
             },
+            // An upgraded blob should only be returned if the caller has permission
+            // to use Domain::BLOB keys. If we got to this point, we already checked
+            // that the caller had that permission.
+            upgradedBlob: if key.domain == Domain::BLOB { upgraded_blob } else { None },
         })
     }
 
diff --git a/keystore2/src/super_key.rs b/keystore2/src/super_key.rs
index 5ee685a..aa434d6 100644
--- a/keystore2/src/super_key.rs
+++ b/keystore2/src/super_key.rs
@@ -23,8 +23,8 @@
 use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
 use anyhow::{Context, Result};
 use keystore2_crypto::{
-    aes_gcm_decrypt, aes_gcm_encrypt, derive_key_from_password, generate_aes256_key, generate_salt,
-    ZVec, AES_256_KEY_LENGTH,
+    aes_gcm_decrypt, aes_gcm_encrypt, generate_aes256_key, generate_salt, Password, ZVec,
+    AES_256_KEY_LENGTH,
 };
 use std::ops::Deref;
 use std::{
@@ -130,7 +130,7 @@
         &self,
         db: &mut KeystoreDB,
         user: UserId,
-        pw: &[u8],
+        pw: &Password,
         legacy_blob_loader: &LegacyBlobLoader,
     ) -> Result<()> {
         let (_, entry) = db
@@ -233,7 +233,7 @@
         db: &mut KeystoreDB,
         legacy_migrator: &LegacyMigrator,
         user_id: u32,
-        pw: &[u8],
+        pw: &Password,
     ) -> Result<UserState> {
         let result = legacy_migrator
             .with_try_migrate_super_key(user_id, pw, || db.load_super_key(user_id))
@@ -261,7 +261,7 @@
         db: &mut KeystoreDB,
         legacy_migrator: &LegacyMigrator,
         user_id: u32,
-        pw: Option<&[u8]>,
+        pw: Option<&Password>,
     ) -> Result<UserState> {
         let super_key_exists_in_db =
             Self::super_key_exists_in_db_for_user(db, legacy_migrator, user_id).context(
@@ -296,7 +296,7 @@
         &self,
         user_id: u32,
         entry: KeyEntry,
-        pw: &[u8],
+        pw: &Password,
     ) -> Result<SuperKey> {
         let super_key = Self::extract_super_key_from_key_entry(entry, pw).context(
             "In populate_cache_from_super_key_blob. Failed to extract super key from key entry",
@@ -306,7 +306,7 @@
     }
 
     /// Extracts super key from the entry loaded from the database
-    pub fn extract_super_key_from_key_entry(entry: KeyEntry, pw: &[u8]) -> Result<SuperKey> {
+    pub fn extract_super_key_from_key_entry(entry: KeyEntry, pw: &Password) -> Result<SuperKey> {
         if let Some((blob, metadata)) = entry.key_blob_info() {
             let key = match (
                 metadata.encrypted_by(),
@@ -315,9 +315,9 @@
                 metadata.aead_tag(),
             ) {
                 (Some(&EncryptedBy::Password), Some(salt), Some(iv), Some(tag)) => {
-                    let key = derive_key_from_password(pw, Some(salt), AES_256_KEY_LENGTH).context(
-                    "In extract_super_key_from_key_entry: Failed to generate key from password.",
-                )?;
+                    let key = pw.derive_key(Some(salt), AES_256_KEY_LENGTH).context(
+                        "In extract_super_key_from_key_entry: Failed to generate key from password.",
+                    )?;
 
                     aes_gcm_decrypt(blob, iv, tag, &key).context(
                         "In extract_super_key_from_key_entry: Failed to decrypt key blob.",
@@ -344,9 +344,13 @@
     }
 
     /// Encrypts the super key from a key derived from the password, before storing in the database.
-    pub fn encrypt_with_password(super_key: &[u8], pw: &[u8]) -> Result<(Vec<u8>, BlobMetaData)> {
+    pub fn encrypt_with_password(
+        super_key: &[u8],
+        pw: &Password,
+    ) -> Result<(Vec<u8>, BlobMetaData)> {
         let salt = generate_salt().context("In encrypt_with_password: Failed to generate salt.")?;
-        let derived_key = derive_key_from_password(pw, Some(&salt), AES_256_KEY_LENGTH)
+        let derived_key = pw
+            .derive_key(Some(&salt), AES_256_KEY_LENGTH)
             .context("In encrypt_with_password: Failed to derive password.")?;
         let mut metadata = BlobMetaData::new();
         metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::Password));
@@ -514,7 +518,7 @@
         legacy_migrator: &LegacyMigrator,
         skm: &SuperKeyManager,
         user_id: u32,
-        password: Option<&[u8]>,
+        password: Option<&Password>,
     ) -> Result<UserState> {
         match skm.get_per_boot_key_by_user_id(user_id) {
             Some(super_key) => {
@@ -548,7 +552,7 @@
         legacy_migrator: &LegacyMigrator,
         skm: &SuperKeyManager,
         user_id: u32,
-        password: &[u8],
+        password: &Password,
     ) -> Result<UserState> {
         match skm.get_per_boot_key_by_user_id(user_id) {
             Some(super_key) => {
diff --git a/keystore2/src/user_manager.rs b/keystore2/src/user_manager.rs
index 123f3a1..0cc2e92 100644
--- a/keystore2/src/user_manager.rs
+++ b/keystore2/src/user_manager.rs
@@ -29,6 +29,7 @@
 use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
 use anyhow::{Context, Result};
 use binder::{IBinderInternal, Strong};
+use keystore2_crypto::Password;
 
 /// This struct is defined to implement the aforementioned AIDL interface.
 /// As of now, it is an empty struct.
@@ -42,7 +43,7 @@
         Ok(result)
     }
 
-    fn on_user_password_changed(user_id: i32, password: Option<&[u8]>) -> Result<()> {
+    fn on_user_password_changed(user_id: i32, password: Option<Password>) -> Result<()> {
         //Check permission. Function should return if this failed. Therefore having '?' at the end
         //is very important.
         check_keystore_permission(KeystorePerm::change_password())
@@ -55,7 +56,7 @@
                     &LEGACY_MIGRATOR,
                     &SUPER_KEY,
                     user_id as u32,
-                    password,
+                    password.as_ref(),
                 )
             })
             .context("In on_user_password_changed.")?
@@ -121,7 +122,7 @@
 
 impl IKeystoreMaintenance for Maintenance {
     fn onUserPasswordChanged(&self, user_id: i32, password: Option<&[u8]>) -> BinderResult<()> {
-        map_or_log_err(Self::on_user_password_changed(user_id, password), Ok)
+        map_or_log_err(Self::on_user_password_changed(user_id, password.map(|pw| pw.into())), Ok)
     }
 
     fn onUserAdded(&self, user_id: i32) -> BinderResult<()> {
diff --git a/ondevice-signing/odsign_main.cpp b/ondevice-signing/odsign_main.cpp
index 58e49ec..33d04ca 100644
--- a/ondevice-signing/odsign_main.cpp
+++ b/ondevice-signing/odsign_main.cpp
@@ -56,7 +56,7 @@
 static const char* kFsVerityProcPath = "/proc/sys/fs/verity";
 
 static const bool kForceCompilation = false;
-static const bool kUseKeystore = false;
+static const bool kUseKeystore = true;
 
 static const char* kOdsignVerificationDoneProp = "odsign.verification.done";
 static const char* kOdsignKeyDoneProp = "odsign.key.done";