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