keystore2 support for app UID migration

- Update migrate_key_namespace to accept specific UIDs for APP domain
  source and destination key descriptors
- Add new API to maintenance service to query a list of aliases for
  specified app UIDs

Test: atest SharedUserMigrationTest#testDataMigration (in internal)
Bug: 211665859
Change-Id: Ica06a8cd7c3f7b85f58d5953a22231cf7e9a1d7f
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 57abc26..39958a3 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -22,12 +22,14 @@
 use crate::globals::{DB, LEGACY_MIGRATOR, SUPER_KEY};
 use crate::permission::{KeyPerm, KeystorePerm};
 use crate::super_key::UserState;
-use crate::utils::{check_key_permission, check_keystore_permission, watchdog as wd};
+use crate::utils::{
+    check_key_permission, check_keystore_permission, list_key_entries, watchdog as wd,
+};
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     IKeyMintDevice::IKeyMintDevice, SecurityLevel::SecurityLevel,
 };
 use android_security_maintenance::aidl::android::security::maintenance::{
-    IKeystoreMaintenance::{BnKeystoreMaintenance, IKeystoreMaintenance},
+    IKeystoreMaintenance::{BnKeystoreMaintenance, IKeystoreMaintenance, UID_SELF},
     UserState::UserState as AidlUserState,
 };
 use android_security_maintenance::binder::{
@@ -37,6 +39,7 @@
 use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
 use anyhow::{Context, Result};
 use keystore2_crypto::Password;
+use keystore2_selinux as selinux;
 
 /// Reexport Domain for the benefit of DeleteListener
 pub use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
@@ -214,46 +217,64 @@
     }
 
     fn migrate_key_namespace(source: &KeyDescriptor, destination: &KeyDescriptor) -> Result<()> {
-        let caller_uid = ThreadState::get_calling_uid();
         let migrate_any_key_permission =
             check_keystore_permission(KeystorePerm::MigrateAnyKey).is_ok();
 
-        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| {
-                                    if !migrate_any_key_permission {
-                                        check_key_permission(KeyPerm::Use, k, &av)?;
-                                        check_key_permission(KeyPerm::Delete, k, &av)?;
-                                        check_key_permission(KeyPerm::Grant, k, &av)?;
-                                    }
-                                    Ok(())
-                                },
-                            )
-                        })
-                        .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."
-                    ))
-                }
-            };
+        let src_uid = match source.domain {
+            Domain::SELINUX | Domain::KEY_ID => ThreadState::get_calling_uid(),
+            Domain::APP if source.nspace == UID_SELF.into() => ThreadState::get_calling_uid(),
+            Domain::APP if source.nspace != UID_SELF.into() && migrate_any_key_permission => {
+                source.nspace as u32
+            }
+            _ => {
+                return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
+                    "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| {
-                if !migrate_any_key_permission {
-                    check_key_permission(KeyPerm::Rebind, k, &None)?;
+        let dest_uid = match destination.domain {
+            Domain::SELINUX => ThreadState::get_calling_uid(),
+            Domain::APP if destination.nspace == UID_SELF.into() => ThreadState::get_calling_uid(),
+            Domain::APP if destination.nspace != UID_SELF.into() && migrate_any_key_permission => {
+                destination.nspace as u32
+            }
+            _ => {
+                return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
+                    "In migrate_key_namespace:
+                     Destination domain must be one of APP or SELINUX.",
+                )
+            }
+        };
+
+        DB.with(|db| {
+            let (key_id_guard, _) = LEGACY_MIGRATOR
+                .with_try_migrate(source, src_uid, || {
+                    db.borrow_mut().load_key_entry(
+                        source,
+                        KeyType::Client,
+                        KeyEntryLoadBits::NONE,
+                        src_uid,
+                        |k, av| {
+                            if migrate_any_key_permission {
+                                Ok(())
+                            } else {
+                                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.")?;
+
+            db.borrow_mut().migrate_key_namespace(key_id_guard, destination, dest_uid, |k| {
+                if migrate_any_key_permission {
+                    Ok(())
+                } else {
+                    check_key_permission(KeyPerm::Rebind, k, &None)
                 }
-                Ok(())
             })
         })
     }
@@ -266,6 +287,30 @@
 
         Maintenance::call_on_all_security_levels("deleteAllKeys", |dev| dev.deleteAllKeys())
     }
+
+    fn list_entries(domain: Domain, nspace: i64) -> Result<Vec<KeyDescriptor>> {
+        let k = match domain {
+            Domain::APP | Domain::SELINUX => KeyDescriptor{domain, nspace, ..Default::default()},
+            _ => return Err(Error::perm()).context(
+                "In list_entries: List entries is only supported for Domain::APP and Domain::SELINUX."
+            ),
+        };
+
+        // The caller has to have either GetInfo for the namespace or List permission
+        check_key_permission(KeyPerm::GetInfo, &k, &None)
+            .or_else(|e| {
+                if Some(&selinux::Error::PermissionDenied)
+                    == e.root_cause().downcast_ref::<selinux::Error>()
+                {
+                    check_keystore_permission(KeystorePerm::List)
+                } else {
+                    Err(e)
+                }
+            })
+            .context("In list_entries: While checking key and keystore permission.")?;
+
+        DB.with(|db| list_key_entries(&mut db.borrow_mut(), domain, nspace))
+    }
 }
 
 impl Interface for Maintenance {}
@@ -315,6 +360,11 @@
         map_or_log_err(Self::migrate_key_namespace(source, destination), Ok)
     }
 
+    fn listEntries(&self, domain: Domain, namespace: i64) -> BinderResult<Vec<KeyDescriptor>> {
+        let _wp = wd::watch_millis("IKeystoreMaintenance::listEntries", 500);
+        map_or_log_err(Self::list_entries(domain, namespace), Ok)
+    }
+
     fn deleteAllKeys(&self) -> BinderResult<()> {
         let _wp = wd::watch_millis("IKeystoreMaintenance::deleteAllKeys", 500);
         map_or_log_err(Self::delete_all_keys(), Ok)