summaryrefslogtreecommitdiffstats
path: root/hmac_key.cpp
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2015-07-08 08:47:25 -0600
committerShawn Willden <swillden@google.com>2015-07-16 11:45:00 -0600
commit33ab0389e908b98702806c746e7babc0d46eb452 (patch)
treee45b4d16c9f9c23a459a21cb75f0e39445f32d72 /hmac_key.cpp
parent7d05d88dc44b18e0350f7fe8d28c20f2f643bb80 (diff)
downloadandroid_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.cpp57
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