Keystore 2.0: Implement clear namespace.
Implements the clearing of a specific namespace. This is requered for
uninstalling an app.
Test: Uninstall an app and check that all its keys get deleted.
Bug: 176123105
Change-Id: I519519f9381ee70a3dd2a93d77db92a510aa8427
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index db06bff..40860be 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -2522,6 +2522,51 @@
.context("In get_key_km_uuid.")
}
+ /// Delete all artifacts belonging to the namespace given by the domain-namespace tuple.
+ /// This leaves all of the blob entries orphaned for subsequent garbage collection.
+ pub fn unbind_keys_for_namespace(&mut self, domain: Domain, namespace: i64) -> Result<()> {
+ if !(domain == Domain::APP || domain == Domain::SELINUX) {
+ return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
+ .context("In unbind_keys_for_namespace.");
+ }
+ self.with_transaction(TransactionBehavior::Immediate, |tx| {
+ tx.execute(
+ "DELETE FROM persistent.keymetadata
+ WHERE keyentryid IN (
+ SELECT id FROM persistent.keyentry
+ WHERE domain = ? AND namespace = ?
+ );",
+ params![domain.0, namespace],
+ )
+ .context("Trying to delete keymetadata.")?;
+ tx.execute(
+ "DELETE FROM persistent.keyparameter
+ WHERE keyentryid IN (
+ SELECT id FROM persistent.keyentry
+ WHERE domain = ? AND namespace = ?
+ );",
+ params![domain.0, namespace],
+ )
+ .context("Trying to delete keyparameters.")?;
+ tx.execute(
+ "DELETE FROM persistent.grant
+ WHERE keyentryid IN (
+ SELECT id FROM persistent.keyentry
+ WHERE domain = ? AND namespace = ?
+ );",
+ params![domain.0, namespace],
+ )
+ .context("Trying to delete grants.")?;
+ tx.execute(
+ "DELETE FROM persistent.keyentry WHERE domain = ? AND namespace = ?;",
+ params![domain.0, namespace],
+ )
+ .context("Trying to delete keyentry.")?;
+ Ok(()).need_gc()
+ })
+ .context("In unbind_keys_for_namespace")
+ }
+
/// Delete the keys created on behalf of the user, denoted by the user id.
/// Delete all the keys unless 'keep_non_super_encrypted_keys' set to true.
/// Returned boolean is to hint the garbage collector to delete the unbound keys.
diff --git a/keystore2/src/legacy_migrator.rs b/keystore2/src/legacy_migrator.rs
index 9ffe86c..1ae8719 100644
--- a/keystore2/src/legacy_migrator.rs
+++ b/keystore2/src/legacy_migrator.rs
@@ -362,11 +362,18 @@
}
}
- /// Deletes all keys belonging to the given uid, migrating them into the database
+ /// Deletes all keys belonging to the given namespace, migrating them into the database
/// for subsequent garbage collection if necessary.
- pub fn bulk_delete_uid(&self, uid: u32, keep_non_super_encrypted_keys: bool) -> Result<()> {
+ pub fn bulk_delete_uid(&self, domain: Domain, nspace: i64) -> Result<()> {
+ let uid = match (domain, nspace) {
+ (Domain::APP, nspace) => nspace as u32,
+ (Domain::SELINUX, Self::WIFI_NAMESPACE) => Self::AID_WIFI,
+ // Nothing to do.
+ _ => return Ok(()),
+ };
+
let result = self.do_serialized(move |migrator_state| {
- migrator_state.bulk_delete(BulkDeleteRequest::Uid(uid), keep_non_super_encrypted_keys)
+ migrator_state.bulk_delete(BulkDeleteRequest::Uid(uid), false)
});
result.unwrap_or(Ok(()))
diff --git a/keystore2/src/user_manager.rs b/keystore2/src/user_manager.rs
index 8e09144..3c393c5 100644
--- a/keystore2/src/user_manager.rs
+++ b/keystore2/src/user_manager.rs
@@ -24,6 +24,7 @@
BnKeystoreUserManager, IKeystoreUserManager,
};
use android_security_usermanager::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 anyhow::{Context, Result};
use binder::{IBinder, Strong};
@@ -85,6 +86,17 @@
})
.context("In add_or_remove_user: Trying to delete keys from db.")
}
+
+ fn clear_namespace(domain: Domain, nspace: i64) -> Result<()> {
+ // Permission check. Must return on error. Do not touch the '?'.
+ check_keystore_permission(KeystorePerm::clear_uid()).context("In clear_namespace.")?;
+
+ LEGACY_MIGRATOR
+ .bulk_delete_uid(domain, nspace)
+ .context("In clear_namespace: Trying to delete legacy keys.")?;
+ DB.with(|db| db.borrow_mut().unbind_keys_for_namespace(domain, nspace))
+ .context("In clear_namespace: Trying to delete keys from db.")
+ }
}
impl Interface for UserManager {}
@@ -101,4 +113,8 @@
fn onUserRemoved(&self, user_id: i32) -> BinderResult<()> {
map_or_log_err(Self::add_or_remove_user(user_id), Ok)
}
+
+ fn clearNamespace(&self, domain: Domain, nspace: i64) -> BinderResult<()> {
+ map_or_log_err(Self::clear_namespace(domain, nspace), Ok)
+ }
}