summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Willden <swillden@google.com>2015-06-26 12:21:56 -0700
committerShawn Willden <swillden@google.com>2015-06-26 12:30:30 -0700
commitebc99a15e324d9f1cfaf681a8c95676984f16f08 (patch)
tree7183f154720fb168bab5b15f4458562b881b9c81
parent08eab179eebe53f56f99af3f9e6fc83e11ec53c0 (diff)
downloadkeymaster-ebc99a15e324d9f1cfaf681a8c95676984f16f08.tar.gz
Support creation and use of HMAC keys with KM_DIGEST_NONE
KM_DIGEST_NONE should mean "any digest" when applied to HMAC keys, allowing any valid digest to be specified during begin() of an HMAC signature or verification operation. Bug: 22119295 Change-Id: I4698435f5d7aaf0a2f66b9c7aa4097f60c9c6eb3
-rw-r--r--android_keymaster_test.cpp53
-rw-r--r--hmac_operation.cpp9
2 files changed, 54 insertions, 8 deletions
diff --git a/android_keymaster_test.cpp b/android_keymaster_test.cpp
index d2ef08d..49cff6e 100644
--- a/android_keymaster_test.cpp
+++ b/android_keymaster_test.cpp
@@ -782,6 +782,29 @@ TEST_P(SigningOperationsTest, HmacSha512Success) {
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
+TEST_P(SigningOperationsTest, HmacAnyDigestSuccess) {
+ ASSERT_EQ(KM_ERROR_OK,
+ GenerateKey(AuthorizationSetBuilder().HmacKey(128).Digest(KM_DIGEST_NONE)));
+ string message = "12345678901234567890123456789012";
+ string signature;
+
+ size_t len;
+ keymaster_digest_t* digests;
+ ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_HMAC,
+ KM_PURPOSE_SIGN, &digests, &len));
+ for (size_t i = 0; i < len; ++i)
+ MacMessage(message, &signature, digests[i], 128 /* small MAC to work with all digests */);
+ free(digests);
+
+ // Ensure that we can't actually try to do an HMAC with no digest
+ AuthorizationSet begin_params(client_params());
+ begin_params.push_back(TAG_DIGEST, KM_DIGEST_NONE);
+ begin_params.push_back(TAG_MAC_LENGTH, 128);
+ EXPECT_EQ(KM_ERROR_UNSUPPORTED_DIGEST, BeginOperation(KM_PURPOSE_SIGN, begin_params));
+
+ EXPECT_EQ(0, GetParam()->keymaster0_calls());
+}
+
TEST_P(SigningOperationsTest, HmacLengthInKey) {
// TODO(swillden): unified API should generate an error on key generation.
ASSERT_EQ(KM_ERROR_OK, GenerateKey(AuthorizationSetBuilder()
@@ -1447,6 +1470,36 @@ TEST_P(VerificationOperationsTest, HmacSha512Success) {
EXPECT_EQ(0, GetParam()->keymaster0_calls());
}
+TEST_P(VerificationOperationsTest, HmacAnyDigestSuccess) {
+ ASSERT_EQ(KM_ERROR_OK,
+ GenerateKey(AuthorizationSetBuilder().HmacKey(128).Digest(KM_DIGEST_NONE)));
+ string message = "12345678901234567890123456789012";
+ string signature;
+
+ size_t len;
+ keymaster_digest_t* digests;
+ ASSERT_EQ(KM_ERROR_OK, device()->get_supported_digests(device(), KM_ALGORITHM_HMAC,
+ KM_PURPOSE_SIGN, &digests, &len));
+ for (size_t i = 0; i < len; ++i) {
+ MacMessage(message, &signature, digests[i], 128 /* small MAC to work with all digests */);
+ VerifyMessage(message, signature, digests[i]);
+ if (len > 1) {
+ size_t wrong_digest_index = (i == 0) ? 1 : 0;
+ AuthorizationSet begin_params(client_params());
+ begin_params.push_back(TAG_DIGEST, digests[wrong_digest_index]);
+ begin_params.push_back(TAG_MAC_LENGTH, 128);
+ EXPECT_EQ(KM_ERROR_OK, BeginOperation(KM_PURPOSE_VERIFY, begin_params));
+ string output;
+ size_t input_consumed;
+ EXPECT_EQ(KM_ERROR_OK, UpdateOperation(message, &output, &input_consumed));
+ EXPECT_EQ(KM_ERROR_VERIFICATION_FAILED, FinishOperation(signature, &output));
+ }
+ }
+ free(digests);
+
+ EXPECT_EQ(0, GetParam()->keymaster0_calls());
+}
+
typedef Keymaster1Test ExportKeyTest;
INSTANTIATE_TEST_CASE_P(AndroidKeymasterTest, ExportKeyTest, test_params);
diff --git a/hmac_operation.cpp b/hmac_operation.cpp
index 75e8a07..b1437c4 100644
--- a/hmac_operation.cpp
+++ b/hmac_operation.cpp
@@ -45,15 +45,8 @@ Operation* HmacOperationFactory::CreateOperation(const Key& key,
}
keymaster_digest_t digest;
- if (!begin_params.GetTagValue(TAG_DIGEST, &digest)) {
- LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST));
- *error = KM_ERROR_UNSUPPORTED_DIGEST;
+ if (!GetAndValidateDigest(begin_params, key, &digest, error))
return nullptr;
- } else if (!key.authorizations().Contains(TAG_DIGEST, digest)) {
- LOG_E("Digest %d was specified, but not authorized by key", digest);
- *error = KM_ERROR_INCOMPATIBLE_DIGEST;
- return nullptr;
- }
const SymmetricKey* symmetric_key = static_cast<const SymmetricKey*>(&key);
UniquePtr<HmacOperation> op(