Clone the KeyMint device to customize it

In order to make modifications, pull in our own copy of the KeyMint
device from the reference implementation.

Bug: 190578423
Test: atest MicrodroidHostTestCases
Change-Id: I2671a0faf0f354a681ab2c988ecedb94b7adeb4b
diff --git a/microdroid/keymint/Android.bp b/microdroid/keymint/Android.bp
index 5867900..5a87145 100644
--- a/microdroid/keymint/Android.bp
+++ b/microdroid/keymint/Android.bp
@@ -16,6 +16,7 @@
     ],
     shared_libs: [
         "android.hardware.security.keymint-V1-ndk_platform",
+        "lib_android_keymaster_keymint_utils",
         "libbase",
         "libbinder_ndk",
         "libcppbor_external",
@@ -26,7 +27,11 @@
         "libpuresoftkeymasterdevice",
         "libutils",
     ],
+    local_include_dirs: [
+        "include",
+    ],
     srcs: [
+        "MicrodroidKeyMintDevice.cpp",
         "service.cpp",
     ],
 }
diff --git a/microdroid/keymint/MicrodroidKeyMintDevice.cpp b/microdroid/keymint/MicrodroidKeyMintDevice.cpp
new file mode 100644
index 0000000..62d6942
--- /dev/null
+++ b/microdroid/keymint/MicrodroidKeyMintDevice.cpp
@@ -0,0 +1,472 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.security.keymint-impl"
+#include "MicrodroidKeyMintDevice.h"
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+#include <android-base/logging.h>
+#include <keymaster/android_keymaster.h>
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/keymaster_configuration.h>
+
+#include "AndroidKeyMintOperation.h"
+#include "KeyMintUtils.h"
+
+namespace aidl::android::hardware::security::keymint {
+
+using namespace keymaster; // NOLINT(google-build-using-namespace)
+
+using km_utils::authToken2AidlVec;
+using km_utils::kmBlob2vector;
+using km_utils::kmError2ScopedAStatus;
+using km_utils::kmParam2Aidl;
+using km_utils::KmParamSet;
+using km_utils::kmParamSet2Aidl;
+using km_utils::legacy_enum_conversion;
+using secureclock::TimeStampToken;
+
+namespace {
+
+vector<KeyCharacteristics> convertKeyCharacteristics(SecurityLevel keyMintSecurityLevel,
+                                                     const AuthorizationSet& requestParams,
+                                                     const AuthorizationSet& sw_enforced,
+                                                     const AuthorizationSet& hw_enforced,
+                                                     bool include_keystore_enforced = true) {
+    KeyCharacteristics keyMintEnforced{keyMintSecurityLevel, {}};
+
+    if (keyMintSecurityLevel != SecurityLevel::SOFTWARE) {
+        // We're pretending to be TRUSTED_ENVIRONMENT or STRONGBOX.
+        keyMintEnforced.authorizations = kmParamSet2Aidl(hw_enforced);
+        if (include_keystore_enforced) {
+            // Put all the software authorizations in the keystore list.
+            KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE,
+                                                kmParamSet2Aidl(sw_enforced)};
+            return {std::move(keyMintEnforced), std::move(keystoreEnforced)};
+        } else {
+            return {std::move(keyMintEnforced)};
+        }
+    }
+
+    KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE, {}};
+    CHECK(hw_enforced.empty()) << "Hardware-enforced list is non-empty for pure SW KeyMint";
+
+    // This is a pure software implementation, so all tags are in sw_enforced.
+    // We need to walk through the SW-enforced list and figure out which tags to
+    // return in the software list and which in the keystore list.
+
+    for (auto& entry : sw_enforced) {
+        switch (entry.tag) {
+            /* Invalid and unused */
+            case KM_TAG_ECIES_SINGLE_HASH_MODE:
+            case KM_TAG_INVALID:
+            case KM_TAG_KDF:
+            case KM_TAG_ROLLBACK_RESISTANCE:
+                CHECK(false) << "We shouldn't see tag " << entry.tag;
+                break;
+
+            /* Unimplemented */
+            case KM_TAG_ALLOW_WHILE_ON_BODY:
+            case KM_TAG_BOOTLOADER_ONLY:
+            case KM_TAG_EARLY_BOOT_ONLY:
+            case KM_TAG_ROLLBACK_RESISTANT:
+            case KM_TAG_STORAGE_KEY:
+            case KM_TAG_TRUSTED_CONFIRMATION_REQUIRED:
+            case KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED:
+                break;
+
+            /* Keystore-enforced if not locally generated. */
+            case KM_TAG_CREATION_DATETIME:
+                // A KeyMaster implementation is required to add this tag to generated/imported
+                // keys. A KeyMint implementation is not required to create this tag, only to echo
+                // it back if it was included in the key generation/import request.
+                if (requestParams.Contains(KM_TAG_CREATION_DATETIME)) {
+                    keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
+                }
+                break;
+
+            /* Disallowed in KeyCharacteristics */
+            case KM_TAG_APPLICATION_DATA:
+            case KM_TAG_ATTESTATION_APPLICATION_ID:
+                break;
+
+            /* Not key characteristics */
+            case KM_TAG_ASSOCIATED_DATA:
+            case KM_TAG_ATTESTATION_CHALLENGE:
+            case KM_TAG_ATTESTATION_ID_BRAND:
+            case KM_TAG_ATTESTATION_ID_DEVICE:
+            case KM_TAG_ATTESTATION_ID_IMEI:
+            case KM_TAG_ATTESTATION_ID_MANUFACTURER:
+            case KM_TAG_ATTESTATION_ID_MEID:
+            case KM_TAG_ATTESTATION_ID_MODEL:
+            case KM_TAG_ATTESTATION_ID_PRODUCT:
+            case KM_TAG_ATTESTATION_ID_SERIAL:
+            case KM_TAG_AUTH_TOKEN:
+            case KM_TAG_CERTIFICATE_SERIAL:
+            case KM_TAG_CERTIFICATE_SUBJECT:
+            case KM_TAG_CERTIFICATE_NOT_AFTER:
+            case KM_TAG_CERTIFICATE_NOT_BEFORE:
+            case KM_TAG_CONFIRMATION_TOKEN:
+            case KM_TAG_DEVICE_UNIQUE_ATTESTATION:
+            case KM_TAG_IDENTITY_CREDENTIAL_KEY:
+            case KM_TAG_MAC_LENGTH:
+            case KM_TAG_NONCE:
+            case KM_TAG_RESET_SINCE_ID_ROTATION:
+            case KM_TAG_ROOT_OF_TRUST:
+            case KM_TAG_UNIQUE_ID:
+                break;
+
+            /* KeyMint-enforced */
+            case KM_TAG_ALGORITHM:
+            case KM_TAG_APPLICATION_ID:
+            case KM_TAG_AUTH_TIMEOUT:
+            case KM_TAG_BLOB_USAGE_REQUIREMENTS:
+            case KM_TAG_BLOCK_MODE:
+            case KM_TAG_BOOT_PATCHLEVEL:
+            case KM_TAG_CALLER_NONCE:
+            case KM_TAG_DIGEST:
+            case KM_TAG_EC_CURVE:
+            case KM_TAG_EXPORTABLE:
+            case KM_TAG_INCLUDE_UNIQUE_ID:
+            case KM_TAG_KEY_SIZE:
+            case KM_TAG_MAX_USES_PER_BOOT:
+            case KM_TAG_MIN_MAC_LENGTH:
+            case KM_TAG_MIN_SECONDS_BETWEEN_OPS:
+            case KM_TAG_NO_AUTH_REQUIRED:
+            case KM_TAG_ORIGIN:
+            case KM_TAG_OS_PATCHLEVEL:
+            case KM_TAG_OS_VERSION:
+            case KM_TAG_PADDING:
+            case KM_TAG_PURPOSE:
+            case KM_TAG_RSA_OAEP_MGF_DIGEST:
+            case KM_TAG_RSA_PUBLIC_EXPONENT:
+            case KM_TAG_UNLOCKED_DEVICE_REQUIRED:
+            case KM_TAG_USER_AUTH_TYPE:
+            case KM_TAG_USER_SECURE_ID:
+            case KM_TAG_VENDOR_PATCHLEVEL:
+                keyMintEnforced.authorizations.push_back(kmParam2Aidl(entry));
+                break;
+
+            /* Keystore-enforced */
+            case KM_TAG_ACTIVE_DATETIME:
+            case KM_TAG_ALL_APPLICATIONS:
+            case KM_TAG_ALL_USERS:
+            case KM_TAG_MAX_BOOT_LEVEL:
+            case KM_TAG_ORIGINATION_EXPIRE_DATETIME:
+            case KM_TAG_USAGE_EXPIRE_DATETIME:
+            case KM_TAG_USER_ID:
+            case KM_TAG_USAGE_COUNT_LIMIT:
+                keystoreEnforced.authorizations.push_back(kmParam2Aidl(entry));
+                break;
+        }
+    }
+
+    vector<KeyCharacteristics> retval;
+    retval.reserve(2);
+    if (!keyMintEnforced.authorizations.empty()) retval.push_back(std::move(keyMintEnforced));
+    if (include_keystore_enforced && !keystoreEnforced.authorizations.empty()) {
+        retval.push_back(std::move(keystoreEnforced));
+    }
+
+    return retval;
+}
+
+Certificate convertCertificate(const keymaster_blob_t& cert) {
+    return {std::vector<uint8_t>(cert.data, cert.data + cert.data_length)};
+}
+
+vector<Certificate> convertCertificateChain(const CertificateChain& chain) {
+    vector<Certificate> retval;
+    retval.reserve(chain.entry_count);
+    std::transform(chain.begin(), chain.end(), std::back_inserter(retval), convertCertificate);
+    return retval;
+}
+
+void addClientAndAppData(const std::vector<uint8_t>& appId, const std::vector<uint8_t>& appData,
+                         ::keymaster::AuthorizationSet* params) {
+    params->Clear();
+    if (appId.size()) {
+        params->push_back(::keymaster::TAG_APPLICATION_ID, appId.data(), appId.size());
+    }
+    if (appData.size()) {
+        params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
+    }
+}
+
+} // namespace
+
+constexpr size_t kOperationTableSize = 16;
+
+MicrodroidKeyMintDevice::MicrodroidKeyMintDevice(SecurityLevel securityLevel)
+      : impl_(new ::keymaster::AndroidKeymaster(
+                [&]() -> auto {
+                    auto context =
+                            new PureSoftKeymasterContext(KmVersion::KEYMINT_1,
+                                                         static_cast<keymaster_security_level_t>(
+                                                                 securityLevel));
+                    context->SetSystemVersion(::keymaster::GetOsVersion(),
+                                              ::keymaster::GetOsPatchlevel());
+                    return context;
+                }(),
+                kOperationTableSize)),
+        securityLevel_(securityLevel) {}
+
+MicrodroidKeyMintDevice::~MicrodroidKeyMintDevice() {}
+
+ScopedAStatus MicrodroidKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
+    info->versionNumber = 1;
+    info->securityLevel = securityLevel_;
+    info->keyMintName = "FakeKeyMintDevice";
+    info->keyMintAuthorName = "Google";
+    info->timestampTokenRequired = false;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::addRngEntropy(const vector<uint8_t>& data) {
+    if (data.size() == 0) {
+        return ScopedAStatus::ok();
+    }
+
+    AddEntropyRequest request(impl_->message_version());
+    request.random_data.Reinitialize(data.data(), data.size());
+
+    AddEntropyResponse response(impl_->message_version());
+    impl_->AddRngEntropy(request, &response);
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::generateKey(const vector<KeyParameter>& keyParams,
+                                                   const optional<AttestationKey>& attestationKey,
+                                                   KeyCreationResult* creationResult) {
+    GenerateKeyRequest request(impl_->message_version());
+    request.key_description.Reinitialize(KmParamSet(keyParams));
+    if (attestationKey) {
+        request.attestation_signing_key_blob =
+                KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+        request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
+        request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
+                                               attestationKey->issuerSubjectName.size());
+    }
+
+    GenerateKeyResponse response(impl_->message_version());
+    impl_->GenerateKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        // Note a key difference between this current aidl and previous hal, is
+        // that hal returns void where as aidl returns the error status.  If
+        // aidl returns error, then aidl will not return any change you may make
+        // to the out parameters.  This is quite different from hal where all
+        // output variable can be modified due to hal returning void.
+        //
+        // So the caller need to be aware not to expect aidl functions to clear
+        // the output variables for you in case of error.  If you left some
+        // wrong data set in the out parameters, they will stay there.
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    creationResult->keyBlob = kmBlob2vector(response.key_blob);
+    creationResult->keyCharacteristics =
+            convertKeyCharacteristics(securityLevel_, request.key_description, response.unenforced,
+                                      response.enforced);
+    creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::importKey(const vector<KeyParameter>& keyParams,
+                                                 KeyFormat keyFormat,
+                                                 const vector<uint8_t>& keyData,
+                                                 const optional<AttestationKey>& attestationKey,
+                                                 KeyCreationResult* creationResult) {
+    ImportKeyRequest request(impl_->message_version());
+    request.key_description.Reinitialize(KmParamSet(keyParams));
+    request.key_format = legacy_enum_conversion(keyFormat);
+    request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
+    if (attestationKey) {
+        request.attestation_signing_key_blob =
+                KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
+        request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
+        request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
+                                               attestationKey->issuerSubjectName.size());
+    }
+
+    ImportKeyResponse response(impl_->message_version());
+    impl_->ImportKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    creationResult->keyBlob = kmBlob2vector(response.key_blob);
+    creationResult->keyCharacteristics =
+            convertKeyCharacteristics(securityLevel_, request.key_description, response.unenforced,
+                                      response.enforced);
+    creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::importWrappedKey(
+        const vector<uint8_t>& wrappedKeyData,        //
+        const vector<uint8_t>& wrappingKeyBlob,       //
+        const vector<uint8_t>& maskingKey,            //
+        const vector<KeyParameter>& unwrappingParams, //
+        int64_t passwordSid, int64_t biometricSid,    //
+        KeyCreationResult* creationResult) {
+    ImportWrappedKeyRequest request(impl_->message_version());
+    request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
+    request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
+    request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
+    request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
+    request.password_sid = static_cast<uint64_t>(passwordSid);
+    request.biometric_sid = static_cast<uint64_t>(biometricSid);
+
+    ImportWrappedKeyResponse response(impl_->message_version());
+    impl_->ImportWrappedKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    creationResult->keyBlob = kmBlob2vector(response.key_blob);
+    creationResult->keyCharacteristics =
+            convertKeyCharacteristics(securityLevel_, request.additional_params,
+                                      response.unenforced, response.enforced);
+    creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
+                                                  const vector<KeyParameter>& upgradeParams,
+                                                  vector<uint8_t>* keyBlob) {
+    UpgradeKeyRequest request(impl_->message_version());
+    request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
+    request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
+
+    UpgradeKeyResponse response(impl_->message_version());
+    impl_->UpgradeKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    *keyBlob = kmBlob2vector(response.upgraded_key);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
+    DeleteKeyRequest request(impl_->message_version());
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+
+    DeleteKeyResponse response(impl_->message_version());
+    impl_->DeleteKey(request, &response);
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::deleteAllKeys() {
+    // There's nothing to be done to delete software key blobs.
+    DeleteAllKeysRequest request(impl_->message_version());
+    DeleteAllKeysResponse response(impl_->message_version());
+    impl_->DeleteAllKeys(request, &response);
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::destroyAttestationIds() {
+    return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
+                                             const vector<KeyParameter>& params,
+                                             const optional<HardwareAuthToken>& authToken,
+                                             BeginResult* result) {
+    BeginOperationRequest request(impl_->message_version());
+    request.purpose = legacy_enum_conversion(purpose);
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+    request.additional_params.Reinitialize(KmParamSet(params));
+
+    vector<uint8_t> vector_token = authToken2AidlVec(authToken);
+    request.additional_params.push_back(TAG_AUTH_TOKEN,
+                                        reinterpret_cast<uint8_t*>(vector_token.data()),
+                                        vector_token.size());
+
+    BeginOperationResponse response(impl_->message_version());
+    impl_->BeginOperation(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    result->params = kmParamSet2Aidl(response.output_params);
+    result->challenge = response.op_handle;
+    result->operation =
+            ndk::SharedRefBase::make<AndroidKeyMintOperation>(impl_, response.op_handle);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::deviceLocked(
+        bool passwordOnly, const std::optional<secureclock::TimeStampToken>& timestampToken) {
+    DeviceLockedRequest request(impl_->message_version());
+    request.passwordOnly = passwordOnly;
+    if (timestampToken.has_value()) {
+        request.token.challenge = timestampToken->challenge;
+        request.token.mac = {timestampToken->mac.data(), timestampToken->mac.size()};
+        request.token.timestamp = timestampToken->timestamp.milliSeconds;
+    }
+    DeviceLockedResponse response = impl_->DeviceLocked(request);
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::earlyBootEnded() {
+    EarlyBootEndedResponse response = impl_->EarlyBootEnded();
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::convertStorageKeyToEphemeral(
+        const std::vector<uint8_t>& /* storageKeyBlob */,
+        std::vector<uint8_t>* /* ephemeralKeyBlob */) {
+    return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus MicrodroidKeyMintDevice::getKeyCharacteristics(
+        const std::vector<uint8_t>& keyBlob, const std::vector<uint8_t>& appId,
+        const std::vector<uint8_t>& appData, std::vector<KeyCharacteristics>* keyCharacteristics) {
+    GetKeyCharacteristicsRequest request(impl_->message_version());
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+    addClientAndAppData(appId, appData, &request.additional_params);
+
+    GetKeyCharacteristicsResponse response(impl_->message_version());
+    impl_->GetKeyCharacteristics(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    AuthorizationSet emptySet;
+    *keyCharacteristics = convertKeyCharacteristics(securityLevel_, emptySet, response.unenforced,
+                                                    response.enforced,
+                                                    /* include_keystore_enforced = */ false);
+
+    return ScopedAStatus::ok();
+}
+
+IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel) {
+    return ::new MicrodroidKeyMintDevice(securityLevel);
+}
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/microdroid/keymint/include/MicrodroidKeyMintDevice.h b/microdroid/keymint/include/MicrodroidKeyMintDevice.h
new file mode 100644
index 0000000..34d09bf
--- /dev/null
+++ b/microdroid/keymint/include/MicrodroidKeyMintDevice.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2021, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
+#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl::android::hardware::security::keymint {
+using ::ndk::ScopedAStatus;
+using std::optional;
+using std::shared_ptr;
+using std::vector;
+
+using secureclock::TimeStampToken;
+
+class MicrodroidKeyMintDevice : public BnKeyMintDevice {
+public:
+    explicit MicrodroidKeyMintDevice(SecurityLevel securityLevel);
+    virtual ~MicrodroidKeyMintDevice();
+
+    ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* info) override;
+
+    ScopedAStatus addRngEntropy(const vector<uint8_t>& data) override;
+
+    ScopedAStatus generateKey(const vector<KeyParameter>& keyParams,
+                              const optional<AttestationKey>& attestationKey,
+                              KeyCreationResult* creationResult) override;
+
+    ScopedAStatus importKey(const vector<KeyParameter>& keyParams, KeyFormat keyFormat,
+                            const vector<uint8_t>& keyData,
+                            const optional<AttestationKey>& attestationKey,
+                            KeyCreationResult* creationResult) override;
+
+    ScopedAStatus importWrappedKey(const vector<uint8_t>& wrappedKeyData,
+                                   const vector<uint8_t>& wrappingKeyBlob,
+                                   const vector<uint8_t>& maskingKey,
+                                   const vector<KeyParameter>& unwrappingParams,
+                                   int64_t passwordSid, int64_t biometricSid,
+                                   KeyCreationResult* creationResult) override;
+
+    ScopedAStatus upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
+                             const vector<KeyParameter>& upgradeParams,
+                             vector<uint8_t>* keyBlob) override;
+
+    ScopedAStatus deleteKey(const vector<uint8_t>& keyBlob) override;
+    ScopedAStatus deleteAllKeys() override;
+    ScopedAStatus destroyAttestationIds() override;
+
+    ScopedAStatus begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
+                        const vector<KeyParameter>& params,
+                        const optional<HardwareAuthToken>& authToken, BeginResult* result) override;
+
+    ScopedAStatus deviceLocked(bool passwordOnly,
+                               const optional<TimeStampToken>& timestampToken) override;
+    ScopedAStatus earlyBootEnded() override;
+
+    ScopedAStatus convertStorageKeyToEphemeral(const std::vector<uint8_t>& storageKeyBlob,
+                                               std::vector<uint8_t>* ephemeralKeyBlob) override;
+
+    ScopedAStatus getKeyCharacteristics(
+            const std::vector<uint8_t>& keyBlob, const std::vector<uint8_t>& appId,
+            const std::vector<uint8_t>& appData,
+            std::vector<KeyCharacteristics>* keyCharacteristics) override;
+
+    shared_ptr<::keymaster::AndroidKeymaster>& getKeymasterImpl() { return impl_; }
+
+protected:
+    std::shared_ptr<::keymaster::AndroidKeymaster> impl_;
+    SecurityLevel securityLevel_;
+};
+
+IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel);
+
+} // namespace aidl::android::hardware::security::keymint
diff --git a/microdroid/keymint/service.cpp b/microdroid/keymint/service.cpp
index d2b75a1..8467b33 100644
--- a/microdroid/keymint/service.cpp
+++ b/microdroid/keymint/service.cpp
@@ -22,7 +22,9 @@
 #include <android/binder_process.h>
 #include <keymaster/soft_keymaster_logger.h>
 
-using aidl::android::hardware::security::keymint::AndroidKeyMintDevice;
+#include "MicrodroidKeyMintDevice.h"
+
+using aidl::android::hardware::security::keymint::MicrodroidKeyMintDevice;
 using aidl::android::hardware::security::keymint::SecurityLevel;
 
 template <typename T, class... Args>
@@ -41,8 +43,8 @@
     // the pool size to 1.
     ABinderProcess_setThreadPoolMaxThreadCount(0);
     // Add Keymint Service
-    std::shared_ptr<AndroidKeyMintDevice> keyMint =
-            addService<AndroidKeyMintDevice>(SecurityLevel::SOFTWARE);
+    std::shared_ptr<MicrodroidKeyMintDevice> keyMint =
+            addService<MicrodroidKeyMintDevice>(SecurityLevel::SOFTWARE);
 
     // VMs cannot implement the Secure Clock Service
     // addService<AndroidSecureClock>(keyMint);