diff options
author | David Drysdale <drysdale@google.com> | 2021-10-13 10:19:38 +0100 |
---|---|---|
committer | David Drysdale <drysdale@google.com> | 2021-11-10 15:05:36 +0000 |
commit | 22146e47b26b87bccc826657cefe02206571621c (patch) | |
tree | b8b8094a390e1e3c6d14c06835fb47dc97a0c5ec | |
parent | eaad67939432456802418579e3b7cbceb1b2cbd6 (diff) | |
download | keymaster-22146e47b26b87bccc826657cefe02206571621c.tar.gz |
Improve UNIQUE_ID generation
- Remove unused generate_unique_id() function.
- Fix unique ID generation code to use ATTESTATION_APPLICATION_ID
rather than APPLICATION_ID.
- Add km_openssl helper functions to build a UNIQUE_ID value from the
inputs and an HBK value for the HMAC-SHA256 function.
- Treat Tag::INCLUDE_UNIQUE_ID as a key generation parameter, similar
to the various ATTESTATION_ID_* tags.
Individual KeyMint implementations still need to provide an
implementation of AttestationContext::GenerateUniqueId(), but that
implementation can be a one-line invocation of
keymaster::generate_unique_id() using a suitable HBK.
Bug: 202487002
Test: VtsAidlKeyMintTargetTest
Merged-In: I3eb8cf22cf52a6d5c7a085ae497500800ecd5438
Change-Id: I3eb8cf22cf52a6d5c7a085ae497500800ecd5438
Ignore-AOSP-First: cherry-pick from aosp/master
-rw-r--r-- | include/keymaster/km_openssl/attestation_record.h | 12 | ||||
-rw-r--r-- | key_blob_utils/software_keyblobs.cpp | 4 | ||||
-rw-r--r-- | km_openssl/attestation_record.cpp | 71 | ||||
-rw-r--r-- | ng/AndroidKeyMintDevice.cpp | 2 |
4 files changed, 49 insertions, 40 deletions
diff --git a/include/keymaster/km_openssl/attestation_record.h b/include/keymaster/km_openssl/attestation_record.h index 3ae1a10..f484da1 100644 --- a/include/keymaster/km_openssl/attestation_record.h +++ b/include/keymaster/km_openssl/attestation_record.h @@ -34,6 +34,9 @@ class AttestationContext; constexpr KmVersion kCurrentKmVersion = KmVersion::KEYMASTER_4_1; +// Size (in bytes) of generated UNIQUE_ID values. +constexpr int UNIQUE_ID_SIZE = 16; + constexpr int EAT_CLAIM_PRIVATE_BASE = -80000; constexpr int EAT_CLAIM_PRIVATE_NON_KM_BASE = EAT_CLAIM_PRIVATE_BASE - 2000; @@ -343,6 +346,15 @@ keymaster_error_t build_eat_record(const AuthorizationSet& attestation_params, const AttestationContext& context, // 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); + +// 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); + /** * Helper functions for attestation record tests. Caller takes ownership of * |attestation_challenge->data| and |unique_id->data|, deallocate using delete[]. diff --git a/key_blob_utils/software_keyblobs.cpp b/key_blob_utils/software_keyblobs.cpp index 764ebcb..475ac36 100644 --- a/key_blob_utils/software_keyblobs.cpp +++ b/key_blob_utils/software_keyblobs.cpp @@ -307,7 +307,7 @@ keymaster_error_t SetKeyBlobAuthorizations(const AuthorizationSet& key_descripti LOG_E("Tag %d not allowed in key generation/import", entry.tag); break; - // These are provided to support attesation key generation, but should not be included in + // These are provided to support attestation key generation, but should not be included in // the key characteristics. case KM_TAG_ATTESTATION_APPLICATION_ID: case KM_TAG_ATTESTATION_CHALLENGE: @@ -323,6 +323,7 @@ keymaster_error_t SetKeyBlobAuthorizations(const AuthorizationSet& key_descripti case KM_TAG_CERTIFICATE_SUBJECT: case KM_TAG_CERTIFICATE_NOT_BEFORE: case KM_TAG_CERTIFICATE_NOT_AFTER: + case KM_TAG_INCLUDE_UNIQUE_ID: case KM_TAG_RESET_SINCE_ID_ROTATION: break; @@ -341,7 +342,6 @@ keymaster_error_t SetKeyBlobAuthorizations(const AuthorizationSet& key_descripti case KM_TAG_DIGEST: case KM_TAG_EARLY_BOOT_ONLY: case KM_TAG_EC_CURVE: - case KM_TAG_INCLUDE_UNIQUE_ID: case KM_TAG_KEY_SIZE: case KM_TAG_MAX_BOOT_LEVEL: case KM_TAG_MAX_USES_PER_BOOT: diff --git a/km_openssl/attestation_record.cpp b/km_openssl/attestation_record.cpp index 92aaeae..3162e4a 100644 --- a/km_openssl/attestation_record.cpp +++ b/km_openssl/attestation_record.cpp @@ -26,6 +26,7 @@ #include <keymaster/android_keymaster_utils.h> #include <keymaster/attestation_context.h> +#include <keymaster/km_openssl/hmac.h> #include <keymaster/km_openssl/openssl_err.h> #include <keymaster/km_openssl/openssl_utils.h> @@ -255,27 +256,6 @@ bool is_valid_attestation_challenge(const keymaster_blob_t& attestation_challeng return (attestation_challenge.data_length <= kMaximumAttestationChallengeLength); } -Buffer generate_unique_id(const AttestationContext& context, // - const AuthorizationSet& sw_enforced, - const AuthorizationSet& attestation_params, // - keymaster_error_t* error) { - uint64_t creation_datetime; - // Only check sw_enforced for TAG_CREATION_DATETIME, since it shouldn't be in tee_enforced, - // since this implementation has no secure wall clock. - if (!sw_enforced.GetTagValue(TAG_CREATION_DATETIME, &creation_datetime)) { - LOG_E("Unique ID cannot be created without creation datetime", 0); - *error = KM_ERROR_INVALID_KEY_BLOB; - return {}; - } - - keymaster_blob_t application_id = {nullptr, 0}; - sw_enforced.GetTagValue(TAG_APPLICATION_ID, &application_id); - - return context.GenerateUniqueId(creation_datetime, application_id, - attestation_params.GetTagValue(TAG_RESET_SINCE_ID_ROTATION), - error); -} - // Put the contents of the keymaster AuthorizationSet auth_list into the EAT record structure. keymaster_error_t build_eat_submod(const AuthorizationSet& auth_list, const EatSecurityLevel security_level, cppbor::Map* submod) { @@ -536,7 +516,6 @@ keymaster_error_t build_auth_list(const AuthorizationSet& auth_list, KM_AUTH_LIS case KM_TAG_AUTH_TOKEN: case KM_TAG_MAC_LENGTH: case KM_TAG_ATTESTATION_CHALLENGE: - case KM_TAG_RESET_SINCE_ID_ROTATION: case KM_TAG_KDF: /* Tags ignored because they're used only to provide for certificate generation */ @@ -544,6 +523,8 @@ keymaster_error_t build_auth_list(const AuthorizationSet& auth_list, KM_AUTH_LIS case KM_TAG_CERTIFICATE_SUBJECT: case KM_TAG_CERTIFICATE_NOT_BEFORE: case KM_TAG_CERTIFICATE_NOT_AFTER: + case KM_TAG_INCLUDE_UNIQUE_ID: + case KM_TAG_RESET_SINCE_ID_ROTATION: /* Tags ignored because they have no meaning off-device */ case KM_TAG_USER_ID: @@ -552,7 +533,6 @@ keymaster_error_t build_auth_list(const AuthorizationSet& auth_list, KM_AUTH_LIS /* Tags ignored because they're not usable by app keys */ case KM_TAG_BOOTLOADER_ONLY: - case KM_TAG_INCLUDE_UNIQUE_ID: case KM_TAG_MAX_BOOT_LEVEL: case KM_TAG_MAX_USES_PER_BOOT: case KM_TAG_MIN_SECONDS_BETWEEN_OPS: @@ -932,9 +912,7 @@ keymaster_error_t build_eat_record(const AuthorizationSet& attestation_params, eat_record.add(EatClaim::SUBMODS, std::move(submods)); } - // Only check tee_enforced for TAG_INCLUDE_UNIQUE_ID. If we don't have hardware we can't - // generate unique IDs. - if (tee_enforced.GetTagValue(TAG_INCLUDE_UNIQUE_ID)) { + if (attestation_params.GetTagValue(TAG_INCLUDE_UNIQUE_ID)) { uint64_t creation_datetime; // Only check sw_enforced for TAG_CREATION_DATETIME, since it shouldn't be in tee_enforced, // since this implementation has no secure wall clock. @@ -943,11 +921,8 @@ keymaster_error_t build_eat_record(const AuthorizationSet& attestation_params, return KM_ERROR_INVALID_KEY_BLOB; } - keymaster_blob_t application_id = {nullptr, 0}; - sw_enforced.GetTagValue(TAG_APPLICATION_ID, &application_id); - Buffer unique_id = context.GenerateUniqueId( - creation_datetime, application_id, + creation_datetime, attestation_app_id, attestation_params.GetTagValue(TAG_RESET_SINCE_ID_ROTATION), &error); if (error != KM_ERROR_OK) return error; @@ -960,6 +935,33 @@ 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) { + uint64_t rounded_date = creation_date_time / 2592000000LLU; + uint8_t* serialized_date = reinterpret_cast<uint8_t*>(&rounded_date); + + 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; +} + +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) { + 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; +} + // Construct an ASN1.1 DER-encoded attestation record containing the values from sw_enforced and // tee_enforced. keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_params, // @@ -1057,9 +1059,7 @@ keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_p error = build_auth_list(tee_enforced, key_desc->tee_enforced); if (error != KM_ERROR_OK) return error; - // Only check tee_enforced for TAG_INCLUDE_UNIQUE_ID. If we don't have hardware we can't - // generate unique IDs. - if (tee_enforced.GetTagValue(TAG_INCLUDE_UNIQUE_ID)) { + if (attestation_params.GetTagValue(TAG_INCLUDE_UNIQUE_ID)) { uint64_t creation_datetime; // Only check sw_enforced for TAG_CREATION_DATETIME, since it shouldn't be in tee_enforced, // since this implementation has no secure wall clock. @@ -1068,11 +1068,8 @@ keymaster_error_t build_attestation_record(const AuthorizationSet& attestation_p return KM_ERROR_INVALID_KEY_BLOB; } - keymaster_blob_t application_id = {nullptr, 0}; - sw_enforced.GetTagValue(TAG_APPLICATION_ID, &application_id); - Buffer unique_id = context.GenerateUniqueId( - creation_datetime, application_id, + creation_datetime, attestation_app_id, attestation_params.GetTagValue(TAG_RESET_SINCE_ID_ROTATION), &error); if (error != KM_ERROR_OK) return error; diff --git a/ng/AndroidKeyMintDevice.cpp b/ng/AndroidKeyMintDevice.cpp index f511c3f..89201bd 100644 --- a/ng/AndroidKeyMintDevice.cpp +++ b/ng/AndroidKeyMintDevice.cpp @@ -121,6 +121,7 @@ vector<KeyCharacteristics> convertKeyCharacteristics(SecurityLevel keyMintSecuri case KM_TAG_CONFIRMATION_TOKEN: case KM_TAG_DEVICE_UNIQUE_ATTESTATION: case KM_TAG_IDENTITY_CREDENTIAL_KEY: + case KM_TAG_INCLUDE_UNIQUE_ID: case KM_TAG_MAC_LENGTH: case KM_TAG_NONCE: case KM_TAG_RESET_SINCE_ID_ROTATION: @@ -140,7 +141,6 @@ vector<KeyCharacteristics> convertKeyCharacteristics(SecurityLevel keyMintSecuri case KM_TAG_EARLY_BOOT_ONLY: case KM_TAG_EC_CURVE: case KM_TAG_EXPORTABLE: - case KM_TAG_INCLUDE_UNIQUE_ID: case KM_TAG_KEY_SIZE: case KM_TAG_MAX_USES_PER_BOOT: case KM_TAG_MIN_MAC_LENGTH: |