Merge "Keystore 2.0: Add keystore2 support to the keystore-engine."
diff --git a/keystore2/TEST_MAPPING b/keystore2/TEST_MAPPING
index d4e20de..99a1e60 100644
--- a/keystore2/TEST_MAPPING
+++ b/keystore2/TEST_MAPPING
@@ -1,7 +1,10 @@
 {
   "presubmit": [
     {
-      "name": "keystore2_certificate_test"
+      "name": "keystore2_crypto_test"
+    },
+    {
+      "name": "keystore2_crypto_test_rust"
     },
     {
       "name": "keystore2_test"
diff --git a/keystore2/aidl/Android.bp b/keystore2/aidl/Android.bp
index d529fa9..c92417b 100644
--- a/keystore2/aidl/Android.bp
+++ b/keystore2/aidl/Android.bp
@@ -118,6 +118,9 @@
 aidl_interface {
     name: "android.security.usermanager",
     srcs: [ "android/security/usermanager/*.aidl" ],
+    imports: [
+        "android.system.keystore2",
+    ],
     unstable: true,
     backend: {
         java: {
diff --git a/keystore2/aidl/android/security/usermanager/IKeystoreUserManager.aidl b/keystore2/aidl/android/security/usermanager/IKeystoreUserManager.aidl
index 3690b1c..83edb1a 100644
--- a/keystore2/aidl/android/security/usermanager/IKeystoreUserManager.aidl
+++ b/keystore2/aidl/android/security/usermanager/IKeystoreUserManager.aidl
@@ -14,11 +14,14 @@
 
 package android.security.usermanager;
 
+import android.system.keystore2.Domain;
+
 // TODO: mark the interface with @SensitiveData when the annotation is ready (b/176110256).
 
 /**
  * IKeystoreUserManager interface exposes the methods for adding/removing users and changing the
  * user's password.
+ * @hide
  */
 interface IKeystoreUserManager {
 
@@ -31,6 +34,7 @@
      * user id.
      *
      * @param userId - Android user id
+     * @hide
      */
     void onUserAdded(in int userId);
 
@@ -42,6 +46,7 @@
      * `ResponseCode::SYSTEM_ERROR` - if failed to delete the keys of the user being deleted.
      *
      * @param userId - Android user id
+     * @hide
      */
     void onUserRemoved(in int userId);
 
@@ -56,6 +61,18 @@
      *
      * @param userId - Android user id
      * @param password - a secret derived from the synthetic password of the user
+     * @hide
      */
     void onUserPasswordChanged(in int userId, in @nullable byte[] password);
+
+    /**
+     * This function deletes all keys within a namespace. It mainly gets called when an app gets
+     * removed and all resources of this app need to be cleaned up.
+     *
+     * @param domain - One of Domain.APP or Domain.SELINUX.
+     * @param nspace - The UID of the app that is to be cleared if domain is Domain.APP or
+     *                 the SEPolicy namespace if domain is Domain.SELINUX.
+     * @hide
+     */
+     void clearNamespace(Domain domain, long nspace);
 }
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/km_compat/Android.bp b/keystore2/src/km_compat/Android.bp
index fa214a7..6b635ff 100644
--- a/keystore2/src/km_compat/Android.bp
+++ b/keystore2/src/km_compat/Android.bp
@@ -119,6 +119,7 @@
         "libkeymint_support",
         "libkeystore2_crypto",
         "libkm_compat",
+        "libkm_compat_service",
         "libutils",
     ],
 }
diff --git a/keystore2/src/km_compat/certificate_test.cpp b/keystore2/src/km_compat/certificate_test.cpp
index de1d60a..06cb0cb 100644
--- a/keystore2/src/km_compat/certificate_test.cpp
+++ b/keystore2/src/km_compat/certificate_test.cpp
@@ -23,6 +23,7 @@
 #include <aidl/android/hardware/security/keymint/BlockMode.h>
 #include <aidl/android/hardware/security/keymint/Digest.h>
 #include <aidl/android/hardware/security/keymint/PaddingMode.h>
+#include <android/binder_manager.h>
 
 #include <openssl/evp.h>
 #include <openssl/x509.h>
@@ -39,16 +40,29 @@
 using ::aidl::android::hardware::security::keymint::PaddingMode;
 using ::aidl::android::hardware::security::keymint::SecurityLevel;
 using ::aidl::android::hardware::security::keymint::Tag;
+using ::aidl::android::security::compat::IKeystoreCompatService;
 
 namespace KMV1 = ::aidl::android::hardware::security::keymint;
 
-static std::variant<std::vector<Certificate>, ScopedAStatus>
-getCertificate(const std::vector<KeyParameter>& keyParams) {
-    static std::shared_ptr<KeyMintDevice> device =
-        KeyMintDevice::createKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT);
+extern "C" int32_t addKeyMintDeviceService();
+
+static std::variant<std::shared_ptr<IKeyMintDevice>, ScopedAStatus> getDevice() {
+    addKeyMintDeviceService();
+    std::shared_ptr<IKeyMintDevice> device;
+    auto service = IKeystoreCompatService::fromBinder(
+        ndk::SpAIBinder(AServiceManager_getService("android.security.compat")));
+    if (!service) {
+        return ScopedAStatus::fromStatus(STATUS_NAME_NOT_FOUND);
+    }
+    service->getKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT, &device);
     if (!device) {
         return ScopedAStatus::fromStatus(STATUS_NAME_NOT_FOUND);
     }
+    return device;
+}
+
+static std::variant<std::vector<Certificate>, ScopedAStatus>
+getCertificate(std::shared_ptr<IKeyMintDevice> device, const std::vector<KeyParameter>& keyParams) {
     KeyCreationResult creationResult;
     auto status = device->generateKey(keyParams, std::nullopt /* attest_key */, &creationResult);
     if (!status.isOk()) {
@@ -76,6 +90,8 @@
         KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::RSA),
         KMV1::makeKeyParameter(KMV1::TAG_KEY_SIZE, 2048),
         KMV1::makeKeyParameter(KMV1::TAG_RSA_PUBLIC_EXPONENT, 65537),
+        KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_BEFORE, 0),
+        KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_AFTER, 253402300799000),
     });
     keyParams.insert(keyParams.end(), extraParams.begin(), extraParams.end());
     return keyParams;
@@ -87,10 +103,12 @@
         KMV1::makeKeyParameter(KMV1::TAG_PADDING, PaddingMode::RSA_PSS),
         KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED),
         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
-        KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::ENCRYPT),
     });
-    auto result = getCertificate(keyParams);
-    ensureCertChainSize(result, 1);
+    auto device = getDevice();
+    if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
+        auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
+        ensureCertChainSize(result, 1);
+    }
 }
 
 TEST(CertificateTest, TestAES) {
@@ -101,8 +119,11 @@
         KMV1::makeKeyParameter(KMV1::TAG_PADDING, PaddingMode::NONE),
         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::ENCRYPT),
     };
-    auto result = getCertificate(keyParams);
-    ensureCertChainSize(result, 0);
+    auto device = getDevice();
+    if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
+        auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
+        ensureCertChainSize(result, 0);
+    }
 }
 
 TEST(CertificateTest, TestAttestation) {
@@ -111,9 +132,12 @@
         KMV1::makeKeyParameter(KMV1::TAG_ATTESTATION_CHALLENGE, 42),
         KMV1::makeKeyParameter(KMV1::TAG_ATTESTATION_APPLICATION_ID, 42),
     });
-    auto result = getCertificate(keyParams);
-    ensureCertChainSize(result, 3);
-    verify(std::get<std::vector<Certificate>>(result).back());
+    auto device = getDevice();
+    if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
+        auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
+        ensureCertChainSize(result, 3);
+        verify(std::get<std::vector<Certificate>>(result).back());
+    }
 }
 
 TEST(CertificateTest, TestRSAKeygenNoEncryptNoAuthRequired) {
@@ -123,9 +147,12 @@
         KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
     });
-    auto result = getCertificate(keyParams);
-    ensureCertChainSize(result, 1);
-    verify(std::get<std::vector<Certificate>>(result)[0]);
+    auto device = getDevice();
+    if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
+        auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
+        ensureCertChainSize(result, 1);
+        verify(std::get<std::vector<Certificate>>(result)[0]);
+    }
 }
 
 TEST(CertificateTest, TestRSAKeygenNoEncryptAuthRequired) {
@@ -134,6 +161,9 @@
         KMV1::makeKeyParameter(KMV1::TAG_PADDING, PaddingMode::RSA_PSS),
         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
     });
-    auto result = getCertificate(keyParams);
-    ensureCertChainSize(result, 1);
+    auto device = getDevice();
+    if (std::holds_alternative<std::shared_ptr<IKeyMintDevice>>(device)) {
+        auto result = getCertificate(std::get<std::shared_ptr<IKeyMintDevice>>(device), keyParams);
+        ensureCertChainSize(result, 1);
+    }
 }
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index 812f513..b25cb0c 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -226,7 +226,9 @@
     if (securityLevel == KeyMintSecurityLevel::SOFTWARE) {
         // If the security level of the backend is `software` we expect the hardware enforced list
         // to be empty. Log a warning otherwise.
-        CHECK(legacyKc.hardwareEnforced.size() == 0);
+        if (legacyKc.hardwareEnforced.size() != 0) {
+            LOG(WARNING) << "Unexpected hardware enforced parameters.";
+        }
         return {keystoreEnforced};
     }
 
@@ -1118,11 +1120,11 @@
 // Constructors and helpers.
 
 KeyMintDevice::KeyMintDevice(sp<Keymaster> device, KeyMintSecurityLevel securityLevel)
-    : mDevice(device) {
+    : mDevice(device), securityLevel_(securityLevel) {
     if (securityLevel == KeyMintSecurityLevel::STRONGBOX) {
-        mOperationSlots.setNumFreeSlots(3);
+        setNumFreeSlots(3);
     } else {
-        mOperationSlots.setNumFreeSlots(15);
+        setNumFreeSlots(15);
     }
 }
 
diff --git a/keystore2/src/km_compat/lib.rs b/keystore2/src/km_compat/lib.rs
index 9be329f..22ddc31 100644
--- a/keystore2/src/km_compat/lib.rs
+++ b/keystore2/src/km_compat/lib.rs
@@ -324,8 +324,14 @@
     fn test_secure_clock() {
         add_keymint_device_service();
         let compat_service: binder::Strong<dyn IKeystoreCompatService> =
-            binder::get_interface(COMPAT_NAME).unwrap();
-        let secure_clock = compat_service.getSecureClock().unwrap();
+            match binder::get_interface(COMPAT_NAME) {
+                Ok(cs) => cs,
+                _ => return,
+            };
+        let secure_clock = match compat_service.getSecureClock() {
+            Ok(sc) => sc,
+            _ => return,
+        };
 
         let challenge = 42;
         let result = secure_clock.generateTimeStamp(challenge);
@@ -339,9 +345,15 @@
     fn test_shared_secret() {
         add_keymint_device_service();
         let compat_service: binder::Strong<dyn IKeystoreCompatService> =
-            binder::get_interface(COMPAT_NAME).unwrap();
-        let shared_secret =
-            compat_service.getSharedSecret(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+            match binder::get_interface(COMPAT_NAME) {
+                Ok(cs) => cs,
+                _ => return,
+            };
+        let shared_secret = match compat_service.getSharedSecret(SecurityLevel::TRUSTED_ENVIRONMENT)
+        {
+            Ok(ss) => ss,
+            _ => return,
+        };
 
         let result = shared_secret.getSharedSecretParameters();
         assert!(result.is_ok(), "{:?}", result);
diff --git a/keystore2/src/km_compat/slot_test.cpp b/keystore2/src/km_compat/slot_test.cpp
index 72d944c..37e7b36 100644
--- a/keystore2/src/km_compat/slot_test.cpp
+++ b/keystore2/src/km_compat/slot_test.cpp
@@ -140,20 +140,20 @@
     ASSERT_EQ(std::get<ScopedAStatus>(result).getServiceSpecificError(),
               static_cast<int32_t>(ErrorCode::TOO_MANY_OPERATIONS));
 
-    // Generating a certificate with signWith also uses a slot.
+    // Generating a certificate with signWith uses a slot but falls back to not using one.
     auto kps = std::vector<KeyParameter>({
         KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::RSA),
         KMV1::makeKeyParameter(KMV1::TAG_KEY_SIZE, 2048),
         KMV1::makeKeyParameter(KMV1::TAG_RSA_PUBLIC_EXPONENT, 65537),
         KMV1::makeKeyParameter(KMV1::TAG_DIGEST, Digest::SHA_2_256),
         KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
+        KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_BEFORE, 0),
+        KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_AFTER, 253402300799000),
         KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
     });
     KeyCreationResult creationResult;
     status = device->generateKey(kps, std::nullopt /* attest_key */, &creationResult);
-    ASSERT_TRUE(!status.isOk());
-    ASSERT_EQ(status.getServiceSpecificError(),
-              static_cast<int32_t>(ErrorCode::TOO_MANY_OPERATIONS));
+    ASSERT_TRUE(status.isOk());
     // But generating a certificate with signCert does not use a slot.
     kps.pop_back();
     status = device->generateKey(kps, std::nullopt /* attest_key */, &creationResult);
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)
+    }
 }
diff --git a/ondevice-signing/Keymaster.cpp b/ondevice-signing/Keymaster.cpp
index d43828a..267dec8 100644
--- a/ondevice-signing/Keymaster.cpp
+++ b/ondevice-signing/Keymaster.cpp
@@ -68,7 +68,7 @@
 
     mDevice = devToUse;
 
-    return true;
+    return mDevice != nullptr;
 }
 
 std::optional<Keymaster> Keymaster::getInstance() {
diff --git a/ondevice-signing/odsign_main.cpp b/ondevice-signing/odsign_main.cpp
index b019bb9..3baba68 100644
--- a/ondevice-signing/odsign_main.cpp
+++ b/ondevice-signing/odsign_main.cpp
@@ -50,6 +50,7 @@
 Result<void> addCertToFsVerityKeyring(const std::string& path) {
     const char* const argv[] = {kFsVerityInitPath, "--load-extra-key", "fsv_ods"};
 
+    // NOLINTNEXTLINE(android-cloexec-open): Deliberately not O_CLOEXEC
     int fd = open(path.c_str(), O_RDONLY);
     pid_t pid = fork();
     if (pid == 0) {