summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Drysdale <drysdale@google.com>2021-10-13 10:19:38 +0100
committerDavid Drysdale <drysdale@google.com>2021-11-10 15:05:36 +0000
commit22146e47b26b87bccc826657cefe02206571621c (patch)
treeb8b8094a390e1e3c6d14c06835fb47dc97a0c5ec
parenteaad67939432456802418579e3b7cbceb1b2cbd6 (diff)
downloadkeymaster-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.h12
-rw-r--r--key_blob_utils/software_keyblobs.cpp4
-rw-r--r--km_openssl/attestation_record.cpp71
-rw-r--r--ng/AndroidKeyMintDevice.cpp2
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: