summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2020-11-17 16:13:49 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2020-11-17 16:13:49 +0000
commit2ef464e90c778ac7927f2a0cd0c9cfe878cbe2c5 (patch)
tree10e8112a2eb0d0266ef2dd502a3ac78ec8096f79
parent38084cc2e3821dc499e4223bb3871ba8d2013cac (diff)
parentfb81829fb4d268857d5b83f64973eb6a405cbb22 (diff)
downloadkeymaster-2ef464e90c778ac7927f2a0cd0c9cfe878cbe2c5.tar.gz
Merge "KeyMint 1 system side coding."
-rw-r--r--Android.bp33
-rw-r--r--android_keymaster/keymaster_configuration.cpp3
-rw-r--r--ng/AndroidKeyMint1Device.cpp276
-rw-r--r--ng/AndroidKeyMint1Operation.cpp154
-rw-r--r--ng/KeyMintAidlUtils.cpp147
-rw-r--r--ng/include/AndroidKeyMint1Device.h101
-rw-r--r--ng/include/AndroidKeyMint1Operation.h84
-rw-r--r--ng/include/KeyMintAidlUtils.h141
8 files changed, 938 insertions, 1 deletions
diff --git a/Android.bp b/Android.bp
index 0639237..219494c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -329,6 +329,39 @@ cc_library_shared {
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 @@ uint32_t GetOsVersion(const char* version_str) {
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