Keystore 2.0: Add API for key migration to IKeystoreMaintenance

Bug: 184664830
Test: atest keystore2_test
Change-Id: Ic61cd403365841ba2202ac3ed8bcb01c97063d45
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index e059a0b..9ceb01a 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -14,14 +14,15 @@
 
 //! This module implements IKeystoreMaintenance AIDL interface.
 
+use crate::database::{KeyEntryLoadBits, KeyType, MonotonicRawTime};
 use crate::error::map_km_error;
-use crate::error::Error as KeystoreError;
+use crate::error::map_or_log_err;
+use crate::error::Error;
 use crate::globals::get_keymint_device;
 use crate::globals::{DB, LEGACY_MIGRATOR, SUPER_KEY};
-use crate::permission::KeystorePerm;
+use crate::permission::{KeyPerm, KeystorePerm};
 use crate::super_key::UserState;
-use crate::utils::check_keystore_permission;
-use crate::{database::MonotonicRawTime, error::map_or_log_err};
+use crate::utils::{check_key_permission, check_keystore_permission};
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::IKeyMintDevice::IKeyMintDevice;
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
 use android_security_maintenance::aidl::android::security::maintenance::{
@@ -29,10 +30,12 @@
     UserState::UserState as AidlUserState,
 };
 use android_security_maintenance::binder::{Interface, Result as BinderResult};
-use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
 use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, KeyDescriptor::KeyDescriptor,
+};
 use anyhow::{Context, Result};
-use binder::{IBinderInternal, Strong};
+use binder::{IBinderInternal, Strong, ThreadState};
 use keystore2_crypto::Password;
 
 /// This struct is defined to implement the aforementioned AIDL interface.
@@ -74,7 +77,7 @@
         {
             UserState::LskfLocked => {
                 // Error - password can not be changed when the device is locked
-                Err(KeystoreError::Rc(ResponseCode::LOCKED))
+                Err(Error::Rc(ResponseCode::LOCKED))
                     .context("In on_user_password_changed. Device is locked.")
             }
             _ => {
@@ -166,6 +169,43 @@
         DB.with(|db| db.borrow_mut().update_last_off_body(MonotonicRawTime::now()))
             .context("In on_device_off_body: Trying to update last off body time.")
     }
+
+    fn migrate_key_namespace(source: &KeyDescriptor, destination: &KeyDescriptor) -> Result<()> {
+        let caller_uid = ThreadState::get_calling_uid();
+
+        DB.with(|db| {
+            let key_id_guard = match source.domain {
+                Domain::APP | Domain::SELINUX | Domain::KEY_ID => {
+                    let (key_id_guard, _) = LEGACY_MIGRATOR
+                        .with_try_migrate(&source, caller_uid, || {
+                            db.borrow_mut().load_key_entry(
+                                &source,
+                                KeyType::Client,
+                                KeyEntryLoadBits::NONE,
+                                caller_uid,
+                                |k, av| {
+                                    check_key_permission(KeyPerm::use_(), k, &av)?;
+                                    check_key_permission(KeyPerm::delete(), k, &av)?;
+                                    check_key_permission(KeyPerm::grant(), k, &av)
+                                },
+                            )
+                        })
+                        .context("In migrate_key_namespace: Failed to load key blob.")?;
+                    key_id_guard
+                }
+                _ => {
+                    return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(concat!(
+                        "In migrate_key_namespace: ",
+                        "Source domain must be one of APP, SELINUX, or KEY_ID."
+                    ))
+                }
+            };
+
+            db.borrow_mut().migrate_key_namespace(key_id_guard, destination, caller_uid, |k| {
+                check_key_permission(KeyPerm::rebind(), k, &None)
+            })
+        })
+    }
 }
 
 impl Interface for Maintenance {}
@@ -198,4 +238,12 @@
     fn onDeviceOffBody(&self) -> BinderResult<()> {
         map_or_log_err(Self::on_device_off_body(), Ok)
     }
+
+    fn migrateKeyNamespace(
+        &self,
+        source: &KeyDescriptor,
+        destination: &KeyDescriptor,
+    ) -> BinderResult<()> {
+        map_or_log_err(Self::migrate_key_namespace(source, destination), Ok)
+    }
 }