diff options
author | Shawn Willden <swillden@google.com> | 2015-06-26 12:21:56 -0700 |
---|---|---|
committer | Shawn Willden <swillden@google.com> | 2015-06-26 12:30:30 -0700 |
commit | ebc99a15e324d9f1cfaf681a8c95676984f16f08 (patch) | |
tree | 7183f154720fb168bab5b15f4458562b881b9c81 | |
parent | 08eab179eebe53f56f99af3f9e6fc83e11ec53c0 (diff) | |
download | keymaster-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.cpp | 53 | ||||
-rw-r--r-- | hmac_operation.cpp | 9 |
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( |