CTS-test that HMAC key can be authorized for one digest only.

Bug: 22337277
Change-Id: Id367db40ed1c81024b1ddc73a66b361975d0a1e2
diff --git a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
index 3283a07..6cd64b8 100644
--- a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
@@ -2395,4 +2395,66 @@
             Log.i(TAG, "Deleted " + (latestImportedEntryNumber + 1) + " keys");
         }
     }
+
+    public void testKeyStore_OnlyOneDigestCanBeAuthorized_HMAC() throws Exception {
+        mKeyStore.load(null);
+
+        for (String algorithm : KeyGeneratorTest.EXPECTED_ALGORITHMS) {
+            if (!TestUtils.isHmacAlgorithm(algorithm)) {
+                continue;
+            }
+            try {
+                String digest = TestUtils.getHmacAlgorithmDigest(algorithm);
+                assertNotNull(digest);
+                SecretKeySpec keyBeingImported = new SecretKeySpec(new byte[16], algorithm);
+
+                KeyProtection.Builder goodSpec =
+                        new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN);
+
+                // Digests authorization not specified in import parameters
+                assertFalse(goodSpec.build().isDigestsSpecified());
+                mKeyStore.setEntry(TEST_ALIAS_1,
+                        new KeyStore.SecretKeyEntry(keyBeingImported),
+                        goodSpec.build());
+                SecretKey key = (SecretKey) mKeyStore.getKey(TEST_ALIAS_1, null);
+                TestUtils.assertContentsInAnyOrder(
+                        Arrays.asList(TestUtils.getKeyInfo(key).getDigests()), digest);
+
+                // The same digest is specified in import parameters
+                mKeyStore.setEntry(TEST_ALIAS_1,
+                        new KeyStore.SecretKeyEntry(keyBeingImported),
+                        TestUtils.buildUpon(goodSpec).setDigests(digest).build());
+                key = (SecretKey) mKeyStore.getKey(TEST_ALIAS_1, null);
+                TestUtils.assertContentsInAnyOrder(
+                        Arrays.asList(TestUtils.getKeyInfo(key).getDigests()), digest);
+
+                // Empty set of digests specified in import parameters
+                try {
+                    mKeyStore.setEntry(TEST_ALIAS_1,
+                            new KeyStore.SecretKeyEntry(keyBeingImported),
+                            TestUtils.buildUpon(goodSpec).setDigests().build());
+                    fail();
+                } catch (KeyStoreException expected) {}
+
+                // A different digest specified in import parameters
+                String anotherDigest = "SHA-256".equalsIgnoreCase(digest) ? "SHA-384" : "SHA-256";
+                try {
+                    mKeyStore.setEntry(TEST_ALIAS_1,
+                            new KeyStore.SecretKeyEntry(keyBeingImported),
+                            TestUtils.buildUpon(goodSpec).setDigests(anotherDigest).build());
+                    fail();
+                } catch (KeyStoreException expected) {}
+                try {
+                    mKeyStore.setEntry(TEST_ALIAS_1,
+                            new KeyStore.SecretKeyEntry(keyBeingImported),
+                            TestUtils.buildUpon(goodSpec)
+                                    .setDigests(digest, anotherDigest)
+                                    .build());
+                    fail();
+                } catch (KeyStoreException expected) {}
+            } catch (Throwable e) {
+                throw new RuntimeException("Failed for " + algorithm, e);
+            }
+        }
+    }
 }
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyGeneratorTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyGeneratorTest.java
index b51d300..88d5421 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyGeneratorTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyGeneratorTest.java
@@ -46,7 +46,7 @@
 public class KeyGeneratorTest extends TestCase {
     private static final String EXPECTED_PROVIDER_NAME = TestUtils.EXPECTED_PROVIDER_NAME;
 
-    private static final String[] EXPECTED_ALGORITHMS = {
+    static final String[] EXPECTED_ALGORITHMS = {
         "AES",
         "HmacSHA1",
         "HmacSHA224",
@@ -291,6 +291,60 @@
         }
     }
 
+    public void testHmacKeyOnlyOneDigestCanBeAuthorized() throws Exception {
+        for (String algorithm : EXPECTED_ALGORITHMS) {
+            if (!TestUtils.isHmacAlgorithm(algorithm)) {
+                continue;
+            }
+
+            try {
+                String digest = TestUtils.getHmacAlgorithmDigest(algorithm);
+                assertNotNull(digest);
+
+                KeyGenParameterSpec.Builder goodSpec = new KeyGenParameterSpec.Builder(
+                        "test1", KeyProperties.PURPOSE_SIGN);
+
+                KeyGenerator keyGenerator = getKeyGenerator(algorithm);
+
+                // Digests authorization not specified in algorithm parameters
+                assertFalse(goodSpec.build().isDigestsSpecified());
+                keyGenerator.init(goodSpec.build());
+                SecretKey key = keyGenerator.generateKey();
+                TestUtils.assertContentsInAnyOrder(
+                        Arrays.asList(TestUtils.getKeyInfo(key).getDigests()), digest);
+
+                // The same digest is specified in algorithm parameters
+                keyGenerator.init(TestUtils.buildUpon(goodSpec).setDigests(digest).build());
+                key = keyGenerator.generateKey();
+                TestUtils.assertContentsInAnyOrder(
+                        Arrays.asList(TestUtils.getKeyInfo(key).getDigests()), digest);
+
+                // No digests specified in algorithm parameters
+                try {
+                    keyGenerator.init(TestUtils.buildUpon(goodSpec).setDigests().build());
+                    fail();
+                } catch (InvalidAlgorithmParameterException expected) {}
+
+                // A different digest specified in algorithm parameters
+                String anotherDigest = "SHA-256".equalsIgnoreCase(digest) ? "SHA-384" : "SHA-256";
+                try {
+                    keyGenerator.init(TestUtils.buildUpon(goodSpec)
+                            .setDigests(anotherDigest)
+                            .build());
+                    fail();
+                } catch (InvalidAlgorithmParameterException expected) {}
+                try {
+                    keyGenerator.init(TestUtils.buildUpon(goodSpec)
+                            .setDigests(digest, anotherDigest)
+                            .build());
+                    fail();
+                } catch (InvalidAlgorithmParameterException expected) {}
+            } catch (Throwable e) {
+                throw new RuntimeException("Failed for " + algorithm, e);
+            }
+        }
+    }
+
     public void testInitWithUnknownBlockModeFails() {
         for (String algorithm : EXPECTED_ALGORITHMS) {
             try {
@@ -402,7 +456,7 @@
         }
     }
 
-    public void testGenerateHonorsAuthorizations() throws Exception {
+    public void testGenerateHonorsRequestedAuthorizations() throws Exception {
         Date keyValidityStart = new Date(System.currentTimeMillis() - TestUtils.DAY_IN_MILLIS);
         Date keyValidityForOriginationEnd =
                 new Date(System.currentTimeMillis() + TestUtils.DAY_IN_MILLIS);
@@ -418,13 +472,12 @@
                 String[] digests;
                 int purposes;
                 if (TestUtils.isHmacAlgorithm(algorithm)) {
-                    String digest = TestUtils.getHmacAlgorithmDigest(algorithm);
-                    String anotherDigest = KeyProperties.DIGEST_SHA256.equalsIgnoreCase(digest)
-                            ? KeyProperties.DIGEST_SHA512 : KeyProperties.DIGEST_SHA256;
-                    digests = new String[] {anotherDigest, digest};
+                    // HMAC key can only be authorized for one digest, the one implied by the key's
+                    // JCA algorithm name.
+                    digests = new String[] {TestUtils.getHmacAlgorithmDigest(algorithm)};
                     purposes = KeyProperties.PURPOSE_SIGN;
                 } else {
-                    digests = new String[] {KeyProperties.DIGEST_SHA384};
+                    digests = new String[] {KeyProperties.DIGEST_SHA384, KeyProperties.DIGEST_SHA1};
                     purposes = KeyProperties.PURPOSE_DECRYPT;
                 }
                 KeyGenerator keyGenerator = getKeyGenerator(algorithm);
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
index 3d3c909..bc6ab9f 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyPairGeneratorTest.java
@@ -297,7 +297,7 @@
         }
     }
 
-    public void testGenerateHonorsAuthorizations() throws Exception {
+    public void testGenerateHonorsRequestedAuthorizations() throws Exception {
         Date keyValidityStart = new Date(System.currentTimeMillis() - TestUtils.DAY_IN_MILLIS);
         Date keyValidityForOriginationEnd =
                 new Date(System.currentTimeMillis() + TestUtils.DAY_IN_MILLIS);
diff --git a/tests/tests/keystore/src/android/keystore/cts/MacTest.java b/tests/tests/keystore/src/android/keystore/cts/MacTest.java
index 8dcf47e..289e31b 100644
--- a/tests/tests/keystore/src/android/keystore/cts/MacTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/MacTest.java
@@ -125,11 +125,12 @@
     }
 
     public void testAndroidKeyStoreKeysHandledByAndroidKeyStoreProvider() throws Exception {
-        SecretKey key = importDefaultKatKey();
         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(provider);
         for (String algorithm : EXPECTED_ALGORITHMS) {
             try {
+                SecretKey key = importDefaultKatKey(algorithm);
+
                 // Generate a MAC
                 Mac mac = Mac.getInstance(algorithm);
                 mac.init(key);
@@ -141,12 +142,12 @@
     }
 
     public void testMacGeneratedByAndroidKeyStoreVerifiesByAndroidKeyStore() throws Exception {
-        SecretKey key = importDefaultKatKey();
-
         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(provider);
         for (String algorithm : EXPECTED_ALGORITHMS) {
             try {
+                SecretKey key = importDefaultKatKey(algorithm);
+
                 // Generate a MAC
                 Mac mac = Mac.getInstance(algorithm, provider);
                 mac.init(key);
@@ -162,13 +163,13 @@
 
     public void testMacGeneratedByAndroidKeyStoreVerifiesByHighestPriorityProvider()
             throws Exception {
-        SecretKey key = getDefaultKatKey();
-        SecretKey keystoreKey = importDefaultKatKey();
-
         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(provider);
         for (String algorithm : EXPECTED_ALGORITHMS) {
             try {
+                SecretKey key = getDefaultKatKey(algorithm);
+                SecretKey keystoreKey = importDefaultKatKey(algorithm);
+
                 // Generate a MAC
                 Mac mac = Mac.getInstance(algorithm, provider);
                 mac.init(keystoreKey);
@@ -184,14 +185,14 @@
 
     public void testMacGeneratedByHighestPriorityProviderVerifiesByAndroidKeyStore()
             throws Exception {
-        SecretKey key = getDefaultKatKey();
-        SecretKey keystoreKey = importDefaultKatKey();
-
         Provider keystoreProvider = Security.getProvider(EXPECTED_PROVIDER_NAME);
         assertNotNull(keystoreProvider);
         for (String algorithm : EXPECTED_ALGORITHMS) {
             Provider signingProvider = null;
             try {
+                SecretKey key = getDefaultKatKey(algorithm);
+                SecretKey keystoreKey = importDefaultKatKey(algorithm);
+
                 // Generate a MAC
                 Mac mac = Mac.getInstance(algorithm);
                 mac.init(key);
@@ -209,11 +210,12 @@
     }
 
     public void testSmallMsgKat() throws Exception {
-        SecretKey key = importDefaultKatKey();
         byte[] message = SHORT_MSG_KAT_MESSAGE;
 
         for (String algorithm : EXPECTED_ALGORITHMS) {
             try {
+                SecretKey key = importDefaultKatKey(algorithm);
+
                 byte[] goodMacBytes = SHORT_MSG_KAT_MACS.get(algorithm);
                 assertNotNull(goodMacBytes);
                 assertMacVerifiesOneShot(algorithm, key, message, goodMacBytes);
@@ -234,11 +236,12 @@
     }
 
     public void testLargeMsgKat() throws Exception {
-        SecretKey key = importDefaultKatKey();
         byte[] message = TestUtils.generateLargeKatMsg(LONG_MSG_KAT_SEED, LONG_MSG_KAT_SIZE_BYTES);
 
         for (String algorithm : EXPECTED_ALGORITHMS) {
             try {
+                SecretKey key = importDefaultKatKey(algorithm);
+
                 byte[] goodMacBytes = LONG_MSG_KAT_MACS.get(algorithm);
                 assertNotNull(goodMacBytes);
                 assertMacVerifiesOneShot(algorithm,  key, message, goodMacBytes);
@@ -452,28 +455,21 @@
         } catch (InvalidKeyException expected) {}
     }
 
-    private SecretKey getDefaultKatKey() {
-        return new SecretKeySpec(KAT_KEY, "HmacSHA1");
+    private SecretKey getDefaultKatKey(String keyAlgorithm) {
+        return new SecretKeySpec(KAT_KEY, keyAlgorithm);
     }
 
-    private SecretKey importDefaultKatKey() throws Exception {
-        return importDefaultKatKey("HmacSHA1",
-                new KeyProtection.Builder(
-                        KeyProperties.PURPOSE_SIGN)
-                        .setDigests(
-                                KeyProperties.DIGEST_SHA1,
-                                KeyProperties.DIGEST_SHA224,
-                                KeyProperties.DIGEST_SHA256,
-                                KeyProperties.DIGEST_SHA384,
-                                KeyProperties.DIGEST_SHA512)
-                        .build());
+    private SecretKey importDefaultKatKey(String keyAlgorithm) throws Exception {
+        return importDefaultKatKey(
+                keyAlgorithm,
+                new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN).build());
     }
 
     private SecretKey importDefaultKatKey(
             String keyAlgorithm, KeyProtection keyProtection) throws Exception {
         return TestUtils.importIntoAndroidKeyStore(
                 "test1",
-                new SecretKeySpec(KAT_KEY, keyAlgorithm),
+                getDefaultKatKey(keyAlgorithm),
                 keyProtection);
     }