Mark ab/6881855 as merged

Bug: 172690556
Change-Id: I9ecdb6b4c377eabf1d0778db70814067f9bcfb74
diff --git a/keystore/KeyAttestationApplicationId.cpp b/keystore/KeyAttestationApplicationId.cpp
index c62571f..1838b07 100644
--- a/keystore/KeyAttestationApplicationId.cpp
+++ b/keystore/KeyAttestationApplicationId.cpp
@@ -26,8 +26,8 @@
 KeyAttestationApplicationId::KeyAttestationApplicationId() = default;
 
 KeyAttestationApplicationId::KeyAttestationApplicationId(
-        std::unique_ptr<KeyAttestationPackageInfo> package) :
-    packageInfos_(new std::vector<std::unique_ptr<KeyAttestationPackageInfo>>()) {
+    std::optional<KeyAttestationPackageInfo> package)
+    : packageInfos_(new std::vector<std::optional<KeyAttestationPackageInfo>>()) {
     packageInfos_->push_back(std::move(package));
 }
 
@@ -39,10 +39,13 @@
 }
 
 status_t KeyAttestationApplicationId::readFromParcel(const Parcel* parcel) {
-    std::unique_ptr<std::vector<std::unique_ptr<KeyAttestationPackageInfo>>> temp_vector;
+    std::optional<std::vector<std::optional<KeyAttestationPackageInfo>>> temp_vector;
     auto rc = parcel->readParcelableVector(&temp_vector);
     if (rc != NO_ERROR) return rc;
-    packageInfos_.reset(temp_vector.release());
+    packageInfos_.reset();
+    if (temp_vector) {
+        packageInfos_ = std::make_shared<PackageInfoVector>(std::move(*temp_vector));
+    }
     return NO_ERROR;
 }
 
diff --git a/keystore/KeyAttestationPackageInfo.cpp b/keystore/KeyAttestationPackageInfo.cpp
index 75fbb7a..8e9a36a 100644
--- a/keystore/KeyAttestationPackageInfo.cpp
+++ b/keystore/KeyAttestationPackageInfo.cpp
@@ -28,7 +28,7 @@
 KeyAttestationPackageInfo::KeyAttestationPackageInfo(const String16& packageName,
                                                      int64_t versionCode,
                                                      SharedSignaturesVector signatures)
-    : packageName_(new String16(packageName)), versionCode_(versionCode), signatures_(signatures) {}
+    : packageName_(packageName), versionCode_(versionCode), signatures_(signatures) {}
 
 status_t KeyAttestationPackageInfo::writeToParcel(Parcel* parcel) const {
     auto rc = parcel->writeString16(packageName_);
@@ -44,10 +44,13 @@
     rc = parcel->readInt64(&versionCode_);
     if (rc != NO_ERROR) return rc;
 
-    std::unique_ptr<SignaturesVector> temp_vector;
+    std::optional<SignaturesVector> temp_vector;
     rc = parcel->readParcelableVector(&temp_vector);
     if (rc != NO_ERROR) return rc;
-    signatures_.reset(temp_vector.release());
+    signatures_.reset();
+    if (temp_vector) {
+        signatures_ = std::make_shared<SignaturesVector>(std::move(*temp_vector));
+    }
     return NO_ERROR;
 }
 
diff --git a/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl b/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl
index 0a51511..f37b838 100644
--- a/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl
+++ b/keystore/binder/android/security/keystore/IKeystoreOperationResultCallback.aidl
@@ -22,6 +22,7 @@
 /**
  * @hide
  */
+@SensitiveData
 oneway interface IKeystoreOperationResultCallback {
     void onFinished(in OperationResult result);
-}
\ No newline at end of file
+}
diff --git a/keystore/binder/android/security/keystore/IKeystoreService.aidl b/keystore/binder/android/security/keystore/IKeystoreService.aidl
index 6edca56..e0879dd 100644
--- a/keystore/binder/android/security/keystore/IKeystoreService.aidl
+++ b/keystore/binder/android/security/keystore/IKeystoreService.aidl
@@ -29,10 +29,11 @@
 /**
  * @hide
  */
+@SensitiveData
 interface IKeystoreService {
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     int getState(int userId);
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     byte[] get(String name, int uid);
     @UnsupportedAppUsage
     int insert(String name, in byte[] item, int uid, int flags);
@@ -40,7 +41,7 @@
     int del(String name, int uid);
     @UnsupportedAppUsage
     int exist(String name, int uid);
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     String[] list(String namePrefix, int uid);
     int onUserPasswordChanged(int userId, String newPassword);
     int lock(int userId);
diff --git a/keystore/include/keystore/KeyAttestationApplicationId.h b/keystore/include/keystore/KeyAttestationApplicationId.h
index 861c2e1..0bf1aad 100644
--- a/keystore/include/keystore/KeyAttestationApplicationId.h
+++ b/keystore/include/keystore/KeyAttestationApplicationId.h
@@ -16,6 +16,7 @@
 #define KEYSTORE_INCLUDE_KEYSTORE_KEYATTESTATIONAPPLICATIONID_H_
 
 #include <memory>
+#include <optional>
 #include <vector>
 
 #include <binder/Parcelable.h>
@@ -30,10 +31,10 @@
   public:
     typedef SharedNullableIterator<const KeyAttestationPackageInfo, std::vector>
         ConstKeyAttestationPackageInfoIterator;
-    typedef std::vector<std::unique_ptr<KeyAttestationPackageInfo>> PackageInfoVector;
+    typedef std::vector<std::optional<KeyAttestationPackageInfo>> PackageInfoVector;
     KeyAttestationApplicationId();
     // Following c'tors are for initializing instances containing test data.
-    explicit KeyAttestationApplicationId(std::unique_ptr<KeyAttestationPackageInfo> package);
+    explicit KeyAttestationApplicationId(std::optional<KeyAttestationPackageInfo> package);
     explicit KeyAttestationApplicationId(PackageInfoVector packages);
 
     status_t writeToParcel(Parcel*) const override;
@@ -47,7 +48,7 @@
     }
 
   private:
-    std::shared_ptr<std::vector<std::unique_ptr<KeyAttestationPackageInfo>>> packageInfos_;
+    std::shared_ptr<PackageInfoVector> packageInfos_;
 };
 
 }  // namespace keymaster
diff --git a/keystore/include/keystore/KeyAttestationPackageInfo.h b/keystore/include/keystore/KeyAttestationPackageInfo.h
index 92d4863..fa638f9 100644
--- a/keystore/include/keystore/KeyAttestationPackageInfo.h
+++ b/keystore/include/keystore/KeyAttestationPackageInfo.h
@@ -18,6 +18,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <optional>
 #include <vector>
 
 #include <binder/Parcelable.h>
@@ -33,8 +34,7 @@
   public:
     typedef SharedNullableIterator<const content::pm::Signature, std::vector>
         ConstSignatureIterator;
-    typedef std::vector<std::unique_ptr<content::pm::Signature>>
-        SignaturesVector;
+    typedef std::vector<std::optional<content::pm::Signature>> SignaturesVector;
     typedef std::shared_ptr<SignaturesVector> SharedSignaturesVector;
 
     KeyAttestationPackageInfo(const String16& packageName, int64_t versionCode,
@@ -44,14 +44,14 @@
     status_t writeToParcel(Parcel*) const override;
     status_t readFromParcel(const Parcel* parcel) override;
 
-    const std::unique_ptr<String16>& package_name() const { return packageName_; }
+    const std::optional<String16>& package_name() const { return packageName_; }
     int64_t version_code() const { return versionCode_; }
 
     ConstSignatureIterator sigs_begin() const { return ConstSignatureIterator(signatures_); }
     ConstSignatureIterator sigs_end() const { return ConstSignatureIterator(); }
 
   private:
-    std::unique_ptr<String16> packageName_;
+    std::optional<String16> packageName_;
     int64_t versionCode_;
     SharedSignaturesVector signatures_;
 };
diff --git a/keystore/include/keystore/KeystoreResponse.h b/keystore/include/keystore/KeystoreResponse.h
index 20f7274..4a7ef0d 100644
--- a/keystore/include/keystore/KeystoreResponse.h
+++ b/keystore/include/keystore/KeystoreResponse.h
@@ -31,29 +31,24 @@
   public:
     KeystoreResponse() = default;
     explicit KeystoreResponse(const int response_code, const String16& error_msg)
-        : response_code_(response_code), error_msg_(std::make_unique<String16>(error_msg)) {}
+        : response_code_(response_code), error_msg_(error_msg) {}
     explicit KeystoreResponse(const int response_code)
         : response_code_(response_code), error_msg_() {}
     // NOLINTNEXTLINE(google-explicit-constructor)
     KeystoreResponse(const ::keystore::KeyStoreServiceReturnCode& rc)
         : response_code_(rc.getErrorCode()), error_msg_() {}
-    KeystoreResponse(const KeystoreResponse& other)
-        : response_code_(other.response_code_), error_msg_() {
-        if (other.error_msg_) {
-            error_msg_ = std::make_unique<String16>(*other.error_msg_);
-        }
-    }
+    KeystoreResponse(const KeystoreResponse& other) = default;
     KeystoreResponse(KeystoreResponse&& other) = default;
 
     status_t readFromParcel(const Parcel* in) override;
     status_t writeToParcel(Parcel* out) const override;
 
     int response_code() const { return response_code_; }
-    const String16* error_msg() const { return error_msg_.get(); }
+    const std::optional<String16>& error_msg() const { return error_msg_; }
 
   private:
     int response_code_;
-    std::unique_ptr<String16> error_msg_;
+    std::optional<String16> error_msg_;
 };
 
 }  // namespace keystore
diff --git a/keystore/include/keystore/utils.h b/keystore/include/keystore/utils.h
index 544dd21..2143d3a 100644
--- a/keystore/include/keystore/utils.h
+++ b/keystore/include/keystore/utils.h
@@ -5,6 +5,7 @@
 
 #include <iterator>
 #include <memory>
+#include <optional>
 #include <vector>
 
 namespace android {
@@ -12,7 +13,7 @@
 
 /*
  * This iterator abstracts from a collection of the form
- * std::shared_ptr<COLLECTION_TYPE<std::unique_ptr<T>>>
+ * std::shared_ptr<COLLECTION_TYPE<std::optional<T>>>
  * such that it is defined both for nulled outer pointer and
  * nulled entries. If shared_ptr(nullptr) is passed in, the iterator behaves
  * like the end iterator yielding an empty collection. Nulled
@@ -25,7 +26,7 @@
 template <typename T, template <typename...> class Coll = std::vector>
 class SharedNullableIterator {
   public:
-    typedef Coll<std::unique_ptr<typename std::remove_const<T>::type>> CollectionType;
+    typedef Coll<std::optional<typename std::remove_const<T>::type>> CollectionType;
     typedef std::shared_ptr<CollectionType> CollectionPtr;
 
     SharedNullableIterator() {}
diff --git a/keystore/key_attestation_log_handler.cpp b/keystore/key_attestation_log_handler.cpp
index 34c76a3..c3278cb 100644
--- a/keystore/key_attestation_log_handler.cpp
+++ b/keystore/key_attestation_log_handler.cpp
@@ -17,7 +17,11 @@
 namespace keystore {
 
 void logKeystoreKeyAttestationEvent(bool wasSuccessful, int32_t errorCode) {
-    android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED,
+    // Due to a requirement in stats-write() method, the optional fields
+    // which are not required for attestation logging, are marked with -1 for
+    // non-repeated fields and 0 for repeated fields.
+    android::util::stats_write(android::util::KEYSTORE_KEY_EVENT_REPORTED, -1, -1, -1, -1, -1, 0, 0,
+                               0, 0, -1, -1,
                                android::util::KEYSTORE_KEY_EVENT_REPORTED__TYPE__KEY_ATTESTATION,
                                wasSuccessful, errorCode);
 }
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
index 3d9e87e..ccd3808 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -271,7 +271,7 @@
 
     if (uid == AID_SYSTEM) {
         /* Use a fixed ID for system callers */
-        auto pinfo = std::make_unique<KeyAttestationPackageInfo>(
+        auto pinfo = std::make_optional<KeyAttestationPackageInfo>(
             String16(kAttestationSystemPackageName), 1 /* version code */,
             std::make_shared<KeyAttestationPackageInfo::SignaturesVector>());
         key_attestation_id = KeyAttestationApplicationId(std::move(pinfo));
@@ -284,7 +284,7 @@
         if (!status.isOk()) {
             ALOGW("package manager request for key attestation ID failed with: %s %d",
                   status.exceptionMessage().string(), status.exceptionCode());
-            auto pinfo = std::make_unique<KeyAttestationPackageInfo>(
+            auto pinfo = std::make_optional<KeyAttestationPackageInfo>(
                 String16(kUnknownPackageName), 1 /* version code */,
                 std::make_shared<KeyAttestationPackageInfo::SignaturesVector>());
             key_attestation_id = KeyAttestationApplicationId(std::move(pinfo));
diff --git a/keystore/tests/aaid_truncation_test.cpp b/keystore/tests/aaid_truncation_test.cpp
index 45c54df..fa4d769 100644
--- a/keystore/tests/aaid_truncation_test.cpp
+++ b/keystore/tests/aaid_truncation_test.cpp
@@ -75,15 +75,15 @@
 using ::android::content::pm::Signature;
 using ::android::security::build_attestation_application_id;
 
-std::unique_ptr<KeyAttestationPackageInfo>
+std::optional<KeyAttestationPackageInfo>
 make_package_info_with_signatures(const char* package_name,
                                   KeyAttestationPackageInfo::SignaturesVector signatures) {
-    return std::make_unique<KeyAttestationPackageInfo>(
+    return std::make_optional<KeyAttestationPackageInfo>(
         String16(package_name), 1 /* version code */,
         std::make_shared<KeyAttestationPackageInfo::SignaturesVector>(std::move(signatures)));
 }
 
-std::unique_ptr<KeyAttestationPackageInfo> make_package_info(const char* package_name) {
+std::optional<KeyAttestationPackageInfo> make_package_info(const char* package_name) {
     return make_package_info_with_signatures(package_name,
                                              KeyAttestationPackageInfo::SignaturesVector());
 }
@@ -111,7 +111,7 @@
     KeyAttestationPackageInfo::SignaturesVector signatures;
     // Add 35 signatures which will surely exceed the 1K limit.
     for (size_t i = 0; i < kTooManySignatures; ++i) {
-        signatures.push_back(std::make_unique<Signature>(dummy_sig_data));
+        signatures.push_back(std::make_optional<Signature>(dummy_sig_data));
     }
 
     KeyAttestationApplicationId app_id(
@@ -131,7 +131,7 @@
         KeyAttestationPackageInfo::SignaturesVector signatures;
         // Add a few signatures for each package
         for (int j = 0; j < 3; ++j) {
-            signatures.push_back(std::make_unique<Signature>(dummy_sig_data));
+            signatures.push_back(std::make_optional<Signature>(dummy_sig_data));
         }
         packages.push_back(
             make_package_info_with_signatures(kReasonablePackageName, std::move(signatures)));
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index b5728a3..40d91c2 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -18,8 +18,8 @@
     srcs: ["src/lib.rs"],
 
     rustlibs: [
-        "libandroid_hardware_keymint",
-        "libandroid_security_keystore2",
+        "android.system.keystore2-rust",
+        "android.hardware.keymint-rust",
         "libanyhow",
         "libbinder_rs",
         "libkeystore2_selinux",
@@ -39,11 +39,12 @@
     test_suites: ["general-tests"],
     auto_gen_config: true,
     rustlibs: [
+        "android.system.keystore2-rust",
+        "android.hardware.keymint-rust",
         "libandroid_logger",
-        "libandroid_hardware_keymint",
-        "libandroid_security_keystore2",
         "libanyhow",
         "libbinder_rs",
+        "libkeystore2_crypto_bindgen",
         "libkeystore2_selinux",
         "liblazy_static",
         "liblibsqlite3_sys",
@@ -51,33 +52,57 @@
         "librusqlite",
         "libthiserror",
     ],
+    shared_libs: ["libkeystore2_crypto"],
 }
 
-// This is a placeholder for the libraries that will be generated from the AIDL specs
-// eventually.
-rust_library {
-    name: "libandroid_hardware_keymint",
-    crate_name: "android_hardware_keymint",
-
-    srcs: ["src/android_hardware_keymint.rs"],
-
-    rustlibs: [
-        "libbinder_rs",
-        "liblazy_static",
+cc_library {
+    name: "libkeystore2_crypto",
+    srcs: [
+        "src/crypto.cpp",
+        "src/certificate_utils.cpp",
+    ],
+    export_include_dirs: ["include",],
+    shared_libs: [
+        "libcrypto",
+        "liblog",
     ],
 }
 
-// This is a placeholder for the libraries that will be generated from the AIDL specs
-// eventually.
-rust_library {
-    name: "libandroid_security_keystore2",
-    crate_name: "android_security_keystore2",
+rust_bindgen {
+    name: "libkeystore2_crypto_bindgen",
+    wrapper_src: "src/crypto.hpp",
+    crate_name: "keystore2_crypto_bindgen",
+    source_stem: "bindings",
+    host_supported: true,
+}
 
-    srcs: ["src/android_security_keystore2.rs"],
-
+rust_binary {
+    name: "keystore2",
+    srcs: ["src/keystore2_main.rs"],
     rustlibs: [
-        "libandroid_hardware_keymint",
+        "libandroid_logger",
         "libbinder_rs",
-        "liblazy_static",
+        "libkeystore2",
+        "liblog_rust",
     ],
+    init_rc: ["keystore2.rc"],
+}
+
+cc_test {
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    srcs: [
+        "src/tests/certificate_utils_test.cpp",
+        "src/tests/gtest_main.cpp",
+    ],
+    static_libs: [
+        "libkeystore2_crypto",
+    ],
+    shared_libs: [
+        "libcrypto",
+    ],
+    name: "keystore2_crypto_test",
 }
diff --git a/keystore2/include/certificate_utils.h b/keystore2/include/certificate_utils.h
new file mode 100644
index 0000000..9d41eb8
--- /dev/null
+++ b/keystore2/include/certificate_utils.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2020, 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/err.h>
+#include <openssl/x509.h>
+#include <stdint.h>
+
+#include <memory>
+#include <optional>
+#include <variant>
+
+namespace keystore {
+// We use boringssl error codes. Error codes that we add are folded into LIB_USER.
+// The CertificateUtilsInternallErrorCodes enum should not be used by callers, instead use the
+// BoringSslError constant definitions below for error codes.
+using BoringSslError = unsigned long;
+
+#define DEFINE_OPENSSL_OBJECT_POINTER(name) using name##_Ptr = bssl::UniquePtr<name>
+
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_BIT_STRING);
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_STRING);
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_INTEGER);
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_OCTET_STRING);
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_TIME);
+DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY);
+DEFINE_OPENSSL_OBJECT_POINTER(X509);
+DEFINE_OPENSSL_OBJECT_POINTER(X509_EXTENSION);
+DEFINE_OPENSSL_OBJECT_POINTER(X509_NAME);
+DEFINE_OPENSSL_OBJECT_POINTER(EVP_PKEY_CTX);
+
+class CertUtilsError {
+  public:
+    enum Error {
+        Ok = 0,
+        BoringSsl,
+        Encoding,
+        MemoryAllocation,
+        InvalidArgument,
+        UnexpectedNullPointer,
+    };
+
+  private:
+    Error e_;
+
+  public:
+    constexpr CertUtilsError(Error e) : e_(e) {}
+    explicit constexpr operator bool() const { return e_ != Ok; }
+};
+
+struct KeyUsageExtension {
+    bool isSigningKey;
+    bool isEncryptionKey;
+    bool isCertificationKey;
+};
+
+struct BasicConstraintsExtension {
+    bool isCa;
+    std::optional<int> pathLength;
+};
+
+/**
+ * This function allocates and prepares an X509 certificate structure with all of the information
+ * given. Next steps would be to set an Issuer with `setIssuer` and sign it with either
+ * `signCert` or `signCertWith`.
+ * @param evp_pkey The public key that the certificate is issued for.
+ * @param serial The certificate serial number.
+ * @param subject The subject common name.
+ * @param activeDateTimeMilliSeconds The not before date in epoch milliseconds.
+ * @param usageExpireDateTimeMilliSeconds The not after date in epoch milliseconds.
+ * @param addSubjectKeyIdEx If true, adds the subject key id extension.
+ * @param keyUsageEx If given adds, the key usage extension with the given flags.
+ * @param basicConstraints If given, adds the basic constraints extension with the given data.
+ * @return CertUtilsError::Ok on success.
+ */
+std::variant<CertUtilsError, X509_Ptr>
+makeCert(const EVP_PKEY* evp_pkey,                                    //
+         const uint32_t serial,                                       //
+         const char subject[],                                        //
+         const uint64_t activeDateTimeMilliSeconds,                   //
+         const uint64_t usageExpireDateTimeMilliSeconds,              //
+         bool addSubjectKeyIdEx,                                      //
+         std::optional<KeyUsageExtension> keyUsageEx,                 //
+         std::optional<BasicConstraintsExtension> basicConstraints);  //
+
+/**
+ * Takes the subject name from `signingCert` and sets it as issuer name in `cert`.
+ * if `addAuthKeyExt` is true it also generates the digest of the signing certificates's public key
+ * and sets it as authority key id extension in `cert`.
+ * For self signed certificates pass the same pointer to both `cert` and `signingCert`.
+ *
+ * @param cert
+ * @param signingCert
+ * @param addAuthKeyExt
+ * @return CertUtilsError::Ok on success.
+ */
+CertUtilsError setIssuer(X509* cert, const X509* signingCert, bool addAuthKeyExt);
+
+/**
+ * Takes a certificate, and private signing_key.
+ * Signs the certificate with the latter.
+ */
+CertUtilsError signCert(X509* certificate, EVP_PKEY* signing_key);
+
+enum class Digest {
+    SHA1,
+    SHA224,
+    SHA256,
+    SHA384,
+    SHA512,
+};
+
+enum class Algo {
+    ECDSA,
+    RSA,
+};
+
+enum class Padding {
+    Ignored,
+    PKCS1_5,
+    PSS,
+};
+
+/**
+ * Sets the signature specifier of the certificate and the signature according to the parameters
+ * c. Then it signs the certificate with the `sign` callback.
+ * IMPORTANT: The parameters `algo`, `padding`, and `digest` do not control the actual signing
+ * algorithm. The caller is responsible to provide a callback that actually performs the signature
+ * as described by this triplet.
+ * The `padding` argument is ignored if `algo` is Algo::EC.
+ * The `digest` field controls the message digest used, and, in case of RSA with PSS padding,
+ *              also the MGF1 digest.
+ *
+ * @param certificate X509 certificate structure to be signed.
+ * @param sign Callback function used to digest and sign the DER encoded to-be-signed certificate.
+ * @param algo Algorithm specifier used to encode the signing algorithm id of the X509 certificate.
+ * @param padding Padding specifier used to encode the signing algorithm id of the X509 certificate.
+ * @param digest Digest specifier used to encode the signing algorithm id of the X509 certificate.
+ * @return CertUtilsError::Ok on success.
+ */
+CertUtilsError signCertWith(X509* certificate,
+                            std::function<std::vector<uint8_t>(const uint8_t*, size_t)> sign,
+                            Algo algo, Padding padding, Digest digest);
+
+/**
+ * Generates the DER representation of the given signed X509 certificate structure.
+ * @param certificate
+ * @return std::vector<uint8_t> with the DER encoded certificate on success. An error code
+ *         otherwise.
+ */
+std::variant<CertUtilsError, std::vector<uint8_t>> encodeCert(X509* certificate);
+
+}  // namespace keystore
diff --git a/keystore2/keystore2.rc b/keystore2/keystore2.rc
new file mode 100644
index 0000000..bc040e5
--- /dev/null
+++ b/keystore2/keystore2.rc
@@ -0,0 +1,20 @@
+# Start the keystore2 service.
+# Keystore 2.0 changes its working directory to the first positional
+# command line option, i.e., /data/misc/keystore, where it stores its
+# database.
+# Keystore shall run as user keystore and groups keystore, readproc, and log.
+#
+# See system/core/init/README.md for information on the init.rc language.
+
+# Start Keystore 2 conditionally
+# TODO b/171563717 Remove when Keystore 2 migration is complete.
+on nonencrypted && property:ro.android.security.keystore2.enable=true
+    enable keystore2
+
+service keystore2 /system/bin/keystore2 /data/misc/keystore
+    class main
+    user keystore
+    group keystore readproc log
+    writepid /dev/cpuset/foreground/tasks
+    # TODO b/171563717 Remove when Keystore 2 migration is complete.
+    disabled
diff --git a/keystore2/src/android_hardware_keymint.rs b/keystore2/src/android_hardware_keymint.rs
deleted file mode 100644
index deb9f7b..0000000
--- a/keystore2/src/android_hardware_keymint.rs
+++ /dev/null
@@ -1,1640 +0,0 @@
-#![allow(non_snake_case)]
-#![allow(missing_docs)]
-#![allow(clippy::identity_op)]
-#![allow(clippy::excessive_precision)]
-#![allow(clippy::too_many_arguments)]
-pub use binder::public_api as binder;
-pub mod aidl {
-  pub mod android {
-    pub mod hardware {
-      pub mod keymint {
-        pub mod Algorithm {
-          #![allow(non_upper_case_globals)]
-          pub type Algorithm = i32;
-          pub const RSA: Algorithm = 1;
-          pub const EC: Algorithm = 3;
-          pub const AES: Algorithm = 32;
-          pub const TRIPLE_DES: Algorithm = 33;
-          pub const HMAC: Algorithm = 128;
-          pub(crate) mod mangled { pub use super::Algorithm as _7_android_8_hardware_7_keymint_9_Algorithm; }
-        }
-        pub mod BeginResult {
-          pub struct BeginResult {
-            pub challenge: i64, 
-            pub params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
-            pub operation: Option<Box<dyn crate::mangled::_7_android_8_hardware_7_keymint_17_IKeyMintOperation>>, 
-          }
-          pub(crate) mod mangled { pub use super::BeginResult as _7_android_8_hardware_7_keymint_11_BeginResult; }
-          impl Default for BeginResult {
-            fn default() -> Self {
-              Self {
-                challenge: 0,
-                params: Default::default(),
-                operation: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for BeginResult {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for BeginResult {}
-          impl binder::parcel::SerializeOption for BeginResult {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.challenge)?;
-              parcel.write(&this.params)?;
-              let __field_ref = this.operation.as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;
-              parcel.write(__field_ref)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for BeginResult {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for BeginResult {}
-          impl binder::parcel::DeserializeOption for BeginResult {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.challenge = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.params = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.operation = Some(parcel.read()?);
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod BlockMode {
-          #![allow(non_upper_case_globals)]
-          pub type BlockMode = i32;
-          pub const ECB: BlockMode = 1;
-          pub const CBC: BlockMode = 2;
-          pub const CTR: BlockMode = 3;
-          pub const GCM: BlockMode = 32;
-          pub(crate) mod mangled { pub use super::BlockMode as _7_android_8_hardware_7_keymint_9_BlockMode; }
-        }
-        pub mod Certificate {
-          pub struct Certificate {
-            pub encodedCertificate: Vec<u8>, 
-          }
-          pub(crate) mod mangled { pub use super::Certificate as _7_android_8_hardware_7_keymint_11_Certificate; }
-          impl Default for Certificate {
-            fn default() -> Self {
-              Self {
-                encodedCertificate: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for Certificate {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for Certificate {}
-          impl binder::parcel::SerializeOption for Certificate {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.encodedCertificate)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for Certificate {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for Certificate {}
-          impl binder::parcel::DeserializeOption for Certificate {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.encodedCertificate = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod Constants {
-          #![allow(non_upper_case_globals)]
-          pub type Constants = i32;
-          pub const AUTH_TOKEN_MAC_LENGTH: Constants = 32;
-          pub(crate) mod mangled { pub use super::Constants as _7_android_8_hardware_7_keymint_9_Constants; }
-        }
-        pub mod Digest {
-          #![allow(non_upper_case_globals)]
-          pub type Digest = i32;
-          pub const NONE: Digest = 0;
-          pub const MD5: Digest = 1;
-          pub const SHA1: Digest = 2;
-          pub const SHA_2_224: Digest = 3;
-          pub const SHA_2_256: Digest = 4;
-          pub const SHA_2_384: Digest = 5;
-          pub const SHA_2_512: Digest = 6;
-          pub(crate) mod mangled { pub use super::Digest as _7_android_8_hardware_7_keymint_6_Digest; }
-        }
-        pub mod EcCurve {
-          #![allow(non_upper_case_globals)]
-          pub type EcCurve = i32;
-          pub const P_224: EcCurve = 0;
-          pub const P_256: EcCurve = 1;
-          pub const P_384: EcCurve = 2;
-          pub const P_521: EcCurve = 3;
-          pub(crate) mod mangled { pub use super::EcCurve as _7_android_8_hardware_7_keymint_7_EcCurve; }
-        }
-        pub mod ErrorCode {
-          #![allow(non_upper_case_globals)]
-          pub type ErrorCode = i32;
-          pub const OK: ErrorCode = 0;
-          pub const ROOT_OF_TRUST_ALREADY_SET: ErrorCode = -1;
-          pub const UNSUPPORTED_PURPOSE: ErrorCode = -2;
-          pub const INCOMPATIBLE_PURPOSE: ErrorCode = -3;
-          pub const UNSUPPORTED_ALGORITHM: ErrorCode = -4;
-          pub const INCOMPATIBLE_ALGORITHM: ErrorCode = -5;
-          pub const UNSUPPORTED_KEY_SIZE: ErrorCode = -6;
-          pub const UNSUPPORTED_BLOCK_MODE: ErrorCode = -7;
-          pub const INCOMPATIBLE_BLOCK_MODE: ErrorCode = -8;
-          pub const UNSUPPORTED_MAC_LENGTH: ErrorCode = -9;
-          pub const UNSUPPORTED_PADDING_MODE: ErrorCode = -10;
-          pub const INCOMPATIBLE_PADDING_MODE: ErrorCode = -11;
-          pub const UNSUPPORTED_DIGEST: ErrorCode = -12;
-          pub const INCOMPATIBLE_DIGEST: ErrorCode = -13;
-          pub const INVALID_EXPIRATION_TIME: ErrorCode = -14;
-          pub const INVALID_USER_ID: ErrorCode = -15;
-          pub const INVALID_AUTHORIZATION_TIMEOUT: ErrorCode = -16;
-          pub const UNSUPPORTED_KEY_FORMAT: ErrorCode = -17;
-          pub const INCOMPATIBLE_KEY_FORMAT: ErrorCode = -18;
-          pub const UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM: ErrorCode = -19;
-          pub const UNSUPPORTED_KEY_VERIFICATION_ALGORITHM: ErrorCode = -20;
-          pub const INVALID_INPUT_LENGTH: ErrorCode = -21;
-          pub const KEY_EXPORT_OPTIONS_INVALID: ErrorCode = -22;
-          pub const DELEGATION_NOT_ALLOWED: ErrorCode = -23;
-          pub const KEY_NOT_YET_VALID: ErrorCode = -24;
-          pub const KEY_EXPIRED: ErrorCode = -25;
-          pub const KEY_USER_NOT_AUTHENTICATED: ErrorCode = -26;
-          pub const OUTPUT_PARAMETER_NULL: ErrorCode = -27;
-          pub const INVALID_OPERATION_HANDLE: ErrorCode = -28;
-          pub const INSUFFICIENT_BUFFER_SPACE: ErrorCode = -29;
-          pub const VERIFICATION_FAILED: ErrorCode = -30;
-          pub const TOO_MANY_OPERATIONS: ErrorCode = -31;
-          pub const UNEXPECTED_NULL_POINTER: ErrorCode = -32;
-          pub const INVALID_KEY_BLOB: ErrorCode = -33;
-          pub const IMPORTED_KEY_NOT_ENCRYPTED: ErrorCode = -34;
-          pub const IMPORTED_KEY_DECRYPTION_FAILED: ErrorCode = -35;
-          pub const IMPORTED_KEY_NOT_SIGNED: ErrorCode = -36;
-          pub const IMPORTED_KEY_VERIFICATION_FAILED: ErrorCode = -37;
-          pub const INVALID_ARGUMENT: ErrorCode = -38;
-          pub const UNSUPPORTED_TAG: ErrorCode = -39;
-          pub const INVALID_TAG: ErrorCode = -40;
-          pub const MEMORY_ALLOCATION_FAILED: ErrorCode = -41;
-          pub const IMPORT_PARAMETER_MISMATCH: ErrorCode = -44;
-          pub const SECURE_HW_ACCESS_DENIED: ErrorCode = -45;
-          pub const OPERATION_CANCELLED: ErrorCode = -46;
-          pub const CONCURRENT_ACCESS_CONFLICT: ErrorCode = -47;
-          pub const SECURE_HW_BUSY: ErrorCode = -48;
-          pub const SECURE_HW_COMMUNICATION_FAILED: ErrorCode = -49;
-          pub const UNSUPPORTED_EC_FIELD: ErrorCode = -50;
-          pub const MISSING_NONCE: ErrorCode = -51;
-          pub const INVALID_NONCE: ErrorCode = -52;
-          pub const MISSING_MAC_LENGTH: ErrorCode = -53;
-          pub const KEY_RATE_LIMIT_EXCEEDED: ErrorCode = -54;
-          pub const CALLER_NONCE_PROHIBITED: ErrorCode = -55;
-          pub const KEY_MAX_OPS_EXCEEDED: ErrorCode = -56;
-          pub const INVALID_MAC_LENGTH: ErrorCode = -57;
-          pub const MISSING_MIN_MAC_LENGTH: ErrorCode = -58;
-          pub const UNSUPPORTED_MIN_MAC_LENGTH: ErrorCode = -59;
-          pub const UNSUPPORTED_KDF: ErrorCode = -60;
-          pub const UNSUPPORTED_EC_CURVE: ErrorCode = -61;
-          pub const KEY_REQUIRES_UPGRADE: ErrorCode = -62;
-          pub const ATTESTATION_CHALLENGE_MISSING: ErrorCode = -63;
-          pub const KEYMINT_NOT_CONFIGURED: ErrorCode = -64;
-          pub const ATTESTATION_APPLICATION_ID_MISSING: ErrorCode = -65;
-          pub const CANNOT_ATTEST_IDS: ErrorCode = -66;
-          pub const ROLLBACK_RESISTANCE_UNAVAILABLE: ErrorCode = -67;
-          pub const HARDWARE_TYPE_UNAVAILABLE: ErrorCode = -68;
-          pub const PROOF_OF_PRESENCE_REQUIRED: ErrorCode = -69;
-          pub const CONCURRENT_PROOF_OF_PRESENCE_REQUESTED: ErrorCode = -70;
-          pub const NO_USER_CONFIRMATION: ErrorCode = -71;
-          pub const DEVICE_LOCKED: ErrorCode = -72;
-          pub const EARLY_BOOT_ENDED: ErrorCode = -73;
-          pub const ATTESTATION_KEYS_NOT_PROVISIONED: ErrorCode = -74;
-          pub const ATTESTATION_IDS_NOT_PROVISIONED: ErrorCode = -75;
-          pub const INVALID_OPERATION: ErrorCode = -76;
-          pub const STORAGE_KEY_UNSUPPORTED: ErrorCode = -77;
-          pub const UNIMPLEMENTED: ErrorCode = -100;
-          pub const VERSION_MISMATCH: ErrorCode = -101;
-          pub const UNKNOWN_ERROR: ErrorCode = -1000;
-          pub(crate) mod mangled { pub use super::ErrorCode as _7_android_8_hardware_7_keymint_9_ErrorCode; }
-        }
-        pub mod HardwareAuthToken {
-          pub struct HardwareAuthToken {
-            pub challenge: i64, 
-            pub userId: i64, 
-            pub authenticatorId: i64, 
-            pub authenticatorType: crate::mangled::_7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType, 
-            pub timestamp: crate::mangled::_7_android_8_hardware_7_keymint_9_Timestamp, 
-            pub mac: Vec<u8>, 
-          }
-          pub(crate) mod mangled { pub use super::HardwareAuthToken as _7_android_8_hardware_7_keymint_17_HardwareAuthToken; }
-          impl Default for HardwareAuthToken {
-            fn default() -> Self {
-              Self {
-                challenge: 0,
-                userId: 0,
-                authenticatorId: 0,
-                authenticatorType: Default::default(),
-                timestamp: Default::default(),
-                mac: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for HardwareAuthToken {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for HardwareAuthToken {}
-          impl binder::parcel::SerializeOption for HardwareAuthToken {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.challenge)?;
-              parcel.write(&this.userId)?;
-              parcel.write(&this.authenticatorId)?;
-              parcel.write(&this.authenticatorType)?;
-              parcel.write(&this.timestamp)?;
-              parcel.write(&this.mac)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for HardwareAuthToken {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for HardwareAuthToken {}
-          impl binder::parcel::DeserializeOption for HardwareAuthToken {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.challenge = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.userId = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.authenticatorId = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.authenticatorType = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.timestamp = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.mac = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod HardwareAuthenticatorType {
-          #![allow(non_upper_case_globals)]
-          pub type HardwareAuthenticatorType = i32;
-          pub const NONE: HardwareAuthenticatorType = 0;
-          pub const PASSWORD: HardwareAuthenticatorType = 1;
-          pub const FINGERPRINT: HardwareAuthenticatorType = 2;
-          pub const ANY: HardwareAuthenticatorType = -1;
-          pub(crate) mod mangled { pub use super::HardwareAuthenticatorType as _7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType; }
-        }
-        pub mod HmacSharingParameters {
-          pub struct HmacSharingParameters {
-            pub seed: Vec<u8>, 
-            pub nonce: Vec<u8>, 
-          }
-          pub(crate) mod mangled { pub use super::HmacSharingParameters as _7_android_8_hardware_7_keymint_21_HmacSharingParameters; }
-          impl Default for HmacSharingParameters {
-            fn default() -> Self {
-              Self {
-                seed: Default::default(),
-                nonce: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for HmacSharingParameters {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for HmacSharingParameters {}
-          impl binder::parcel::SerializeOption for HmacSharingParameters {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.seed)?;
-              parcel.write(&this.nonce)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for HmacSharingParameters {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for HmacSharingParameters {}
-          impl binder::parcel::DeserializeOption for HmacSharingParameters {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.seed = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.nonce = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod IKeyMintDevice {
-          #![allow(non_upper_case_globals)]
-          #![allow(non_snake_case)]
-          #[allow(unused_imports)] use binder::IBinder;
-          use binder::declare_binder_interface;
-          declare_binder_interface! {
-            IKeyMintDevice["android.hardware.keymint.IKeyMintDevice"] {
-              native: BnKeyMintDevice(on_transact),
-              proxy: BpKeyMintDevice {
-              },
-            }
-          }
-          pub trait IKeyMintDevice: binder::Interface + Send {
-            fn get_descriptor() -> &'static str where Self: Sized { "android.hardware.keymint.IKeyMintDevice" }
-            fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn deleteAllKeys(&self) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn destroyAttestationIds(&self) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
-              DEFAULT_IMPL.lock().unwrap().clone()
-            }
-            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
-              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
-            }
-          }
-          pub const TRANSACTION_getHardwareInfo: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
-          pub const TRANSACTION_verifyAuthorization: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
-          pub const TRANSACTION_addRngEntropy: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
-          pub const TRANSACTION_generateKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
-          pub const TRANSACTION_importKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
-          pub const TRANSACTION_importWrappedKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 5;
-          pub const TRANSACTION_upgradeKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 6;
-          pub const TRANSACTION_deleteKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 7;
-          pub const TRANSACTION_deleteAllKeys: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 8;
-          pub const TRANSACTION_destroyAttestationIds: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 9;
-          pub const TRANSACTION_begin: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 10;
-          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeyMintDevice + Sync>>;
-          use lazy_static::lazy_static;
-          lazy_static! {
-            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
-          }
-          pub(crate) mod mangled { pub use super::IKeyMintDevice as _7_android_8_hardware_7_keymint_14_IKeyMintDevice; }
-          impl IKeyMintDevice for BpKeyMintDevice {
-            fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_getHardwareInfo, 0, |_aidl_data| {
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.getHardwareInfo();
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo = _aidl_reply.read()?;
-              Ok(_aidl_return)
-            }
-            fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_verifyAuthorization, 0, |_aidl_data| {
-                _aidl_data.write(&_arg_challenge)?;
-                _aidl_data.write(_arg_parametersToVerify)?;
-                _aidl_data.write(_arg_token)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.verifyAuthorization(_arg_challenge, _arg_parametersToVerify, _arg_token);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_reply.read()?;
-              Ok(_aidl_return)
-            }
-            fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_addRngEntropy, 0, |_aidl_data| {
-                _aidl_data.write(_arg_data)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.addRngEntropy(_arg_data);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              Ok(())
-            }
-            fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_generateKey, 0, |_aidl_data| {
-                _aidl_data.write(_arg_keyParams)?;
-                _aidl_data.write_slice_size(Some(_arg_generatedKeyBlob))?;
-                _aidl_data.write_slice_size(Some(_arg_outCertChain))?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.generateKey(_arg_keyParams, _arg_generatedKeyBlob, _arg_generatedKeyCharacteristics, _arg_outCertChain);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_generatedKeyBlob = _aidl_reply.read()?;
-              *_arg_generatedKeyCharacteristics = _aidl_reply.read()?;
-              *_arg_outCertChain = _aidl_reply.read()?;
-              Ok(())
-            }
-            fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_importKey, 0, |_aidl_data| {
-                _aidl_data.write(_arg_inKeyParams)?;
-                _aidl_data.write(&_arg_inKeyFormat)?;
-                _aidl_data.write(_arg_inKeyData)?;
-                _aidl_data.write_slice_size(Some(_arg_outImportedKeyBlob))?;
-                _aidl_data.write_slice_size(Some(_arg_outCertChain))?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.importKey(_arg_inKeyParams, _arg_inKeyFormat, _arg_inKeyData, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics, _arg_outCertChain);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_outImportedKeyBlob = _aidl_reply.read()?;
-              *_arg_outImportedKeyCharacteristics = _aidl_reply.read()?;
-              *_arg_outCertChain = _aidl_reply.read()?;
-              Ok(())
-            }
-            fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_importWrappedKey, 0, |_aidl_data| {
-                _aidl_data.write(_arg_inWrappedKeyData)?;
-                _aidl_data.write(_arg_inWrappingKeyBlob)?;
-                _aidl_data.write(_arg_inMaskingKey)?;
-                _aidl_data.write(_arg_inUnwrappingParams)?;
-                _aidl_data.write(&_arg_inPasswordSid)?;
-                _aidl_data.write(&_arg_inBiometricSid)?;
-                _aidl_data.write_slice_size(Some(_arg_outImportedKeyBlob))?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.importWrappedKey(_arg_inWrappedKeyData, _arg_inWrappingKeyBlob, _arg_inMaskingKey, _arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_outImportedKeyBlob = _aidl_reply.read()?;
-              *_arg_outImportedKeyCharacteristics = _aidl_reply.read()?;
-              Ok(())
-            }
-            fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_upgradeKey, 0, |_aidl_data| {
-                _aidl_data.write(_arg_inKeyBlobToUpgrade)?;
-                _aidl_data.write(_arg_inUpgradeParams)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.upgradeKey(_arg_inKeyBlobToUpgrade, _arg_inUpgradeParams);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              let _aidl_return: Vec<u8> = _aidl_reply.read()?;
-              Ok(_aidl_return)
-            }
-            fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_deleteKey, 0, |_aidl_data| {
-                _aidl_data.write(_arg_inKeyBlob)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.deleteKey(_arg_inKeyBlob);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              Ok(())
-            }
-            fn deleteAllKeys(&self) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_deleteAllKeys, 0, |_aidl_data| {
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.deleteAllKeys();
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              Ok(())
-            }
-            fn destroyAttestationIds(&self) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_destroyAttestationIds, 0, |_aidl_data| {
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.destroyAttestationIds();
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              Ok(())
-            }
-            fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_begin, 0, |_aidl_data| {
-                _aidl_data.write(&_arg_inPurpose)?;
-                _aidl_data.write(_arg_inKeyBlob)?;
-                _aidl_data.write(_arg_inParams)?;
-                _aidl_data.write(_arg_inAuthToken)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintDevice>::getDefaultImpl() {
-                  return _aidl_default_impl.begin(_arg_inPurpose, _arg_inKeyBlob, _arg_inParams, _arg_inAuthToken);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              let _aidl_return: crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult = _aidl_reply.read()?;
-              Ok(_aidl_return)
-            }
-          }
-          impl IKeyMintDevice for binder::Binder<BnKeyMintDevice> {
-            fn getHardwareInfo(&self) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo> { self.0.getHardwareInfo() }
-            fn verifyAuthorization(&self, _arg_challenge: i64, _arg_parametersToVerify: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_token: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken> { self.0.verifyAuthorization(_arg_challenge, _arg_parametersToVerify, _arg_token) }
-            fn addRngEntropy(&self, _arg_data: &[u8]) -> binder::public_api::Result<()> { self.0.addRngEntropy(_arg_data) }
-            fn generateKey(&self, _arg_keyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_generatedKeyBlob: &mut Vec<u8>, _arg_generatedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> { self.0.generateKey(_arg_keyParams, _arg_generatedKeyBlob, _arg_generatedKeyCharacteristics, _arg_outCertChain) }
-            fn importKey(&self, _arg_inKeyParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat, _arg_inKeyData: &[u8], _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics, _arg_outCertChain: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate>) -> binder::public_api::Result<()> { self.0.importKey(_arg_inKeyParams, _arg_inKeyFormat, _arg_inKeyData, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics, _arg_outCertChain) }
-            fn importWrappedKey(&self, _arg_inWrappedKeyData: &[u8], _arg_inWrappingKeyBlob: &[u8], _arg_inMaskingKey: &[u8], _arg_inUnwrappingParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inPasswordSid: i64, _arg_inBiometricSid: i64, _arg_outImportedKeyBlob: &mut Vec<u8>, _arg_outImportedKeyCharacteristics: &mut crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics) -> binder::public_api::Result<()> { self.0.importWrappedKey(_arg_inWrappedKeyData, _arg_inWrappingKeyBlob, _arg_inMaskingKey, _arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, _arg_outImportedKeyBlob, _arg_outImportedKeyCharacteristics) }
-            fn upgradeKey(&self, _arg_inKeyBlobToUpgrade: &[u8], _arg_inUpgradeParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter]) -> binder::public_api::Result<Vec<u8>> { self.0.upgradeKey(_arg_inKeyBlobToUpgrade, _arg_inUpgradeParams) }
-            fn deleteKey(&self, _arg_inKeyBlob: &[u8]) -> binder::public_api::Result<()> { self.0.deleteKey(_arg_inKeyBlob) }
-            fn deleteAllKeys(&self) -> binder::public_api::Result<()> { self.0.deleteAllKeys() }
-            fn destroyAttestationIds(&self) -> binder::public_api::Result<()> { self.0.destroyAttestationIds() }
-            fn begin(&self, _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose, _arg_inKeyBlob: &[u8], _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_inAuthToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken) -> binder::public_api::Result<crate::mangled::_7_android_8_hardware_7_keymint_11_BeginResult> { self.0.begin(_arg_inPurpose, _arg_inKeyBlob, _arg_inParams, _arg_inAuthToken) }
-          }
-          fn on_transact(_aidl_service: &dyn IKeyMintDevice, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
-            match _aidl_code {
-              TRANSACTION_getHardwareInfo => {
-                let _aidl_return = _aidl_service.getHardwareInfo();
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(_aidl_return)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_verifyAuthorization => {
-                let _arg_challenge: i64 = _aidl_data.read()?;
-                let _arg_parametersToVerify: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_token: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.verifyAuthorization(_arg_challenge, &_arg_parametersToVerify, &_arg_token);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(_aidl_return)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_addRngEntropy => {
-                let _arg_data: Vec<u8> = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.addRngEntropy(&_arg_data);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_generateKey => {
-                let _arg_keyParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let mut _arg_generatedKeyBlob: Vec<u8> = Default::default();
-                _aidl_data.resize_out_vec(&mut _arg_generatedKeyBlob)?;
-                let mut _arg_generatedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
-                let mut _arg_outCertChain: Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate> = Default::default();
-                _aidl_data.resize_out_vec(&mut _arg_outCertChain)?;
-                let _aidl_return = _aidl_service.generateKey(&_arg_keyParams, &mut _arg_generatedKeyBlob, &mut _arg_generatedKeyCharacteristics, &mut _arg_outCertChain);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_generatedKeyBlob)?;
-                    _aidl_reply.write(&_arg_generatedKeyCharacteristics)?;
-                    _aidl_reply.write(&_arg_outCertChain)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_importKey => {
-                let _arg_inKeyParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_inKeyFormat: crate::mangled::_7_android_8_hardware_7_keymint_9_KeyFormat = _aidl_data.read()?;
-                let _arg_inKeyData: Vec<u8> = _aidl_data.read()?;
-                let mut _arg_outImportedKeyBlob: Vec<u8> = Default::default();
-                _aidl_data.resize_out_vec(&mut _arg_outImportedKeyBlob)?;
-                let mut _arg_outImportedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
-                let mut _arg_outCertChain: Vec<crate::mangled::_7_android_8_hardware_7_keymint_11_Certificate> = Default::default();
-                _aidl_data.resize_out_vec(&mut _arg_outCertChain)?;
-                let _aidl_return = _aidl_service.importKey(&_arg_inKeyParams, _arg_inKeyFormat, &_arg_inKeyData, &mut _arg_outImportedKeyBlob, &mut _arg_outImportedKeyCharacteristics, &mut _arg_outCertChain);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_outImportedKeyBlob)?;
-                    _aidl_reply.write(&_arg_outImportedKeyCharacteristics)?;
-                    _aidl_reply.write(&_arg_outCertChain)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_importWrappedKey => {
-                let _arg_inWrappedKeyData: Vec<u8> = _aidl_data.read()?;
-                let _arg_inWrappingKeyBlob: Vec<u8> = _aidl_data.read()?;
-                let _arg_inMaskingKey: Vec<u8> = _aidl_data.read()?;
-                let _arg_inUnwrappingParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_inPasswordSid: i64 = _aidl_data.read()?;
-                let _arg_inBiometricSid: i64 = _aidl_data.read()?;
-                let mut _arg_outImportedKeyBlob: Vec<u8> = Default::default();
-                _aidl_data.resize_out_vec(&mut _arg_outImportedKeyBlob)?;
-                let mut _arg_outImportedKeyCharacteristics: crate::mangled::_7_android_8_hardware_7_keymint_18_KeyCharacteristics = Default::default();
-                let _aidl_return = _aidl_service.importWrappedKey(&_arg_inWrappedKeyData, &_arg_inWrappingKeyBlob, &_arg_inMaskingKey, &_arg_inUnwrappingParams, _arg_inPasswordSid, _arg_inBiometricSid, &mut _arg_outImportedKeyBlob, &mut _arg_outImportedKeyCharacteristics);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_outImportedKeyBlob)?;
-                    _aidl_reply.write(&_arg_outImportedKeyCharacteristics)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_upgradeKey => {
-                let _arg_inKeyBlobToUpgrade: Vec<u8> = _aidl_data.read()?;
-                let _arg_inUpgradeParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.upgradeKey(&_arg_inKeyBlobToUpgrade, &_arg_inUpgradeParams);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(_aidl_return)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_deleteKey => {
-                let _arg_inKeyBlob: Vec<u8> = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.deleteKey(&_arg_inKeyBlob);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_deleteAllKeys => {
-                let _aidl_return = _aidl_service.deleteAllKeys();
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_destroyAttestationIds => {
-                let _aidl_return = _aidl_service.destroyAttestationIds();
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_begin => {
-                let _arg_inPurpose: crate::mangled::_7_android_8_hardware_7_keymint_10_KeyPurpose = _aidl_data.read()?;
-                let _arg_inKeyBlob: Vec<u8> = _aidl_data.read()?;
-                let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_inAuthToken: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.begin(_arg_inPurpose, &_arg_inKeyBlob, &_arg_inParams, &_arg_inAuthToken);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(_aidl_return)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
-            }
-          }
-        }
-        pub mod IKeyMintOperation {
-          #![allow(non_upper_case_globals)]
-          #![allow(non_snake_case)]
-          #[allow(unused_imports)] use binder::IBinder;
-          use binder::declare_binder_interface;
-          declare_binder_interface! {
-            IKeyMintOperation["android.hardware.keymint.IKeyMintOperation"] {
-              native: BnKeyMintOperation(on_transact),
-              proxy: BpKeyMintOperation {
-              },
-            }
-          }
-          pub trait IKeyMintOperation: binder::Interface + Send {
-            fn get_descriptor() -> &'static str where Self: Sized { "android.hardware.keymint.IKeyMintOperation" }
-            fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn abort(&self) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
-              DEFAULT_IMPL.lock().unwrap().clone()
-            }
-            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
-              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
-            }
-          }
-          pub const TRANSACTION_update: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
-          pub const TRANSACTION_finish: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
-          pub const TRANSACTION_abort: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
-          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeyMintOperation + Sync>>;
-          use lazy_static::lazy_static;
-          lazy_static! {
-            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
-          }
-          pub(crate) mod mangled { pub use super::IKeyMintOperation as _7_android_8_hardware_7_keymint_17_IKeyMintOperation; }
-          impl IKeyMintOperation for BpKeyMintOperation {
-            fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_update, 0, |_aidl_data| {
-                _aidl_data.write(_arg_inParams)?;
-                _aidl_data.write(_arg_input)?;
-                _aidl_data.write(_arg_inVerificationToken)?;
-                _aidl_data.write_slice_size(Some(_arg_outParams))?;
-                _aidl_data.write_slice_size(Some(_arg_output))?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
-                  return _aidl_default_impl.update(_arg_inParams, _arg_input, _arg_inVerificationToken, _arg_outParams, _arg_output);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              let _aidl_return: i32 = _aidl_reply.read()?;
-              *_arg_outParams = _aidl_reply.read()?;
-              *_arg_output = _aidl_reply.read()?;
-              Ok(_aidl_return)
-            }
-            fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_finish, 0, |_aidl_data| {
-                _aidl_data.write(_arg_inParams)?;
-                _aidl_data.write(_arg_input)?;
-                _aidl_data.write(_arg_inSignature)?;
-                _aidl_data.write(_arg_authToken)?;
-                _aidl_data.write(_arg_inVerificationToken)?;
-                _aidl_data.write_slice_size(Some(_arg_outParams))?;
-                _aidl_data.write_slice_size(Some(_arg_output))?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
-                  return _aidl_default_impl.finish(_arg_inParams, _arg_input, _arg_inSignature, _arg_authToken, _arg_inVerificationToken, _arg_outParams, _arg_output);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_outParams = _aidl_reply.read()?;
-              *_arg_output = _aidl_reply.read()?;
-              Ok(())
-            }
-            fn abort(&self) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_abort, 0, |_aidl_data| {
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeyMintOperation>::getDefaultImpl() {
-                  return _aidl_default_impl.abort();
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              Ok(())
-            }
-          }
-          impl IKeyMintOperation for binder::Binder<BnKeyMintOperation> {
-            fn update(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<i32> { self.0.update(_arg_inParams, _arg_input, _arg_inVerificationToken, _arg_outParams, _arg_output) }
-            fn finish(&self, _arg_inParams: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_input: &[u8], _arg_inSignature: &[u8], _arg_authToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken, _arg_inVerificationToken: &crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken, _arg_outParams: &mut Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, _arg_output: &mut Vec<u8>) -> binder::public_api::Result<()> { self.0.finish(_arg_inParams, _arg_input, _arg_inSignature, _arg_authToken, _arg_inVerificationToken, _arg_outParams, _arg_output) }
-            fn abort(&self) -> binder::public_api::Result<()> { self.0.abort() }
-          }
-          fn on_transact(_aidl_service: &dyn IKeyMintOperation, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
-            match _aidl_code {
-              TRANSACTION_update => {
-                let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_input: Vec<u8> = _aidl_data.read()?;
-                let _arg_inVerificationToken: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_data.read()?;
-                let mut _arg_outParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = Default::default();
-                _aidl_data.resize_out_vec(&mut _arg_outParams)?;
-                let mut _arg_output: Vec<u8> = Default::default();
-                _aidl_data.resize_out_vec(&mut _arg_output)?;
-                let _aidl_return = _aidl_service.update(&_arg_inParams, &_arg_input, &_arg_inVerificationToken, &mut _arg_outParams, &mut _arg_output);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(_aidl_return)?;
-                    _aidl_reply.write(&_arg_outParams)?;
-                    _aidl_reply.write(&_arg_output)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_finish => {
-                let _arg_inParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_input: Vec<u8> = _aidl_data.read()?;
-                let _arg_inSignature: Vec<u8> = _aidl_data.read()?;
-                let _arg_authToken: crate::mangled::_7_android_8_hardware_7_keymint_17_HardwareAuthToken = _aidl_data.read()?;
-                let _arg_inVerificationToken: crate::mangled::_7_android_8_hardware_7_keymint_17_VerificationToken = _aidl_data.read()?;
-                let mut _arg_outParams: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = Default::default();
-                _aidl_data.resize_out_vec(&mut _arg_outParams)?;
-                let mut _arg_output: Vec<u8> = Default::default();
-                _aidl_data.resize_out_vec(&mut _arg_output)?;
-                let _aidl_return = _aidl_service.finish(&_arg_inParams, &_arg_input, &_arg_inSignature, &_arg_authToken, &_arg_inVerificationToken, &mut _arg_outParams, &mut _arg_output);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_outParams)?;
-                    _aidl_reply.write(&_arg_output)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_abort => {
-                let _aidl_return = _aidl_service.abort();
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
-            }
-          }
-        }
-        pub mod KeyCharacteristics {
-          pub struct KeyCharacteristics {
-            pub softwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
-            pub hardwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
-          }
-          pub(crate) mod mangled { pub use super::KeyCharacteristics as _7_android_8_hardware_7_keymint_18_KeyCharacteristics; }
-          impl Default for KeyCharacteristics {
-            fn default() -> Self {
-              Self {
-                softwareEnforced: Default::default(),
-                hardwareEnforced: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for KeyCharacteristics {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for KeyCharacteristics {}
-          impl binder::parcel::SerializeOption for KeyCharacteristics {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.softwareEnforced)?;
-              parcel.write(&this.hardwareEnforced)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for KeyCharacteristics {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for KeyCharacteristics {}
-          impl binder::parcel::DeserializeOption for KeyCharacteristics {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.softwareEnforced = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.hardwareEnforced = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod KeyDerivationFunction {
-          #![allow(non_upper_case_globals)]
-          pub type KeyDerivationFunction = i32;
-          pub const NONE: KeyDerivationFunction = 0;
-          pub const RFC5869_SHA256: KeyDerivationFunction = 1;
-          pub const ISO18033_2_KDF1_SHA1: KeyDerivationFunction = 2;
-          pub const ISO18033_2_KDF1_SHA256: KeyDerivationFunction = 3;
-          pub const ISO18033_2_KDF2_SHA1: KeyDerivationFunction = 4;
-          pub const ISO18033_2_KDF2_SHA256: KeyDerivationFunction = 5;
-          pub(crate) mod mangled { pub use super::KeyDerivationFunction as _7_android_8_hardware_7_keymint_21_KeyDerivationFunction; }
-        }
-        pub mod KeyFormat {
-          #![allow(non_upper_case_globals)]
-          pub type KeyFormat = i32;
-          pub const X509: KeyFormat = 0;
-          pub const PKCS8: KeyFormat = 1;
-          pub const RAW: KeyFormat = 3;
-          pub(crate) mod mangled { pub use super::KeyFormat as _7_android_8_hardware_7_keymint_9_KeyFormat; }
-        }
-        pub mod KeyMintHardwareInfo {
-          pub struct KeyMintHardwareInfo {
-            pub versionNumber: i32, 
-            pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, 
-            pub keyMintName: String, 
-            pub keyMintAuthorName: String, 
-          }
-          pub(crate) mod mangled { pub use super::KeyMintHardwareInfo as _7_android_8_hardware_7_keymint_19_KeyMintHardwareInfo; }
-          impl Default for KeyMintHardwareInfo {
-            fn default() -> Self {
-              Self {
-                versionNumber: 0,
-                securityLevel: Default::default(),
-                keyMintName: Default::default(),
-                keyMintAuthorName: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for KeyMintHardwareInfo {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for KeyMintHardwareInfo {}
-          impl binder::parcel::SerializeOption for KeyMintHardwareInfo {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.versionNumber)?;
-              parcel.write(&this.securityLevel)?;
-              parcel.write(&this.keyMintName)?;
-              parcel.write(&this.keyMintAuthorName)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for KeyMintHardwareInfo {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for KeyMintHardwareInfo {}
-          impl binder::parcel::DeserializeOption for KeyMintHardwareInfo {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.versionNumber = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.securityLevel = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.keyMintName = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.keyMintAuthorName = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod KeyOrigin {
-          #![allow(non_upper_case_globals)]
-          pub type KeyOrigin = i32;
-          pub const GENERATED: KeyOrigin = 0;
-          pub const DERIVED: KeyOrigin = 1;
-          pub const IMPORTED: KeyOrigin = 2;
-          pub const RESERVED: KeyOrigin = 3;
-          pub const SECURELY_IMPORTED: KeyOrigin = 4;
-          pub(crate) mod mangled { pub use super::KeyOrigin as _7_android_8_hardware_7_keymint_9_KeyOrigin; }
-        }
-        pub mod KeyParameter {
-          pub struct KeyParameter {
-            pub tag: crate::mangled::_7_android_8_hardware_7_keymint_3_Tag, 
-            pub boolValue: bool, 
-            pub integer: i32, 
-            pub longInteger: i64, 
-            pub dateTime: i64, 
-            pub blob: Vec<u8>, 
-          }
-          pub(crate) mod mangled { pub use super::KeyParameter as _7_android_8_hardware_7_keymint_12_KeyParameter; }
-          impl Default for KeyParameter {
-            fn default() -> Self {
-              Self {
-                tag: Default::default(),
-                boolValue: false,
-                integer: 0,
-                longInteger: 0,
-                dateTime: 0,
-                blob: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for KeyParameter {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for KeyParameter {}
-          impl binder::parcel::SerializeOption for KeyParameter {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.tag)?;
-              parcel.write(&this.boolValue)?;
-              parcel.write(&this.integer)?;
-              parcel.write(&this.longInteger)?;
-              parcel.write(&this.dateTime)?;
-              parcel.write(&this.blob)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for KeyParameter {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for KeyParameter {}
-          impl binder::parcel::DeserializeOption for KeyParameter {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.tag = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.boolValue = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.integer = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.longInteger = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.dateTime = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.blob = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod KeyPurpose {
-          #![allow(non_upper_case_globals)]
-          pub type KeyPurpose = i32;
-          pub const ENCRYPT: KeyPurpose = 0;
-          pub const DECRYPT: KeyPurpose = 1;
-          pub const SIGN: KeyPurpose = 2;
-          pub const VERIFY: KeyPurpose = 3;
-          pub const WRAP_KEY: KeyPurpose = 5;
-          pub(crate) mod mangled { pub use super::KeyPurpose as _7_android_8_hardware_7_keymint_10_KeyPurpose; }
-        }
-        pub mod PaddingMode {
-          #![allow(non_upper_case_globals)]
-          pub type PaddingMode = i32;
-          pub const NONE: PaddingMode = 1;
-          pub const RSA_OAEP: PaddingMode = 2;
-          pub const RSA_PSS: PaddingMode = 3;
-          pub const RSA_PKCS1_1_5_ENCRYPT: PaddingMode = 4;
-          pub const RSA_PKCS1_1_5_SIGN: PaddingMode = 5;
-          pub const PKCS7: PaddingMode = 64;
-          pub(crate) mod mangled { pub use super::PaddingMode as _7_android_8_hardware_7_keymint_11_PaddingMode; }
-        }
-        pub mod SecurityLevel {
-          #![allow(non_upper_case_globals)]
-          pub type SecurityLevel = i32;
-          pub const SOFTWARE: SecurityLevel = 0;
-          pub const TRUSTED_ENVIRONMENT: SecurityLevel = 1;
-          pub const STRONGBOX: SecurityLevel = 2;
-          pub(crate) mod mangled { pub use super::SecurityLevel as _7_android_8_hardware_7_keymint_13_SecurityLevel; }
-        }
-        pub mod Tag {
-          #![allow(non_upper_case_globals)]
-          pub type Tag = i32;
-          pub const INVALID: Tag = 0;
-          pub const PURPOSE: Tag = 536870913;
-          pub const ALGORITHM: Tag = 268435458;
-          pub const KEY_SIZE: Tag = 805306371;
-          pub const BLOCK_MODE: Tag = 536870916;
-          pub const DIGEST: Tag = 536870917;
-          pub const PADDING: Tag = 536870918;
-          pub const CALLER_NONCE: Tag = 1879048199;
-          pub const MIN_MAC_LENGTH: Tag = 805306376;
-          pub const EC_CURVE: Tag = 268435466;
-          pub const RSA_PUBLIC_EXPONENT: Tag = 1342177480;
-          pub const INCLUDE_UNIQUE_ID: Tag = 1879048394;
-          pub const BLOB_USAGE_REQUIREMENTS: Tag = 268435757;
-          pub const BOOTLOADER_ONLY: Tag = 1879048494;
-          pub const ROLLBACK_RESISTANCE: Tag = 1879048495;
-          pub const HARDWARE_TYPE: Tag = 268435760;
-          pub const EARLY_BOOT_ONLY: Tag = 1879048497;
-          pub const ACTIVE_DATETIME: Tag = 1610613136;
-          pub const ORIGINATION_EXPIRE_DATETIME: Tag = 1610613137;
-          pub const USAGE_EXPIRE_DATETIME: Tag = 1610613138;
-          pub const MIN_SECONDS_BETWEEN_OPS: Tag = 805306771;
-          pub const MAX_USES_PER_BOOT: Tag = 805306772;
-          pub const USER_ID: Tag = 805306869;
-          pub const USER_SECURE_ID: Tag = 1073742326;
-          pub const NO_AUTH_REQUIRED: Tag = 1879048695;
-          pub const USER_AUTH_TYPE: Tag = 268435960;
-          pub const AUTH_TIMEOUT: Tag = 805306873;
-          pub const ALLOW_WHILE_ON_BODY: Tag = 1879048698;
-          pub const TRUSTED_USER_PRESENCE_REQUIRED: Tag = 1879048699;
-          pub const TRUSTED_CONFIRMATION_REQUIRED: Tag = 1879048700;
-          pub const UNLOCKED_DEVICE_REQUIRED: Tag = 1879048701;
-          pub const APPLICATION_ID: Tag = -1879047591;
-          pub const APPLICATION_DATA: Tag = -1879047492;
-          pub const CREATION_DATETIME: Tag = 1610613437;
-          pub const ORIGIN: Tag = 268436158;
-          pub const ROOT_OF_TRUST: Tag = -1879047488;
-          pub const OS_VERSION: Tag = 805307073;
-          pub const OS_PATCHLEVEL: Tag = 805307074;
-          pub const UNIQUE_ID: Tag = -1879047485;
-          pub const ATTESTATION_CHALLENGE: Tag = -1879047484;
-          pub const ATTESTATION_APPLICATION_ID: Tag = -1879047483;
-          pub const ATTESTATION_ID_BRAND: Tag = -1879047482;
-          pub const ATTESTATION_ID_DEVICE: Tag = -1879047481;
-          pub const ATTESTATION_ID_PRODUCT: Tag = -1879047480;
-          pub const ATTESTATION_ID_SERIAL: Tag = -1879047479;
-          pub const ATTESTATION_ID_IMEI: Tag = -1879047478;
-          pub const ATTESTATION_ID_MEID: Tag = -1879047477;
-          pub const ATTESTATION_ID_MANUFACTURER: Tag = -1879047476;
-          pub const ATTESTATION_ID_MODEL: Tag = -1879047475;
-          pub const VENDOR_PATCHLEVEL: Tag = 805307086;
-          pub const BOOT_PATCHLEVEL: Tag = 805307087;
-          pub const DEVICE_UNIQUE_ATTESTATION: Tag = 1879048912;
-          pub const IDENTITY_CREDENTIAL_KEY: Tag = 1879048913;
-          pub const STORAGE_KEY: Tag = 1879048914;
-          pub const ASSOCIATED_DATA: Tag = -1879047192;
-          pub const NONCE: Tag = -1879047191;
-          pub const MAC_LENGTH: Tag = 805307371;
-          pub const RESET_SINCE_ID_ROTATION: Tag = 1879049196;
-          pub const CONFIRMATION_TOKEN: Tag = -1879047187;
-          pub(crate) mod mangled { pub use super::Tag as _7_android_8_hardware_7_keymint_3_Tag; }
-        }
-        pub mod TagType {
-          #![allow(non_upper_case_globals)]
-          pub type TagType = i32;
-          pub const INVALID: TagType = 0;
-          pub const ENUM: TagType = 268435456;
-          pub const ENUM_REP: TagType = 536870912;
-          pub const UINT: TagType = 805306368;
-          pub const UINT_REP: TagType = 1073741824;
-          pub const ULONG: TagType = 1342177280;
-          pub const DATE: TagType = 1610612736;
-          pub const BOOL: TagType = 1879048192;
-          pub const BIGNUM: TagType = -2147483648;
-          pub const BYTES: TagType = -1879048192;
-          pub const ULONG_REP: TagType = -1610612736;
-          pub(crate) mod mangled { pub use super::TagType as _7_android_8_hardware_7_keymint_7_TagType; }
-        }
-        pub mod Timestamp {
-          pub struct Timestamp {
-            pub milliSeconds: i64, 
-          }
-          pub(crate) mod mangled { pub use super::Timestamp as _7_android_8_hardware_7_keymint_9_Timestamp; }
-          impl Default for Timestamp {
-            fn default() -> Self {
-              Self {
-                milliSeconds: 0,
-              }
-            }
-          }
-          impl binder::parcel::Serialize for Timestamp {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for Timestamp {}
-          impl binder::parcel::SerializeOption for Timestamp {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.milliSeconds)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for Timestamp {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for Timestamp {}
-          impl binder::parcel::DeserializeOption for Timestamp {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.milliSeconds = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod VerificationToken {
-          pub struct VerificationToken {
-            pub challenge: i64, 
-            pub timestamp: crate::mangled::_7_android_8_hardware_7_keymint_9_Timestamp, 
-            pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, 
-            pub mac: Vec<u8>, 
-          }
-          pub(crate) mod mangled { pub use super::VerificationToken as _7_android_8_hardware_7_keymint_17_VerificationToken; }
-          impl Default for VerificationToken {
-            fn default() -> Self {
-              Self {
-                challenge: 0,
-                timestamp: Default::default(),
-                securityLevel: Default::default(),
-                mac: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for VerificationToken {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for VerificationToken {}
-          impl binder::parcel::SerializeOption for VerificationToken {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.challenge)?;
-              parcel.write(&this.timestamp)?;
-              parcel.write(&this.securityLevel)?;
-              parcel.write(&this.mac)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for VerificationToken {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for VerificationToken {}
-          impl binder::parcel::DeserializeOption for VerificationToken {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.challenge = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.timestamp = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.securityLevel = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.mac = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-      }
-    }
-  }
-}
-pub mod mangled {
-  pub use super::aidl::android::hardware::keymint::Algorithm::mangled::*;
-  pub use super::aidl::android::hardware::keymint::BeginResult::mangled::*;
-  pub use super::aidl::android::hardware::keymint::BlockMode::mangled::*;
-  pub use super::aidl::android::hardware::keymint::Certificate::mangled::*;
-  pub use super::aidl::android::hardware::keymint::Constants::mangled::*;
-  pub use super::aidl::android::hardware::keymint::Digest::mangled::*;
-  pub use super::aidl::android::hardware::keymint::EcCurve::mangled::*;
-  pub use super::aidl::android::hardware::keymint::ErrorCode::mangled::*;
-  pub use super::aidl::android::hardware::keymint::HardwareAuthToken::mangled::*;
-  pub use super::aidl::android::hardware::keymint::HardwareAuthenticatorType::mangled::*;
-  pub use super::aidl::android::hardware::keymint::HmacSharingParameters::mangled::*;
-  pub use super::aidl::android::hardware::keymint::IKeyMintDevice::mangled::*;
-  pub use super::aidl::android::hardware::keymint::IKeyMintOperation::mangled::*;
-  pub use super::aidl::android::hardware::keymint::KeyCharacteristics::mangled::*;
-  pub use super::aidl::android::hardware::keymint::KeyDerivationFunction::mangled::*;
-  pub use super::aidl::android::hardware::keymint::KeyFormat::mangled::*;
-  pub use super::aidl::android::hardware::keymint::KeyMintHardwareInfo::mangled::*;
-  pub use super::aidl::android::hardware::keymint::KeyOrigin::mangled::*;
-  pub use super::aidl::android::hardware::keymint::KeyParameter::mangled::*;
-  pub use super::aidl::android::hardware::keymint::KeyPurpose::mangled::*;
-  pub use super::aidl::android::hardware::keymint::PaddingMode::mangled::*;
-  pub use super::aidl::android::hardware::keymint::SecurityLevel::mangled::*;
-  pub use super::aidl::android::hardware::keymint::Tag::mangled::*;
-  pub use super::aidl::android::hardware::keymint::TagType::mangled::*;
-  pub use super::aidl::android::hardware::keymint::Timestamp::mangled::*;
-  pub use super::aidl::android::hardware::keymint::VerificationToken::mangled::*;
-}
diff --git a/keystore2/src/android_security_keystore2.rs b/keystore2/src/android_security_keystore2.rs
deleted file mode 100644
index d22a593..0000000
--- a/keystore2/src/android_security_keystore2.rs
+++ /dev/null
@@ -1,1143 +0,0 @@
-#![allow(non_snake_case)]
-#![allow(missing_docs)]
-#![allow(clippy::identity_op)]
-#![allow(clippy::excessive_precision)]
-#![allow(clippy::too_many_arguments)]
-pub use binder::public_api as binder;
-pub mod aidl {
-  pub mod android {
-    pub mod security {
-      pub mod keystore2 {
-        pub mod AuthenticatorSpec {
-          pub struct AuthenticatorSpec {
-            pub authenticatorType: crate::mangled::_7_android_8_hardware_7_keymint_25_HardwareAuthenticatorType, 
-            pub authenticatorId: i64, 
-          }
-          pub(crate) mod mangled { pub use super::AuthenticatorSpec as _7_android_8_security_9_keystore2_17_AuthenticatorSpec; }
-          impl Default for AuthenticatorSpec {
-            fn default() -> Self {
-              Self {
-                authenticatorType: Default::default(),
-                authenticatorId: 0,
-              }
-            }
-          }
-          impl binder::parcel::Serialize for AuthenticatorSpec {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for AuthenticatorSpec {}
-          impl binder::parcel::SerializeOption for AuthenticatorSpec {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.authenticatorType)?;
-              parcel.write(&this.authenticatorId)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for AuthenticatorSpec {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for AuthenticatorSpec {}
-          impl binder::parcel::DeserializeOption for AuthenticatorSpec {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.authenticatorType = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.authenticatorId = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod Certificate {
-          pub struct Certificate {
-            pub data: Vec<u8>, 
-          }
-          pub(crate) mod mangled { pub use super::Certificate as _7_android_8_security_9_keystore2_11_Certificate; }
-          impl Default for Certificate {
-            fn default() -> Self {
-              Self {
-                data: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for Certificate {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for Certificate {}
-          impl binder::parcel::SerializeOption for Certificate {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.data)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for Certificate {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for Certificate {}
-          impl binder::parcel::DeserializeOption for Certificate {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.data = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod CertificateChain {
-          pub struct CertificateChain {
-            pub data: Vec<u8>, 
-          }
-          pub(crate) mod mangled { pub use super::CertificateChain as _7_android_8_security_9_keystore2_16_CertificateChain; }
-          impl Default for CertificateChain {
-            fn default() -> Self {
-              Self {
-                data: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for CertificateChain {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for CertificateChain {}
-          impl binder::parcel::SerializeOption for CertificateChain {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.data)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for CertificateChain {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for CertificateChain {}
-          impl binder::parcel::DeserializeOption for CertificateChain {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.data = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod Domain {
-          #![allow(non_upper_case_globals)]
-          pub type Domain = i32;
-          pub const App: Domain = 0;
-          pub const Grant: Domain = 1;
-          pub const SELinux: Domain = 2;
-          pub const Blob: Domain = 3;
-          pub const KeyId: Domain = 4;
-          pub(crate) mod mangled { pub use super::Domain as _7_android_8_security_9_keystore2_6_Domain; }
-        }
-        pub mod IKeystoreOperation {
-          #![allow(non_upper_case_globals)]
-          #![allow(non_snake_case)]
-          #[allow(unused_imports)] use binder::IBinder;
-          use binder::declare_binder_interface;
-          declare_binder_interface! {
-            IKeystoreOperation["android.security.keystore2.IKeystoreOperation"] {
-              native: BnKeystoreOperation(on_transact),
-              proxy: BpKeystoreOperation {
-              },
-            }
-          }
-          pub trait IKeystoreOperation: binder::Interface + Send {
-            fn get_descriptor() -> &'static str where Self: Sized { "android.security.keystore2.IKeystoreOperation" }
-            fn update(&self, _arg_input: Option<&[u8]>, _arg_aadInput: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn finish(&self, _arg_input: Option<&[u8]>, _arg_signature: Option<&[u8]>, _arg_entropy: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn abort(&self) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
-              DEFAULT_IMPL.lock().unwrap().clone()
-            }
-            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
-              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
-            }
-          }
-          pub const TRANSACTION_update: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
-          pub const TRANSACTION_finish: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
-          pub const TRANSACTION_abort: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
-          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeystoreOperation + Sync>>;
-          use lazy_static::lazy_static;
-          lazy_static! {
-            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
-          }
-          pub(crate) mod mangled { pub use super::IKeystoreOperation as _7_android_8_security_9_keystore2_18_IKeystoreOperation; }
-          impl IKeystoreOperation for BpKeystoreOperation {
-            fn update(&self, _arg_input: Option<&[u8]>, _arg_aadInput: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_update, 0, |_aidl_data| {
-                _aidl_data.write(&_arg_input)?;
-                _aidl_data.write(&_arg_aadInput)?;
-                _aidl_data.write_slice_size(_arg_output.as_deref())?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreOperation>::getDefaultImpl() {
-                  return _aidl_default_impl.update(_arg_input, _arg_aadInput, _arg_output);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_output = _aidl_reply.read()?;
-              Ok(())
-            }
-            fn finish(&self, _arg_input: Option<&[u8]>, _arg_signature: Option<&[u8]>, _arg_entropy: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_finish, 0, |_aidl_data| {
-                _aidl_data.write(&_arg_input)?;
-                _aidl_data.write(&_arg_signature)?;
-                _aidl_data.write(&_arg_entropy)?;
-                _aidl_data.write_slice_size(_arg_output.as_deref())?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreOperation>::getDefaultImpl() {
-                  return _aidl_default_impl.finish(_arg_input, _arg_signature, _arg_entropy, _arg_output);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_output = _aidl_reply.read()?;
-              Ok(())
-            }
-            fn abort(&self) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_abort, 0, |_aidl_data| {
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreOperation>::getDefaultImpl() {
-                  return _aidl_default_impl.abort();
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              Ok(())
-            }
-          }
-          impl IKeystoreOperation for binder::Binder<BnKeystoreOperation> {
-            fn update(&self, _arg_input: Option<&[u8]>, _arg_aadInput: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> { self.0.update(_arg_input, _arg_aadInput, _arg_output) }
-            fn finish(&self, _arg_input: Option<&[u8]>, _arg_signature: Option<&[u8]>, _arg_entropy: Option<&[u8]>, _arg_output: &mut Option<Vec<u8>>) -> binder::public_api::Result<()> { self.0.finish(_arg_input, _arg_signature, _arg_entropy, _arg_output) }
-            fn abort(&self) -> binder::public_api::Result<()> { self.0.abort() }
-          }
-          fn on_transact(_aidl_service: &dyn IKeystoreOperation, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
-            match _aidl_code {
-              TRANSACTION_update => {
-                let _arg_input: Option<Vec<u8>> = _aidl_data.read()?;
-                let _arg_aadInput: Option<Vec<u8>> = _aidl_data.read()?;
-                let mut _arg_output: Option<Vec<u8>> = Default::default();
-                _aidl_data.resize_nullable_out_vec(&mut _arg_output)?;
-                let _aidl_return = _aidl_service.update(_arg_input.as_deref(), _arg_aadInput.as_deref(), &mut _arg_output);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_output)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_finish => {
-                let _arg_input: Option<Vec<u8>> = _aidl_data.read()?;
-                let _arg_signature: Option<Vec<u8>> = _aidl_data.read()?;
-                let _arg_entropy: Option<Vec<u8>> = _aidl_data.read()?;
-                let mut _arg_output: Option<Vec<u8>> = Default::default();
-                _aidl_data.resize_nullable_out_vec(&mut _arg_output)?;
-                let _aidl_return = _aidl_service.finish(_arg_input.as_deref(), _arg_signature.as_deref(), _arg_entropy.as_deref(), &mut _arg_output);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_output)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_abort => {
-                let _aidl_return = _aidl_service.abort();
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
-            }
-          }
-        }
-        pub mod IKeystoreSecurityLevel {
-          #![allow(non_upper_case_globals)]
-          #![allow(non_snake_case)]
-          #[allow(unused_imports)] use binder::IBinder;
-          use binder::declare_binder_interface;
-          declare_binder_interface! {
-            IKeystoreSecurityLevel["android.security.keystore2.IKeystoreSecurityLevel"] {
-              native: BnKeystoreSecurityLevel(on_transact),
-              proxy: BpKeystoreSecurityLevel {
-              },
-            }
-          }
-          pub trait IKeystoreSecurityLevel: binder::Interface + Send {
-            fn get_descriptor() -> &'static str where Self: Sized { "android.security.keystore2.IKeystoreSecurityLevel" }
-            fn create(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_operationParameters: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_forced: bool, _arg_challenge: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation>> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: Option<&crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn generateKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_entropy: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn importKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_keyData: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn importWrappedKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_wrappingKey: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_maskingKey: &[u8], _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_authenticators: &[crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
-              DEFAULT_IMPL.lock().unwrap().clone()
-            }
-            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
-              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
-            }
-          }
-          pub const TRANSACTION_create: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
-          pub const TRANSACTION_updateSubcomponent: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
-          pub const TRANSACTION_generateKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
-          pub const TRANSACTION_importKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
-          pub const TRANSACTION_importWrappedKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
-          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeystoreSecurityLevel + Sync>>;
-          use lazy_static::lazy_static;
-          lazy_static! {
-            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
-          }
-          pub(crate) mod mangled { pub use super::IKeystoreSecurityLevel as _7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel; }
-          impl IKeystoreSecurityLevel for BpKeystoreSecurityLevel {
-            fn create(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_operationParameters: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_forced: bool, _arg_challenge: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation>> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_create, 0, |_aidl_data| {
-                _aidl_data.write(_arg_key)?;
-                _aidl_data.write(_arg_operationParameters)?;
-                _aidl_data.write(&_arg_forced)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
-                  return _aidl_default_impl.create(_arg_key, _arg_operationParameters, _arg_forced, _arg_challenge);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              let _aidl_return: Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation> = _aidl_reply.read()?;
-              *_arg_challenge = _aidl_reply.read()?;
-              Ok(_aidl_return)
-            }
-            fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: Option<&crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_updateSubcomponent, 0, |_aidl_data| {
-                _aidl_data.write(_arg_key)?;
-                _aidl_data.write(&_arg_publicCert)?;
-                _aidl_data.write(&_arg_certificateChain)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
-                  return _aidl_default_impl.updateSubcomponent(_arg_key, _arg_publicCert, _arg_certificateChain);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              Ok(())
-            }
-            fn generateKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_entropy: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_generateKey, 0, |_aidl_data| {
-                _aidl_data.write(_arg_key)?;
-                _aidl_data.write(_arg_params)?;
-                _aidl_data.write(_arg_entropy)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
-                  return _aidl_default_impl.generateKey(_arg_key, _arg_params, _arg_entropy, _arg_resultKey, _arg_publicCert, _arg_certificateChain);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_resultKey = _aidl_reply.read()?;
-              *_arg_publicCert = _aidl_reply.read()?;
-              *_arg_certificateChain = _aidl_reply.read()?;
-              Ok(())
-            }
-            fn importKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_keyData: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_importKey, 0, |_aidl_data| {
-                _aidl_data.write(_arg_key)?;
-                _aidl_data.write(_arg_params)?;
-                _aidl_data.write(_arg_keyData)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
-                  return _aidl_default_impl.importKey(_arg_key, _arg_params, _arg_keyData, _arg_resultKey, _arg_publicCert, _arg_certificateChain);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_resultKey = _aidl_reply.read()?;
-              *_arg_publicCert = _aidl_reply.read()?;
-              *_arg_certificateChain = _aidl_reply.read()?;
-              Ok(())
-            }
-            fn importWrappedKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_wrappingKey: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_maskingKey: &[u8], _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_authenticators: &[crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_importWrappedKey, 0, |_aidl_data| {
-                _aidl_data.write(_arg_key)?;
-                _aidl_data.write(_arg_wrappingKey)?;
-                _aidl_data.write(_arg_maskingKey)?;
-                _aidl_data.write(_arg_params)?;
-                _aidl_data.write(_arg_authenticators)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreSecurityLevel>::getDefaultImpl() {
-                  return _aidl_default_impl.importWrappedKey(_arg_key, _arg_wrappingKey, _arg_maskingKey, _arg_params, _arg_authenticators, _arg_resultKey, _arg_publicCert, _arg_certificateChain);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_resultKey = _aidl_reply.read()?;
-              *_arg_publicCert = _aidl_reply.read()?;
-              *_arg_certificateChain = _aidl_reply.read()?;
-              Ok(())
-            }
-          }
-          impl IKeystoreSecurityLevel for binder::Binder<BnKeystoreSecurityLevel> {
-            fn create(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_operationParameters: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_forced: bool, _arg_challenge: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_18_IKeystoreOperation>> { self.0.create(_arg_key, _arg_operationParameters, _arg_forced, _arg_challenge) }
-            fn updateSubcomponent(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: Option<&crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: Option<&crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> { self.0.updateSubcomponent(_arg_key, _arg_publicCert, _arg_certificateChain) }
-            fn generateKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_entropy: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> { self.0.generateKey(_arg_key, _arg_params, _arg_entropy, _arg_resultKey, _arg_publicCert, _arg_certificateChain) }
-            fn importKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_keyData: &[u8], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> { self.0.importKey(_arg_key, _arg_params, _arg_keyData, _arg_resultKey, _arg_publicCert, _arg_certificateChain) }
-            fn importWrappedKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_wrappingKey: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_maskingKey: &[u8], _arg_params: &[crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter], _arg_authenticators: &[crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec], _arg_resultKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<()> { self.0.importWrappedKey(_arg_key, _arg_wrappingKey, _arg_maskingKey, _arg_params, _arg_authenticators, _arg_resultKey, _arg_publicCert, _arg_certificateChain) }
-          }
-          fn on_transact(_aidl_service: &dyn IKeystoreSecurityLevel, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
-            match _aidl_code {
-              TRANSACTION_create => {
-                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let _arg_operationParameters: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_forced: bool = _aidl_data.read()?;
-                let mut _arg_challenge: Option<crate::mangled::_7_android_8_security_9_keystore2_18_OperationChallenge> = Default::default();
-                let _aidl_return = _aidl_service.create(&_arg_key, &_arg_operationParameters, _arg_forced, &mut _arg_challenge);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(_aidl_return)?;
-                    _aidl_reply.write(&_arg_challenge)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_updateSubcomponent => {
-                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = _aidl_data.read()?;
-                let _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.updateSubcomponent(&_arg_key, _arg_publicCert.as_ref(), _arg_certificateChain.as_ref());
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_generateKey => {
-                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let _arg_params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_entropy: Vec<u8> = _aidl_data.read()?;
-                let mut _arg_resultKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
-                let mut _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = Default::default();
-                let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
-                let _aidl_return = _aidl_service.generateKey(&_arg_key, &_arg_params, &_arg_entropy, &mut _arg_resultKey, &mut _arg_publicCert, &mut _arg_certificateChain);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_resultKey)?;
-                    _aidl_reply.write(&_arg_publicCert)?;
-                    _aidl_reply.write(&_arg_certificateChain)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_importKey => {
-                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let _arg_params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_keyData: Vec<u8> = _aidl_data.read()?;
-                let mut _arg_resultKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
-                let mut _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = Default::default();
-                let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
-                let _aidl_return = _aidl_service.importKey(&_arg_key, &_arg_params, &_arg_keyData, &mut _arg_resultKey, &mut _arg_publicCert, &mut _arg_certificateChain);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_resultKey)?;
-                    _aidl_reply.write(&_arg_publicCert)?;
-                    _aidl_reply.write(&_arg_certificateChain)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_importWrappedKey => {
-                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let _arg_wrappingKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let _arg_maskingKey: Vec<u8> = _aidl_data.read()?;
-                let _arg_params: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter> = _aidl_data.read()?;
-                let _arg_authenticators: Vec<crate::mangled::_7_android_8_security_9_keystore2_17_AuthenticatorSpec> = _aidl_data.read()?;
-                let mut _arg_resultKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
-                let mut _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = Default::default();
-                let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
-                let _aidl_return = _aidl_service.importWrappedKey(&_arg_key, &_arg_wrappingKey, &_arg_maskingKey, &_arg_params, &_arg_authenticators, &mut _arg_resultKey, &mut _arg_publicCert, &mut _arg_certificateChain);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_resultKey)?;
-                    _aidl_reply.write(&_arg_publicCert)?;
-                    _aidl_reply.write(&_arg_certificateChain)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
-            }
-          }
-        }
-        pub mod IKeystoreService {
-          #![allow(non_upper_case_globals)]
-          #![allow(non_snake_case)]
-          #[allow(unused_imports)] use binder::IBinder;
-          use binder::declare_binder_interface;
-          declare_binder_interface! {
-            IKeystoreService["android.security.keystore2.IKeystoreService"] {
-              native: BnKeystoreService(on_transact),
-              proxy: BpKeystoreService {
-              },
-            }
-          }
-          pub trait IKeystoreService: binder::Interface + Send {
-            fn get_descriptor() -> &'static str where Self: Sized { "android.security.keystore2.IKeystoreService" }
-            fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn getKeyEntry(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_metadata: &mut crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_namespace_: i64) -> binder::public_api::Result<Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn grant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32, _arg_accessVector: i32, _arg_grantKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<()> {
-              Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
-            }
-            fn getDefaultImpl() -> DefaultImpl where Self: Sized {
-              DEFAULT_IMPL.lock().unwrap().clone()
-            }
-            fn setDefaultImpl(d: DefaultImpl) -> DefaultImpl where Self: Sized {
-              std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
-            }
-          }
-          pub const TRANSACTION_getSecurityLevel: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 0;
-          pub const TRANSACTION_getKeyEntry: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 1;
-          pub const TRANSACTION_listEntries: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 2;
-          pub const TRANSACTION_deleteKey: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 3;
-          pub const TRANSACTION_grant: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 4;
-          pub const TRANSACTION_ungrant: binder::TransactionCode = binder::SpIBinder::FIRST_CALL_TRANSACTION + 5;
-          pub type DefaultImpl = Option<std::sync::Arc<dyn IKeystoreService + Sync>>;
-          use lazy_static::lazy_static;
-          lazy_static! {
-            static ref DEFAULT_IMPL: std::sync::Mutex<DefaultImpl> = std::sync::Mutex::new(None);
-          }
-          pub(crate) mod mangled { pub use super::IKeystoreService as _7_android_8_security_9_keystore2_16_IKeystoreService; }
-          impl IKeystoreService for BpKeystoreService {
-            fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_getSecurityLevel, 0, |_aidl_data| {
-                _aidl_data.write(&_arg_securityLevel)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
-                  return _aidl_default_impl.getSecurityLevel(_arg_securityLevel);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              let _aidl_return: Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel> = _aidl_reply.read()?;
-              Ok(_aidl_return)
-            }
-            fn getKeyEntry(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_metadata: &mut crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_getKeyEntry, 0, |_aidl_data| {
-                _aidl_data.write(_arg_key)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
-                  return _aidl_default_impl.getKeyEntry(_arg_key, _arg_metadata, _arg_publicCert, _arg_certificateChain);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              let _aidl_return: Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel> = _aidl_reply.read()?;
-              *_arg_metadata = _aidl_reply.read()?;
-              *_arg_publicCert = _aidl_reply.read()?;
-              *_arg_certificateChain = _aidl_reply.read()?;
-              Ok(_aidl_return)
-            }
-            fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_namespace_: i64) -> binder::public_api::Result<Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_listEntries, 0, |_aidl_data| {
-                _aidl_data.write(&_arg_domain)?;
-                _aidl_data.write(&_arg_namespace_)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
-                  return _aidl_default_impl.listEntries(_arg_domain, _arg_namespace_);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              let _aidl_return: Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor> = _aidl_reply.read()?;
-              Ok(_aidl_return)
-            }
-            fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_deleteKey, 0, |_aidl_data| {
-                _aidl_data.write(_arg_key)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
-                  return _aidl_default_impl.deleteKey(_arg_key);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              Ok(())
-            }
-            fn grant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32, _arg_accessVector: i32, _arg_grantKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_grant, 0, |_aidl_data| {
-                _aidl_data.write(_arg_key)?;
-                _aidl_data.write(&_arg_granteeUid)?;
-                _aidl_data.write(&_arg_accessVector)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
-                  return _aidl_default_impl.grant(_arg_key, _arg_granteeUid, _arg_accessVector, _arg_grantKey);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              *_arg_grantKey = _aidl_reply.read()?;
-              Ok(())
-            }
-            fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<()> {
-              let _aidl_reply = self.binder.transact(TRANSACTION_ungrant, 0, |_aidl_data| {
-                _aidl_data.write(_arg_key)?;
-                _aidl_data.write(&_arg_granteeUid)?;
-                Ok(())
-              });
-              if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
-                if let Some(_aidl_default_impl) = <Self as IKeystoreService>::getDefaultImpl() {
-                  return _aidl_default_impl.ungrant(_arg_key, _arg_granteeUid);
-                }
-              }
-              let _aidl_reply = _aidl_reply?;
-              let _aidl_status: binder::Status = _aidl_reply.read()?;
-              if !_aidl_status.is_ok() { return Err(_aidl_status); }
-              Ok(())
-            }
-          }
-          impl IKeystoreService for binder::Binder<BnKeystoreService> {
-            fn getSecurityLevel(&self, _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> { self.0.getSecurityLevel(_arg_securityLevel) }
-            fn getKeyEntry(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_metadata: &mut crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata, _arg_publicCert: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate>, _arg_certificateChain: &mut Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain>) -> binder::public_api::Result<Box<dyn crate::mangled::_7_android_8_security_9_keystore2_22_IKeystoreSecurityLevel>> { self.0.getKeyEntry(_arg_key, _arg_metadata, _arg_publicCert, _arg_certificateChain) }
-            fn listEntries(&self, _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, _arg_namespace_: i64) -> binder::public_api::Result<Vec<crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor>> { self.0.listEntries(_arg_domain, _arg_namespace_) }
-            fn deleteKey(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> { self.0.deleteKey(_arg_key) }
-            fn grant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32, _arg_accessVector: i32, _arg_grantKey: &mut crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor) -> binder::public_api::Result<()> { self.0.grant(_arg_key, _arg_granteeUid, _arg_accessVector, _arg_grantKey) }
-            fn ungrant(&self, _arg_key: &crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, _arg_granteeUid: i32) -> binder::public_api::Result<()> { self.0.ungrant(_arg_key, _arg_granteeUid) }
-          }
-          fn on_transact(_aidl_service: &dyn IKeystoreService, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
-            match _aidl_code {
-              TRANSACTION_getSecurityLevel => {
-                let _arg_securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.getSecurityLevel(_arg_securityLevel);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(_aidl_return)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_getKeyEntry => {
-                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let mut _arg_metadata: crate::mangled::_7_android_8_security_9_keystore2_11_KeyMetadata = Default::default();
-                let mut _arg_publicCert: Option<crate::mangled::_7_android_8_security_9_keystore2_11_Certificate> = Default::default();
-                let mut _arg_certificateChain: Option<crate::mangled::_7_android_8_security_9_keystore2_16_CertificateChain> = Default::default();
-                let _aidl_return = _aidl_service.getKeyEntry(&_arg_key, &mut _arg_metadata, &mut _arg_publicCert, &mut _arg_certificateChain);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(_aidl_return)?;
-                    _aidl_reply.write(&_arg_metadata)?;
-                    _aidl_reply.write(&_arg_publicCert)?;
-                    _aidl_reply.write(&_arg_certificateChain)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_listEntries => {
-                let _arg_domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain = _aidl_data.read()?;
-                let _arg_namespace_: i64 = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.listEntries(_arg_domain, _arg_namespace_);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(_aidl_return)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_deleteKey => {
-                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.deleteKey(&_arg_key);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_grant => {
-                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let _arg_granteeUid: i32 = _aidl_data.read()?;
-                let _arg_accessVector: i32 = _aidl_data.read()?;
-                let mut _arg_grantKey: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = Default::default();
-                let _aidl_return = _aidl_service.grant(&_arg_key, _arg_granteeUid, _arg_accessVector, &mut _arg_grantKey);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                    _aidl_reply.write(&_arg_grantKey)?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              TRANSACTION_ungrant => {
-                let _arg_key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor = _aidl_data.read()?;
-                let _arg_granteeUid: i32 = _aidl_data.read()?;
-                let _aidl_return = _aidl_service.ungrant(&_arg_key, _arg_granteeUid);
-                match &_aidl_return {
-                  Ok(_aidl_return) => {
-                    _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
-                  }
-                  Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
-                }
-                Ok(())
-              }
-              _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
-            }
-          }
-        }
-        pub mod KeyDescriptor {
-          #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
-          pub struct KeyDescriptor {
-            pub domain: crate::mangled::_7_android_8_security_9_keystore2_6_Domain, 
-            pub namespace_: i64, 
-            pub alias: Option<String>, 
-            pub blob: Option<Vec<u8>>, 
-          }
-          pub(crate) mod mangled { pub use super::KeyDescriptor as _7_android_8_security_9_keystore2_13_KeyDescriptor; }
-          impl Default for KeyDescriptor {
-            fn default() -> Self {
-              Self {
-                domain: Default::default(),
-                namespace_: 0,
-                alias: Default::default(),
-                blob: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for KeyDescriptor {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for KeyDescriptor {}
-          impl binder::parcel::SerializeOption for KeyDescriptor {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.domain)?;
-              parcel.write(&this.namespace_)?;
-              parcel.write(&this.alias)?;
-              parcel.write(&this.blob)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for KeyDescriptor {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for KeyDescriptor {}
-          impl binder::parcel::DeserializeOption for KeyDescriptor {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.domain = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.namespace_ = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.alias = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.blob = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod KeyMetadata {
-          pub struct KeyMetadata {
-            pub key: crate::mangled::_7_android_8_security_9_keystore2_13_KeyDescriptor, 
-            pub securityLevel: crate::mangled::_7_android_8_hardware_7_keymint_13_SecurityLevel, 
-            pub hardwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
-            pub softwareEnforced: Vec<crate::mangled::_7_android_8_hardware_7_keymint_12_KeyParameter>, 
-          }
-          pub(crate) mod mangled { pub use super::KeyMetadata as _7_android_8_security_9_keystore2_11_KeyMetadata; }
-          impl Default for KeyMetadata {
-            fn default() -> Self {
-              Self {
-                key: Default::default(),
-                securityLevel: Default::default(),
-                hardwareEnforced: Default::default(),
-                softwareEnforced: Default::default(),
-              }
-            }
-          }
-          impl binder::parcel::Serialize for KeyMetadata {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for KeyMetadata {}
-          impl binder::parcel::SerializeOption for KeyMetadata {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.key)?;
-              parcel.write(&this.securityLevel)?;
-              parcel.write(&this.hardwareEnforced)?;
-              parcel.write(&this.softwareEnforced)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for KeyMetadata {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for KeyMetadata {}
-          impl binder::parcel::DeserializeOption for KeyMetadata {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.key = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.securityLevel = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.hardwareEnforced = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              result.softwareEnforced = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod KeyPermission {
-          #![allow(non_upper_case_globals)]
-          pub type KeyPermission = i32;
-          pub const None: KeyPermission = 0;
-          pub const Delete: KeyPermission = 1;
-          pub const GenUniqueId: KeyPermission = 2;
-          pub const GetInfo: KeyPermission = 4;
-          pub const Grant: KeyPermission = 8;
-          pub const ManageBlob: KeyPermission = 16;
-          pub const Rebind: KeyPermission = 32;
-          pub const ReqForcedOp: KeyPermission = 64;
-          pub const Update: KeyPermission = 128;
-          pub const Use: KeyPermission = 256;
-          pub const UseDevId: KeyPermission = 512;
-          pub(crate) mod mangled { pub use super::KeyPermission as _7_android_8_security_9_keystore2_13_KeyPermission; }
-        }
-        pub mod OperationChallenge {
-          pub struct OperationChallenge {
-            pub challenge: i64, 
-          }
-          pub(crate) mod mangled { pub use super::OperationChallenge as _7_android_8_security_9_keystore2_18_OperationChallenge; }
-          impl Default for OperationChallenge {
-            fn default() -> Self {
-              Self {
-                challenge: 0,
-              }
-            }
-          }
-          impl binder::parcel::Serialize for OperationChallenge {
-            fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-            }
-          }
-          impl binder::parcel::SerializeArray for OperationChallenge {}
-          impl binder::parcel::SerializeOption for OperationChallenge {
-            fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-              let this = if let Some(this) = this {
-                parcel.write(&1i32)?;
-                this
-              } else {
-                return parcel.write(&0i32);
-              };
-              let start_pos = parcel.get_data_position();
-              parcel.write(&0i32)?;
-              parcel.write(&this.challenge)?;
-              let end_pos = parcel.get_data_position();
-              let parcelable_size = (end_pos - start_pos) as i32;
-              unsafe { parcel.set_data_position(start_pos)?; }
-              parcel.write(&parcelable_size)?;
-              unsafe { parcel.set_data_position(end_pos)?; }
-              Ok(())
-            }
-          }
-          impl binder::parcel::Deserialize for OperationChallenge {
-            fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-              <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-                 .transpose()
-                 .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-            }
-          }
-          impl binder::parcel::DeserializeArray for OperationChallenge {}
-          impl binder::parcel::DeserializeOption for OperationChallenge {
-            fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-              let status: i32 = parcel.read()?;
-              if status == 0 { return Ok(None); }
-              let start_pos = parcel.get_data_position();
-              let parcelable_size: i32 = parcel.read()?;
-              if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-              let mut result = Self::default();
-              result.challenge = parcel.read()?;
-              if (parcel.get_data_position() - start_pos) >= parcelable_size {
-                unsafe { parcel.set_data_position(start_pos + parcelable_size)?; }
-                return Ok(Some(result));
-              }
-              Ok(Some(result))
-            }
-          }
-        }
-        pub mod ResponseCode {
-          #![allow(non_upper_case_globals)]
-          pub type ResponseCode = i32;
-          pub const Ok: ResponseCode = 0;
-          pub const Locked: ResponseCode = 2;
-          pub const Uninitialized: ResponseCode = 3;
-          pub const SystemError: ResponseCode = 4;
-          pub const PermissionDenied: ResponseCode = 6;
-          pub const KeyNotFound: ResponseCode = 7;
-          pub const ValueCorrupted: ResponseCode = 8;
-          pub const WrongPassword: ResponseCode = 10;
-          pub const OpAuthNeeded: ResponseCode = 15;
-          pub const KeyPermanentlyInvalidated: ResponseCode = 17;
-          pub const NoSuchSecurityLevel: ResponseCode = 18;
-          pub const KeymintErrorCode: ResponseCode = 19;
-          pub const BackendBusy: ResponseCode = 20;
-          pub(crate) mod mangled { pub use super::ResponseCode as _7_android_8_security_9_keystore2_12_ResponseCode; }
-        }
-      }
-    }
-  }
-}
-pub mod mangled {
-  pub use super::aidl::android::security::keystore2::AuthenticatorSpec::mangled::*;
-  pub use super::aidl::android::security::keystore2::Certificate::mangled::*;
-  pub use super::aidl::android::security::keystore2::CertificateChain::mangled::*;
-  pub use super::aidl::android::security::keystore2::Domain::mangled::*;
-  pub use super::aidl::android::security::keystore2::IKeystoreOperation::mangled::*;
-  pub use super::aidl::android::security::keystore2::IKeystoreSecurityLevel::mangled::*;
-  pub use super::aidl::android::security::keystore2::IKeystoreService::mangled::*;
-  pub use super::aidl::android::security::keystore2::KeyDescriptor::mangled::*;
-  pub use super::aidl::android::security::keystore2::KeyMetadata::mangled::*;
-  pub use super::aidl::android::security::keystore2::KeyPermission::mangled::*;
-  pub use super::aidl::android::security::keystore2::OperationChallenge::mangled::*;
-  pub use super::aidl::android::security::keystore2::ResponseCode::mangled::*;
-  pub(crate) use android_hardware_keymint::mangled::*;
-}
diff --git a/keystore2/src/certificate_utils.cpp b/keystore2/src/certificate_utils.cpp
new file mode 100644
index 0000000..56dd3f4
--- /dev/null
+++ b/keystore2/src/certificate_utils.cpp
@@ -0,0 +1,558 @@
+/*
+ * Copyright 2020, 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 <certificate_utils.h>
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/x509v3.h>
+
+#include <functional>
+#include <limits>
+#include <string>
+#include <variant>
+#include <vector>
+
+namespace keystore {
+
+namespace {
+
+constexpr int kDigitalSignatureKeyUsageBit = 0;
+constexpr int kKeyEnciphermentKeyUsageBit = 2;
+constexpr int kDataEnciphermentKeyUsageBit = 3;
+constexpr int kKeyCertSignBit = 5;
+constexpr int kMaxKeyUsageBit = 8;
+
+DEFINE_OPENSSL_OBJECT_POINTER(ASN1_STRING);
+DEFINE_OPENSSL_OBJECT_POINTER(RSA_PSS_PARAMS);
+DEFINE_OPENSSL_OBJECT_POINTER(AUTHORITY_KEYID);
+DEFINE_OPENSSL_OBJECT_POINTER(BASIC_CONSTRAINTS);
+DEFINE_OPENSSL_OBJECT_POINTER(X509_ALGOR);
+
+}  // namespace
+
+std::variant<CertUtilsError, X509_NAME_Ptr> makeCommonName(const std::string& name) {
+    X509_NAME_Ptr x509_name(X509_NAME_new());
+    if (!x509_name) {
+        return CertUtilsError::BoringSsl;
+    }
+    if (!X509_NAME_add_entry_by_txt(x509_name.get(), "CN", MBSTRING_ASC,
+                                    reinterpret_cast<const uint8_t*>(name.c_str()), name.length(),
+                                    -1 /* loc */, 0 /* set */)) {
+        return CertUtilsError::BoringSsl;
+    }
+    return x509_name;
+}
+
+std::variant<CertUtilsError, std::vector<uint8_t>> makeKeyId(const X509* cert) {
+    std::vector<uint8_t> keyid(20);
+    unsigned int len;
+    if (!X509_pubkey_digest(cert, EVP_sha1(), keyid.data(), &len)) {
+        return CertUtilsError::Encoding;
+    }
+    return keyid;
+}
+
+std::variant<CertUtilsError, AUTHORITY_KEYID_Ptr>
+makeAuthorityKeyExtension(const std::vector<uint8_t>& keyid) {
+    AUTHORITY_KEYID_Ptr auth_key(AUTHORITY_KEYID_new());
+    if (!auth_key) {
+        return CertUtilsError::MemoryAllocation;
+    }
+
+    auth_key->keyid = ASN1_OCTET_STRING_new();
+    if (auth_key->keyid == nullptr) {
+        return CertUtilsError::MemoryAllocation;
+    }
+
+    if (!ASN1_OCTET_STRING_set(auth_key->keyid, keyid.data(), keyid.size())) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    return auth_key;
+}
+
+std::variant<CertUtilsError, ASN1_OCTET_STRING_Ptr>
+makeSubjectKeyExtension(const std::vector<uint8_t>& keyid) {
+
+    // Build OCTET_STRING
+    ASN1_OCTET_STRING_Ptr keyid_str(ASN1_OCTET_STRING_new());
+    if (!keyid_str || !ASN1_OCTET_STRING_set(keyid_str.get(), keyid.data(), keyid.size())) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    return keyid_str;
+}
+
+std::variant<CertUtilsError, BASIC_CONSTRAINTS_Ptr>
+makeBasicConstraintsExtension(bool is_ca, std::optional<int> path_length) {
+
+    BASIC_CONSTRAINTS_Ptr bcons(BASIC_CONSTRAINTS_new());
+    if (!bcons) {
+        return CertUtilsError::MemoryAllocation;
+    }
+
+    bcons->ca = is_ca;
+    bcons->pathlen = nullptr;
+    if (path_length) {
+        bcons->pathlen = ASN1_INTEGER_new();
+        if (bcons->pathlen == nullptr || !ASN1_INTEGER_set(bcons->pathlen, *path_length)) {
+            return CertUtilsError::BoringSsl;
+        }
+    }
+
+    return bcons;
+}
+
+std::variant<CertUtilsError, ASN1_BIT_STRING_Ptr>
+makeKeyUsageExtension(bool is_signing_key, bool is_encryption_key, bool is_cert_key) {
+    // Build BIT_STRING with correct contents.
+    ASN1_BIT_STRING_Ptr key_usage(ASN1_BIT_STRING_new());
+    if (!key_usage) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    for (size_t i = 0; i <= kMaxKeyUsageBit; ++i) {
+        if (!ASN1_BIT_STRING_set_bit(key_usage.get(), i, 0)) {
+            return CertUtilsError::BoringSsl;
+        }
+    }
+
+    if (is_signing_key) {
+        if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kDigitalSignatureKeyUsageBit, 1)) {
+            return CertUtilsError::BoringSsl;
+        }
+    }
+
+    if (is_encryption_key) {
+        if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyEnciphermentKeyUsageBit, 1) ||
+            !ASN1_BIT_STRING_set_bit(key_usage.get(), kDataEnciphermentKeyUsageBit, 1)) {
+            return CertUtilsError::BoringSsl;
+        }
+    }
+
+    if (is_cert_key) {
+        if (!ASN1_BIT_STRING_set_bit(key_usage.get(), kKeyCertSignBit, 1)) {
+            return CertUtilsError::BoringSsl;
+        }
+    }
+
+    return key_usage;
+}
+
+// Creates a rump certificate structure with serial, subject and issuer names, as well as
+// activation and expiry date.
+// Callers should pass an empty X509_Ptr and check the return value for CertUtilsError::Ok (0)
+// before accessing the result.
+std::variant<CertUtilsError, X509_Ptr>
+makeCertRump(const uint32_t serial, const char subject[], const uint64_t activeDateTimeMilliSeconds,
+             const uint64_t usageExpireDateTimeMilliSeconds) {
+
+    // Sanitize pointer arguments.
+    if (!subject || strlen(subject) == 0) {
+        return CertUtilsError::InvalidArgument;
+    }
+
+    // Create certificate structure.
+    X509_Ptr certificate(X509_new());
+    if (!certificate) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    // Set the X509 version.
+    if (!X509_set_version(certificate.get(), 2 /* version 3, but zero-based */)) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    // Set the certificate serialNumber
+    ASN1_INTEGER_Ptr serialNumber(ASN1_INTEGER_new());
+    if (!serialNumber || !ASN1_INTEGER_set(serialNumber.get(), serial) ||
+        !X509_set_serialNumber(certificate.get(), serialNumber.get() /* Don't release; copied */))
+        return CertUtilsError::BoringSsl;
+
+    // Set Subject Name
+    auto subjectName = makeCommonName(subject);
+    if (auto x509_subject = std::get_if<X509_NAME_Ptr>(&subjectName)) {
+        if (!X509_set_subject_name(certificate.get(), x509_subject->get() /* copied */)) {
+            return CertUtilsError::BoringSsl;
+        }
+    } else {
+        return std::get<CertUtilsError>(subjectName);
+    }
+
+    // Set activation date.
+    ASN1_TIME_Ptr notBefore(ASN1_TIME_new());
+    if (!notBefore || !ASN1_TIME_set(notBefore.get(), activeDateTimeMilliSeconds / 1000) ||
+        !X509_set_notBefore(certificate.get(), notBefore.get() /* Don't release; copied */))
+        return CertUtilsError::BoringSsl;
+
+    // Set expiration date.
+    time_t notAfterTime;
+    notAfterTime = (time_t)std::min((uint64_t)std::numeric_limits<time_t>::max(),
+                                    usageExpireDateTimeMilliSeconds / 1000);
+
+    ASN1_TIME_Ptr notAfter(ASN1_TIME_new());
+    if (!notAfter || !ASN1_TIME_set(notAfter.get(), notAfterTime) ||
+        !X509_set_notAfter(certificate.get(), notAfter.get() /* Don't release; copied */)) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    return certificate;
+}
+
+std::variant<CertUtilsError, X509_Ptr>
+makeCert(const EVP_PKEY* evp_pkey, const uint32_t serial, const char subject[],
+         const uint64_t activeDateTimeMilliSeconds, const uint64_t usageExpireDateTimeMilliSeconds,
+         bool addSubjectKeyIdEx, std::optional<KeyUsageExtension> keyUsageEx,
+         std::optional<BasicConstraintsExtension> basicConstraints) {
+
+    // Make the rump certificate with serial, subject, not before and not after dates.
+    auto certificateV =
+        makeCertRump(serial, subject, activeDateTimeMilliSeconds, usageExpireDateTimeMilliSeconds);
+    if (auto error = std::get_if<CertUtilsError>(&certificateV)) {
+        return *error;
+    }
+    auto certificate = std::move(std::get<X509_Ptr>(certificateV));
+
+    // Set the public key.
+    if (!X509_set_pubkey(certificate.get(), const_cast<EVP_PKEY*>(evp_pkey))) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    if (keyUsageEx) {
+        // Make and add the key usage extension.
+        auto key_usage_extensionV = makeKeyUsageExtension(
+            keyUsageEx->isSigningKey, keyUsageEx->isEncryptionKey, keyUsageEx->isCertificationKey);
+        if (auto error = std::get_if<CertUtilsError>(&key_usage_extensionV)) {
+            return *error;
+        }
+        auto key_usage_extension = std::move(std::get<ASN1_BIT_STRING_Ptr>(key_usage_extensionV));
+        if (!X509_add1_ext_i2d(certificate.get(), NID_key_usage,
+                               key_usage_extension.get() /* Don't release; copied */,
+                               true /* critical */, 0 /* flags */)) {
+            return CertUtilsError::BoringSsl;
+        }
+    }
+
+    if (basicConstraints) {
+        // Make and add basic constraints
+        auto basic_constraints_extensionV =
+            makeBasicConstraintsExtension(basicConstraints->isCa, basicConstraints->pathLength);
+        if (auto error = std::get_if<CertUtilsError>(&basic_constraints_extensionV)) {
+            return *error;
+        }
+        auto basic_constraints_extension =
+            std::move(std::get<BASIC_CONSTRAINTS_Ptr>(basic_constraints_extensionV));
+        if (!X509_add1_ext_i2d(certificate.get(), NID_basic_constraints,
+                               basic_constraints_extension.get() /* Don't release; copied */,
+                               true /* critical */, 0 /* flags */)) {
+            return CertUtilsError::BoringSsl;
+        }
+    }
+
+    if (addSubjectKeyIdEx) {
+        // Make and add subject key id extension.
+        auto keyidV = makeKeyId(certificate.get());
+        if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
+            return *error;
+        }
+        auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
+
+        auto subject_key_extensionV = makeSubjectKeyExtension(keyid);
+        if (auto error = std::get_if<CertUtilsError>(&subject_key_extensionV)) {
+            return *error;
+        }
+        auto subject_key_extension =
+            std::move(std::get<ASN1_OCTET_STRING_Ptr>(subject_key_extensionV));
+        if (!X509_add1_ext_i2d(certificate.get(), NID_subject_key_identifier,
+                               subject_key_extension.get() /* Don't release; copied */,
+                               false /* critical */, 0 /* flags */)) {
+            return CertUtilsError::BoringSsl;
+        }
+    }
+
+    return certificate;
+}
+
+CertUtilsError setIssuer(X509* cert, const X509* signingCert, bool addAuthKeyExt) {
+
+    X509_NAME* issuerName(X509_get_subject_name(signingCert));
+
+    // Set Issuer Name
+    if (issuerName) {
+        if (!X509_set_issuer_name(cert, issuerName /* copied */)) {
+            return CertUtilsError::BoringSsl;
+        }
+    } else {
+        return CertUtilsError::Encoding;
+    }
+
+    if (addAuthKeyExt) {
+        // Make and add authority key extension - self signed.
+        auto keyidV = makeKeyId(signingCert);
+        if (auto error = std::get_if<CertUtilsError>(&keyidV)) {
+            return *error;
+        }
+        auto& keyid = std::get<std::vector<uint8_t>>(keyidV);
+
+        auto auth_key_extensionV = makeAuthorityKeyExtension(keyid);
+        if (auto error = std::get_if<CertUtilsError>(&auth_key_extensionV)) {
+            return *error;
+        }
+        auto auth_key_extension = std::move(std::get<AUTHORITY_KEYID_Ptr>(auth_key_extensionV));
+        if (!X509_add1_ext_i2d(cert, NID_authority_key_identifier, auth_key_extension.get(), false,
+                               0)) {
+            return CertUtilsError::BoringSsl;
+        }
+    }
+    return CertUtilsError::Ok;
+}
+
+// Takes a certificate a signing certificate and the raw private signing_key. And signs
+// the certificate with the latter.
+CertUtilsError signCert(X509* certificate, EVP_PKEY* signing_key) {
+
+    if (certificate == nullptr) {
+        return CertUtilsError::UnexpectedNullPointer;
+    }
+
+    if (!X509_sign(certificate, signing_key, EVP_sha256())) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    return CertUtilsError::Ok;
+}
+
+std::variant<CertUtilsError, std::vector<uint8_t>> encodeCert(X509* certificate) {
+    int len = i2d_X509(certificate, nullptr);
+    if (len < 0) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    auto result = std::vector<uint8_t>(len);
+    uint8_t* p = result.data();
+
+    if (i2d_X509(certificate, &p) < 0) {
+        return CertUtilsError::BoringSsl;
+    }
+    return result;
+}
+
+CertUtilsError setRsaDigestAlgorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
+    if (alg_ptr == nullptr || digest == nullptr) {
+        return CertUtilsError::UnexpectedNullPointer;
+    }
+    *alg_ptr = X509_ALGOR_new();
+    if (*alg_ptr == nullptr) {
+        return CertUtilsError::MemoryAllocation;
+    }
+    X509_ALGOR_set_md(*alg_ptr, digest);
+    return CertUtilsError::Ok;
+}
+
+CertUtilsError setPssMaskGeneratorField(X509_ALGOR** alg_ptr, const EVP_MD* digest) {
+    X509_ALGOR* mgf1_digest = nullptr;
+    if (auto error = setRsaDigestAlgorField(&mgf1_digest, digest)) {
+        return error;
+    }
+    X509_ALGOR_Ptr mgf1_digest_ptr(mgf1_digest);
+
+    ASN1_OCTET_STRING* mgf1_digest_algor_str = nullptr;
+    if (!ASN1_item_pack(mgf1_digest, ASN1_ITEM_rptr(X509_ALGOR), &mgf1_digest_algor_str)) {
+        return CertUtilsError::Encoding;
+    }
+    ASN1_OCTET_STRING_Ptr mgf1_digest_algor_str_ptr(mgf1_digest_algor_str);
+
+    *alg_ptr = X509_ALGOR_new();
+    if (*alg_ptr == nullptr) {
+        return CertUtilsError::MemoryAllocation;
+    }
+    X509_ALGOR_set0(*alg_ptr, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, mgf1_digest_algor_str);
+    // *alg_ptr took ownership of the octet string
+    mgf1_digest_algor_str_ptr.release();
+    return CertUtilsError::Ok;
+}
+
+static CertUtilsError setSaltLength(RSA_PSS_PARAMS* pss_params, unsigned length) {
+    pss_params->saltLength = ASN1_INTEGER_new();
+    if (pss_params->saltLength == nullptr) {
+        return CertUtilsError::MemoryAllocation;
+    }
+    if (!ASN1_INTEGER_set(pss_params->saltLength, length)) {
+        return CertUtilsError::Encoding;
+    };
+    return CertUtilsError::Ok;
+}
+
+std::variant<CertUtilsError, ASN1_STRING_Ptr> buildRsaPssParameter(Digest digest) {
+    RSA_PSS_PARAMS_Ptr pss(RSA_PSS_PARAMS_new());
+    if (!pss) {
+        return CertUtilsError::MemoryAllocation;
+    }
+
+    const EVP_MD* md = nullptr;
+
+    switch (digest) {
+    case Digest::SHA1:
+        break;
+    case Digest::SHA224:
+        md = EVP_sha224();
+        break;
+    case Digest::SHA256:
+        md = EVP_sha256();
+        break;
+    case Digest::SHA384:
+        md = EVP_sha384();
+        break;
+    case Digest::SHA512:
+        md = EVP_sha512();
+        break;
+    default:
+        return CertUtilsError::InvalidArgument;
+    }
+
+    if (md != nullptr) {
+        if (auto error = setSaltLength(pss.get(), EVP_MD_size(md))) {
+            return error;
+        }
+        if (auto error = setRsaDigestAlgorField(&pss->hashAlgorithm, md)) {
+            return error;
+        }
+        if (auto error = setPssMaskGeneratorField(&pss->maskGenAlgorithm, md)) {
+            return error;
+        }
+    }
+
+    ASN1_STRING* algo_str = nullptr;
+    if (!ASN1_item_pack(pss.get(), ASN1_ITEM_rptr(RSA_PSS_PARAMS), &algo_str)) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    return ASN1_STRING_Ptr(algo_str);
+}
+
+CertUtilsError makeAndSetAlgo(X509_ALGOR* algo_field, Algo algo, Padding padding, Digest digest) {
+    if (algo_field == nullptr) {
+        return CertUtilsError::UnexpectedNullPointer;
+    }
+    ASN1_STRING_Ptr param;
+    int param_type = V_ASN1_UNDEF;
+    int nid = 0;
+    switch (algo) {
+    case Algo::ECDSA:
+        switch (digest) {
+        case Digest::SHA1:
+            nid = NID_ecdsa_with_SHA1;
+            break;
+        case Digest::SHA224:
+            nid = NID_ecdsa_with_SHA224;
+            break;
+        case Digest::SHA256:
+            nid = NID_ecdsa_with_SHA256;
+            break;
+        case Digest::SHA384:
+            nid = NID_ecdsa_with_SHA384;
+            break;
+        case Digest::SHA512:
+            nid = NID_ecdsa_with_SHA512;
+            break;
+        default:
+            return CertUtilsError::InvalidArgument;
+        }
+        break;
+    case Algo::RSA:
+        switch (padding) {
+        case Padding::PKCS1_5:
+            param_type = V_ASN1_NULL;
+            switch (digest) {
+            case Digest::SHA1:
+                nid = NID_sha1WithRSAEncryption;
+                break;
+            case Digest::SHA224:
+                nid = NID_sha224WithRSAEncryption;
+                break;
+            case Digest::SHA256:
+                nid = NID_sha256WithRSAEncryption;
+                break;
+            case Digest::SHA384:
+                nid = NID_sha384WithRSAEncryption;
+                break;
+            case Digest::SHA512:
+                nid = NID_sha512WithRSAEncryption;
+                break;
+            default:
+                return CertUtilsError::InvalidArgument;
+            }
+            break;
+        case Padding::PSS: {
+            auto v = buildRsaPssParameter(digest);
+            if (auto param_str = std::get_if<ASN1_STRING_Ptr>(&v)) {
+                param = std::move(*param_str);
+                param_type = V_ASN1_SEQUENCE;
+                nid = NID_rsassaPss;
+            } else {
+                return std::get<CertUtilsError>(v);
+            }
+            break;
+        }
+        default:
+            return CertUtilsError::InvalidArgument;
+        }
+        break;
+    default:
+        return CertUtilsError::InvalidArgument;
+    }
+
+    if (!X509_ALGOR_set0(algo_field, OBJ_nid2obj(nid), param_type, param.get())) {
+        return CertUtilsError::Encoding;
+    }
+    // The X509 struct took ownership.
+    param.release();
+    return CertUtilsError::Ok;
+}
+
+// This function allows for signing a
+CertUtilsError signCertWith(X509* certificate,
+                            std::function<std::vector<uint8_t>(const uint8_t*, size_t)> sign,
+                            Algo algo, Padding padding, Digest digest) {
+    if (auto error = makeAndSetAlgo(certificate->sig_alg, algo, padding, digest)) {
+        return error;
+    }
+    if (auto error = makeAndSetAlgo(certificate->cert_info->signature, algo, padding, digest)) {
+        return error;
+    }
+
+    uint8_t* cert_buf = nullptr;
+    size_t buf_len = i2d_re_X509_tbs(certificate, &cert_buf);
+    if (buf_len < 0) {
+        return CertUtilsError::Encoding;
+    }
+
+    bssl::UniquePtr<uint8_t> free_cert_buf(cert_buf);
+    auto signature = sign(cert_buf, buf_len);
+
+    if (!ASN1_STRING_set(certificate->signature, signature.data(), signature.size())) {
+        return CertUtilsError::BoringSsl;
+    }
+
+    certificate->signature->flags &= ~(0x07);
+    certificate->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+    return CertUtilsError::Ok;
+}
+
+}  // namespace keystore
diff --git a/keystore2/src/crypto.cpp b/keystore2/src/crypto.cpp
new file mode 100644
index 0000000..8c52e4c
--- /dev/null
+++ b/keystore2/src/crypto.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define LOG_TAG "keystore2"
+
+#include "crypto.hpp"
+
+#include <log/log.h>
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+
+#include <vector>
+
+// Copied from system/security/keystore/blob.h.
+
+constexpr size_t kGcmTagLength = 128 / 8;
+constexpr size_t kAes128KeySizeBytes = 128 / 8;
+
+// Copied from system/security/keystore/blob.cpp.
+
+#if defined(__clang__)
+#define OPTNONE __attribute__((optnone))
+#elif defined(__GNUC__)
+#define OPTNONE __attribute__((optimize("O0")))
+#else
+#error Need a definition for OPTNONE
+#endif
+
+class ArrayEraser {
+  public:
+    ArrayEraser(uint8_t* arr, size_t size) : mArr(arr), mSize(size) {}
+    OPTNONE ~ArrayEraser() { std::fill(mArr, mArr + mSize, 0); }
+
+  private:
+    volatile uint8_t* mArr;
+    size_t mSize;
+};
+
+/**
+ * Returns a EVP_CIPHER appropriate for the given key size.
+ */
+const EVP_CIPHER* getAesCipherForKey(size_t key_size) {
+    const EVP_CIPHER* cipher = EVP_aes_256_gcm();
+    if (key_size == kAes128KeySizeBytes) {
+        cipher = EVP_aes_128_gcm();
+    }
+    return cipher;
+}
+
+/*
+ * Encrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
+ * 'iv' and write output to 'out' (which may be the same location as 'in') and 128-bit tag to
+ * 'tag'.
+ */
+bool AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
+                     size_t key_size, const uint8_t* iv, uint8_t* tag) {
+
+    // There can be 128-bit and 256-bit keys
+    const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
+
+    bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
+
+    EVP_EncryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
+    EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
+
+    std::vector<uint8_t> out_tmp(len);
+    uint8_t* out_pos = out_tmp.data();
+    int out_len;
+
+    EVP_EncryptUpdate(ctx.get(), out_pos, &out_len, in, len);
+    out_pos += out_len;
+    EVP_EncryptFinal_ex(ctx.get(), out_pos, &out_len);
+    out_pos += out_len;
+    if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
+        ALOGD("Encrypted ciphertext is the wrong size, expected %zu, got %zd", len,
+              out_pos - out_tmp.data());
+        return false;
+    }
+
+    std::copy(out_tmp.data(), out_pos, out);
+    EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, kGcmTagLength, tag);
+
+    return true;
+}
+
+/*
+ * Decrypt 'len' data at 'in' with AES-GCM, using 128-bit or 256-bit key at 'key', 96-bit IV at
+ * 'iv', checking 128-bit tag at 'tag' and writing plaintext to 'out'(which may be the same
+ * location as 'in').
+ */
+bool AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len, const uint8_t* key,
+                     size_t key_size, const uint8_t* iv, const uint8_t* tag) {
+
+    // There can be 128-bit and 256-bit keys
+    const EVP_CIPHER* cipher = getAesCipherForKey(key_size);
+
+    bssl::UniquePtr<EVP_CIPHER_CTX> ctx(EVP_CIPHER_CTX_new());
+
+    EVP_DecryptInit_ex(ctx.get(), cipher, nullptr /* engine */, key, iv);
+    EVP_CIPHER_CTX_set_padding(ctx.get(), 0 /* no padding needed with GCM */);
+    EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, kGcmTagLength, const_cast<uint8_t*>(tag));
+
+    std::vector<uint8_t> out_tmp(len);
+    ArrayEraser out_eraser(out_tmp.data(), len);
+    uint8_t* out_pos = out_tmp.data();
+    int out_len;
+
+    EVP_DecryptUpdate(ctx.get(), out_pos, &out_len, in, len);
+    out_pos += out_len;
+    if (!EVP_DecryptFinal_ex(ctx.get(), out_pos, &out_len)) {
+        ALOGE("Failed to decrypt blob; ciphertext or tag is likely corrupted");
+        return false;
+    }
+    out_pos += out_len;
+    if (out_pos - out_tmp.data() != static_cast<ssize_t>(len)) {
+        ALOGE("Encrypted plaintext is the wrong size, expected %zu, got %zd", len,
+              out_pos - out_tmp.data());
+        return false;
+    }
+
+    std::copy(out_tmp.data(), out_pos, out);
+
+    return true;
+}
+
+// Copied from system/security/keystore/keymaster_enforcement.cpp.
+
+class EvpMdCtx {
+  public:
+    EvpMdCtx() { EVP_MD_CTX_init(&ctx_); }
+    ~EvpMdCtx() { EVP_MD_CTX_cleanup(&ctx_); }
+
+    EVP_MD_CTX* get() { return &ctx_; }
+
+  private:
+    EVP_MD_CTX ctx_;
+};
+
+bool CreateKeyId(const uint8_t* key_blob, size_t len, km_id_t* out_id) {
+    EvpMdCtx ctx;
+
+    uint8_t hash[EVP_MAX_MD_SIZE];
+    unsigned int hash_len;
+    if (EVP_DigestInit_ex(ctx.get(), EVP_sha256(), nullptr /* ENGINE */) &&
+        EVP_DigestUpdate(ctx.get(), key_blob, len) &&
+        EVP_DigestFinal_ex(ctx.get(), hash, &hash_len)) {
+        assert(hash_len >= sizeof(*out_id));
+        memcpy(out_id, hash, sizeof(*out_id));
+        return true;
+    }
+
+    return false;
+}
+
+// Copied from system/security/keystore/user_state.h
+
+static constexpr size_t SALT_SIZE = 16;
+
+// Copied from system/security/keystore/user_state.cpp.
+
+void generateKeyFromPassword(uint8_t* key, size_t key_len, const char* pw, size_t pw_len,
+                             uint8_t* salt) {
+    size_t saltSize;
+    if (salt != nullptr) {
+        saltSize = SALT_SIZE;
+    } else {
+        // Pre-gingerbread used this hardwired salt, readMasterKey will rewrite these when found
+        salt = (uint8_t*)"keystore";
+        // sizeof = 9, not strlen = 8
+        saltSize = sizeof("keystore");
+    }
+
+    const EVP_MD* digest = EVP_sha256();
+
+    // SHA1 was used prior to increasing the key size
+    if (key_len == kAes128KeySizeBytes) {
+        digest = EVP_sha1();
+    }
+
+    PKCS5_PBKDF2_HMAC(pw, pw_len, salt, saltSize, 8192, digest, key_len, key);
+}
diff --git a/keystore2/src/crypto.hpp b/keystore2/src/crypto.hpp
new file mode 100644
index 0000000..9a9bb2e
--- /dev/null
+++ b/keystore2/src/crypto.hpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef __CRYPTO_H__
+#define __CRYPTO_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+extern "C" {
+  bool AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len,
+                       const uint8_t* key, size_t key_size, const uint8_t* iv, uint8_t* tag);
+  bool AES_gcm_decrypt(const uint8_t* in, uint8_t* out, size_t len,
+                       const uint8_t* key, size_t key_size, const uint8_t* iv,
+                       const uint8_t* tag);
+
+  // Copied from system/security/keystore/keymaster_enforcement.h.
+  typedef uint64_t km_id_t;
+
+  bool CreateKeyId(const uint8_t* key_blob, size_t len, km_id_t* out_id);
+
+  void generateKeyFromPassword(uint8_t* key, size_t key_len, const char* pw,
+                               size_t pw_len, uint8_t* salt);
+}
+
+#endif  //  __CRYPTO_H__
diff --git a/keystore2/src/crypto.rs b/keystore2/src/crypto.rs
new file mode 100644
index 0000000..b25b648
--- /dev/null
+++ b/keystore2/src/crypto.rs
@@ -0,0 +1,78 @@
+// Copyright 2020, 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.
+
+#[cfg(test)]
+mod tests {
+
+    use keystore2_crypto_bindgen::{
+        generateKeyFromPassword, AES_gcm_decrypt, AES_gcm_encrypt, CreateKeyId,
+    };
+
+    #[test]
+    fn test_encrypt_decrypt() {
+        let input = vec![0; 16];
+        let mut out = vec![0; 16];
+        let mut out2 = vec![0; 16];
+        let key = vec![0; 16];
+        let iv = vec![0; 12];
+        let mut tag = vec![0; 16];
+        unsafe {
+            let res = AES_gcm_encrypt(
+                input.as_ptr(),
+                out.as_mut_ptr(),
+                16,
+                key.as_ptr(),
+                16,
+                iv.as_ptr(),
+                tag.as_mut_ptr(),
+            );
+            assert!(res);
+            assert_ne!(out, input);
+            assert_ne!(tag, input);
+            let res = AES_gcm_decrypt(
+                out.as_ptr(),
+                out2.as_mut_ptr(),
+                16,
+                key.as_ptr(),
+                16,
+                iv.as_ptr(),
+                tag.as_ptr(),
+            );
+            assert!(res);
+            assert_eq!(out2, input);
+        }
+    }
+
+    #[test]
+    fn test_create_key_id() {
+        let blob = vec![0; 16];
+        let mut out: u64 = 0;
+        unsafe {
+            let res = CreateKeyId(blob.as_ptr(), 16, &mut out);
+            assert!(res);
+            assert_ne!(out, 0);
+        }
+    }
+
+    #[test]
+    fn test_generate_key_from_password() {
+        let mut key = vec![0; 16];
+        let pw = vec![0; 16];
+        let mut salt = vec![0; 16];
+        unsafe {
+            generateKeyFromPassword(key.as_mut_ptr(), 16, pw.as_ptr(), 16, salt.as_mut_ptr());
+        }
+        assert_ne!(key, vec![0; 16]);
+    }
+}
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index ea70195..0ce4ad6 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -41,23 +41,27 @@
 //! from the database module these functions take permission check
 //! callbacks.
 
-use crate::error::Error as KsError;
-use crate::key_parameter::{KeyParameter, SqlField, TagType};
-use crate::{error, permission::KeyPermSet};
+use crate::error::{Error as KsError, ResponseCode};
+use crate::key_parameter::{KeyParameter, SqlField, Tag};
+use crate::permission::KeyPermSet;
 use anyhow::{anyhow, Context, Result};
 
-use android_hardware_keymint::aidl::android::hardware::keymint::SecurityLevel::SecurityLevel as SecurityLevelType;
-use android_security_keystore2::aidl::android::security::keystore2::{
-    Domain, Domain::Domain as DomainType, KeyDescriptor::KeyDescriptor,
+use android_hardware_keymint::aidl::android::hardware::keymint::SecurityLevel::SecurityLevel;
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, KeyDescriptor::KeyDescriptor,
 };
 
+use lazy_static::lazy_static;
 #[cfg(not(test))]
 use rand::prelude::random;
 use rusqlite::{
     params, types::FromSql, types::FromSqlResult, types::ToSqlOutput, types::ValueRef, Connection,
     OptionalExtension, Row, Rows, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
 };
-use std::sync::Once;
+use std::{
+    collections::HashSet,
+    sync::{Condvar, Mutex, Once},
+};
 #[cfg(test)]
 use tests::random;
 
@@ -89,17 +93,78 @@
     }
 }
 
+lazy_static! {
+    static ref KEY_ID_LOCK: KeyIdLockDb = KeyIdLockDb::new();
+}
+
+struct KeyIdLockDb {
+    locked_keys: Mutex<HashSet<i64>>,
+    cond_var: Condvar,
+}
+
+/// A locked key. While a guard exists for a given key id, the same key cannot be loaded
+/// from the database a second time. Most functions manipulating the key blob database
+/// require a KeyIdGuard.
+#[derive(Debug)]
+pub struct KeyIdGuard(i64);
+
+impl KeyIdLockDb {
+    fn new() -> Self {
+        Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() }
+    }
+
+    /// This function blocks until an exclusive lock for the given key entry id can
+    /// be acquired. It returns a guard object, that represents the lifecycle of the
+    /// acquired lock.
+    pub fn get(&self, key_id: i64) -> KeyIdGuard {
+        let mut locked_keys = self.locked_keys.lock().unwrap();
+        while locked_keys.contains(&key_id) {
+            locked_keys = self.cond_var.wait(locked_keys).unwrap();
+        }
+        locked_keys.insert(key_id);
+        KeyIdGuard(key_id)
+    }
+
+    /// This function attempts to acquire an exclusive lock on a given key id. If the
+    /// given key id is already taken the function returns None immediately. If a lock
+    /// can be acquired this function returns a guard object, that represents the
+    /// lifecycle of the acquired lock.
+    pub fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> {
+        let mut locked_keys = self.locked_keys.lock().unwrap();
+        if locked_keys.insert(key_id) {
+            Some(KeyIdGuard(key_id))
+        } else {
+            None
+        }
+    }
+}
+
+impl KeyIdGuard {
+    /// Get the numeric key id of the locked key.
+    pub fn id(&self) -> i64 {
+        self.0
+    }
+}
+
+impl Drop for KeyIdGuard {
+    fn drop(&mut self) {
+        let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap();
+        locked_keys.remove(&self.0);
+        KEY_ID_LOCK.cond_var.notify_all();
+    }
+}
+
 /// This type represents a Keystore 2.0 key entry.
 /// An entry has a unique `id` by which it can be found in the database.
 /// It has a security level field, key parameters, and three optional fields
 /// for the KeyMint blob, public certificate and a public certificate chain.
-#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
 pub struct KeyEntry {
     id: i64,
     km_blob: Option<Vec<u8>>,
     cert: Option<Vec<u8>>,
     cert_chain: Option<Vec<u8>>,
-    sec_level: SecurityLevelType,
+    sec_level: SecurityLevel,
     parameters: Vec<KeyParameter>,
 }
 
@@ -133,9 +198,17 @@
         self.cert_chain.take()
     }
     /// Returns the security level of the key entry.
-    pub fn sec_level(&self) -> SecurityLevelType {
+    pub fn sec_level(&self) -> SecurityLevel {
         self.sec_level
     }
+    /// Exposes the key parameters of this key entry.
+    pub fn key_parameters(&self) -> &Vec<KeyParameter> {
+        &self.parameters
+    }
+    /// Consumes this key entry and extracts the keyparameters from it.
+    pub fn into_key_parameters(self) -> Vec<KeyParameter> {
+        self.parameters
+    }
 }
 
 /// Indicates the sub component of a key entry for persistent storage.
@@ -261,22 +334,24 @@
     /// key artifacts, i.e., blobs and parameters have been associated with the new
     /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
     /// atomic even if key generation is not.
-    pub fn create_key_entry(&self, domain: DomainType, namespace: i64) -> Result<i64> {
+    pub fn create_key_entry(&self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
         match domain {
-            Domain::App | Domain::SELinux => {}
+            Domain::APP | Domain::SELINUX => {}
             _ => {
                 return Err(KsError::sys())
                     .context(format!("Domain {:?} must be either App or SELinux.", domain));
             }
         }
-        Self::insert_with_retry(|id| {
-            self.conn.execute(
-                "INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
+        Ok(KEY_ID_LOCK.get(
+            Self::insert_with_retry(|id| {
+                self.conn.execute(
+                    "INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
                      VALUES(?, datetime('now'), ?, ?, NULL);",
-                params![id, domain as i64, namespace],
-            )
-        })
-        .context("In create_key_entry")
+                    params![id, domain.0 as u32, namespace],
+                )
+            })
+            .context("In create_key_entry")?,
+        ))
     }
 
     /// Inserts a new blob and associates it with the given key id. Each blob
@@ -287,16 +362,16 @@
     /// other than `SubComponentType::KM_BLOB` are ignored.
     pub fn insert_blob(
         &mut self,
-        key_id: i64,
+        key_id: &KeyIdGuard,
         sc_type: SubComponentType,
         blob: &[u8],
-        sec_level: SecurityLevelType,
+        sec_level: SecurityLevel,
     ) -> Result<()> {
         self.conn
             .execute(
                 "INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob, sec_level)
                     VALUES (?, ?, ?, ?);",
-                params![sc_type, key_id, blob, sec_level],
+                params![sc_type, key_id.0, blob, sec_level.0],
             )
             .context("Failed to insert blob.")?;
         Ok(())
@@ -306,7 +381,7 @@
     /// and associates them with the given `key_id`.
     pub fn insert_keyparameter<'a>(
         &mut self,
-        key_id: i64,
+        key_id: &KeyIdGuard,
         params: impl IntoIterator<Item = &'a KeyParameter>,
     ) -> Result<()> {
         let mut stmt = self
@@ -319,8 +394,13 @@
 
         let iter = params.into_iter();
         for p in iter {
-            stmt.insert(params![key_id, p.get_tag(), p.key_parameter_value(), p.security_level()])
-                .with_context(|| format!("In insert_keyparameter: Failed to insert {:?}", p))?;
+            stmt.insert(params![
+                key_id.0,
+                p.get_tag().0,
+                p.key_parameter_value(),
+                p.security_level().0
+            ])
+            .with_context(|| format!("In insert_keyparameter: Failed to insert {:?}", p))?;
         }
         Ok(())
     }
@@ -330,13 +410,13 @@
     /// with the same alias-domain-namespace tuple if such row exits.
     pub fn rebind_alias(
         &mut self,
-        newid: i64,
+        newid: &KeyIdGuard,
         alias: &str,
-        domain: DomainType,
+        domain: Domain,
         namespace: i64,
     ) -> Result<()> {
         match domain {
-            Domain::App | Domain::SELinux => {}
+            Domain::APP | Domain::SELINUX => {}
             _ => {
                 return Err(KsError::sys()).context(format!(
                     "In rebind_alias: Domain {:?} must be either App or SELinux.",
@@ -352,7 +432,7 @@
             "UPDATE persistent.keyentry
                  SET alias = NULL, domain = NULL, namespace = NULL
                  WHERE alias = ? AND domain = ? AND namespace = ?;",
-            params![alias, domain as i64, namespace],
+            params![alias, domain.0 as u32, namespace],
         )
         .context("In rebind_alias: Failed to rebind existing entry.")?;
         let result = tx
@@ -360,7 +440,7 @@
                 "UPDATE persistent.keyentry
                     SET alias = ?
                     WHERE id = ? AND domain = ? AND namespace = ?;",
-                params![alias, newid, domain as i64, namespace],
+                params![alias, newid.0, domain.0 as u32, namespace],
             )
             .context("In rebind_alias: Failed to set alias.")?;
         if result != 1 {
@@ -395,10 +475,10 @@
             )
             .context("In load_key_entry_id: Failed to select from keyentry table.")?;
         let mut rows = stmt
-            .query(params![key.domain, key.namespace_, alias])
+            .query(params![key.domain.0 as u32, key.nspace, alias])
             .context("In load_key_entry_id: Failed to read from keyentry table.")?;
         Self::with_rows_extract_one(&mut rows, |row| {
-            row.map_or_else(|| Err(KsError::Rc(error::Rc::KeyNotFound)), Ok)?
+            row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
                 .get(0)
                 .context("Failed to unpack id.")
         })
@@ -408,13 +488,13 @@
     /// This helper function completes the access tuple of a key, which is required
     /// to perform access control. The strategy depends on the `domain` field in the
     /// key descriptor.
-    /// * Domain::SELinux: The access tuple is complete and this function only loads
+    /// * Domain::SELINUX: The access tuple is complete and this function only loads
     ///       the key_id for further processing.
-    /// * Domain::App: Like Domain::SELinux, but the tuple is completed by `caller_uid`
+    /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
     ///       which serves as the namespace.
-    /// * Domain::Grant: The grant table is queried for the `key_id` and the
+    /// * Domain::GRANT: The grant table is queried for the `key_id` and the
     ///       `access_vector`.
-    /// * Domain::KeyId: The keyentry table is queried for the owning `domain` and
+    /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
     ///       `namespace`.
     /// In each case the information returned is sufficient to perform the access
     /// check and the key id can be used to load further key artifacts.
@@ -429,67 +509,69 @@
             // We already have the full access tuple to perform access control.
             // The only distinction is that we use the caller_uid instead
             // of the caller supplied namespace if the domain field is
-            // Domain::App.
-            Domain::App | Domain::SELinux => {
+            // Domain::APP.
+            Domain::APP | Domain::SELINUX => {
                 let mut access_key = key;
-                if access_key.domain == Domain::App {
-                    access_key.namespace_ = caller_uid as i64;
+                if access_key.domain == Domain::APP {
+                    access_key.nspace = caller_uid as i64;
                 }
                 let key_id = Self::load_key_entry_id(&access_key, &tx)
-                    .with_context(|| format!("With key.domain = {}.", access_key.domain))?;
+                    .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
 
                 Ok((key_id, access_key, None))
             }
 
-            // Domain::Grant. In this case we load the key_id and the access_vector
+            // Domain::GRANT. In this case we load the key_id and the access_vector
             // from the grant table.
-            Domain::Grant => {
+            Domain::GRANT => {
                 let mut stmt = tx
                     .prepare(
                         "SELECT keyentryid, access_vector FROM perboot.grant
                             WHERE grantee = ? AND id = ?;",
                     )
-                    .context("Domain::Grant prepare statement failed")?;
+                    .context("Domain::GRANT prepare statement failed")?;
                 let mut rows = stmt
-                    .query(params![caller_uid as i64, key.namespace_])
+                    .query(params![caller_uid as i64, key.nspace])
                     .context("Domain:Grant: query failed.")?;
                 let (key_id, access_vector): (i64, i32) =
                     Self::with_rows_extract_one(&mut rows, |row| {
-                        let r = row.map_or_else(|| Err(KsError::Rc(error::Rc::KeyNotFound)), Ok)?;
+                        let r =
+                            row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
                         Ok((
                             r.get(0).context("Failed to unpack key_id.")?,
                             r.get(1).context("Failed to unpack access_vector.")?,
                         ))
                     })
-                    .context("Domain::Grant.")?;
+                    .context("Domain::GRANT.")?;
                 Ok((key_id, key, Some(access_vector.into())))
             }
 
-            // Domain::KeyId. In this case we load the domain and namespace from the
+            // Domain::KEY_ID. In this case we load the domain and namespace from the
             // keyentry database because we need them for access control.
-            Domain::KeyId => {
+            Domain::KEY_ID => {
                 let mut stmt = tx
                     .prepare(
                         "SELECT domain, namespace FROM persistent.keyentry
                             WHERE
                             id = ?;",
                     )
-                    .context("Domain::KeyId: prepare statement failed")?;
+                    .context("Domain::KEY_ID: prepare statement failed")?;
                 let mut rows =
-                    stmt.query(params![key.namespace_]).context("Domain::KeyId: query failed.")?;
-                let (domain, namespace): (DomainType, i64) =
+                    stmt.query(params![key.nspace]).context("Domain::KEY_ID: query failed.")?;
+                let (domain, namespace): (Domain, i64) =
                     Self::with_rows_extract_one(&mut rows, |row| {
-                        let r = row.map_or_else(|| Err(KsError::Rc(error::Rc::KeyNotFound)), Ok)?;
+                        let r =
+                            row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
                         Ok((
-                            r.get(0).context("Failed to unpack domain.")?,
+                            Domain(r.get(0).context("Failed to unpack domain.")?),
                             r.get(1).context("Failed to unpack namespace.")?,
                         ))
                     })
-                    .context("Domain::KeyId.")?;
-                let key_id = key.namespace_;
+                    .context("Domain::KEY_ID.")?;
+                let key_id = key.nspace;
                 let mut access_key = key;
                 access_key.domain = domain;
-                access_key.namespace_ = namespace;
+                access_key.nspace = namespace;
 
                 Ok((key_id, access_key, None))
             }
@@ -501,7 +583,7 @@
         key_id: i64,
         load_bits: KeyEntryLoadBits,
         tx: &Transaction,
-    ) -> Result<(SecurityLevelType, Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
+    ) -> Result<(SecurityLevel, Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
         let mut stmt = tx
             .prepare(
                 "SELECT MAX(id), sec_level, subcomponent_type, blob FROM persistent.blobentry
@@ -512,7 +594,7 @@
         let mut rows =
             stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
 
-        let mut sec_level: SecurityLevelType = Default::default();
+        let mut sec_level: SecurityLevel = Default::default();
         let mut km_blob: Option<Vec<u8>> = None;
         let mut cert_blob: Option<Vec<u8>> = None;
         let mut cert_chain_blob: Option<Vec<u8>> = None;
@@ -521,7 +603,8 @@
                 row.get(2).context("Failed to extract subcomponent_type.")?;
             match (sub_type, load_bits.load_public()) {
                 (SubComponentType::KM_BLOB, _) => {
-                    sec_level = row.get(1).context("Failed to extract security level.")?;
+                    sec_level =
+                        SecurityLevel(row.get(1).context("Failed to extract security level.")?);
                     if load_bits.load_km() {
                         km_blob = Some(row.get(3).context("Failed to extract KM blob.")?);
                     }
@@ -557,8 +640,8 @@
         let mut rows =
             stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
         Self::with_rows_extract_all(&mut rows, |row| {
-            let tag: TagType = row.get(0).context("Failed to read tag.")?;
-            let sec_level: SecurityLevelType = row.get(2).context("Failed to read sec_level.")?;
+            let tag = Tag(row.get(0).context("Failed to read tag.")?);
+            let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
             parameters.push(
                 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
                     .context("Failed to read KeyParameter.")?,
@@ -581,10 +664,18 @@
         load_bits: KeyEntryLoadBits,
         caller_uid: u32,
         check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
-    ) -> Result<KeyEntry> {
+    ) -> Result<(KeyIdGuard, KeyEntry)> {
+        // KEY ID LOCK 1/2
+        // If we got a key descriptor with a key id we can get the lock right away.
+        // Otherwise we have to defer it until we know the key id.
+        let key_id_guard = match key.domain {
+            Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)),
+            _ => None,
+        };
+
         let tx = self
             .conn
-            .transaction_with_behavior(TransactionBehavior::Deferred)
+            .unchecked_transaction()
             .context("In load_key_entry: Failed to initialize transaction.")?;
 
         // Load the key_id and complete the access control tuple.
@@ -595,21 +686,71 @@
         // So do not touch that '?' at the end.
         check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
 
-        let (sec_level, km_blob, cert_blob, cert_chain_blob) =
-            Self::load_blob_components(key_id, load_bits, &tx).context("In load_key_entry.")?;
+        // KEY ID LOCK 2/2
+        // If we did not get a key id lock by now, it was because we got a key descriptor
+        // without a key id. At this point we got the key id, so we can try and get a lock.
+        // However, we cannot block here, because we are in the middle of the transaction.
+        // So first we try to get the lock non blocking. If that fails, we roll back the
+        // transaction and block until we get the lock. After we successfully got the lock,
+        // we start a new transaction and load the access tuple again.
+        //
+        // We don't need to perform access control again, because we already established
+        // that the caller had access to the given key. But we need to make sure that the
+        // key id still exists. So we have to load the key entry by key id this time.
+        let (key_id_guard, tx) = match key_id_guard {
+            None => match KEY_ID_LOCK.try_get(key_id) {
+                None => {
+                    // Roll back the transaction.
+                    tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?;
 
-        let parameters = Self::load_key_parameters(key_id, &tx).context("In load_key_entry.")?;
+                    // Block until we have a key id lock.
+                    let key_id_guard = KEY_ID_LOCK.get(key_id);
+
+                    // Create a new transaction.
+                    let tx = self.conn.unchecked_transaction().context(
+                        "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
+                    )?;
+
+                    Self::load_access_tuple(
+                        &tx,
+                        // This time we have to load the key by the retrieved key id, because the
+                        // alias may have been rebound after we rolled back the transaction.
+                        KeyDescriptor {
+                            domain: Domain::KEY_ID,
+                            nspace: key_id,
+                            ..Default::default()
+                        },
+                        caller_uid,
+                    )
+                    .context("In load_key_entry. (deferred key lock)")?;
+                    (key_id_guard, tx)
+                }
+                Some(l) => (l, tx),
+            },
+            Some(key_id_guard) => (key_id_guard, tx),
+        };
+
+        let (sec_level, km_blob, cert_blob, cert_chain_blob) =
+            Self::load_blob_components(key_id_guard.id(), load_bits, &tx)
+                .context("In load_key_entry.")?;
+
+        let parameters =
+            Self::load_key_parameters(key_id_guard.id(), &tx).context("In load_key_entry.")?;
 
         tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
 
-        Ok(KeyEntry {
-            id: key_id,
-            km_blob,
-            cert: cert_blob,
-            cert_chain: cert_chain_blob,
-            sec_level,
-            parameters,
-        })
+        let key_id = key_id_guard.id();
+        Ok((
+            key_id_guard,
+            KeyEntry {
+                id: key_id,
+                km_blob,
+                cert: cert_blob,
+                cert_chain: cert_chain_blob,
+                sec_level,
+                parameters,
+            },
+        ))
     }
 
     /// Adds a grant to the grant table.
@@ -634,10 +775,10 @@
         // Load the key_id and complete the access control tuple.
         // We ignore the access vector here because grants cannot be granted.
         // The access vector returned here expresses the permissions the
-        // grantee has if key.domain == Domain::Grant. But this vector
+        // grantee has if key.domain == Domain::GRANT. But this vector
         // cannot include the grant permission by design, so there is no way the
         // subsequent permission check can pass.
-        // We could check key.domain == Domain::Grant and fail early.
+        // We could check key.domain == Domain::GRANT and fail early.
         // But even if we load the access tuple by grant here, the permission
         // check denies the attempt to create a grant by grant descriptor.
         let (key_id, access_key_descriptor, _) =
@@ -681,7 +822,7 @@
         };
         tx.commit().context("In grant: failed to commit transaction.")?;
 
-        Ok(KeyDescriptor { domain: Domain::Grant, namespace_: grant_id, alias: None, blob: None })
+        Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
     }
 
     /// This function checks permissions like `grant` and `load_key_entry`
@@ -790,6 +931,9 @@
     use crate::permission::{KeyPerm, KeyPermSet};
     use rusqlite::NO_PARAMS;
     use std::cell::RefCell;
+    use std::sync::atomic::{AtomicU8, Ordering};
+    use std::sync::Arc;
+    use std::thread;
 
     static PERSISTENT_TEST_SQL: &str = "/data/local/tmp/persistent.sqlite";
     static PERBOOT_TEST_SQL: &str = "/data/local/tmp/perboot.sqlite";
@@ -849,7 +993,7 @@
     fn test_no_persistence_for_tests() -> Result<()> {
         let db = new_test_db()?;
 
-        db.create_key_entry(Domain::App, 100)?;
+        db.create_key_entry(Domain::APP, 100)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 1);
         let db = new_test_db()?;
@@ -865,7 +1009,7 @@
         let _file_guard_perboot = TempFile { filename: PERBOOT_TEST_SQL };
         let db = new_test_db_with_persistent_file()?;
 
-        db.create_key_entry(Domain::App, 100)?;
+        db.create_key_entry(Domain::APP, 100)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 1);
         let db = new_test_db_with_persistent_file()?;
@@ -877,32 +1021,32 @@
 
     #[test]
     fn test_create_key_entry() -> Result<()> {
-        fn extractor(ke: &KeyEntryRow) -> (DomainType, i64, Option<&str>) {
+        fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
             (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
         }
 
         let db = new_test_db()?;
 
-        db.create_key_entry(Domain::App, 100)?;
-        db.create_key_entry(Domain::SELinux, 101)?;
+        db.create_key_entry(Domain::APP, 100)?;
+        db.create_key_entry(Domain::SELINUX, 101)?;
 
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
-        assert_eq!(extractor(&entries[0]), (Domain::App, 100, None));
-        assert_eq!(extractor(&entries[1]), (Domain::SELinux, 101, None));
+        assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
+        assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
 
         // Test that we must pass in a valid Domain.
         check_result_is_error_containing_string(
-            db.create_key_entry(Domain::Grant, 102),
-            "Domain 1 must be either App or SELinux.",
+            db.create_key_entry(Domain::GRANT, 102),
+            "Domain Domain(1) must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
-            db.create_key_entry(Domain::Blob, 103),
-            "Domain 3 must be either App or SELinux.",
+            db.create_key_entry(Domain::BLOB, 103),
+            "Domain Domain(3) must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
-            db.create_key_entry(Domain::KeyId, 104),
-            "Domain 4 must be either App or SELinux.",
+            db.create_key_entry(Domain::KEY_ID, 104),
+            "Domain Domain(4) must be either App or SELinux.",
         );
 
         Ok(())
@@ -910,56 +1054,56 @@
 
     #[test]
     fn test_rebind_alias() -> Result<()> {
-        fn extractor(ke: &KeyEntryRow) -> (Option<DomainType>, Option<i64>, Option<&str>) {
+        fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
             (ke.domain, ke.namespace, ke.alias.as_deref())
         }
 
         let mut db = new_test_db()?;
-        db.create_key_entry(Domain::App, 42)?;
-        db.create_key_entry(Domain::App, 42)?;
+        db.create_key_entry(Domain::APP, 42)?;
+        db.create_key_entry(Domain::APP, 42)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
-        assert_eq!(extractor(&entries[0]), (Some(Domain::App), Some(42), None));
-        assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), None));
+        assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
 
         // Test that the first call to rebind_alias sets the alias.
-        db.rebind_alias(entries[0].id, "foo", Domain::App, 42)?;
+        db.rebind_alias(&KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
-        assert_eq!(extractor(&entries[0]), (Some(Domain::App), Some(42), Some("foo")));
-        assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), None));
+        assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
 
         // Test that the second call to rebind_alias also empties the old one.
-        db.rebind_alias(entries[1].id, "foo", Domain::App, 42)?;
+        db.rebind_alias(&KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
         assert_eq!(extractor(&entries[0]), (None, None, None));
-        assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), Some("foo")));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
 
         // Test that we must pass in a valid Domain.
         check_result_is_error_containing_string(
-            db.rebind_alias(0, "foo", Domain::Grant, 42),
-            "Domain 1 must be either App or SELinux.",
+            db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
+            "Domain Domain(1) must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
-            db.rebind_alias(0, "foo", Domain::Blob, 42),
-            "Domain 3 must be either App or SELinux.",
+            db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
+            "Domain Domain(3) must be either App or SELinux.",
         );
         check_result_is_error_containing_string(
-            db.rebind_alias(0, "foo", Domain::KeyId, 42),
-            "Domain 4 must be either App or SELinux.",
+            db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
+            "Domain Domain(4) must be either App or SELinux.",
         );
 
         // Test that we correctly handle setting an alias for something that does not exist.
         check_result_is_error_containing_string(
-            db.rebind_alias(0, "foo", Domain::SELinux, 42),
+            db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
             "Expected to update a single entry but instead updated 0",
         );
         // Test that we correctly abort the transaction in this case.
         let entries = get_keyentry(&db)?;
         assert_eq!(entries.len(), 2);
         assert_eq!(extractor(&entries[0]), (None, None, None));
-        assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), Some("foo")));
+        assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
 
         Ok(())
     }
@@ -977,8 +1121,8 @@
             NO_PARAMS,
         )?;
         let app_key = KeyDescriptor {
-            domain: super::Domain::App,
-            namespace_: 0,
+            domain: super::Domain::APP,
+            nspace: 0,
             alias: Some("key".to_string()),
             blob: None,
         };
@@ -996,9 +1140,9 @@
                 assert_eq!(
                     *k,
                     KeyDescriptor {
-                        domain: super::Domain::App,
+                        domain: super::Domain::APP,
                         // namespace must be set to the caller_uid.
-                        namespace_: CALLER_UID as i64,
+                        nspace: CALLER_UID as i64,
                         alias: Some("key".to_string()),
                         blob: None,
                     }
@@ -1009,17 +1153,17 @@
         assert_eq!(
             app_granted_key,
             KeyDescriptor {
-                domain: super::Domain::Grant,
+                domain: super::Domain::GRANT,
                 // The grantid is next_random due to the mock random number generator.
-                namespace_: next_random,
+                nspace: next_random,
                 alias: None,
                 blob: None,
             }
         );
 
         let selinux_key = KeyDescriptor {
-            domain: super::Domain::SELinux,
-            namespace_: SELINUX_NAMESPACE,
+            domain: super::Domain::SELINUX,
+            nspace: SELINUX_NAMESPACE,
             alias: Some("yek".to_string()),
             blob: None,
         };
@@ -1030,10 +1174,10 @@
                 assert_eq!(
                     *k,
                     KeyDescriptor {
-                        domain: super::Domain::SELinux,
+                        domain: super::Domain::SELINUX,
                         // namespace must be the supplied SELinux
                         // namespace.
-                        namespace_: SELINUX_NAMESPACE,
+                        nspace: SELINUX_NAMESPACE,
                         alias: Some("yek".to_string()),
                         blob: None,
                     }
@@ -1044,9 +1188,9 @@
         assert_eq!(
             selinux_granted_key,
             KeyDescriptor {
-                domain: super::Domain::Grant,
+                domain: super::Domain::GRANT,
                 // The grantid is next_random + 1 due to the mock random number generator.
-                namespace_: next_random + 1,
+                nspace: next_random + 1,
                 alias: None,
                 blob: None,
             }
@@ -1059,10 +1203,10 @@
                 assert_eq!(
                     *k,
                     KeyDescriptor {
-                        domain: super::Domain::SELinux,
+                        domain: super::Domain::SELINUX,
                         // namespace must be the supplied SELinux
                         // namespace.
-                        namespace_: SELINUX_NAMESPACE,
+                        nspace: SELINUX_NAMESPACE,
                         alias: Some("yek".to_string()),
                         blob: None,
                     }
@@ -1073,9 +1217,9 @@
         assert_eq!(
             selinux_granted_key,
             KeyDescriptor {
-                domain: super::Domain::Grant,
+                domain: super::Domain::GRANT,
                 // Same grant id as before. The entry was only updated.
-                namespace_: next_random + 1,
+                nspace: next_random + 1,
                 alias: None,
                 blob: None,
             }
@@ -1120,9 +1264,24 @@
     #[test]
     fn test_insert_blob() -> Result<()> {
         let mut db = new_test_db()?;
-        db.insert_blob(1, SubComponentType::KM_BLOB, TEST_KM_BLOB, 1)?;
-        db.insert_blob(1, SubComponentType::CERT, TEST_CERT_BLOB, 2)?;
-        db.insert_blob(1, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB, 3)?;
+        db.insert_blob(
+            &KEY_ID_LOCK.get(1),
+            SubComponentType::KM_BLOB,
+            TEST_KM_BLOB,
+            SecurityLevel::SOFTWARE,
+        )?;
+        db.insert_blob(
+            &KEY_ID_LOCK.get(1),
+            SubComponentType::CERT,
+            TEST_CERT_BLOB,
+            SecurityLevel::TRUSTED_ENVIRONMENT,
+        )?;
+        db.insert_blob(
+            &KEY_ID_LOCK.get(1),
+            SubComponentType::CERT_CHAIN,
+            TEST_CERT_CHAIN_BLOB,
+            SecurityLevel::STRONGBOX,
+        )?;
 
         let mut stmt = db.conn.prepare(
             "SELECT subcomponent_type, keyentryid, blob, sec_level FROM persistent.blobentry
@@ -1133,11 +1292,11 @@
                 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
             })?;
         let r = rows.next().unwrap().unwrap();
-        assert_eq!(r, (SubComponentType::KM_BLOB, 1, TEST_KM_BLOB.to_vec(), 1));
+        assert_eq!(r, (SubComponentType::KM_BLOB, 1, TEST_KM_BLOB.to_vec(), 0));
         let r = rows.next().unwrap().unwrap();
-        assert_eq!(r, (SubComponentType::CERT, 1, TEST_CERT_BLOB.to_vec(), 2));
+        assert_eq!(r, (SubComponentType::CERT, 1, TEST_CERT_BLOB.to_vec(), 1));
         let r = rows.next().unwrap().unwrap();
-        assert_eq!(r, (SubComponentType::CERT_CHAIN, 1, TEST_CERT_CHAIN_BLOB.to_vec(), 3));
+        assert_eq!(r, (SubComponentType::CERT_CHAIN, 1, TEST_CERT_CHAIN_BLOB.to_vec(), 2));
 
         Ok(())
     }
@@ -1147,12 +1306,13 @@
     #[test]
     fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
         let mut db = new_test_db()?;
-        let key_id = make_test_key_entry(&mut db, Domain::App, 1, TEST_ALIAS)
-            .context("test_insert_and_load_full_keyentry_domain_app")?;
-        let key_entry = db.load_key_entry(
+        let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
+            .context("test_insert_and_load_full_keyentry_domain_app")?
+            .0;
+        let (_key_guard, key_entry) = db.load_key_entry(
             KeyDescriptor {
-                domain: Domain::App,
-                namespace_: 0,
+                domain: Domain::APP,
+                nspace: 0,
                 alias: Some(TEST_ALIAS.to_string()),
                 blob: None,
             },
@@ -1167,8 +1327,8 @@
                 km_blob: Some(TEST_KM_BLOB.to_vec()),
                 cert: Some(TEST_CERT_BLOB.to_vec()),
                 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
-                sec_level: 1,
-                parameters: make_test_params()
+                sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+                parameters: make_test_params(),
             }
         );
         Ok(())
@@ -1177,12 +1337,13 @@
     #[test]
     fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
         let mut db = new_test_db()?;
-        let key_id = make_test_key_entry(&mut db, Domain::SELinux, 1, TEST_ALIAS)
-            .context("test_insert_and_load_full_keyentry_domain_selinux")?;
-        let key_entry = db.load_key_entry(
+        let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
+            .context("test_insert_and_load_full_keyentry_domain_selinux")?
+            .0;
+        let (_key_guard, key_entry) = db.load_key_entry(
             KeyDescriptor {
-                domain: Domain::SELinux,
-                namespace_: 1,
+                domain: Domain::SELINUX,
+                nspace: 1,
                 alias: Some(TEST_ALIAS.to_string()),
                 blob: None,
             },
@@ -1197,8 +1358,8 @@
                 km_blob: Some(TEST_KM_BLOB.to_vec()),
                 cert: Some(TEST_CERT_BLOB.to_vec()),
                 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
-                sec_level: 1,
-                parameters: make_test_params()
+                sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+                parameters: make_test_params(),
             }
         );
         Ok(())
@@ -1207,10 +1368,11 @@
     #[test]
     fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
         let mut db = new_test_db()?;
-        let key_id = make_test_key_entry(&mut db, Domain::SELinux, 1, TEST_ALIAS)
-            .context("test_insert_and_load_full_keyentry_domain_key_id")?;
-        let key_entry = db.load_key_entry(
-            KeyDescriptor { domain: Domain::KeyId, namespace_: key_id, alias: None, blob: None },
+        let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
+            .context("test_insert_and_load_full_keyentry_domain_key_id")?
+            .0;
+        let (_key_guard, key_entry) = db.load_key_entry(
+            KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
             KeyEntryLoadBits::BOTH,
             1,
             |_k, _av| Ok(()),
@@ -1222,8 +1384,8 @@
                 km_blob: Some(TEST_KM_BLOB.to_vec()),
                 cert: Some(TEST_CERT_BLOB.to_vec()),
                 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
-                sec_level: 1,
-                parameters: make_test_params()
+                sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+                parameters: make_test_params(),
             }
         );
 
@@ -1233,13 +1395,14 @@
     #[test]
     fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
         let mut db = new_test_db()?;
-        let key_id = make_test_key_entry(&mut db, Domain::App, 1, TEST_ALIAS)
-            .context("test_insert_and_load_full_keyentry_from_grant")?;
+        let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
+            .context("test_insert_and_load_full_keyentry_from_grant")?
+            .0;
 
         let granted_key = db.grant(
             KeyDescriptor {
-                domain: Domain::App,
-                namespace_: 0,
+                domain: Domain::APP,
+                nspace: 0,
                 alias: Some(TEST_ALIAS.to_string()),
                 blob: None,
             },
@@ -1251,11 +1414,12 @@
 
         debug_dump_grant_table(&mut db)?;
 
-        let key_entry = db.load_key_entry(granted_key, KeyEntryLoadBits::BOTH, 2, |k, av| {
-            assert_eq!(Domain::Grant, k.domain);
-            assert!(av.unwrap().includes(KeyPerm::use_()));
-            Ok(())
-        })?;
+        let (_key_guard, key_entry) =
+            db.load_key_entry(granted_key, KeyEntryLoadBits::BOTH, 2, |k, av| {
+                assert_eq!(Domain::GRANT, k.domain);
+                assert!(av.unwrap().includes(KeyPerm::use_()));
+                Ok(())
+            })?;
 
         assert_eq!(
             key_entry,
@@ -1264,13 +1428,106 @@
                 km_blob: Some(TEST_KM_BLOB.to_vec()),
                 cert: Some(TEST_CERT_BLOB.to_vec()),
                 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
-                sec_level: 1,
-                parameters: make_test_params()
+                sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+                parameters: make_test_params(),
             }
         );
         Ok(())
     }
 
+    static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
+
+    static KEY_LOCK_TEST_SQL: &str = "/data/local/tmp/persistent_key_lock.sqlite";
+    static KEY_LOCK_PERBOOT_TEST_SQL: &str = "/data/local/tmp/perboot_key_lock.sqlite";
+
+    fn new_test_db_with_persistent_file_key_lock() -> Result<KeystoreDB> {
+        let conn = KeystoreDB::make_connection(KEY_LOCK_TEST_SQL, KEY_LOCK_PERBOOT_TEST_SQL)?;
+
+        KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
+        Ok(KeystoreDB { conn })
+    }
+
+    #[test]
+    fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
+        let handle = {
+            let _file_guard_persistent = Arc::new(TempFile { filename: KEY_LOCK_TEST_SQL });
+            let _file_guard_perboot = Arc::new(TempFile { filename: KEY_LOCK_PERBOOT_TEST_SQL });
+            let mut db = new_test_db_with_persistent_file_key_lock()?;
+            let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS)
+                .context("test_insert_and_load_full_keyentry_domain_app")?
+                .0;
+            let (_key_guard, key_entry) = db.load_key_entry(
+                KeyDescriptor {
+                    domain: Domain::APP,
+                    nspace: 0,
+                    alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
+                    blob: None,
+                },
+                KeyEntryLoadBits::BOTH,
+                33,
+                |_k, _av| Ok(()),
+            )?;
+            assert_eq!(
+                key_entry,
+                KeyEntry {
+                    id: key_id,
+                    km_blob: Some(TEST_KM_BLOB.to_vec()),
+                    cert: Some(TEST_CERT_BLOB.to_vec()),
+                    cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
+                    sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
+                    parameters: make_test_params(),
+                }
+            );
+            let state = Arc::new(AtomicU8::new(1));
+            let state2 = state.clone();
+
+            // Spawning a second thread that attempts to acquire the key id lock
+            // for the same key as the primary thread. The primary thread then
+            // waits, thereby forcing the secondary thread into the second stage
+            // of acquiring the lock (see KEY ID LOCK 2/2 above).
+            // The test succeeds if the secondary thread observes the transition
+            // of `state` from 1 to 2, despite having a whole second to overtake
+            // the primary thread.
+            let handle = thread::spawn(move || {
+                let _file_a = _file_guard_persistent;
+                let _file_b = _file_guard_perboot;
+                let mut db = new_test_db_with_persistent_file_key_lock().unwrap();
+                assert!(db
+                    .load_key_entry(
+                        KeyDescriptor {
+                            domain: Domain::APP,
+                            nspace: 0,
+                            alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
+                            blob: None,
+                        },
+                        KeyEntryLoadBits::BOTH,
+                        33,
+                        |_k, _av| Ok(()),
+                    )
+                    .is_ok());
+                // We should only see a 2 here because we can only return
+                // from load_key_entry when the `_key_guard` expires,
+                // which happens at the end of the scope.
+                assert_eq!(2, state2.load(Ordering::Relaxed));
+            });
+
+            thread::sleep(std::time::Duration::from_millis(1000));
+
+            assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
+
+            // Return the handle from this scope so we can join with the
+            // secondary thread after the key id lock has expired.
+            handle
+            // This is where the `_key_guard` goes out of scope,
+            // which is the reason for concurrent load_key_entry on the same key
+            // to unblock.
+        };
+        // Join with the secondary thread and unwrap, to propagate failing asserts to the
+        // main test thread. We will not see failing asserts in secondary threads otherwise.
+        handle.join().unwrap();
+        Ok(())
+    }
+
     // Helpers
 
     // Checks that the given result is an error containing the given string.
@@ -1292,7 +1549,7 @@
     struct KeyEntryRow {
         id: i64,
         creation_date: String,
-        domain: Option<DomainType>,
+        domain: Option<Domain>,
         namespace: Option<i64>,
         alias: Option<String>,
     }
@@ -1304,7 +1561,10 @@
                 Ok(KeyEntryRow {
                     id: row.get(0)?,
                     creation_date: row.get(1)?,
-                    domain: row.get(2)?,
+                    domain: match row.get(2)? {
+                        Some(i) => Some(Domain(i)),
+                        None => None,
+                    },
                     namespace: row.get(3)?,
                     alias: row.get(4)?,
                 })
@@ -1537,16 +1797,31 @@
 
     fn make_test_key_entry(
         db: &mut KeystoreDB,
-        domain: DomainType,
+        domain: Domain,
         namespace: i64,
         alias: &str,
-    ) -> Result<i64> {
+    ) -> Result<KeyIdGuard> {
         let key_id = db.create_key_entry(domain, namespace)?;
-        db.insert_blob(key_id, SubComponentType::KM_BLOB, TEST_KM_BLOB, 1)?;
-        db.insert_blob(key_id, SubComponentType::CERT, TEST_CERT_BLOB, 1)?;
-        db.insert_blob(key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB, 1)?;
-        db.insert_keyparameter(key_id, &make_test_params())?;
-        db.rebind_alias(key_id, alias, domain, namespace)?;
+        db.insert_blob(
+            &key_id,
+            SubComponentType::KM_BLOB,
+            TEST_KM_BLOB,
+            SecurityLevel::TRUSTED_ENVIRONMENT,
+        )?;
+        db.insert_blob(
+            &key_id,
+            SubComponentType::CERT,
+            TEST_CERT_BLOB,
+            SecurityLevel::TRUSTED_ENVIRONMENT,
+        )?;
+        db.insert_blob(
+            &key_id,
+            SubComponentType::CERT_CHAIN,
+            TEST_CERT_CHAIN_BLOB,
+            SecurityLevel::TRUSTED_ENVIRONMENT,
+        )?;
+        db.insert_keyparameter(&key_id, &make_test_params())?;
+        db.rebind_alias(&key_id, alias, domain, namespace)?;
         Ok(key_id)
     }
 
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index 0326610..63ebe62 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -25,22 +25,19 @@
 //! This crate provides the convenience method `map_or_log_err` to convert `anyhow::Error`
 //! into this wire type. In addition to handling the conversion of `Error`
 //! to the `Result` wire type it handles any other error by mapping it to
-//! `ResponseCode::SystemError` and logs any error condition.
+//! `ResponseCode::SYSTEM_ERROR` and logs any error condition.
 //!
 //! Keystore functions should use `anyhow::Result` to return error conditions, and
 //! context should be added every time an error is forwarded.
 
 use std::cmp::PartialEq;
 
-pub use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode as Ec;
-pub use android_security_keystore2::aidl::android::security::keystore2::ResponseCode as Rc;
-
-use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode::ErrorCode;
-use android_security_keystore2::aidl::android::security::keystore2::ResponseCode::ResponseCode;
+pub use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode::ErrorCode;
+pub use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
 
 use keystore2_selinux as selinux;
 
-use android_security_keystore2::binder::{
+use android_system_keystore2::binder::{
     ExceptionCode, Result as BinderResult, Status as BinderStatus,
 };
 
@@ -60,14 +57,14 @@
 }
 
 impl Error {
-    /// Short hand for `Error::Rc(ResponseCode::SystemError)`
+    /// Short hand for `Error::Rc(ResponseCode::SYSTEM_ERROR)`
     pub fn sys() -> Self {
-        Error::Rc(Rc::SystemError)
+        Error::Rc(ResponseCode::SYSTEM_ERROR)
     }
 
-    /// Short hand for `Error::Rc(ResponseCode::PermissionDenied`
+    /// Short hand for `Error::Rc(ResponseCode::PERMISSION_DENIED`
     pub fn perm() -> Self {
-        Error::Rc(Rc::PermissionDenied)
+        Error::Rc(ResponseCode::PERMISSION_DENIED)
     }
 }
 
@@ -83,7 +80,7 @@
                 let se = s.service_specific_error();
                 if se < 0 {
                     // Negative service specific errors are KM error codes.
-                    Error::Km(s.service_specific_error())
+                    Error::Km(ErrorCode(s.service_specific_error()))
                 } else {
                     // Non negative error codes cannot be KM error codes.
                     // So we create an `Error::Binder` variant to preserve
@@ -102,16 +99,16 @@
 }
 
 /// This function should be used by Keystore service calls to translate error conditions
-/// into `android.security.keystore2.Result` which is imported here as `aidl::Result`
+/// into `android.system.keystore2.Result` which is imported here as `aidl::Result`
 /// and newtyped as AidlResult.
 /// All error conditions get logged by this function.
 /// All `Error::Rc(x)` variants get mapped onto `aidl::Result{x, 0}`.
 /// All `Error::Km(x)` variants get mapped onto
 /// `aidl::Result{aidl::ResponseCode::KeymintErrorCode, x}`.
-/// `selinux::Error::perm()` is mapped on `aidl::Result{aidl::ResponseCode::PermissionDenied, 0}`.
+/// `selinux::Error::perm()` is mapped on `aidl::Result{aidl::ResponseCode::PERMISSION_DENIED, 0}`.
 ///
 /// All non `Error` error conditions get mapped onto
-/// `aidl::Result{aidl::ResponseCode::SystemError}`.
+/// `aidl::Result{aidl::ResponseCode::SYSTEM_ERROR}`.
 ///
 /// `handle_ok` will be called if `result` is `Ok(value)` where `value` will be passed
 /// as argument to `handle_ok`. `handle_ok` must generate an `AidlResult`, typically
@@ -125,7 +122,7 @@
 ///     if (good_but_auth_required) {
 ///         Ok(aidl::ResponseCode::OpAuthRequired)
 ///     } else {
-///         Err(anyhow!(Error::Rc(aidl::ResponseCode::KeyNotFound)))
+///         Err(anyhow!(Error::Rc(aidl::ResponseCode::KEY_NOT_FOUND)))
 ///     }
 /// }
 ///
@@ -140,15 +137,15 @@
             log::error!("{:?}", e);
             let root_cause = e.root_cause();
             let rc = match root_cause.downcast_ref::<Error>() {
-                Some(Error::Rc(rcode)) => *rcode,
-                Some(Error::Km(ec)) => *ec,
+                Some(Error::Rc(rcode)) => rcode.0,
+                Some(Error::Km(ec)) => ec.0,
                 // If an Error::Binder reaches this stage we report a system error.
                 // The exception code and possible service specific error will be
                 // printed in the error log above.
-                Some(Error::Binder(_, _)) => Rc::SystemError,
+                Some(Error::Binder(_, _)) => ResponseCode::SYSTEM_ERROR.0,
                 None => match root_cause.downcast_ref::<selinux::Error>() {
-                    Some(selinux::Error::PermissionDenied) => Rc::PermissionDenied,
-                    _ => Rc::SystemError,
+                    Some(selinux::Error::PermissionDenied) => ResponseCode::PERMISSION_DENIED.0,
+                    _ => ResponseCode::SYSTEM_ERROR.0,
                 },
             };
             Err(BinderStatus::new_service_specific_error(rc, None))
@@ -161,7 +158,7 @@
 pub mod tests {
 
     use super::*;
-    use android_security_keystore2::binder::{
+    use android_system_keystore2::binder::{
         ExceptionCode, Result as BinderResult, Status as BinderStatus,
     };
     use anyhow::{anyhow, Context};
@@ -229,27 +226,27 @@
         );
         // All Error::Rc(x) get mapped on a service specific error
         // code of x.
-        for rc in Rc::Ok..Rc::BackendBusy {
+        for rc in ResponseCode::LOCKED.0..ResponseCode::BACKEND_BUSY.0 {
             assert_eq!(
                 Result::<(), i32>::Err(rc),
-                map_or_log_err(nested_rc(rc), |_| Err(BinderStatus::ok()))
+                map_or_log_err(nested_rc(ResponseCode(rc)), |_| Err(BinderStatus::ok()))
                     .map_err(|s| s.service_specific_error())
             );
         }
 
         // All Keystore Error::Km(x) get mapped on a service
         // specific error of x.
-        for ec in Ec::UNKNOWN_ERROR..Ec::ROOT_OF_TRUST_ALREADY_SET {
+        for ec in ErrorCode::UNKNOWN_ERROR.0..ErrorCode::ROOT_OF_TRUST_ALREADY_SET.0 {
             assert_eq!(
                 Result::<(), i32>::Err(ec),
-                map_or_log_err(nested_ec(ec), |_| Err(BinderStatus::ok()))
+                map_or_log_err(nested_ec(ErrorCode(ec)), |_| Err(BinderStatus::ok()))
                     .map_err(|s| s.service_specific_error())
             );
         }
 
         // All Keymint errors x received through a Binder Result get mapped on
         // a service specific error of x.
-        for ec in Ec::UNKNOWN_ERROR..Ec::ROOT_OF_TRUST_ALREADY_SET {
+        for ec in ErrorCode::UNKNOWN_ERROR.0..ErrorCode::ROOT_OF_TRUST_ALREADY_SET.0 {
             assert_eq!(
                 Result::<(), i32>::Err(ec),
                 map_or_log_err(
@@ -266,44 +263,47 @@
         // service specific error.
         let sse = map_km_error(binder_sse_error(1));
         assert_eq!(Err(Error::Binder(ExceptionCode::SERVICE_SPECIFIC, 1)), sse);
-        // map_or_log_err then maps it on a service specific error of Rc::SystemError.
+        // map_or_log_err then maps it on a service specific error of ResponseCode::SYSTEM_ERROR.
         assert_eq!(
-            Result::<(), i32>::Err(Rc::SystemError),
+            Result::<(), ResponseCode>::Err(ResponseCode::SYSTEM_ERROR),
             map_or_log_err(sse.context("Non negative service specific error."), |_| Err(
                 BinderStatus::ok()
             ))
-            .map_err(|s| s.service_specific_error())
+            .map_err(|s| ResponseCode(s.service_specific_error()))
         );
 
         // map_km_error creates a Error::Binder variant storing the given exception code.
         let binder_exception = map_km_error(binder_exception(ExceptionCode::TRANSACTION_FAILED));
         assert_eq!(Err(Error::Binder(ExceptionCode::TRANSACTION_FAILED, 0)), binder_exception);
-        // map_or_log_err then maps it on a service specific error of Rc::SystemError.
+        // map_or_log_err then maps it on a service specific error of ResponseCode::SYSTEM_ERROR.
         assert_eq!(
-            Result::<(), i32>::Err(Rc::SystemError),
+            Result::<(), ResponseCode>::Err(ResponseCode::SYSTEM_ERROR),
             map_or_log_err(binder_exception.context("Binder Exception."), |_| Err(
                 BinderStatus::ok()
             ))
-            .map_err(|s| s.service_specific_error())
+            .map_err(|s| ResponseCode(s.service_specific_error()))
         );
 
-        // selinux::Error::Perm() needs to be mapped to Rc::PermissionDenied
+        // selinux::Error::Perm() needs to be mapped to ResponseCode::PERMISSION_DENIED
         assert_eq!(
-            Result::<(), i32>::Err(Rc::PermissionDenied),
+            Result::<(), ResponseCode>::Err(ResponseCode::PERMISSION_DENIED),
             map_or_log_err(nested_selinux_perm(), |_| Err(BinderStatus::ok()))
-                .map_err(|s| s.service_specific_error())
+                .map_err(|s| ResponseCode(s.service_specific_error()))
         );
 
         // All other errors get mapped on System Error.
         assert_eq!(
-            Result::<(), i32>::Err(Rc::SystemError),
+            Result::<(), ResponseCode>::Err(ResponseCode::SYSTEM_ERROR),
             map_or_log_err(nested_other_error(), |_| Err(BinderStatus::ok()))
-                .map_err(|s| s.service_specific_error())
+                .map_err(|s| ResponseCode(s.service_specific_error()))
         );
 
         // Result::Ok variants get passed to the ok handler.
-        assert_eq!(Ok(Rc::OpAuthNeeded), map_or_log_err(nested_ok(Rc::OpAuthNeeded), Ok));
-        assert_eq!(Ok(Rc::Ok), map_or_log_err(nested_ok(Rc::Ok), Ok));
+        assert_eq!(Ok(ResponseCode::LOCKED), map_or_log_err(nested_ok(ResponseCode::LOCKED), Ok));
+        assert_eq!(
+            Ok(ResponseCode::SYSTEM_ERROR),
+            map_or_log_err(nested_ok(ResponseCode::SYSTEM_ERROR), Ok)
+        );
 
         Ok(())
     }
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
new file mode 100644
index 0000000..0654b29
--- /dev/null
+++ b/keystore2/src/globals.rs
@@ -0,0 +1,29 @@
+// Copyright 2020, 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.
+
+//! This module holds global state of Keystore such as the thread local
+//! database connections and connections to services that Keystore needs
+//! to talk to.
+
+use crate::database::KeystoreDB;
+use std::cell::RefCell;
+
+thread_local! {
+    /// Database connections are not thread safe, but connecting to the
+    /// same database multiple times is safe as long as each connection is
+    /// used by only one thread. So we store one database connection per
+    /// thread in this thread local key.
+    pub static DB: RefCell<KeystoreDB> =
+            RefCell::new(KeystoreDB::new().expect("Failed to open database."));
+}
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
index f08031e..5698c96 100644
--- a/keystore2/src/key_parameter.rs
+++ b/keystore2/src/key_parameter.rs
@@ -17,18 +17,15 @@
 //! and the methods to work with KeyParameter.
 
 use crate::error::Error as KeystoreError;
-use crate::error::Rc;
+use crate::error::ResponseCode;
+
 pub use android_hardware_keymint::aidl::android::hardware::keymint::{
-    Algorithm, Algorithm::Algorithm as AlgorithmType, BlockMode,
-    BlockMode::BlockMode as BlockModeType, Digest, Digest::Digest as DigestType, EcCurve,
-    EcCurve::EcCurve as EcCurveType, HardwareAuthenticatorType,
-    HardwareAuthenticatorType::HardwareAuthenticatorType as HardwareAuthenticatorTypeType,
-    KeyOrigin, KeyOrigin::KeyOrigin as KeyOriginType,
-    KeyParameter::KeyParameter as AidlKeyParameter, KeyPurpose,
-    KeyPurpose::KeyPurpose as KeyPurposeType, PaddingMode,
-    PaddingMode::PaddingMode as PaddingModeType, SecurityLevel,
-    SecurityLevel::SecurityLevel as SecurityLevelType, Tag, Tag::Tag as TagType,
+    Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
+    HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
+    KeyParameter::KeyParameter as KmKeyParameter, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
+    SecurityLevel::SecurityLevel, Tag::Tag,
 };
+use android_system_keystore2::aidl::android::system::keystore2::Authorization::Authorization;
 use anyhow::{Context, Result};
 use rusqlite::types::{FromSql, Null, ToSql, ToSqlOutput};
 use rusqlite::{Result as SqlResult, Row};
@@ -37,7 +34,7 @@
 #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
 pub struct KeyParameter {
     key_parameter_value: KeyParameterValue,
-    security_level: SecurityLevelType,
+    security_level: SecurityLevel,
 }
 
 /// KeyParameterValue holds a value corresponding to one of the Tags defined in
@@ -47,23 +44,23 @@
     /// Associated with Tag:INVALID
     Invalid,
     /// Set of purposes for which the key may be used
-    KeyPurpose(KeyPurposeType),
+    KeyPurpose(KeyPurpose),
     /// Cryptographic algorithm with which the key is used
-    Algorithm(AlgorithmType),
+    Algorithm(Algorithm),
     /// Size of the key , in bits
     KeySize(i32),
     /// Block cipher mode(s) with which the key may be used
-    BlockMode(BlockModeType),
+    BlockMode(BlockMode),
     /// Digest algorithms that may be used with the key to perform signing and verification
-    Digest(DigestType),
+    Digest(Digest),
     /// Padding modes that may be used with the key.  Relevant to RSA, AES and 3DES keys.
-    PaddingMode(PaddingModeType),
+    PaddingMode(PaddingMode),
     /// Can the caller provide a nonce for nonce-requiring operations
     CallerNonce,
     /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
     MinMacLength(i32),
     /// The elliptic curve
-    EcCurve(EcCurveType),
+    EcCurve(EcCurve),
     /// Value of the public exponent for an RSA key pair
     RSAPublicExponent(i64),
     /// An attestation certificate for the generated key should contain an application-scoped
@@ -93,7 +90,7 @@
     /// No authentication is required to use this key
     NoAuthRequired,
     /// The types of user authenticators that may be used to authorize this key
-    HardwareAuthenticatorType(HardwareAuthenticatorTypeType),
+    HardwareAuthenticatorType(HardwareAuthenticatorType),
     /// The time in seconds for which the key is authorized for use, after user authentication
     AuthTimeout(i32),
     /// The key may be used after authentication timeout if device is still on-body
@@ -114,7 +111,7 @@
     /// Specifies the date and time the key was created
     CreationDateTime(i64),
     /// Specifies where the key was created, if known
-    KeyOrigin(KeyOriginType),
+    KeyOrigin(KeyOrigin),
     /// The key used by verified boot to validate the operating system booted
     RootOfTrust(Vec<u8>),
     /// System OS version with which the key may be used
@@ -164,12 +161,12 @@
 
 impl KeyParameter {
     /// Create an instance of KeyParameter, given the value and the security level.
-    pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevelType) -> Self {
+    pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> Self {
         KeyParameter { key_parameter_value, security_level }
     }
 
     /// Returns the tag given the KeyParameter instance.
-    pub fn get_tag(&self) -> TagType {
+    pub fn get_tag(&self) -> Tag {
         match self.key_parameter_value {
             KeyParameterValue::Invalid => Tag::INVALID,
             KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
@@ -233,9 +230,19 @@
     }
 
     /// Returns the security level of a KeyParameter.
-    pub fn security_level(&self) -> &SecurityLevelType {
+    pub fn security_level(&self) -> &SecurityLevel {
         &self.security_level
     }
+
+    /// An authorization is a KeyParameter with an associated security level that is used
+    /// to convey the key characteristics to keystore clients. This function consumes
+    /// an internal KeyParameter representation to produce the Authorization wire type.
+    pub fn into_authorization(self) -> Authorization {
+        Authorization {
+            securityLevel: self.security_level,
+            keyParameter: self.key_parameter_value.convert_to_wire(),
+        }
+    }
 }
 
 /// This struct is defined to postpone converting rusqlite column value to the
@@ -264,15 +271,15 @@
     fn to_sql(&self) -> SqlResult<ToSqlOutput> {
         match self {
             KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
-            KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(*k as u32)),
-            KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(*a as u32)),
+            KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
+            KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
             KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
-            KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(*b as u32)),
-            KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(*d as u32)),
-            KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(*p as u32)),
+            KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
+            KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
+            KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
             KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
             KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
-            KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(*e as u32)),
+            KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
             KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
             KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
             KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
@@ -285,7 +292,7 @@
             KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
             KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
             KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
-            KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(*h as u32)),
+            KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
             KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
             KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
             KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
@@ -294,7 +301,7 @@
             KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
             KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
             KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
-            KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(*k as u32)),
+            KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
             KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
             KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
             KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
@@ -328,25 +335,25 @@
     /// This filtering is enforced at a higher level and here we support conversion for all the
     /// variants.
     pub fn new_from_sql(
-        tag_val: TagType,
+        tag_val: Tag,
         data: &SqlField,
-        security_level_val: SecurityLevelType,
+        security_level_val: SecurityLevel,
     ) -> Result<Self> {
         let key_param_value = match tag_val {
             Tag::INVALID => KeyParameterValue::Invalid,
             Tag::PURPOSE => {
-                let key_purpose: KeyPurposeType = data
+                let key_purpose: i32 = data
                     .get()
-                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
                     .context("Failed to read sql data for tag: PURPOSE.")?;
-                KeyParameterValue::KeyPurpose(key_purpose)
+                KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
             }
             Tag::ALGORITHM => {
-                let algorithm: AlgorithmType = data
+                let algorithm: i32 = data
                     .get()
-                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
                     .context("Failed to read sql data for tag: ALGORITHM.")?;
-                KeyParameterValue::Algorithm(algorithm)
+                KeyParameterValue::Algorithm(Algorithm(algorithm))
             }
             Tag::KEY_SIZE => {
                 let key_size: i32 =
@@ -354,25 +361,25 @@
                 KeyParameterValue::KeySize(key_size)
             }
             Tag::BLOCK_MODE => {
-                let block_mode: BlockModeType = data
+                let block_mode: i32 = data
                     .get()
-                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
                     .context("Failed to read sql data for tag: BLOCK_MODE.")?;
-                KeyParameterValue::BlockMode(block_mode)
+                KeyParameterValue::BlockMode(BlockMode(block_mode))
             }
             Tag::DIGEST => {
-                let digest: DigestType = data
+                let digest: i32 = data
                     .get()
-                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
                     .context("Failed to read sql data for tag: DIGEST.")?;
-                KeyParameterValue::Digest(digest)
+                KeyParameterValue::Digest(Digest(digest))
             }
             Tag::PADDING => {
-                let padding: PaddingModeType = data
+                let padding: i32 = data
                     .get()
-                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
                     .context("Failed to read sql data for tag: PADDING.")?;
-                KeyParameterValue::PaddingMode(padding)
+                KeyParameterValue::PaddingMode(PaddingMode(padding))
             }
             Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
             Tag::MIN_MAC_LENGTH => {
@@ -381,11 +388,11 @@
                 KeyParameterValue::MinMacLength(min_mac_length)
             }
             Tag::EC_CURVE => {
-                let ec_curve: EcCurveType = data
+                let ec_curve: i32 = data
                     .get()
-                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
                     .context("Failed to read sql data for tag: EC_CURVE.")?;
-                KeyParameterValue::EcCurve(ec_curve)
+                KeyParameterValue::EcCurve(EcCurve(ec_curve))
             }
             Tag::RSA_PUBLIC_EXPONENT => {
                 let rsa_pub_exponent: i64 =
@@ -436,11 +443,13 @@
             }
             Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
             Tag::USER_AUTH_TYPE => {
-                let user_auth_type: HardwareAuthenticatorTypeType = data
+                let user_auth_type: i32 = data
                     .get()
-                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
                     .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
-                KeyParameterValue::HardwareAuthenticatorType(user_auth_type)
+                KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
+                    user_auth_type,
+                ))
             }
             Tag::AUTH_TIMEOUT => {
                 let auth_timeout: i32 =
@@ -467,11 +476,11 @@
                 KeyParameterValue::CreationDateTime(creation_datetime)
             }
             Tag::ORIGIN => {
-                let origin: KeyOriginType = data
+                let origin: i32 = data
                     .get()
-                    .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
+                    .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
                     .context("Failed to read sql data for tag: ORIGIN.")?;
-                KeyParameterValue::KeyOrigin(origin)
+                KeyParameterValue::KeyOrigin(KeyOrigin(origin))
             }
             Tag::ROOT_OF_TRUST => {
                 let root_of_trust: Vec<u8> =
@@ -581,7 +590,7 @@
                 KeyParameterValue::ConfirmationToken(confirmation_token)
             }
             _ => {
-                return Err(KeystoreError::Rc(Rc::ValueCorrupted))
+                return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
                     .context("Failed to decode Tag enum from value.")?
             }
         };
@@ -590,296 +599,323 @@
 }
 
 /// Macro rules for converting key parameter to/from wire type.
-/// This macro takes three different pieces of information about each of the KeyParameterValue
-/// variants.
-/// 1. variant name
-/// 2. tag name corresponding to the variant
-/// 3. the field name in the AidlKeyParameter struct, in which information about this variant is
-/// stored when converted
+/// This macro takes between three and four different pieces of information about each
+/// of the KeyParameterValue variants:
+/// 1. The KeyParameterValue variant name,
+/// 2. the tag name corresponding to the variant,
+/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
+///    stored when converted, and
+/// 4. an optional enum type name when the nested value is of enum type.
 /// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
 /// the two conversion methods: convert_to_wire() and convert_from_wire().
 /// ## Example
 /// ```
 /// implement_key_parameter_conversion_to_from_wire! {
 ///         Invalid, INVALID, na;
-///         KeyPurpose, PURPOSE, integer;
+///         KeyPurpose, PURPOSE, integer, KeyPurpose;
 ///         CallerNonce, CALLER_NONCE, boolValue;
 ///         UserSecureID, USER_SECURE_ID, longInteger;
 ///         ApplicationID, APPLICATION_ID, blob;
-///         ActiveDateTime, ACTIVE_DATETIME, dateTime;
 /// }
 /// ```
 /// expands to:
 /// ```
-/// pub fn convert_to_wire(self) -> AidlKeyParameter {
+/// pub fn convert_to_wire(self) -> KmKeyParameter {
 ///         match self {
-///                 KeyParameterValue::Invalid => AidlKeyParameter {
+///                 KeyParameterValue::Invalid => KmKeyParameter {
 ///                         tag: Tag::INVALID,
 ///                         ..Default::default()
 ///                 },
-///                 KeyParameterValue::KeyPurpose(v) => AidlKeyParameter {
+///                 KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
 ///                         tag: Tag::PURPOSE,
-///                         integer: v,
+///                         integer: v.0,
 ///                         ..Default::default()
 ///                 },
-///                 KeyParameterValue::CallerNonce => AidlKeyParameter {
+///                 KeyParameterValue::CallerNonce => KmKeyParameter {
 ///                         tag: Tag::CALLER_NONCE,
 ///                         boolValue: true,
 ///                         ..Default::default()
 ///                 },
-///                 KeyParameterValue::UserSecureID(v) => AidlKeyParameter {
+///                 KeyParameterValue::UserSecureID(v) => KmKeyParameter {
 ///                         tag: Tag::USER_SECURE_ID,
 ///                         longInteger: v,
 ///                         ..Default::default()
 ///                 },
-///                 KeyParameterValue::ApplicationID(v) => AidlKeyParameter {
+///                 KeyParameterValue::ApplicationID(v) => KmKeyParameter {
 ///                         tag: Tag::APPLICATION_ID,
 ///                         blob: v,
 ///                         ..Default::default()
 ///                 },
-///                 KeyParameterValue::ActiveDateTime(v) => AidlKeyParameter {
-///                         tag: Tag::ACTIVE_DATETIME,
-///                         dateTime: v,
-///                         ..Default::default()
-///                 },
 ///         }
 /// }
 /// ```
 /// and
 /// ```
-/// pub fn convert_from_wire(aidl_kp: AidlKeyParameter) -> KeyParameterValue {
+/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
 ///         match aidl_kp {
-///                 AidlKeyParameter {
+///                 KmKeyParameter {
 ///                         tag: Tag::INVALID,
 ///                         ..
 ///                 } => KeyParameterValue::Invalid,
-///                 AidlKeyParameter {
+///                 KmKeyParameter {
 ///                         tag: Tag::PURPOSE,
 ///                         integer: v,
 ///                         ..
-///                 } => KeyParameterValue::KeyPurpose(v),
-///                 AidlKeyParameter {
+///                 } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
+///                 KmKeyParameter {
 ///                         tag: Tag::CALLER_NONCE,
 ///                         boolValue: true,
 ///                         ..
 ///                 } => KeyParameterValue::CallerNonce,
-///                 AidlKeyParameter {
+///                 KmKeyParameter {
 ///                          tag: Tag::USER_SECURE_ID,
 ///                          longInteger: v,
 ///                          ..
 ///                 } => KeyParameterValue::UserSecureID(v),
-///                 AidlKeyParameter {
+///                 KmKeyParameter {
 ///                          tag: Tag::APPLICATION_ID,
 ///                          blob: v,
 ///                          ..
 ///                 } => KeyParameterValue::ApplicationID(v),
-///                 AidlKeyParameter {
-///                          tag: Tag::ACTIVE_DATETIME,
-///                          dateTime: v,
-///                          ..
-///                 } => KeyParameterValue::ActiveDateTime(v),
 ///                 _ => KeyParameterValue::Invalid,
 ///         }
 /// }
 ///
 macro_rules! implement_key_parameter_conversion_to_from_wire {
-     // There are three groups of rules in this macro.
-     // 1. The first group contains the rule which acts as the public interface. It takes the input
-     //    given to this macro and prepares it to be given as input to the two groups of rules
-     //    mentioned below.
-     // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
-     // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
-     //
-     // Input to this macro is first handled by the first macro rule (belonging to the first
-     // group above), which pre-processes the input such that rules in the other two groups
-     // generate the code for the two methods, when called recursively.
-     // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
-     // four macro rules in the second two groups. These four rules intend to do the following
-     // tasks respectively:
-     // i) generates match arms related to Invalid KeyParameterValue variant.
-     // ii) generates match arms related to boolValue field in AidlKeyParameter struct.
-     // iii) generates match arms related to all the other fields in AidlKeyParameter struct.
-     // iv) generates the method definition including the match arms generated from the above
-     // three recursive macro rules.
+    // There are three groups of rules in this macro.
+    // 1. The first group contains the rule which acts as the public interface. It takes the input
+    //    given to this macro and prepares it to be given as input to the two groups of rules
+    //    mentioned below.
+    // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
+    // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
+    //
+    // Input to this macro is first handled by the first macro rule (belonging to the first
+    // group above), which pre-processes the input such that rules in the other two groups
+    // generate the code for the two methods, when called recursively.
+    // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
+    // four macro rules in the second two groups. These four rules intend to do the following
+    // tasks respectively:
+    // i) generates match arms related to Invalid KeyParameterValue variant.
+    // ii) generates match arms related to boolValue field in KmKeyParameter struct.
+    // iii) generates match arms related to all the other fields in KmKeyParameter struct.
+    // iv) generates the method definition including the match arms generated from the above
+    // three recursive macro rules.
 
-     // This rule is applied on the input given to the macro invocations from outside the macro.
-     ($($variant:ident, $tag_name:ident, $field_name:ident;)*) => {
-         // pre-processes input to target the rules that generate convert_to_wire() method.
-         implement_key_parameter_conversion_to_from_wire! {@to
-             [], $($variant, $tag_name, $field_name;)*
-         }
-         // pre-processes input to target the rules that generate convert_from_wire() method.
-         implement_key_parameter_conversion_to_from_wire! {@from
-             [], $($variant, $tag_name, $field_name;)*
-         }
-     };
+    // This rule is applied on the input given to the macro invocations from outside the macro.
+    ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
+        // pre-processes input to target the rules that generate convert_to_wire() method.
+        implement_key_parameter_conversion_to_from_wire! {@to
+            [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
+        }
+        // pre-processes input to target the rules that generate convert_from_wire() method.
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [], $($variant, $tag_name, $field_name $(,$enum_type)?;)*
+        }
+    };
 
-     // Following four rules (belonging to the aforementioned second group) generate
-     // convert_to_wire() conversion method.
-     // -----------------------------------------------------------------------
-     // This rule handles Invalid variant.
-     // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
-     // KeyParameterValue::Invalid => AidlKeyParameter {
-     //                                 tag: Tag::INVALID,
-     //                                 ..Default::default()
-     //                               },
-     (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
-         implement_key_parameter_conversion_to_from_wire! {@to
-             [$($out)*
-                 KeyParameterValue::Invalid => AidlKeyParameter {
-                     tag: Tag::INVALID,
-                     ..Default::default()
-                 },
-             ], $($in)*
-         }
-     };
-     // This rule handles all variants that correspond to bool values.
-     // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
-     // a match arm like:
-     // KeyParameterValue::CallerNonce => AidlKeyParameter {
-     //                                      tag: Tag::CALLER_NONCE,
-     //                                      boolValue: true,
-     //                                      ..Default::default()
-     //                                   },
-     (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
-         implement_key_parameter_conversion_to_from_wire! {@to
-             [$($out)*
-                 KeyParameterValue::$variant => AidlKeyParameter {
-                     tag: Tag::$tag_val,
-                     boolValue: true,
-                     ..Default::default()
-                 },
-             ], $($in)*
-         }
-     };
-     // This rule handles all variants that are neither invalid nor bool values
-     // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
-     // AidlKeyParameter).
-     // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
-     // like: KeyParameterValue::ConfirmationToken(v) => AidlKeyParameter {
-     //                                                      tag: Tag::CONFIRMATION_TOKEN,
-     //                                                      blob: v,
-     //                                                      ..Default::default(),
-     //                                                }
-     (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
-         implement_key_parameter_conversion_to_from_wire! {@to
-             [$($out)*
-                 KeyParameterValue::$variant(v) => AidlKeyParameter {
-                     tag: Tag::$tag_val,
-                     $field: v,
-                     ..Default::default()
-                 },
-             ], $($in)*
-         }
-     };
-     // After all the match arms are generated by the above three rules, this rule combines them
-     // into the convert_to_wire() method.
-     (@to [$($out:tt)*], ) => {
-         /// Conversion of key parameter to wire type
-         pub fn convert_to_wire(self) -> AidlKeyParameter {
-             match self {
-                 $($out)*
-             }
-         }
-     };
+    // Following four rules (belonging to the aforementioned second group) generate
+    // convert_to_wire() conversion method.
+    // -----------------------------------------------------------------------
+    // This rule handles Invalid variant.
+    // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
+    // KeyParameterValue::Invalid => KmKeyParameter {
+    //                                   tag: Tag::INVALID,
+    //                                   ..Default::default()
+    //                               },
+    (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@to
+            [$($out)*
+                KeyParameterValue::Invalid => KmKeyParameter {
+                    tag: Tag::INVALID,
+                    ..Default::default()
+                },
+            ], $($in)*
+        }
+    };
+    // This rule handles all variants that correspond to bool values.
+    // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates
+    // a match arm like:
+    // KeyParameterValue::CallerNonce => KmKeyParameter {
+    //                                       tag: Tag::CALLER_NONCE,
+    //                                       boolValue: true,
+    //                                       ..Default::default()
+    //                                   },
+    (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@to
+            [$($out)*
+                KeyParameterValue::$variant => KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    boolValue: true,
+                    ..Default::default()
+                },
+            ], $($in)*
+        }
+    };
+    // This rule handles all enum variants.
+    // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
+    // like: KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
+    //                                               tag: Tag::PURPOSE,
+    //                                               integer: v.0,
+    //                                               ..Default::default(),
+    //                                           },
+    (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
+       implement_key_parameter_conversion_to_from_wire! {@to
+           [$($out)*
+               KeyParameterValue::$variant(v) => KmKeyParameter {
+                   tag: Tag::$tag_val,
+                   $field: v.0,
+                   ..Default::default()
+               },
+           ], $($in)*
+       }
+    };
+    // This rule handles all variants that are neither invalid nor bool values nor enums
+    // (i.e. all variants which correspond to integer, longInteger, and blob fields in
+    // KmKeyParameter).
+    // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
+    // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
+    //                                                      tag: Tag::CONFIRMATION_TOKEN,
+    //                                                      blob: v,
+    //                                                      ..Default::default(),
+    //                                                  },
+    (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@to
+            [$($out)*
+                KeyParameterValue::$variant(v) => KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    $field: v,
+                    ..Default::default()
+                },
+            ], $($in)*
+        }
+    };
+    // After all the match arms are generated by the above three rules, this rule combines them
+    // into the convert_to_wire() method.
+    (@to [$($out:tt)*], ) => {
+        /// Conversion of key parameter to wire type
+        pub fn convert_to_wire(self) -> KmKeyParameter {
+            match self {
+                $($out)*
+            }
+        }
+    };
 
-     // Following four rules (belonging to the aforementioned third group) generate
-     // convert_from_wire() conversion method.
-     // ------------------------------------------------------------------------
-     // This rule handles Invalid variant.
-     // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
-     // AidlKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
-     (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
-         implement_key_parameter_conversion_to_from_wire! {@from
-             [$($out)*
-                 AidlKeyParameter {
-                     tag: Tag::INVALID,
-                     ..
-                 } => KeyParameterValue::Invalid,
-             ], $($in)*
-         }
-     };
-     // This rule handles all variants that correspond to bool values.
-     // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
-     // AidlKeyParameter {
-     //      tag: Tag::CALLER_NONCE,
-     //      boolValue: true,
-     //      ..
-     // } => KeyParameterValue::CallerNonce,
-     (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
-         implement_key_parameter_conversion_to_from_wire! {@from
-             [$($out)*
-                 AidlKeyParameter {
-                     tag: Tag::$tag_val,
-                     boolValue: true,
-                     ..
-                 } => KeyParameterValue::$variant,
-             ], $($in)*
-         }
-     };
-     // This rule handles all variants that are neither invalid nor bool values
-     // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
-     // AidlKeyParameter).
-     // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
-     // like:
-     // AidlKeyParameter {
-     //         tag: Tag::CONFIRMATION_TOKEN,
-     //         blob: v,
-     //         ..,
-     // } => KeyParameterValue::ConfirmationToken(v),
-     (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
-         implement_key_parameter_conversion_to_from_wire! {@from
-             [$($out)*
-                 AidlKeyParameter {
-                     tag: Tag::$tag_val,
-                     $field: v,
-                     ..
-                 } => KeyParameterValue::$variant(v),
-             ], $($in)*
-         }
-     };
-     // After all the match arms are generated by the above three rules, this rule combines them
-     // into the convert_from_wire() method.
-     (@from [$($out:tt)*], ) => {
-         /// Conversion of key parameter from wire type
-         pub fn convert_from_wire(aidl_kp: AidlKeyParameter) -> KeyParameterValue {
-             match aidl_kp {
-                 $($out)*
-                 _ => KeyParameterValue::Invalid,
-             }
-         }
-     };
+    // Following four rules (belonging to the aforementioned third group) generate
+    // convert_from_wire() conversion method.
+    // ------------------------------------------------------------------------
+    // This rule handles Invalid variant.
+    // On an input: 'Invalid, INVALID, na;' it generates a match arm like:
+    // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
+    (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [$($out)*
+                KmKeyParameter {
+                    tag: Tag::INVALID,
+                    ..
+                } => KeyParameterValue::Invalid,
+            ], $($in)*
+        }
+    };
+    // This rule handles all variants that correspond to bool values.
+    // On an input like: 'CallerNonce, CALLER_NONCE, boolValue;' it generates a match arm like:
+    // KmKeyParameter {
+    //      tag: Tag::CALLER_NONCE,
+    //      boolValue: true,
+    //      ..
+    // } => KeyParameterValue::CallerNonce,
+    (@from [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [$($out)*
+                KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    boolValue: true,
+                    ..
+                } => KeyParameterValue::$variant,
+            ], $($in)*
+        }
+    };
+    // This rule handles all enum variants.
+    // On an input like: 'KeyPurpose, PURPOSE, integer, KeyPurpose;' it generates a match arm
+    // like:
+    // KmKeyParameter {
+    //         tag: Tag::PURPOSE,
+    //         integer: v,
+    //         ..,
+    // } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
+    (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident, $enum_type:ident; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [$($out)*
+                KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    $field: v,
+                    ..
+                } => KeyParameterValue::$variant($enum_type(v)),
+            ], $($in)*
+        }
+    };
+    // This rule handles all variants that are neither invalid nor bool values nor enums
+    // (i.e. all variants which correspond to integer, longInteger, and blob fields in
+    // KmKeyParameter).
+    // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
+    // like:
+    // KmKeyParameter {
+    //         tag: Tag::CONFIRMATION_TOKEN,
+    //         blob: v,
+    //         ..,
+    // } => KeyParameterValue::ConfirmationToken(v),
+    (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
+        implement_key_parameter_conversion_to_from_wire! {@from
+            [$($out)*
+                KmKeyParameter {
+                    tag: Tag::$tag_val,
+                    $field: v,
+                    ..
+                } => KeyParameterValue::$variant(v),
+            ], $($in)*
+        }
+    };
+    // After all the match arms are generated by the above three rules, this rule combines them
+    // into the convert_from_wire() method.
+    (@from [$($out:tt)*], ) => {
+        /// Conversion of key parameter from wire type
+        pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
+            match aidl_kp {
+                $($out)*
+                _ => KeyParameterValue::Invalid,
+            }
+        }
+    };
 }
 
 impl KeyParameterValue {
     // Invoke the macro that generates the code for key parameter conversion to/from wire type
     // with all possible variants of KeyParameterValue. Each line corresponding to a variant
     // contains: variant identifier, tag value, and the related field name (i.e.
-    // boolValue/integer/longInteger/dateTime/blob) in the AidlKeyParameter.
+    // boolValue/integer/longInteger/blob) in the KmKeyParameter.
     implement_key_parameter_conversion_to_from_wire! {
         Invalid, INVALID, na;
-        KeyPurpose, PURPOSE, integer;
-        Algorithm, ALGORITHM, integer;
+        KeyPurpose, PURPOSE, integer, KeyPurpose;
+        Algorithm, ALGORITHM, integer, Algorithm;
         KeySize, KEY_SIZE, integer;
-        BlockMode, BLOCK_MODE, integer;
-        Digest, DIGEST, integer;
-        PaddingMode, PADDING, integer;
+        BlockMode, BLOCK_MODE, integer, BlockMode;
+        Digest, DIGEST, integer, Digest;
+        PaddingMode, PADDING, integer, PaddingMode;
         CallerNonce, CALLER_NONCE, boolValue;
         MinMacLength, MIN_MAC_LENGTH, integer;
-        EcCurve, EC_CURVE, integer;
+        EcCurve, EC_CURVE, integer, EcCurve;
         RSAPublicExponent, RSA_PUBLIC_EXPONENT, longInteger;
         IncludeUniqueID, INCLUDE_UNIQUE_ID, boolValue;
         BootLoaderOnly, BOOTLOADER_ONLY, boolValue;
         RollbackResistance, ROLLBACK_RESISTANCE, boolValue;
-        ActiveDateTime, ACTIVE_DATETIME, dateTime;
-        OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, dateTime;
-        UsageExpireDateTime, USAGE_EXPIRE_DATETIME, dateTime;
+        ActiveDateTime, ACTIVE_DATETIME, longInteger;
+        OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, longInteger;
+        UsageExpireDateTime, USAGE_EXPIRE_DATETIME, longInteger;
         MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, integer;
         MaxUsesPerBoot, MAX_USES_PER_BOOT, integer;
         UserID, USER_ID, integer;
         UserSecureID, USER_SECURE_ID, longInteger;
         NoAuthRequired, NO_AUTH_REQUIRED, boolValue;
-        HardwareAuthenticatorType, USER_AUTH_TYPE, integer;
+        HardwareAuthenticatorType, USER_AUTH_TYPE, integer, HardwareAuthenticatorType;
         AuthTimeout, AUTH_TIMEOUT, integer;
         AllowWhileOnBody, ALLOW_WHILE_ON_BODY, boolValue;
         TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, boolValue;
@@ -887,8 +923,8 @@
         UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, boolValue;
         ApplicationID, APPLICATION_ID, blob;
         ApplicationData, APPLICATION_DATA, blob;
-        CreationDateTime, CREATION_DATETIME, dateTime;
-        KeyOrigin, ORIGIN, integer;
+        CreationDateTime, CREATION_DATETIME, longInteger;
+        KeyOrigin, ORIGIN, integer, KeyOrigin;
         RootOfTrust, ROOT_OF_TRUST, blob;
         OSVersion, OS_VERSION, integer;
         OSPatchLevel, OS_PATCHLEVEL, integer;
@@ -960,9 +996,9 @@
         insert_into_keyparameter(
             &db,
             1,
-            Tag::ALGORITHM,
-            &Algorithm::RSA,
-            SecurityLevel::STRONGBOX,
+            Tag::ALGORITHM.0,
+            &Algorithm::RSA.0,
+            SecurityLevel::STRONGBOX.0,
         )?;
         let key_param = query_from_keyparameter(&db)?;
         assert_eq!(Tag::ALGORITHM, key_param.get_tag());
@@ -976,7 +1012,7 @@
     #[test]
     fn test_new_from_sql_i32() -> Result<()> {
         let db = init_db()?;
-        insert_into_keyparameter(&db, 1, Tag::KEY_SIZE, &1024, SecurityLevel::STRONGBOX)?;
+        insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
         let key_param = query_from_keyparameter(&db)?;
         assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
         assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
@@ -992,9 +1028,9 @@
         insert_into_keyparameter(
             &db,
             1,
-            Tag::RSA_PUBLIC_EXPONENT,
+            Tag::RSA_PUBLIC_EXPONENT.0,
             &(i64::MAX),
-            SecurityLevel::STRONGBOX,
+            SecurityLevel::STRONGBOX.0,
         )?;
         let key_param = query_from_keyparameter(&db)?;
         assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
@@ -1010,7 +1046,7 @@
     #[test]
     fn test_new_from_sql_bool() -> Result<()> {
         let db = init_db()?;
-        insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE, &Null, SecurityLevel::STRONGBOX)?;
+        insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
         let key_param = query_from_keyparameter(&db)?;
         assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
         assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
@@ -1027,9 +1063,9 @@
         insert_into_keyparameter(
             &db,
             1,
-            Tag::APPLICATION_ID,
+            Tag::APPLICATION_ID.0,
             &app_id_bytes,
-            SecurityLevel::STRONGBOX,
+            SecurityLevel::STRONGBOX.0,
         )?;
         let key_param = query_from_keyparameter(&db)?;
         assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
@@ -1140,7 +1176,7 @@
     #[test]
     fn test_invalid_conversion_from_sql() -> Result<()> {
         let db = init_db()?;
-        insert_into_keyparameter(&db, 1, Tag::ALGORITHM, &Null, 1)?;
+        insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
         tests::check_result_contains_error_string(
             query_from_keyparameter(&db),
             "Failed to read sql data for tag: ALGORITHM.",
@@ -1175,7 +1211,7 @@
     ) -> Result<()> {
         db.execute(
             "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
-VALUES(?, ?, ?, ?);",
+                VALUES(?, ?, ?, ?);",
             params![key_id, tag, *value, security_level],
         )?;
         Ok(())
@@ -1185,32 +1221,33 @@
     fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
         db.execute(
             "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
-VALUES(?, ?, ?, ?);",
-            params![key_id, kp.get_tag(), kp.key_parameter_value(), kp.security_level()],
+                VALUES(?, ?, ?, ?);",
+            params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
         )?;
         Ok(())
     }
 
     /// Helper method to query a row from keyparameter table
     fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
-        let mut stmt = db.prepare(
-            "SELECT tag, data, security_level FROM
-persistent.keyparameter",
-        )?;
+        let mut stmt =
+            db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
         let mut rows = stmt.query(NO_PARAMS)?;
         let row = rows.next()?.unwrap();
-        Ok(KeyParameter::new_from_sql(row.get(0)?, &SqlField(1, row), row.get(2)?)?)
+        Ok(KeyParameter::new_from_sql(
+            Tag(row.get(0)?),
+            &SqlField(1, row),
+            SecurityLevel(row.get(2)?),
+        )?)
     }
 }
 
 /// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
-/// KeyParameter, for the five different types used in AidlKeyParameter, in addition to Invalid
+/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
 /// key parameter.
 /// i) bool
 /// ii) integer
 /// iii) longInteger
-/// iv) dateTime
-/// v) blob
+/// iv) blob
 #[cfg(test)]
 mod wire_tests {
     use crate::key_parameter::*;
@@ -1236,7 +1273,7 @@
         );
         let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
         assert_eq!(Tag::PURPOSE, actual.tag);
-        assert_eq!(KeyPurpose::ENCRYPT, actual.integer);
+        assert_eq!(KeyPurpose::ENCRYPT.0, actual.integer);
     }
     #[test]
     fn test_convert_to_wire_long_integer() {
@@ -1247,16 +1284,6 @@
         assert_eq!(i64::MAX, actual.longInteger);
     }
     #[test]
-    fn test_convert_to_wire_date_time() {
-        let kp = KeyParameter::new(
-            KeyParameterValue::ActiveDateTime(i64::MAX),
-            SecurityLevel::STRONGBOX,
-        );
-        let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
-        assert_eq!(Tag::ACTIVE_DATETIME, actual.tag);
-        assert_eq!(i64::MAX, actual.dateTime);
-    }
-    #[test]
     fn test_convert_to_wire_blob() {
         let kp = KeyParameter::new(
             KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
@@ -1270,22 +1297,22 @@
     /// unit tests for from conversion
     #[test]
     fn test_convert_from_wire_invalid() {
-        let aidl_kp = AidlKeyParameter { tag: Tag::INVALID, ..Default::default() };
+        let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
         let actual = KeyParameterValue::convert_from_wire(aidl_kp);
         assert_eq!(KeyParameterValue::Invalid, actual);
     }
     #[test]
     fn test_convert_from_wire_bool() {
         let aidl_kp =
-            AidlKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
+            KmKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
         let actual = KeyParameterValue::convert_from_wire(aidl_kp);
         assert_eq!(KeyParameterValue::CallerNonce, actual);
     }
     #[test]
     fn test_convert_from_wire_integer() {
-        let aidl_kp = AidlKeyParameter {
+        let aidl_kp = KmKeyParameter {
             tag: Tag::PURPOSE,
-            integer: KeyPurpose::ENCRYPT,
+            integer: KeyPurpose::ENCRYPT.0,
             ..Default::default()
         };
         let actual = KeyParameterValue::convert_from_wire(aidl_kp);
@@ -1293,7 +1320,7 @@
     }
     #[test]
     fn test_convert_from_wire_long_integer() {
-        let aidl_kp = AidlKeyParameter {
+        let aidl_kp = KmKeyParameter {
             tag: Tag::USER_SECURE_ID,
             longInteger: i64::MAX,
             ..Default::default()
@@ -1302,18 +1329,8 @@
         assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
     }
     #[test]
-    fn test_convert_from_wire_date_time() {
-        let aidl_kp = AidlKeyParameter {
-            tag: Tag::ACTIVE_DATETIME,
-            dateTime: i64::MAX,
-            ..Default::default()
-        };
-        let actual = KeyParameterValue::convert_from_wire(aidl_kp);
-        assert_eq!(KeyParameterValue::ActiveDateTime(i64::MAX), actual);
-    }
-    #[test]
     fn test_convert_from_wire_blob() {
-        let aidl_kp = AidlKeyParameter {
+        let aidl_kp = KmKeyParameter {
             tag: Tag::CONFIRMATION_TOKEN,
             blob: String::from("ConfirmationToken").into_bytes(),
             ..Default::default()
diff --git a/keystore2/src/keystore2_main.rs b/keystore2/src/keystore2_main.rs
new file mode 100644
index 0000000..dea0a93
--- /dev/null
+++ b/keystore2/src/keystore2_main.rs
@@ -0,0 +1,59 @@
+// Copyright 2020, 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.
+
+//! This crate implements Keystore 2.0.
+
+use binder::Interface;
+use keystore2::service::KeystoreService;
+use log::{error, info};
+use std::panic;
+
+static KS2_SERVICE_NAME: &str = "android.system.keystore2";
+
+/// Keystore 2.0 takes one argument which is a path indicating its designated working directory.
+fn main() {
+    // Initialize android logging.
+    android_logger::init_once(
+        android_logger::Config::default().with_tag("keystore2").with_min_level(log::Level::Debug),
+    );
+    // Redirect panic messages to logcat.
+    panic::set_hook(Box::new(|panic_info| {
+        error!("{}", panic_info);
+    }));
+
+    // Saying hi.
+    info!("Keystore2 is starting.");
+
+    let mut args = std::env::args();
+    args.next().expect("That's odd. How is there not even a first argument?");
+    if let Some(dir) = args.next() {
+        if std::env::set_current_dir(dir.clone()).is_err() {
+            panic!("Failed to set working directory {}.", dir)
+        }
+    } else {
+        panic!("Must specify a working directory.");
+    }
+
+    let ks_service = KeystoreService::new_native_binder().unwrap_or_else(|e| {
+        panic!("Failed to create service {} because of {:?}.", KS2_SERVICE_NAME, e);
+    });
+    binder::add_service(KS2_SERVICE_NAME, ks_service.as_binder()).unwrap_or_else(|e| {
+        panic!("Failed to register service {} because of {:?}.", KS2_SERVICE_NAME, e);
+    });
+
+    info!("Successfully registered Keystore 2.0 service.");
+    info!("Joining threadpool now.");
+
+    binder::ProcessState::join_thread_pool();
+}
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
index b5fef3e..3e13c5f 100644
--- a/keystore2/src/lib.rs
+++ b/keystore2/src/lib.rs
@@ -14,8 +14,14 @@
 
 //! This crate implements the Android Keystore 2.0 service.
 
+mod crypto;
 pub mod database;
 pub mod error;
+pub mod globals;
 /// Internal Representation of Key Parameter and convenience functions.
 pub mod key_parameter;
+pub mod operation;
 pub mod permission;
+pub mod security_level;
+pub mod service;
+pub mod utils;
diff --git a/keystore2/src/operation.rs b/keystore2/src/operation.rs
new file mode 100644
index 0000000..14edc6c
--- /dev/null
+++ b/keystore2/src/operation.rs
@@ -0,0 +1,815 @@
+// Copyright 2020, 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.
+
+//! This crate implements the `IKeystoreOperation` AIDL interface, which represents
+//! an ongoing key operation, as well as the operation database, which is mainly
+//! required for tracking operations for the purpose of pruning.
+//! This crate also implements an operation pruning strategy.
+//!
+//! Operations implement the API calls update, finish, and abort.
+//! Additionally, an operation can be dropped and pruned. The former
+//! happens if the client deletes a binder to the operation object.
+//! An existing operation may get pruned when running out of operation
+//! slots and a new operation takes precedence.
+//!
+//! ## Operation Lifecycle
+//! An operation gets created when the client calls `IKeystoreSecurityLevel::create`.
+//! It may receive zero or more update request. The lifecycle ends when:
+//!  * `update` yields an error.
+//!  * `finish` is called.
+//!  * `abort` is called.
+//!  * The operation gets dropped.
+//!  * The operation gets pruned.
+//! `Operation` has an `Outcome` member. While the outcome is `Outcome::Unknown`,
+//! the operation is active and in a good state. Any of the above conditions may
+//! change the outcome to one of the defined outcomes Success, Abort, Dropped,
+//! Pruned, or ErrorCode. The latter is chosen in the case of an unexpected error, during
+//! `update` or `finish`. `Success` is chosen iff `finish` completes without error.
+//! Note that all operations get dropped eventually in the sense that they lose
+//! their last reference and get destroyed. At that point, the fate of the operation
+//! gets logged. However, an operation will transition to `Outcome::Dropped` iff
+//! the operation was still active (`Outcome::Unknown`) at that time.
+//!
+//! ## Operation Dropping
+//! To observe the dropping of an operation, we have to make sure that there
+//! are no strong references to the IBinder representing this operation.
+//! This would be simple enough if the operation object would need to be accessed
+//! only by transactions. But to perform pruning, we have to retain a reference to the
+//! original operation object.
+//!
+//! ## Operation Pruning
+//! Pruning an operation happens during the creation of a new operation.
+//! We have to iterate through the operation database to find a suitable
+//! candidate. Then we abort and finalize this operation setting its outcome to
+//! `Outcome::Pruned`. The corresponding KeyMint operation slot will have been freed
+//! up at this point, but the `Operation` object lingers. When the client
+//! attempts to use the operation again they will receive
+//! ErrorCode::INVALID_OPERATION_HANDLE indicating that the operation no longer
+//! exits. This should be the cue for the client to destroy its binder.
+//! At that point the operation gets dropped.
+//!
+//! ## Architecture
+//! The `IKeystoreOperation` trait is implemented by `KeystoreOperation`.
+//! This acts as a proxy object holding a strong reference to actual operation
+//! implementation `Operation`.
+//!
+//! ```
+//! struct KeystoreOperation {
+//!     operation: Mutex<Option<Arc<Operation>>>,
+//! }
+//! ```
+//!
+//! The `Mutex` serves two purposes. It provides interior mutability allowing
+//! us to set the Option to None. We do this when the life cycle ends during
+//! a call to `update`, `finish`, or `abort`. As a result most of the Operation
+//! related resources are freed. The `KeystoreOperation` proxy object still
+//! lingers until dropped by the client.
+//! The second purpose is to protect operations against concurrent usage.
+//! Failing to lock this mutex yields `ResponseCode::OPERATION_BUSY` and indicates
+//! a programming error in the client.
+//!
+//! Note that the Mutex only protects the operation against concurrent client calls.
+//! We still retain weak references to the operation in the operation database:
+//!
+//! ```
+//! struct OperationDb {
+//!     operations: Mutex<Vec<Weak<Operation>>>
+//! }
+//! ```
+//!
+//! This allows us to access the operations for the purpose of pruning.
+//! We do this in three phases.
+//!  1. We gather the pruning information. Besides non mutable information,
+//!     we access `last_usage` which is protected by a mutex.
+//!     We only lock this mutex for single statements at a time. During
+//!     this phase we hold the operation db lock.
+//!  2. We choose a pruning candidate by computing the pruning resistance
+//!     of each operation. We do this entirely with information we now
+//!     have on the stack without holding any locks.
+//!     (See `OperationDb::prune` for more details on the pruning strategy.)
+//!  3. During pruning we briefly lock the operation database again to get the
+//!     the pruning candidate by index. We then attempt to abort the candidate.
+//!     If the candidate was touched in the meantime or is currently fulfilling
+//!     a request (i.e., the client calls update, finish, or abort),
+//!     we go back to 1 and try again.
+//!
+//! So the outer Mutex in `KeystoreOperation::operation` only protects
+//! operations against concurrent client calls but not against concurrent
+//! pruning attempts. This is what the `Operation::outcome` mutex is used for.
+//!
+//! ```
+//! struct Operation {
+//!     ...
+//!     outcome: Mutex<Outcome>,
+//!     ...
+//! }
+//! ```
+//!
+//! Any request that can change the outcome, i.e., `update`, `finish`, `abort`,
+//! `drop`, and `prune` has to take the outcome lock and check if the outcome
+//! is still `Outcome::Unknown` before entering. `prune` is special in that
+//! it will `try_lock`, because we don't want to be blocked on a potentially
+//! long running request at another operation. If it fails to get the lock
+//! the operation is either being touched, which changes its pruning resistance,
+//! or it transitions to its end-of-life, which means we may get a free slot.
+//! Either way, we have to revaluate the pruning scores.
+
+use std::{
+    collections::HashMap,
+    sync::{Arc, Mutex, MutexGuard, Weak},
+    time::Duration,
+    time::Instant,
+};
+
+use crate::error::{map_km_error, map_or_log_err, Error, ErrorCode, ResponseCode};
+use crate::utils::Asp;
+use android_hardware_keymint::aidl::android::hardware::keymint::{
+    ByteArray::ByteArray, IKeyMintOperation::IKeyMintOperation,
+    KeyParameter::KeyParameter as KmParam, KeyParameterArray::KeyParameterArray, Tag::Tag,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    IKeystoreOperation::BnKeystoreOperation, IKeystoreOperation::IKeystoreOperation,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface};
+
+/// Operations have `Outcome::Unknown` as long as they are active. They transition
+/// to one of the other variants exactly once. The distinction in outcome is mainly
+/// for the statistic.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+enum Outcome {
+    Unknown,
+    Success,
+    Abort,
+    Dropped,
+    Pruned,
+    ErrorCode(ErrorCode),
+}
+
+/// Operation bundles all of the operation related resources and tracks the operation's
+/// outcome.
+#[derive(Debug)]
+pub struct Operation {
+    // The index of this operation in the OperationDb.
+    index: usize,
+    km_op: Asp,
+    last_usage: Mutex<Instant>,
+    outcome: Mutex<Outcome>,
+    owner: u32, // Uid of the operation's owner.
+}
+
+struct PruningInfo {
+    last_usage: Instant,
+    owner: u32,
+    index: usize,
+}
+
+// We don't except more than 32KiB of data in `update`, `updateAad`, and `finish`.
+const MAX_RECEIVE_DATA: usize = 0x8000;
+
+impl Operation {
+    /// Constructor
+    pub fn new(index: usize, km_op: Box<dyn IKeyMintOperation>, owner: u32) -> Self {
+        Self {
+            index,
+            km_op: Asp::new(km_op.as_binder()),
+            last_usage: Mutex::new(Instant::now()),
+            outcome: Mutex::new(Outcome::Unknown),
+            owner,
+        }
+    }
+
+    fn get_pruning_info(&self) -> Option<PruningInfo> {
+        // An operation may be finalized.
+        if let Ok(guard) = self.outcome.try_lock() {
+            match *guard {
+                Outcome::Unknown => {}
+                // If the outcome is any other than unknown, it has been finalized,
+                // and we can no longer consider it for pruning.
+                _ => return None,
+            }
+        }
+        // Else: If we could not grab the lock, this means that the operation is currently
+        //       being used and it may be transitioning to finalized or it was simply updated.
+        //       In any case it is fair game to consider it for pruning. If the operation
+        //       transitioned to a final state, we will notice when we attempt to prune, and
+        //       a subsequent attempt to create a new operation will succeed.
+        Some(PruningInfo {
+            // Expect safety:
+            // `last_usage` is locked only for primitive single line statements.
+            // There is no chance to panic and poison the mutex.
+            last_usage: *self.last_usage.lock().expect("In get_pruning_info."),
+            owner: self.owner,
+            index: self.index,
+        })
+    }
+
+    fn prune(&self, last_usage: Instant) -> Result<(), Error> {
+        let mut locked_outcome = match self.outcome.try_lock() {
+            Ok(guard) => match *guard {
+                Outcome::Unknown => guard,
+                _ => return Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)),
+            },
+            Err(_) => return Err(Error::Rc(ResponseCode::OPERATION_BUSY)),
+        };
+
+        // In `OperationDb::prune`, which is our caller, we first gather the pruning
+        // information including the last usage. When we select a candidate
+        // we call `prune` on that candidate passing the last_usage
+        // that we gathered earlier. If the actual last usage
+        // has changed since than, it means the operation was busy in the
+        // meantime, which means that we have to reevaluate the pruning score.
+        //
+        // Expect safety:
+        // `last_usage` is locked only for primitive single line statements.
+        // There is no chance to panic and poison the mutex.
+        if *self.last_usage.lock().expect("In Operation::prune()") != last_usage {
+            return Err(Error::Rc(ResponseCode::OPERATION_BUSY));
+        }
+        *locked_outcome = Outcome::Pruned;
+
+        let km_op: Box<dyn IKeyMintOperation> = match self.km_op.get_interface() {
+            Ok(km_op) => km_op,
+            Err(e) => {
+                log::error!("In prune: Failed to get KeyMintOperation interface.\n    {:?}", e);
+                return Err(Error::sys());
+            }
+        };
+
+        // We abort the operation. If there was an error we log it but ignore it.
+        if let Err(e) = map_km_error(km_op.abort()) {
+            log::error!("In prune: KeyMint::abort failed with {:?}.", e);
+        }
+
+        Ok(())
+    }
+
+    // This function takes a Result from a KeyMint call and inspects it for errors.
+    // If an error was found it updates the given `locked_outcome` accordingly.
+    // It forwards the Result unmodified.
+    // The precondition to this call must be *locked_outcome == Outcome::Unknown.
+    // Ideally the `locked_outcome` came from a successful call to `check_active`
+    // see below.
+    fn update_outcome<T>(
+        &self,
+        locked_outcome: &mut Outcome,
+        err: Result<T, Error>,
+    ) -> Result<T, Error> {
+        match &err {
+            Err(Error::Km(e)) => *locked_outcome = Outcome::ErrorCode(*e),
+            Err(_) => *locked_outcome = Outcome::ErrorCode(ErrorCode::UNKNOWN_ERROR),
+            Ok(_) => (),
+        }
+        err
+    }
+
+    // This function grabs the outcome lock and checks the current outcome state.
+    // If the outcome is still `Outcome::Unknown`, this function returns
+    // the locked outcome for further updates. In any other case it returns
+    // ErrorCode::INVALID_OPERATION_HANDLE indicating that this operation has
+    // been finalized and is no longer active.
+    fn check_active(&self) -> Result<MutexGuard<Outcome>> {
+        let guard = self.outcome.lock().expect("In check_active.");
+        match *guard {
+            Outcome::Unknown => Ok(guard),
+            _ => Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)).context(format!(
+                "In check_active: Call on finalized operation with outcome: {:?}.",
+                *guard
+            )),
+        }
+    }
+
+    // This function checks the amount of input data sent to us. We reject any buffer
+    // exceeding MAX_RECEIVE_DATA bytes as input to `update`, `update_aad`, and `finish`
+    // in order to force clients into using reasonable limits.
+    fn check_input_length(data: &[u8]) -> Result<()> {
+        if data.len() > MAX_RECEIVE_DATA {
+            // This error code is unique, no context required here.
+            return Err(anyhow!(Error::Rc(ResponseCode::TOO_MUCH_DATA)));
+        }
+        Ok(())
+    }
+
+    // Update the last usage to now.
+    fn touch(&self) {
+        // Expect safety:
+        // `last_usage` is locked only for primitive single line statements.
+        // There is no chance to panic and poison the mutex.
+        *self.last_usage.lock().expect("In touch.") = Instant::now();
+    }
+
+    /// Implementation of `IKeystoreOperation::updateAad`.
+    /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
+    fn update_aad(&self, aad_input: &[u8]) -> Result<()> {
+        let mut outcome = self.check_active().context("In update_aad")?;
+        Self::check_input_length(aad_input).context("In update_aad")?;
+        self.touch();
+
+        let params = KeyParameterArray {
+            params: vec![KmParam {
+                tag: Tag::ASSOCIATED_DATA,
+                blob: aad_input.into(),
+                ..Default::default()
+            }],
+        };
+
+        let mut out_params: Option<KeyParameterArray> = None;
+        let mut output: Option<ByteArray> = None;
+
+        let km_op: Box<dyn IKeyMintOperation> =
+            self.km_op.get_interface().context("In update: Failed to get KeyMintOperation.")?;
+
+        self.update_outcome(
+            &mut *outcome,
+            map_km_error(km_op.update(
+                Some(&params),
+                None,
+                // TODO Get auth token from enforcement module if required.
+                None,
+                // TODO Get verification token from enforcement module if required.
+                None,
+                &mut out_params,
+                &mut output,
+            )),
+        )
+        .context("In update_aad: KeyMint::update failed.")?;
+
+        Ok(())
+    }
+
+    /// Implementation of `IKeystoreOperation::update`.
+    /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
+    fn update(&self, input: &[u8]) -> Result<Option<Vec<u8>>> {
+        let mut outcome = self.check_active().context("In update")?;
+        Self::check_input_length(input).context("In update")?;
+        self.touch();
+
+        let mut out_params: Option<KeyParameterArray> = None;
+        let mut output: Option<ByteArray> = None;
+
+        let km_op: Box<dyn IKeyMintOperation> =
+            self.km_op.get_interface().context("In update: Failed to get KeyMintOperation.")?;
+
+        self.update_outcome(
+            &mut *outcome,
+            map_km_error(km_op.update(
+                None,
+                Some(input),
+                // TODO Get auth token from enforcement module if required.
+                None,
+                // TODO Get verification token from enforcement module if required.
+                None,
+                &mut out_params,
+                &mut output,
+            )),
+        )
+        .context("In update: KeyMint::update failed.")?;
+
+        match output {
+            Some(blob) => Ok(Some(blob.data)),
+            None => Ok(None),
+        }
+    }
+
+    /// Implementation of `IKeystoreOperation::finish`.
+    /// Refer to the AIDL spec at system/hardware/interfaces/keystore2 for details.
+    fn finish(&self, input: Option<&[u8]>, signature: Option<&[u8]>) -> Result<Option<Vec<u8>>> {
+        let mut outcome = self.check_active().context("In finish")?;
+        if let Some(input) = input {
+            Self::check_input_length(input).context("In finish")?;
+        }
+        self.touch();
+
+        let mut out_params: Option<KeyParameterArray> = None;
+
+        let km_op: Box<dyn IKeyMintOperation> =
+            self.km_op.get_interface().context("In finish: Failed to get KeyMintOperation.")?;
+
+        let output = self
+            .update_outcome(
+                &mut *outcome,
+                map_km_error(km_op.finish(
+                    None,
+                    input,
+                    signature,
+                    // TODO Get auth token from enforcement module if required.
+                    None,
+                    // TODO Get verification token from enforcement module if required.
+                    None,
+                    &mut out_params,
+                )),
+            )
+            .context("In finish: KeyMint::finish failed.")?;
+
+        // At this point the operation concluded successfully.
+        *outcome = Outcome::Success;
+
+        if output.is_empty() {
+            Ok(None)
+        } else {
+            Ok(Some(output))
+        }
+    }
+
+    /// Aborts the operation if it is active. IFF the operation is aborted the outcome is
+    /// set to `outcome`. `outcome` must reflect the reason for the abort. Since the operation
+    /// gets aborted `outcome` must not be `Operation::Success` or `Operation::Unknown`.
+    fn abort(&self, outcome: Outcome) -> Result<()> {
+        let mut locked_outcome = self.check_active().context("In abort")?;
+        *locked_outcome = outcome;
+        let km_op: Box<dyn IKeyMintOperation> =
+            self.km_op.get_interface().context("In abort: Failed to get KeyMintOperation.")?;
+
+        map_km_error(km_op.abort()).context("In abort: KeyMint::abort failed.")
+    }
+}
+
+impl Drop for Operation {
+    fn drop(&mut self) {
+        if let Ok(Outcome::Unknown) = self.outcome.get_mut() {
+            // If the operation was still active we call abort, setting
+            // the outcome to `Outcome::Dropped`
+            if let Err(e) = self.abort(Outcome::Dropped) {
+                log::error!("While dropping Operation: abort failed:\n    {:?}", e);
+            }
+        }
+    }
+}
+
+/// The OperationDb holds weak references to all ongoing operations.
+/// Its main purpose is to facilitate operation pruning.
+#[derive(Debug, Default)]
+pub struct OperationDb {
+    // TODO replace Vec with WeakTable when the weak_table crate becomes
+    // available.
+    operations: Mutex<Vec<Weak<Operation>>>,
+}
+
+impl OperationDb {
+    /// Creates a new OperationDb.
+    pub fn new() -> Self {
+        Self { operations: Mutex::new(Vec::new()) }
+    }
+
+    /// Creates a new operation.
+    /// This function takes a KeyMint operation and an associated
+    /// owner uid and returns a new Operation wrapped in a `std::sync::Arc`.
+    pub fn create_operation(
+        &self,
+        km_op: Box<dyn IKeyMintOperation>,
+        owner: u32,
+    ) -> Arc<Operation> {
+        // We use unwrap because we don't allow code that can panic while locked.
+        let mut operations = self.operations.lock().expect("In create_operation.");
+
+        let mut index: usize = 0;
+        // First we iterate through the operation slots to try and find an unused
+        // slot. If we don't find one, we append the new entry instead.
+        match (*operations).iter_mut().find(|s| {
+            index += 1;
+            s.upgrade().is_none()
+        }) {
+            Some(free_slot) => {
+                let new_op = Arc::new(Operation::new(index - 1, km_op, owner));
+                *free_slot = Arc::downgrade(&new_op);
+                new_op
+            }
+            None => {
+                let new_op = Arc::new(Operation::new(operations.len(), km_op, owner));
+                operations.push(Arc::downgrade(&new_op));
+                new_op
+            }
+        }
+    }
+
+    fn get(&self, index: usize) -> Option<Arc<Operation>> {
+        self.operations.lock().expect("In OperationDb::get.").get(index).and_then(|op| op.upgrade())
+    }
+
+    /// Attempts to prune an operation.
+    ///
+    /// This function is used during operation creation, i.e., by
+    /// `KeystoreSecurityLevel::create_operation`, to try and free up an operation slot
+    /// if it got `ErrorCode::TOO_MANY_OPERATIONS` from the KeyMint backend. It is not
+    /// guaranteed that an operation slot is available after this call successfully
+    /// returned for various reasons. E.g., another thread may have snatched up the newly
+    /// available slot. Callers may have to call prune multiple times before they get a
+    /// free operation slot. Prune may also return `Err(Error::Rc(ResponseCode::BACKEND_BUSY))`
+    /// which indicates that no prunable operation was found.
+    ///
+    /// To find a suitable candidate we compute the malus for the caller and each existing
+    /// operation. The malus is the inverse of the pruning power (caller) or pruning
+    /// resistance (existing operation).
+    ///
+    /// The malus is based on the number of sibling operations and age. Sibling
+    /// operations are operations that have the same owner (UID).
+    ///
+    /// Every operation, existing or new, starts with a malus of 1. Every sibling
+    /// increases the malus by one. The age is the time since an operation was last touched.
+    /// It increases the malus by log6(<age in seconds> + 1) rounded down to the next
+    /// integer. So the malus increases stepwise after 5s, 35s, 215s, ...
+    /// Of two operations with the same malus the least recently used one is considered
+    /// weaker.
+    ///
+    /// For the caller to be able to prune an operation it must find an operation
+    /// with a malus higher than its own.
+    ///
+    /// The malus can be expressed as
+    /// ```
+    /// malus = 1 + no_of_siblings + floor(log6(age_in_seconds + 1))
+    /// ```
+    /// where the constant `1` accounts for the operation under consideration.
+    /// In reality we compute it as
+    /// ```
+    /// caller_malus = 1 + running_siblings
+    /// ```
+    /// because the new operation has no age and is not included in the `running_siblings`,
+    /// and
+    /// ```
+    /// running_malus = running_siblings + floor(log6(age_in_seconds + 1))
+    /// ```
+    /// because a running operation is included in the `running_siblings` and it has
+    /// an age.
+    ///
+    /// ## Example
+    /// A caller with no running operations has a malus of 1. Young (age < 5s) operations
+    /// also with no siblings have a malus of one and cannot be pruned by the caller.
+    /// We have to find an operation that has at least one sibling or is older than 5s.
+    ///
+    /// A caller with one running operation has a malus of 2. Now even young siblings
+    /// or single child aging (5s <= age < 35s) operations are off limit. An aging
+    /// sibling of two, however, would have a malus of 3 and would be fair game.
+    ///
+    /// ## Rationale
+    /// Due to the limitation of KeyMint operation slots, we cannot get around pruning or
+    /// a single app could easily DoS KeyMint.
+    /// Keystore 1.0 used to always prune the least recently used operation. This at least
+    /// guaranteed that new operations can always be started. With the increased usage
+    /// of Keystore we saw increased pruning activity which can lead to a livelock
+    /// situation in the worst case.
+    ///
+    /// With the new pruning strategy we want to provide well behaved clients with
+    /// progress assurances while punishing DoS attempts. As a result of this
+    /// strategy we can be in the situation where no operation can be pruned and the
+    /// creation of a new operation fails. This allows single child operations which
+    /// are frequently updated to complete, thereby breaking up livelock situations
+    /// and facilitating system wide progress.
+    ///
+    /// ## Update
+    /// We also allow callers to cannibalize their own sibling operations if no other
+    /// slot can be found. In this case the least recently used sibling is pruned.
+    pub fn prune(&self, caller: u32) -> Result<(), Error> {
+        loop {
+            // Maps the uid of the owner to the number of operations that owner has
+            // (running_siblings). More operations per owner lowers the pruning
+            // resistance of the operations of that owner. Whereas the number of
+            // ongoing operations of the caller lowers the pruning power of the caller.
+            let mut owners: HashMap<u32, u64> = HashMap::new();
+            let mut pruning_info: Vec<PruningInfo> = Vec::new();
+
+            let now = Instant::now();
+            self.operations
+                .lock()
+                .expect("In OperationDb::prune: Trying to lock self.operations.")
+                .iter()
+                .for_each(|op| {
+                    if let Some(op) = op.upgrade() {
+                        if let Some(p_info) = op.get_pruning_info() {
+                            let owner = p_info.owner;
+                            pruning_info.push(p_info);
+                            // Count operations per owner.
+                            *owners.entry(owner).or_insert(0) += 1;
+                        }
+                    }
+                });
+
+            let caller_malus = 1u64 + *owners.entry(caller).or_default();
+
+            // We iterate through all operations computing the malus and finding
+            // the candidate with the highest malus which must also be higher
+            // than the caller_malus.
+            struct CandidateInfo {
+                index: usize,
+                malus: u64,
+                last_usage: Instant,
+                age: Duration,
+            }
+            let mut oldest_caller_op: Option<CandidateInfo> = None;
+            let candidate = pruning_info.iter().fold(
+                None,
+                |acc: Option<CandidateInfo>, &PruningInfo { last_usage, owner, index }| {
+                    // Compute the age of the current operation.
+                    let age = now
+                        .checked_duration_since(last_usage)
+                        .unwrap_or_else(|| Duration::new(0, 0));
+
+                    // Find the least recently used sibling as an alternative pruning candidate.
+                    if owner == caller {
+                        if let Some(CandidateInfo { age: a, .. }) = oldest_caller_op {
+                            if age > a {
+                                oldest_caller_op =
+                                    Some(CandidateInfo { index, malus: 0, last_usage, age });
+                            }
+                        } else {
+                            oldest_caller_op =
+                                Some(CandidateInfo { index, malus: 0, last_usage, age });
+                        }
+                    }
+
+                    // Compute the malus of the current operation.
+                    // Expect safety: Every owner in pruning_info was counted in
+                    // the owners map. So this unwrap cannot panic.
+                    let malus = *owners
+                        .get(&owner)
+                        .expect("This is odd. We should have counted every owner in pruning_info.")
+                        + ((age.as_secs() + 1) as f64).log(6.0).floor() as u64;
+
+                    // Now check if the current operation is a viable/better candidate
+                    // the one currently stored in the accumulator.
+                    match acc {
+                        // First we have to find any operation that is prunable by the caller.
+                        None => {
+                            if caller_malus < malus {
+                                Some(CandidateInfo { index, malus, last_usage, age })
+                            } else {
+                                None
+                            }
+                        }
+                        // If we have found one we look for the operation with the worst score.
+                        // If there is a tie, the older operation is considered weaker.
+                        Some(CandidateInfo { index: i, malus: m, last_usage: l, age: a }) => {
+                            if malus > m || (malus == m && age > a) {
+                                Some(CandidateInfo { index, malus, last_usage, age })
+                            } else {
+                                Some(CandidateInfo { index: i, malus: m, last_usage: l, age: a })
+                            }
+                        }
+                    }
+                },
+            );
+
+            // If we did not find a suitable candidate we may cannibalize our oldest sibling.
+            let candidate = candidate.or(oldest_caller_op);
+
+            match candidate {
+                Some(CandidateInfo { index, malus: _, last_usage, age: _ }) => {
+                    match self.get(index) {
+                        Some(op) => {
+                            match op.prune(last_usage) {
+                                // We successfully freed up a slot.
+                                Ok(()) => break Ok(()),
+                                // This means the operation we tried to prune was on its way
+                                // out. It also means that the slot it had occupied was freed up.
+                                Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)) => break Ok(()),
+                                // This means the operation we tried to prune was currently
+                                // servicing a request. There are two options.
+                                // * Assume that it was touched, which means that its
+                                //   pruning resistance increased. In that case we have
+                                //   to start over and find another candidate.
+                                // * Assume that the operation is transitioning to end-of-life.
+                                //   which means that we got a free slot for free.
+                                // If we assume the first but the second is true, we prune
+                                // a good operation without need (aggressive approach).
+                                // If we assume the second but the first is true, our
+                                // caller will attempt to create a new KeyMint operation,
+                                // fail with `ErrorCode::TOO_MANY_OPERATIONS`, and call
+                                // us again (conservative approach).
+                                Err(Error::Rc(ResponseCode::OPERATION_BUSY)) => {
+                                    // We choose the conservative approach, because
+                                    // every needlessly pruned operation can impact
+                                    // the user experience.
+                                    // To switch to the aggressive approach replace
+                                    // the following line with `continue`.
+                                    break Ok(());
+                                }
+
+                                // The candidate may have been touched so the score
+                                // has changed since our evaluation.
+                                _ => continue,
+                            }
+                        }
+                        // This index does not exist any more. The operation
+                        // in this slot was dropped. Good news, a slot
+                        // has freed up.
+                        None => break Ok(()),
+                    }
+                }
+                // We did not get a pruning candidate.
+                None => break Err(Error::Rc(ResponseCode::BACKEND_BUSY)),
+            }
+        }
+    }
+}
+
+/// Implementation of IKeystoreOperation.
+pub struct KeystoreOperation {
+    operation: Mutex<Option<Arc<Operation>>>,
+}
+
+impl KeystoreOperation {
+    /// Creates a new operation instance wrapped in a
+    /// BnKeystoreOperation proxy object. It also
+    /// calls `IBinder::set_requesting_sid` on the new interface, because
+    /// we need it for checking Keystore permissions.
+    pub fn new_native_binder(operation: Arc<Operation>) -> impl IKeystoreOperation + Send {
+        let result =
+            BnKeystoreOperation::new_binder(Self { operation: Mutex::new(Some(operation)) });
+        result.as_binder().set_requesting_sid(true);
+        result
+    }
+
+    /// Grabs the outer operation mutex and calls `f` on the locked operation.
+    /// The function also deletes the operation if it returns with an error or if
+    /// `delete_op` is true.
+    fn with_locked_operation<T, F>(&self, f: F, delete_op: bool) -> Result<T>
+    where
+        for<'a> F: FnOnce(&'a Operation) -> Result<T>,
+    {
+        let mut delete_op: bool = delete_op;
+        match self.operation.try_lock() {
+            Ok(mut mutex_guard) => {
+                let result = match &*mutex_guard {
+                    Some(op) => {
+                        let result = f(&*op);
+                        // Any error here means we can discard the operation.
+                        if result.is_err() {
+                            delete_op = true;
+                        }
+                        result
+                    }
+                    None => Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE))
+                        .context("In KeystoreOperation::with_locked_operation"),
+                };
+
+                if delete_op {
+                    // We give up our reference to the Operation, thereby freeing up our
+                    // internal resources and ending the wrapped KeyMint operation.
+                    // This KeystoreOperation object will still be owned by an SpIBinder
+                    // until the client drops its remote reference.
+                    *mutex_guard = None;
+                }
+                result
+            }
+            Err(_) => Err(Error::Rc(ResponseCode::OPERATION_BUSY))
+                .context("In KeystoreOperation::with_locked_operation"),
+        }
+    }
+}
+
+impl binder::Interface for KeystoreOperation {}
+
+impl IKeystoreOperation for KeystoreOperation {
+    fn updateAad(&self, aad_input: &[u8]) -> binder::public_api::Result<()> {
+        map_or_log_err(
+            self.with_locked_operation(
+                |op| op.update_aad(aad_input).context("In KeystoreOperation::updateAad"),
+                false,
+            ),
+            Ok,
+        )
+    }
+
+    fn update(&self, input: &[u8]) -> binder::public_api::Result<Option<Vec<u8>>> {
+        map_or_log_err(
+            self.with_locked_operation(
+                |op| op.update(input).context("In KeystoreOperation::update"),
+                false,
+            ),
+            Ok,
+        )
+    }
+    fn finish(
+        &self,
+        input: Option<&[u8]>,
+        signature: Option<&[u8]>,
+    ) -> binder::public_api::Result<Option<Vec<u8>>> {
+        map_or_log_err(
+            self.with_locked_operation(
+                |op| op.finish(input, signature).context("In KeystoreOperation::finish"),
+                true,
+            ),
+            Ok,
+        )
+    }
+
+    fn abort(&self) -> binder::public_api::Result<()> {
+        map_or_log_err(
+            self.with_locked_operation(
+                |op| op.abort(Outcome::Abort).context("In KeystoreOperation::abort"),
+                true,
+            ),
+            Ok,
+        )
+    }
+}
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
index 1880623..0917256 100644
--- a/keystore2/src/permission.rs
+++ b/keystore2/src/permission.rs
@@ -18,9 +18,9 @@
 //! It also provides KeystorePerm and KeyPerm as convenience wrappers for the SELinux permission
 //! defined by keystore2 and keystore2_key respectively.
 
-use android_security_keystore2::aidl::android::security::keystore2::KeyPermission;
-
-use android_security_keystore2::aidl::android::security::keystore2::KeyDescriptor::KeyDescriptor;
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
+};
 
 use std::cmp::PartialEq;
 use std::convert::From;
@@ -137,10 +137,10 @@
     =>
     {
         $(#[$m])*
-        pub struct $name(pub $aidl_name::$aidl_name);
+        pub struct $name(pub $aidl_name);
 
-        impl From<$aidl_name::$aidl_name> for $name {
-            fn from (p: $aidl_name::$aidl_name) -> Self {
+        impl From<$aidl_name> for $name {
+            fn from (p: $aidl_name) -> Self {
                 match p {
                     $aidl_name::$def_name => Self($aidl_name::$def_name),
                     $($aidl_name::$element_name => Self($aidl_name::$element_name),)*
@@ -149,8 +149,8 @@
             }
         }
 
-        impl Into<$aidl_name::$aidl_name> for $name {
-            fn into(self) -> $aidl_name::$aidl_name {
+        impl Into<$aidl_name> for $name {
+            fn into(self) -> $aidl_name {
                 self.0
             }
         }
@@ -192,17 +192,17 @@
     ///                       KeyPerm::get_info().to_selinux());
     /// ```
     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-    KeyPerm from KeyPermission with default (None, none) {
-        Delete,         selinux name: delete;
-        GenUniqueId,    selinux name: gen_unique_id;
-        GetInfo,        selinux name: get_info;
-        Grant,          selinux name: grant;
-        ManageBlob,     selinux name: manage_blob;
-        Rebind,         selinux name: rebind;
-        ReqForcedOp,    selinux name: req_forced_op;
-        Update,         selinux name: update;
-        Use,            selinux name: use;
-        UseDevId,       selinux name: use_dev_id;
+    KeyPerm from KeyPermission with default (NONE, none) {
+        DELETE,         selinux name: delete;
+        GEN_UNIQUE_ID,  selinux name: gen_unique_id;
+        GET_INFO,       selinux name: get_info;
+        GRANT,          selinux name: grant;
+        MANAGE_BLOB,    selinux name: manage_blob;
+        REBIND,         selinux name: rebind;
+        REQ_FORCED_OP,  selinux name: req_forced_op;
+        UPDATE,         selinux name: update;
+        USE,            selinux name: use;
+        USE_DEV_ID,     selinux name: use_dev_id;
     }
 );
 
@@ -356,7 +356,7 @@
                 let p = self.vec.0 & (1 << self.pos);
                 self.pos += 1;
                 if p != 0 {
-                    return Some(KeyPerm::from(p));
+                    return Some(KeyPerm::from(KeyPermission(p)));
                 }
             }
         }
@@ -365,7 +365,7 @@
 
 impl From<KeyPerm> for KeyPermSet {
     fn from(p: KeyPerm) -> Self {
-        Self(p.0 as i32)
+        Self((p.0).0 as i32)
     }
 }
 
@@ -400,7 +400,7 @@
 macro_rules! key_perm_set {
     () => { KeyPermSet(0) };
     ($head:expr $(, $tail:expr)* $(,)?) => {
-        KeyPermSet($head.0 as i32 $(| $tail.0 as i32)*)
+        KeyPermSet(($head.0).0 $(| ($tail.0).0)*)
     };
 }
 
@@ -429,8 +429,8 @@
 /// Attempts to grant the grant permission are always denied.
 ///
 /// The only viable target domains are
-///  * `Domain::App` in which case u:r:keystore:s0 is used as target context and
-///  * `Domain::SELinux` in which case the `key.namespace_` parameter is looked up in
+///  * `Domain::APP` in which case u:r:keystore:s0 is used as target context and
+///  * `Domain::SELINUX` in which case the `key.nspace` parameter is looked up in
 ///                      SELinux keystore key backend, and the result is used
 ///                      as target context.
 pub fn check_grant_permission(
@@ -438,12 +438,10 @@
     access_vec: KeyPermSet,
     key: &KeyDescriptor,
 ) -> anyhow::Result<()> {
-    use android_security_keystore2::aidl::android::security::keystore2::Domain;
-
     let target_context = match key.domain {
-        Domain::App => getcon().context("check_grant_permission: getcon failed.")?,
-        Domain::SELinux => lookup_keystore2_key_context(key.namespace_)
-            .context("check_grant_permission: Domain::SELinux: Failed to lookup namespace.")?,
+        Domain::APP => getcon().context("check_grant_permission: getcon failed.")?,
+        Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
+            .context("check_grant_permission: Domain::SELINUX: Failed to lookup namespace.")?,
         _ => return Err(KsError::sys()).context(format!("Cannot grant {:?}.", key.domain)),
     };
 
@@ -469,19 +467,19 @@
 /// descriptor `key` in the security class `keystore2_key`.
 ///
 /// The behavior differs slightly depending on the selected target domain:
-///  * `Domain::App` u:r:keystore:s0 is used as target context.
-///  * `Domain::SELinux` `key.namespace_` parameter is looked up in the SELinux keystore key
+///  * `Domain::APP` u:r:keystore:s0 is used as target context.
+///  * `Domain::SELINUX` `key.nspace` parameter is looked up in the SELinux keystore key
 ///                      backend, and the result is used as target context.
-///  * `Domain::Blob` Same as SELinux but the "manage_blob" permission is always checked additionally
+///  * `Domain::BLOB` Same as SELinux but the "manage_blob" permission is always checked additionally
 ///                   to the one supplied in `perm`.
-///  * `Domain::Grant` Does not use selinux::check_access. Instead the `access_vector`
+///  * `Domain::GRANT` Does not use selinux::check_access. Instead the `access_vector`
 ///                    parameter is queried for permission, which must be supplied in this case.
 ///
 /// ## Return values.
 ///  * Ok(()) If the requested permissions were granted.
 ///  * Err(selinux::Error::perm()) If the requested permissions were denied.
-///  * Err(KsError::sys()) This error is produced if `Domain::Grant` is selected but no `access_vec`
-///                      was supplied. It is also produced if `Domain::KeyId` was selected, and
+///  * Err(KsError::sys()) This error is produced if `Domain::GRANT` is selected but no `access_vec`
+///                      was supplied. It is also produced if `Domain::KEY_ID` was selected, and
 ///                      on various unexpected backend failures.
 pub fn check_key_permission(
     caller_ctx: &CStr,
@@ -489,14 +487,12 @@
     key: &KeyDescriptor,
     access_vector: &Option<KeyPermSet>,
 ) -> anyhow::Result<()> {
-    use android_security_keystore2::aidl::android::security::keystore2::Domain;
-
     let target_context = match key.domain {
         // apps get the default keystore context
-        Domain::App => getcon().context("check_key_permission: getcon failed.")?,
-        Domain::SELinux => lookup_keystore2_key_context(key.namespace_)
-            .context("check_key_permission: Domain::SELinux: Failed to lookup namespace.")?,
-        Domain::Grant => {
+        Domain::APP => getcon().context("check_key_permission: getcon failed.")?,
+        Domain::SELINUX => lookup_keystore2_key_context(key.nspace)
+            .context("check_key_permission: Domain::SELINUX: Failed to lookup namespace.")?,
+        Domain::GRANT => {
             match access_vector {
                 Some(pv) => {
                     if pv.includes(perm) {
@@ -509,20 +505,20 @@
                 None => {
                     // If DOMAIN_GRANT was selected an access vector must be supplied.
                     return Err(KsError::sys()).context(
-                        "Cannot check permission for Domain::Grant without access vector.",
+                        "Cannot check permission for Domain::GRANT without access vector.",
                     );
                 }
             }
         }
-        Domain::KeyId => {
-            // We should never be called with `Domain::KeyId. The database
-            // lookup should have converted this into one of `Domain::App`
-            // or `Domain::SELinux`.
-            return Err(KsError::sys()).context("Cannot check permission for Domain::KeyId.");
+        Domain::KEY_ID => {
+            // We should never be called with `Domain::KEY_ID. The database
+            // lookup should have converted this into one of `Domain::APP`
+            // or `Domain::SELINUX`.
+            return Err(KsError::sys()).context("Cannot check permission for Domain::KEY_ID.");
         }
-        Domain::Blob => {
-            let tctx = lookup_keystore2_key_context(key.namespace_)
-                .context("Domain::Blob: Failed to lookup namespace.")?;
+        Domain::BLOB => {
+            let tctx = lookup_keystore2_key_context(key.nspace)
+                .context("Domain::BLOB: Failed to lookup namespace.")?;
             // If DOMAIN_KEY_BLOB was specified, we check for the "manage_blob"
             // permission in addition to the requested permission.
             selinux::check_access(
@@ -536,7 +532,7 @@
         }
         _ => {
             return Err(KsError::sys())
-                .context(format!("Unknown domain value: \"{}\".", key.domain))
+                .context(format!("Unknown domain value: \"{:?}\".", key.domain))
         }
     };
 
@@ -650,8 +646,7 @@
     fn check_grant_permission_app() -> Result<()> {
         let system_server_ctx = Context::new("u:r:system_server:s0")?;
         let shell_ctx = Context::new("u:r:shell:s0")?;
-        use android_security_keystore2::aidl::android::security::keystore2::Domain;
-        let key = KeyDescriptor { domain: Domain::App, namespace_: 0, alias: None, blob: None };
+        let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
         assert!(check_grant_permission(&system_server_ctx, NOT_GRANT_PERMS, &key).is_ok());
         // attempts to grant the grant permission must always fail even when privileged.
 
@@ -667,11 +662,10 @@
 
     #[test]
     fn check_grant_permission_selinux() -> Result<()> {
-        use android_security_keystore2::aidl::android::security::keystore2::Domain;
         let (sctx, namespace, is_su) = check_context()?;
         let key = KeyDescriptor {
-            domain: Domain::SELinux,
-            namespace_: namespace as i64,
+            domain: Domain::SELINUX,
+            nspace: namespace as i64,
             alias: None,
             blob: None,
         };
@@ -688,8 +682,7 @@
 
     #[test]
     fn check_key_permission_domain_grant() -> Result<()> {
-        use android_security_keystore2::aidl::android::security::keystore2::Domain;
-        let key = KeyDescriptor { domain: Domain::Grant, namespace_: 0, alias: None, blob: None };
+        let key = KeyDescriptor { domain: Domain::GRANT, nspace: 0, alias: None, blob: None };
 
         assert_perm_failed!(check_key_permission(
             &selinux::Context::new("ignored").unwrap(),
@@ -711,9 +704,8 @@
         let system_server_ctx = Context::new("u:r:system_server:s0")?;
         let shell_ctx = Context::new("u:r:shell:s0")?;
         let gmscore_app = Context::new("u:r:gmscore_app:s0")?;
-        use android_security_keystore2::aidl::android::security::keystore2::Domain;
 
-        let key = KeyDescriptor { domain: Domain::App, namespace_: 0, alias: None, blob: None };
+        let key = KeyDescriptor { domain: Domain::APP, nspace: 0, alias: None, blob: None };
 
         assert!(check_key_permission(&system_server_ctx, KeyPerm::use_(), &key, &None).is_ok());
         assert!(check_key_permission(&system_server_ctx, KeyPerm::delete(), &key, &None).is_ok());
@@ -752,11 +744,10 @@
 
     #[test]
     fn check_key_permission_domain_selinux() -> Result<()> {
-        use android_security_keystore2::aidl::android::security::keystore2::Domain;
         let (sctx, namespace, is_su) = check_context()?;
         let key = KeyDescriptor {
-            domain: Domain::SELinux,
-            namespace_: namespace as i64,
+            domain: Domain::SELINUX,
+            nspace: namespace as i64,
             alias: None,
             blob: None,
         };
@@ -789,11 +780,10 @@
 
     #[test]
     fn check_key_permission_domain_blob() -> Result<()> {
-        use android_security_keystore2::aidl::android::security::keystore2::Domain;
         let (sctx, namespace, is_su) = check_context()?;
         let key = KeyDescriptor {
-            domain: Domain::Blob,
-            namespace_: namespace as i64,
+            domain: Domain::BLOB,
+            nspace: namespace as i64,
             alias: None,
             blob: None,
         };
@@ -808,8 +798,7 @@
 
     #[test]
     fn check_key_permission_domain_key_id() -> Result<()> {
-        use android_security_keystore2::aidl::android::security::keystore2::Domain;
-        let key = KeyDescriptor { domain: Domain::KeyId, namespace_: 0, alias: None, blob: None };
+        let key = KeyDescriptor { domain: Domain::KEY_ID, nspace: 0, alias: None, blob: None };
 
         assert_eq!(
             Some(&KsError::sys()),
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
new file mode 100644
index 0000000..24a2e99
--- /dev/null
+++ b/keystore2/src/security_level.rs
@@ -0,0 +1,590 @@
+// Copyright 2020, 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.
+
+#![allow(unused_variables)]
+
+//! This crate implements the IKeystoreSecurityLevel interface.
+
+use android_hardware_keymint::aidl::android::hardware::keymint::{
+    Algorithm::Algorithm, ByteArray::ByteArray, Certificate::Certificate as KmCertificate,
+    HardwareAuthenticatorType::HardwareAuthenticatorType, IKeyMintDevice::IKeyMintDevice,
+    KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
+    KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel, Tag::Tag,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    AuthenticatorSpec::AuthenticatorSpec, CreateOperationResponse::CreateOperationResponse,
+    Domain::Domain, IKeystoreOperation::IKeystoreOperation,
+    IKeystoreSecurityLevel::BnKeystoreSecurityLevel,
+    IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+    KeyMetadata::KeyMetadata, KeyParameters::KeyParameters,
+};
+
+use crate::permission::KeyPerm;
+use crate::utils::{check_key_permission, Asp};
+use crate::{database::KeyIdGuard, globals::DB};
+use crate::{
+    database::{KeyEntry, KeyEntryLoadBits, SubComponentType},
+    operation::KeystoreOperation,
+    operation::OperationDb,
+};
+use crate::{
+    error::{self, map_km_error, map_or_log_err, Error, ErrorCode},
+    utils::key_characteristics_to_internal,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface, ThreadState};
+
+/// Implementation of the IKeystoreSecurityLevel Interface.
+pub struct KeystoreSecurityLevel {
+    security_level: SecurityLevel,
+    keymint: Asp,
+    operation_db: OperationDb,
+}
+
+static KEYMINT_SERVICE_NAME: &str = "android.hardware.keymint.IKeyMintDevice";
+
+// Blob of 32 zeroes used as empty masking key.
+static ZERO_BLOB_32: &[u8] = &[0; 32];
+
+impl KeystoreSecurityLevel {
+    /// Creates a new security level instance wrapped in a
+    /// BnKeystoreSecurityLevel proxy object. It also
+    /// calls `IBinder::set_requesting_sid` on the new interface, because
+    /// we need it for checking keystore permissions.
+    pub fn new_native_binder(
+        security_level: SecurityLevel,
+    ) -> Result<impl IKeystoreSecurityLevel + Send> {
+        let service_name = format!("{}/default", KEYMINT_SERVICE_NAME);
+        let keymint: Box<dyn IKeyMintDevice> =
+            binder::get_interface(&service_name).map_err(|e| {
+                anyhow!(format!(
+                    "Could not get KeyMint instance: {} failed with error code {:?}",
+                    service_name, e
+                ))
+            })?;
+
+        let result = BnKeystoreSecurityLevel::new_binder(Self {
+            security_level,
+            keymint: Asp::new(keymint.as_binder()),
+            operation_db: OperationDb::new(),
+        });
+        result.as_binder().set_requesting_sid(true);
+        Ok(result)
+    }
+
+    fn store_new_key(
+        &self,
+        key: KeyDescriptor,
+        key_characteristics: KeyCharacteristics,
+        km_cert_chain: Option<Vec<KmCertificate>>,
+        blob: ByteArray,
+    ) -> Result<KeyMetadata> {
+        let (cert, cert_chain): (Option<Vec<u8>>, Option<Vec<u8>>) = match km_cert_chain {
+            Some(mut chain) => (
+                match chain.len() {
+                    0 => None,
+                    _ => Some(chain.remove(0).encodedCertificate),
+                },
+                match chain.len() {
+                    0 => None,
+                    _ => Some(
+                        chain
+                            .iter()
+                            .map(|c| c.encodedCertificate.iter())
+                            .flatten()
+                            .copied()
+                            .collect(),
+                    ),
+                },
+            ),
+            None => (None, None),
+        };
+
+        let key_parameters =
+            key_characteristics_to_internal(key_characteristics, self.security_level);
+
+        let key = match key.domain {
+            Domain::BLOB => {
+                KeyDescriptor { domain: Domain::BLOB, blob: Some(blob.data), ..Default::default() }
+            }
+            _ => DB
+                .with(|db| {
+                    let mut db = db.borrow_mut();
+                    let key_id = db
+                        .create_key_entry(key.domain, key.nspace)
+                        .context("Trying to create a key entry.")?;
+                    db.insert_blob(
+                        &key_id,
+                        SubComponentType::KM_BLOB,
+                        &blob.data,
+                        self.security_level,
+                    )
+                    .context("Trying to insert km blob.")?;
+                    if let Some(c) = &cert {
+                        db.insert_blob(&key_id, SubComponentType::CERT, c, self.security_level)
+                            .context("Trying to insert cert blob.")?;
+                    }
+                    if let Some(c) = &cert_chain {
+                        db.insert_blob(
+                            &key_id,
+                            SubComponentType::CERT_CHAIN,
+                            c,
+                            self.security_level,
+                        )
+                        .context("Trying to insert cert chain blob.")?;
+                    }
+                    db.insert_keyparameter(&key_id, &key_parameters)
+                        .context("Trying to insert key parameters.")?;
+                    match &key.alias {
+                        Some(alias) => db
+                            .rebind_alias(&key_id, alias, key.domain, key.nspace)
+                            .context("Failed to rebind alias.")?,
+                        None => {
+                            return Err(error::Error::sys()).context(
+                                "Alias must be specified. (This should have been checked earlier.)",
+                            )
+                        }
+                    }
+                    Ok(KeyDescriptor {
+                        domain: Domain::KEY_ID,
+                        nspace: key_id.id(),
+                        ..Default::default()
+                    })
+                })
+                .context("In store_new_key.")?,
+        };
+
+        Ok(KeyMetadata {
+            key,
+            keySecurityLevel: self.security_level,
+            certificate: cert,
+            certificateChain: cert_chain,
+            authorizations: crate::utils::key_parameters_to_authorizations(key_parameters),
+            ..Default::default()
+        })
+    }
+
+    fn create_operation(
+        &self,
+        key: &KeyDescriptor,
+        operation_parameters: &[KeyParameter],
+        forced: bool,
+    ) -> Result<CreateOperationResponse> {
+        let caller_uid = ThreadState::get_calling_uid();
+        // We use `scoping_blob` to extend the life cycle of the blob loaded from the database,
+        // so that we can use it by reference like the blob provided by the key descriptor.
+        // Otherwise, we would have to clone the blob from the key descriptor.
+        let scoping_blob: Vec<u8>;
+        let (km_blob, key_id_guard) = match key.domain {
+            Domain::BLOB => {
+                check_key_permission(KeyPerm::use_(), key, &None)
+                    .context("In create_operation: checking use permission for Domain::BLOB.")?;
+                (
+                    match &key.blob {
+                        Some(blob) => blob,
+                        None => {
+                            return Err(Error::sys()).context(concat!(
+                                "In create_operation: Key blob must be specified when",
+                                " using Domain::BLOB."
+                            ))
+                        }
+                    },
+                    None,
+                )
+            }
+            _ => {
+                let (key_id_guard, mut key_entry) = DB
+                    .with::<_, Result<(KeyIdGuard, KeyEntry)>>(|db| {
+                        db.borrow_mut().load_key_entry(
+                            key.clone(),
+                            KeyEntryLoadBits::KM,
+                            caller_uid,
+                            |k, av| check_key_permission(KeyPerm::use_(), k, &av),
+                        )
+                    })
+                    .context("In create_operation: Failed to load key blob.")?;
+                scoping_blob = match key_entry.take_km_blob() {
+                    Some(blob) => blob,
+                    None => {
+                        return Err(Error::sys()).context(concat!(
+                            "In create_operation: Successfully loaded key entry,",
+                            " but KM blob was missing."
+                        ))
+                    }
+                };
+                (&scoping_blob, Some(key_id_guard))
+            }
+        };
+
+        // TODO Authorize begin operation.
+        // Check if we need an authorization token.
+        // Lookup authorization token and request VerificationToken if required.
+
+        let purpose = operation_parameters.iter().find(|p| p.tag == Tag::PURPOSE).map_or(
+            Err(Error::Km(ErrorCode::INVALID_ARGUMENT))
+                .context("In create_operation: No operation purpose specified."),
+            |kp| Ok(KeyPurpose(kp.integer)),
+        )?;
+
+        let km_dev: Box<dyn IKeyMintDevice> = self
+            .keymint
+            .get_interface()
+            .context("In create_operation: Failed to get KeyMint device")?;
+
+        let (begin_result, upgraded_blob) = self
+            .upgrade_keyblob_if_required_with(
+                &*km_dev,
+                key_id_guard,
+                &km_blob,
+                &operation_parameters,
+                |blob| loop {
+                    match map_km_error(km_dev.begin(
+                        purpose,
+                        blob,
+                        &operation_parameters,
+                        &Default::default(),
+                    )) {
+                        Err(Error::Km(ErrorCode::TOO_MANY_OPERATIONS)) => {
+                            self.operation_db.prune(caller_uid)?;
+                            continue;
+                        }
+                        v => return v,
+                    }
+                },
+            )
+            .context("In create_operation: Failed to begin operation.")?;
+
+        let operation = match begin_result.operation {
+            Some(km_op) => self.operation_db.create_operation(km_op, caller_uid),
+            None => return Err(Error::sys()).context("In create_operation: Begin operation returned successfully, but did not return a valid operation."),
+        };
+
+        let op_binder: Box<dyn IKeystoreOperation> =
+            KeystoreOperation::new_native_binder(operation)
+                .as_binder()
+                .into_interface()
+                .context("In create_operation: Failed to create IKeystoreOperation.")?;
+
+        // TODO we need to the enforcement module to determine if we need to return the challenge.
+        // We return None for now because we don't support auth bound keys yet.
+        Ok(CreateOperationResponse {
+            iOperation: Some(op_binder),
+            operationChallenge: None,
+            parameters: match begin_result.params.len() {
+                0 => None,
+                _ => Some(KeyParameters { keyParameter: begin_result.params }),
+            },
+        })
+    }
+
+    fn generate_key(
+        &self,
+        key: &KeyDescriptor,
+        attestation_key: Option<&KeyDescriptor>,
+        params: &[KeyParameter],
+        flags: i32,
+        entropy: &[u8],
+    ) -> Result<KeyMetadata> {
+        if key.domain != Domain::BLOB && key.alias.is_none() {
+            return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+                .context("In generate_key: Alias must be specified");
+        }
+
+        let key = match key.domain {
+            Domain::APP => KeyDescriptor {
+                domain: key.domain,
+                nspace: ThreadState::get_calling_uid() as i64,
+                alias: key.alias.clone(),
+                blob: None,
+            },
+            _ => key.clone(),
+        };
+
+        // generate_key requires the rebind permission.
+        check_key_permission(KeyPerm::rebind(), &key, &None).context("In generate_key.")?;
+
+        let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
+        map_km_error(km_dev.addRngEntropy(entropy))?;
+        let mut blob: ByteArray = Default::default();
+        let mut key_characteristics: KeyCharacteristics = Default::default();
+        let mut certificate_chain: Vec<KmCertificate> = Default::default();
+        map_km_error(km_dev.generateKey(
+            &params,
+            &mut blob,
+            &mut key_characteristics,
+            &mut certificate_chain,
+        ))?;
+
+        self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
+            .context("In generate_key.")
+    }
+
+    fn import_key(
+        &self,
+        key: &KeyDescriptor,
+        attestation_key: Option<&KeyDescriptor>,
+        params: &[KeyParameter],
+        flags: i32,
+        key_data: &[u8],
+    ) -> Result<KeyMetadata> {
+        if key.domain != Domain::BLOB && key.alias.is_none() {
+            return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+                .context("In import_key: Alias must be specified");
+        }
+
+        let key = match key.domain {
+            Domain::APP => KeyDescriptor {
+                domain: key.domain,
+                nspace: ThreadState::get_calling_uid() as i64,
+                alias: key.alias.clone(),
+                blob: None,
+            },
+            _ => key.clone(),
+        };
+
+        // import_key requires the rebind permission.
+        check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_key.")?;
+
+        let mut blob: ByteArray = Default::default();
+        let mut key_characteristics: KeyCharacteristics = Default::default();
+        let mut certificate_chain: Vec<KmCertificate> = Default::default();
+
+        let format = params
+            .iter()
+            .find(|p| p.tag == Tag::ALGORITHM)
+            .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+            .context("No KeyParameter 'Algorithm'.")
+            .and_then(|p| match Algorithm(p.integer) {
+                Algorithm::AES | Algorithm::HMAC | Algorithm::TRIPLE_DES => Ok(KeyFormat::RAW),
+                Algorithm::RSA | Algorithm::EC => Ok(KeyFormat::PKCS8),
+                algorithm => Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+                    .context(format!("Unknown Algorithm {:?}.", algorithm)),
+            })
+            .context("In import_key.")?;
+
+        let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
+        map_km_error(km_dev.importKey(
+            &params,
+            format,
+            key_data,
+            &mut blob,
+            &mut key_characteristics,
+            &mut certificate_chain,
+        ))?;
+
+        self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
+            .context("In import_key.")
+    }
+
+    fn import_wrapped_key(
+        &self,
+        key: &KeyDescriptor,
+        wrapping_key: &KeyDescriptor,
+        masking_key: Option<&[u8]>,
+        params: &[KeyParameter],
+        authenticators: &[AuthenticatorSpec],
+    ) -> Result<KeyMetadata> {
+        if key.domain != Domain::BLOB && key.alias.is_none() {
+            return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+                .context("In import_wrapped_key: Alias must be specified.");
+        }
+
+        if wrapping_key.domain == Domain::BLOB {
+            return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
+                "In import_wrapped_key: Import wrapped key not supported for self managed blobs.",
+            );
+        }
+
+        let wrapped_data = match &key.blob {
+            Some(d) => d,
+            None => {
+                return Err(error::Error::Km(ErrorCode::INVALID_ARGUMENT)).context(
+                    "In import_wrapped_key: Blob must be specified and hold wrapped key data.",
+                )
+            }
+        };
+
+        let key = match key.domain {
+            Domain::APP => KeyDescriptor {
+                domain: key.domain,
+                nspace: ThreadState::get_calling_uid() as i64,
+                alias: key.alias.clone(),
+                blob: None,
+            },
+            _ => key.clone(),
+        };
+
+        // import_wrapped_key requires the rebind permission for the new key.
+        check_key_permission(KeyPerm::rebind(), &key, &None).context("In import_wrapped_key.")?;
+
+        let (wrapping_key_id_guard, wrapping_key_entry) = DB
+            .with(|db| {
+                db.borrow_mut().load_key_entry(
+                    wrapping_key.clone(),
+                    KeyEntryLoadBits::KM,
+                    ThreadState::get_calling_uid(),
+                    |k, av| check_key_permission(KeyPerm::use_(), k, &av),
+                )
+            })
+            .context("Failed to load wrapping key.")?;
+        let wrapping_key_blob = match wrapping_key_entry.km_blob() {
+            Some(blob) => blob,
+            None => {
+                return Err(error::Error::sys()).context(concat!(
+                    "No km_blob after successfully loading key.",
+                    " This should never happen."
+                ))
+            }
+        };
+
+        // km_dev.importWrappedKey does not return a certificate chain.
+        // TODO Do we assume that all wrapped keys are symmetric?
+        // let certificate_chain: Vec<KmCertificate> = Default::default();
+
+        let pw_sid = authenticators
+            .iter()
+            .find_map(|a| match a.authenticatorType {
+                HardwareAuthenticatorType::PASSWORD => Some(a.authenticatorId),
+                _ => None,
+            })
+            .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+            .context("A password authenticator SID must be specified.")?;
+
+        let fp_sid = authenticators
+            .iter()
+            .find_map(|a| match a.authenticatorType {
+                HardwareAuthenticatorType::FINGERPRINT => Some(a.authenticatorId),
+                _ => None,
+            })
+            .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
+            .context("A fingerprint authenticator SID must be specified.")?;
+
+        let masking_key = masking_key.unwrap_or(ZERO_BLOB_32);
+
+        let km_dev: Box<dyn IKeyMintDevice> = self.keymint.get_interface()?;
+        let ((blob, key_characteristics), _) = self.upgrade_keyblob_if_required_with(
+            &*km_dev,
+            Some(wrapping_key_id_guard),
+            wrapping_key_blob,
+            &[],
+            |wrapping_blob| {
+                let mut blob: ByteArray = Default::default();
+                let mut key_characteristics: KeyCharacteristics = Default::default();
+                map_km_error(km_dev.importWrappedKey(
+                    wrapped_data,
+                    wrapping_key_blob,
+                    masking_key,
+                    &params,
+                    pw_sid,
+                    fp_sid,
+                    &mut blob,
+                    &mut key_characteristics,
+                ))?;
+                Ok((blob, key_characteristics))
+            },
+        )?;
+
+        self.store_new_key(key, key_characteristics, None, blob).context("In import_wrapped_key.")
+    }
+
+    fn upgrade_keyblob_if_required_with<T, F>(
+        &self,
+        km_dev: &dyn IKeyMintDevice,
+        key_id_guard: Option<KeyIdGuard>,
+        blob: &[u8],
+        params: &[KeyParameter],
+        f: F,
+    ) -> Result<(T, Option<Vec<u8>>)>
+    where
+        F: Fn(&[u8]) -> Result<T, Error>,
+    {
+        match f(blob) {
+            Err(Error::Km(ErrorCode::KEY_REQUIRES_UPGRADE)) => {
+                let upgraded_blob = map_km_error(km_dev.upgradeKey(blob, params))
+                    .context("In upgrade_keyblob_if_required_with: Upgrade failed.")?;
+                key_id_guard.map_or(Ok(()), |key_id_guard| {
+                    DB.with(|db| {
+                        db.borrow_mut().insert_blob(
+                            &key_id_guard,
+                            SubComponentType::KM_BLOB,
+                            &upgraded_blob,
+                            self.security_level,
+                        )
+                    })
+                    .context(concat!(
+                        "In upgrade_keyblob_if_required_with: ",
+                        "Failed to insert upgraded blob into the database.",
+                    ))
+                })?;
+                match f(&upgraded_blob) {
+                    Ok(v) => Ok((v, Some(upgraded_blob))),
+                    Err(e) => Err(e).context(concat!(
+                        "In upgrade_keyblob_if_required_with: ",
+                        "Failed to perform operation on second try."
+                    )),
+                }
+            }
+            Err(e) => {
+                Err(e).context("In upgrade_keyblob_if_required_with: Failed perform operation.")
+            }
+            Ok(v) => Ok((v, None)),
+        }
+    }
+}
+
+impl binder::Interface for KeystoreSecurityLevel {}
+
+impl IKeystoreSecurityLevel for KeystoreSecurityLevel {
+    fn createOperation(
+        &self,
+        key: &KeyDescriptor,
+        operation_parameters: &[KeyParameter],
+        forced: bool,
+    ) -> binder::public_api::Result<CreateOperationResponse> {
+        map_or_log_err(self.create_operation(key, operation_parameters, forced), Ok)
+    }
+    fn generateKey(
+        &self,
+        key: &KeyDescriptor,
+        attestation_key: Option<&KeyDescriptor>,
+        params: &[KeyParameter],
+        flags: i32,
+        entropy: &[u8],
+    ) -> binder::public_api::Result<KeyMetadata> {
+        map_or_log_err(self.generate_key(key, attestation_key, params, flags, entropy), Ok)
+    }
+    fn importKey(
+        &self,
+        key: &KeyDescriptor,
+        attestation_key: Option<&KeyDescriptor>,
+        params: &[KeyParameter],
+        flags: i32,
+        key_data: &[u8],
+    ) -> binder::public_api::Result<KeyMetadata> {
+        map_or_log_err(self.import_key(key, attestation_key, params, flags, key_data), Ok)
+    }
+    fn importWrappedKey(
+        &self,
+        key: &KeyDescriptor,
+        wrapping_key: &KeyDescriptor,
+        masking_key: Option<&[u8]>,
+        params: &[KeyParameter],
+        authenticators: &[AuthenticatorSpec],
+    ) -> binder::public_api::Result<KeyMetadata> {
+        map_or_log_err(
+            self.import_wrapped_key(key, wrapping_key, masking_key, params, authenticators),
+            Ok,
+        )
+    }
+}
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
new file mode 100644
index 0000000..71aecbd
--- /dev/null
+++ b/keystore2/src/service.rs
@@ -0,0 +1,232 @@
+// Copyright 2020, 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.
+
+// TODO remove when fully implemented.
+#![allow(unused_variables)]
+
+//! This crate implement the core Keystore 2.0 service API as defined by the Keystore 2.0
+//! AIDL spec.
+
+use crate::database::{KeyEntryLoadBits, SubComponentType};
+use crate::error::{self, map_or_log_err, ErrorCode};
+use crate::globals::DB;
+use crate::permission;
+use crate::permission::KeyPerm;
+use crate::security_level::KeystoreSecurityLevel;
+use crate::utils::{
+    check_grant_permission, check_key_permission, key_parameters_to_authorizations, Asp,
+};
+use android_hardware_keymint::aidl::android::hardware::keymint::SecurityLevel::SecurityLevel;
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
+    IKeystoreService::BnKeystoreService, IKeystoreService::IKeystoreService,
+    KeyDescriptor::KeyDescriptor, KeyEntryResponse::KeyEntryResponse, KeyMetadata::KeyMetadata,
+};
+use anyhow::{anyhow, Context, Result};
+use binder::{IBinder, Interface, ThreadState};
+
+/// Implementation of the IKeystoreService.
+pub struct KeystoreService {
+    sec_level: Asp,
+}
+
+impl KeystoreService {
+    /// Create a new instance of the Keystore 2.0 service.
+    pub fn new_native_binder() -> Result<impl IKeystoreService> {
+        let result = BnKeystoreService::new_binder(Self {
+            sec_level: Asp::new({
+                let sec_level =
+                    KeystoreSecurityLevel::new_native_binder(SecurityLevel::TRUSTED_ENVIRONMENT)
+                        .context("While trying to create IKeystoreSecurityLevel")?;
+                sec_level.as_binder()
+            }),
+        });
+        result.as_binder().set_requesting_sid(true);
+        Ok(result)
+    }
+
+    fn get_security_level(
+        &self,
+        security_level: SecurityLevel,
+    ) -> Result<Box<dyn IKeystoreSecurityLevel>> {
+        match security_level {
+            SecurityLevel::TRUSTED_ENVIRONMENT => self
+                .sec_level
+                .get_interface()
+                .context("In get_security_level: Failed to get IKeystoreSecurityLevel."),
+            _ => Err(anyhow!(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))),
+        }
+    }
+
+    fn get_key_entry(&self, key: &KeyDescriptor) -> Result<KeyEntryResponse> {
+        let (key_id_guard, mut key_entry) = DB
+            .with(|db| {
+                db.borrow_mut().load_key_entry(
+                    key.clone(),
+                    KeyEntryLoadBits::PUBLIC,
+                    ThreadState::get_calling_uid(),
+                    |k, av| check_key_permission(KeyPerm::get_info(), k, &av),
+                )
+            })
+            .context("In get_key_entry, while trying to load key info.")?;
+
+        let i_sec_level = match key_entry.sec_level() {
+            SecurityLevel::TRUSTED_ENVIRONMENT => self
+                .sec_level
+                .get_interface()
+                .context("In get_key_entry: Failed to get IKeystoreSecurityLevel.")?,
+            _ => return Err(anyhow!(error::Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))),
+        };
+
+        Ok(KeyEntryResponse {
+            iSecurityLevel: Some(i_sec_level),
+            metadata: KeyMetadata {
+                key: KeyDescriptor {
+                    domain: Domain::KEY_ID,
+                    nspace: key_id_guard.id(),
+                    ..Default::default()
+                },
+                keySecurityLevel: key_entry.sec_level(),
+                certificate: key_entry.take_cert(),
+                certificateChain: key_entry.take_cert_chain(),
+                authorizations: key_parameters_to_authorizations(key_entry.into_key_parameters()),
+                ..Default::default()
+            },
+        })
+    }
+
+    fn update_subcomponent(
+        &self,
+        key: &KeyDescriptor,
+        public_cert: Option<&[u8]>,
+        certificate_chain: Option<&[u8]>,
+    ) -> Result<()> {
+        DB.with::<_, Result<()>>(|db| {
+            let mut db = db.borrow_mut();
+            let (key_id_guard, key_entry) = db
+                .load_key_entry(
+                    key.clone(),
+                    KeyEntryLoadBits::NONE,
+                    ThreadState::get_calling_uid(),
+                    |k, av| {
+                        check_key_permission(KeyPerm::update(), k, &av)
+                            .context("In update_subcomponent.")
+                    },
+                )
+                .context("Failed to load key_entry.")?;
+
+            if let Some(cert) = public_cert {
+                db.insert_blob(&key_id_guard, SubComponentType::CERT, cert, key_entry.sec_level())
+                    .context("Failed to update cert subcomponent.")?;
+            }
+
+            if let Some(cert_chain) = certificate_chain {
+                db.insert_blob(
+                    &key_id_guard,
+                    SubComponentType::CERT_CHAIN,
+                    cert_chain,
+                    key_entry.sec_level(),
+                )
+                .context("Failed to update cert chain subcomponent.")?;
+            }
+            Ok(())
+        })
+        .context("In update_subcomponent.")
+    }
+
+    fn list_entries(&self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
+        // TODO implement.
+        Err(anyhow!(error::Error::sys()))
+    }
+
+    fn delete_key(&self, key: &KeyDescriptor) -> Result<()> {
+        // TODO implement.
+        Err(anyhow!(error::Error::sys()))
+    }
+
+    fn grant(
+        &self,
+        key: &KeyDescriptor,
+        grantee_uid: i32,
+        access_vector: permission::KeyPermSet,
+    ) -> Result<KeyDescriptor> {
+        DB.with(|db| {
+            db.borrow_mut().grant(
+                key.clone(),
+                ThreadState::get_calling_uid(),
+                grantee_uid as u32,
+                access_vector,
+                |k, av| check_grant_permission(*av, k).context("During grant."),
+            )
+        })
+        .context("In KeystoreService::grant.")
+    }
+
+    fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> Result<()> {
+        DB.with(|db| {
+            db.borrow_mut().ungrant(
+                key.clone(),
+                ThreadState::get_calling_uid(),
+                grantee_uid as u32,
+                |k| check_key_permission(KeyPerm::grant(), k, &None),
+            )
+        })
+        .context("In KeystoreService::ungrant.")
+    }
+}
+
+impl binder::Interface for KeystoreService {}
+
+// Implementation of IKeystoreService. See AIDL spec at
+// system/security/keystore2/binder/android/security/keystore2/IKeystoreService.aidl
+impl IKeystoreService for KeystoreService {
+    fn getSecurityLevel(
+        &self,
+        security_level: SecurityLevel,
+    ) -> binder::public_api::Result<Box<dyn IKeystoreSecurityLevel>> {
+        map_or_log_err(self.get_security_level(SecurityLevel(security_level.0)), Ok)
+    }
+    fn getKeyEntry(&self, key: &KeyDescriptor) -> binder::public_api::Result<KeyEntryResponse> {
+        map_or_log_err(self.get_key_entry(key), Ok)
+    }
+    fn updateSubcomponent(
+        &self,
+        key: &KeyDescriptor,
+        public_cert: Option<&[u8]>,
+        certificate_chain: Option<&[u8]>,
+    ) -> binder::public_api::Result<()> {
+        map_or_log_err(self.update_subcomponent(key, public_cert, certificate_chain), Ok)
+    }
+    fn listEntries(
+        &self,
+        domain: Domain,
+        namespace: i64,
+    ) -> binder::public_api::Result<Vec<KeyDescriptor>> {
+        map_or_log_err(self.list_entries(domain, namespace), Ok)
+    }
+    fn deleteKey(&self, key: &KeyDescriptor) -> binder::public_api::Result<()> {
+        map_or_log_err(self.delete_key(key), Ok)
+    }
+    fn grant(
+        &self,
+        key: &KeyDescriptor,
+        grantee_uid: i32,
+        access_vector: i32,
+    ) -> binder::public_api::Result<KeyDescriptor> {
+        map_or_log_err(self.grant(key, grantee_uid, access_vector.into()), Ok)
+    }
+    fn ungrant(&self, key: &KeyDescriptor, grantee_uid: i32) -> binder::public_api::Result<()> {
+        map_or_log_err(self.ungrant(key, grantee_uid), Ok)
+    }
+}
diff --git a/keystore2/src/tests/certificate_utils_test.cpp b/keystore2/src/tests/certificate_utils_test.cpp
new file mode 100644
index 0000000..2df9ce5
--- /dev/null
+++ b/keystore2/src/tests/certificate_utils_test.cpp
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2020, 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 <gtest/gtest.h>
+
+#include "certificate_utils.h"
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <variant>
+
+#include "test_keys.h"
+
+using namespace keystore;
+
+// I leave these here in case they are needed for debugging.
+namespace debug_utils {
+
+void log_ssl_error() {
+    unsigned long error = ERR_peek_last_error();
+
+    char buf[128];
+    ERR_error_string_n(error, buf, sizeof(buf));
+    std::cout << "BoringSslError: " << buf << std::endl;
+}
+
+std::string hexdump(const std::vector<uint8_t>& data) {
+    std::stringstream s;
+    size_t column_count = 0;
+    for (auto& c : data) {
+        s << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)c;
+        if (++column_count % 40 == 0) s << "\n";
+    }
+    return s.str();
+}
+
+}  // namespace debug_utils
+
+constexpr uint64_t kValidity = 24 * 60 * 60 * 1000;  // 24 hours in milliseconds
+
+const EVP_MD* getMD(Digest digest) {
+    switch (digest) {
+    case Digest::SHA1:
+        return EVP_sha1();
+    case Digest::SHA224:
+        return EVP_sha224();
+    case Digest::SHA256:
+        return EVP_sha256();
+    case Digest::SHA384:
+        return EVP_sha384();
+    case Digest::SHA512:
+        return EVP_sha512();
+    }
+}
+
+std::array<Digest, 5> digests = {
+    Digest::SHA1, Digest::SHA224, Digest::SHA256, Digest::SHA384, Digest::SHA512,
+};
+
+static const char* toString(Digest d) {
+    switch (d) {
+    case Digest::SHA1:
+        return "SHA1";
+    case Digest::SHA224:
+        return "SHA224";
+    case Digest::SHA256:
+        return "SHA256";
+    case Digest::SHA384:
+        return "SHA384";
+    case Digest::SHA512:
+        return "SHA512";
+    }
+}
+
+std::array<Padding, 2> rsa_paddings = {
+    Padding::PSS,
+    Padding::PKCS1_5,
+};
+
+enum class EcCurve {
+    P224,
+    P256,
+    P384,
+    P521,
+};
+
+std::array<int, 4> ec_curves = {
+    NID_secp224r1,
+    NID_X9_62_prime256v1,
+    NID_secp384r1,
+    NID_secp521r1,
+};
+
+static const char* curveNidToString(int nid) {
+    switch (nid) {
+    case NID_secp224r1:
+        return "P224";
+    case NID_X9_62_prime256v1:
+        return "P256";
+    case NID_secp384r1:
+        return "P384";
+    case NID_secp521r1:
+        return "P521";
+    default:
+        return "Unknown";
+    }
+}
+
+std::array<long, 2> rsa_key_sizes = {
+    2048,
+    4096,
+};
+
+using EcParam = std::tuple<int /* EC curve NID */, Digest>;
+
+class CertificateUtilsWithEcCurve : public testing::TestWithParam<EcParam> {};
+
+static std::string paramToStringEc(testing::TestParamInfo<EcParam> param) {
+    std::stringstream s;
+    auto [curve_nid, digest] = param.param;
+    s << param.index << "_" << curveNidToString(curve_nid) << "_" << toString(digest);
+    return s.str();
+}
+
+INSTANTIATE_TEST_SUITE_P(CertSigningWithCallbackEC, CertificateUtilsWithEcCurve,
+                         testing::Combine(testing::ValuesIn(ec_curves), testing::ValuesIn(digests)),
+                         paramToStringEc);
+
+TEST_P(CertificateUtilsWithEcCurve, CertSigningWithCallbackEC) {
+    // Structured decomposition (e.g.: auto [a, b, c] = ...) does not work here because
+    // names bound this way cannot be captured in lambda expressions so we use std::tie instead.
+    int curve_nid;
+    Digest digest;
+    std::tie(curve_nid, digest) = GetParam();
+    EVP_PKEY_CTX_Ptr pkey_ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL));
+    ASSERT_TRUE((bool)pkey_ctx);
+    ASSERT_TRUE(EVP_PKEY_keygen_init(pkey_ctx.get()));
+    ASSERT_TRUE(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pkey_ctx.get(), curve_nid));
+
+    EVP_PKEY* pkey_ptr = nullptr;
+    ASSERT_TRUE(EVP_PKEY_keygen(pkey_ctx.get(), &pkey_ptr));
+    EVP_PKEY_Ptr pkey(pkey_ptr);
+    ASSERT_TRUE(pkey);
+
+    uint64_t now_ms = (uint64_t)time(nullptr) * 1000;
+
+    BasicConstraintsExtension bcons{
+        .isCa = true,
+        .pathLength = {},
+    };
+
+    KeyUsageExtension keyUsage{
+        .isSigningKey = true,
+        .isEncryptionKey = false,
+        .isCertificationKey = true,
+    };
+
+    auto certV = makeCert(pkey.get(), 1, "Me", now_ms - kValidity, now_ms + kValidity,
+                          true /* subject key id extension */, keyUsage, bcons);
+    ASSERT_TRUE(std::holds_alternative<X509_Ptr>(certV));
+    auto& cert = std::get<X509_Ptr>(certV);
+    ASSERT_TRUE(!setIssuer(cert.get(), cert.get(), true));
+
+    ASSERT_TRUE(!signCertWith(
+        cert.get(),
+        [&](const uint8_t* data, size_t len) {
+            bssl::ScopedEVP_MD_CTX sign_ctx;
+            EXPECT_TRUE(
+                EVP_DigestSignInit(sign_ctx.get(), nullptr, getMD(digest), nullptr, pkey.get()));
+
+            std::vector<uint8_t> sig_buf(512);
+            size_t sig_len = 512;
+            EVP_DigestSign(sign_ctx.get(), sig_buf.data(), &sig_len, data, len);
+            sig_buf.resize(sig_len);
+            return sig_buf;
+        },
+        Algo::ECDSA, Padding::Ignored, digest));
+
+    auto encCertV = encodeCert(cert.get());
+    ASSERT_TRUE(std::holds_alternative<std::vector<uint8_t>>(encCertV));
+
+    auto& encCert = std::get<1>(encCertV);
+    // Uncomment the next line to dump the DER encoded signed certificate as hex string.
+    // You can pipe this dump into  "xxd -r -p | openssl x509 -inform der -text -noout"
+    // to inspect the certificate.
+    // std::cout << "DER encoded cert:\n" << debug_utils::hexdump(encCert) << std::endl;
+
+    const uint8_t* p = encCert.data();
+    X509_Ptr decoded_cert(d2i_X509(nullptr, &p, (long)encCert.size()));
+    EVP_PKEY_Ptr decoded_pkey(X509_get_pubkey(decoded_cert.get()));
+    ASSERT_TRUE(X509_verify(decoded_cert.get(), decoded_pkey.get()));
+}
+
+using RsaParams = std::tuple<long /* key size */, Padding, Digest>;
+
+class CertificateUtilsWithRsa : public testing::TestWithParam<RsaParams> {};
+
+static std::string paramsToStringRsa(testing::TestParamInfo<RsaParams> param) {
+    std::stringstream s;
+    auto [key_size, padding, digest] = param.param;
+    s << param.index << "_" << key_size << "_";
+    switch (padding) {
+    case Padding::PSS:
+        s << "PSS";
+        break;
+    case Padding::PKCS1_5:
+        s << "PKCS1_5";
+        break;
+    case Padding::Ignored:
+        s << "Ignored";
+    }
+    s << "_" << toString(digest);
+    return s.str();
+}
+
+INSTANTIATE_TEST_SUITE_P(CertSigningWithCallbackRsa, CertificateUtilsWithRsa,
+                         testing::Combine(testing::ValuesIn(rsa_key_sizes),
+                                          testing::ValuesIn(rsa_paddings),
+                                          testing::ValuesIn(digests)),
+                         paramsToStringRsa);
+
+TEST_P(CertificateUtilsWithRsa, CertSigningWithCallbackRsa) {
+    // Structured decomposition (e.g.: auto [a, b, c] = ...) does not work here because
+    // names bound this way cannot be captured in lambda expressions so we use std::tie instead.
+    long key_size;
+    Padding padding;
+    Digest digest;
+    std::tie(key_size, padding, digest) = GetParam();
+
+    CBS cbs;
+    switch (key_size) {
+    case 2048:
+        CBS_init(&cbs, rsa_key_2k, rsa_key_2k_len);
+        break;
+    case 4096:
+        CBS_init(&cbs, rsa_key_4k, rsa_key_4k_len);
+        break;
+    default:
+        FAIL();
+    }
+    EVP_PKEY_Ptr pkey(EVP_parse_private_key(&cbs));
+    ASSERT_TRUE(pkey);
+
+    uint64_t now_ms = (uint64_t)time(nullptr) * 1000;
+
+    BasicConstraintsExtension bcons{
+        .isCa = true,
+        .pathLength = 0,
+    };
+
+    KeyUsageExtension keyUsage{
+        .isSigningKey = true,
+        .isEncryptionKey = false,
+        .isCertificationKey = true,
+    };
+
+    auto certV = makeCert(pkey.get(), 1, "Me", now_ms - kValidity, now_ms + kValidity,
+                          true /* subject key id extension */, keyUsage, bcons);
+    ASSERT_TRUE(std::holds_alternative<X509_Ptr>(certV));
+    auto& cert = std::get<X509_Ptr>(certV);
+    ASSERT_TRUE(!setIssuer(cert.get(), cert.get(), true));
+
+    ASSERT_TRUE(!signCertWith(
+        cert.get(),
+        [&](const uint8_t* data, size_t len) {
+            bssl::ScopedEVP_MD_CTX sign_ctx;
+            EVP_PKEY_CTX* pkey_sign_ctx_ptr;
+            EXPECT_TRUE(EVP_DigestSignInit(sign_ctx.get(), &pkey_sign_ctx_ptr, getMD(digest),
+                                           nullptr, pkey.get()));
+
+            if (padding == Padding::PSS) {
+                EXPECT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pkey_sign_ctx_ptr, RSA_PKCS1_PSS_PADDING));
+                EXPECT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_sign_ctx_ptr, -1));
+            } else {
+                EXPECT_TRUE(EVP_PKEY_CTX_set_rsa_padding(pkey_sign_ctx_ptr, RSA_PKCS1_PADDING));
+            }
+
+            std::vector<uint8_t> sig_buf(1024);
+            size_t sig_len = 1024;
+            EVP_DigestSign(sign_ctx.get(), sig_buf.data(), &sig_len, data, len);
+            sig_buf.resize(sig_len);
+            return sig_buf;
+        },
+        Algo::RSA, padding, digest));
+
+    auto encCertV = encodeCert(cert.get());
+    ASSERT_TRUE(std::holds_alternative<std::vector<uint8_t>>(encCertV));
+
+    auto& encCert = std::get<1>(encCertV);
+    // Uncomment the next line to dump the DER encoded signed certificate as hex string.
+    // You can pipe this dump into  "xxd -r -p | openssl x509 -inform der -text -noout"
+    // to inspect the certificate.
+    // std::cout << "DER encoded cert:\n" << debug_utils::hexdump(encCert) << std::endl;
+
+    const uint8_t* p = encCert.data();
+    X509_Ptr decoded_cert(d2i_X509(nullptr, &p, (long)encCert.size()));
+    EVP_PKEY_Ptr decoded_pkey(X509_get_pubkey(decoded_cert.get()));
+    ASSERT_TRUE(X509_verify(decoded_cert.get(), decoded_pkey.get()));
+}
diff --git a/keystore2/src/tests/gtest_main.cpp b/keystore2/src/tests/gtest_main.cpp
new file mode 100644
index 0000000..149cbbc
--- /dev/null
+++ b/keystore2/src/tests/gtest_main.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2020 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 <gtest/gtest.h>
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/keystore2/src/tests/test_keys.h b/keystore2/src/tests/test_keys.h
new file mode 100644
index 0000000..d3b1175
--- /dev/null
+++ b/keystore2/src/tests/test_keys.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2020, 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
+
+constexpr const unsigned char rsa_key_4k[] = {
+    0x30, 0x82, 0x09, 0x41, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x09, 0x2b, 0x30, 0x82, 0x09, 0x27, 0x02, 0x01,
+    0x00, 0x02, 0x82, 0x02, 0x01, 0x00, 0xac, 0x07, 0x4e, 0xc6, 0x20, 0xb9, 0x78, 0x03, 0xd0, 0x53,
+    0x22, 0xa4, 0xef, 0x6d, 0xd1, 0x7a, 0x7e, 0x5e, 0x5e, 0x1d, 0xe7, 0x9b, 0x30, 0x31, 0x99, 0xe8,
+    0x1c, 0xdf, 0x32, 0x0c, 0xdb, 0xdb, 0xc2, 0x4c, 0x22, 0x10, 0x71, 0xd0, 0x76, 0x83, 0xb0, 0x50,
+    0x66, 0xa4, 0x43, 0x75, 0xe8, 0x46, 0xde, 0x58, 0x9e, 0x31, 0x82, 0x81, 0x8c, 0x36, 0x20, 0xbb,
+    0x42, 0xcd, 0xb9, 0x21, 0x29, 0x67, 0x39, 0x4d, 0x2a, 0x1c, 0xc2, 0x89, 0x48, 0x23, 0x5f, 0xdd,
+    0x60, 0xc4, 0x04, 0x42, 0xbe, 0x6f, 0x01, 0xa5, 0xf8, 0xac, 0xba, 0x27, 0xd1, 0x87, 0x08, 0x6b,
+    0xe6, 0x1b, 0xfc, 0xba, 0xff, 0x7e, 0xc9, 0xaf, 0x76, 0x28, 0xe8, 0x93, 0x2c, 0xbf, 0x6f, 0xed,
+    0xf3, 0x6f, 0x21, 0xc1, 0xe7, 0x56, 0xf5, 0x15, 0x56, 0xa8, 0xa1, 0xfd, 0xb7, 0xb3, 0x8c, 0x3d,
+    0x1f, 0xf3, 0x80, 0xea, 0x79, 0xff, 0x0c, 0xc6, 0xb6, 0x59, 0xa0, 0x3f, 0x13, 0xb0, 0x4f, 0xb3,
+    0x1c, 0xe1, 0x2a, 0xa5, 0x45, 0x02, 0x51, 0xa3, 0x74, 0x15, 0xee, 0xf0, 0xca, 0xba, 0x7d, 0xca,
+    0xc6, 0x87, 0xd6, 0x12, 0x9b, 0xbb, 0x4b, 0x86, 0xc7, 0xcb, 0x88, 0xc6, 0x10, 0xee, 0x34, 0x51,
+    0x4b, 0xe9, 0x9d, 0xbb, 0x59, 0x03, 0xff, 0xbf, 0x98, 0x0a, 0xfd, 0xf2, 0xd0, 0x06, 0x0e, 0x51,
+    0xd1, 0xbb, 0x8b, 0xbd, 0xca, 0x26, 0x4d, 0x05, 0x0e, 0xee, 0x82, 0x0f, 0xf6, 0x38, 0x46, 0x2a,
+    0x7f, 0xfd, 0x37, 0xe6, 0xcf, 0xaa, 0x6a, 0x84, 0xbc, 0xa7, 0xd2, 0x06, 0x29, 0x49, 0x4c, 0xd2,
+    0x28, 0xd4, 0x48, 0x09, 0xfc, 0x91, 0x1e, 0xb0, 0x06, 0xf9, 0x5b, 0xbe, 0xd9, 0xb8, 0x01, 0xec,
+    0x3a, 0xc3, 0xa2, 0x1d, 0x89, 0x0b, 0x22, 0xf8, 0xf0, 0x8e, 0x95, 0xe0, 0x3d, 0x5b, 0x80, 0x38,
+    0x21, 0x80, 0x10, 0x04, 0x54, 0xaa, 0xa5, 0x81, 0x8b, 0x47, 0x73, 0x54, 0xcb, 0x06, 0xa9, 0x01,
+    0xf5, 0x57, 0x72, 0xdd, 0x5f, 0x9f, 0xe1, 0x14, 0x1f, 0xc1, 0x3b, 0xda, 0xd1, 0xad, 0xc7, 0x9c,
+    0x70, 0x18, 0xfd, 0x07, 0x7e, 0x37, 0x0d, 0xb4, 0x30, 0xff, 0x6d, 0x4b, 0x99, 0xdb, 0x3f, 0x23,
+    0xd7, 0x15, 0x3d, 0x4c, 0x14, 0x63, 0x98, 0xf5, 0x03, 0x63, 0x4e, 0x63, 0x15, 0x6a, 0xce, 0x7f,
+    0xfc, 0x4f, 0xa0, 0x72, 0x49, 0x3f, 0xd9, 0xa2, 0xde, 0x65, 0xac, 0x35, 0x88, 0x03, 0x55, 0xf5,
+    0x27, 0x57, 0x4e, 0x4b, 0xef, 0x44, 0x1d, 0xd1, 0xe9, 0xaf, 0x89, 0x7e, 0x19, 0x2a, 0xc4, 0x48,
+    0x80, 0x8d, 0x22, 0xd6, 0x4f, 0x79, 0x39, 0x15, 0x00, 0xc0, 0xa8, 0x93, 0x5a, 0x05, 0xce, 0xc8,
+    0x3f, 0x27, 0x40, 0x09, 0x1f, 0x2a, 0x0c, 0x32, 0x6a, 0x2d, 0xef, 0x51, 0x79, 0x51, 0xf1, 0xfe,
+    0xdb, 0x2c, 0xb5, 0x2f, 0x4d, 0x94, 0x1d, 0xd2, 0xb8, 0xed, 0x53, 0x58, 0x3e, 0xb4, 0x65, 0xfb,
+    0xca, 0x9f, 0xfe, 0x5c, 0x68, 0x20, 0x58, 0xd9, 0xfd, 0xc7, 0x4d, 0x0f, 0x03, 0x37, 0x61, 0xaf,
+    0x2b, 0x90, 0xe1, 0xfc, 0x15, 0xa6, 0xf1, 0xac, 0x5d, 0xad, 0xb4, 0xbe, 0xf6, 0xb4, 0x7b, 0x42,
+    0xe6, 0x17, 0xe9, 0x79, 0xde, 0x65, 0x50, 0x70, 0x6b, 0x46, 0x24, 0x73, 0x4d, 0xa3, 0x54, 0x3a,
+    0x21, 0xc2, 0x1c, 0x80, 0x1d, 0xf6, 0xd4, 0x0e, 0x7a, 0xa5, 0x4e, 0x97, 0xc1, 0x15, 0x37, 0x02,
+    0xea, 0x55, 0xff, 0xad, 0x59, 0x95, 0xa0, 0x24, 0xd0, 0x58, 0x59, 0xf7, 0x9a, 0x4e, 0x2b, 0x78,
+    0x89, 0x91, 0x9c, 0x67, 0x14, 0xe4, 0x24, 0xc3, 0xb8, 0xd3, 0x7d, 0x06, 0xaf, 0x46, 0x8f, 0xe7,
+    0x07, 0x88, 0xf0, 0x4c, 0xf4, 0xb8, 0x3a, 0x2a, 0x9c, 0x89, 0x2f, 0x7c, 0x32, 0xfd, 0x52, 0x55,
+    0xd8, 0xe1, 0x58, 0x46, 0xe5, 0xc3, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x02, 0x00, 0x08,
+    0x79, 0xcf, 0xb2, 0xc9, 0x57, 0xfa, 0x06, 0xce, 0x13, 0xda, 0x88, 0x1f, 0xd7, 0xdc, 0x53, 0x59,
+    0xb8, 0x92, 0x90, 0x8c, 0xa1, 0xc3, 0xcd, 0x1d, 0xd5, 0x26, 0xdf, 0x04, 0x5b, 0x47, 0xd5, 0xdb,
+    0x0b, 0xdf, 0x3d, 0xca, 0x2d, 0xc8, 0x39, 0x12, 0xcd, 0xd3, 0x50, 0xd2, 0x96, 0x13, 0x9c, 0xb2,
+    0x45, 0xd1, 0x7d, 0x84, 0xfd, 0x97, 0x07, 0xef, 0xb2, 0xea, 0x46, 0xb2, 0x91, 0x64, 0xb5, 0xd6,
+    0x47, 0xec, 0x04, 0x40, 0xbd, 0x7c, 0xd5, 0x69, 0x5a, 0xc1, 0xf2, 0xc6, 0x76, 0xf7, 0x65, 0x06,
+    0xc2, 0xc3, 0xae, 0xd6, 0xf9, 0x31, 0x44, 0xa2, 0xf0, 0x96, 0x04, 0xd8, 0xfd, 0xe9, 0xaa, 0xb8,
+    0x8b, 0x31, 0x9a, 0x30, 0x63, 0x57, 0xf8, 0x12, 0xae, 0xb9, 0xa8, 0xc7, 0x14, 0x03, 0xae, 0xf0,
+    0x22, 0x5e, 0x03, 0xae, 0xff, 0x8e, 0x36, 0x85, 0x79, 0x59, 0x82, 0xa8, 0xde, 0x64, 0xa6, 0x61,
+    0x5d, 0xc5, 0x0c, 0x43, 0x6d, 0xf8, 0x2d, 0x5e, 0xaf, 0xe7, 0x83, 0x5c, 0x93, 0x8a, 0x03, 0xe4,
+    0x3b, 0xd6, 0x73, 0x62, 0x33, 0x70, 0xf9, 0xa1, 0x4b, 0x05, 0x5f, 0x19, 0xf8, 0x0e, 0xbe, 0x3a,
+    0xa9, 0x68, 0x5c, 0xa9, 0xdf, 0x80, 0x64, 0x0c, 0x25, 0xd9, 0x44, 0xa8, 0x65, 0xdb, 0xab, 0xeb,
+    0xc4, 0xe7, 0xdb, 0xda, 0xc9, 0x44, 0xe0, 0x97, 0x82, 0x06, 0x80, 0x64, 0x11, 0x34, 0xcd, 0x90,
+    0x4b, 0xe8, 0x81, 0x6d, 0xdd, 0x15, 0x77, 0x8e, 0x55, 0x77, 0xba, 0xe5, 0x2f, 0x35, 0x1a, 0x23,
+    0x67, 0x68, 0xd8, 0x27, 0xeb, 0xef, 0xca, 0xd1, 0xc3, 0x25, 0x09, 0xd8, 0x86, 0xcd, 0x6f, 0xe5,
+    0x00, 0x2d, 0x47, 0xc9, 0xf2, 0x6c, 0x4d, 0xb9, 0xa2, 0x86, 0xfe, 0xae, 0x95, 0x1f, 0xf4, 0x71,
+    0x83, 0xac, 0x6e, 0x8a, 0x09, 0xe3, 0x5c, 0x07, 0xc4, 0x3c, 0x3a, 0x50, 0x0f, 0xb6, 0x90, 0x21,
+    0x25, 0xdf, 0x2d, 0x61, 0x89, 0xb6, 0x3c, 0xb3, 0xc3, 0xc0, 0xd9, 0x2e, 0x73, 0x76, 0xf6, 0x46,
+    0x46, 0xf8, 0x01, 0xbd, 0x0b, 0x94, 0x80, 0xf6, 0x94, 0x5b, 0x17, 0x9e, 0xbc, 0xdb, 0x9d, 0xfd,
+    0xc2, 0x3e, 0x56, 0xa1, 0xa0, 0x1a, 0xed, 0x82, 0xcb, 0xb0, 0xb3, 0xd4, 0x58, 0xb4, 0x91, 0x8e,
+    0xd9, 0x84, 0xb8, 0x94, 0xc2, 0x86, 0x42, 0xa6, 0x86, 0xf2, 0x9c, 0x1d, 0xc7, 0xc9, 0xed, 0x6d,
+    0x0d, 0x8d, 0x98, 0x08, 0xf3, 0x52, 0xe7, 0x7f, 0xfe, 0xe0, 0x9f, 0xdf, 0x43, 0x8e, 0xbc, 0x3f,
+    0x93, 0x41, 0x44, 0x7b, 0x26, 0x0e, 0x2e, 0xc1, 0xc2, 0x4e, 0xc7, 0xb4, 0x5c, 0xc5, 0x55, 0xae,
+    0xbb, 0xb4, 0x2f, 0xd5, 0x1f, 0x34, 0xce, 0x94, 0x66, 0x12, 0x41, 0x8a, 0x15, 0x8b, 0xcb, 0xdd,
+    0x00, 0xf9, 0xa0, 0x55, 0xa6, 0x8b, 0xe9, 0x13, 0x14, 0xc6, 0x0b, 0x98, 0x8f, 0xff, 0x2f, 0x9a,
+    0xe8, 0x78, 0x68, 0x94, 0xeb, 0x53, 0xeb, 0x4b, 0xed, 0x5a, 0x6d, 0x1c, 0xe2, 0xe5, 0xc7, 0xde,
+    0x13, 0xa9, 0xaf, 0xa3, 0xc7, 0x54, 0x26, 0xa0, 0x3f, 0x44, 0xdd, 0x9f, 0x14, 0xe2, 0xc4, 0x9a,
+    0xf5, 0x30, 0xea, 0x2e, 0x75, 0xc6, 0xd3, 0xf8, 0x5e, 0x9b, 0x02, 0x0d, 0xc8, 0x81, 0x6c, 0x13,
+    0x3b, 0x9c, 0x89, 0x54, 0x52, 0x41, 0x62, 0xad, 0xa0, 0x52, 0xaa, 0x2c, 0xc4, 0x2c, 0x63, 0x58,
+    0xf6, 0xb1, 0xfa, 0xdc, 0x77, 0xed, 0x3e, 0x8c, 0x12, 0x94, 0x09, 0x57, 0x18, 0xb3, 0x04, 0x53,
+    0x3c, 0xad, 0xa8, 0x45, 0x4b, 0x19, 0xa0, 0xcb, 0x8f, 0x6f, 0x5d, 0x2d, 0xcc, 0xe1, 0xfe, 0x4a,
+    0xe6, 0x20, 0xed, 0x9a, 0x76, 0x4f, 0x17, 0xfd, 0xed, 0x1e, 0x6e, 0x41, 0x21, 0x43, 0xe4, 0xe9,
+    0x47, 0x01, 0x1f, 0x76, 0x68, 0x4d, 0xbb, 0xd3, 0xba, 0x68, 0x34, 0x06, 0x6a, 0xf5, 0xe9, 0x02,
+    0x82, 0x01, 0x01, 0x00, 0xdb, 0xc5, 0x0d, 0x95, 0x88, 0x5f, 0x2c, 0xa9, 0x7c, 0xb7, 0x06, 0xd8,
+    0x20, 0x60, 0x72, 0x80, 0xec, 0xae, 0xf4, 0xdc, 0x48, 0x5d, 0x9d, 0x6d, 0x2a, 0x54, 0x36, 0xe1,
+    0x32, 0x25, 0x10, 0x4d, 0x56, 0x0f, 0x51, 0xe9, 0xbc, 0x95, 0x3f, 0x38, 0x43, 0xed, 0xc6, 0x6a,
+    0x16, 0xb0, 0x06, 0x90, 0x85, 0x51, 0x07, 0xea, 0x7b, 0x1d, 0x64, 0x12, 0x39, 0x7e, 0x32, 0x92,
+    0x3e, 0xcc, 0x97, 0x91, 0x02, 0x6c, 0xf8, 0x95, 0xc7, 0x39, 0xa1, 0x5c, 0xd3, 0x62, 0xcc, 0x29,
+    0x83, 0x27, 0xe6, 0x36, 0xba, 0xf6, 0x62, 0x80, 0xf6, 0x15, 0xda, 0x0f, 0xc4, 0x47, 0x81, 0x44,
+    0x96, 0xba, 0xec, 0x37, 0x8c, 0x95, 0xb2, 0x30, 0x12, 0xc0, 0x4d, 0x62, 0x88, 0x5e, 0x7d, 0x13,
+    0x6d, 0x83, 0x14, 0x1e, 0xd7, 0xc2, 0xeb, 0x9d, 0xbd, 0xa4, 0x70, 0x78, 0xf3, 0xb1, 0x6b, 0x6c,
+    0xe9, 0x37, 0x63, 0x47, 0x6f, 0xed, 0xea, 0xd6, 0x32, 0x80, 0x71, 0xa2, 0x7f, 0x38, 0x67, 0xb4,
+    0x1f, 0xf0, 0x7f, 0xb6, 0xb7, 0x56, 0xe7, 0x24, 0xaa, 0x2f, 0xb9, 0x93, 0xb8, 0xab, 0x2a, 0xec,
+    0xc4, 0x19, 0x9a, 0xea, 0x5d, 0x01, 0x1e, 0xdd, 0x5c, 0x05, 0x37, 0x12, 0x04, 0x32, 0xb2, 0x5d,
+    0x16, 0xdc, 0x88, 0x0c, 0xfe, 0x1e, 0xf6, 0x9f, 0x63, 0xbf, 0xb2, 0x00, 0x6b, 0x99, 0xbe, 0x42,
+    0x96, 0x41, 0xe0, 0x3d, 0xd1, 0x35, 0x6a, 0xf1, 0x81, 0x09, 0xd6, 0x4c, 0xdd, 0xc0, 0x20, 0x6e,
+    0x0d, 0xcb, 0x30, 0x11, 0x73, 0x11, 0x82, 0x5e, 0x1b, 0x9a, 0xa0, 0x57, 0xcd, 0xd7, 0xab, 0xa2,
+    0xe9, 0xed, 0xe7, 0x26, 0x8d, 0x30, 0x09, 0xe7, 0x5a, 0xa1, 0xd0, 0x62, 0xac, 0x7f, 0x15, 0xd1,
+    0x9a, 0x0a, 0x97, 0x5d, 0x8a, 0xc0, 0x47, 0xa4, 0xa8, 0x8b, 0x26, 0x75, 0x35, 0x5d, 0xa9, 0xf1,
+    0x1a, 0x61, 0xdc, 0xbf, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc8, 0x63, 0x6e, 0x9c, 0x88, 0xcd, 0x33,
+    0xef, 0x72, 0x80, 0x00, 0x6b, 0x8e, 0xb0, 0xd2, 0xa9, 0x5c, 0x78, 0xf7, 0x25, 0x8f, 0xba, 0x49,
+    0x60, 0xa3, 0x33, 0xf4, 0x16, 0x1c, 0x81, 0xad, 0x82, 0x39, 0xa5, 0xa8, 0x12, 0xc2, 0x7e, 0x05,
+    0x33, 0x9c, 0xd9, 0xa9, 0xa4, 0x02, 0xf8, 0x43, 0xdf, 0xa6, 0x39, 0xdb, 0xc0, 0x60, 0xdc, 0x53,
+    0x76, 0x7c, 0xef, 0xf0, 0x58, 0x44, 0x3d, 0xc7, 0x77, 0xe6, 0x6f, 0x2a, 0xbd, 0x89, 0x8b, 0x40,
+    0xe3, 0x02, 0x80, 0x8c, 0x46, 0x24, 0x4c, 0x63, 0xc4, 0x06, 0xb1, 0x48, 0x92, 0x0a, 0x86, 0x58,
+    0xe3, 0x08, 0x2a, 0x2e, 0x4b, 0xdd, 0xa6, 0x64, 0x68, 0xe9, 0xac, 0x07, 0x2b, 0x3d, 0x2f, 0x42,
+    0x68, 0x5a, 0x42, 0xdb, 0xb7, 0x5a, 0x67, 0xc4, 0x5f, 0x19, 0xba, 0xff, 0xed, 0x17, 0x0b, 0xf8,
+    0x26, 0x36, 0xd7, 0x9d, 0x3a, 0x3d, 0x0e, 0x5f, 0x31, 0x29, 0x3f, 0xf4, 0x24, 0x2f, 0x0a, 0xa2,
+    0x21, 0x0e, 0x6e, 0x86, 0xf5, 0x1e, 0xb7, 0xce, 0x81, 0x95, 0xd0, 0xcd, 0x97, 0xd1, 0x2c, 0xd4,
+    0x9f, 0x95, 0xd6, 0x7c, 0x68, 0x80, 0x4f, 0xe6, 0x5c, 0xab, 0xfe, 0x6b, 0xf9, 0x8b, 0x12, 0x99,
+    0xad, 0xc9, 0x64, 0x21, 0x99, 0xef, 0xfb, 0xd3, 0x16, 0x8b, 0x95, 0x93, 0xa7, 0xb7, 0x24, 0x36,
+    0x00, 0xb2, 0xa2, 0xbe, 0x79, 0x4e, 0x66, 0xbd, 0xe1, 0x2d, 0xd0, 0xa9, 0x76, 0xe1, 0x13, 0x0d,
+    0xb5, 0x4b, 0xc5, 0xe9, 0x63, 0x23, 0x45, 0xcf, 0x5f, 0x0d, 0x5c, 0xce, 0x93, 0x7f, 0xa9, 0x68,
+    0xf6, 0xfc, 0x2c, 0x54, 0x40, 0x43, 0xca, 0x9d, 0xfd, 0x43, 0x81, 0x4d, 0xbe, 0x98, 0x87, 0xca,
+    0x2c, 0x82, 0x32, 0xb7, 0xcf, 0xa1, 0xc5, 0xf8, 0x55, 0xea, 0x2b, 0x6d, 0xfc, 0xe7, 0x5d, 0xcf,
+    0xde, 0xf8, 0x15, 0xc2, 0xc3, 0xa2, 0xe6, 0x83, 0xfd, 0x02, 0x82, 0x01, 0x00, 0x2c, 0x83, 0x3a,
+    0xff, 0x20, 0x81, 0xf6, 0x6f, 0xd5, 0xbc, 0xd4, 0x7c, 0x0e, 0x02, 0xba, 0xee, 0x76, 0x01, 0xf1,
+    0xc2, 0x74, 0x3d, 0xd1, 0xd6, 0xfc, 0x8d, 0xd6, 0x17, 0xc2, 0xaa, 0x53, 0x24, 0xf6, 0xdb, 0x5f,
+    0x81, 0xf2, 0x1a, 0x60, 0x95, 0xaa, 0xdc, 0x8c, 0x25, 0x8c, 0xb6, 0xd6, 0x7d, 0x8b, 0x23, 0x20,
+    0x71, 0x53, 0xc2, 0x5e, 0x34, 0x7a, 0xc4, 0x9e, 0xc5, 0x94, 0x46, 0xa8, 0x24, 0x4c, 0xd3, 0x79,
+    0x7e, 0x0c, 0xbe, 0x15, 0x7a, 0xd1, 0xad, 0xdf, 0x20, 0x41, 0x5a, 0x61, 0x7c, 0x90, 0x5d, 0xbb,
+    0x11, 0xd7, 0xc6, 0x11, 0x46, 0xc4, 0x40, 0x9f, 0x64, 0x1f, 0x0b, 0x79, 0x30, 0xbf, 0x1e, 0xca,
+    0xda, 0x85, 0xd1, 0xc1, 0x5a, 0xc5, 0xb8, 0x2d, 0xa9, 0x33, 0xb3, 0x2a, 0xee, 0x1c, 0x51, 0x74,
+    0x9b, 0x9c, 0x7f, 0xa3, 0xf0, 0x3b, 0x9b, 0xa1, 0xe0, 0x8b, 0x54, 0x16, 0x9d, 0xaf, 0x84, 0x06,
+    0xde, 0x9f, 0x97, 0xf8, 0x6c, 0x2b, 0x4c, 0x67, 0x64, 0xca, 0x5b, 0x51, 0xe2, 0xd6, 0x3b, 0x99,
+    0xd1, 0x89, 0x4e, 0xe5, 0x4d, 0x90, 0x47, 0xcb, 0x07, 0xed, 0xa8, 0x2a, 0x02, 0x72, 0x17, 0xfa,
+    0x02, 0x67, 0xd2, 0xfe, 0x96, 0x7d, 0x97, 0x2f, 0x1d, 0x3f, 0xb6, 0x27, 0x30, 0x4a, 0x80, 0x46,
+    0xff, 0x7d, 0x9a, 0xa4, 0x19, 0x05, 0xb2, 0x3c, 0x21, 0x0c, 0x82, 0x07, 0x43, 0x3e, 0x0e, 0x8d,
+    0xbc, 0xa0, 0xa0, 0x37, 0x71, 0x96, 0x30, 0x85, 0xe1, 0x04, 0x96, 0x35, 0x04, 0x33, 0xc4, 0x46,
+    0x1d, 0x7d, 0x85, 0xd2, 0x18, 0x36, 0xaf, 0x0a, 0x2a, 0x93, 0x2b, 0x06, 0x78, 0x7e, 0x7c, 0x4e,
+    0x65, 0x37, 0xac, 0x32, 0xa2, 0xe9, 0xc1, 0x4b, 0xd0, 0x0a, 0x5d, 0x3e, 0xcf, 0x49, 0x7d, 0x2c,
+    0x85, 0xa3, 0x45, 0x9b, 0xe2, 0x7d, 0x8e, 0x9d, 0x0f, 0x22, 0x82, 0xd3, 0xcd, 0x02, 0x82, 0x01,
+    0x00, 0x46, 0xe8, 0x18, 0x3d, 0xbf, 0x92, 0x8c, 0xec, 0x0f, 0xa2, 0x07, 0x84, 0x07, 0xab, 0xbd,
+    0xff, 0x3b, 0xbf, 0x7a, 0x04, 0x8a, 0x85, 0x2a, 0x6d, 0xcd, 0x92, 0x16, 0xae, 0xb4, 0x4b, 0x96,
+    0xaf, 0xdb, 0xe2, 0x28, 0x44, 0xeb, 0x19, 0x58, 0x91, 0xd8, 0xd0, 0x94, 0x5c, 0x7a, 0xc8, 0x8a,
+    0x8b, 0xda, 0xef, 0xe2, 0x38, 0x82, 0x8d, 0xb3, 0xe2, 0xdb, 0x76, 0xb3, 0x9f, 0x28, 0x16, 0x8c,
+    0x3c, 0x7b, 0x07, 0x9f, 0x22, 0x0e, 0x47, 0x7e, 0x20, 0x55, 0xc4, 0x52, 0xde, 0x86, 0xfd, 0x98,
+    0xd7, 0xc6, 0x5e, 0x79, 0x05, 0x64, 0x40, 0x01, 0xb7, 0xe4, 0x2d, 0xb8, 0xd0, 0x13, 0x90, 0x4b,
+    0x3b, 0x6c, 0x63, 0xf8, 0xed, 0x6d, 0xeb, 0x09, 0x1e, 0x8f, 0xc1, 0xd4, 0xa9, 0x5e, 0x8e, 0x15,
+    0x48, 0x69, 0x7c, 0x68, 0x0e, 0xe6, 0xf6, 0xcf, 0x4a, 0x06, 0x61, 0xe9, 0x3a, 0xb0, 0x5c, 0x23,
+    0x86, 0xeb, 0xc7, 0xbb, 0x86, 0x0a, 0x37, 0x43, 0x03, 0x5b, 0x6d, 0xf4, 0xc7, 0x4b, 0xa5, 0x52,
+    0xa7, 0x3b, 0xf1, 0xf4, 0xad, 0xe1, 0xd0, 0x71, 0x34, 0x3e, 0xfa, 0xf4, 0x6e, 0xad, 0xe8, 0x97,
+    0xe4, 0xf6, 0xdf, 0x42, 0x29, 0xbc, 0xf2, 0x49, 0xfa, 0xda, 0xa6, 0x59, 0xd5, 0x74, 0xbb, 0xb1,
+    0x07, 0xeb, 0x40, 0x74, 0x4d, 0x06, 0x5b, 0x03, 0xd8, 0xdf, 0x5d, 0x02, 0xf5, 0x3d, 0xae, 0xd1,
+    0x45, 0x9a, 0xc6, 0x99, 0x10, 0x7d, 0xb8, 0x16, 0x43, 0xae, 0x9a, 0x4b, 0x69, 0x4f, 0x13, 0xe6,
+    0xbb, 0x05, 0xa9, 0x6f, 0x57, 0x75, 0xf6, 0xe6, 0x33, 0x6f, 0x2b, 0xe8, 0x6c, 0x0d, 0x10, 0xe7,
+    0x32, 0xb4, 0xee, 0x4e, 0x2a, 0x41, 0x22, 0xdb, 0x81, 0x40, 0x58, 0xdd, 0xfd, 0xd4, 0x8a, 0x8e,
+    0xc3, 0x27, 0xe7, 0x52, 0x36, 0x09, 0x50, 0x82, 0xbb, 0xad, 0x21, 0x56, 0x17, 0x8f, 0xce, 0xed,
+    0xa9, 0x02, 0x82, 0x01, 0x00, 0x78, 0x0c, 0x4f, 0x07, 0x4a, 0x2d, 0x91, 0xa3, 0xfd, 0x1c, 0xb3,
+    0xb5, 0xcb, 0x11, 0x1c, 0x04, 0xc9, 0x7f, 0xbf, 0x86, 0x7d, 0x5e, 0x2e, 0xf4, 0x2c, 0xad, 0x9e,
+    0x35, 0x74, 0x2e, 0x55, 0xc6, 0xaf, 0x1c, 0x76, 0xb9, 0x3d, 0x44, 0xe7, 0xdd, 0x5f, 0x32, 0x0e,
+    0xce, 0x4b, 0x43, 0x6d, 0x7c, 0x10, 0xd3, 0x01, 0x6f, 0x22, 0xa5, 0xb3, 0xaf, 0x40, 0x80, 0x57,
+    0xf0, 0x96, 0x7c, 0xb8, 0xae, 0xbc, 0x35, 0x8b, 0xa1, 0x59, 0xdc, 0xc4, 0xf7, 0x8b, 0xda, 0xe7,
+    0x91, 0x9b, 0xa7, 0x54, 0x61, 0xad, 0x9d, 0x0a, 0x68, 0xc3, 0xc5, 0x10, 0x9e, 0x39, 0x16, 0x9c,
+    0x3b, 0xf3, 0x3a, 0xdf, 0xb9, 0x72, 0xed, 0x4f, 0x56, 0x1e, 0x5c, 0x8b, 0x35, 0x0b, 0xa6, 0x08,
+    0x83, 0x96, 0xd4, 0x6d, 0x3f, 0xe3, 0x6a, 0x25, 0xa2, 0xe8, 0x0f, 0xce, 0x0c, 0x26, 0x85, 0x02,
+    0xba, 0xe1, 0xfc, 0xdc, 0xa0, 0x18, 0xfc, 0x7c, 0x87, 0xa6, 0x6b, 0xf5, 0x92, 0xa8, 0x83, 0x5f,
+    0xbf, 0xa5, 0xe3, 0x0e, 0x21, 0x10, 0xbf, 0x44, 0x49, 0xc7, 0x62, 0x36, 0x46, 0x0b, 0x97, 0xdc,
+    0xd4, 0x30, 0x02, 0xd4, 0x04, 0xcb, 0x8f, 0xfe, 0xde, 0x76, 0x44, 0x9f, 0xd6, 0x55, 0x8e, 0x45,
+    0xaa, 0x10, 0xd4, 0xa0, 0x2c, 0x49, 0x72, 0x6e, 0x5f, 0xf1, 0xd5, 0x0a, 0x1e, 0xba, 0xc6, 0xb4,
+    0xb6, 0x93, 0x9d, 0x6a, 0xe4, 0xaa, 0x61, 0x3a, 0xca, 0x77, 0xa4, 0x16, 0xa2, 0x4f, 0x2f, 0xad,
+    0xe6, 0xb5, 0x64, 0x93, 0x37, 0xf9, 0xdc, 0x28, 0x70, 0x54, 0x0b, 0xb2, 0x15, 0x96, 0x60, 0xbc,
+    0x86, 0x16, 0xfc, 0x5c, 0xf0, 0x75, 0xc2, 0x6f, 0x51, 0x4f, 0x71, 0xbb, 0x77, 0xed, 0xe8, 0x2b,
+    0xf2, 0xe3, 0x7d, 0x02, 0xa8, 0xfe, 0x26, 0x8a, 0x40, 0x63, 0x8f, 0x14, 0x84, 0xd2, 0x00, 0x70,
+    0x6a, 0xf3, 0xde, 0xf8, 0x66};
+constexpr const unsigned int rsa_key_4k_len = sizeof(rsa_key_4k);
+
+constexpr const unsigned char rsa_key_2k[] = {
+    0x30, 0x82, 0x04, 0xbd, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x04, 0xa7, 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01,
+    0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9d, 0xd0, 0xca, 0x63, 0xaa, 0x59, 0x73, 0x13, 0x55, 0x53,
+    0xdc, 0x5d, 0x4d, 0xf9, 0x5c, 0x4f, 0x31, 0xe3, 0x34, 0x45, 0xbf, 0xc5, 0x8b, 0x43, 0x8f, 0x10,
+    0xb6, 0x22, 0xaf, 0xe0, 0x12, 0xff, 0xf5, 0xa8, 0x71, 0x0a, 0xe9, 0x67, 0x8d, 0x05, 0xd2, 0x69,
+    0x35, 0x32, 0x8d, 0x94, 0x9f, 0x52, 0x63, 0x4e, 0x54, 0x0b, 0x29, 0x3d, 0x7b, 0x5e, 0xc0, 0x98,
+    0x94, 0x23, 0x43, 0x46, 0x39, 0xce, 0xc2, 0xe1, 0x2b, 0xcd, 0x00, 0x6c, 0x9d, 0xe7, 0x81, 0xb9,
+    0x6b, 0x97, 0xea, 0x3a, 0xe7, 0x09, 0x06, 0x6b, 0xf3, 0xe1, 0x7a, 0x03, 0xcd, 0x51, 0x2c, 0x16,
+    0x19, 0x6c, 0xdf, 0x2c, 0xd5, 0x96, 0x92, 0x19, 0xaa, 0x91, 0xe3, 0xa5, 0xc7, 0xe1, 0x0b, 0x07,
+    0xb6, 0x84, 0xd3, 0xa7, 0x1f, 0x0d, 0x22, 0xb9, 0xc1, 0x76, 0x16, 0x81, 0x53, 0x50, 0x7d, 0x54,
+    0x2a, 0x26, 0x9e, 0xfa, 0xb1, 0xb7, 0x83, 0x05, 0x24, 0x81, 0xea, 0x5a, 0x6c, 0xb5, 0x92, 0x69,
+    0x63, 0x35, 0xfa, 0x04, 0xae, 0xee, 0xc5, 0xdb, 0xf0, 0x9b, 0xfe, 0xe6, 0xc4, 0x73, 0x18, 0x3d,
+    0xd3, 0x01, 0xaf, 0x03, 0x43, 0x95, 0xca, 0xab, 0x43, 0x04, 0x64, 0x49, 0xe7, 0x47, 0xf8, 0x97,
+    0xe5, 0x63, 0xd1, 0x3d, 0x21, 0x9b, 0xd5, 0x13, 0x2a, 0xb0, 0xf1, 0xf9, 0xff, 0xd2, 0xb7, 0x12,
+    0xa8, 0xa0, 0x20, 0x38, 0xde, 0x41, 0x8e, 0xa3, 0xc7, 0xce, 0x5b, 0x9c, 0x30, 0x1a, 0xaf, 0x13,
+    0x11, 0xd1, 0xd0, 0x71, 0x7f, 0x1e, 0x47, 0xa8, 0x32, 0x3b, 0x4a, 0x36, 0xa8, 0x6d, 0x8c, 0xd7,
+    0x5f, 0x93, 0x95, 0xa8, 0xe0, 0xfa, 0x59, 0xb5, 0x6c, 0x1f, 0xfb, 0x01, 0x64, 0xf5, 0x5d, 0xf5,
+    0x17, 0x75, 0x53, 0xfb, 0xc3, 0x3f, 0xd7, 0xc5, 0x45, 0x53, 0xb4, 0xa2, 0xcf, 0xa5, 0x71, 0xf0,
+    0x7a, 0x8b, 0x66, 0x09, 0xfa, 0x4d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x03,
+    0xe9, 0x06, 0x4d, 0x6a, 0xe2, 0xa0, 0x2b, 0x24, 0xa1, 0x99, 0x23, 0xb2, 0x08, 0xbc, 0x2f, 0x4a,
+    0xd2, 0xa6, 0x30, 0x6b, 0x91, 0xd6, 0xf8, 0xb1, 0x0f, 0x9e, 0x71, 0x04, 0x94, 0xe8, 0xe8, 0xf1,
+    0x00, 0x1f, 0xf0, 0xea, 0x70, 0x97, 0x8f, 0x6d, 0xde, 0x65, 0x24, 0x35, 0x5a, 0xd9, 0xdf, 0x13,
+    0x8e, 0x7f, 0x74, 0x44, 0x02, 0x28, 0x7a, 0x39, 0x61, 0x19, 0x1b, 0xe3, 0x3b, 0xac, 0x62, 0x01,
+    0x9f, 0xcc, 0xfd, 0xdd, 0x85, 0x53, 0x72, 0x46, 0xdb, 0x69, 0x1d, 0x90, 0xa9, 0xad, 0xf6, 0x22,
+    0x1e, 0x6e, 0xf8, 0x06, 0xc0, 0x6d, 0x08, 0x16, 0x5a, 0x0e, 0x7e, 0x37, 0xec, 0xbc, 0xa1, 0x68,
+    0x49, 0xa7, 0x84, 0x1e, 0xdf, 0xb4, 0x30, 0xa6, 0x1d, 0x26, 0x4f, 0x6b, 0x39, 0x1d, 0xad, 0x58,
+    0x7a, 0x16, 0xca, 0x38, 0xc0, 0xdd, 0x3c, 0xc6, 0x26, 0x32, 0xe1, 0xd5, 0xc2, 0xeb, 0x6a, 0xa6,
+    0x70, 0x1f, 0x50, 0x82, 0x2d, 0xf6, 0x09, 0x27, 0x56, 0x4f, 0xf1, 0xed, 0x62, 0x60, 0xe5, 0x55,
+    0x0f, 0x8d, 0xbe, 0xd7, 0x5a, 0xb7, 0x7c, 0x57, 0x25, 0xe5, 0xa3, 0x46, 0xb6, 0x97, 0xe0, 0x87,
+    0x43, 0x04, 0x46, 0xd8, 0x4f, 0xbe, 0x80, 0x75, 0x40, 0x48, 0x2d, 0xc0, 0x57, 0xf8, 0x76, 0xbd,
+    0xd8, 0x14, 0xa0, 0x7b, 0x39, 0x4f, 0xcf, 0xdc, 0x34, 0x5b, 0x1e, 0x91, 0xef, 0xa7, 0xc8, 0x82,
+    0x2c, 0xe8, 0xe4, 0x01, 0x2b, 0xa6, 0x92, 0x4e, 0x0b, 0xd1, 0x98, 0xdc, 0x45, 0x46, 0x3f, 0x89,
+    0xb1, 0x01, 0xb5, 0xa7, 0xeb, 0x71, 0x2f, 0x09, 0x10, 0x3c, 0x71, 0x14, 0xf3, 0x86, 0x18, 0xa8,
+    0x5a, 0x30, 0xef, 0xfe, 0x87, 0x65, 0xb1, 0xaf, 0x9c, 0x8d, 0x3e, 0xc8, 0x8d, 0x72, 0xf5, 0x16,
+    0xcb, 0x3a, 0xb8, 0xb1, 0x18, 0xa5, 0x43, 0x1d, 0x24, 0xa1, 0x1c, 0x2d, 0x2d, 0x87, 0xc1, 0x02,
+    0x81, 0x81, 0x00, 0xde, 0x87, 0xff, 0x74, 0x9d, 0x86, 0x9b, 0x0b, 0x18, 0xb7, 0xa4, 0x50, 0xda,
+    0x2d, 0x27, 0xff, 0x0e, 0x4d, 0xae, 0x40, 0x21, 0x92, 0x0b, 0x1d, 0x8b, 0xdd, 0x81, 0xdc, 0x40,
+    0x1c, 0xed, 0x7d, 0x39, 0xd6, 0x1d, 0xdd, 0x88, 0xd0, 0x92, 0xee, 0x74, 0xca, 0x96, 0xa7, 0x6a,
+    0x58, 0xd3, 0xc6, 0xf4, 0x3e, 0x93, 0x43, 0x54, 0x07, 0x72, 0x3a, 0x8d, 0x3b, 0x09, 0xe0, 0x16,
+    0x16, 0x71, 0xf1, 0xae, 0xc4, 0xc0, 0x46, 0xce, 0x40, 0x6d, 0xba, 0xf0, 0x4d, 0x1d, 0x04, 0x9a,
+    0x32, 0x31, 0xe1, 0x07, 0x9b, 0x90, 0x7c, 0xc2, 0xb2, 0xfc, 0x4e, 0xb9, 0x61, 0xd4, 0xdb, 0x4a,
+    0xa1, 0xb9, 0x78, 0x46, 0x98, 0xa9, 0xfb, 0x21, 0x60, 0xb8, 0x07, 0x6b, 0x24, 0x4d, 0x4d, 0x35,
+    0x83, 0x0b, 0x21, 0xac, 0xdf, 0x93, 0x2f, 0xb5, 0xec, 0xe5, 0x99, 0x1a, 0x59, 0xaa, 0xd3, 0xbb,
+    0x8f, 0xe9, 0xad, 0x02, 0x81, 0x81, 0x00, 0xb5, 0x8d, 0x14, 0x8e, 0x85, 0xd9, 0x7c, 0x9e, 0xfc,
+    0xa1, 0x1f, 0x1a, 0x84, 0x31, 0x07, 0x71, 0x1a, 0x72, 0x91, 0xc0, 0xc5, 0xac, 0x8f, 0xa7, 0x0f,
+    0x37, 0x48, 0x51, 0x12, 0xda, 0x0d, 0x30, 0x6d, 0x97, 0x21, 0x20, 0x90, 0x49, 0x4d, 0x2b, 0xc1,
+    0x89, 0x8e, 0x00, 0x66, 0x18, 0x47, 0xd5, 0x68, 0x62, 0xe7, 0x29, 0xf4, 0x95, 0x59, 0x5b, 0xba,
+    0x4b, 0xc2, 0x20, 0xda, 0xef, 0x4f, 0x33, 0x0e, 0x99, 0xfe, 0x6c, 0xec, 0xf9, 0xd8, 0x81, 0x3a,
+    0x46, 0x1a, 0xbd, 0xba, 0xf7, 0xfc, 0xd7, 0x19, 0xf8, 0x2d, 0xd1, 0x81, 0x88, 0xce, 0x55, 0x98,
+    0xe6, 0xbc, 0x25, 0x67, 0xa6, 0xbe, 0x2b, 0x0f, 0x1d, 0xb6, 0x0d, 0xea, 0xc6, 0xb6, 0x95, 0xee,
+    0x42, 0x3e, 0x1b, 0xf5, 0x8c, 0xf3, 0x19, 0x8e, 0x59, 0xfc, 0xe1, 0x42, 0x1b, 0x26, 0x20, 0x09,
+    0x8a, 0x1b, 0x57, 0x8e, 0xe1, 0xa7, 0x21, 0x02, 0x81, 0x80, 0x78, 0xc7, 0x33, 0x7d, 0x25, 0xaa,
+    0x53, 0x28, 0x38, 0xa8, 0x23, 0x84, 0xc6, 0x85, 0xcf, 0xb9, 0x7d, 0x17, 0xe8, 0x45, 0x62, 0x73,
+    0x13, 0x99, 0x5b, 0xba, 0x43, 0xab, 0x39, 0x18, 0xfa, 0x45, 0x07, 0x49, 0x11, 0x38, 0x95, 0xf3,
+    0x2e, 0x6c, 0x41, 0xf3, 0x5a, 0xc5, 0x4e, 0xd1, 0x1b, 0x50, 0x56, 0x6c, 0x48, 0x1d, 0x38, 0xd4,
+    0x39, 0xc9, 0x51, 0xb2, 0x03, 0x70, 0x1e, 0x4c, 0xdc, 0x57, 0x22, 0x56, 0x23, 0x4d, 0xca, 0xcf,
+    0xe9, 0x3e, 0x97, 0x02, 0x23, 0x87, 0xc5, 0xf1, 0x0c, 0x65, 0x68, 0x6d, 0xa4, 0x84, 0x32, 0x60,
+    0x56, 0xd4, 0x9b, 0x85, 0x5f, 0xb4, 0x0d, 0xd3, 0xad, 0x08, 0x7c, 0xb8, 0x8b, 0x39, 0x84, 0x2a,
+    0x2c, 0x77, 0xca, 0x4d, 0x0f, 0xaf, 0xa2, 0x25, 0x97, 0xbb, 0x15, 0x4a, 0xdb, 0x65, 0xff, 0xc5,
+    0xad, 0xef, 0xe4, 0xff, 0x59, 0xda, 0x45, 0x68, 0x9c, 0x99, 0x02, 0x81, 0x80, 0x16, 0x45, 0x0a,
+    0xfb, 0x7c, 0x91, 0xb4, 0x06, 0xb0, 0x88, 0x77, 0x0f, 0x42, 0x9d, 0xdd, 0x02, 0xd3, 0xb2, 0xb0,
+    0x0c, 0x4c, 0x73, 0x21, 0x5f, 0xe5, 0xae, 0xeb, 0x50, 0xfe, 0x95, 0xfe, 0xbe, 0x2d, 0x03, 0x37,
+    0xce, 0x0d, 0xc4, 0xe0, 0x11, 0x78, 0xf9, 0x0d, 0x91, 0x20, 0xf4, 0xe3, 0x82, 0xda, 0xfe, 0x1e,
+    0xca, 0xf7, 0xb4, 0x86, 0x34, 0x89, 0x42, 0x97, 0xba, 0x7e, 0x00, 0x92, 0xdf, 0x79, 0x70, 0x0c,
+    0x54, 0x82, 0x31, 0x17, 0x8c, 0xaa, 0x80, 0x44, 0xf1, 0x77, 0x08, 0xca, 0x5b, 0xfc, 0x54, 0x84,
+    0x12, 0x49, 0xe8, 0x65, 0x1e, 0xfc, 0xd5, 0x78, 0xc8, 0xc1, 0xd1, 0x23, 0x4c, 0x96, 0xdb, 0x17,
+    0x24, 0xd7, 0xe2, 0xae, 0x2c, 0xef, 0xff, 0xf2, 0x2c, 0x6d, 0xcf, 0x6f, 0x56, 0x78, 0x2e, 0xb3,
+    0xa5, 0x51, 0xfd, 0x90, 0x8c, 0xa7, 0x7e, 0xe8, 0x61, 0xb2, 0x26, 0x1d, 0xe1, 0x02, 0x81, 0x81,
+    0x00, 0x88, 0xf6, 0x9a, 0xec, 0xab, 0xb6, 0x25, 0x2c, 0x12, 0x4e, 0x90, 0x8f, 0xea, 0xa2, 0x7e,
+    0x62, 0x41, 0xd7, 0xfd, 0x7c, 0x5d, 0xaa, 0x83, 0xfa, 0xc7, 0x48, 0x51, 0x54, 0xed, 0x72, 0x59,
+    0x95, 0xc0, 0x61, 0xdc, 0xfa, 0xc6, 0xb8, 0xd5, 0x5f, 0x9a, 0xd0, 0x7e, 0xcb, 0x3f, 0xc4, 0xfd,
+    0xb4, 0x4d, 0x46, 0x74, 0xc4, 0xf0, 0x45, 0xd4, 0x62, 0xdc, 0x27, 0x37, 0x4a, 0x8a, 0xcf, 0x27,
+    0x1a, 0x6f, 0x00, 0x50, 0x12, 0x99, 0x8d, 0xd7, 0xa8, 0xdf, 0xf3, 0xa4, 0x61, 0x18, 0x4f, 0xed,
+    0x1d, 0xac, 0x51, 0xd4, 0x44, 0x2f, 0x73, 0xea, 0xe7, 0xd7, 0xd2, 0x81, 0xe1, 0xe8, 0x4e, 0x0a,
+    0xeb, 0xbd, 0x40, 0x2b, 0x62, 0xb3, 0x43, 0x60, 0x72, 0x73, 0x31, 0xc0, 0x7a, 0x16, 0x15, 0x83,
+    0x71, 0x2f, 0x2e, 0xb4, 0x17, 0x43, 0x12, 0x30, 0x08, 0xef, 0x72, 0xdb, 0xc9, 0x50, 0x28, 0x5a,
+    0xda};
+constexpr const unsigned int rsa_key_2k_len = sizeof(rsa_key_2k);
\ No newline at end of file
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
new file mode 100644
index 0000000..1c678c3
--- /dev/null
+++ b/keystore2/src/utils.rs
@@ -0,0 +1,138 @@
+// Copyright 2020, 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.
+
+//! This module implements utility functions used by the Keystore 2.0 service
+//! implementation.
+
+use crate::permission;
+use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
+use crate::{error::Error, key_parameter::KeyParameterValue};
+use android_hardware_keymint::aidl::android::hardware::keymint::{
+    KeyCharacteristics::KeyCharacteristics, SecurityLevel::SecurityLevel,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Authorization::Authorization, KeyDescriptor::KeyDescriptor,
+};
+use anyhow::{anyhow, Context};
+use binder::{FromIBinder, SpIBinder, ThreadState};
+use std::sync::Mutex;
+
+/// This function uses its namesake in the permission module and in
+/// combination with with_calling_sid from the binder crate to check
+/// if the caller has the given keystore permission.
+pub fn check_keystore_permission(perm: KeystorePerm) -> anyhow::Result<()> {
+    ThreadState::with_calling_sid(|calling_sid| {
+        permission::check_keystore_permission(
+            &calling_sid.ok_or_else(Error::sys).context(
+                "In check_keystore_permission: Cannot check permission without calling_sid.",
+            )?,
+            perm,
+        )
+    })
+}
+
+/// This function uses its namesake in the permission module and in
+/// combination with with_calling_sid from the binder crate to check
+/// if the caller has the given grant permission.
+pub fn check_grant_permission(access_vec: KeyPermSet, key: &KeyDescriptor) -> anyhow::Result<()> {
+    ThreadState::with_calling_sid(|calling_sid| {
+        permission::check_grant_permission(
+            &calling_sid.ok_or_else(Error::sys).context(
+                "In check_grant_permission: Cannot check permission without calling_sid.",
+            )?,
+            access_vec,
+            key,
+        )
+    })
+}
+
+/// This function uses its namesake in the permission module and in
+/// combination with with_calling_sid from the binder crate to check
+/// if the caller has the given key permission.
+pub fn check_key_permission(
+    perm: KeyPerm,
+    key: &KeyDescriptor,
+    access_vector: &Option<KeyPermSet>,
+) -> anyhow::Result<()> {
+    ThreadState::with_calling_sid(|calling_sid| {
+        permission::check_key_permission(
+            &calling_sid
+                .ok_or_else(Error::sys)
+                .context("In check_key_permission: Cannot check permission without calling_sid.")?,
+            perm,
+            key,
+            access_vector,
+        )
+    })
+}
+
+/// Thread safe wrapper around SpIBinder. It is safe to have SpIBinder smart pointers to the
+/// same object in multiple threads, but cloning a SpIBinder is not thread safe.
+/// Keystore frequently hands out binder tokens to the security level interface. If this
+/// is to happen from a multi threaded thread pool, the SpIBinder needs to be protected by a
+/// Mutex.
+#[derive(Debug)]
+pub struct Asp(Mutex<SpIBinder>);
+
+impl Asp {
+    /// Creates a new instance owning a SpIBinder wrapped in a Mutex.
+    pub fn new(i: SpIBinder) -> Self {
+        Self(Mutex::new(i))
+    }
+
+    /// Clones the owned SpIBinder and attempts to convert it into the requested interface.
+    pub fn get_interface<T: FromIBinder + ?Sized>(&self) -> anyhow::Result<Box<T>> {
+        // We can use unwrap here because we never panic when locked, so the mutex
+        // can never be poisoned.
+        let lock = self.0.lock().unwrap();
+        (*lock)
+            .clone()
+            .into_interface()
+            .map_err(|e| anyhow!(format!("get_interface failed with error code {:?}", e)))
+    }
+}
+
+/// Converts a set of key characteristics as returned from KeyMint into the internal
+/// representation of the keystore service.
+/// The parameter `hw_security_level` indicates which security level shall be used for
+/// parameters found in the hardware enforced parameter list.
+pub fn key_characteristics_to_internal(
+    key_characteristics: KeyCharacteristics,
+    hw_security_level: SecurityLevel,
+) -> Vec<crate::key_parameter::KeyParameter> {
+    key_characteristics
+        .hardwareEnforced
+        .into_iter()
+        .map(|aidl_kp| {
+            crate::key_parameter::KeyParameter::new(
+                KeyParameterValue::convert_from_wire(aidl_kp),
+                hw_security_level,
+            )
+        })
+        .chain(key_characteristics.softwareEnforced.into_iter().map(|aidl_kp| {
+            crate::key_parameter::KeyParameter::new(
+                KeyParameterValue::convert_from_wire(aidl_kp),
+                SecurityLevel::SOFTWARE,
+            )
+        }))
+        .collect()
+}
+
+/// Converts a set of key characteristics from the internal representation into a set of
+/// Authorizations as they are used to convey key characteristics to the clients of keystore.
+pub fn key_parameters_to_authorizations(
+    parameters: Vec<crate::key_parameter::KeyParameter>,
+) -> Vec<Authorization> {
+    parameters.into_iter().map(|p| p.into_authorization()).collect()
+}
diff --git a/provisioner/Android.bp b/provisioner/Android.bp
new file mode 100644
index 0000000..c1c8d15
--- /dev/null
+++ b/provisioner/Android.bp
@@ -0,0 +1,44 @@
+//
+// Copyright (C) 2020 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.
+//
+
+aidl_interface {
+    name: "android.security.provisioner",
+    unstable: true,
+    local_include_dir: "binder",
+    srcs: [
+        "binder/android/security/provisioner/*.aidl",
+    ],
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        cpp: {
+            enabled: false,
+        },
+        ndk: {
+            enabled: false,
+        },
+    },
+}
+
+java_binary {
+    name: "provisioner_cli",
+    wrapper: "provisioner_cli",
+    srcs: ["src/com/android/commands/provisioner/**/*.java"],
+    static_libs: [
+        "android.security.provisioner-java",
+    ],
+}
diff --git a/provisioner/binder/android/security/provisioner/IProvisionerService.aidl b/provisioner/binder/android/security/provisioner/IProvisionerService.aidl
new file mode 100644
index 0000000..f81e9ab
--- /dev/null
+++ b/provisioner/binder/android/security/provisioner/IProvisionerService.aidl
@@ -0,0 +1,27 @@
+/**
+ * Copyright (c) 2020, 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.
+ */
+
+package android.security.provisioner;
+
+/**
+ * @hide
+ */
+interface IProvisionerService {
+    byte[] getCertificateRequest(in boolean testMode,
+                                 in int keyCount,
+                                 in byte[] endpointEncryptionKey,
+                                 in byte[] challenge) = 0;
+}
diff --git a/provisioner/provisioner_cli b/provisioner/provisioner_cli
new file mode 100755
index 0000000..7b53d6e
--- /dev/null
+++ b/provisioner/provisioner_cli
@@ -0,0 +1,21 @@
+#!/system/bin/sh
+#
+# Copyright (C) 2020 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.
+#
+# Script to start "provisioner_cli" on the device.
+#
+base=/system
+export CLASSPATH=$base/framework/provisioner_cli.jar
+exec app_process $base/bin com.android.commands.provisioner.Cli "$@"
diff --git a/provisioner/src/com/android/commands/provisioner/Cli.java b/provisioner/src/com/android/commands/provisioner/Cli.java
new file mode 100644
index 0000000..62afdac
--- /dev/null
+++ b/provisioner/src/com/android/commands/provisioner/Cli.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2020 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.
+ */
+
+package com.android.commands.provisioner;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.security.provisioner.IProvisionerService;
+
+import com.android.internal.os.BaseCommand;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.IllegalArgumentException;
+
+/**
+ * Contains the implementation of the remote provisioning command-line interface.
+ */
+public class Cli extends BaseCommand {
+    /**
+     * Creates an instance of the command-line interface and runs it. This is the entry point of
+     * the tool.
+     */
+    public static void main(String[] args) {
+        new Cli().run(args);
+    }
+
+    /**
+     * Runs the command requested by the invoker. It parses the very first required argument, which
+     * is the command, and calls the appropriate handler.
+     */
+    @Override
+    public void onRun() throws Exception {
+        String cmd = nextArgRequired();
+        switch (cmd) {
+        case "get-req":
+            getRequest();
+            break;
+
+        case "help":
+            onShowUsage(System.out);
+            break;
+
+        default:
+            throw new IllegalArgumentException("unknown command: " + cmd);
+        }
+    }
+
+    /**
+     * Retrieves a 'certificate request' from the provisioning service. The COSE-encoded
+     * 'certificate chain' describing the endpoint encryption key (EEK) to use for encryption is
+     * read from the standard input. The retrieved request is written to the standard output.
+     */
+    private void getRequest() throws Exception {
+        // Process options.
+        boolean test = false;
+        byte[] challenge = null;
+        int count = 0;
+        String arg;
+        while ((arg = nextArg()) != null) {
+            switch (arg) {
+            case "--test":
+                test = true;
+                break;
+
+            case "--challenge":
+                // TODO: We may need a different encoding of the challenge.
+                challenge = nextArgRequired().getBytes();
+                break;
+
+            case "--count":
+                count = Integer.parseInt(nextArgRequired());
+                if (count < 0) {
+                    throw new IllegalArgumentException(
+                            "--count must be followed by non-negative number");
+                }
+                break;
+
+            default:
+                throw new IllegalArgumentException("unknown argument: " + arg);
+            }
+        }
+
+        // Send the request over to the provisioning service and write the result to stdout.
+        byte[] res = getService().getCertificateRequest(test, count, readAll(System.in), challenge);
+        if (res != null) {
+            System.out.write(res);
+        }
+    }
+
+    /**
+     * Retrieves an implementation of the IProvisionerService interface. It allows the caller to
+     * call into the service via binder.
+     */
+    private static IProvisionerService getService() throws RemoteException {
+        IBinder binder = ServiceManager.getService("remote-provisioner");
+        if (binder == null) {
+            throw new RemoteException("Provisioning service is inaccessible");
+        }
+        return IProvisionerService.Stub.asInterface(binder);
+    }
+
+    /** Reads all data from the provided input stream and returns it as a byte array. */
+    private static byte[] readAll(InputStream in) throws IOException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        byte[] buf = new byte[1024];
+        int read;
+        while ((read = in.read(buf)) != -1) {
+            out.write(buf, 0, read);
+        }
+        return out.toByteArray();
+    }
+
+    /**
+     * Writes the usage information to the given stream. This is displayed to users of the tool when
+     * they ask for help or when they pass incorrect arguments to the tool.
+     */
+    @Override
+    public void onShowUsage(PrintStream out) {
+        out.println(
+                "Usage: provisioner_cli <command> [options]\n" +
+                "Commands: help\n" +
+                "          get-req [--count <n>] [--test] [--challenge <v>]");
+    }
+}