diff options
author | Shawn Willden <swillden@google.com> | 2015-07-08 08:47:25 -0600 |
---|---|---|
committer | Shawn Willden <swillden@google.com> | 2015-07-16 11:45:00 -0600 |
commit | 33ab0389e908b98702806c746e7babc0d46eb452 (patch) | |
tree | e45b4d16c9f9c23a459a21cb75f0e39445f32d72 /hmac_key.cpp | |
parent | 7d05d88dc44b18e0350f7fe8d28c20f2f643bb80 (diff) | |
download | android_system_keymaster-33ab0389e908b98702806c746e7babc0d46eb452.tar.gz android_system_keymaster-33ab0389e908b98702806c746e7babc0d46eb452.tar.bz2 android_system_keymaster-33ab0389e908b98702806c746e7babc0d46eb452.zip |
Add support for KM_TAG_MIN_MAC_LENGTH.
HMAC and AES-GCM keys must be bound to a mininum MAC/tag length at
creation, and operations may not specify a length smaller than the
minimum, or provide a length smaller than the minimum during
verification.
Bug: 22337277
Change-Id: Id5ae2f4259045ba1418c28e9de8f4a47e67fd433
Diffstat (limited to 'hmac_key.cpp')
-rw-r--r-- | hmac_key.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/hmac_key.cpp b/hmac_key.cpp index 2e814a6..91455e3 100644 --- a/hmac_key.cpp +++ b/hmac_key.cpp @@ -46,6 +46,13 @@ keymaster_error_t HmacKeyFactory::LoadKey(const KeymasterKeyBlob& key_material, if (!key) return KM_ERROR_OUTPUT_PARAMETER_NULL; + uint32_t min_mac_length; + if (!hw_enforced.GetTagValue(TAG_MIN_MAC_LENGTH, &min_mac_length) && + !sw_enforced.GetTagValue(TAG_MIN_MAC_LENGTH, &min_mac_length)) { + LOG_E("HMAC key must have KM_TAG_MIN_MAC_LENGTH", 0); + return KM_ERROR_INVALID_KEY_BLOB; + } + keymaster_error_t error; key->reset(new (std::nothrow) HmacKey(key_material, hw_enforced, sw_enforced, &error)); if (!key->get()) @@ -53,4 +60,54 @@ keymaster_error_t HmacKeyFactory::LoadKey(const KeymasterKeyBlob& key_material, return error; } +keymaster_error_t HmacKeyFactory::validate_algorithm_specific_new_key_params( + const AuthorizationSet& key_description) const { + uint32_t min_mac_length_bits; + if (!key_description.GetTagValue(TAG_MIN_MAC_LENGTH, &min_mac_length_bits)) + return KM_ERROR_MISSING_MIN_MAC_LENGTH; + + keymaster_digest_t digest; + if (!key_description.GetTagValue(TAG_DIGEST, &digest)) { + LOG_E("%d digests specified for HMAC key", key_description.GetTagCount(TAG_DIGEST)); + return KM_ERROR_UNSUPPORTED_DIGEST; + } + + size_t hash_size_bits = 0; + switch (digest) { + case KM_DIGEST_NONE: + return KM_ERROR_UNSUPPORTED_DIGEST; + case KM_DIGEST_MD5: + hash_size_bits = 128; + break; + case KM_DIGEST_SHA1: + hash_size_bits = 160; + break; + case KM_DIGEST_SHA_2_224: + hash_size_bits = 224; + break; + case KM_DIGEST_SHA_2_256: + hash_size_bits = 256; + break; + case KM_DIGEST_SHA_2_384: + hash_size_bits = 384; + break; + case KM_DIGEST_SHA_2_512: + hash_size_bits = 512; + break; + }; + + if (hash_size_bits == 0) { + // digest was not matched + return KM_ERROR_UNSUPPORTED_DIGEST; + } + + if (min_mac_length_bits % 8 != 0 || min_mac_length_bits > hash_size_bits) + return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH; + + if (min_mac_length_bits < kMinHmacLengthBits) + return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH; + + return KM_ERROR_OK; +} + } // namespace keymaster |