Implement onLockScreenEvent method of IKeystoreAuthorization AIDL interface.

In addition, this CL creates a global instance of LegacyBlobLoader.

Bug: 159475191,166672367
Test: TBD
Change-Id: I04005238f973b5eae98a07400688ea17edba80f8
diff --git a/keystore2/src/authorization.rs b/keystore2/src/authorization.rs
index 409feba..ba27df8 100644
--- a/keystore2/src/authorization.rs
+++ b/keystore2/src/authorization.rs
@@ -14,8 +14,9 @@
 
 //! This module implements IKeyAuthorization AIDL interface.
 
+use crate::error::Error as KeystoreError;
 use crate::error::map_or_log_err;
-use crate::globals::ENFORCEMENTS;
+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::{
@@ -28,6 +29,8 @@
 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;
 
@@ -59,6 +62,59 @@
         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 {}
@@ -67,4 +123,13 @@
     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/enforcements.rs b/keystore2/src/enforcements.rs
index 93e077c..4ff3950 100644
--- a/keystore2/src/enforcements.rs
+++ b/keystore2/src/enforcements.rs
@@ -211,6 +211,7 @@
         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
@@ -267,12 +268,7 @@
                     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;
@@ -320,6 +316,16 @@
             );
         }
 
+        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() {
             // key requiring authentication per operation
             if !is_time_out_key {
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index 3c79eed..7ceff26 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -20,6 +20,7 @@
 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::{
@@ -91,6 +92,10 @@
     /// 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";
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 7a87e8d..943f69f 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -33,6 +33,7 @@
 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::{
@@ -47,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};
@@ -83,6 +85,7 @@
         &self,
         key: KeyDescriptor,
         creation_result: KeyCreationResult,
+        user_id: u32,
     ) -> Result<KeyMetadata> {
         let KeyCreationResult {
             keyBlob: key_blob,
@@ -108,7 +111,12 @@
             },
         );
 
-        let key_parameters = key_characteristics_to_internal(key_characteristics);
+        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.")?;
 
@@ -335,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,
             },
@@ -353,7 +362,8 @@
         map_km_error(km_dev.addRngEntropy(entropy))?;
         let creation_result = map_km_error(km_dev.generateKey(&params))?;
 
-        self.store_new_key(key, creation_result).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(
@@ -368,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,
             },
@@ -401,7 +412,8 @@
         let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
         let creation_result = map_km_error(km_dev.importKey(&params, format, key_data))?;
 
-        self.store_new_key(key, creation_result).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(
@@ -432,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,
             },
@@ -451,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),
                 )
             })
@@ -509,7 +522,8 @@
             },
         )?;
 
-        self.store_new_key(key, creation_result).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>(