diff options
83 files changed, 1420 insertions, 328 deletions
@@ -52,15 +52,12 @@ cc_defaults { "-Wall", "-Werror", "-Wunused", - ], - clang: true, - clang_cflags: [ "-Wno-error=unused-const-variable", "-Wno-error=unused-private-field", "-Wimplicit-fallthrough", // TODO(krasin): reenable coverage flags, when the new Clang toolchain is released. // Currently, if enabled, these flags will cause an internal error in Clang. - "-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" + "-fno-sanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp", ], tidy: true, tidy_checks: [ @@ -69,6 +66,11 @@ cc_defaults { sanitize: { integer_overflow: false, }, + target: { + windows: { + enabled: true, + }, + }, } cc_library_shared { @@ -82,15 +84,15 @@ cc_library_shared { "android_keymaster/serializable.cpp", ], header_libs: ["libhardware_headers"], - defaults: ["keymaster_defaults" ], - clang_cflags: [ + defaults: ["keymaster_defaults"], + cflags: [ "-DKEYMASTER_NAME_TAGS", ], export_include_dirs: ["include"], host_supported: true, target: { host: { - clang_cflags: [ + cflags: [ "-fno-rtti", // TODO(b/156427382): Remove workaround when possible. ], }, @@ -163,12 +165,12 @@ cc_library { export_shared_lib_headers: ["libcppbor_external"], header_libs: ["libhardware_headers"], export_header_lib_headers: ["libhardware_headers"], - defaults: ["keymaster_defaults" ], + defaults: ["keymaster_defaults"], host_supported: true, export_include_dirs: ["include"], target: { host: { - clang_cflags: [ + cflags: [ "-fno-rtti", // TODO(b/156427382): Remove workaround when possible. ], }, @@ -273,7 +275,7 @@ cc_library { "libcutils", "libbase", ], - clang_cflags: [ + cflags: [ "-DKEYMASTER_NAME_TAGS", "-fno-rtti", // TODO(b/156427382): Remove workaround when possible. ], @@ -311,10 +313,13 @@ cc_library_shared { "libsoft_attestation_cert", "libutils", ], - export_include_dirs: ["include", "ng/include"], + export_include_dirs: [ + "include", + "ng/include", + ], } -cc_library_shared { +cc_library { name: "libkeymaster4", srcs: [ "legacy_support/keymaster_passthrough_key.cpp", @@ -339,7 +344,7 @@ cc_library_shared { ], export_include_dirs: [ "ng/include", - "include" + "include", ], } @@ -409,6 +414,7 @@ cc_library { ], shared_libs: [ "libhidlbase", + "android.hardware.security.rkp-V3-ndk", "android.hardware.security.secureclock-V1-ndk", "android.hardware.security.sharedsecret-V1-ndk", "lib_android_keymaster_keymint_utils", @@ -423,7 +429,10 @@ cc_library { "libpuresoftkeymasterdevice", "libutils", ], - export_include_dirs: ["include", "ng/include"], + export_include_dirs: [ + "include", + "ng/include", + ], } cc_library { @@ -441,6 +450,11 @@ cc_library { "libcrypto", "liblog", ], + target: { + windows: { + enabled: true, + }, + }, } cc_defaults { @@ -462,7 +476,7 @@ cc_defaults { host_supported: true, target: { host: { - clang_cflags: [ + cflags: [ "-fno-rtti", // TODO(b/156427382): Remove when default library removes this ], }, diff --git a/android_keymaster/android_keymaster.cpp b/android_keymaster/android_keymaster.cpp index 420bbf2..f4e1dd9 100644 --- a/android_keymaster/android_keymaster.cpp +++ b/android_keymaster/android_keymaster.cpp @@ -16,6 +16,7 @@ #include <keymaster/android_keymaster.h> +#include <utility> #include <vector> #include <assert.h> @@ -133,6 +134,7 @@ std::pair<const uint8_t*, size_t> blob2Pair(const keymaster_blob_t& blob) { return {blob.data, blob.data_length}; } +constexpr int kMaxChallengeSizeV2 = 64; constexpr int kP256AffinePointSize = 32; constexpr int kRoTVersion1 = 40001; @@ -140,13 +142,13 @@ constexpr int kRoTVersion1 = 40001; AndroidKeymaster::AndroidKeymaster(KeymasterContext* context, size_t operation_table_size, int32_t message_version) - : context_(context), operation_table_(new (std::nothrow) OperationTable(operation_table_size)), + : context_(context), operation_table_(new(std::nothrow) OperationTable(operation_table_size)), message_version_(message_version) {} AndroidKeymaster::~AndroidKeymaster() {} AndroidKeymaster::AndroidKeymaster(AndroidKeymaster&& other) - : context_(move(other.context_)), operation_table_(move(other.operation_table_)), + : context_(std::move(other.context_)), operation_table_(std::move(other.operation_table_)), message_version_(other.message_version_) {} // TODO(swillden): Unify support analysis. Right now, we have per-keytype methods that determine if @@ -350,7 +352,7 @@ void AndroidKeymaster::GenerateKey(const GenerateKeyRequest& request, response->enforced.Clear(); response->unenforced.Clear(); response->error = factory->GenerateKey(request.key_description, - move(attest_key), // + std::move(attest_key), // request.issuer_subject, &response->key_blob, // &response->enforced, @@ -358,16 +360,25 @@ void AndroidKeymaster::GenerateKey(const GenerateKeyRequest& request, &response->certificate_chain); } +constexpr int kRkpVersionWithoutSuperencryption = 3; + void AndroidKeymaster::GenerateRkpKey(const GenerateRkpKeyRequest& request, GenerateRkpKeyResponse* response) { if (response == nullptr) return; auto rem_prov_ctx = context_->GetRemoteProvisioningContext(); - if (rem_prov_ctx == nullptr) { + if (!rem_prov_ctx) { response->error = static_cast<keymaster_error_t>(kStatusFailed); return; } + GetHwInfoResponse hwInfo(message_version()); + rem_prov_ctx->GetHwInfo(&hwInfo); + if (hwInfo.version >= kRkpVersionWithoutSuperencryption && request.test_mode) { + response->error = static_cast<keymaster_error_t>(kStatusRemoved); + return; + } + // Generate the keypair that will become the attestation key. GenerateKeyRequest gen_key_request(message_version_); gen_key_request.key_description.Reinitialize(kKeyMintEcdsaP256Params, @@ -424,12 +435,19 @@ void AndroidKeymaster::GenerateCsr(const GenerateCsrRequest& request, if (response == nullptr) return; auto rem_prov_ctx = context_->GetRemoteProvisioningContext(); - if (rem_prov_ctx == nullptr) { + if (!rem_prov_ctx) { LOG_E("Couldn't get a pointer to the remote provisioning context, returned null.", 0); response->error = static_cast<keymaster_error_t>(kStatusFailed); return; } + GetHwInfoResponse hwInfo(message_version()); + rem_prov_ctx->GetHwInfo(&hwInfo); + if (hwInfo.version >= kRkpVersionWithoutSuperencryption) { + response->error = static_cast<keymaster_error_t>(kStatusRemoved); + return; + } + auto macFunction = getMacFunction(request.test_mode, rem_prov_ctx); auto pubKeysToSign = validateAndExtractPubkeys(request.test_mode, request.num_keys, request.keys_to_sign_array, macFunction); @@ -450,8 +468,8 @@ void AndroidKeymaster::GenerateCsr(const GenerateCsrRequest& request, return cppcose::generateHmacSha256(ephemeral_mac_key, input); }; - auto pubKeysToSignMac = - generateCoseMac0Mac(ephemeral_mac_function, std::vector<uint8_t>{}, *pubKeysToSign); + auto pubKeysToSignMac = generateCoseMac0Mac(ephemeral_mac_function, std::vector<uint8_t>{}, + pubKeysToSign->encode()); if (!pubKeysToSignMac) { LOG_E("Failed to generate COSE_Mac0 over the public keys to sign.", 0); response->error = static_cast<keymaster_error_t>(kStatusFailed); @@ -459,7 +477,8 @@ void AndroidKeymaster::GenerateCsr(const GenerateCsrRequest& request, } response->keys_to_sign_mac = KeymasterBlob(pubKeysToSignMac->data(), pubKeysToSignMac->size()); - std::unique_ptr<cppbor::Map> device_info_map = rem_prov_ctx->CreateDeviceInfo(); + std::unique_ptr<cppbor::Map> device_info_map = + rem_prov_ctx->CreateDeviceInfo(2 /* csrVersion */); std::vector<uint8_t> device_info = device_info_map->encode(); response->device_info_blob = KeymasterBlob(device_info.data(), device_info.size()); auto protectedDataPayload = rem_prov_ctx->BuildProtectedDataPayload( @@ -518,6 +537,48 @@ void AndroidKeymaster::GenerateCsr(const GenerateCsrRequest& request, response->error = KM_ERROR_OK; } +void AndroidKeymaster::GenerateCsrV2(const GenerateCsrV2Request& request, + GenerateCsrV2Response* response) { + + if (response == nullptr) return; + + if (request.challenge.size() > kMaxChallengeSizeV2) { + LOG_E("Challenge is too large. %zu expected. %zu actual.", + kMaxChallengeSizeV2, // + request.challenge.size()); // + response->error = static_cast<keymaster_error_t>(kStatusFailed); + return; + } + + auto rem_prov_ctx = context_->GetRemoteProvisioningContext(); + if (rem_prov_ctx == nullptr) { + LOG_E("Couldn't get a pointer to the remote provisioning context, returned null.", 0); + response->error = static_cast<keymaster_error_t>(kStatusFailed); + return; + } + + auto macFunction = getMacFunction(false /* test_mode */, rem_prov_ctx); + auto pubKeys = validateAndExtractPubkeys(false /* test_mode */, request.num_keys, + request.keys_to_sign_array, macFunction); + if (!pubKeys.isOk()) { + LOG_E("Failed to validate and extract the public keys for the CSR", 0); + response->error = static_cast<keymaster_error_t>(pubKeys.moveError()); + return; + } + + auto csr = rem_prov_ctx->BuildCsr( + std::vector(request.challenge.begin(), request.challenge.end()), std::move(*pubKeys)); + if (!csr) { + LOG_E("Failed to build CSR", 0); + response->error = static_cast<keymaster_error_t>(kStatusFailed); + return; + } + + auto csr_blob = csr->encode(); + response->csr = KeymasterBlob(csr_blob.data(), csr_blob.size()); + response->error = KM_ERROR_OK; +} + void AndroidKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request, GetKeyCharacteristicsResponse* response) { if (response == nullptr) return; @@ -528,8 +589,8 @@ void AndroidKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& if (response->error != KM_ERROR_OK) return; // scavenge the key object for the auth lists - response->enforced = move(key->hw_enforced()); - response->unenforced = move(key->sw_enforced()); + response->enforced = std::move(key->hw_enforced()); + response->unenforced = std::move(key->sw_enforced()); response->error = CheckVersionInfo(response->enforced, response->unenforced, *context_); } @@ -553,7 +614,7 @@ void AndroidKeymaster::BeginOperation(const BeginOperationRequest& request, uint32_t sd_slot = key->secure_deletion_slot(); OperationPtr operation( - factory->CreateOperation(move(*key), request.additional_params, &response->error)); + factory->CreateOperation(std::move(*key), request.additional_params, &response->error)); if (operation.get() == nullptr) return; operation->set_secure_deletion_slot(sd_slot); @@ -581,7 +642,7 @@ void AndroidKeymaster::BeginOperation(const BeginOperationRequest& request, if (response->error != KM_ERROR_OK) return; response->op_handle = operation->operation_handle(); - response->error = operation_table_->Add(move(operation)); + response->error = operation_table_->Add(std::move(operation)); } void AndroidKeymaster::UpdateOperation(const UpdateOperationRequest& request, @@ -799,7 +860,7 @@ void AndroidKeymaster::ImportKey(const ImportKeyRequest& request, ImportKeyRespo response->error = factory->ImportKey(request.key_description, // request.key_format, // request.key_data, // - move(attest_key), // + std::move(attest_key), // request.issuer_subject, // &response->key_blob, // &response->enforced, // @@ -998,4 +1059,33 @@ GetRootOfTrustResponse AndroidKeymaster::GetRootOfTrust(const GetRootOfTrustRequ return response; } +GetHwInfoResponse AndroidKeymaster::GetHwInfo() { + GetHwInfoResponse response(message_version()); + + auto rem_prov_ctx = context_->GetRemoteProvisioningContext(); + if (!rem_prov_ctx) { + LOG_E("Couldn't get a pointer to the remote provisioning context, returned null.", 0); + response.error = static_cast<keymaster_error_t>(kStatusFailed); + return response; + } + + rem_prov_ctx->GetHwInfo(&response); + response.error = KM_ERROR_OK; + return response; +} + +SetAttestationIdsResponse +AndroidKeymaster::SetAttestationIds(const SetAttestationIdsRequest& request) { + SetAttestationIdsResponse response(message_version()); + response.error = context_->SetAttestationIds(request); + return response; +} + +SetAttestationIdsKM3Response +AndroidKeymaster::SetAttestationIdsKM3(const SetAttestationIdsKM3Request& request) { + SetAttestationIdsKM3Response response(message_version()); + response.error = context_->SetAttestationIdsKM3(request); + return response; +} + } // namespace keymaster diff --git a/android_keymaster/android_keymaster_messages.cpp b/android_keymaster/android_keymaster_messages.cpp index 3dfd529..78553ea 100644 --- a/android_keymaster/android_keymaster_messages.cpp +++ b/android_keymaster/android_keymaster_messages.cpp @@ -310,6 +310,66 @@ bool GenerateCsrResponse::NonErrorDeserialize(const uint8_t** buf_ptr, const uin deserialize_blob(&protected_data_blob, buf_ptr, end); } +size_t GenerateCsrV2Request::SerializedSize() const { + size_t size = sizeof(uint32_t); /* num_keys */ + for (size_t i = 0; i < num_keys; i++) { + size += blob_size(keys_to_sign_array[i]); + } + size += blob_size(challenge); + return size; +} + +uint8_t* GenerateCsrV2Request::Serialize(uint8_t* buf, const uint8_t* end) const { + buf = append_uint32_to_buf(buf, end, num_keys); + for (size_t i = 0; i < num_keys; i++) { + buf = serialize_blob(keys_to_sign_array[i], buf, end); + } + return serialize_blob(challenge, buf, end); +} + +bool GenerateCsrV2Request::Deserialize(const uint8_t** buf_ptr, const uint8_t* end) { + if (!copy_from_buf(buf_ptr, end, &num_keys, sizeof(uint32_t))) return false; + + keys_to_sign_array = new (std::nothrow) KeymasterBlob[num_keys]; + if (!keys_to_sign_array) return false; + for (size_t i = 0; i < num_keys; i++) { + if (!deserialize_blob(&keys_to_sign_array[i], buf_ptr, end)) return false; + } + return deserialize_blob(&challenge, buf_ptr, end); +} + +bool GenerateCsrV2Request::InitKeysToSign(uint32_t count) { + num_keys = count; + keys_to_sign_array = new (std::nothrow) KeymasterBlob[count]; + if (!keys_to_sign_array) { + return false; + } + return true; +} + +void GenerateCsrV2Request::SetKeyToSign(uint32_t index, const void* data, size_t length) { + if (index >= num_keys) { + return; + } + set_blob(&keys_to_sign_array[index], data, length); +} + +void GenerateCsrV2Request::SetChallenge(const void* data, size_t length) { + set_blob(&challenge, data, length); +} + +size_t GenerateCsrV2Response::NonErrorSerializedSize() const { + return blob_size(csr); +} + +uint8_t* GenerateCsrV2Response::NonErrorSerialize(uint8_t* buf, const uint8_t* end) const { + return serialize_blob(csr, buf, end); +} + +bool GenerateCsrV2Response::NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) { + return deserialize_blob(&csr, buf_ptr, end); +} + GetKeyCharacteristicsRequest::~GetKeyCharacteristicsRequest() { delete[] key_blob.key_material; } diff --git a/android_keymaster/keymaster_enforcement.cpp b/android_keymaster/keymaster_enforcement.cpp index de768cb..5c3bf01 100644 --- a/android_keymaster/keymaster_enforcement.cpp +++ b/android_keymaster/keymaster_enforcement.cpp @@ -313,6 +313,7 @@ keymaster_error_t KeymasterEnforcement::AuthorizeBegin(const keymaster_purpose_t case KM_TAG_ATTESTATION_ID_PRODUCT: case KM_TAG_ATTESTATION_ID_SERIAL: case KM_TAG_ATTESTATION_ID_IMEI: + case KM_TAG_ATTESTATION_ID_SECOND_IMEI: case KM_TAG_ATTESTATION_ID_MEID: case KM_TAG_ATTESTATION_ID_MANUFACTURER: case KM_TAG_ATTESTATION_ID_MODEL: diff --git a/android_keymaster/keymaster_tags.cpp b/android_keymaster/keymaster_tags.cpp index dc42061..f1aafea 100644 --- a/android_keymaster/keymaster_tags.cpp +++ b/android_keymaster/keymaster_tags.cpp @@ -131,6 +131,8 @@ const char* StringifyTag(keymaster_tag_t tag) { return "KM_TAG_ATTESTATION_ID_SERIAL"; case KM_TAG_ATTESTATION_ID_IMEI: return "KM_TAG_ATTESTATION_ID_IMEI"; + case KM_TAG_ATTESTATION_ID_SECOND_IMEI: + return "KM_TAG_ATTESTATION_ID_SECOND_IMEI"; case KM_TAG_ATTESTATION_ID_MEID: return "KM_TAG_ATTESTATION_ID_MEID"; case KM_TAG_ATTESTATION_ID_MANUFACTURER: @@ -214,6 +216,7 @@ DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_DEVICE); DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_PRODUCT); DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SERIAL); DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_IMEI); +DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SECOND_IMEI); DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MEID); DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MANUFACTURER); DEFINE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL); diff --git a/android_keymaster/operation_table.cpp b/android_keymaster/operation_table.cpp index 50d47f5..0d8b431 100644 --- a/android_keymaster/operation_table.cpp +++ b/android_keymaster/operation_table.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <utility> + #include <keymaster/android_keymaster_utils.h> #include <keymaster/operation.h> #include <keymaster/operation_table.h> @@ -27,7 +29,7 @@ keymaster_error_t OperationTable::Add(OperationPtr&& operation) { } for (size_t i = 0; i < table_size_; ++i) { if (!table_[i]) { - table_[i] = move(operation); + table_[i] = std::move(operation); return KM_ERROR_OK; } } diff --git a/android_keymaster/remote_provisioning_utils.cpp b/android_keymaster/remote_provisioning_utils.cpp index 78a058a..5a5ab80 100644 --- a/android_keymaster/remote_provisioning_utils.cpp +++ b/android_keymaster/remote_provisioning_utils.cpp @@ -124,7 +124,7 @@ validateAndExtractEekPubAndId(bool testMode, const KeymasterBlob& endpointEncryp eek->getBstrValue(CoseKey::KEY_ID).value()); } -StatusOr<std::vector<uint8_t> /* pubkeys */> +StatusOr<cppbor::Array /* pubkeys */> validateAndExtractPubkeys(bool testMode, uint32_t numKeys, KeymasterBlob* keysToSign, const cppcose::HmacSha256Function& macFunction) { auto pubKeysToMac = cppbor::Array(); @@ -186,7 +186,7 @@ validateAndExtractPubkeys(bool testMode, uint32_t numKeys, KeymasterBlob* keysTo pubKeysToMac.add(pubKey->moveMap()); } - return pubKeysToMac.encode(); + return pubKeysToMac; } cppbor::Array buildCertReqRecipients(const std::vector<uint8_t>& pubkey, diff --git a/contexts/keymaster1_passthrough_context.cpp b/contexts/keymaster1_passthrough_context.cpp index 02c4623..8dcd5cf 100644 --- a/contexts/keymaster1_passthrough_context.cpp +++ b/contexts/keymaster1_passthrough_context.cpp @@ -17,6 +17,8 @@ #include <keymaster/contexts/keymaster1_passthrough_context.h> +#include <utility> + #include <keymaster/contexts/soft_attestation_cert.h> #include <keymaster/key_blob_utils/integrity_assured_key_blob.h> #include <keymaster/key_blob_utils/ocb_utils.h> @@ -171,8 +173,8 @@ Keymaster1PassthroughContext::ParseKeyBlob(const KeymasterKeyBlob& blob, } auto factory = GetKeyFactory(algorithm); - return factory->LoadKey(move(key_material), additional_params, move(hw_enforced), - move(sw_enforced), key); + return factory->LoadKey(std::move(key_material), additional_params, std::move(hw_enforced), + std::move(sw_enforced), key); } keymaster_error_t Keymaster1PassthroughContext::DeleteKey(const KeymasterKeyBlob& blob) const { diff --git a/contexts/keymaster2_passthrough_context.cpp b/contexts/keymaster2_passthrough_context.cpp index 75ed9b6..23fc145 100644 --- a/contexts/keymaster2_passthrough_context.cpp +++ b/contexts/keymaster2_passthrough_context.cpp @@ -17,6 +17,8 @@ #include <keymaster/contexts/keymaster2_passthrough_context.h> +#include <utility> + #include <keymaster/legacy_support/keymaster_passthrough_engine.h> #include <keymaster/legacy_support/keymaster_passthrough_key.h> @@ -105,8 +107,8 @@ Keymaster2PassthroughContext::ParseKeyBlob(const KeymasterKeyBlob& blob, KeymasterKeyBlob key_material = blob; auto factory = GetKeyFactory(algorithm); - return factory->LoadKey(move(key_material), additional_params, move(hw_enforced), - move(sw_enforced), key); + return factory->LoadKey(std::move(key_material), additional_params, std::move(hw_enforced), + std::move(sw_enforced), key); } keymaster_error_t Keymaster2PassthroughContext::DeleteKey(const KeymasterKeyBlob& blob) const { diff --git a/contexts/pure_soft_keymaster_context.cpp b/contexts/pure_soft_keymaster_context.cpp index 937238b..d68ce05 100644 --- a/contexts/pure_soft_keymaster_context.cpp +++ b/contexts/pure_soft_keymaster_context.cpp @@ -18,6 +18,7 @@ #include <assert.h> #include <memory> +#include <utility> #include <openssl/aes.h> #include <openssl/evp.h> @@ -324,8 +325,8 @@ keymaster_error_t PureSoftKeymasterContext::ParseKeyBlob(const KeymasterKeyBlob& } auto factory = GetKeyFactory(algorithm); - return factory->LoadKey(move(key_material), additional_params, move(hw_enforced), - move(sw_enforced), key); + return factory->LoadKey(std::move(key_material), additional_params, std::move(hw_enforced), + std::move(sw_enforced), key); }; AuthorizationSet hidden; @@ -416,7 +417,8 @@ PureSoftKeymasterContext::GenerateAttestation(const Key& key, AttestKeyInfo attest_key_info(attest_key, &issuer_subject, error); if (*error != KM_ERROR_OK) return {}; - return generate_attestation(asymmetric_key, attest_params, move(attest_key_info), *this, error); + return generate_attestation(asymmetric_key, attest_params, std::move(attest_key_info), *this, + error); } CertificateChain PureSoftKeymasterContext::GenerateSelfSignedCertificate( @@ -452,8 +454,10 @@ keymaster::Buffer PureSoftKeymasterContext::GenerateUniqueId(uint64_t creation_d // The secret must contain at least 128 bits of entropy and be unique to the individual device" const std::vector<uint8_t> fake_hbk = {'M', 'u', 's', 't', 'B', 'e', 'R', 'a', 'n', 'd', 'o', 'm', 'B', 'i', 't', 's'}; - return keymaster::generate_unique_id(fake_hbk, creation_date_time, application_id, - reset_since_rotation); + Buffer unique_id; + *error = keymaster::generate_unique_id(fake_hbk, creation_date_time, application_id, + reset_since_rotation, &unique_id); + return unique_id; } static keymaster_error_t TranslateAuthorizationSetError(AuthorizationSet::Error err) { @@ -508,7 +512,7 @@ keymaster_error_t PureSoftKeymasterContext::UnwrapKey( AuthorizationSet out_params; OperationPtr operation( - operation_factory->CreateOperation(move(*key), wrapping_key_params, &error)); + operation_factory->CreateOperation(std::move(*key), wrapping_key_params, &error)); if (!operation.get()) return error; error = operation->Begin(wrapping_key_params, &out_params); @@ -559,15 +563,16 @@ keymaster_error_t PureSoftKeymasterContext::UnwrapKey( if (!aes_factory) return KM_ERROR_UNKNOWN_ERROR; UniquePtr<Key> aes_key; - error = aes_factory->LoadKey(move(key_material), gcm_params, move(transit_key_authorizations), - AuthorizationSet(), &aes_key); + error = aes_factory->LoadKey(std::move(key_material), gcm_params, + std::move(transit_key_authorizations), AuthorizationSet(), + &aes_key); if (error != KM_ERROR_OK) return error; auto aes_operation_factory = GetOperationFactory(KM_ALGORITHM_AES, KM_PURPOSE_DECRYPT); if (!aes_operation_factory) return KM_ERROR_UNKNOWN_ERROR; OperationPtr aes_operation( - aes_operation_factory->CreateOperation(move(*aes_key), gcm_params, &error)); + aes_operation_factory->CreateOperation(std::move(*aes_key), gcm_params, &error)); if (!aes_operation.get()) return error; error = aes_operation->Begin(gcm_params, &out_params); diff --git a/contexts/pure_soft_remote_provisioning_context.cpp b/contexts/pure_soft_remote_provisioning_context.cpp index 6919458..fcafec4 100644 --- a/contexts/pure_soft_remote_provisioning_context.cpp +++ b/contexts/pure_soft_remote_provisioning_context.cpp @@ -71,7 +71,8 @@ PureSoftRemoteProvisioningContext::DeriveBytesFromHbk(const std::string& context return result; } -std::unique_ptr<cppbor::Map> PureSoftRemoteProvisioningContext::CreateDeviceInfo() const { +std::unique_ptr<cppbor::Map> +PureSoftRemoteProvisioningContext::CreateDeviceInfo(uint32_t csrVersion) const { auto result = std::make_unique<cppbor::Map>(cppbor::Map()); // The following placeholders show how the DeviceInfo map would be populated. @@ -101,7 +102,10 @@ std::unique_ptr<cppbor::Map> PureSoftRemoteProvisioningContext::CreateDeviceInfo if (vendor_patchlevel_) { result->add(cppbor::Tstr("vendor_patch_level"), cppbor::Uint(*vendor_patchlevel_)); } - result->add(cppbor::Tstr("version"), cppbor::Uint(2)); + // "version" field was removed from DeviceInfo in CSR v3. + if (csrVersion < 3) { + result->add(cppbor::Tstr("version"), cppbor::Uint(csrVersion)); + } result->add(cppbor::Tstr("fused"), cppbor::Uint(0)); // "software" security level is not supported, so lie and say we're a TEE @@ -137,7 +141,6 @@ PureSoftRemoteProvisioningContext::GenerateBcc(bool testMode) const { .add(CoseKey::KEY_TYPE, OCTET_KEY_PAIR) .add(CoseKey::ALGORITHM, EDDSA) .add(CoseKey::CURVE, ED25519) - .add(CoseKey::KEY_OPS, VERIFY) .add(CoseKey::PUBKEY_X, pubKey) .canonicalize(); auto sign1Payload = cppbor::Map() @@ -193,6 +196,35 @@ PureSoftRemoteProvisioningContext::GenerateHmacSha256(const cppcose::bytevec& in return *result; } +void PureSoftRemoteProvisioningContext::GetHwInfo(GetHwInfoResponse* hwInfo) const { + hwInfo->version = 3; + hwInfo->rpcAuthorName = "Google"; + hwInfo->supportedEekCurve = 2 /* CURVE_25519 */; + hwInfo->uniqueId = "default keymint"; + hwInfo->supportedNumKeysInCsr = 20; +} + +cppcose::ErrMsgOr<cppbor::Array> +PureSoftRemoteProvisioningContext::BuildCsr(const std::vector<uint8_t>& challenge, + cppbor::Array keysToSign) const { + LazyInitProdBcc(); + uint32_t csrVersion = 3; + auto deviceInfo = std::move(*CreateDeviceInfo(csrVersion)); + auto csrPayload = cppbor::Array() + .add(csrVersion) + .add("keymint" /* CertificateType */) + .add(std::move(deviceInfo)) + .add(std::move(keysToSign)); + auto signedDataPayload = cppbor::Array().add(challenge).add(cppbor::Bstr(csrPayload.encode())); + auto signedData = constructCoseSign1(devicePrivKey_, signedDataPayload.encode(), {} /* aad */); + + return cppbor::Array() + .add(1 /* version */) + .add(cppbor::Map() /* UdsCerts */) + .add(std::move(*bcc_.clone()->asArray()) /* DiceCertChain */) + .add(std::move(*signedData) /* SignedData */); +} + void PureSoftRemoteProvisioningContext::SetSystemVersion(uint32_t os_version, uint32_t os_patchlevel) { os_version_ = os_version; diff --git a/contexts/soft_keymaster_context.cpp b/contexts/soft_keymaster_context.cpp index 66c1a57..ed216b1 100644 --- a/contexts/soft_keymaster_context.cpp +++ b/contexts/soft_keymaster_context.cpp @@ -273,8 +273,8 @@ keymaster_error_t SoftKeymasterContext::ParseKeyBlob(const KeymasterKeyBlob& blo return KM_ERROR_INVALID_ARGUMENT; } auto factory = GetKeyFactory(algorithm); - return factory->LoadKey(move(key_material), additional_params, move(hw_enforced), - move(sw_enforced), key); + return factory->LoadKey(std::move(key_material), additional_params, std::move(hw_enforced), + std::move(sw_enforced), key); }; error = BuildHiddenAuthorizations(additional_params, &hidden, root_of_trust_); diff --git a/contexts/soft_keymaster_logger.cpp b/contexts/soft_keymaster_logger.cpp index 4940e45..e6b3730 100644 --- a/contexts/soft_keymaster_logger.cpp +++ b/contexts/soft_keymaster_logger.cpp @@ -17,7 +17,10 @@ #include <keymaster/soft_keymaster_logger.h> #include <stdarg.h> + +#ifndef _WIN32 #include <syslog.h> +#endif #define LOG_TAG "SoftKeymaster" #include <log/log.h> diff --git a/cppcose/cppcose.cpp b/cppcose/cppcose.cpp index 411dc01..2eb39de 100644 --- a/cppcose/cppcose.cpp +++ b/cppcose/cppcose.cpp @@ -27,6 +27,7 @@ namespace cppcose { constexpr int kP256AffinePointSize = 32; +constexpr int kP384AffinePointSize = 48; using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>; using EVP_PKEY_CTX_Ptr = bssl::UniquePtr<EVP_PKEY_CTX>; @@ -58,7 +59,7 @@ ErrMsgOr<bssl::UniquePtr<EVP_CIPHER_CTX>> aesGcmInitAndProcessAad(const bytevec& return std::move(ctx); } -ErrMsgOr<bytevec> signEcdsaDigest(const bytevec& key, const bytevec& data) { +ErrMsgOr<bytevec> signP256Digest(const bytevec& key, const bytevec& data) { auto bn = BIGNUM_Ptr(BN_bin2bn(key.data(), key.size(), nullptr)); if (bn.get() == nullptr) { return "Error creating BIGNUM"; @@ -141,19 +142,17 @@ ErrMsgOr<bytevec> ecdh(const bytevec& publicKey, const bytevec& privateKey) { return sharedSecret; } -} // namespace - -ErrMsgOr<bytevec> ecdsaCoseSignatureToDer(const bytevec& ecdsaCoseSignature) { - if (ecdsaCoseSignature.size() != 64) { +ErrMsgOr<bytevec> ecdsaCoseSignatureToDer(int point_size, const bytevec& ecdsaCoseSignature) { + if (ecdsaCoseSignature.size() != (size_t)(point_size * 2)) { return "COSE signature wrong length"; } - auto rBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data(), 32, nullptr)); + auto rBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data(), point_size, nullptr)); if (rBn.get() == nullptr) { return "Error creating BIGNUM for r"; } - auto sBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data() + 32, 32, nullptr)); + auto sBn = BIGNUM_Ptr(BN_bin2bn(ecdsaCoseSignature.data() + point_size, point_size, nullptr)); if (sBn.get() == nullptr) { return "Error creating BIGNUM for s"; } @@ -169,23 +168,58 @@ ErrMsgOr<bytevec> ecdsaCoseSignatureToDer(const bytevec& ecdsaCoseSignature) { return derSignature; } -ErrMsgOr<bytevec> ecdsaDerSignatureToCose(const bytevec& ecdsaSignature) { +ErrMsgOr<bytevec> ecdsaDerSignatureToCose(int point_size, const bytevec& ecdsaSignature) { const unsigned char* p = ecdsaSignature.data(); auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, ecdsaSignature.size())); if (sig == nullptr) { return "Error decoding DER signature"; } - bytevec ecdsaCoseSignature(64, 0); - if (BN_bn2binpad(ECDSA_SIG_get0_r(sig.get()), ecdsaCoseSignature.data(), 32) != 32) { + bytevec ecdsaCoseSignature(point_size * 2, 0); + if (BN_bn2binpad(ECDSA_SIG_get0_r(sig.get()), ecdsaCoseSignature.data(), point_size) != + point_size) { return "Error encoding r"; } - if (BN_bn2binpad(ECDSA_SIG_get0_s(sig.get()), ecdsaCoseSignature.data() + 32, 32) != 32) { + if (BN_bn2binpad(ECDSA_SIG_get0_s(sig.get()), ecdsaCoseSignature.data() + point_size, + point_size) != point_size) { return "Error encoding s"; } return ecdsaCoseSignature; } +bool verifyEcdsaDigest(int curve_nid, const bytevec& key, const bytevec& digest, + const bytevec& signature) { + const unsigned char* p = (unsigned char*)signature.data(); + auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, signature.size())); + if (sig.get() == nullptr) { + return false; + } + + auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(curve_nid)); + auto point = EC_POINT_Ptr(EC_POINT_new(group.get())); + if (EC_POINT_oct2point(group.get(), point.get(), key.data(), key.size(), nullptr) != 1) { + return false; + } + auto ecKey = EC_KEY_Ptr(EC_KEY_new()); + if (ecKey.get() == nullptr) { + return false; + } + if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) { + return false; + } + if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) { + return false; + } + + int rc = ECDSA_do_verify(digest.data(), digest.size(), sig.get(), ecKey.get()); + if (rc != 1) { + return false; + } + return true; +} + +} // namespace + ErrMsgOr<HmacSha256> generateHmacSha256(const bytevec& key, const bytevec& data) { HmacSha256 digest; unsigned int outLen; @@ -275,10 +309,10 @@ ErrMsgOr<bytevec> createECDSACoseSign1Signature(const bytevec& key, const byteve .add(aad) .add(payload) .encode(); - auto ecdsaSignature = signEcdsaDigest(key, sha256(signatureInput)); + auto ecdsaSignature = signP256Digest(key, sha256(signatureInput)); if (!ecdsaSignature) return ecdsaSignature.moveMessage(); - return ecdsaDerSignatureToCose(*ecdsaSignature); + return ecdsaDerSignatureToCose(kP256AffinePointSize, *ecdsaSignature); } ErrMsgOr<bytevec> createCoseSign1Signature(const bytevec& key, const bytevec& protectedParams, @@ -354,7 +388,8 @@ ErrMsgOr<bytevec> verifyAndParseCoseSign1(const cppbor::Array* coseSign1, auto& algorithm = parsedProtParams->asMap()->get(ALGORITHM); if (!algorithm || !algorithm->asInt() || - !(algorithm->asInt()->value() == EDDSA || algorithm->asInt()->value() == ES256)) { + !(algorithm->asInt()->value() == EDDSA || algorithm->asInt()->value() == ES256 || + algorithm->asInt()->value() == ES384)) { return "Unsupported signature algorithm"; } @@ -376,7 +411,7 @@ ErrMsgOr<bytevec> verifyAndParseCoseSign1(const cppbor::Array* coseSign1, key->getBstrValue(CoseKey::PUBKEY_X)->data())) { return "Signature verification failed"; } - } else { // P256 + } else if (algorithm->asInt()->value() == ES256) { auto key = CoseKey::parseP256(selfSigned ? payload->value() : signingCoseKey); if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty() || key->getBstrValue(CoseKey::PUBKEY_Y)->empty()) { @@ -385,13 +420,33 @@ ErrMsgOr<bytevec> verifyAndParseCoseSign1(const cppbor::Array* coseSign1, auto publicKey = key->getEcPublicKey(); if (!publicKey) return publicKey.moveMessage(); - auto ecdsaDerSignature = ecdsaCoseSignatureToDer(signature->value()); + auto ecdsaDerSignature = ecdsaCoseSignatureToDer(kP256AffinePointSize, signature->value()); + if (!ecdsaDerSignature) return ecdsaDerSignature.moveMessage(); + + // convert public key to uncompressed form by prepending 0x04 at begin. + publicKey->insert(publicKey->begin(), 0x04); + + if (!verifyEcdsaDigest(NID_X9_62_prime256v1, publicKey.moveValue(), sha256(signatureInput), + *ecdsaDerSignature)) { + return "Signature verification failed"; + } + } else { // ES384 + auto key = CoseKey::parseP384(selfSigned ? payload->value() : signingCoseKey); + if (!key || key->getBstrValue(CoseKey::PUBKEY_X)->empty() || + key->getBstrValue(CoseKey::PUBKEY_Y)->empty()) { + return "Bad signing key: " + key.moveMessage(); + } + auto publicKey = key->getEcPublicKey(); + if (!publicKey) return publicKey.moveMessage(); + + auto ecdsaDerSignature = ecdsaCoseSignatureToDer(kP384AffinePointSize, signature->value()); if (!ecdsaDerSignature) return ecdsaDerSignature.moveMessage(); // convert public key to uncompressed form by prepending 0x04 at begin. publicKey->insert(publicKey->begin(), 0x04); - if (!verifyEcdsaDigest(publicKey.moveValue(), sha256(signatureInput), *ecdsaDerSignature)) { + if (!verifyEcdsaDigest(NID_secp384r1, publicKey.moveValue(), sha384(signatureInput), + *ecdsaDerSignature)) { return "Signature verification failed"; } } @@ -708,34 +763,13 @@ bytevec sha256(const bytevec& data) { return ret; } -bool verifyEcdsaDigest(const bytevec& key, const bytevec& digest, const bytevec& signature) { - const unsigned char* p = (unsigned char*)signature.data(); - auto sig = ECDSA_SIG_Ptr(d2i_ECDSA_SIG(nullptr, &p, signature.size())); - if (sig.get() == nullptr) { - return false; - } - - auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); - auto point = EC_POINT_Ptr(EC_POINT_new(group.get())); - if (EC_POINT_oct2point(group.get(), point.get(), key.data(), key.size(), nullptr) != 1) { - return false; - } - auto ecKey = EC_KEY_Ptr(EC_KEY_new()); - if (ecKey.get() == nullptr) { - return false; - } - if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) { - return false; - } - if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) { - return false; - } - - int rc = ECDSA_do_verify(digest.data(), digest.size(), sig.get(), ecKey.get()); - if (rc != 1) { - return false; - } - return true; +bytevec sha384(const bytevec& data) { + bytevec ret(SHA384_DIGEST_LENGTH); + SHA512_CTX ctx; + SHA384_Init(&ctx); + SHA384_Update(&ctx, data.data(), data.size()); + SHA384_Final((unsigned char*)ret.data(), &ctx); + return ret; } } // namespace cppcose diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp new file mode 100644 index 0000000..75af40f --- /dev/null +++ b/fuzzer/Android.bp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "system_keymaster_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["system_keymaster_license"], +} + +cc_defaults { + name: "libkeymaster4_fuzzer_defaults", + static_libs: [ + "libbase", + "liblog", + "libkeymaster4", + "libutils", + ], + shared_libs: [ + "android.hardware.keymaster@4.0", + "libcrypto", + "libhidlbase", + "libkeymaster_messages", + "libcutils", + "libkeymaster_portable", + "libpuresoftkeymasterdevice", + "libkeymaster4support", + "libvndksupport", + ], + include_dirs: [ + "system/keymaster/legacy_support", + ], + fuzz_config: { + cc: [ + "android-media-fuzzing-reports@google.com", + ], + componentid: 533764, + hotlists: [ + "4593311", + ], + description: "The fuzzer targets the APIs of libkeymaster4", + vector: "local_no_privileges_required", + service_privilege: "privileged", + users: "multi_user", + fuzzed_code_usage: "shipped", + }, +} + +cc_fuzz { + name: "k4_AndroidKeymaster4Device_fuzzer", + defaults: [ + "libkeymaster4_fuzzer_defaults", + ], + srcs: [ + "k4_AndroidKeymaster4Device_fuzzer.cpp", + ], +} + +cc_fuzz { + name: "k4_keymaster_configuration_fuzzer", + defaults: [ + "libkeymaster4_fuzzer_defaults", + ], + srcs: [ + "k4_keymaster_configuration_fuzzer.cpp", + ], +} diff --git a/fuzzer/README.md b/fuzzer/README.md new file mode 100644 index 0000000..04f972c --- /dev/null +++ b/fuzzer/README.md @@ -0,0 +1,56 @@ +# Fuzzers for libkeymaster4 + +## Plugin Design Considerations +The fuzzer plugins for libkeymaster4 are designed based on the understanding of the +source code and try to achieve the following: + +##### Maximize code coverage +The configuration parameters are not hardcoded, but instead selected based on +incoming data. This ensures more code paths are reached by the fuzzers. + +libkeymaster4 supports the following parameters: +1. Security Level (parameter name: `securityLevel`) +2. Padding Mode (parameter name: `paddingMode`) +3. Digest (parameter name: `digest`) +4. Key Format (parameter name: `keyFormat`) +5. Key Purpose (parameter name: `keyPurpose`) + +| Parameter| Valid Values| Configured Value| +|------------- |-------------| ----- | +| `securityLevel` | 0.`SecurityLevel::SOFTWARE` 1.`SecurityLevel::TRUSTED_ENVIRONMENT` 2.`SecurityLevel::STRONGBOX`| Value obtained from FuzzedDataProvider| +| `paddingMode` | 0.`PaddingMode::NONE` 1.`PaddingMode::RSA_OAEP` 2.`PaddingMode::RSA_PSS` 3. `PaddingMode::RSA_PKCS1_1_5_ENCRYPT` 4.`PaddingMode::RSA_PKCS1_1_5_SIGN` 5.`PaddingMode::PKCS7`| Value obtained from FuzzedDataProvider| +| `digest` | 1. `Digest::NONE` 2.`Digest::MD5` 3.`Digest::SHA1` 4.`Digest::SHA_2_224` 5.`Digest::SHA_2_256` 6.`Digest::SHA_2_384` 7.`Digest::SHA_2_512`| Value obtained from FuzzedDataProvider| +| `keyFormat` | 1. `KeyFormat::X509` 2.`KeyFormat::PKCS8` 3.`KeyFormat::RAW`| Value obtained from FuzzedDataProvider| +| `keyPurpose` | 1. `KeyPurpose::ENCRYPT` 2.`KeyPurpose::DECRYPT` 3.`KeyPurpose::SIGN` 4. `KeyPurpose::VERIFY` 5. `KeyPurpose::WRAP_KEY`| Value obtained from FuzzedDataProvider| + +This also ensures that the plugins are always deterministic for any given input. + +##### Maximize utilization of input data +The plugins feed the entire input data to the module. +This ensures that the plugins tolerate any kind of input (empty, huge, +malformed, etc) and dont `exit()` on any input and thereby increasing the +chance of identifying vulnerabilities. + +## Build + +This describes steps to build k4_AndroidKeymaster4Device_fuzzer and k4_keymaster_configuration_fuzzer binaries + +### Android + +#### Steps to build +Build the fuzzer +``` + $ mm k4_AndroidKeymaster4Device_fuzzer + $ mm k4_keymaster_configuration_fuzzer +``` +#### Steps to run +To run on device +``` + $ adb sync data + $ adb shell /data/fuzz/${TARGET_ARCH}/k4_AndroidKeymaster4Device_fuzzer/k4_AndroidKeymaster4Device_fuzzer + $ adb shell /data/fuzz/${TARGET_ARCH}/k4_keymaster_configuration_fuzzer/k4_keymaster_configuration_fuzzer +``` + +## References: + * http://llvm.org/docs/LibFuzzer.html + * https://github.com/google/oss-fuzz diff --git a/fuzzer/k4_AndroidKeymaster4Device_fuzzer.cpp b/fuzzer/k4_AndroidKeymaster4Device_fuzzer.cpp new file mode 100644 index 0000000..be60b75 --- /dev/null +++ b/fuzzer/k4_AndroidKeymaster4Device_fuzzer.cpp @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <AndroidKeymaster4Device.h> +#include <android/hardware/keymaster/4.0/IKeymasterDevice.h> +#include <fuzzer/FuzzedDataProvider.h> +#include <keymasterV4_0/authorization_set.h> + +namespace keymaster::V4_0::ng::fuzzer { + +using ::android::hardware::hidl_string; +using ::android::hardware::keymaster::V4_0::AuthorizationSet; +using ::android::hardware::keymaster::V4_0::AuthorizationSetBuilder; +using ::android::hardware::keymaster::V4_0::Digest; +using ::android::hardware::keymaster::V4_0::KeyFormat; +using ::android::hardware::keymaster::V4_0::KeyPurpose; +using ::android::hardware::keymaster::V4_0::PaddingMode; + +constexpr SecurityLevel kSecurityLevel[] = { + SecurityLevel::SOFTWARE, + SecurityLevel::TRUSTED_ENVIRONMENT, + SecurityLevel::STRONGBOX, +}; + +constexpr PaddingMode kPaddingMode[] = { + PaddingMode::NONE, + PaddingMode::RSA_OAEP, + PaddingMode::RSA_PSS, + PaddingMode::RSA_PKCS1_1_5_ENCRYPT, + PaddingMode::RSA_PKCS1_1_5_SIGN, + PaddingMode::PKCS7, +}; + +constexpr Digest kDigest[] = { + Digest::NONE, Digest::MD5, Digest::SHA1, Digest::SHA_2_224, + Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512, +}; + +constexpr KeyFormat kKeyFormat[] = { + KeyFormat::X509, + KeyFormat::PKCS8, + KeyFormat::RAW, +}; + +constexpr KeyPurpose kKeyPurpose[] = { + KeyPurpose::ENCRYPT, KeyPurpose::DECRYPT, KeyPurpose::SIGN, + KeyPurpose::VERIFY, KeyPurpose::WRAP_KEY, +}; + +constexpr uint32_t kRSAKeySize[] = {1024, 2048, 3072, 4096}; +constexpr uint32_t kECCKeySize[] = {224, 256, 384, 521}; +constexpr size_t kMinBytes = 0; +constexpr size_t kMaxBytes = 100; + +class KeyMaster4DeviceFuzzer { + public: + bool init(const uint8_t* data, size_t size); + void process(); + + private: + AuthorizationSet getAuthorizationSet(); + sp<IKeymasterDevice> mKeymaster = nullptr; + std::unique_ptr<FuzzedDataProvider> mFdp = nullptr; +}; + +AuthorizationSet KeyMaster4DeviceFuzzer::getAuthorizationSet() { + auto keyMasterFunction = mFdp->PickValueInArray< + const std::function<android::hardware::keymaster::V4_0::AuthorizationSet()>>({ + [&]() { + return AuthorizationSetBuilder() + .RsaSigningKey(mFdp->PickValueInArray(kRSAKeySize), + mFdp->ConsumeIntegral<uint32_t>()) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .EcdsaKey(mFdp->PickValueInArray(kECCKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .AesKey(mFdp->PickValueInArray(kECCKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .TripleDesKey(mFdp->PickValueInArray(kRSAKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .HmacKey(mFdp->PickValueInArray(kRSAKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .RsaEncryptionKey(mFdp->PickValueInArray(kRSAKeySize), + mFdp->ConsumeIntegral<uint64_t>()) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .EcdsaSigningKey(mFdp->PickValueInArray(kRSAKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .AesEncryptionKey(mFdp->PickValueInArray(kECCKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .TripleDesEncryptionKey(mFdp->PickValueInArray(kRSAKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .RsaKey(mFdp->PickValueInArray(kRSAKeySize), mFdp->ConsumeIntegral<uint64_t>()) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + }); + return keyMasterFunction(); +} + +bool KeyMaster4DeviceFuzzer::init(const uint8_t* data, size_t size) { + mFdp = std::make_unique<FuzzedDataProvider>(data, size); + mKeymaster = CreateKeymasterDevice(mFdp->PickValueInArray(kSecurityLevel)); + if (!mKeymaster) { + return false; + } + return true; +} + +void KeyMaster4DeviceFuzzer::process() { + std::vector<uint8_t> dataVec = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->addRngEntropy(dataVec); + + hidl_vec<uint8_t> keyBlob = {}; + mKeymaster->generateKey(getAuthorizationSet().hidl_data(), + [&]([[maybe_unused]] ErrorCode hidlError, + const hidl_vec<uint8_t>& hidlKeyBlob, + [[maybe_unused]] const KeyCharacteristics& hidlKeyCharacteristics) { + keyBlob = hidlKeyBlob; + }); + + mKeymaster->attestKey( + keyBlob, getAuthorizationSet().hidl_data(), + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<hidl_vec<uint8_t>>& hidlCertificateChain) {}); + + mKeymaster->upgradeKey(keyBlob, hidl_vec<KeyParameter>(), + [&]([[maybe_unused]] ErrorCode error, + [[maybe_unused]] const hidl_vec<uint8_t>& upgraded_blob) {}); + + std::vector<uint8_t> clientId = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + std::vector<uint8_t> appData = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->getKeyCharacteristics( + keyBlob, clientId, appData, + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const KeyCharacteristics& hidlKeyCharacteristics) {}); + + KeyFormat keyFormat = mFdp->PickValueInArray(kKeyFormat); + std::vector<uint8_t> keyData; + keyData = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + ErrorCode importKeyError; + if (mKeymaster + ->importKey(getAuthorizationSet().hidl_data(), keyFormat, keyData, + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlKeyBlob, + [[maybe_unused]] const KeyCharacteristics& hidlKeyCharacteristics) { + importKeyError = hidlError; + }) + .isOk()) { + if (importKeyError == ErrorCode::OK) { + abort(); + } + } + + std::vector<uint8_t> wrappedKey, wrappingKey, maskingKey; + wrappedKey = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + wrappingKey = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + maskingKey = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + uint64_t passwordSid = mFdp->ConsumeIntegral<uint64_t>(); + uint64_t biometricSid = mFdp->ConsumeIntegral<uint64_t>(); + mKeymaster->importWrappedKey( + wrappedKey, wrappingKey, maskingKey, getAuthorizationSet().hidl_data(), passwordSid, + biometricSid, + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlKeyBlob, + [[maybe_unused]] const KeyCharacteristics& hidlKeyCharacteristics) {}); + + std::vector<uint8_t> keyBlobExportKey = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->exportKey(keyFormat, keyBlobExportKey, clientId, appData, + [&]([[maybe_unused]] ErrorCode hidlErrorCode, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlKeyMaterial) {}); + + KeyPurpose keyPurpose = mFdp->PickValueInArray(kKeyPurpose); + mKeymaster->begin(keyPurpose, keyBlob, getAuthorizationSet().hidl_data(), HardwareAuthToken(), + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<KeyParameter>& hidlOutParams, + [[maybe_unused]] uint64_t hidlOpHandle) {}); + + uint64_t operationHandle = mFdp->ConsumeIntegral<uint64_t>(); + std::vector<uint8_t> input = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->update(operationHandle, getAuthorizationSet().hidl_data(), input, + HardwareAuthToken(), VerificationToken(), + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] uint32_t hidlInputConsumed, + [[maybe_unused]] const hidl_vec<KeyParameter>& hidlOutParams, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlOutput) {}); + + std::vector<uint8_t> signature = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->finish(operationHandle, getAuthorizationSet().hidl_data(), input, signature, + HardwareAuthToken(), VerificationToken(), + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<KeyParameter>& hidlOutParams, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlOutput) {}); + + mKeymaster->deleteKey(keyBlob); + mKeymaster->deleteAllKeys(); + mKeymaster->abort(mFdp->ConsumeIntegral<uint64_t>()); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + KeyMaster4DeviceFuzzer km4DeviceFuzzer; + if (km4DeviceFuzzer.init(data, size)) { + km4DeviceFuzzer.process(); + } + return 0; +} +} // namespace keymaster::V4_0::ng::fuzzer diff --git a/fuzzer/k4_keymaster_configuration_fuzzer.cpp b/fuzzer/k4_keymaster_configuration_fuzzer.cpp new file mode 100644 index 0000000..06403bb --- /dev/null +++ b/fuzzer/k4_keymaster_configuration_fuzzer.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include <fuzzer/FuzzedDataProvider.h> +#include <keymaster/keymaster_configuration.h> + +constexpr size_t kMaxCharacters = 100; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + FuzzedDataProvider fdp(data, size); + keymaster::GetOsVersion(fdp.ConsumeRandomLengthString(kMaxCharacters).c_str()); + keymaster::GetOsPatchlevel(fdp.ConsumeRandomLengthString(kMaxCharacters).c_str()); + + return 0; +} diff --git a/include/keymaster/android_keymaster.h b/include/keymaster/android_keymaster.h index 6c3acc5..1e51def 100644 --- a/include/keymaster/android_keymaster.h +++ b/include/keymaster/android_keymaster.h @@ -16,6 +16,7 @@ #pragma once +#include "android_keymaster_messages.h" #include <keymaster/android_keymaster_messages.h> #include <keymaster/authorization_set.h> @@ -75,6 +76,7 @@ class AndroidKeymaster { void GenerateKey(const GenerateKeyRequest& request, GenerateKeyResponse* response); void GenerateRkpKey(const GenerateRkpKeyRequest& request, GenerateRkpKeyResponse* response); void GenerateCsr(const GenerateCsrRequest& request, GenerateCsrResponse* response); + void GenerateCsrV2(const GenerateCsrV2Request& request, GenerateCsrV2Response* response); void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request, GetKeyCharacteristicsResponse* response); void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response); @@ -100,6 +102,9 @@ class AndroidKeymaster { ConfigureVerifiedBootInfoResponse ConfigureVerifiedBootInfo(const ConfigureVerifiedBootInfoRequest& request); GetRootOfTrustResponse GetRootOfTrust(const GetRootOfTrustRequest& request); + GetHwInfoResponse GetHwInfo(); + SetAttestationIdsResponse SetAttestationIds(const SetAttestationIdsRequest& request); + SetAttestationIdsKM3Response SetAttestationIdsKM3(const SetAttestationIdsKM3Request& request); bool has_operation(keymaster_operation_handle_t op_handle) const; diff --git a/include/keymaster/android_keymaster_messages.h b/include/keymaster/android_keymaster_messages.h index 6e38860..01ff5ff 100644 --- a/include/keymaster/android_keymaster_messages.h +++ b/include/keymaster/android_keymaster_messages.h @@ -23,6 +23,7 @@ #include <string> #include <string_view> +#include <utility> #include <vector> #include <keymaster/android_keymaster_utils.h> @@ -69,6 +70,10 @@ enum AndroidKeymasterCommand : uint32_t { CONFIGURE_BOOT_PATCHLEVEL = 33, CONFIGURE_VERIFIED_BOOT_INFO = 34, GET_ROOT_OF_TRUST = 35, + GET_HW_INFO = 36, + GENERATE_CSR_V2 = 37, + SET_ATTESTATION_IDS = 38, + SET_ATTESTATION_IDS_KM3 = 39, }; /** @@ -131,6 +136,7 @@ inline int32_t MessageVersion(KmVersion version, uint32_t /* km_date */ = 0) { return 3; case KmVersion::KEYMINT_1: case KmVersion::KEYMINT_2: + case KmVersion::KEYMINT_3: return 4; } return kInvalidMessageVersion; @@ -427,6 +433,33 @@ struct GenerateCsrResponse : public KeymasterResponse { KeymasterBlob protected_data_blob; }; +struct GenerateCsrV2Request : public KeymasterMessage { + explicit GenerateCsrV2Request(int32_t ver) : KeymasterMessage(ver) {} + + ~GenerateCsrV2Request() override { delete[] keys_to_sign_array; } + + size_t SerializedSize() const override; + uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; + bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override; + bool InitKeysToSign(uint32_t count); + void SetKeyToSign(uint32_t index, const void* data, size_t length); + void SetChallenge(const void* data, size_t length); + + uint32_t num_keys = 0; + KeymasterBlob* keys_to_sign_array = nullptr; + KeymasterBlob challenge; +}; + +struct GenerateCsrV2Response : public KeymasterResponse { + explicit GenerateCsrV2Response(int32_t ver) : KeymasterResponse(ver) {} + + size_t NonErrorSerializedSize() const override; + uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override; + bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override; + + KeymasterBlob csr; +}; + struct GetKeyCharacteristicsRequest : public KeymasterMessage { explicit GetKeyCharacteristicsRequest(int32_t ver) : KeymasterMessage(ver) { key_blob.key_material = nullptr; @@ -768,11 +801,11 @@ using ConfigureResponse = EmptyKeymasterResponse; struct HmacSharingParameters : public Serializable { HmacSharingParameters() : seed({}) { memset(nonce, 0, sizeof(nonce)); } HmacSharingParameters(HmacSharingParameters&& other) { - seed = move(other.seed); + seed = std::move(other.seed); memcpy(nonce, other.nonce, sizeof(nonce)); } - void SetSeed(KeymasterBlob&& value) { seed = move(value); } + void SetSeed(KeymasterBlob&& value) { seed = std::move(value); } size_t SerializedSize() const override; uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override; @@ -808,9 +841,9 @@ struct GetHmacSharingParametersRequest : public EmptyKeymasterRequest { struct GetHmacSharingParametersResponse : public KeymasterResponse { explicit GetHmacSharingParametersResponse(int32_t ver) : KeymasterResponse(ver) {} GetHmacSharingParametersResponse(GetHmacSharingParametersResponse&& other) - : KeymasterResponse(other.message_version), params(move(other.params)) {} + : KeymasterResponse(other.message_version), params(std::move(other.params)) {} - void SetSeed(KeymasterBlob&& seed_data) { params.SetSeed(move(seed_data)); } + void SetSeed(KeymasterBlob&& seed_data) { params.SetSeed(std::move(seed_data)); } size_t NonErrorSerializedSize() const override { return params.SerializedSize(); } uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override { @@ -841,7 +874,7 @@ struct ComputeSharedHmacResponse : public KeymasterResponse { explicit ComputeSharedHmacResponse(int32_t ver) : KeymasterResponse(ver) {} ComputeSharedHmacResponse(ComputeSharedHmacResponse&& other) : KeymasterResponse(other.message_version) { - sharing_check = move(other.sharing_check); + sharing_check = std::move(other.sharing_check); } size_t NonErrorSerializedSize() const override; @@ -901,7 +934,7 @@ struct HardwareAuthToken : public Serializable { authenticator_id = other.authenticator_id; authenticator_type = other.authenticator_type; timestamp = other.timestamp; - mac = move(other.mac); + mac = std::move(other.mac); } size_t SerializedSize() const override; @@ -921,9 +954,9 @@ struct VerificationToken : public Serializable { VerificationToken(VerificationToken&& other) { challenge = other.challenge; timestamp = other.timestamp; - parameters_verified = move(other.parameters_verified); + parameters_verified = std::move(other.parameters_verified); security_level = other.security_level; - mac = move(other.mac); + mac = std::move(other.mac); } size_t SerializedSize() const override; @@ -996,7 +1029,7 @@ struct EarlyBootEndedResponse : public KeymasterResponse { struct DeviceLockedRequest : public KeymasterMessage { explicit DeviceLockedRequest(int32_t ver) : KeymasterMessage(ver) {} explicit DeviceLockedRequest(int32_t ver, bool passwordOnly_, VerificationToken&& token_) - : KeymasterMessage(ver), passwordOnly(passwordOnly_), token(move(token_)) {} + : KeymasterMessage(ver), passwordOnly(passwordOnly_), token(std::move(token_)) {} size_t SerializedSize() const override { return 1; } uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { @@ -1059,7 +1092,7 @@ struct TimestampToken : public Serializable { challenge = other.challenge; timestamp = other.timestamp; security_level = other.security_level; - mac = move(other.mac); + mac = std::move(other.mac); } size_t SerializedSize() const override { return sizeof(challenge) + sizeof(timestamp) + sizeof(security_level) + @@ -1153,6 +1186,29 @@ struct SetAttestationIdsRequest : public KeymasterMessage { using SetAttestationIdsResponse = EmptyKeymasterResponse; +struct SetAttestationIdsKM3Request : public KeymasterMessage { + explicit SetAttestationIdsKM3Request(int32_t ver) : KeymasterMessage(ver), base(ver) {} + size_t SerializedSize() const override { + return base.SerializedSize() // + + second_imei.SerializedSize(); + } + + uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override { + buf = base.Serialize(buf, end); + return second_imei.Serialize(buf, end); + } + + bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override { + return base.Deserialize(buf_ptr, end) // + && second_imei.Deserialize(buf_ptr, end); // + } + + SetAttestationIdsRequest base; + Buffer second_imei; +}; + +using SetAttestationIdsKM3Response = EmptyKeymasterResponse; + struct ConfigureVendorPatchlevelRequest : public KeymasterMessage { explicit ConfigureVendorPatchlevelRequest(int32_t ver) : KeymasterMessage(ver) {} @@ -1249,4 +1305,38 @@ struct GetRootOfTrustResponse : public KeymasterResponse { std::vector<uint8_t> rootOfTrust; }; +struct GetHwInfoRequest : public EmptyKeymasterRequest { + explicit GetHwInfoRequest(int32_t ver) : EmptyKeymasterRequest(ver) {} +}; + +struct GetHwInfoResponse : public KeymasterResponse { + explicit GetHwInfoResponse(int32_t ver) : KeymasterResponse(ver) {} + + size_t NonErrorSerializedSize() const override { + return sizeof(version) + sizeof(uint32_t) + rpcAuthorName.size() + + sizeof(supportedEekCurve) + sizeof(uint32_t) + uniqueId.size() + + sizeof(supportedNumKeysInCsr); + } + uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t* end) const override { + buf = append_uint32_to_buf(buf, end, version); + buf = append_collection_to_buf(buf, end, rpcAuthorName); + buf = append_uint32_to_buf(buf, end, supportedEekCurve); + buf = append_collection_to_buf(buf, end, uniqueId); + return append_uint32_to_buf(buf, end, supportedNumKeysInCsr); + } + bool NonErrorDeserialize(const uint8_t** buf_ptr, const uint8_t* end) override { + return copy_uint32_from_buf(buf_ptr, end, &version) && + copy_collection_from_buf(buf_ptr, end, &rpcAuthorName) && + copy_uint32_from_buf(buf_ptr, end, &supportedEekCurve) && + copy_collection_from_buf(buf_ptr, end, &uniqueId) && + copy_uint32_from_buf(buf_ptr, end, &supportedNumKeysInCsr); + } + + uint32_t version; + std::string rpcAuthorName; + uint32_t supportedEekCurve; + std::string uniqueId; + uint32_t supportedNumKeysInCsr; +}; + } // namespace keymaster diff --git a/include/keymaster/android_keymaster_utils.h b/include/keymaster/android_keymaster_utils.h index 324287a..519bd82 100644 --- a/include/keymaster/android_keymaster_utils.h +++ b/include/keymaster/android_keymaster_utils.h @@ -16,6 +16,8 @@ #pragma once +#include <utility> + #include <stdint.h> #include <time.h> // for time_t. @@ -253,7 +255,7 @@ keymaster_error_t EcCurveToKeySize(keymaster_ec_curve_t curve, uint32_t* key_siz template <class F> class final_action { public: - explicit final_action(F f) : f_(move(f)) {} + explicit final_action(F f) : f_(std::move(f)) {} ~final_action() { f_(); } private: @@ -280,7 +282,8 @@ struct CertificateChain : public keymaster_cert_chain_t { } } - CertificateChain(CertificateChain&& other) : keymaster_cert_chain_t{} { *this = move(other); } + CertificateChain(CertificateChain&& other) : keymaster_cert_chain_t{} + { *this = std::move(other); } ~CertificateChain() { Clear(); } diff --git a/include/keymaster/authorization_set.h b/include/keymaster/authorization_set.h index ce3ef75..6fff0d3 100644 --- a/include/keymaster/authorization_set.h +++ b/include/keymaster/authorization_set.h @@ -16,6 +16,8 @@ #pragma once +#include <utility> + #include <keymaster/UniquePtr.h> #include <hardware/keymaster_defs.h> @@ -692,18 +694,18 @@ class AuthProxy { : hw_enforced_(hw_enforced), sw_enforced_(sw_enforced) {} template <typename... ARGS> bool Contains(ARGS&&... args) const { - return hw_enforced_.Contains(forward<ARGS>(args)...) || - sw_enforced_.Contains(forward<ARGS>(args)...); + return hw_enforced_.Contains(std::forward<ARGS>(args)...) || + sw_enforced_.Contains(std::forward<ARGS>(args)...); } template <typename... ARGS> bool GetTagValue(ARGS&&... args) const { - return hw_enforced_.GetTagValue(forward<ARGS>(args)...) || - sw_enforced_.GetTagValue(forward<ARGS>(args)...); + return hw_enforced_.GetTagValue(std::forward<ARGS>(args)...) || + sw_enforced_.GetTagValue(std::forward<ARGS>(args)...); } template <typename... ARGS> bool GetTagCount(ARGS&&... args) const { - return hw_enforced_.GetTagCount(forward<ARGS>(args)...) || - sw_enforced_.GetTagCount(forward<ARGS>(args)...); + return hw_enforced_.GetTagCount(std::forward<ARGS>(args)...) || + sw_enforced_.GetTagCount(std::forward<ARGS>(args)...); } AuthProxyIterator begin() const { return AuthProxyIterator(hw_enforced_, sw_enforced_); } diff --git a/include/keymaster/contexts/pure_soft_remote_provisioning_context.h b/include/keymaster/contexts/pure_soft_remote_provisioning_context.h index 90cd79f..7d7e51e 100644 --- a/include/keymaster/contexts/pure_soft_remote_provisioning_context.h +++ b/include/keymaster/contexts/pure_soft_remote_provisioning_context.h @@ -38,13 +38,16 @@ class PureSoftRemoteProvisioningContext : public RemoteProvisioningContext { ~PureSoftRemoteProvisioningContext() override = default; std::vector<uint8_t> DeriveBytesFromHbk(const std::string& context, size_t numBytes) const override; - std::unique_ptr<cppbor::Map> CreateDeviceInfo() const override; + std::unique_ptr<cppbor::Map> CreateDeviceInfo(uint32_t csrVersion) const override; cppcose::ErrMsgOr<std::vector<uint8_t>> BuildProtectedDataPayload(bool isTestMode, // const std::vector<uint8_t>& macKey, // const std::vector<uint8_t>& aad) const override; std::optional<cppcose::HmacSha256> GenerateHmacSha256(const cppcose::bytevec& input) const override; + void GetHwInfo(GetHwInfoResponse* hwInfo) const override; + cppcose::ErrMsgOr<cppbor::Array> BuildCsr(const std::vector<uint8_t>& challenge, + cppbor::Array keysToSign) const override; void SetSystemVersion(uint32_t os_version, uint32_t os_patchlevel); void SetVendorPatchlevel(uint32_t vendor_patchlevel); diff --git a/include/keymaster/cppcose/cppcose.h b/include/keymaster/cppcose/cppcose.h index c000ebe..fa5916f 100644 --- a/include/keymaster/cppcose/cppcose.h +++ b/include/keymaster/cppcose/cppcose.h @@ -81,9 +81,10 @@ enum CoseKeyAlgorithm : int { ES256 = -7, // ECDSA with SHA-256 EDDSA = -8, ECDH_ES_HKDF_256 = -25, + ES384 = -35, // ECDSA with SHA-384 }; -enum CoseKeyCurve : int { P256 = 1, X25519 = 4, ED25519 = 6 }; +enum CoseKeyCurve : int { P256 = 1, P384 = 2, X25519 = 4, ED25519 = 6 }; enum CoseKeyType : int { OCTET_KEY_PAIR = 1, EC2 = 2, SYMMETRIC_KEY = 4 }; enum CoseKeyOps : int { SIGN = 1, VERIFY = 2, ENCRYPT = 3, DECRYPT = 4 }; @@ -213,6 +214,20 @@ class CoseKey { return key; } + static ErrMsgOr<CoseKey> parseP384(const bytevec& coseKey) { + auto key = parse(coseKey, EC2, ES384, P384); + if (!key) return key; + + auto& pubkey_x = key->getMap().get(PUBKEY_X); + auto& pubkey_y = key->getMap().get(PUBKEY_Y); + if (!pubkey_x || !pubkey_y || !pubkey_x->asBstr() || !pubkey_y->asBstr() || + pubkey_x->asBstr()->value().size() != 48 || pubkey_y->asBstr()->value().size() != 48) { + return "Invalid P384 public key"; + } + + return key; + } + static ErrMsgOr<bytevec> getEcPublicKey(const bytevec& pubX, const bytevec& pubY) { if (pubX.empty() || pubY.empty()) { return "Missing input parameters"; @@ -285,9 +300,6 @@ ErrMsgOr<cppbor::Array> constructECDSACoseSign1(const bytevec& key, cppbor::Map extraProtectedFields, const bytevec& payload, const bytevec& aad); -ErrMsgOr<bytevec> ecdsaCoseSignatureToDer(const bytevec& ecdsaCoseSignature); - -ErrMsgOr<bytevec> ecdsaDerSignatureToCose(const bytevec& ecdsaSignature); /** * Verify and parse a COSE_Sign1 message, returning the payload. * @@ -320,8 +332,8 @@ ErrMsgOr<bytevec> x25519_HKDF_DeriveKey(const bytevec& senderPubKey, const bytev const bytevec& recipientPubKey, bool senderIsA); ErrMsgOr<bytevec> ECDH_HKDF_DeriveKey(const bytevec& pubKeyA, const bytevec& privKeyA, const bytevec& pubKeyB, bool senderIsA); -bool verifyEcdsaDigest(const bytevec& key, const bytevec& digest, const bytevec& signature); bytevec sha256(const bytevec& data); +bytevec sha384(const bytevec& data); ErrMsgOr<bytevec /* ciphertextWithTag */> aesGcmEncrypt(const bytevec& key, const bytevec& nonce, const bytevec& aad, const bytevec& plaintext); diff --git a/include/keymaster/key.h b/include/keymaster/key.h index eb0f026..2653e24 100644 --- a/include/keymaster/key.h +++ b/include/keymaster/key.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_KEY_H_ #define SYSTEM_KEYMASTER_KEY_H_ +#include <utility> + #include <assert.h> #include <hardware/keymaster_defs.h> @@ -53,9 +55,9 @@ class Key { // Methods to move data out of the key. These could be overloads of the methods above, with ref // qualifiers, but naming them differently makes it harder to accidentally make a temporary copy // when we mean to move. - AuthorizationSet&& hw_enforced_move() { return move(hw_enforced_); } - AuthorizationSet&& sw_enforced_move() { return move(sw_enforced_); } - KeymasterKeyBlob&& key_material_move() { return move(key_material_); } + AuthorizationSet&& hw_enforced_move() { return std::move(hw_enforced_); } + AuthorizationSet&& sw_enforced_move() { return std::move(sw_enforced_); } + KeymasterKeyBlob&& key_material_move() { return std::move(key_material_); } const KeyFactory* key_factory() const { return key_factory_; } const KeyFactory*& key_factory() { return key_factory_; } @@ -66,7 +68,7 @@ class Key { protected: Key(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, const KeyFactory* key_factory) - : hw_enforced_(move(hw_enforced)), sw_enforced_(move(sw_enforced)), + : hw_enforced_(std::move(hw_enforced)), sw_enforced_(std::move(sw_enforced)), key_factory_(key_factory) {} protected: diff --git a/include/keymaster/keymaster_context.h b/include/keymaster/keymaster_context.h index 8c4bb57..f4d01dc 100644 --- a/include/keymaster/keymaster_context.h +++ b/include/keymaster/keymaster_context.h @@ -24,6 +24,7 @@ #include <hardware/keymaster_defs.h> +#include <keymaster/android_keymaster_messages.h> #include <keymaster/android_keymaster_utils.h> #include <keymaster/keymaster_enforcement.h> #include <keymaster/km_version.h> @@ -272,6 +273,24 @@ class KeymasterContext { */ virtual std::optional<uint32_t> GetBootPatchlevel() const { return std::nullopt; } + /** + * Sets attestation IDs for the implementation. On physical devices (as opposed to emulators) + * attestation IDs should only be set during provisioning process. + */ + virtual keymaster_error_t SetAttestationIds(const SetAttestationIdsRequest& /* request */) { + return KM_ERROR_UNIMPLEMENTED; + } + + /** + * Sets KM3 attestation IDs for the implementation. On physical + * devices (as opposed to emulators) attestation ID should only be set + * during provisioning process. + */ + virtual keymaster_error_t + SetAttestationIdsKM3(const SetAttestationIdsKM3Request& /* request */) { + return KM_ERROR_UNIMPLEMENTED; + } + private: // Uncopyable. KeymasterContext(const KeymasterContext&); diff --git a/include/keymaster/keymaster_tags.h b/include/keymaster/keymaster_tags.h index f620dfb..29eae7c 100644 --- a/include/keymaster/keymaster_tags.h +++ b/include/keymaster/keymaster_tags.h @@ -108,7 +108,7 @@ template <keymaster_tag_type_t tag_type, keymaster_tag_t tag> class TypedTag { // NOLINTNEXTLINE(google-explicit-constructor) inline operator keymaster_tag_t() { return tag; } // NOLINTNEXTLINE(google-runtime-int) - inline long masked_tag() { return static_cast<long>(keymaster_tag_mask_type(tag)); } + inline int masked_tag() { return static_cast<int>(keymaster_tag_mask_type(tag)); } }; template <keymaster_tag_type_t tag_type, keymaster_tag_t tag, typename KeymasterEnum> @@ -126,7 +126,7 @@ class TypedEnumTag { // NOLINTNEXTLINE(google-explicit-constructor) inline operator keymaster_tag_t() { return tag; } // NOLINTNEXTLINE(google-runtime-int) - inline long masked_tag() { return static_cast<long>(keymaster_tag_mask_type(tag)); } + inline int masked_tag() { return static_cast<int>(keymaster_tag_mask_type(tag)); } }; #ifdef KEYMASTER_NAME_TAGS @@ -180,6 +180,7 @@ DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_DEVICE); DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_PRODUCT); DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SERIAL); DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_IMEI); +DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_SECOND_IMEI); DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MEID); DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MANUFACTURER); DECLARE_KEYMASTER_TAG(KM_BYTES, TAG_ATTESTATION_ID_MODEL); diff --git a/include/keymaster/km_openssl/aes_key.h b/include/keymaster/km_openssl/aes_key.h index f00a665..95cfc5f 100644 --- a/include/keymaster/km_openssl/aes_key.h +++ b/include/keymaster/km_openssl/aes_key.h @@ -16,6 +16,8 @@ #pragma once +#include <utility> + #include <openssl/aes.h> #include "symmetric_key.h" @@ -52,7 +54,8 @@ class AesKey : public SymmetricKey { public: AesKey(KeymasterKeyBlob&& key_material, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, const KeyFactory* key_factory) - : SymmetricKey(move(key_material), move(hw_enforced), move(sw_enforced), key_factory) {} + : SymmetricKey(std::move(key_material), std::move(hw_enforced), std::move(sw_enforced), + key_factory) {} }; } // namespace keymaster diff --git a/include/keymaster/km_openssl/asymmetric_key.h b/include/keymaster/km_openssl/asymmetric_key.h index b523116..816930e 100644 --- a/include/keymaster/km_openssl/asymmetric_key.h +++ b/include/keymaster/km_openssl/asymmetric_key.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_ASYMMETRIC_KEY_H #define SYSTEM_KEYMASTER_ASYMMETRIC_KEY_H +#include <utility> + #include <openssl/evp.h> #include <keymaster/key.h> @@ -28,7 +30,7 @@ class AsymmetricKey : public Key { public: AsymmetricKey(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, const KeyFactory* key_factory) - : Key(move(hw_enforced), move(sw_enforced), key_factory) {} + : Key(std::move(hw_enforced), std::move(sw_enforced), key_factory) {} virtual ~AsymmetricKey() {} virtual int evp_key_type() const = 0; diff --git a/include/keymaster/km_openssl/attestation_record.h b/include/keymaster/km_openssl/attestation_record.h index f9ab811..35b9956 100644 --- a/include/keymaster/km_openssl/attestation_record.h +++ b/include/keymaster/km_openssl/attestation_record.h @@ -121,6 +121,7 @@ typedef struct km_auth_list { ASN1_INTEGER* boot_patch_level; ASN1_NULL* device_unique_attestation; ASN1_NULL* identity_credential_key; + ASN1_OCTET_STRING* attestation_id_second_imei; } KM_AUTH_LIST; ASN1_SEQUENCE(KM_AUTH_LIST) = { @@ -191,6 +192,8 @@ ASN1_SEQUENCE(KM_AUTH_LIST) = { TAG_DEVICE_UNIQUE_ATTESTATION.masked_tag()), ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential_key, ASN1_NULL, TAG_IDENTITY_CREDENTIAL_KEY.masked_tag()), + ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_second_imei, ASN1_OCTET_STRING, + TAG_ATTESTATION_ID_SECOND_IMEI.masked_tag()), } ASN1_SEQUENCE_END(KM_AUTH_LIST); DECLARE_ASN1_FUNCTIONS(KM_AUTH_LIST); @@ -347,13 +350,14 @@ keymaster_error_t build_eat_record(const AuthorizationSet& attestation_params, std::vector<uint8_t>* eat_token); // Builds the input to HMAC-SHA256 for unique ID generation. -std::vector<uint8_t> build_unique_id_input(uint64_t creation_date_time, - const keymaster_blob_t& application_id, - bool reset_since_rotation); +keymaster_error_t build_unique_id_input(uint64_t creation_date_time, + const keymaster_blob_t& application_id, + bool reset_since_rotation, Buffer* input_data); // Builds a unique ID of size UNIQUE_ID_SIZE from the given inputs. -Buffer generate_unique_id(const std::vector<uint8_t>& hbk, uint64_t creation_date_time, - const keymaster_blob_t& application_id, bool reset_since_rotation); +keymaster_error_t generate_unique_id(const std::vector<uint8_t>& hbk, uint64_t creation_date_time, + const keymaster_blob_t& application_id, + bool reset_since_rotation, Buffer* unique_id); /** * Helper functions for attestation record tests. Caller takes ownership of @@ -400,7 +404,7 @@ keymaster_error_t extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet /** * Convert a KeymasterContext::Version to the keymaster version number used in attestations. */ -inline static uint version_to_attestation_km_version(KmVersion version) { +inline static uint32_t version_to_attestation_km_version(KmVersion version) { switch (version) { default: case KmVersion::KEYMASTER_1: @@ -418,13 +422,15 @@ inline static uint version_to_attestation_km_version(KmVersion version) { return 100; case KmVersion::KEYMINT_2: return 200; + case KmVersion::KEYMINT_3: + return 300; } } /** * Convert a KeymasterContext::Version to the corresponding attestation format version number. */ -inline static uint version_to_attestation_version(KmVersion version) { +inline static uint32_t version_to_attestation_version(KmVersion version) { switch (version) { default: case KmVersion::KEYMASTER_1: @@ -441,6 +447,8 @@ inline static uint version_to_attestation_version(KmVersion version) { return 100; case KmVersion::KEYMINT_2: return 200; + case KmVersion::KEYMINT_3: + return 300; } } diff --git a/include/keymaster/km_openssl/curve25519_key.h b/include/keymaster/km_openssl/curve25519_key.h index f5f168e..c1aedef 100644 --- a/include/keymaster/km_openssl/curve25519_key.h +++ b/include/keymaster/km_openssl/curve25519_key.h @@ -16,6 +16,8 @@ #pragma once +#include <utility> + #include <keymaster/km_openssl/asymmetric_key.h> #include <keymaster/km_openssl/openssl_utils.h> @@ -36,10 +38,10 @@ class Curve25519Key : public AsymmetricKey { public: Curve25519Key(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory) - : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory) {} + : AsymmetricKey(std::move(hw_enforced), std::move(sw_enforced), factory) {} Curve25519Key(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory, const KeymasterKeyBlob& key_material) - : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory) { + : AsymmetricKey(std::move(hw_enforced), std::move(sw_enforced), factory) { key_material_ = key_material; } diff --git a/include/keymaster/km_openssl/ec_key.h b/include/keymaster/km_openssl/ec_key.h index 9ad5c70..e7feb1e 100644 --- a/include/keymaster/km_openssl/ec_key.h +++ b/include/keymaster/km_openssl/ec_key.h @@ -16,6 +16,8 @@ #pragma once +#include <utility> + #include <openssl/ec.h> #include <keymaster/km_openssl/asymmetric_key.h> @@ -28,10 +30,11 @@ class EcdsaOperationFactory; class EcKey : public AsymmetricKey { public: EcKey(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory) - : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory) {} + : AsymmetricKey(std::move(hw_enforced), std::move(sw_enforced), factory) {} EcKey(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory, EC_KEY_Ptr ec_key) - : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory), ec_key_(move(ec_key)) {} + : AsymmetricKey(std::move(hw_enforced), std::move(sw_enforced), factory), + ec_key_(std::move(ec_key)) {} int evp_key_type() const override { return EVP_PKEY_EC; } @@ -43,7 +46,8 @@ class EcKey : public AsymmetricKey { protected: EcKey(EC_KEY* ec_key, AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* key_factory) - : AsymmetricKey(move(hw_enforced), move(sw_enforced), key_factory), ec_key_(ec_key) {} + : AsymmetricKey(std::move(hw_enforced), std::move(sw_enforced), key_factory), + ec_key_(ec_key) {} private: EC_KEY_Ptr ec_key_; diff --git a/include/keymaster/km_openssl/ecdh_operation.h b/include/keymaster/km_openssl/ecdh_operation.h index 6a96009..00b8a2c 100644 --- a/include/keymaster/km_openssl/ecdh_operation.h +++ b/include/keymaster/km_openssl/ecdh_operation.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_ECDH_OPERATION_H_ #define SYSTEM_KEYMASTER_ECDH_OPERATION_H_ +#include <utility> + #include <openssl/ec.h> #include <openssl/evp.h> @@ -31,7 +33,8 @@ namespace keymaster { class EcdhOperation : public Operation { public: EcdhOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, EVP_PKEY* key) - : Operation(KM_PURPOSE_AGREE_KEY, move(hw_enforced), move(sw_enforced)), ecdh_key_(key) {} + : Operation(KM_PURPOSE_AGREE_KEY, std::move(hw_enforced), std::move(sw_enforced)), + ecdh_key_(key) {} keymaster_error_t Abort() override { return KM_ERROR_OK; } @@ -51,7 +54,7 @@ class EcdhOperation : public Operation { class X25519Operation : public EcdhOperation { public: X25519Operation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, EVP_PKEY* key) - : EcdhOperation(move(hw_enforced), move(sw_enforced), key) {} + : EcdhOperation(std::move(hw_enforced), std::move(sw_enforced), key) {} keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& input, const Buffer& signature, AuthorizationSet* output_params, diff --git a/include/keymaster/km_openssl/ecdsa_operation.h b/include/keymaster/km_openssl/ecdsa_operation.h index 457c381..f423bef 100644 --- a/include/keymaster/km_openssl/ecdsa_operation.h +++ b/include/keymaster/km_openssl/ecdsa_operation.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_ECDSA_OPERATION_H_ #define SYSTEM_KEYMASTER_ECDSA_OPERATION_H_ +#include <utility> + #include <openssl/ec.h> #include <openssl/evp.h> @@ -32,7 +34,7 @@ class EcdsaOperation : public Operation { public: EcdsaOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_purpose_t purpose, keymaster_digest_t digest, EVP_PKEY* key) - : Operation(purpose, move(hw_enforced), move(sw_enforced)), digest_(digest), + : Operation(purpose, std::move(hw_enforced), std::move(sw_enforced)), digest_(digest), digest_algorithm_(nullptr), ecdsa_key_(key) { EVP_MD_CTX_init(&digest_ctx_); } @@ -55,7 +57,8 @@ class EcdsaSignOperation : public EcdsaOperation { public: EcdsaSignOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, EVP_PKEY* key) - : EcdsaOperation(move(hw_enforced), move(sw_enforced), KM_PURPOSE_SIGN, digest, key) {} + : EcdsaOperation(std::move(hw_enforced), std::move(sw_enforced), KM_PURPOSE_SIGN, digest, + key) {} keymaster_error_t Begin(const AuthorizationSet& input_params, AuthorizationSet* output_params) override; keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input, @@ -70,7 +73,8 @@ class EcdsaVerifyOperation : public EcdsaOperation { public: EcdsaVerifyOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, EVP_PKEY* key) - : EcdsaOperation(move(hw_enforced), move(sw_enforced), KM_PURPOSE_VERIFY, digest, key) {} + : EcdsaOperation(std::move(hw_enforced), std::move(sw_enforced), KM_PURPOSE_VERIFY, digest, + key) {} keymaster_error_t Begin(const AuthorizationSet& input_params, AuthorizationSet* output_params) override; keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input, @@ -85,7 +89,7 @@ class Ed25519SignOperation : public EcdsaSignOperation { public: Ed25519SignOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, EVP_PKEY* key) - : EcdsaSignOperation(move(hw_enforced), move(sw_enforced), digest, key) {} + : EcdsaSignOperation(std::move(hw_enforced), std::move(sw_enforced), digest, key) {} keymaster_error_t Begin(const AuthorizationSet& input_params, AuthorizationSet* output_params) override; keymaster_error_t Update(const AuthorizationSet& additional_params, const Buffer& input, @@ -119,10 +123,10 @@ class EcdsaSignOperationFactory : public EcdsaOperationFactory { keymaster_digest_t digest, EVP_PKEY* key) override { if (IsEd25519Key(hw_enforced, sw_enforced)) { return new (std::nothrow) - Ed25519SignOperation(move(hw_enforced), move(sw_enforced), digest, key); + Ed25519SignOperation(std::move(hw_enforced), std::move(sw_enforced), digest, key); } else { return new (std::nothrow) - EcdsaSignOperation(move(hw_enforced), move(sw_enforced), digest, key); + EcdsaSignOperation(std::move(hw_enforced), std::move(sw_enforced), digest, key); } } }; @@ -133,7 +137,7 @@ class EcdsaVerifyOperationFactory : public EcdsaOperationFactory { Operation* InstantiateOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, EVP_PKEY* key) override { return new (std::nothrow) - EcdsaVerifyOperation(move(hw_enforced), move(sw_enforced), digest, key); + EcdsaVerifyOperation(std::move(hw_enforced), std::move(sw_enforced), digest, key); } }; diff --git a/include/keymaster/km_openssl/hmac_key.h b/include/keymaster/km_openssl/hmac_key.h index 55d802a..3e2df2b 100644 --- a/include/keymaster/km_openssl/hmac_key.h +++ b/include/keymaster/km_openssl/hmac_key.h @@ -16,6 +16,8 @@ #pragma once +#include <utility> + #include "symmetric_key.h" namespace keymaster { @@ -50,7 +52,8 @@ class HmacKey : public SymmetricKey { public: HmacKey(KeymasterKeyBlob&& key_material, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, const KeyFactory* key_factory) - : SymmetricKey(move(key_material), move(hw_enforced), move(sw_enforced), key_factory) {} + : SymmetricKey(std::move(key_material), std::move(hw_enforced), std::move(sw_enforced), + key_factory) {} }; } // namespace keymaster diff --git a/include/keymaster/km_openssl/rsa_key.h b/include/keymaster/km_openssl/rsa_key.h index 3cd7c3a..6ea6919 100644 --- a/include/keymaster/km_openssl/rsa_key.h +++ b/include/keymaster/km_openssl/rsa_key.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_RSA_KEY_H_ #define SYSTEM_KEYMASTER_RSA_KEY_H_ +#include <utility> + #include <openssl/rsa.h> #include <keymaster/km_openssl/openssl_utils.h> @@ -28,10 +30,11 @@ namespace keymaster { class RsaKey : public AsymmetricKey { public: RsaKey(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory) - : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory) {} + : AsymmetricKey(std::move(hw_enforced), std::move(sw_enforced), factory) {} RsaKey(AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* factory, RSA_Ptr rsa_key) - : AsymmetricKey(move(hw_enforced), move(sw_enforced), factory), rsa_key_(move(rsa_key)) {} + : AsymmetricKey(std::move(hw_enforced), std::move(sw_enforced), factory), + rsa_key_(std::move(rsa_key)) {} int evp_key_type() const override { return EVP_PKEY_RSA; } @@ -46,7 +49,8 @@ class RsaKey : public AsymmetricKey { protected: RsaKey(RSA* rsa, AuthorizationSet hw_enforced, AuthorizationSet sw_enforced, const KeyFactory* key_factory) - : AsymmetricKey(move(hw_enforced), move(sw_enforced), key_factory), rsa_key_(rsa) {} + : AsymmetricKey(std::move(hw_enforced), std::move(sw_enforced), key_factory), rsa_key_(rsa) + {} private: RSA_Ptr rsa_key_; diff --git a/include/keymaster/km_openssl/rsa_operation.h b/include/keymaster/km_openssl/rsa_operation.h index 99004f2..cb4422f 100644 --- a/include/keymaster/km_openssl/rsa_operation.h +++ b/include/keymaster/km_openssl/rsa_operation.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_RSA_OPERATION_H_ #define SYSTEM_KEYMASTER_RSA_OPERATION_H_ +#include <utility> + #include <keymaster/UniquePtr.h> #include <openssl/evp.h> @@ -36,7 +38,7 @@ class RsaOperation : public Operation { RsaOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_purpose_t purpose, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) - : Operation(purpose, move(hw_enforced), move(sw_enforced)), rsa_key_(key), + : Operation(purpose, std::move(hw_enforced), std::move(sw_enforced)), rsa_key_(key), padding_(padding), digest_(digest), digest_algorithm_(nullptr) {} ~RsaOperation(); @@ -91,8 +93,8 @@ class RsaSignOperation : public RsaDigestingOperation { public: RsaSignOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) - : RsaDigestingOperation(move(hw_enforced), move(sw_enforced), KM_PURPOSE_SIGN, digest, - padding, key) {} + : RsaDigestingOperation(std::move(hw_enforced), std::move(sw_enforced), KM_PURPOSE_SIGN, + digest, padding, key) {} keymaster_error_t Begin(const AuthorizationSet& input_params, AuthorizationSet* output_params) override; @@ -115,8 +117,8 @@ class RsaVerifyOperation : public RsaDigestingOperation { public: RsaVerifyOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) - : RsaDigestingOperation(move(hw_enforced), move(sw_enforced), KM_PURPOSE_VERIFY, digest, - padding, key) {} + : RsaDigestingOperation(std::move(hw_enforced), std::move(sw_enforced), KM_PURPOSE_VERIFY, + digest, padding, key) {} keymaster_error_t Begin(const AuthorizationSet& input_params, AuthorizationSet* output_params) override; @@ -140,7 +142,8 @@ class RsaCryptOperation : public RsaOperation { RsaCryptOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_purpose_t purpose, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) - : RsaOperation(move(hw_enforced), move(sw_enforced), purpose, digest, padding, key), + : RsaOperation(std::move(hw_enforced), std::move(sw_enforced), purpose, digest, padding, + key), mgf_digest_(KM_DIGEST_SHA1), mgf_digest_algorithm_(nullptr) {} keymaster_digest_t oaepMgfDigest() { return mgf_digest_; } void setOaepMgfDigest(keymaster_digest_t mgf_digest) { mgf_digest_ = mgf_digest; } @@ -165,8 +168,8 @@ class RsaEncryptOperation : public RsaCryptOperation { public: RsaEncryptOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) - : RsaCryptOperation(move(hw_enforced), move(sw_enforced), KM_PURPOSE_ENCRYPT, digest, - padding, key) {} + : RsaCryptOperation(std::move(hw_enforced), std::move(sw_enforced), KM_PURPOSE_ENCRYPT, + digest, padding, key) {} keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& input, const Buffer& signature, AuthorizationSet* output_params, Buffer* output) override; @@ -179,8 +182,8 @@ class RsaDecryptOperation : public RsaCryptOperation { public: RsaDecryptOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) - : RsaCryptOperation(move(hw_enforced), move(sw_enforced), KM_PURPOSE_DECRYPT, digest, - padding, key) {} + : RsaCryptOperation(std::move(hw_enforced), std::move(sw_enforced), KM_PURPOSE_DECRYPT, + digest, padding, key) {} keymaster_error_t Finish(const AuthorizationSet& additional_params, const Buffer& input, const Buffer& signature, AuthorizationSet* output_params, Buffer* output) override; @@ -197,7 +200,7 @@ class RsaOperationFactory : public OperationFactory { OperationPtr CreateOperation(Key&& key, const AuthorizationSet& begin_params, keymaster_error_t* error) override { - return OperationPtr(CreateRsaOperation(move(key), begin_params, error)); + return OperationPtr(CreateRsaOperation(std::move(key), begin_params, error)); } const keymaster_digest_t* SupportedDigests(size_t* digest_count) const override; @@ -246,7 +249,7 @@ class RsaSigningOperationFactory : public RsaDigestingOperationFactory { AuthorizationSet&& sw_enforced, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) override { return new (std::nothrow) - RsaSignOperation(move(hw_enforced), move(sw_enforced), digest, padding, key); + RsaSignOperation(std::move(hw_enforced), std::move(sw_enforced), digest, padding, key); } }; @@ -259,7 +262,8 @@ class RsaVerificationOperationFactory : public RsaDigestingOperationFactory { AuthorizationSet&& sw_enforced, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) override { return new (std::nothrow) - RsaVerifyOperation(move(hw_enforced), move(sw_enforced), digest, padding, key); + RsaVerifyOperation(std::move(hw_enforced), std::move(sw_enforced), digest, padding, + key); } }; @@ -272,7 +276,8 @@ class RsaEncryptionOperationFactory : public RsaCryptingOperationFactory { AuthorizationSet&& sw_enforced, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) override { return new (std::nothrow) - RsaEncryptOperation(move(hw_enforced), move(sw_enforced), digest, padding, key); + RsaEncryptOperation(std::move(hw_enforced), std::move(sw_enforced), digest, padding, + key); } }; @@ -285,7 +290,8 @@ class RsaDecryptionOperationFactory : public RsaCryptingOperationFactory { AuthorizationSet&& sw_enforced, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) override { return new (std::nothrow) - RsaDecryptOperation(move(hw_enforced), move(sw_enforced), digest, padding, key); + RsaDecryptOperation(std::move(hw_enforced), std::move(sw_enforced), digest, padding, + key); } }; diff --git a/include/keymaster/km_openssl/triple_des_key.h b/include/keymaster/km_openssl/triple_des_key.h index a03d595..5e8f3fc 100644 --- a/include/keymaster/km_openssl/triple_des_key.h +++ b/include/keymaster/km_openssl/triple_des_key.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_TRIPLE_DES_KEY_H_ #define SYSTEM_KEYMASTER_TRIPLE_DES_KEY_H_ +#include <utility> + #include <openssl/des.h> #include "symmetric_key.h" @@ -53,7 +55,8 @@ class TripleDesKey : public SymmetricKey { public: TripleDesKey(KeymasterKeyBlob&& key_material, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, const KeyFactory* key_factory) - : SymmetricKey(move(key_material), move(hw_enforced), move(sw_enforced), key_factory) {} + : SymmetricKey(std::move(key_material), std::move(hw_enforced), std::move(sw_enforced), + key_factory) {} }; } // namespace keymaster diff --git a/include/keymaster/km_version.h b/include/keymaster/km_version.h index 122d045..6287aa3 100644 --- a/include/keymaster/km_version.h +++ b/include/keymaster/km_version.h @@ -32,6 +32,7 @@ enum class KmVersion { KEYMASTER_4_1 = 41, KEYMINT_1 = 100, KEYMINT_2 = 200, + KEYMINT_3 = 300, }; }; // namespace keymaster diff --git a/include/keymaster/legacy_support/ec_keymaster1_key.h b/include/keymaster/legacy_support/ec_keymaster1_key.h index d695c74..88adf64 100644 --- a/include/keymaster/legacy_support/ec_keymaster1_key.h +++ b/include/keymaster/legacy_support/ec_keymaster1_key.h @@ -16,6 +16,8 @@ #pragma once +#include <utility> + #include <openssl/ecdsa.h> #include <hardware/keymaster1.h> @@ -77,7 +79,7 @@ class EcdsaKeymaster1Key : public EcKey { public: EcdsaKeymaster1Key(EC_KEY* ecdsa_key, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, const KeyFactory* key_factory) - : EcKey(ecdsa_key, move(hw_enforced), move(sw_enforced), key_factory) {} + : EcKey(ecdsa_key, std::move(hw_enforced), std::move(sw_enforced), key_factory) {} }; } // namespace keymaster diff --git a/include/keymaster/legacy_support/keymaster1_legacy_support.h b/include/keymaster/legacy_support/keymaster1_legacy_support.h index a09b5e5..531f1a1 100644 --- a/include/keymaster/legacy_support/keymaster1_legacy_support.h +++ b/include/keymaster/legacy_support/keymaster1_legacy_support.h @@ -18,6 +18,7 @@ #pragma once #include <map> +#include <utility> #include <vector> #include <hardware/keymaster1.h> @@ -61,7 +62,7 @@ template <typename KM1_SOFTDIGEST_FACTORY> class Keymaster1ArbitrationFactory : Keymaster1ArbitrationFactory(const KeymasterPassthroughEngine* ptengine, keymaster_algorithm_t algorithm, const keymaster1_device_t* dev, SOFT_FACTORY_CONSRUCTOR_ARGS&&... args) - : software_digest_factory_(forward<SOFT_FACTORY_CONSRUCTOR_ARGS>(args)...), + : software_digest_factory_(std::forward<SOFT_FACTORY_CONSRUCTOR_ARGS>(args)...), passthrough_factory_(ptengine, algorithm), legacy_support_(dev) {} keymaster_error_t GenerateKey(const AuthorizationSet& key_description, UniquePtr<Key> attest_key, // @@ -71,11 +72,11 @@ template <typename KM1_SOFTDIGEST_FACTORY> class Keymaster1ArbitrationFactory : AuthorizationSet* sw_enforced, CertificateChain* cert_chain) const { if (legacy_support_.RequiresSoftwareDigesting(key_description)) { - return software_digest_factory_.GenerateKey(key_description, move(attest_key), + return software_digest_factory_.GenerateKey(key_description, std::move(attest_key), issuer_subject, key_blob, hw_enforced, sw_enforced, cert_chain); } else { - return passthrough_factory_.GenerateKey(key_description, move(attest_key), + return passthrough_factory_.GenerateKey(key_description, std::move(attest_key), issuer_subject, key_blob, hw_enforced, sw_enforced, cert_chain); } @@ -91,12 +92,14 @@ template <typename KM1_SOFTDIGEST_FACTORY> class Keymaster1ArbitrationFactory : AuthorizationSet* sw_enforced, CertificateChain* cert_chain) const { if (legacy_support_.RequiresSoftwareDigesting(key_description)) { return software_digest_factory_.ImportKey( - key_description, input_key_material_format, input_key_material, move(attest_key), - issuer_subject, output_key_blob, hw_enforced, sw_enforced, cert_chain); + key_description, input_key_material_format, input_key_material, + std::move(attest_key), issuer_subject, output_key_blob, hw_enforced, sw_enforced, + cert_chain); } else { return passthrough_factory_.ImportKey( - key_description, input_key_material_format, input_key_material, move(attest_key), - issuer_subject, output_key_blob, hw_enforced, sw_enforced, cert_chain); + key_description, input_key_material_format, input_key_material, + std::move(attest_key), issuer_subject, output_key_blob, hw_enforced, sw_enforced, + cert_chain); } } @@ -111,11 +114,13 @@ template <typename KM1_SOFTDIGEST_FACTORY> class Keymaster1ArbitrationFactory : if (legacy_support_.RequiresSoftwareDigesting(digest, AuthProxy(hw_enforced, sw_enforced))) { - return software_digest_factory_.LoadKey(move(key_material), additional_params, - move(hw_enforced), move(sw_enforced), key); + return software_digest_factory_.LoadKey(std::move(key_material), additional_params, + std::move(hw_enforced), std::move(sw_enforced), + key); } else { - return passthrough_factory_.LoadKey(move(key_material), additional_params, - move(hw_enforced), move(sw_enforced), key); + return passthrough_factory_.LoadKey(std::move(key_material), additional_params, + std::move(hw_enforced), std::move(sw_enforced), + key); } } diff --git a/include/keymaster/legacy_support/keymaster_passthrough_key.h b/include/keymaster/legacy_support/keymaster_passthrough_key.h index e262181..859a864 100644 --- a/include/keymaster/legacy_support/keymaster_passthrough_key.h +++ b/include/keymaster/legacy_support/keymaster_passthrough_key.h @@ -17,6 +17,8 @@ #pragma once +#include <utility> + #include <keymaster/android_keymaster_utils.h> #include <keymaster/authorization_set.h> #include <keymaster/key.h> @@ -84,9 +86,9 @@ class KeymasterPassthroughKey : public Key { AuthorizationSet&& sw_enforced, const KeyFactory* key_factory, keymaster_error_t* error, const AuthorizationSet& additional_parameters, const KeymasterPassthroughEngine* engine) - : Key(move(hw_enforced), move(sw_enforced), key_factory), + : Key(std::move(hw_enforced), std::move(sw_enforced), key_factory), additional_parameters_(additional_parameters), engine_(engine) { - key_material_ = move(key_material); + key_material_ = std::move(key_material); if (*error != KM_ERROR_OK) return; if (additional_parameters.is_valid() != additional_parameters_.is_valid() && additional_parameters_.is_valid() == AuthorizationSet::ALLOCATION_FAILURE) { diff --git a/include/keymaster/legacy_support/rsa_keymaster1_key.h b/include/keymaster/legacy_support/rsa_keymaster1_key.h index e114aef..939f9d8 100644 --- a/include/keymaster/legacy_support/rsa_keymaster1_key.h +++ b/include/keymaster/legacy_support/rsa_keymaster1_key.h @@ -16,6 +16,8 @@ #pragma once +#include <utility> + #include <openssl/rsa.h> #include <keymaster/km_openssl/rsa_key.h> @@ -79,7 +81,7 @@ class RsaKeymaster1Key : public RsaKey { public: RsaKeymaster1Key(RSA* rsa_key, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, const KeyFactory* key_factory) - : RsaKey(rsa_key, move(hw_enforced), move(sw_enforced), key_factory) {} + : RsaKey(rsa_key, std::move(hw_enforced), std::move(sw_enforced), key_factory) {} }; } // namespace keymaster diff --git a/include/keymaster/mem.h b/include/keymaster/mem.h index 6d5de1b..6593099 100644 --- a/include/keymaster/mem.h +++ b/include/keymaster/mem.h @@ -18,9 +18,6 @@ namespace keymaster { -using std::forward; -using std::move; - /* * Array Manipulation functions. This set of templated inline functions provides some nice tools * for operating on c-style arrays. C-style arrays actually do have a defined size associated with diff --git a/include/keymaster/operation.h b/include/keymaster/operation.h index aa02599..5643595 100644 --- a/include/keymaster/operation.h +++ b/include/keymaster/operation.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_OPERATION_H_ #define SYSTEM_KEYMASTER_OPERATION_H_ +#include <utility> + #include <assert.h> #include <stdint.h> #include <stdlib.h> @@ -93,7 +95,8 @@ class Operation { public: explicit Operation(keymaster_purpose_t purpose, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced) - : purpose_(purpose), hw_enforced_(move(hw_enforced)), sw_enforced_(move(sw_enforced)) {} + : purpose_(purpose), hw_enforced_(std::move(hw_enforced)), + sw_enforced_(std::move(sw_enforced)) {} virtual ~Operation() {} Operation(const Operation&) = delete; diff --git a/include/keymaster/remote_provisioning_context.h b/include/keymaster/remote_provisioning_context.h index fee1d44..cc65502 100644 --- a/include/keymaster/remote_provisioning_context.h +++ b/include/keymaster/remote_provisioning_context.h @@ -23,6 +23,7 @@ #include <vector> #include <cppbor.h> +#include <keymaster/android_keymaster_messages.h> #include <keymaster/cppcose/cppcose.h> namespace keymaster { @@ -33,7 +34,7 @@ class RemoteProvisioningContext { virtual ~RemoteProvisioningContext(){}; virtual std::vector<uint8_t> DeriveBytesFromHbk(const std::string& context, size_t numBytes) const = 0; - virtual std::unique_ptr<cppbor::Map> CreateDeviceInfo() const = 0; + virtual std::unique_ptr<cppbor::Map> CreateDeviceInfo(uint32_t csrVersion) const = 0; virtual cppcose::ErrMsgOr<std::vector<uint8_t>> BuildProtectedDataPayload(bool testMode, // const std::vector<uint8_t>& macKey, // @@ -42,6 +43,9 @@ class RemoteProvisioningContext { // input hasn't changed across multiple calls to the remote provisioning HAL. virtual std::optional<cppcose::HmacSha256> GenerateHmacSha256(const cppcose::bytevec& input) const = 0; + virtual void GetHwInfo(GetHwInfoResponse* hwInfo) const = 0; + virtual cppcose::ErrMsgOr<cppbor::Array> BuildCsr(const std::vector<uint8_t>& challenge, + cppbor::Array keysToSign) const = 0; private: // Uncopyable. diff --git a/include/keymaster/remote_provisioning_utils.h b/include/keymaster/remote_provisioning_utils.h index 9fc0d2e..e51d418 100644 --- a/include/keymaster/remote_provisioning_utils.h +++ b/include/keymaster/remote_provisioning_utils.h @@ -30,6 +30,7 @@ constexpr keymaster_error_t kStatusInvalidMac = static_cast<keymaster_error_t>(- constexpr keymaster_error_t kStatusProductionKeyInTestRequest = static_cast<keymaster_error_t>(-3); constexpr keymaster_error_t kStatusTestKeyInProductionRequest = static_cast<keymaster_error_t>(-4); constexpr keymaster_error_t kStatusInvalidEek = static_cast<keymaster_error_t>(-5); +constexpr keymaster_error_t kStatusRemoved = static_cast<keymaster_error_t>(-6); template <typename T> class StatusOr { public: @@ -68,7 +69,7 @@ template <typename T> class StatusOr { StatusOr<std::pair<std::vector<uint8_t> /* EEK pub */, std::vector<uint8_t> /* EEK ID */>> validateAndExtractEekPubAndId(bool testMode, const KeymasterBlob& endpointEncryptionCertChain); -StatusOr<std::vector<uint8_t> /* pubkeys */> +StatusOr<cppbor::Array /* pubkeys */> validateAndExtractPubkeys(bool testMode, uint32_t numKeys, KeymasterBlob* keysToSign, const cppcose::HmacSha256Function& macFunction); diff --git a/include/keymaster/serializable.h b/include/keymaster/serializable.h index f043574..09e98b1 100644 --- a/include/keymaster/serializable.h +++ b/include/keymaster/serializable.h @@ -22,6 +22,7 @@ #include <string.h> #include <iterator> +#include <utility> #include <keymaster/UniquePtr.h> #include <keymaster/logger.h> @@ -251,14 +252,14 @@ class Buffer : public Serializable { Buffer() : buffer_(nullptr), buffer_size_(0), read_position_(0), write_position_(0) {} explicit Buffer(size_t size) : buffer_(nullptr) { Reinitialize(size); } Buffer(const void* buf, size_t size) : buffer_(nullptr) { Reinitialize(buf, size); } - Buffer(Buffer&& b) { *this = move(b); } + Buffer(Buffer&& b) { *this = std::move(b); } Buffer(const Buffer&) = delete; ~Buffer() { Clear(); } Buffer& operator=(Buffer&& other) { if (this == &other) return *this; - buffer_ = move(other.buffer_); + buffer_ = std::move(other.buffer_); buffer_size_ = other.buffer_size_; other.buffer_size_ = 0; read_position_ = other.read_position_; diff --git a/key_blob_utils/auth_encrypted_key_blob.cpp b/key_blob_utils/auth_encrypted_key_blob.cpp index 3cdcf5c..c726d4d 100644 --- a/key_blob_utils/auth_encrypted_key_blob.cpp +++ b/key_blob_utils/auth_encrypted_key_blob.cpp @@ -16,6 +16,8 @@ #include <keymaster/key_blob_utils/auth_encrypted_key_blob.h> +#include <utility> + #include <openssl/digest.h> #include <openssl/evp.h> #include <openssl/hkdf.h> @@ -139,7 +141,7 @@ KmErrorOr<EncryptedKey> AesGcmEncryptKey(const AuthorizationSet& hw_enforced, EncryptedKey retval; retval.format = format; retval.ciphertext = KeymasterKeyBlob(ciphertext_len); - retval.nonce = move(nonce); + retval.nonce = std::move(nonce); retval.tag = Buffer(kAesGcmTagLength); if (!(EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_gcm(), nullptr /* engine */, kek->peek_read(), diff --git a/key_blob_utils/software_keyblobs.cpp b/key_blob_utils/software_keyblobs.cpp index 8897545..3a2929e 100644 --- a/key_blob_utils/software_keyblobs.cpp +++ b/key_blob_utils/software_keyblobs.cpp @@ -95,7 +95,7 @@ keymaster_error_t FakeKeyAuthorizations(EVP_PKEY* pubkey, AuthorizationSet* hw_e hw_enforced->Clear(); sw_enforced->Clear(); - switch (EVP_PKEY_type(pubkey->type)) { + switch (EVP_PKEY_id(pubkey)) { case EVP_PKEY_RSA: { hw_enforced->push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA); hw_enforced->push_back(TAG_DIGEST, KM_DIGEST_NONE); @@ -196,7 +196,7 @@ keymaster_error_t ParseOldSoftkeymasterBlob(const KeymasterKeyBlob& blob, } p += publicLen; - if (end - p < 2) { + if (end - p < sizeof(type)) { LOG_W("key blob appears to be truncated (if an old SW key)", 0); return KM_ERROR_INVALID_KEY_BLOB; } @@ -318,6 +318,7 @@ keymaster_error_t SetKeyBlobAuthorizations(const AuthorizationSet& key_descripti case KM_TAG_ATTESTATION_ID_BRAND: case KM_TAG_ATTESTATION_ID_DEVICE: case KM_TAG_ATTESTATION_ID_IMEI: + case KM_TAG_ATTESTATION_ID_SECOND_IMEI: case KM_TAG_ATTESTATION_ID_MANUFACTURER: case KM_TAG_ATTESTATION_ID_MEID: case KM_TAG_ATTESTATION_ID_MODEL: diff --git a/km_openssl/aes_key.cpp b/km_openssl/aes_key.cpp index 5df9e9e..04fa087 100644 --- a/km_openssl/aes_key.cpp +++ b/km_openssl/aes_key.cpp @@ -16,6 +16,8 @@ #include <keymaster/km_openssl/aes_key.h> +#include <utility> + #include <assert.h> #include <openssl/err.h> @@ -60,7 +62,8 @@ keymaster_error_t AesKeyFactory::LoadKey(KeymasterKeyBlob&& key_material, keymaster_error_t error = KM_ERROR_OK; key->reset(new (std::nothrow) - AesKey(move(key_material), move(hw_enforced), move(sw_enforced), this)); + AesKey(std::move(key_material), std::move(hw_enforced), std::move(sw_enforced), + this)); if (!key->get()) error = KM_ERROR_MEMORY_ALLOCATION_FAILED; return error; } diff --git a/km_openssl/asymmetric_key_factory.cpp b/km_openssl/asymmetric_key_factory.cpp index 963694c..2fa1018 100644 --- a/km_openssl/asymmetric_key_factory.cpp +++ b/km_openssl/asymmetric_key_factory.cpp @@ -16,6 +16,8 @@ #include <keymaster/asymmetric_key_factory.h> +#include <utility> + #include <keymaster/android_keymaster_utils.h> #include <keymaster/km_openssl/asymmetric_key.h> @@ -44,11 +46,12 @@ keymaster_error_t AsymmetricKeyFactory::LoadKey(KeymasterKeyBlob&& key_material, AuthorizationSet&& sw_enforced, UniquePtr<Key>* key) const { UniquePtr<AsymmetricKey> asym_key; - keymaster_error_t error = CreateEmptyKey(move(hw_enforced), move(sw_enforced), &asym_key); + keymaster_error_t error = CreateEmptyKey(std::move(hw_enforced), std::move(sw_enforced), + &asym_key); if (error != KM_ERROR_OK) return error; const uint8_t* tmp = key_material.key_material; - asym_key->key_material() = move(key_material); + asym_key->key_material() = std::move(key_material); EVP_PKEY* pkey = d2i_PrivateKey(asym_key->evp_key_type(), nullptr /* pkey */, &tmp, asym_key->key_material().key_material_size); diff --git a/km_openssl/attestation_record.cpp b/km_openssl/attestation_record.cpp index f413064..36cf320 100644 --- a/km_openssl/attestation_record.cpp +++ b/km_openssl/attestation_record.cpp @@ -47,10 +47,11 @@ IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST); IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION); static const keymaster_tag_t kDeviceAttestationTags[] = { - KM_TAG_ATTESTATION_ID_BRAND, KM_TAG_ATTESTATION_ID_DEVICE, KM_TAG_ATTESTATION_ID_PRODUCT, - KM_TAG_ATTESTATION_ID_SERIAL, KM_TAG_ATTESTATION_ID_IMEI, KM_TAG_ATTESTATION_ID_MEID, + KM_TAG_ATTESTATION_ID_BRAND, KM_TAG_ATTESTATION_ID_DEVICE, + KM_TAG_ATTESTATION_ID_PRODUCT, KM_TAG_ATTESTATION_ID_SERIAL, + KM_TAG_ATTESTATION_ID_IMEI, KM_TAG_ATTESTATION_ID_MEID, KM_TAG_ATTESTATION_ID_MANUFACTURER, KM_TAG_ATTESTATION_ID_MODEL, -}; + KM_TAG_ATTESTATION_ID_SECOND_IMEI}; struct KM_AUTH_LIST_Delete { void operator()(KM_AUTH_LIST* p) { KM_AUTH_LIST_free(p); } @@ -679,6 +680,9 @@ keymaster_error_t build_auth_list(const AuthorizationSet& auth_list, KM_AUTH_LIS case KM_TAG_ATTESTATION_ID_IMEI: string_ptr = &record->attestation_id_imei; break; + case KM_TAG_ATTESTATION_ID_SECOND_IMEI: + string_ptr = &record->attestation_id_second_imei; + break; case KM_TAG_ATTESTATION_ID_MEID: string_ptr = &record->attestation_id_meid; break; @@ -936,31 +940,47 @@ keymaster_error_t build_eat_record(const AuthorizationSet& attestation_params, return KM_ERROR_OK; } -std::vector<uint8_t> build_unique_id_input(uint64_t creation_date_time, - const keymaster_blob_t& application_id, - bool reset_since_rotation) { +keymaster_error_t build_unique_id_input(uint64_t creation_date_time, + const keymaster_blob_t& application_id, + bool reset_since_rotation, Buffer* input_data) { + if (input_data == nullptr) { + return KM_ERROR_UNEXPECTED_NULL_POINTER; + } uint64_t rounded_date = creation_date_time / 2592000000LLU; uint8_t* serialized_date = reinterpret_cast<uint8_t*>(&rounded_date); + uint8_t reset_byte = (reset_since_rotation ? 1 : 0); - std::vector<uint8_t> input; - input.insert(input.end(), serialized_date, serialized_date + sizeof(rounded_date)); - input.insert(input.end(), application_id.data, - application_id.data + application_id.data_length); - input.push_back(reset_since_rotation ? 1 : 0); - return input; + if (!input_data->Reinitialize(sizeof(rounded_date) + application_id.data_length + 1) || + !input_data->write(serialized_date, sizeof(rounded_date)) || + !input_data->write(application_id.data, application_id.data_length) || + !input_data->write(&reset_byte, 1)) { + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + } + return KM_ERROR_OK; } -Buffer generate_unique_id(const std::vector<uint8_t>& hbk, uint64_t creation_date_time, - const keymaster_blob_t& application_id, bool reset_since_rotation) { +keymaster_error_t generate_unique_id(const std::vector<uint8_t>& hbk, uint64_t creation_date_time, + const keymaster_blob_t& application_id, + bool reset_since_rotation, Buffer* unique_id) { + if (unique_id == nullptr) { + return KM_ERROR_UNEXPECTED_NULL_POINTER; + } HmacSha256 hmac; hmac.Init(hbk.data(), hbk.size()); - std::vector<uint8_t> input = - build_unique_id_input(creation_date_time, application_id, reset_since_rotation); - Buffer unique_id(UNIQUE_ID_SIZE); - hmac.Sign(input.data(), input.size(), unique_id.peek_write(), unique_id.available_write()); - unique_id.advance_write(UNIQUE_ID_SIZE); - return unique_id; + Buffer input; + keymaster_error_t error = + build_unique_id_input(creation_date_time, application_id, reset_since_rotation, &input); + if (error != KM_ERROR_OK) { + return error; + } + if (!unique_id->Reinitialize(UNIQUE_ID_SIZE)) { + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + } + hmac.Sign(input.peek_read(), input.available_read(), unique_id->peek_write(), + unique_id->available_write()); + unique_id->advance_write(UNIQUE_ID_SIZE); + return KM_ERROR_OK; } // Construct an ASN1.1 DER-encoded attestation record containing the values from sw_enforced and @@ -1388,6 +1408,14 @@ keymaster_error_t extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet return KM_ERROR_MEMORY_ALLOCATION_FAILED; } + // Second IMEI + if (record->attestation_id_second_imei && + !auth_list->push_back(TAG_ATTESTATION_ID_SECOND_IMEI, + record->attestation_id_second_imei->data, + record->attestation_id_second_imei->length)) { + return KM_ERROR_MEMORY_ALLOCATION_FAILED; + } + return KM_ERROR_OK; } diff --git a/km_openssl/attestation_utils.cpp b/km_openssl/attestation_utils.cpp index e9a6aa3..a288446 100644 --- a/km_openssl/attestation_utils.cpp +++ b/km_openssl/attestation_utils.cpp @@ -15,6 +15,8 @@ ** limitations under the License. */ +#include <utility> + #include <openssl/evp.h> #include <openssl/x509v3.h> @@ -146,7 +148,7 @@ keymaster_error_t make_attestation_cert(const EVP_PKEY* evp_pkey, const X509_NAM return error; } - *cert_out = move(certificate); + *cert_out = std::move(certificate); return KM_ERROR_OK; } @@ -266,7 +268,7 @@ CertificateChain generate_attestation(const AsymmetricKey& key, } return generate_attestation(pkey.get(), key.sw_enforced(), key.hw_enforced(), attest_params, - move(attest_key), context, error); + std::move(attest_key), context, error); } CertificateChain generate_attestation(const EVP_PKEY* evp_key, // @@ -317,7 +319,7 @@ CertificateChain generate_attestation(const EVP_PKEY* evp_key, // *error = sign_cert(certificate.get(), signing_key_ptr); if (*error != KM_ERROR_OK) return {}; - return make_cert_chain(certificate.get(), move(cert_chain), error); + return make_cert_chain(certificate.get(), std::move(cert_chain), error); } } // namespace keymaster diff --git a/km_openssl/block_cipher_operation.cpp b/km_openssl/block_cipher_operation.cpp index a381e75..296cb9c 100644 --- a/km_openssl/block_cipher_operation.cpp +++ b/km_openssl/block_cipher_operation.cpp @@ -16,6 +16,8 @@ #include "block_cipher_operation.h" +#include <utility> + #include <stdio.h> #include <keymaster/UniquePtr.h> @@ -117,11 +119,12 @@ OperationPtr BlockCipherOperationFactory::CreateOperation(Key&& key, switch (purpose_) { case KM_PURPOSE_ENCRYPT: op.reset(new (std::nothrow) BlockCipherEvpEncryptOperation( // - block_mode, padding, caller_nonce, tag_length, move(key), GetCipherDescription())); + block_mode, padding, caller_nonce, tag_length, std::move(key), + GetCipherDescription())); break; case KM_PURPOSE_DECRYPT: op.reset(new (std::nothrow) BlockCipherEvpDecryptOperation( - block_mode, padding, tag_length, move(key), GetCipherDescription())); + block_mode, padding, tag_length, std::move(key), GetCipherDescription())); break; default: *error = KM_ERROR_UNSUPPORTED_PURPOSE; diff --git a/km_openssl/block_cipher_operation.h b/km_openssl/block_cipher_operation.h index 9c25bda..cd78805 100644 --- a/km_openssl/block_cipher_operation.h +++ b/km_openssl/block_cipher_operation.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_BLOCK_CIPHER_OPERATION_H_ #define SYSTEM_KEYMASTER_BLOCK_CIPHER_OPERATION_H_ +#include <utility> + #include <openssl/evp.h> #include <keymaster/operation.h> @@ -121,7 +123,7 @@ class BlockCipherEvpEncryptOperation : public BlockCipherEvpOperation { bool caller_iv, size_t tag_length, Key&& key, const EvpCipherDescription& cipher_description) : BlockCipherEvpOperation(KM_PURPOSE_ENCRYPT, block_mode, padding, caller_iv, tag_length, - move(key), cipher_description) {} + std::move(key), cipher_description) {} keymaster_error_t Begin(const AuthorizationSet& input_params, AuthorizationSet* output_params) override; @@ -141,7 +143,7 @@ class BlockCipherEvpDecryptOperation : public BlockCipherEvpOperation { size_t tag_length, Key&& key, const EvpCipherDescription& cipher_description) : BlockCipherEvpOperation(KM_PURPOSE_DECRYPT, block_mode, padding, - false /* caller_iv -- don't care */, tag_length, move(key), + false /* caller_iv -- don't care */, tag_length, std::move(key), cipher_description) {} keymaster_error_t Begin(const AuthorizationSet& input_params, diff --git a/km_openssl/certificate_utils.cpp b/km_openssl/certificate_utils.cpp index 9118c68..17a34b0 100644 --- a/km_openssl/certificate_utils.cpp +++ b/km_openssl/certificate_utils.cpp @@ -15,6 +15,7 @@ */ #include <iostream> +#include <utility> #include <openssl/asn1.h> #include <openssl/evp.h> @@ -40,7 +41,7 @@ constexpr int kKeyAgreementKeyUsageBit = 4; constexpr int kMaxKeyUsageBit = 8; template <typename T> T&& min(T&& a, T&& b) { - return (a < b) ? forward<T>(a) : forward<T>(b); + return (a < b) ? std::forward<T>(a) : std::forward<T>(b); } keymaster_error_t fake_sign_cert(X509* cert) { @@ -76,7 +77,7 @@ keymaster_error_t make_name_from_str(const char name[], X509_NAME_Ptr* name_out) 0 /* set */)) { return TranslateLastOpenSslError(); } - *name_out = move(x509_name); + *name_out = std::move(x509_name); return KM_ERROR_OK; } @@ -89,7 +90,7 @@ keymaster_error_t make_name_from_der(const keymaster_blob_t& name, X509_NAME_Ptr return TranslateLastOpenSslError(); } - *name_out = move(x509_name); + *name_out = std::move(x509_name); return KM_ERROR_OK; } @@ -124,7 +125,7 @@ keymaster_error_t get_certificate_params(const AuthorizationSet& caller_params, // Default serial is one. BN_one(serial.get()); } - cert_params->serial = move(serial); + cert_params->serial = std::move(serial); cert_params->active_date_time = 0; cert_params->expire_date_time = kUndefinedExpirationDateTime; @@ -228,7 +229,7 @@ keymaster_error_t make_key_usage_extension(bool is_signing_key, bool is_encrypti return TranslateLastOpenSslError(); } - *usage_extension_out = move(key_usage_extension); + *usage_extension_out = std::move(key_usage_extension); return KM_ERROR_OK; } @@ -285,7 +286,7 @@ keymaster_error_t make_cert_rump(const X509_NAME* issuer, return TranslateLastOpenSslError(); } - *cert_out = move(certificate); + *cert_out = std::move(certificate); return KM_ERROR_OK; } @@ -315,7 +316,7 @@ keymaster_error_t make_cert(const EVP_PKEY* evp_pkey, const X509_NAME* issuer, return TranslateLastOpenSslError(); } - *cert_out = move(certificate); + *cert_out = std::move(certificate); return KM_ERROR_OK; } diff --git a/km_openssl/ec_key_factory.cpp b/km_openssl/ec_key_factory.cpp index 4ec3175..087ca63 100644 --- a/km_openssl/ec_key_factory.cpp +++ b/km_openssl/ec_key_factory.cpp @@ -16,6 +16,8 @@ #include <keymaster/km_openssl/ec_key_factory.h> +#include <utility> + #include <openssl/curve25519.h> #include <openssl/evp.h> @@ -178,14 +180,14 @@ keymaster_error_t EcKeyFactory::GenerateKey(const AuthorizationSet& key_descript } else if (is_x25519) { key.reset(new (std::nothrow) X25519Key(*hw_enforced, *sw_enforced, this, key_material)); } else { - key.reset(new (std::nothrow) EcKey(*hw_enforced, *sw_enforced, this, move(ec_key))); + key.reset(new (std::nothrow) EcKey(*hw_enforced, *sw_enforced, this, std::move(ec_key))); } if (key == nullptr) { return KM_ERROR_MEMORY_ALLOCATION_FAILED; } if (key_description.Contains(TAG_ATTESTATION_CHALLENGE)) { - *cert_chain = context_.GenerateAttestation(*key, key_description, move(attest_key), + *cert_chain = context_.GenerateAttestation(*key, key_description, std::move(attest_key), issuer_subject, &error); } else if (attest_key.get() != nullptr) { return KM_ERROR_ATTESTATION_CHALLENGE_MISSING; @@ -207,8 +209,8 @@ keymaster_error_t EcKeyFactory::ImportKey(const AuthorizationSet& key_descriptio AuthorizationSet* sw_enforced, CertificateChain* cert_chain) const { if (input_key_material_format == KM_KEY_FORMAT_RAW) { - return ImportRawKey(key_description, input_key_material, move(attest_key), issuer_subject, - output_key_blob, hw_enforced, sw_enforced, cert_chain); + return ImportRawKey(key_description, input_key_material, std::move(attest_key), + issuer_subject, output_key_blob, hw_enforced, sw_enforced, cert_chain); } if (!output_key_blob || !hw_enforced || !sw_enforced) return KM_ERROR_OUTPUT_PARAMETER_NULL; @@ -231,7 +233,7 @@ keymaster_error_t EcKeyFactory::ImportKey(const AuthorizationSet& key_descriptio if (error != KM_ERROR_OK) return error; std::unique_ptr<AsymmetricKey> key; - switch (EVP_PKEY_type(pkey->type)) { + switch (EVP_PKEY_id(pkey.get())) { case EVP_PKEY_ED25519: key.reset(new (std::nothrow) Ed25519Key(*hw_enforced, *sw_enforced, this)); if (key.get() == nullptr) { @@ -254,7 +256,7 @@ keymaster_error_t EcKeyFactory::ImportKey(const AuthorizationSet& key_descriptio EC_KEY_Ptr ec_key(EVP_PKEY_get1_EC_KEY(pkey.get())); if (!ec_key.get()) return KM_ERROR_INVALID_ARGUMENT; - key.reset(new (std::nothrow) EcKey(*hw_enforced, *sw_enforced, this, move(ec_key))); + key.reset(new (std::nothrow) EcKey(*hw_enforced, *sw_enforced, this, std::move(ec_key))); if (key.get() == nullptr) { return KM_ERROR_MEMORY_ALLOCATION_FAILED; } @@ -268,7 +270,7 @@ keymaster_error_t EcKeyFactory::ImportKey(const AuthorizationSet& key_descriptio } if (key_description.Contains(KM_TAG_ATTESTATION_CHALLENGE)) { - *cert_chain = context_.GenerateAttestation(*key, key_description, move(attest_key), + *cert_chain = context_.GenerateAttestation(*key, key_description, std::move(attest_key), issuer_subject, &error); } else if (attest_key.get() != nullptr) { return KM_ERROR_ATTESTATION_CHALLENGE_MISSING; @@ -359,7 +361,7 @@ keymaster_error_t EcKeyFactory::ImportRawKey(const AuthorizationSet& key_descrip } if (key_description.Contains(KM_TAG_ATTESTATION_CHALLENGE)) { - *cert_chain = context_.GenerateAttestation(*key, key_description, move(attest_key), + *cert_chain = context_.GenerateAttestation(*key, key_description, std::move(attest_key), issuer_subject, &error); } else if (attest_key.get() != nullptr) { return KM_ERROR_ATTESTATION_CHALLENGE_MISSING; @@ -392,7 +394,7 @@ keymaster_error_t EcKeyFactory::UpdateImportKeyDescription(const AuthorizationSe return KM_ERROR_IMPORT_PARAMETER_MISMATCH; } - switch (EVP_PKEY_type(pkey->type)) { + switch (EVP_PKEY_id(pkey.get())) { case EVP_PKEY_EC: { UniquePtr<EC_KEY, EC_KEY_Delete> ec_key(EVP_PKEY_get1_EC_KEY(pkey.get())); if (!ec_key.get()) return TranslateLastOpenSslError(); @@ -509,11 +511,13 @@ keymaster_error_t EcKeyFactory::CreateEmptyKey(AuthorizationSet&& hw_enforced, if (is_x25519) { return KM_ERROR_INCOMPATIBLE_PURPOSE; } - key->reset(new (std::nothrow) Ed25519Key(move(hw_enforced), move(sw_enforced), this)); + key->reset(new (std::nothrow) Ed25519Key(std::move(hw_enforced), std::move(sw_enforced), + this)); } else if (is_x25519) { - key->reset(new (std::nothrow) X25519Key(move(hw_enforced), move(sw_enforced), this)); + key->reset(new (std::nothrow) X25519Key(std::move(hw_enforced), std::move(sw_enforced), + this)); } else { - key->reset(new (std::nothrow) EcKey(move(hw_enforced), move(sw_enforced), this)); + key->reset(new (std::nothrow) EcKey(std::move(hw_enforced), std::move(sw_enforced), this)); } if (!(*key)) return KM_ERROR_MEMORY_ALLOCATION_FAILED; return KM_ERROR_OK; diff --git a/km_openssl/ecdh_operation.cpp b/km_openssl/ecdh_operation.cpp index 47f7361..1fa68df 100644 --- a/km_openssl/ecdh_operation.cpp +++ b/km_openssl/ecdh_operation.cpp @@ -16,13 +16,15 @@ #include <keymaster/km_openssl/ecdh_operation.h> +#include <utility> +#include <vector> + #include <keymaster/km_openssl/ec_key.h> #include <keymaster/km_openssl/openssl_err.h> #include <keymaster/km_openssl/openssl_utils.h> #include <keymaster/logger.h> #include <openssl/curve25519.h> #include <openssl/err.h> -#include <vector> namespace keymaster { @@ -149,14 +151,14 @@ OperationPtr EcdhOperationFactory::CreateOperation(Key&& key, *error = KM_ERROR_OK; EcdhOperation* op = nullptr; - switch (EVP_PKEY_type(pkey->type)) { + switch (EVP_PKEY_id(pkey.get())) { case EVP_PKEY_X25519: - op = new (std::nothrow) X25519Operation(move(key.hw_enforced_move()), - move(key.sw_enforced_move()), pkey.release()); + op = new (std::nothrow) X25519Operation(std::move(key.hw_enforced_move()), + std::move(key.sw_enforced_move()), pkey.release()); break; case EVP_PKEY_EC: - op = new (std::nothrow) EcdhOperation(move(key.hw_enforced_move()), - move(key.sw_enforced_move()), pkey.release()); + op = new (std::nothrow) EcdhOperation(std::move(key.hw_enforced_move()), + std::move(key.sw_enforced_move()), pkey.release()); break; default: *error = KM_ERROR_UNKNOWN_ERROR; diff --git a/km_openssl/hmac_key.cpp b/km_openssl/hmac_key.cpp index d74ff37..c8f2444 100644 --- a/km_openssl/hmac_key.cpp +++ b/km_openssl/hmac_key.cpp @@ -16,6 +16,8 @@ #include <keymaster/km_openssl/hmac_key.h> +#include <utility> + #include <openssl/err.h> #include <openssl/rand.h> @@ -52,7 +54,8 @@ keymaster_error_t HmacKeyFactory::LoadKey(KeymasterKeyBlob&& key_material, } key->reset(new (std::nothrow) - HmacKey(move(key_material), move(hw_enforced), move(sw_enforced), this)); + HmacKey(std::move(key_material), std::move(hw_enforced), std::move(sw_enforced), + this)); if (!key->get()) return KM_ERROR_MEMORY_ALLOCATION_FAILED; return KM_ERROR_OK; } diff --git a/km_openssl/hmac_operation.cpp b/km_openssl/hmac_operation.cpp index 759ca12..a05e200 100644 --- a/km_openssl/hmac_operation.cpp +++ b/km_openssl/hmac_operation.cpp @@ -16,6 +16,8 @@ #include "hmac_operation.h" +#include <utility> + #include <openssl/evp.h> #include <openssl/hmac.h> @@ -69,7 +71,7 @@ OperationPtr HmacOperationFactory::CreateOperation(Key&& key, const Authorizatio } UniquePtr<HmacOperation> op(new (std::nothrow) HmacOperation( - move(key), purpose(), digest, mac_length_bits / 8, min_mac_length_bits / 8)); + std::move(key), purpose(), digest, mac_length_bits / 8, min_mac_length_bits / 8)); if (!op.get()) *error = KM_ERROR_MEMORY_ALLOCATION_FAILED; else @@ -77,7 +79,7 @@ OperationPtr HmacOperationFactory::CreateOperation(Key&& key, const Authorizatio if (*error != KM_ERROR_OK) return nullptr; - return move(op); + return std::move(op); } static keymaster_digest_t supported_digests[] = {KM_DIGEST_SHA1, KM_DIGEST_SHA_2_224, diff --git a/km_openssl/openssl_utils.cpp b/km_openssl/openssl_utils.cpp index 2672cdc..6b91ecc 100644 --- a/km_openssl/openssl_utils.cpp +++ b/km_openssl/openssl_utils.cpp @@ -80,7 +80,7 @@ keymaster_error_t convert_pkcs8_blob_to_evp(const uint8_t* key_data, size_t key_ // Check the key type detected from the PKCS8 blob matches the KM algorithm we expect. keymaster_algorithm_t got_algorithm; - switch (EVP_PKEY_type((*pkey)->type)) { + switch (EVP_PKEY_id(pkey->get())) { case EVP_PKEY_RSA: got_algorithm = KM_ALGORITHM_RSA; break; @@ -91,13 +91,13 @@ keymaster_error_t convert_pkcs8_blob_to_evp(const uint8_t* key_data, size_t key_ break; default: LOG_E("EVP key algorithm was unknown (type %d), not the expected %d", - EVP_PKEY_type((*pkey)->type), expected_algorithm); + EVP_PKEY_id(pkey->get()), expected_algorithm); return KM_ERROR_INVALID_KEY_BLOB; } if (expected_algorithm != got_algorithm) { LOG_E("EVP key algorithm was %d (from type %d), not the expected %d", got_algorithm, - EVP_PKEY_type((*pkey)->type), expected_algorithm); + EVP_PKEY_id(pkey->get()), expected_algorithm); return KM_ERROR_INVALID_KEY_BLOB; } @@ -115,7 +115,7 @@ keymaster_error_t KeyMaterialToEvpKey(keymaster_key_format_t key_format, } keymaster_error_t EvpKeyToKeyMaterial(const EVP_PKEY* pkey, KeymasterKeyBlob* key_blob) { - switch (EVP_PKEY_type(pkey->type)) { + switch (EVP_PKEY_id(pkey)) { case EVP_PKEY_ED25519: case EVP_PKEY_X25519: { // BoringSSL's i2d_PrivateKey does not handle curve 25519 keys. diff --git a/km_openssl/rsa_key_factory.cpp b/km_openssl/rsa_key_factory.cpp index ed7162d..27f64e4 100644 --- a/km_openssl/rsa_key_factory.cpp +++ b/km_openssl/rsa_key_factory.cpp @@ -16,6 +16,8 @@ #include <keymaster/km_openssl/rsa_key_factory.h> +#include <utility> + #include <keymaster/keymaster_context.h> #include <keymaster/km_openssl/openssl_err.h> #include <keymaster/km_openssl/openssl_utils.h> @@ -101,9 +103,9 @@ keymaster_error_t RsaKeyFactory::GenerateKey(const AuthorizationSet& key_descrip if (context_.GetKmVersion() < KmVersion::KEYMINT_1) return KM_ERROR_OK; if (!cert_chain) return KM_ERROR_UNEXPECTED_NULL_POINTER; - RsaKey key(*hw_enforced, *sw_enforced, this, move(rsa_key)); + RsaKey key(*hw_enforced, *sw_enforced, this, std::move(rsa_key)); if (key_description.Contains(TAG_ATTESTATION_CHALLENGE)) { - *cert_chain = context_.GenerateAttestation(key, key_description, move(attest_key), + *cert_chain = context_.GenerateAttestation(key, key_description, std::move(attest_key), issuer_subject, &error); } else if (attest_key.get() != nullptr) { return KM_ERROR_ATTESTATION_CHALLENGE_MISSING; @@ -148,9 +150,9 @@ keymaster_error_t RsaKeyFactory::ImportKey(const AuthorizationSet& key_descripti RSA_Ptr rsa_key(EVP_PKEY_get1_RSA(pkey.get())); if (!rsa_key.get()) return KM_ERROR_INVALID_ARGUMENT; - RsaKey key(*hw_enforced, *sw_enforced, this, move(rsa_key)); + RsaKey key(*hw_enforced, *sw_enforced, this, std::move(rsa_key)); if (key_description.Contains(KM_TAG_ATTESTATION_CHALLENGE)) { - *cert_chain = context_.GenerateAttestation(key, key_description, move(attest_key), + *cert_chain = context_.GenerateAttestation(key, key_description, std::move(attest_key), issuer_subject, &error); } else if (attest_key.get() != nullptr) { return KM_ERROR_ATTESTATION_CHALLENGE_MISSING; @@ -212,7 +214,7 @@ keymaster_error_t RsaKeyFactory::UpdateImportKeyDescription(const AuthorizationS keymaster_error_t RsaKeyFactory::CreateEmptyKey(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, UniquePtr<AsymmetricKey>* key) const { - key->reset(new (std::nothrow) RsaKey(move(hw_enforced), move(sw_enforced), this)); + key->reset(new (std::nothrow) RsaKey(std::move(hw_enforced), std::move(sw_enforced), this)); if (!(*key)) return KM_ERROR_MEMORY_ALLOCATION_FAILED; return KM_ERROR_OK; } diff --git a/km_openssl/rsa_operation.cpp b/km_openssl/rsa_operation.cpp index a4710d4..e445321 100644 --- a/km_openssl/rsa_operation.cpp +++ b/km_openssl/rsa_operation.cpp @@ -16,6 +16,8 @@ #include <keymaster/km_openssl/rsa_operation.h> +#include <utility> + #include <limits.h> #include <openssl/err.h> @@ -98,7 +100,7 @@ RsaOperation* RsaCryptingOperationFactory::CreateRsaOperation(Key&& key, *error = GetAndValidateMgfDigest(begin_params, key, &mgf_digest); if (*error != KM_ERROR_OK) return nullptr; UniquePtr<RsaOperation> op( - RsaOperationFactory::CreateRsaOperation(move(key), begin_params, error)); + RsaOperationFactory::CreateRsaOperation(std::move(key), begin_params, error)); if (op.get()) { switch (op->padding()) { case KM_PAD_NONE: @@ -240,7 +242,7 @@ RsaDigestingOperation::RsaDigestingOperation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_purpose_t purpose, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key) - : RsaOperation(move(hw_enforced), move(sw_enforced), purpose, digest, padding, key) { + : RsaOperation(std::move(hw_enforced), std::move(sw_enforced), purpose, digest, padding, key) { EVP_MD_CTX_init(&digest_ctx_); } RsaDigestingOperation::~RsaDigestingOperation() { diff --git a/km_openssl/soft_keymaster_enforcement.cpp b/km_openssl/soft_keymaster_enforcement.cpp index 0a3c2f6..0f5df6e 100644 --- a/km_openssl/soft_keymaster_enforcement.cpp +++ b/km_openssl/soft_keymaster_enforcement.cpp @@ -29,6 +29,10 @@ #include <keymaster/km_openssl/openssl_err.h> #include <keymaster/km_openssl/openssl_utils.h> +#ifdef _WIN32 +#include <sysinfoapi.h> +#endif + namespace keymaster { namespace { @@ -52,11 +56,15 @@ class EvpMdCtx { } // anonymous namespace uint64_t SoftKeymasterEnforcement::get_current_time_ms() const { +#ifdef _WIN32 + return GetTickCount64(); +#else struct timespec tp; int err = clock_gettime(CLOCK_BOOTTIME, &tp); if (err || tp.tv_sec < 0) return 0; return static_cast<uint64_t>(tp.tv_sec) * 1000 + static_cast<uint64_t>(tp.tv_nsec) / 1000000; +#endif } bool SoftKeymasterEnforcement::CreateKeyId(const keymaster_key_blob_t& key_blob, diff --git a/km_openssl/symmetric_key.cpp b/km_openssl/symmetric_key.cpp index 1b89d66..d60d9f8 100644 --- a/km_openssl/symmetric_key.cpp +++ b/km_openssl/symmetric_key.cpp @@ -16,6 +16,8 @@ #include <keymaster/km_openssl/symmetric_key.h> +#include <utility> + #include <assert.h> #include <openssl/err.h> @@ -105,8 +107,8 @@ SymmetricKeyFactory::SupportedImportFormats(size_t* format_count) const { SymmetricKey::SymmetricKey(KeymasterKeyBlob&& key_material, AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, const KeyFactory* key_factory) - : Key(move(hw_enforced), move(sw_enforced), key_factory) { - key_material_ = move(key_material); + : Key(std::move(hw_enforced), std::move(sw_enforced), key_factory) { + key_material_ = std::move(key_material); } SymmetricKey::~SymmetricKey() {} diff --git a/km_openssl/triple_des_key.cpp b/km_openssl/triple_des_key.cpp index 8c267e6..d60d204 100644 --- a/km_openssl/triple_des_key.cpp +++ b/km_openssl/triple_des_key.cpp @@ -16,6 +16,8 @@ #include <keymaster/km_openssl/triple_des_key.h> +#include <utility> + #include <assert.h> #include <openssl/err.h> @@ -48,7 +50,8 @@ keymaster_error_t TripleDesKeyFactory::LoadKey(KeymasterKeyBlob&& key_material, keymaster_error_t error = KM_ERROR_OK; key->reset(new (std::nothrow) - TripleDesKey(move(key_material), move(hw_enforced), move(sw_enforced), this)); + TripleDesKey(std::move(key_material), std::move(hw_enforced), + std::move(sw_enforced), this)); if (!key->get()) error = KM_ERROR_MEMORY_ALLOCATION_FAILED; return error; } diff --git a/legacy_support/ec_keymaster1_key.cpp b/legacy_support/ec_keymaster1_key.cpp index ddb3725..64c6916 100644 --- a/legacy_support/ec_keymaster1_key.cpp +++ b/legacy_support/ec_keymaster1_key.cpp @@ -17,6 +17,7 @@ #include <keymaster/legacy_support/ec_keymaster1_key.h> #include <memory> +#include <utility> #include <keymaster/km_openssl/ecdsa_operation.h> #include <keymaster/logger.h> @@ -112,10 +113,11 @@ keymaster_error_t EcdsaKeymaster1KeyFactory::LoadKey(KeymasterKeyBlob&& key_mate if (!ecdsa) return error; key->reset(new (std::nothrow) - EcdsaKeymaster1Key(ecdsa.release(), move(hw_enforced), move(sw_enforced), this)); + EcdsaKeymaster1Key(ecdsa.release(), std::move(hw_enforced), + std::move(sw_enforced), this)); if (!(*key)) return KM_ERROR_MEMORY_ALLOCATION_FAILED; - (*key)->key_material() = move(key_material); + (*key)->key_material() = std::move(key_material); return KM_ERROR_OK; } diff --git a/legacy_support/ecdsa_keymaster1_operation.h b/legacy_support/ecdsa_keymaster1_operation.h index e52deae..2b6d2b8 100644 --- a/legacy_support/ecdsa_keymaster1_operation.h +++ b/legacy_support/ecdsa_keymaster1_operation.h @@ -17,6 +17,8 @@ #ifndef SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_OPERATION_H_ #define SYSTEM_KEYMASTER_ECDSA_KEYMASTER1_OPERATION_H_ +#include <utility> + #include <openssl/evp.h> #include <hardware/keymaster1.h> @@ -56,7 +58,7 @@ template <typename BaseOperation> class EcdsaKeymaster1Operation : public BaseOp EcdsaKeymaster1Operation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, EVP_PKEY* key, const Keymaster1Engine* engine) - : BaseOperation(move(hw_enforced), move(sw_enforced), digest, key), + : BaseOperation(std::move(hw_enforced), std::move(sw_enforced), digest, key), wrapped_operation_(super::purpose(), engine) { // Shouldn't be instantiated for public key operations. assert(super::purpose() != KM_PURPOSE_VERIFY); diff --git a/legacy_support/keymaster1_engine.cpp b/legacy_support/keymaster1_engine.cpp index 4cd16e5..10bfc57 100644 --- a/legacy_support/keymaster1_engine.cpp +++ b/legacy_support/keymaster1_engine.cpp @@ -203,7 +203,7 @@ EC_KEY* Keymaster1Engine::BuildEcKey(const KeymasterKeyBlob& blob, } Keymaster1Engine::KeyData* Keymaster1Engine::GetData(EVP_PKEY* key) const { - switch (EVP_PKEY_type(key->type)) { + switch (EVP_PKEY_id(key)) { case EVP_PKEY_RSA: { unique_ptr<RSA, RSA_Delete> rsa(EVP_PKEY_get1_RSA(key)); return GetData(rsa.get()); diff --git a/legacy_support/keymaster1_legacy_support.cpp b/legacy_support/keymaster1_legacy_support.cpp index 3fd5cb4..b327ce3 100644 --- a/legacy_support/keymaster1_legacy_support.cpp +++ b/legacy_support/keymaster1_legacy_support.cpp @@ -23,6 +23,7 @@ #include <algorithm> #include <vector> +#include <utility> namespace keymaster { @@ -228,7 +229,7 @@ keymaster_error_t Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::Gener AuthorizationSet* sw_enforced, // CertificateChain* cert_chain) const { if (legacy_support_.RequiresSoftwareDigesting(key_description)) { - return software_digest_factory_.GenerateKey(key_description, move(attest_key), + return software_digest_factory_.GenerateKey(key_description, std::move(attest_key), issuer_subject, key_blob, hw_enforced, sw_enforced, cert_chain); } else { @@ -252,7 +253,7 @@ keymaster_error_t Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::Gener } } - return passthrough_factory_.GenerateKey(mutable_key_description, move(attest_key), + return passthrough_factory_.GenerateKey(mutable_key_description, std::move(attest_key), issuer_subject, key_blob, hw_enforced, sw_enforced, cert_chain); } @@ -268,8 +269,8 @@ keymaster_error_t Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::LoadK } bool requires_software_digesting = legacy_support_.RequiresSoftwareDigesting(digest, AuthProxy(hw_enforced, sw_enforced)); - auto rc = software_digest_factory_.LoadKey(move(key_material), additional_params, - move(hw_enforced), move(sw_enforced), key); + auto rc = software_digest_factory_.LoadKey(std::move(key_material), additional_params, + std::move(hw_enforced), std::move(sw_enforced), key); if (rc != KM_ERROR_OK) return rc; if (!requires_software_digesting) { (*key)->key_factory() = &passthrough_factory_; @@ -287,8 +288,8 @@ keymaster_error_t Keymaster1ArbitrationFactory<RsaKeymaster1KeyFactory>::LoadKey } bool requires_software_digesting = legacy_support_.RequiresSoftwareDigesting(digest, AuthProxy(hw_enforced, sw_enforced)); - auto rc = software_digest_factory_.LoadKey(move(key_material), additional_params, - move(hw_enforced), move(sw_enforced), key); + auto rc = software_digest_factory_.LoadKey(std::move(key_material), additional_params, + std::move(hw_enforced), std::move(sw_enforced), key); if (rc != KM_ERROR_OK) return rc; if (!requires_software_digesting) { (*key)->key_factory() = &passthrough_factory_; diff --git a/legacy_support/keymaster_passthrough_key.cpp b/legacy_support/keymaster_passthrough_key.cpp index 52b56e8..b649684 100644 --- a/legacy_support/keymaster_passthrough_key.cpp +++ b/legacy_support/keymaster_passthrough_key.cpp @@ -17,6 +17,8 @@ #include <keymaster/legacy_support/keymaster_passthrough_key.h> +#include <utility> + namespace keymaster { keymaster_error_t KeymasterPassthroughKeyFactory::LoadKey(KeymasterKeyBlob&& key_material, @@ -28,8 +30,9 @@ keymaster_error_t KeymasterPassthroughKeyFactory::LoadKey(KeymasterKeyBlob&& key if (!key) return KM_ERROR_OUTPUT_PARAMETER_NULL; key->reset(new (std::nothrow) - KeymasterPassthroughKey(move(key_material), move(hw_enforced), move(sw_enforced), - this, &error, additional_params, engine_)); + KeymasterPassthroughKey(std::move(key_material), std::move(hw_enforced), + std::move(sw_enforced), this, &error, additional_params, + engine_)); if (!key->get()) error = KM_ERROR_MEMORY_ALLOCATION_FAILED; return error; diff --git a/legacy_support/keymaster_passthrough_operation.cpp b/legacy_support/keymaster_passthrough_operation.cpp index 7b10722..c98449d 100644 --- a/legacy_support/keymaster_passthrough_operation.cpp +++ b/legacy_support/keymaster_passthrough_operation.cpp @@ -17,6 +17,7 @@ #include "keymaster_passthrough_operation.h" #include <keymaster/android_keymaster_utils.h> +#include <utility> #include <vector> namespace keymaster { @@ -85,7 +86,7 @@ keymaster_error_t KeymasterPassthroughOperation<keymaster1_device_t>::Finish( } accumulated_out_params.Deduplicate(); - if (output_params) *output_params = move(accumulated_out_params); + if (output_params) *output_params = std::move(accumulated_out_params); return KM_ERROR_OK; } diff --git a/legacy_support/rsa_keymaster1_key.cpp b/legacy_support/rsa_keymaster1_key.cpp index ff5576c..89ed859 100644 --- a/legacy_support/rsa_keymaster1_key.cpp +++ b/legacy_support/rsa_keymaster1_key.cpp @@ -14,9 +14,11 @@ * limitations under the License. */ -#include <keymaster/contexts/soft_keymaster_context.h> #include <keymaster/legacy_support/rsa_keymaster1_key.h> +#include <utility> + +#include <keymaster/contexts/soft_keymaster_context.h> #include <keymaster/km_openssl/openssl_utils.h> #include <keymaster/logger.h> @@ -121,10 +123,11 @@ keymaster_error_t RsaKeymaster1KeyFactory::LoadKey(KeymasterKeyBlob&& key_materi if (!rsa.get()) return error; key->reset(new (std::nothrow) - RsaKeymaster1Key(rsa.release(), move(hw_enforced), move(sw_enforced), this)); + RsaKeymaster1Key(rsa.release(), std::move(hw_enforced), std::move(sw_enforced), + this)); if (!(*key)) return KM_ERROR_MEMORY_ALLOCATION_FAILED; - (*key)->key_material() = move(key_material); + (*key)->key_material() = std::move(key_material); return KM_ERROR_OK; } diff --git a/legacy_support/rsa_keymaster1_operation.h b/legacy_support/rsa_keymaster1_operation.h index 124c4b7..fb0eda9 100644 --- a/legacy_support/rsa_keymaster1_operation.h +++ b/legacy_support/rsa_keymaster1_operation.h @@ -16,6 +16,8 @@ #pragma once +#include <utility> + #include <openssl/evp.h> #include <hardware/keymaster1.h> @@ -55,7 +57,7 @@ template <typename BaseOperation> class RsaKeymaster1Operation : public BaseOper RsaKeymaster1Operation(AuthorizationSet&& hw_enforced, AuthorizationSet&& sw_enforced, keymaster_digest_t digest, keymaster_padding_t padding, EVP_PKEY* key, const Keymaster1Engine* engine) - : BaseOperation(move(hw_enforced), move(sw_enforced), digest, padding, key), + : BaseOperation(std::move(hw_enforced), std::move(sw_enforced), digest, padding, key), wrapped_operation_(super::purpose(), engine) { // Shouldn't be instantiated for public key operations. assert(super::purpose() != KM_PURPOSE_VERIFY); diff --git a/ng/AndroidKeyMintDevice.cpp b/ng/AndroidKeyMintDevice.cpp index 25ad463..fb7b632 100644 --- a/ng/AndroidKeyMintDevice.cpp +++ b/ng/AndroidKeyMintDevice.cpp @@ -108,6 +108,7 @@ vector<KeyCharacteristics> convertKeyCharacteristics(SecurityLevel keyMintSecuri case KM_TAG_ATTESTATION_ID_BRAND: case KM_TAG_ATTESTATION_ID_DEVICE: case KM_TAG_ATTESTATION_ID_IMEI: + case KM_TAG_ATTESTATION_ID_SECOND_IMEI: case KM_TAG_ATTESTATION_ID_MANUFACTURER: case KM_TAG_ATTESTATION_ID_MEID: case KM_TAG_ATTESTATION_ID_MODEL: @@ -213,10 +214,10 @@ void addClientAndAppData(const std::vector<uint8_t>& appId, const std::vector<ui constexpr size_t kOperationTableSize = 16; AndroidKeyMintDevice::AndroidKeyMintDevice(SecurityLevel securityLevel) - : impl_(new (std::nothrow)::keymaster::AndroidKeymaster( + : impl_(new(std::nothrow)::keymaster::AndroidKeymaster( [&]() -> auto{ auto context = new (std::nothrow) PureSoftKeymasterContext( - KmVersion::KEYMINT_2, static_cast<keymaster_security_level_t>(securityLevel)); + KmVersion::KEYMINT_3, static_cast<keymaster_security_level_t>(securityLevel)); context->SetSystemVersion(::keymaster::GetOsVersion(), ::keymaster::GetOsPatchlevel()); context->SetVendorPatchlevel(::keymaster::GetVendorPatchlevel()); @@ -241,7 +242,7 @@ AndroidKeyMintDevice::AndroidKeyMintDevice(SecurityLevel securityLevel) AndroidKeyMintDevice::~AndroidKeyMintDevice() {} ScopedAStatus AndroidKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) { - info->versionNumber = 2; + info->versionNumber = 3; info->securityLevel = securityLevel_; info->keyMintName = "FakeKeyMintDevice"; info->keyMintAuthorName = "Google"; diff --git a/ng/AndroidKeyMintOperation.cpp b/ng/AndroidKeyMintOperation.cpp index 17f6b33..b886bd7 100644 --- a/ng/AndroidKeyMintOperation.cpp +++ b/ng/AndroidKeyMintOperation.cpp @@ -50,11 +50,16 @@ AndroidKeyMintOperation::~AndroidKeyMintOperation() { ScopedAStatus AndroidKeyMintOperation::updateAad(const vector<uint8_t>& input, - const optional<HardwareAuthToken>& /* authToken */, + const optional<HardwareAuthToken>& authToken, const optional<TimeStampToken>& /* timestampToken */) { UpdateOperationRequest request(impl_->message_version()); request.op_handle = opHandle_; request.additional_params.push_back(TAG_ASSOCIATED_DATA, input.data(), input.size()); + if (authToken) { + auto tokenAsVec(authToken2AidlVec(*authToken)); + request.additional_params.push_back(keymaster::TAG_AUTH_TOKEN, tokenAsVec.data(), + tokenAsVec.size()); + } UpdateOperationResponse response(impl_->message_version()); impl_->UpdateOperation(request, &response); @@ -63,7 +68,7 @@ AndroidKeyMintOperation::updateAad(const vector<uint8_t>& input, } ScopedAStatus AndroidKeyMintOperation::update(const vector<uint8_t>& input, - const optional<HardwareAuthToken>& /* authToken */, + const optional<HardwareAuthToken>& authToken, const optional<TimeStampToken>& /* timestampToken */, vector<uint8_t>* output) { @@ -72,6 +77,11 @@ ScopedAStatus AndroidKeyMintOperation::update(const vector<uint8_t>& input, UpdateOperationRequest request(impl_->message_version()); request.op_handle = opHandle_; request.input.Reinitialize(input.data(), input.size()); + if (authToken) { + auto tokenAsVec(authToken2AidlVec(*authToken)); + request.additional_params.push_back(keymaster::TAG_AUTH_TOKEN, tokenAsVec.data(), + tokenAsVec.size()); + } UpdateOperationResponse response(impl_->message_version()); impl_->UpdateOperation(request, &response); @@ -88,7 +98,7 @@ ScopedAStatus AndroidKeyMintOperation::update(const vector<uint8_t>& input, ScopedAStatus AndroidKeyMintOperation::finish(const optional<vector<uint8_t>>& input, // const optional<vector<uint8_t>>& signature, // - const optional<HardwareAuthToken>& /* authToken */, + const optional<HardwareAuthToken>& authToken, const optional<TimeStampToken>& /* timestampToken */, const optional<vector<uint8_t>>& /* confirmationToken */, vector<uint8_t>* output) { @@ -102,6 +112,11 @@ AndroidKeyMintOperation::finish(const optional<vector<uint8_t>>& input, // request.op_handle = opHandle_; if (input) request.input.Reinitialize(input->data(), input->size()); if (signature) request.signature.Reinitialize(signature->data(), signature->size()); + if (authToken) { + auto tokenAsVec(authToken2AidlVec(*authToken)); + request.additional_params.push_back(keymaster::TAG_AUTH_TOKEN, tokenAsVec.data(), + tokenAsVec.size()); + } FinishOperationResponse response(impl_->message_version()); impl_->FinishOperation(request, &response); diff --git a/ng/AndroidRemotelyProvisionedComponentDevice.cpp b/ng/AndroidRemotelyProvisionedComponentDevice.cpp index 54ea70c..c8d4070 100644 --- a/ng/AndroidRemotelyProvisionedComponentDevice.cpp +++ b/ng/AndroidRemotelyProvisionedComponentDevice.cpp @@ -35,8 +35,12 @@ namespace aidl::android::hardware::security::keymint { using keymaster::GenerateCsrRequest; using keymaster::GenerateCsrResponse; +using keymaster::GenerateCsrV2Request; +using keymaster::GenerateCsrV2Response; using keymaster::GenerateRkpKeyRequest; using keymaster::GenerateRkpKeyResponse; +using keymaster::GetHwInfoRequest; +using keymaster::GetHwInfoResponse; using keymaster::KeymasterBlob; using ::std::string; using ::std::unique_ptr; @@ -83,10 +87,16 @@ AndroidRemotelyProvisionedComponentDevice::AndroidRemotelyProvisionedComponentDe } ScopedAStatus AndroidRemotelyProvisionedComponentDevice::getHardwareInfo(RpcHardwareInfo* info) { - info->versionNumber = 2; - info->rpcAuthorName = "Google"; - info->supportedEekCurve = RpcHardwareInfo::CURVE_25519; - info->uniqueId = "default keymint"; + GetHwInfoResponse response = impl_->GetHwInfo(); + if (response.error != KM_ERROR_OK) { + return Status(-static_cast<int32_t>(response.error), "Failed to get hardware info."); + } + + info->versionNumber = response.version; + info->rpcAuthorName = response.rpcAuthorName; + info->supportedEekCurve = response.supportedEekCurve; + info->uniqueId = response.uniqueId; + info->supportedNumKeysInCsr = response.supportedNumKeysInCsr; return ScopedAStatus::ok(); } @@ -133,4 +143,25 @@ ScopedAStatus AndroidRemotelyProvisionedComponentDevice::generateCertificateRequ return ScopedAStatus::ok(); } +ScopedAStatus AndroidRemotelyProvisionedComponentDevice::generateCertificateRequestV2( + const std::vector<MacedPublicKey>& keysToSign, const std::vector<uint8_t>& challenge, + std::vector<uint8_t>* csr) { + GenerateCsrV2Request request(impl_->message_version()); + if (!request.InitKeysToSign(keysToSign.size())) { + return km_utils::kmError2ScopedAStatus(static_cast<keymaster_error_t>(STATUS_FAILED)); + } + for (size_t i = 0; i < keysToSign.size(); i++) { + request.SetKeyToSign(i, keysToSign[i].macedKey.data(), keysToSign[i].macedKey.size()); + } + request.SetChallenge(challenge.data(), challenge.size()); + GenerateCsrV2Response response(impl_->message_version()); + impl_->GenerateCsrV2(request, &response); + + if (response.error != KM_ERROR_OK) { + return Status(-static_cast<int32_t>(response.error), "Failure in CSR v2 generation."); + } + *csr = km_utils::kmBlob2vector(response.csr); + return ScopedAStatus::ok(); +} + } // namespace aidl::android::hardware::security::keymint diff --git a/ng/KeyMintAidlUtils.cpp b/ng/KeyMintAidlUtils.cpp index 28b5744..8f78027 100644 --- a/ng/KeyMintAidlUtils.cpp +++ b/ng/KeyMintAidlUtils.cpp @@ -24,30 +24,6 @@ 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) { diff --git a/ng/KeyMintUtils.cpp b/ng/KeyMintUtils.cpp index 45967fd..98763fd 100644 --- a/ng/KeyMintUtils.cpp +++ b/ng/KeyMintUtils.cpp @@ -39,6 +39,12 @@ KeyParameter kmEnumParam2Aidl(const keymaster_key_param_t& param) { case KM_TAG_DIGEST: return KeyParameter{Tag::DIGEST, KeyParameterValue::make<KeyParameterValue::digest>( static_cast<Digest>(param.enumerated))}; + + case KM_TAG_RSA_OAEP_MGF_DIGEST: + return KeyParameter{Tag::RSA_OAEP_MGF_DIGEST, + KeyParameterValue::make<KeyParameterValue::digest>( + static_cast<Digest>(param.enumerated))}; + case KM_TAG_PADDING: return KeyParameter{Tag::PADDING, KeyParameterValue::make<KeyParameterValue::paddingMode>( static_cast<PaddingMode>(param.enumerated))}; @@ -52,10 +58,17 @@ KeyParameter kmEnumParam2Aidl(const keymaster_key_param_t& param) { case KM_TAG_ORIGIN: return KeyParameter{Tag::ORIGIN, KeyParameterValue::make<KeyParameterValue::origin>( static_cast<KeyOrigin>(param.enumerated))}; + case KM_TAG_BLOB_USAGE_REQUIREMENTS: case KM_TAG_KDF: - default: return KeyParameter{Tag::INVALID, false}; + + default: + // Unknown tag. We can't represent it properly because it's some unknown enum. But KeyMint + // specs require us to return unknown tags. Pretending it's an integer value is the best we + // can do. Upstream will have to deal with it. + return KeyParameter{static_cast<Tag>(param.tag), + KeyParameterValue::make<KeyParameterValue::integer>(param.enumerated)}; } } @@ -90,9 +103,11 @@ keymaster_key_param_t aidlEnumParam2Km(const KeyParameter& param) { return aidlEnumVal2Km<KeyParameterValue::origin>(tag, param.value); case KM_TAG_BLOB_USAGE_REQUIREMENTS: case KM_TAG_KDF: + CHECK(false) << "Unused enum tag: Something is broken"; + return keymaster_param_enum(KM_TAG_INVALID, false); default: - CHECK(false) << "Unknown or unused enum tag: Something is broken"; - return keymaster_param_enum(tag, false); + // Unknown tag. This can happen when system is newer than secure world. Pass it through. + return keymaster_param_enum(tag, param.value.get<KeyParameterValue::integer>()); } } @@ -108,7 +123,7 @@ vector<uint8_t> authToken2AidlVec(const std::optional<HardwareAuthToken>& token) vector<uint8_t> result; if (!token.has_value()) return result; - if (token->mac.size() < 32) return result; + if (token->mac.size() != 32) return result; result.resize(sizeof(hw_auth_token_t)); auto pos = result.begin(); @@ -129,7 +144,6 @@ KeyParameter kmParam2Aidl(const keymaster_key_param_t& param) { case KM_ENUM: case KM_ENUM_REP: return kmEnumParam2Aidl(param); - break; case KM_UINT: case KM_UINT_REP: @@ -140,28 +154,23 @@ KeyParameter kmParam2Aidl(const keymaster_key_param_t& param) { case KM_ULONG_REP: return KeyParameter{ tag, KeyParameterValue::make<KeyParameterValue::longInteger>(param.long_integer)}; - break; case KM_DATE: return KeyParameter{tag, KeyParameterValue::make<KeyParameterValue::dateTime>(param.date_time)}; - break; case KM_BOOL: return KeyParameter{tag, param.boolean}; - break; case KM_BIGNUM: case KM_BYTES: return {tag, KeyParameterValue::make<KeyParameterValue::blob>( std::vector(param.blob.data, param.blob.data + param.blob.data_length))}; - break; case KM_INVALID: default: CHECK(false) << "Unknown or unused tag type: Something is broken"; return KeyParameter{Tag::INVALID, false}; - break; } } diff --git a/ng/include/AndroidRemotelyProvisionedComponentDevice.h b/ng/include/AndroidRemotelyProvisionedComponentDevice.h index eef81f3..9879a94 100644 --- a/ng/include/AndroidRemotelyProvisionedComponentDevice.h +++ b/ng/include/AndroidRemotelyProvisionedComponentDevice.h @@ -46,6 +46,10 @@ class AndroidRemotelyProvisionedComponentDevice : public BnRemotelyProvisionedCo DeviceInfo* deviceInfo, ProtectedData* protectedData, std::vector<uint8_t>* keysToSignMac) override; + ScopedAStatus generateCertificateRequestV2(const std::vector<MacedPublicKey>& keysToSign, + const std::vector<uint8_t>& challenge, + std::vector<uint8_t>* csr) override; + private: std::shared_ptr<::keymaster::AndroidKeymaster> impl_; }; diff --git a/tests/android_keymaster_messages_test.cpp b/tests/android_keymaster_messages_test.cpp index 6b873b4..fc0923e 100644 --- a/tests/android_keymaster_messages_test.cpp +++ b/tests/android_keymaster_messages_test.cpp @@ -249,6 +249,46 @@ TEST(RoundTrip, GenerateCsrResponse) { } } +TEST(RoundTrip, GenerateCsrV2Request) { + for (int ver = 0; ver <= kMaxMessageVersion; ++ver) { + GenerateCsrV2Request req(ver); + EXPECT_TRUE(req.InitKeysToSign(2)); + for (size_t i = 0; i < req.num_keys; i++) { + req.SetKeyToSign(i, dup_array(TEST_DATA), array_length(TEST_DATA)); + } + req.SetChallenge(dup_array(TEST_DATA), array_length(TEST_DATA)); + UniquePtr<GenerateCsrV2Request> deserialized(round_trip(ver, req, 49)); + EXPECT_EQ(deserialized->num_keys, req.num_keys); + for (int i = 0; i < (int)req.num_keys; i++) { + EXPECT_EQ(deserialized->keys_to_sign_array[i].data_length, + req.keys_to_sign_array[i].data_length); + EXPECT_EQ(0, std::memcmp(deserialized->keys_to_sign_array[i].data, + req.keys_to_sign_array[i].data, + req.keys_to_sign_array[i].data_length)); + } + EXPECT_EQ(deserialized->challenge.data_length, req.challenge.data_length); + EXPECT_EQ(0, std::memcmp(deserialized->challenge.data, req.challenge.data, + req.challenge.data_length)); + } +} + +TEST(RoundTrip, GenerateCsrV2Response) { + for (int ver = 0; ver <= kMaxMessageVersion; ++ver) { + GenerateCsrV2Response rsp(ver); + rsp.error = KM_ERROR_OK; + rsp.csr.data = dup_array(TEST_DATA); + rsp.csr.data_length = array_length(TEST_DATA); + + UniquePtr<GenerateCsrV2Response> deserialized; + deserialized.reset(round_trip(ver, rsp, 19)); + + EXPECT_EQ(KM_ERROR_OK, deserialized->error); + EXPECT_EQ(deserialized->csr.data_length, rsp.csr.data_length); + EXPECT_EQ(0, + std::memcmp(deserialized->csr.data, rsp.csr.data, deserialized->csr.data_length)); + } +} + TEST(RoundTrip, GetKeyCharacteristicsRequest) { for (int ver = 0; ver <= kMaxMessageVersion; ++ver) { GetKeyCharacteristicsRequest req(ver); @@ -867,6 +907,28 @@ TEST(RoundTrip, GetRootOfTrustResponse) { } } +TEST(RoundTrip, GetHwInfoResponse) { + for (int ver = 0; ver <= kMaxMessageVersion; ++ver) { + GetHwInfoResponse rsp(ver); + rsp.error = KM_ERROR_OK; + rsp.version = 17; + rsp.rpcAuthorName = "AAAAA"; + rsp.supportedEekCurve = 48; + rsp.uniqueId = "BBBBB"; + rsp.supportedNumKeysInCsr = 549; + + UniquePtr<GetHwInfoResponse> deserialized; + deserialized.reset(round_trip(ver, rsp, 34)); + + EXPECT_EQ(KM_ERROR_OK, deserialized->error); + EXPECT_EQ(deserialized->version, rsp.version); + EXPECT_EQ(deserialized->rpcAuthorName, rsp.rpcAuthorName); + EXPECT_EQ(deserialized->supportedEekCurve, rsp.supportedEekCurve); + EXPECT_EQ(deserialized->uniqueId, rsp.uniqueId); + EXPECT_EQ(deserialized->supportedNumKeysInCsr, rsp.supportedNumKeysInCsr); + } +} + #define SET_ATTESTATION_ID(x) msg.x.Reinitialize(#x, strlen(#x)) void check_id(const Buffer& id, const char* value) { @@ -900,6 +962,31 @@ TEST(RoundTrip, SetAttestationIdsRequest) { } } +TEST(RoundTrip, SetAttestationIdsKM3Request) { + for (int ver = 0; ver <= kMaxMessageVersion; ++ver) { + SetAttestationIdsKM3Request msg(ver); + SET_ATTESTATION_ID(base.brand); + SET_ATTESTATION_ID(base.device); + SET_ATTESTATION_ID(base.product); + SET_ATTESTATION_ID(base.serial); + SET_ATTESTATION_ID(base.imei); + SET_ATTESTATION_ID(base.meid); + SET_ATTESTATION_ID(base.manufacturer); + SET_ATTESTATION_ID(base.model); + SET_ATTESTATION_ID(second_imei); + + UniquePtr<SetAttestationIdsKM3Request> deserialized(round_trip(ver, msg, 136)); + ASSERT_TRUE(deserialized); + CHECK_ID(base.brand); + CHECK_ID(base.device); + CHECK_ID(base.product); + CHECK_ID(base.serial); + CHECK_ID(base.imei); + CHECK_ID(base.model); + CHECK_ID(second_imei); + } +} + uint8_t msgbuf[] = { 220, 88, 183, 255, 71, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 228, 174, 98, 187, 191, 135, 253, 200, 51, 230, 114, 247, 151, 109, @@ -966,7 +1053,9 @@ template <typename Message> void parse_garbage() { } #define GARBAGE_TEST(Message) \ - TEST(GarbageTest, Message) { parse_garbage<Message>(); } + TEST(GarbageTest, Message) { \ + parse_garbage<Message>(); \ + } GARBAGE_TEST(AbortOperationRequest); GARBAGE_TEST(EmptyKeymasterResponse); @@ -994,6 +1083,7 @@ GARBAGE_TEST(UpgradeKeyResponse); GARBAGE_TEST(GenerateTimestampTokenRequest); GARBAGE_TEST(GenerateTimestampTokenResponse); GARBAGE_TEST(SetAttestationIdsRequest); +GARBAGE_TEST(SetAttestationIdsKM3Request); GARBAGE_TEST(ConfigureVerifiedBootInfoRequest); GARBAGE_TEST(GetRootOfTrustRequest); GARBAGE_TEST(GetRootOfTrustResponse); diff --git a/tests/key_blob_test.cpp b/tests/key_blob_test.cpp index f69551b..2c751f1 100644 --- a/tests/key_blob_test.cpp +++ b/tests/key_blob_test.cpp @@ -15,6 +15,7 @@ */ #include <algorithm> +#include <utility> #include <gtest/gtest.h> @@ -79,7 +80,7 @@ class KeyBlobTest : public ::testing::TestWithParam<AuthEncryptedBlobFormat>, keymaster_error_t Decrypt() { auto result = - DecryptKey(move(deserialized_key_), hidden_, secure_deletion_data_, master_key_); + DecryptKey(std::move(deserialized_key_), hidden_, secure_deletion_data_, master_key_); if (!result) return result.error(); decrypted_plaintext_ = std::move(*result); return KM_ERROR_OK; |