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.

Cherry-picked from internal.

Bug: 22119295
Change-Id: I4698435f5d7aaf0a2f66b9c7aa4097f60c9c6eb3
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 @@
     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 @@
     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 @@
     }
 
     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(