Merge "KeyMint 1 system side coding." am: 2ef464e90c

Original change: https://android-review.googlesource.com/c/platform/system/keymaster/+/1317980

Change-Id: Iaeb2c696d4412d89a09067286af2df4650c10a00
diff --git a/Android.bp b/Android.bp
index 0639237..219494c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -329,6 +329,39 @@
     export_include_dirs: ["ng/include"],
 }
 
+
+cc_library_shared {
+    name: "libkeymint1",
+    vendor_available: true,
+    srcs: [
+        "legacy_support/keymaster_passthrough_key.cpp",
+        "legacy_support/keymaster_passthrough_engine.cpp",
+        "legacy_support/keymaster_passthrough_operation.cpp",
+        "ng/KeyMintAidlUtils.cpp",
+        "ng/AndroidKeyMint1Device.cpp",
+        "ng/AndroidKeyMint1Operation.cpp",
+        "android_keymaster/keymaster_configuration.cpp",
+    ],
+    defaults: ["keymaster_defaults"],
+    shared_libs: [
+        "libkeymaster_messages",
+        "android.hardware.keymint-ndk_platform",
+        "libbase",
+        "libcrypto",
+        "libcutils",
+        "libbinder_ndk",
+        "libcppbor",
+	"libhidlbase",
+        "libkeymaster_portable",
+        "libkeymaster_messages",
+        "libpuresoftkeymasterdevice",
+        "liblog",
+        "libutils",
+    ],
+    export_include_dirs: ["include", "ng/include"],
+}
+
+
 // libkeymasterfiles is an empty library that exports all of the files in keymaster as includes.
 cc_library_static {
     name: "libkeymasterfiles",
diff --git a/android_keymaster/keymaster_configuration.cpp b/android_keymaster/keymaster_configuration.cpp
index 0bcf6f9..5b1abbf 100644
--- a/android_keymaster/keymaster_configuration.cpp
+++ b/android_keymaster/keymaster_configuration.cpp
@@ -91,7 +91,8 @@
         regexec(&regex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
     regfree(&regex);
     if (not_match) {
-        ALOGI("Platform version string does not match expected format.  Using version 0.");
+        ALOGI("Platform version string \"%s\" does not match expected format.  Using version 0.",
+              version_str);
         return 0;
     }
 
diff --git a/ng/AndroidKeyMint1Device.cpp b/ng/AndroidKeyMint1Device.cpp
new file mode 100644
index 0000000..e77c874
--- /dev/null
+++ b/ng/AndroidKeyMint1Device.cpp
@@ -0,0 +1,276 @@
+/*
+ **
+ ** 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.
+ */
+
+#define LOG_TAG "android.hardware.keymint@1.0-impl"
+#include <log/log.h>
+
+#include "include/AndroidKeyMint1Device.h"
+
+#include "KeyMintAidlUtils.h"
+#include "include/AndroidKeyMint1Operation.h"
+
+#include <aidl/android/hardware/keymint/ErrorCode.h>
+
+#include <keymaster/android_keymaster.h>
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/keymaster_configuration.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace keymint {
+namespace V1_0 {
+
+using ::aidl::android::hardware::keymint::ErrorCode;
+using ::aidl::android::hardware::keymint::HardwareAuthToken;
+using ::aidl::android::hardware::keymint::VerificationToken;
+
+using namespace ::keymaster;
+
+constexpr size_t kOperationTableSize = 16;
+
+AndroidKeyMint1Device::AndroidKeyMint1Device(SecurityLevel securityLevel)
+    : impl_(new ::keymaster::AndroidKeymaster(
+          [&]() -> auto {
+              auto context = new PureSoftKeymasterContext(
+                  static_cast<keymaster_security_level_t>(securityLevel));
+              context->SetSystemVersion(::keymaster::GetOsVersion(),
+                                        ::keymaster::GetOsPatchlevel());
+              return context;
+          }(),
+          kOperationTableSize)),
+      securityLevel_(securityLevel) {}
+
+AndroidKeyMint1Device::~AndroidKeyMint1Device() {}
+
+ScopedAStatus AndroidKeyMint1Device::getHardwareInfo(KeyMintHardwareInfo* info) {
+    info->versionNumber = 1;
+    info->securityLevel = securityLevel_;
+    info->keyMintName = "FakeKeyMintDevice";
+    info->keyMintAuthorName = "Google";
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMint1Device::verifyAuthorization(int64_t challenge,                   //
+                                                         const HardwareAuthToken& authToken,  //
+                                                         VerificationToken* verificationToken) {
+
+    VerifyAuthorizationRequest request;
+    request.challenge = static_cast<uint64_t>(challenge);
+    request.auth_token.challenge = authToken.challenge;
+    request.auth_token.user_id = authToken.userId;
+    request.auth_token.authenticator_id = authToken.authenticatorId;
+    request.auth_token.authenticator_type = legacy_enum_conversion(authToken.authenticatorType);
+
+    // TODO(seleneh) b/162481130 remove the casting once uint is supported in aidl
+    request.auth_token.timestamp = static_cast<uint64_t>(authToken.timestamp.milliSeconds);
+    KeymasterBlob mac(authToken.mac.data(), authToken.mac.size());
+    request.auth_token.mac = KeymasterBlob(authToken.mac.data(), authToken.mac.size());
+
+    auto response = impl_->VerifyAuthorization(request);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    verificationToken->challenge = response.token.challenge;
+    verificationToken->timestamp.milliSeconds = static_cast<int64_t>(response.token.timestamp);
+    verificationToken->securityLevel = legacy_enum_conversion(response.token.security_level);
+    verificationToken->mac = kmBlob2vector(response.token.mac);
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMint1Device::addRngEntropy(const vector<uint8_t>& data) {
+    if (data.size() == 0) {
+        return ScopedAStatus::ok();
+    }
+
+    AddEntropyRequest request;
+    request.random_data.Reinitialize(data.data(), data.size());
+
+    AddEntropyResponse response;
+    impl_->AddRngEntropy(request, &response);
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMint1Device::generateKey(const vector<KeyParameter>& keyParams,
+                                                 ByteArray* generatedKeyBlob,
+                                                 KeyCharacteristics* generatedKeyCharacteristics,
+                                                 vector<Certificate>* /* certChain */) {
+
+    GenerateKeyRequest request;
+    request.key_description.Reinitialize(KmParamSet(keyParams));
+
+    GenerateKeyResponse response;
+    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);
+    }
+
+    generatedKeyBlob->data = kmBlob2vector(response.key_blob);
+    generatedKeyCharacteristics->hardwareEnforced = kmParamSet2Aidl(response.enforced);
+    generatedKeyCharacteristics->softwareEnforced = kmParamSet2Aidl(response.unenforced);
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMint1Device::importKey(const vector<KeyParameter>& keyParams,
+                                               KeyFormat keyFormat, const vector<uint8_t>& keyData,
+                                               ByteArray* importedKeyBlob,
+                                               KeyCharacteristics* importedKeyCharacteristics,
+                                               vector<Certificate>* /* certChain */) {
+
+    ImportKeyRequest request;
+    request.key_description.Reinitialize(KmParamSet(keyParams));
+    request.key_format = legacy_enum_conversion(keyFormat);
+    request.SetKeyMaterial(keyData.data(), keyData.size());
+
+    ImportKeyResponse response;
+    impl_->ImportKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    importedKeyBlob->data = kmBlob2vector(response.key_blob);
+    importedKeyCharacteristics->hardwareEnforced = kmParamSet2Aidl(response.enforced);
+    importedKeyCharacteristics->softwareEnforced = kmParamSet2Aidl(response.unenforced);
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMint1Device::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, ByteArray* importedKeyBlob,
+    KeyCharacteristics* importedKeyCharacteristics) {
+
+    ImportWrappedKeyRequest request;
+    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_->ImportWrappedKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    importedKeyBlob->data = kmBlob2vector(response.key_blob);
+    importedKeyCharacteristics->hardwareEnforced = kmParamSet2Aidl(response.enforced);
+    importedKeyCharacteristics->softwareEnforced = kmParamSet2Aidl(response.unenforced);
+
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMint1Device::upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
+                                                const vector<KeyParameter>& upgradeParams,
+                                                vector<uint8_t>* keyBlob) {
+
+    UpgradeKeyRequest request;
+    request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
+    request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
+
+    UpgradeKeyResponse response;
+    impl_->UpgradeKey(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return kmError2ScopedAStatus(response.error);
+    }
+
+    *keyBlob = kmBlob2vector(response.upgraded_key);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus AndroidKeyMint1Device::deleteKey(const vector<uint8_t>& keyBlob) {
+    DeleteKeyRequest request;
+    request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
+
+    DeleteKeyResponse response;
+    impl_->DeleteKey(request, &response);
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMint1Device::deleteAllKeys() {
+    // There's nothing to be done to delete software key blobs.
+    DeleteAllKeysRequest request;
+    DeleteAllKeysResponse response;
+    impl_->DeleteAllKeys(request, &response);
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMint1Device::destroyAttestationIds() {
+    return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
+}
+
+ScopedAStatus AndroidKeyMint1Device::begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
+                                           const vector<KeyParameter>& params,
+                                           const HardwareAuthToken& authToken,
+                                           BeginResult* result) {
+
+    BeginOperationRequest request;
+    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_->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<AndroidKeyMint1Operation>(impl_, response.op_handle);
+    return ScopedAStatus::ok();
+}
+
+IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel) {
+
+    return ::new AndroidKeyMint1Device(securityLevel);
+}
+
+}  // namespace V1_0
+}  // namespace keymint
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/ng/AndroidKeyMint1Operation.cpp b/ng/AndroidKeyMint1Operation.cpp
new file mode 100644
index 0000000..d0b379a
--- /dev/null
+++ b/ng/AndroidKeyMint1Operation.cpp
@@ -0,0 +1,154 @@
+/*
+ *
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.keymint@1.0-impl"
+#include <log/log.h>
+
+#include "include/AndroidKeyMint1Operation.h"
+
+#include "KeyMintAidlUtils.h"
+#include <aidl/android/hardware/keymint/ErrorCode.h>
+#include <keymaster/android_keymaster.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace keymint {
+namespace V1_0 {
+
+using ::aidl::android::hardware::keymint::ErrorCode;
+
+using ::keymaster::AbortOperationRequest;
+using ::keymaster::AbortOperationResponse;
+using ::keymaster::FinishOperationRequest;
+using ::keymaster::FinishOperationResponse;
+using ::keymaster::UpdateOperationRequest;
+using ::keymaster::UpdateOperationResponse;
+
+AndroidKeyMint1Operation::AndroidKeyMint1Operation(
+    const shared_ptr<::keymaster::AndroidKeymaster> implementation,
+    keymaster_operation_handle_t opHandle)
+    : impl_(std::move(implementation)), opHandle_(opHandle) {}
+
+AndroidKeyMint1Operation::~AndroidKeyMint1Operation() {
+    if (opHandle_ != 0) {
+        abort();
+    }
+}
+
+ScopedAStatus AndroidKeyMint1Operation::update(const optional<KeyParameterArray>& params,
+                                               const optional<vector<uint8_t>>& input,
+                                               const optional<HardwareAuthToken>& /* authToken */,
+                                               const optional<VerificationToken>&
+                                               /* verificationToken */,
+                                               optional<KeyParameterArray>* updatedParams,
+                                               optional<ByteArray>* output,
+                                               int32_t* inputConsumed) {
+    if (!updatedParams || !output || !inputConsumed) {
+        return kmError2ScopedAStatus(KM_ERROR_OUTPUT_PARAMETER_NULL);
+    }
+
+    UpdateOperationRequest request;
+    request.op_handle = opHandle_;
+    if (input) {
+        request.input.Reinitialize(input->data(), input->size());
+    }
+
+    if (params) {
+        request.additional_params.Reinitialize(KmParamSet(params->params));
+    }
+
+    UpdateOperationResponse response;
+    impl_->UpdateOperation(request, &response);
+
+    *inputConsumed = 0;
+    if (response.error == KM_ERROR_OK) {
+        *inputConsumed = response.input_consumed;
+
+        updatedParams->emplace();
+        (*updatedParams)->params = kmParamSet2Aidl(response.output_params);
+
+        output->emplace();
+        (*output)->data = kmBuffer2vector(response.output);
+
+        return ScopedAStatus::ok();
+    }
+
+    opHandle_ = 0;
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMint1Operation::finish(const optional<KeyParameterArray>& params,
+                                               const optional<vector<uint8_t>>& input,
+                                               const optional<vector<uint8_t>>& signature,
+                                               const optional<HardwareAuthToken>& /* authToken */,
+                                               const optional<VerificationToken>&
+                                               /* verificationToken */,
+                                               optional<KeyParameterArray>* updatedParams,
+                                               vector<uint8_t>* output) {
+
+    if (!updatedParams || !output) {
+        return ScopedAStatus(AStatus_fromServiceSpecificError(
+            static_cast<int32_t>(ErrorCode::OUTPUT_PARAMETER_NULL)));
+    }
+
+    FinishOperationRequest request;
+    request.op_handle = opHandle_;
+
+    if (input) {
+        request.input.Reinitialize(input->data(), input->size());
+    }
+
+    if (signature) {
+        request.signature.Reinitialize(signature->data(), signature->size());
+    }
+
+    if (params) {
+        request.additional_params.Reinitialize(KmParamSet(params->params));
+    }
+
+    FinishOperationResponse response;
+    impl_->FinishOperation(request, &response);
+    opHandle_ = 0;
+
+    if (response.error == KM_ERROR_OK) {
+        updatedParams->emplace();
+        (*updatedParams)->params = kmParamSet2Aidl(response.output_params);
+
+        *output = kmBuffer2vector(response.output);
+        return ScopedAStatus::ok();
+    }
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+ScopedAStatus AndroidKeyMint1Operation::abort() {
+    AbortOperationRequest request;
+    request.op_handle = opHandle_;
+
+    AbortOperationResponse response;
+    impl_->AbortOperation(request, &response);
+    opHandle_ = 0;
+
+    return kmError2ScopedAStatus(response.error);
+}
+
+}  // namespace V1_0
+}  // namespace keymint
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/ng/KeyMintAidlUtils.cpp b/ng/KeyMintAidlUtils.cpp
new file mode 100644
index 0000000..17a53a5
--- /dev/null
+++ b/ng/KeyMintAidlUtils.cpp
@@ -0,0 +1,147 @@
+/*
+ *
+ * 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 "include/KeyMintAidlUtils.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace keymint {
+
+using namespace ::keymaster;
+
+vector<uint8_t> authToken2AidlVec(const HardwareAuthToken& token) {
+    static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
+                          sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+                          sizeof(token.timestamp) + 32 /* HMAC size */
+                      == sizeof(hw_auth_token_t),
+                  "HardwareAuthToken content size does not match hw_auth_token_t size");
+
+    vector<uint8_t> result;
+
+    if (token.mac.size() <= 32) return result;
+
+    result.resize(sizeof(hw_auth_token_t));
+    auto pos = result.begin();
+    *pos++ = 0;  // Version byte
+    pos = copy_bytes_to_iterator(token.challenge, pos);
+    pos = copy_bytes_to_iterator(token.userId, pos);
+    pos = copy_bytes_to_iterator(token.authenticatorId, pos);
+    pos = copy_bytes_to_iterator(token.authenticatorType, pos);
+    pos = copy_bytes_to_iterator(token.timestamp, pos);
+    pos = std::copy(token.mac.data(), token.mac.data() + token.mac.size(), pos);
+
+    return result;
+}
+
+// TODO(seleneh): This needs to be modified depends on how aidl support for union came out to
+// be.
+vector<KeyParameter> kmParamSet2Aidl(const keymaster_key_param_set_t& set) {
+    vector<KeyParameter> result;
+    if (set.length == 0 || set.params == nullptr) return result;
+
+    result.resize(set.length);
+    keymaster_key_param_t* params = set.params;
+    for (size_t i = 0; i < set.length; ++i) {
+        auto tag = params[i].tag;
+        result[i].tag = legacy_enum_conversion(tag);
+        switch (typeFromTag(tag)) {
+        case KM_ENUM:
+        case KM_ENUM_REP:
+            result[i].integer = params[i].enumerated;
+            break;
+        case KM_UINT:
+        case KM_UINT_REP:
+            result[i].integer = params[i].integer;
+            break;
+        case KM_ULONG:
+        case KM_ULONG_REP:
+            result[i].longInteger = params[i].long_integer;
+            break;
+        case KM_DATE:
+            result[i].longInteger = params[i].date_time;
+            break;
+        case KM_BOOL:
+            result[i].boolValue = params[i].boolean;
+            break;
+        case KM_BIGNUM:
+        case KM_BYTES:
+            result[i].blob.assign(params[i].blob.data,
+                                  params[i].blob.data + params[i].blob.data_length);
+            break;
+        case KM_INVALID:
+        default:
+            params[i].tag = KM_TAG_INVALID;
+            /* just skip */
+            break;
+        }
+    }
+    return result;
+}
+
+// TODO(seleneh): This needs to be modified depends on how aidl support for union came out to
+// be.
+keymaster_key_param_set_t aidlKeyParams2Km(const vector<KeyParameter>& keyParams) {
+    keymaster_key_param_set_t set;
+
+    set.params = new keymaster_key_param_t[keyParams.size()];
+    set.length = keyParams.size();
+
+    for (size_t i = 0; i < keyParams.size(); ++i) {
+        auto tag = legacy_enum_conversion(keyParams[i].tag);
+        switch (typeFromTag(tag)) {
+        case KM_ENUM:
+        case KM_ENUM_REP:
+            set.params[i] = keymaster_param_enum(tag, keyParams[i].integer);
+            break;
+        case KM_UINT:
+        case KM_UINT_REP:
+            set.params[i] = keymaster_param_int(tag, keyParams[i].integer);
+            break;
+        case KM_ULONG:
+        case KM_ULONG_REP:
+            set.params[i] = keymaster_param_long(tag, keyParams[i].longInteger);
+            break;
+        case KM_DATE:
+            set.params[i] = keymaster_param_date(tag, keyParams[i].longInteger);
+            break;
+        case KM_BOOL:
+            if (keyParams[i].boolValue)
+                set.params[i] = keymaster_param_bool(tag);
+            else
+                set.params[i].tag = KM_TAG_INVALID;
+            break;
+        case KM_BIGNUM:
+        case KM_BYTES:
+            set.params[i] =
+                keymaster_param_blob(tag, keyParams[i].blob.data(), keyParams[i].blob.size());
+            break;
+        case KM_INVALID:
+        default:
+            set.params[i].tag = KM_TAG_INVALID;
+            /* just skip */
+            break;
+        }
+    }
+
+    return set;
+}
+
+}  // namespace keymint
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/ng/include/AndroidKeyMint1Device.h b/ng/include/AndroidKeyMint1Device.h
new file mode 100644
index 0000000..0c447e9
--- /dev/null
+++ b/ng/include/AndroidKeyMint1Device.h
@@ -0,0 +1,101 @@
+/*
+ **
+ ** 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 <aidl/android/hardware/keymint/BnKeyMintDevice.h>
+#include <aidl/android/hardware/keymint/BnKeyMintOperation.h>
+#include <aidl/android/hardware/keymint/HardwareAuthToken.h>
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace keymint {
+
+namespace V1_0 {
+
+using ::aidl::android::hardware::keymint::Certificate;
+using ::aidl::android::hardware::keymint::HardwareAuthToken;
+using ::aidl::android::hardware::keymint::IKeyMintOperation;
+using ::aidl::android::hardware::keymint::KeyCharacteristics;
+using ::aidl::android::hardware::keymint::KeyFormat;
+using ::aidl::android::hardware::keymint::KeyMintHardwareInfo;
+using ::aidl::android::hardware::keymint::KeyParameter;
+using ::aidl::android::hardware::keymint::KeyPurpose;
+using ::aidl::android::hardware::keymint::VerificationToken;
+
+using ::ndk::ScopedAStatus;
+using std::shared_ptr;
+using std::vector;
+
+class AndroidKeyMint1Device : public BnKeyMintDevice {
+  public:
+    explicit AndroidKeyMint1Device(SecurityLevel securityLevel);
+    virtual ~AndroidKeyMint1Device();
+
+    ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* info) override;
+
+    ScopedAStatus verifyAuthorization(int64_t challenge, const HardwareAuthToken& token,
+                                      VerificationToken* verificationToken) override;
+
+    ScopedAStatus addRngEntropy(const vector<uint8_t>& data) override;
+
+    ScopedAStatus generateKey(const vector<KeyParameter>& keyParams, ByteArray* generatedKeyBlob,
+                              KeyCharacteristics* generatedKeyCharacteristics,
+                              vector<Certificate>* certChain) override;
+
+    ScopedAStatus importKey(const vector<KeyParameter>& keyParams, KeyFormat keyFormat,
+                            const vector<uint8_t>& keyData, ByteArray* importedKeyBlob,
+                            KeyCharacteristics* importedKeyCharacteristics,
+                            vector<Certificate>* certChain) 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,
+                                   ByteArray* importedKeyBlob,
+                                   KeyCharacteristics* importedKeyCharacteristics) 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 HardwareAuthToken& authToken,
+                        BeginResult* result) override;
+
+  protected:
+    std::shared_ptr<::keymaster::AndroidKeymaster> impl_;
+    SecurityLevel securityLevel_;
+};
+
+IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel);
+
+}  // namespace V1_0
+}  // namespace keymint
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/ng/include/AndroidKeyMint1Operation.h b/ng/include/AndroidKeyMint1Operation.h
new file mode 100644
index 0000000..67c614a
--- /dev/null
+++ b/ng/include/AndroidKeyMint1Operation.h
@@ -0,0 +1,84 @@
+/*
+ **
+ ** 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.
+ */
+
+#ifndef android_hardware_keymint_V1_0_AndroidKeyMint1Operation_H_
+#define android_hardware_keymint_V1_0_AndroidKeyMint1Operation_H_
+
+#include <aidl/android/hardware/keymint/BnKeyMintOperation.h>
+
+#include <hardware/keymaster_defs.h>
+
+namespace keymaster {
+class AndroidKeymaster;
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace keymint {
+
+namespace V1_0 {
+
+using ::aidl::android::hardware::keymint::HardwareAuthToken;
+using ::aidl::android::hardware::keymint::KeyParameterArray;
+using ::aidl::android::hardware::keymint::VerificationToken;
+
+using ::ndk::ScopedAStatus;
+using std::optional;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+
+class AndroidKeyMint1Operation : public BnKeyMintOperation {
+  public:
+    explicit AndroidKeyMint1Operation(
+        const shared_ptr<::keymaster::AndroidKeymaster> implementation,
+        keymaster_operation_handle_t opHandle);
+
+    AndroidKeyMint1Operation() = delete;
+
+    virtual ~AndroidKeyMint1Operation();
+
+    ScopedAStatus update(const optional<KeyParameterArray>& params,
+                         const optional<vector<uint8_t>>& input,
+                         const optional<HardwareAuthToken>& authToken,
+                         const optional<VerificationToken>& verificationToken,
+                         optional<KeyParameterArray>* updatedParams, optional<ByteArray>* output,
+                         int32_t* inputConsumed) override;
+
+    ScopedAStatus finish(const optional<KeyParameterArray>& params,     //
+                         const optional<vector<uint8_t>>& input,        //
+                         const optional<vector<uint8_t>>& signature,    //
+                         const optional<HardwareAuthToken>& authToken,  //
+                         const optional<VerificationToken>& verificationToken,
+                         optional<KeyParameterArray>* resultParams,  //
+                         vector<uint8_t>* output) override;
+
+    ScopedAStatus abort() override;
+
+  protected:
+    std::shared_ptr<::keymaster::AndroidKeymaster> impl_;
+    keymaster_operation_handle_t opHandle_;
+};
+
+}  // namespace V1_0
+}  // namespace keymint
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
+
+#endif  // android_hardware_keymint_V1_0_AndroidKeyMint1Operation_H_
diff --git a/ng/include/KeyMintAidlUtils.h b/ng/include/KeyMintAidlUtils.h
new file mode 100644
index 0000000..6425676
--- /dev/null
+++ b/ng/include/KeyMintAidlUtils.h
@@ -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.
+ */
+
+#include <log/log.h>
+
+#include <aidl/android/hardware/keymint/Certificate.h>
+#include <aidl/android/hardware/keymint/HardwareAuthToken.h>
+#include <aidl/android/hardware/keymint/HardwareAuthenticatorType.h>
+#include <aidl/android/hardware/keymint/KeyFormat.h>
+#include <aidl/android/hardware/keymint/KeyParameter.h>
+#include <aidl/android/hardware/keymint/KeyPurpose.h>
+#include <aidl/android/hardware/keymint/SecurityLevel.h>
+#include <aidl/android/hardware/keymint/Tag.h>
+
+#include <keymaster/keymaster_enforcement.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace keymint {
+
+using ::aidl::android::hardware::keymint::HardwareAuthToken;
+using ::ndk::ScopedAStatus;
+using std::vector;
+
+inline keymaster_tag_t legacy_enum_conversion(const Tag value) {
+    return keymaster_tag_t(value);
+}
+
+inline Tag legacy_enum_conversion(const keymaster_tag_t value) {
+    return Tag(value);
+}
+
+inline keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
+    return static_cast<keymaster_purpose_t>(value);
+}
+
+inline keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
+    return static_cast<keymaster_key_format_t>(value);
+}
+
+inline SecurityLevel legacy_enum_conversion(const keymaster_security_level_t value) {
+    return static_cast<SecurityLevel>(value);
+}
+
+inline hw_authenticator_type_t legacy_enum_conversion(const HardwareAuthenticatorType value) {
+    return static_cast<hw_authenticator_type_t>(value);
+}
+
+inline ScopedAStatus kmError2ScopedAStatus(const keymaster_error_t value) {
+    return (value == KM_ERROR_OK
+                ? ScopedAStatus::ok()
+                : ScopedAStatus(AStatus_fromServiceSpecificError(static_cast<int32_t>(value))));
+}
+
+inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
+    return keymaster_tag_get_type(tag);
+}
+
+keymaster_key_param_set_t aidlKeyParams2Km(const vector<KeyParameter>& keyParams);
+
+class KmParamSet : public keymaster_key_param_set_t {
+  public:
+    explicit KmParamSet(const vector<KeyParameter>& keyParams)
+        : keymaster_key_param_set_t(aidlKeyParams2Km(keyParams)) {}
+
+    KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
+        other.length = 0;
+        other.params = nullptr;
+    }
+
+    KmParamSet(const KmParamSet&) = delete;
+    ~KmParamSet() { delete[] params; }
+};
+
+inline vector<uint8_t> kmBlob2vector(const keymaster_key_blob_t& blob) {
+    vector<uint8_t> result(blob.key_material, blob.key_material + blob.key_material_size);
+    return result;
+}
+
+inline vector<uint8_t> kmBlob2vector(const keymaster_blob_t& blob) {
+    vector<uint8_t> result(blob.data, blob.data + blob.data_length);
+    return result;
+}
+
+inline vector<uint8_t> kmBuffer2vector(const ::keymaster::Buffer& buf) {
+    vector<uint8_t> result(buf.peek_read(), buf.peek_read() + buf.available_read());
+    return result;
+}
+
+inline vector<Certificate> kmCertChain2Aidl(const keymaster_cert_chain_t& cert_chain) {
+    vector<Certificate> result;
+    if (!cert_chain.entry_count || !cert_chain.entries) return result;
+
+    result.resize(cert_chain.entry_count);
+    for (size_t i = 0; i < cert_chain.entry_count; ++i) {
+        result[i].encodedCertificate = kmBlob2vector(cert_chain.entries[i]);
+    }
+
+    return result;
+}
+
+template <typename T, typename OutIter>
+inline OutIter copy_bytes_to_iterator(const T& value, OutIter dest) {
+    const uint8_t* value_ptr = reinterpret_cast<const uint8_t*>(&value);
+    return std::copy(value_ptr, value_ptr + sizeof(value), dest);
+}
+
+vector<uint8_t> authToken2AidlVec(const HardwareAuthToken& token);
+
+vector<KeyParameter> kmParamSet2Aidl(const keymaster_key_param_set_t& set);
+
+inline void addClientAndAppData(const vector<uint8_t>& clientId, const vector<uint8_t>& appData,
+                                ::keymaster::AuthorizationSet* params) {
+    params->Clear();
+    if (clientId.size()) {
+        params->push_back(::keymaster::TAG_APPLICATION_ID, clientId.data(), clientId.size());
+    }
+    if (appData.size()) {
+        params->push_back(::keymaster::TAG_APPLICATION_DATA, appData.data(), appData.size());
+    }
+}
+
+}  // namespace keymint
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl