Merge changes I1c694e5b,Ic64b5376

* changes:
  Keystore 2.0: Make keystore2 early boot ready.
  Add Rust bindings to get the list of HALs.
diff --git a/keystore-engine/Android.bp b/keystore-engine/Android.bp
index b8127d3..9980765 100644
--- a/keystore-engine/Android.bp
+++ b/keystore-engine/Android.bp
@@ -27,6 +27,7 @@
     srcs: [
         "android_engine.cpp",
         "keystore_backend_binder.cpp",
+        "keystore2_engine.cpp",
     ],
 
     cflags: [
@@ -36,7 +37,9 @@
     ],
 
     shared_libs: [
+        "android.system.keystore2-V1-ndk_platform",
         "libbinder",
+        "libbinder_ndk",
         "libcrypto",
         "libcutils",
         "libhidlbase",
@@ -58,6 +61,7 @@
     srcs: [
         "android_engine.cpp",
         "keystore_backend_hidl.cpp",
+        "keystore2_engine.cpp",
     ],
 
     cflags: [
@@ -68,7 +72,10 @@
     ],
 
     shared_libs: [
+        "android.system.keystore2-V1-ndk_platform",
         "android.system.wifi.keystore@1.0",
+        "libbase",
+        "libbinder_ndk",
         "libcrypto",
         "liblog",
         "libhidlbase",
diff --git a/keystore-engine/android_engine.cpp b/keystore-engine/android_engine.cpp
index e3525b2..5881523 100644
--- a/keystore-engine/android_engine.cpp
+++ b/keystore-engine/android_engine.cpp
@@ -23,10 +23,7 @@
 #define LOG_TAG "keystore-engine"
 
 #include <pthread.h>
-#include <sys/socket.h>
-#include <stdarg.h>
 #include <string.h>
-#include <unistd.h>
 
 #include <log/log.h>
 
@@ -41,6 +38,8 @@
 
 #include <memory>
 
+#include "keystore2_engine.h"
+
 #ifndef BACKEND_WIFI_HIDL
 #include "keystore_backend_binder.h"
 #else
@@ -335,6 +334,10 @@
 EVP_PKEY* EVP_PKEY_from_keystore(const char* key_id) {
     ALOGV("EVP_PKEY_from_keystore(\"%s\")", key_id);
 
+    if (auto ks2_key = EVP_PKEY_from_keystore2(key_id)) {
+        return ks2_key;
+    }
+
     ensure_keystore_engine();
 
     uint8_t *pubkey = nullptr;
diff --git a/keystore-engine/keystore2_engine.cpp b/keystore-engine/keystore2_engine.cpp
new file mode 100644
index 0000000..8d25f48
--- /dev/null
+++ b/keystore-engine/keystore2_engine.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "keystore2_engine.h"
+
+#include <aidl/android/system/keystore2/IKeystoreService.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <android/binder_manager.h>
+
+#include <private/android_filesystem_config.h>
+
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+#include <openssl/engine.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+
+#define AT __func__ << ":" << __LINE__ << " "
+
+constexpr const char keystore2_service_name[] = "android.system.keystore2";
+const std::string keystore2_grant_id_prefix("ks2_keystore-engine_grant_id:");
+
+/**
+ * Keystore 2.0 namespace identifiers.
+ * Keep in sync with system/sepolicy/private/keystore2_key_contexts.
+ */
+constexpr const int64_t KS2_NAMESPACE_WIFI = 102;
+
+namespace ks2 = ::aidl::android::system::keystore2;
+namespace KMV1 = ::aidl::android::hardware::security::keymint;
+
+namespace {
+
+int64_t getNamespaceforCurrentUid() {
+    auto uid = getuid();
+    switch (uid) {
+    case AID_WIFI:
+        return KS2_NAMESPACE_WIFI;
+    // 0 is the super user namespace, and nothing has access to this namespace on user builds.
+    // So this will always fail.
+    default:
+        return 0;
+    }
+}
+
+struct Keystore2KeyBackend {
+    ks2::KeyDescriptor descriptor_;
+    std::shared_ptr<ks2::IKeystoreSecurityLevel> i_keystore_security_level_;
+};
+
+/* key_backend_dup is called when one of the RSA or EC_KEY objects is duplicated. */
+extern "C" int key_backend_dup(CRYPTO_EX_DATA* /* to */, const CRYPTO_EX_DATA* /* from */,
+                               void** from_d, int /* index */, long /* argl */, void* /* argp */) {
+    auto key_backend = reinterpret_cast<std::shared_ptr<Keystore2KeyBackend>*>(*from_d);
+    if (key_backend != nullptr) {
+        *from_d = new std::shared_ptr<Keystore2KeyBackend>(*key_backend);
+    }
+    return 1;
+}
+
+/* key_backend_free is called when one of the RSA, DSA or EC_KEY object is freed. */
+extern "C" void key_backend_free(void* /* parent */, void* ptr, CRYPTO_EX_DATA* /* ad */,
+                                 int /* index */, long /* argl */, void* /* argp */) {
+    delete reinterpret_cast<std::shared_ptr<Keystore2KeyBackend>*>(ptr);
+}
+
+extern "C" int rsa_private_transform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len);
+extern "C" int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+                          unsigned int* sig_len, EC_KEY* ec_key);
+/* KeystoreEngine is a BoringSSL ENGINE that implements RSA and ECDSA by
+ * forwarding the requested operations to Keystore. */
+class Keystore2Engine {
+  public:
+    Keystore2Engine()
+        : rsa_index_(RSA_get_ex_new_index(0 /* argl */, nullptr /* argp */, nullptr /* new_func */,
+                                          key_backend_dup, key_backend_free)),
+          ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */, nullptr /* argp */,
+                                                nullptr /* new_func */, key_backend_dup,
+                                                key_backend_free)),
+          engine_(ENGINE_new()) {
+        memset(&rsa_method_, 0, sizeof(rsa_method_));
+        rsa_method_.common.is_static = 1;
+        rsa_method_.private_transform = rsa_private_transform;
+        rsa_method_.flags = RSA_FLAG_OPAQUE;
+        ENGINE_set_RSA_method(engine_, &rsa_method_, sizeof(rsa_method_));
+
+        memset(&ecdsa_method_, 0, sizeof(ecdsa_method_));
+        ecdsa_method_.common.is_static = 1;
+        ecdsa_method_.sign = ecdsa_sign;
+        ecdsa_method_.flags = ECDSA_FLAG_OPAQUE;
+        ENGINE_set_ECDSA_method(engine_, &ecdsa_method_, sizeof(ecdsa_method_));
+    }
+
+    int rsa_ex_index() const { return rsa_index_; }
+    int ec_key_ex_index() const { return ec_key_index_; }
+
+    const ENGINE* engine() const { return engine_; }
+
+    static const Keystore2Engine& get() {
+        static Keystore2Engine engine;
+        return engine;
+    }
+
+  private:
+    const int rsa_index_;
+    const int ec_key_index_;
+    RSA_METHOD rsa_method_;
+    ECDSA_METHOD ecdsa_method_;
+    ENGINE* const engine_;
+};
+
+#define OWNERSHIP_TRANSFERRED(x) x.release()
+
+/* wrap_rsa returns an |EVP_PKEY| that contains an RSA key where the public
+ * part is taken from |public_rsa| and the private operations are forwarded to
+ * KeyStore and operate on the key named |key_id|. */
+bssl::UniquePtr<EVP_PKEY> wrap_rsa(std::shared_ptr<Keystore2KeyBackend> key_backend,
+                                   const RSA* public_rsa) {
+    bssl::UniquePtr<RSA> rsa(RSA_new_method(Keystore2Engine::get().engine()));
+    if (rsa.get() == nullptr) {
+        return nullptr;
+    }
+
+    auto key_backend_copy = new decltype(key_backend)(key_backend);
+
+    if (!RSA_set_ex_data(rsa.get(), Keystore2Engine::get().rsa_ex_index(), key_backend_copy)) {
+        delete key_backend_copy;
+        return nullptr;
+    }
+
+    rsa->n = BN_dup(public_rsa->n);
+    rsa->e = BN_dup(public_rsa->e);
+    if (rsa->n == nullptr || rsa->e == nullptr) {
+        return nullptr;
+    }
+
+    bssl::UniquePtr<EVP_PKEY> result(EVP_PKEY_new());
+    if (result.get() == nullptr || !EVP_PKEY_assign_RSA(result.get(), rsa.get())) {
+        return nullptr;
+    }
+    OWNERSHIP_TRANSFERRED(rsa);
+
+    return result;
+}
+
+/* wrap_ecdsa returns an |EVP_PKEY| that contains an ECDSA key where the public
+ * part is taken from |public_rsa| and the private operations are forwarded to
+ * KeyStore and operate on the key named |key_id|. */
+bssl::UniquePtr<EVP_PKEY> wrap_ecdsa(std::shared_ptr<Keystore2KeyBackend> key_backend,
+                                     const EC_KEY* public_ecdsa) {
+    bssl::UniquePtr<EC_KEY> ec(EC_KEY_new_method(Keystore2Engine::get().engine()));
+    if (ec.get() == nullptr) {
+        return nullptr;
+    }
+
+    if (!EC_KEY_set_group(ec.get(), EC_KEY_get0_group(public_ecdsa)) ||
+        !EC_KEY_set_public_key(ec.get(), EC_KEY_get0_public_key(public_ecdsa))) {
+        return nullptr;
+    }
+
+    auto key_backend_copy = new decltype(key_backend)(key_backend);
+
+    if (!EC_KEY_set_ex_data(ec.get(), Keystore2Engine::get().ec_key_ex_index(), key_backend_copy)) {
+        delete key_backend_copy;
+        return nullptr;
+    }
+
+    bssl::UniquePtr<EVP_PKEY> result(EVP_PKEY_new());
+    if (result.get() == nullptr || !EVP_PKEY_assign_EC_KEY(result.get(), ec.get())) {
+        return nullptr;
+    }
+    OWNERSHIP_TRANSFERRED(ec);
+
+    return result;
+}
+
+std::optional<std::vector<uint8_t>> keystore2_sign(const Keystore2KeyBackend& key_backend,
+                                                   std::vector<uint8_t> input,
+                                                   KMV1::Algorithm algorithm) {
+    auto sec_level = key_backend.i_keystore_security_level_;
+    ks2::CreateOperationResponse response;
+
+    std::vector<KMV1::KeyParameter> op_params(4);
+    op_params[0] = KMV1::KeyParameter{
+        .tag = KMV1::Tag::PURPOSE,
+        .value = KMV1::KeyParameterValue::make<KMV1::KeyParameterValue::keyPurpose>(
+            KMV1::KeyPurpose::SIGN)};
+    op_params[1] = KMV1::KeyParameter{
+        .tag = KMV1::Tag::ALGORITHM,
+        .value = KMV1::KeyParameterValue::make<KMV1::KeyParameterValue::algorithm>(algorithm)};
+    op_params[2] = KMV1::KeyParameter{
+        .tag = KMV1::Tag::PADDING,
+        .value = KMV1::KeyParameterValue::make<KMV1::KeyParameterValue::paddingMode>(
+            KMV1::PaddingMode::NONE)};
+    op_params[3] =
+        KMV1::KeyParameter{.tag = KMV1::Tag::DIGEST,
+                           .value = KMV1::KeyParameterValue::make<KMV1::KeyParameterValue::digest>(
+                               KMV1::Digest::NONE)};
+
+    auto rc = sec_level->createOperation(key_backend.descriptor_, op_params, false /* forced */,
+                                         &response);
+    if (!rc.isOk()) {
+        auto exception_code = rc.getExceptionCode();
+        if (exception_code == EX_SERVICE_SPECIFIC) {
+            LOG(ERROR) << AT << "Keystore createOperation returned service specific error: "
+                       << rc.getServiceSpecificError();
+        } else {
+            LOG(ERROR) << AT << "Communication with Keystore createOperation failed error: "
+                       << exception_code;
+        }
+        return std::nullopt;
+    }
+
+    auto op = response.iOperation;
+
+    std::optional<std::vector<uint8_t>> output = std::nullopt;
+    rc = op->finish(std::move(input), {}, &output);
+    if (!rc.isOk()) {
+        auto exception_code = rc.getExceptionCode();
+        if (exception_code == EX_SERVICE_SPECIFIC) {
+            LOG(ERROR) << AT << "Keystore finish returned service specific error: "
+                       << rc.getServiceSpecificError();
+        } else {
+            LOG(ERROR) << AT
+                       << "Communication with Keystore finish failed error: " << exception_code;
+        }
+        return std::nullopt;
+    }
+
+    if (!output) {
+        LOG(ERROR) << AT << "We did not get a signature from Keystore.";
+    }
+
+    return output;
+}
+
+/* rsa_private_transform takes a big-endian integer from |in|, calculates the
+ * d'th power of it, modulo the RSA modulus, and writes the result as a
+ * big-endian integer to |out|. Both |in| and |out| are |len| bytes long. It
+ * returns one on success and zero otherwise. */
+extern "C" int rsa_private_transform(RSA* rsa, uint8_t* out, const uint8_t* in, size_t len) {
+    auto key_backend = reinterpret_cast<std::shared_ptr<Keystore2KeyBackend>*>(
+        RSA_get_ex_data(rsa, Keystore2Engine::get().rsa_ex_index()));
+
+    if (key_backend == nullptr) {
+        LOG(ERROR) << AT << "Invalid key.";
+        return 0;
+    }
+
+    auto output =
+        keystore2_sign(**key_backend, std::vector<uint8_t>(in, in + len), KMV1::Algorithm::RSA);
+    if (!output) {
+        return 0;
+    }
+
+    if (output->size() > len) {
+        /* The result of the RSA operation can never be larger than the size of
+         * the modulus so we assume that the result has extra zeros on the
+         * left. This provides attackers with an oracle, but there's nothing
+         * that we can do about it here. */
+        LOG(WARNING) << "Reply len " << output->size() << " greater than expected " << len;
+        memcpy(out, &output->data()[output->size() - len], len);
+    } else if (output->size() < len) {
+        /* If the Keystore implementation returns a short value we assume that
+         * it's because it removed leading zeros from the left side. This is
+         * bad because it provides attackers with an oracle but we cannot do
+         * anything about a broken Keystore implementation here. */
+        LOG(WARNING) << "Reply len " << output->size() << " less than expected " << len;
+        memset(out, 0, len);
+        memcpy(out + len - output->size(), output->data(), output->size());
+    } else {
+        memcpy(out, output->data(), len);
+    }
+
+    return 1;
+}
+
+/* ecdsa_sign signs |digest_len| bytes from |digest| with |ec_key| and writes
+ * the resulting signature (an ASN.1 encoded blob) to |sig|. It returns one on
+ * success and zero otherwise. */
+extern "C" int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig,
+                          unsigned int* sig_len, EC_KEY* ec_key) {
+    auto key_backend = reinterpret_cast<std::shared_ptr<Keystore2KeyBackend>*>(
+        EC_KEY_get_ex_data(ec_key, Keystore2Engine::get().ec_key_ex_index()));
+
+    if (key_backend == nullptr) {
+        LOG(ERROR) << AT << "Invalid key.";
+        return 0;
+    }
+
+    size_t ecdsa_size = ECDSA_size(ec_key);
+
+    auto output = keystore2_sign(**key_backend, std::vector<uint8_t>(digest, digest + digest_len),
+                                 KMV1::Algorithm::EC);
+    if (!output) {
+        LOG(ERROR) << "There was an error during ecdsa_sign.";
+        return 0;
+    }
+
+    if (output->size() == 0) {
+        LOG(ERROR) << "No valid signature returned";
+        return 0;
+    } else if (output->size() > ecdsa_size) {
+        LOG(ERROR) << "Signature is too large";
+        return 0;
+    }
+
+    memcpy(sig, output->data(), output->size());
+    *sig_len = output->size();
+
+    return 1;
+}
+
+}  // namespace
+
+/* EVP_PKEY_from_keystore returns an |EVP_PKEY| that contains either an RSA or
+ * ECDSA key where the public part of the key reflects the value of the key
+ * named |key_id| in Keystore and the private operations are forwarded onto
+ * KeyStore. */
+extern "C" EVP_PKEY* EVP_PKEY_from_keystore2(const char* key_id) {
+    ::ndk::SpAIBinder keystoreBinder(AServiceManager_checkService(keystore2_service_name));
+    auto keystore2 = ks2::IKeystoreService::fromBinder(keystoreBinder);
+
+    if (!keystore2) {
+        LOG(ERROR) << AT << "Unable to connect to Keystore 2.0.";
+        return nullptr;
+    }
+
+    std::string alias = key_id;
+    if (android::base::StartsWith(alias, "USRPKEY_")) {
+        LOG(WARNING) << AT << "Keystore backend used with legacy alias prefix - ignoring.";
+        alias = alias.substr(8);
+    }
+
+    ks2::KeyDescriptor descriptor = {
+        .domain = ks2::Domain::SELINUX,
+        .nspace = getNamespaceforCurrentUid(),
+        .alias = alias,
+        .blob = std::nullopt,
+    };
+
+    // If the key_id starts with the grant id prefix, we parse the following string as numeric
+    // grant id. We can then use the grant domain without alias to load the designated key.
+    if (alias.find(keystore2_grant_id_prefix) == 0) {
+        std::stringstream s(alias.substr(keystore2_grant_id_prefix.size()));
+        s >> std::hex >> reinterpret_cast<uint64_t&>(descriptor.nspace);
+        descriptor.domain = ks2::Domain::GRANT;
+        descriptor.alias = std::nullopt;
+    }
+
+    ks2::KeyEntryResponse response;
+    auto rc = keystore2->getKeyEntry(descriptor, &response);
+    if (!rc.isOk()) {
+        auto exception_code = rc.getExceptionCode();
+        if (exception_code == EX_SERVICE_SPECIFIC) {
+            LOG(ERROR) << AT << "Keystore getKeyEntry returned service specific error: "
+                       << rc.getServiceSpecificError();
+        } else {
+            LOG(ERROR) << AT << "Communication with Keystore getKeyEntry failed error: "
+                       << exception_code;
+        }
+        return nullptr;
+    }
+
+    if (!response.metadata.certificate) {
+        LOG(ERROR) << AT << "No public key found.";
+        return nullptr;
+    }
+
+    const uint8_t* p = response.metadata.certificate->data();
+    bssl::UniquePtr<X509> x509(d2i_X509(nullptr, &p, response.metadata.certificate->size()));
+    if (!x509) {
+        LOG(ERROR) << AT << "Failed to parse x509 certificate.";
+        return nullptr;
+    }
+    bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509.get()));
+    if (!pkey) {
+        LOG(ERROR) << AT << "Failed to extract public key.";
+        return nullptr;
+    }
+
+    auto key_backend = std::make_shared<Keystore2KeyBackend>(
+        Keystore2KeyBackend{response.metadata.key, response.iSecurityLevel});
+
+    bssl::UniquePtr<EVP_PKEY> result;
+    switch (EVP_PKEY_type(pkey->type)) {
+    case EVP_PKEY_RSA: {
+        bssl::UniquePtr<RSA> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
+        result = wrap_rsa(key_backend, public_rsa.get());
+        break;
+    }
+    case EVP_PKEY_EC: {
+        bssl::UniquePtr<EC_KEY> public_ecdsa(EVP_PKEY_get1_EC_KEY(pkey.get()));
+        result = wrap_ecdsa(key_backend, public_ecdsa.get());
+        break;
+    }
+    default:
+        LOG(ERROR) << AT << "Unsupported key type " << EVP_PKEY_type(pkey->type);
+        return nullptr;
+    }
+
+    return result.release();
+}
diff --git a/keystore-engine/keystore2_engine.h b/keystore-engine/keystore2_engine.h
new file mode 100644
index 0000000..a8381d9
--- /dev/null
+++ b/keystore-engine/keystore2_engine.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <openssl/evp.h>
+
+extern "C" EVP_PKEY* EVP_PKEY_from_keystore2(const char* key_id);
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..6cfb565 100644
--- a/ondevice-signing/Keymaster.cpp
+++ b/ondevice-signing/Keymaster.cpp
@@ -66,9 +66,12 @@
         }
     }
 
+    if (devToUse == nullptr) {
+        LOG(WARNING) << "Didn't find a keymaster to use.";
+    }
     mDevice = devToUse;
 
-    return true;
+    return mDevice != nullptr;
 }
 
 std::optional<Keymaster> Keymaster::getInstance() {
diff --git a/ondevice-signing/KeymasterSigningKey.cpp b/ondevice-signing/KeymasterSigningKey.cpp
index f35f92b..2b748e4 100644
--- a/ondevice-signing/KeymasterSigningKey.cpp
+++ b/ondevice-signing/KeymasterSigningKey.cpp
@@ -61,7 +61,11 @@
 
 Result<void> KeymasterSigningKey::createSigningKey() {
     KeymasterSigningKey signingKey;
-    mKeymaster = Keymaster::getInstance();
+    auto keymaster = Keymaster::getInstance();
+    if (!keymaster.has_value()) {
+        return Error() << "Failed to initialize keymaster.";
+    }
+    mKeymaster = keymaster;
 
     auto keyBlob = mKeymaster->createKey();
 
@@ -112,8 +116,12 @@
 }
 
 Result<void> KeymasterSigningKey::initializeFromKeyblob(const std::string& path) {
-    mKeymaster = Keymaster::getInstance();
     std::string keyBlobData;
+    auto keymaster = Keymaster::getInstance();
+    if (!keymaster.has_value()) {
+        return Error() << "Failed to initialize keymaster.";
+    }
+    mKeymaster = keymaster;
 
     bool result = ReadFileToString(path, &keyBlobData);
     if (!result) {
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) {