diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2020-11-17 16:13:49 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-11-17 16:13:49 +0000 |
commit | 2ef464e90c778ac7927f2a0cd0c9cfe878cbe2c5 (patch) | |
tree | 10e8112a2eb0d0266ef2dd502a3ac78ec8096f79 | |
parent | 38084cc2e3821dc499e4223bb3871ba8d2013cac (diff) | |
parent | fb81829fb4d268857d5b83f64973eb6a405cbb22 (diff) | |
download | keymaster-2ef464e90c778ac7927f2a0cd0c9cfe878cbe2c5.tar.gz |
Merge "KeyMint 1 system side coding."
-rw-r--r-- | Android.bp | 33 | ||||
-rw-r--r-- | android_keymaster/keymaster_configuration.cpp | 3 | ||||
-rw-r--r-- | ng/AndroidKeyMint1Device.cpp | 276 | ||||
-rw-r--r-- | ng/AndroidKeyMint1Operation.cpp | 154 | ||||
-rw-r--r-- | ng/KeyMintAidlUtils.cpp | 147 | ||||
-rw-r--r-- | ng/include/AndroidKeyMint1Device.h | 101 | ||||
-rw-r--r-- | ng/include/AndroidKeyMint1Operation.h | 84 | ||||
-rw-r--r-- | ng/include/KeyMintAidlUtils.h | 141 |
8 files changed, 938 insertions, 1 deletions
@@ -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(®ex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */); regfree(®ex); 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 |