Merge "Update fmtlib to 10.1.1" into main
diff --git a/keystore-engine/Android.bp b/keystore-engine/Android.bp
index 52a2aef..3087675 100644
--- a/keystore-engine/Android.bp
+++ b/keystore-engine/Android.bp
@@ -21,7 +21,7 @@
     default_applicable_licenses: ["system_security_license"],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "libkeystore-engine",
 
     srcs: [
diff --git a/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
index b31a51e..54894ff 100644
--- a/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
+++ b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
@@ -16,7 +16,6 @@
 
 import android.hardware.security.keymint.HardwareAuthToken;
 import android.hardware.security.keymint.HardwareAuthenticatorType;
-import android.security.authorization.LockScreenEvent;
 import android.security.authorization.AuthorizationTokens;
 
 // TODO: mark the interface with @SensitiveData when the annotation is ready (b/176110256).
@@ -41,41 +40,51 @@
     void addAuthToken(in HardwareAuthToken authToken);
 
     /**
-     * Unlocks the keystore for the given user id.
+     * Tells Keystore that the device is now unlocked for a user.  Requires the 'Unlock' permission.
      *
-     * Callers require 'Unlock' permission.
+     * This method makes Keystore start allowing the use of the given user's keys that require an
+     * unlocked device, following the device boot or an earlier call to onDeviceLocked() which
+     * disabled the use of such keys.  In addition, once per boot, this method must be called with a
+     * password before keys that require user authentication can be used.
      *
-     * Super-Encryption Key:
-     * When the device is unlocked (and password is non-null), Keystore stores in memory
-     * a super-encryption key derived from the password that protects UNLOCKED_DEVICE_REQUIRED
-     * keys; this key is wiped from memory when the device is locked.
-     *
-     * If unlockingSids is non-empty on lock, then before the super-encryption key is wiped from
-     * memory, a copy of it is stored in memory encrypted with a fresh AES key. This key is then
-     * imported into KM, tagged such that it can be used given a valid, recent auth token for any
-     * of the unlockingSids.
-     *
-     * Options for unlock:
-     *  - If the password is non-null, the super-encryption key is re-derived as above.
-     *  - If the password is null, then if a suitable auth token to access the encrypted
-     *    Super-encryption key stored in KM has been sent to keystore (via addAuthToken), the
-     *    encrypted super-encryption key is recovered so that UNLOCKED_DEVICE_REQUIRED keys can
-     *    be used once again.
-     *  - If neither of these are met, then the operation fails.
+     * To enable access to these keys, this method attempts to decrypt and cache the user's super
+     * keys.  If the password is given, i.e. if the unlock occurred using an LSKF-equivalent
+     * mechanism, then both the AfterFirstUnlock and UnlockedDeviceRequired super keys are decrypted
+     * (if not already done).  Otherwise, only the UnlockedDeviceRequired super keys are decrypted,
+     * and this only works if a valid HardwareAuthToken has been added to Keystore for one of the
+     * 'unlockingSids' that was passed to the last call to onDeviceLocked() for the user.
      *
      * ## 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
-     * `ResponseCode::VALUE_CORRUPTED` - if the super key can not be decrypted.
-     * `ResponseCode::KEY_NOT_FOUND` - if the super key is not found.
+     * `ResponseCode::PERMISSION_DENIED` - if the caller does not have the 'Unlock' permission.
+     * `ResponseCode::VALUE_CORRUPTED` - if a super key can not be decrypted.
+     * `ResponseCode::KEY_NOT_FOUND` - if a super key is not found.
+     * `ResponseCode::SYSTEM_ERROR` - if another error occurred.
      *
-     * @param lockScreenEvent whether the lock screen locked or unlocked
-     * @param userId android user id
-     * @param password synthetic password derived from the user's LSKF, must be null on lock
-     * @param unlockingSids list of biometric SIDs for this user, ignored on unlock
+     * @param userId The Android user ID of the user for which the device is now unlocked
+     * @param password If available, a secret derived from the user's synthetic password
      */
-    void onLockScreenEvent(in LockScreenEvent lockScreenEvent, in int userId,
-                           in @nullable byte[] password, in @nullable long[] unlockingSids);
+    void onDeviceUnlocked(in int userId, in @nullable byte[] password);
+
+    /**
+     * Tells Keystore that the device is now locked for a user.  Requires the 'Lock' permission.
+     *
+     * This method makes Keystore stop allowing the use of the given user's keys that require an
+     * unlocked device.  This is done through logical enforcement, and also through cryptographic
+     * enforcement by wiping the UnlockedDeviceRequired super keys from memory.
+     *
+     * unlockingSids is the list of SIDs of the user's biometrics with which the device may be
+     * unlocked later.  If this list is non-empty, then instead of completely wiping the
+     * UnlockedDeviceRequired super keys from memory, this method re-encrypts these super keys with
+     * a new AES key that is imported into KeyMint and bound to the given SIDs.  This allows the
+     * UnlockedDeviceRequired super keys to be recovered if the device is unlocked with a biometric.
+     *
+     * ## Error conditions:
+     * `ResponseCode::PERMISSION_DENIED` - if the caller does not have the 'Lock' permission.
+     *
+     * @param userId The Android user ID of the user for which the device is now locked
+     * @param unlockingSids The user's list of biometric SIDs
+     */
+    void onDeviceLocked(in int userId, in long[] unlockingSids);
 
     /**
      * Allows Credstore to retrieve a HardwareAuthToken and a TimestampToken.
diff --git a/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl b/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl
deleted file mode 100644
index c7553a2..0000000
--- a/keystore2/aidl/android/security/authorization/LockScreenEvent.aidl
+++ /dev/null
@@ -1,22 +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.authorization;
-
-/** @hide */
-@Backing(type="int")
-enum LockScreenEvent {
-    UNLOCK = 0,
-    LOCK = 1,
-}
diff --git a/keystore2/keystore2.rc b/keystore2/keystore2.rc
index 6f88dd3..d7d6951 100644
--- a/keystore2/keystore2.rc
+++ b/keystore2/keystore2.rc
@@ -11,3 +11,5 @@
     user keystore
     group keystore readproc log
     task_profiles ProcessCapacityHigh
+    # The default memlock limit of 65536 bytes is too low for keystore.
+    rlimit memlock unlimited unlimited
diff --git a/keystore2/src/authorization.rs b/keystore2/src/authorization.rs
index 7416b7f..36f94e9 100644
--- a/keystore2/src/authorization.rs
+++ b/keystore2/src/authorization.rs
@@ -26,8 +26,7 @@
 };
 use android_security_authorization::aidl::android::security::authorization::{
     AuthorizationTokens::AuthorizationTokens, IKeystoreAuthorization::BnKeystoreAuthorization,
-    IKeystoreAuthorization::IKeystoreAuthorization, LockScreenEvent::LockScreenEvent,
-    ResponseCode::ResponseCode,
+    IKeystoreAuthorization::IKeystoreAuthorization, ResponseCode::ResponseCode,
 };
 use android_security_authorization::binder::{
     BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status as BinderStatus,
@@ -144,71 +143,43 @@
         Ok(())
     }
 
-    fn on_lock_screen_event(
-        &self,
-        lock_screen_event: LockScreenEvent,
-        user_id: i32,
-        password: Option<Password>,
-        unlocking_sids: Option<&[i64]>,
-    ) -> Result<()> {
+    fn on_device_unlocked(&self, user_id: i32, password: Option<Password>) -> Result<()> {
         log::info!(
-            "on_lock_screen_event({:?}, user_id={:?}, password.is_some()={}, unlocking_sids={:?})",
-            lock_screen_event,
+            "on_device_unlocked(user_id={}, password.is_some()={})",
             user_id,
             password.is_some(),
-            unlocking_sids
         );
-        match (lock_screen_event, password) {
-            (LockScreenEvent::UNLOCK, Some(password)) => {
-                // This corresponds to the unlock() method in legacy keystore API.
-                // check permission
-                check_keystore_permission(KeystorePerm::Unlock)
-                    .context(ks_err!("Unlock with password."))?;
-                ENFORCEMENTS.set_device_locked(user_id, false);
+        check_keystore_permission(KeystorePerm::Unlock).context(ks_err!("Unlock."))?;
+        ENFORCEMENTS.set_device_locked(user_id, false);
 
-                let mut skm = SUPER_KEY.write().unwrap();
-
-                DB.with(|db| {
-                    skm.unlock_user(
-                        &mut db.borrow_mut(),
-                        &LEGACY_IMPORTER,
-                        user_id as u32,
-                        &password,
-                    )
-                })
-                .context(ks_err!("Unlock with password."))?;
-                Ok(())
-            }
-            (LockScreenEvent::UNLOCK, None) => {
-                check_keystore_permission(KeystorePerm::Unlock).context(ks_err!("Unlock."))?;
-                ENFORCEMENTS.set_device_locked(user_id, false);
-                let mut skm = SUPER_KEY.write().unwrap();
-                DB.with(|db| {
-                    skm.try_unlock_user_with_biometric(&mut db.borrow_mut(), user_id as u32)
-                })
-                .context(ks_err!("try_unlock_user_with_biometric failed"))?;
-                Ok(())
-            }
-            (LockScreenEvent::LOCK, None) => {
-                check_keystore_permission(KeystorePerm::Lock).context(ks_err!("Lock"))?;
-                ENFORCEMENTS.set_device_locked(user_id, true);
-                let mut skm = SUPER_KEY.write().unwrap();
-                DB.with(|db| {
-                    skm.lock_unlocked_device_required_keys(
-                        &mut db.borrow_mut(),
-                        user_id as u32,
-                        unlocking_sids.unwrap_or(&[]),
-                    );
-                });
-                Ok(())
-            }
-            _ => {
-                // Any other combination is not supported.
-                Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(ks_err!("Unknown event."))
-            }
+        let mut skm = SUPER_KEY.write().unwrap();
+        if let Some(password) = password {
+            DB.with(|db| {
+                skm.unlock_user(&mut db.borrow_mut(), &LEGACY_IMPORTER, user_id as u32, &password)
+            })
+            .context(ks_err!("Unlock with password."))
+        } else {
+            DB.with(|db| skm.try_unlock_user_with_biometric(&mut db.borrow_mut(), user_id as u32))
+                .context(ks_err!("try_unlock_user_with_biometric failed"))
         }
     }
 
+    fn on_device_locked(&self, user_id: i32, unlocking_sids: &[i64]) -> Result<()> {
+        log::info!("on_device_locked(user_id={}, unlocking_sids={:?})", user_id, unlocking_sids);
+
+        check_keystore_permission(KeystorePerm::Lock).context(ks_err!("Lock"))?;
+        ENFORCEMENTS.set_device_locked(user_id, true);
+        let mut skm = SUPER_KEY.write().unwrap();
+        DB.with(|db| {
+            skm.lock_unlocked_device_required_keys(
+                &mut db.borrow_mut(),
+                user_id as u32,
+                unlocking_sids,
+            );
+        });
+        Ok(())
+    }
+
     fn get_auth_tokens_for_credstore(
         &self,
         challenge: i64,
@@ -264,26 +235,14 @@
         map_or_log_err(self.add_auth_token(auth_token), Ok)
     }
 
-    fn onLockScreenEvent(
-        &self,
-        lock_screen_event: LockScreenEvent,
-        user_id: i32,
-        password: Option<&[u8]>,
-        unlocking_sids: Option<&[i64]>,
-    ) -> BinderResult<()> {
-        let _wp =
-            wd::watch_millis_with("IKeystoreAuthorization::onLockScreenEvent", 500, move || {
-                format!("lock event: {}", lock_screen_event.0)
-            });
-        map_or_log_err(
-            self.on_lock_screen_event(
-                lock_screen_event,
-                user_id,
-                password.map(|pw| pw.into()),
-                unlocking_sids,
-            ),
-            Ok,
-        )
+    fn onDeviceUnlocked(&self, user_id: i32, password: Option<&[u8]>) -> BinderResult<()> {
+        let _wp = wd::watch_millis("IKeystoreAuthorization::onDeviceUnlocked", 500);
+        map_or_log_err(self.on_device_unlocked(user_id, password.map(|pw| pw.into())), Ok)
+    }
+
+    fn onDeviceLocked(&self, user_id: i32, unlocking_sids: &[i64]) -> BinderResult<()> {
+        let _wp = wd::watch_millis("IKeystoreAuthorization::onDeviceLocked", 500);
+        map_or_log_err(self.on_device_locked(user_id, unlocking_sids), Ok)
     }
 
     fn getAuthTokensForCredStore(
diff --git a/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs b/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
index faf954a..c2cd3ad 100644
--- a/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
+++ b/keystore2/tests/legacy_blobs/keystore2_legacy_blob_tests.rs
@@ -28,7 +28,7 @@
 use android_security_maintenance::aidl::android::security::maintenance::IKeystoreMaintenance::IKeystoreMaintenance;
 
 use android_security_authorization::aidl::android::security::authorization::{
-    IKeystoreAuthorization::IKeystoreAuthorization, LockScreenEvent::LockScreenEvent,
+    IKeystoreAuthorization::IKeystoreAuthorization,
 };
 
 use keystore2::key_parameter::KeyParameter as KsKeyparameter;
@@ -229,8 +229,7 @@
             keystore2_restart_service();
 
             let auth_service = get_authorization();
-            match auth_service.onLockScreenEvent(LockScreenEvent::UNLOCK, 99, Some(PASSWORD), None)
-            {
+            match auth_service.onDeviceUnlocked(99, Some(PASSWORD)) {
                 Ok(result) => {
                     println!("Unlock Result: {:?}", result);
                 }
@@ -487,8 +486,7 @@
             keystore2_restart_service();
 
             let auth_service = get_authorization();
-            match auth_service.onLockScreenEvent(LockScreenEvent::UNLOCK, 98, Some(PASSWORD), None)
-            {
+            match auth_service.onDeviceUnlocked(98, Some(PASSWORD)) {
                 Ok(result) => {
                     println!("Unlock Result: {:?}", result);
                 }
diff --git a/provisioner/rkp_factory_extraction_tool.cpp b/provisioner/rkp_factory_extraction_tool.cpp
index 5765e05..0a3a59a 100644
--- a/provisioner/rkp_factory_extraction_tool.cpp
+++ b/provisioner/rkp_factory_extraction_tool.cpp
@@ -42,6 +42,8 @@
             "If true, this tool performs a self-test, validating the payload for correctness. "
             "This checks that the device on the factory line is producing valid output "
             "before attempting to upload the output to the device info service.");
+DEFINE_string(serialno_prop, "ro.serialno",
+              "The property of getting serial number. Defaults to 'ro.serialno'.");
 
 namespace {
 
@@ -59,7 +61,7 @@
         auto bytes = csr.encode();
         std::copy(bytes.begin(), bytes.end(), std::ostream_iterator<char>(std::cout));
     } else if (FLAGS_output_format == kBuildPlusCsr) {
-        auto [json, error] = jsonEncodeCsrWithBuild(instance_name, csr);
+        auto [json, error] = jsonEncodeCsrWithBuild(instance_name, csr, FLAGS_serialno_prop);
         if (!error.empty()) {
             std::cerr << "Error JSON encoding the output: " << error;
             exit(1);