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)
+ }
}