changeset 58822:2cd3a8f8be61

8172680: Support SHA-3 based Hmac algorithms Summary: enhanced SunJCE provider with Hmac with SHA3 digests Reviewed-by: weijun
author valeriep
date Tue, 14 Apr 2020 22:31:54 +0000
parents 9eea66de64df
children 8011263c55ad
files src/java.base/share/classes/com/sun/crypto/provider/HmacCore.java src/java.base/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java test/jdk/com/sun/crypto/provider/Mac/MacKAT.java
diffstat 4 files changed, 273 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/com/sun/crypto/provider/HmacCore.java	Tue Apr 14 22:12:13 2020 +0000
+++ b/src/java.base/share/classes/com/sun/crypto/provider/HmacCore.java	Tue Apr 14 22:31:54 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,12 +34,20 @@
 import java.security.*;
 import java.security.spec.*;
 
+import sun.security.x509.AlgorithmId;
+
 /**
  * This class constitutes the core of HMAC-<MD> algorithms, where
- * <MD> can be SHA1 or MD5, etc. See RFC 2104 for spec.
+ * <MD> is the digest algorithm used by HMAC as in RFC 2104
+ * "HMAC: Keyed-Hashing for Message Authentication".
  *
- * It also contains the implementation classes for SHA-224, SHA-256,
- * SHA-384, and SHA-512 HMACs.
+ * It also contains implementation classes for:
+ * - HmacMD5
+ * - HmacSHA1
+ * - HMAC with SHA-2 family of digests, i.e. HmacSHA224, HmacSHA256,
+ *   HmacSHA384, HmacSHA512, HmacSHA512/224, HmacSHA512/256, and
+ * - HMAC with SHA-3 family of digests, i.e. HmacSHA3-224, HmacSHA3-256,
+ *   HmacSHA3-384, HmacSHA3-512
  *
  * @author Jan Luehe
  */
@@ -281,14 +289,47 @@
             super("SHA-512", 128);
         }
     }
+
+    // nested static class for the HmacSHA512/224 implementation
     public static final class HmacSHA512_224 extends HmacCore {
         public HmacSHA512_224() throws NoSuchAlgorithmException {
             super("SHA-512/224", 128);
         }
     }
+
+    // nested static class for the HmacSHA512/256 implementation
     public static final class HmacSHA512_256 extends HmacCore {
         public HmacSHA512_256() throws NoSuchAlgorithmException {
             super("SHA-512/256", 128);
         }
     }
+
+    // nested static class for the HmacSHA3-224 implementation
+    public static final class HmacSHA3_224 extends HmacCore {
+        public HmacSHA3_224() throws NoSuchAlgorithmException {
+            super("SHA3-224", 144);
+        }
+    }
+
+    // nested static class for the HmacSHA3-256 implementation
+    public static final class HmacSHA3_256 extends HmacCore {
+        public HmacSHA3_256() throws NoSuchAlgorithmException {
+            super("SHA3-256", 136);
+        }
+    }
+
+    // nested static class for the HmacSHA3-384 implementation
+    public static final class HmacSHA3_384 extends HmacCore {
+        public HmacSHA3_384() throws NoSuchAlgorithmException {
+            super("SHA3-384", 104);
+        }
+    }
+
+    // nested static class for the HmacSHA3-512 implementation
+    public static final class HmacSHA3_512 extends HmacCore {
+        public HmacSHA3_512() throws NoSuchAlgorithmException {
+            super("SHA3-512", 72);
+            System.out.println(AlgorithmId.get("HmacSHA3-512"));
+        }
+    }
 }
--- a/src/java.base/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java	Tue Apr 14 22:12:13 2020 +0000
+++ b/src/java.base/share/classes/com/sun/crypto/provider/KeyGeneratorCore.java	Tue Apr 14 22:31:54 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -105,10 +105,10 @@
         return new SecretKeySpec(b, name);
     }
 
-    // nested static classes for the HmacSHA-2 family of key generator
-    abstract static class HmacSHA2KG extends KeyGeneratorSpi {
+    // nested static classes for the Hmac key generator
+    abstract static class HmacKG extends KeyGeneratorSpi {
         private final KeyGeneratorCore core;
-        protected HmacSHA2KG(String algoName, int len) {
+        protected HmacKG(String algoName, int len) {
             core = new KeyGeneratorCore(algoName, len);
         }
         @Override
@@ -129,26 +129,56 @@
             return core.implGenerateKey();
         }
 
-        public static final class SHA224 extends HmacSHA2KG {
+        public static final class SHA224 extends HmacKG {
             public SHA224() {
                 super("HmacSHA224", 224);
             }
         }
-        public static final class SHA256 extends HmacSHA2KG {
+        public static final class SHA256 extends HmacKG {
             public SHA256() {
                 super("HmacSHA256", 256);
             }
         }
-        public static final class SHA384 extends HmacSHA2KG {
+        public static final class SHA384 extends HmacKG {
             public SHA384() {
                 super("HmacSHA384", 384);
             }
         }
-        public static final class SHA512 extends HmacSHA2KG {
+        public static final class SHA512 extends HmacKG {
             public SHA512() {
                 super("HmacSHA512", 512);
             }
         }
+        public static final class SHA512_224 extends HmacKG {
+            public SHA512_224() {
+                super("HmacSHA512/224", 224);
+            }
+        }
+        public static final class SHA512_256 extends HmacKG {
+            public SHA512_256() {
+                super("HmacSHA512/256", 256);
+            }
+        }
+        public static final class SHA3_224 extends HmacKG {
+            public SHA3_224() {
+                super("HmacSHA3-224", 224);
+            }
+        }
+        public static final class SHA3_256 extends HmacKG {
+            public SHA3_256() {
+                super("HmacSHA3-256", 256);
+            }
+        }
+        public static final class SHA3_384 extends HmacKG {
+            public SHA3_384() {
+                super("HmacSHA3-384", 384);
+            }
+        }
+        public static final class SHA3_512 extends HmacKG {
+            public SHA3_512() {
+                super("HmacSHA3-512", 512);
+            }
+        }
     }
 
     // nested static class for the RC2 key generator
--- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java	Tue Apr 14 22:12:13 2020 +0000
+++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java	Tue Apr 14 22:31:54 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
  *
  * - Diffie-Hellman Key Agreement
  *
- * - HMAC-MD5, HMAC-SHA1, HMAC-SHA-224, HMAC-SHA-256, HMAC-SHA-384, HMAC-SHA-512
+ * - HMAC-MD5, HMAC-SHA1, HMAC with SHA2 family and SHA3 family of digests
  *
  */
 
@@ -178,6 +178,18 @@
         List<String> macSHA256Aliases = createAliasesWithOid(macOidBase + "9");
         List<String> macSHA384Aliases = createAliasesWithOid(macOidBase + "10");
         List<String> macSHA512Aliases = createAliasesWithOid(macOidBase + "11");
+        List<String> macSHA512_224Aliases = createAliasesWithOid(macOidBase + "12");
+        List<String> macSHA512_256Aliases = createAliasesWithOid(macOidBase + "13");
+
+        String nistHashAlgsOidBase = "2.16.840.1.101.3.4.2.";
+        List<String> macSHA3_224Aliases =
+            createAliasesWithOid(nistHashAlgsOidBase + "13");
+        List<String> macSHA3_256Aliases =
+            createAliasesWithOid(nistHashAlgsOidBase + "14");
+        List<String> macSHA3_384Aliases =
+            createAliasesWithOid(nistHashAlgsOidBase + "15");
+        List<String> macSHA3_512Aliases =
+            createAliasesWithOid(nistHashAlgsOidBase + "16");
 
         // reuse attribute map and reset before each reuse
         HashMap<String, String> attrs = new HashMap<>(3);
@@ -409,17 +421,36 @@
                 "com.sun.crypto.provider.HmacSHA1KeyGenerator",
                 macSHA1Aliases, null);
         ps("KeyGenerator", "HmacSHA224",
-                "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA224",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA224",
                 macSHA224Aliases, null);
         ps("KeyGenerator", "HmacSHA256",
-                "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA256",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA256",
                 macSHA256Aliases, null);
         ps("KeyGenerator", "HmacSHA384",
-                "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA384",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA384",
                 macSHA384Aliases, null);
         ps("KeyGenerator", "HmacSHA512",
-                "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA2KG$SHA512",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA512",
                 macSHA512Aliases, null);
+        ps("KeyGenerator", "HmacSHA512/224",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA512_224",
+                macSHA512_224Aliases, null);
+        ps("KeyGenerator", "HmacSHA512/256",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA512_256",
+                macSHA512_256Aliases, null);
+
+        ps("KeyGenerator", "HmacSHA3-224",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_224",
+                macSHA3_224Aliases, null);
+        ps("KeyGenerator", "HmacSHA3-256",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_256",
+                macSHA3_256Aliases, null);
+        ps("KeyGenerator", "HmacSHA3-384",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_384",
+                macSHA3_384Aliases, null);
+        ps("KeyGenerator", "HmacSHA3-512",
+                "com.sun.crypto.provider.KeyGeneratorCore$HmacKG$SHA3_512",
+                macSHA3_512Aliases, null);
 
         ps("KeyPairGenerator", "DiffieHellman",
                 "com.sun.crypto.provider.DHKeyPairGenerator",
@@ -678,13 +709,26 @@
                 macSHA384Aliases, attrs);
         ps("Mac", "HmacSHA512", "com.sun.crypto.provider.HmacCore$HmacSHA512",
                 macSHA512Aliases, attrs);
-        // TODO: aliases with OIDs
         ps("Mac", "HmacSHA512/224",
                 "com.sun.crypto.provider.HmacCore$HmacSHA512_224",
-                null, attrs);
+                macSHA512_224Aliases, attrs);
         ps("Mac", "HmacSHA512/256",
                 "com.sun.crypto.provider.HmacCore$HmacSHA512_256",
-                null, attrs);
+                macSHA512_256Aliases, attrs);
+
+        ps("Mac", "HmacSHA3-224",
+                "com.sun.crypto.provider.HmacCore$HmacSHA3_224",
+                macSHA3_224Aliases, attrs);
+        ps("Mac", "HmacSHA3-256",
+                "com.sun.crypto.provider.HmacCore$HmacSHA3_256",
+                macSHA3_256Aliases, attrs);
+        ps("Mac", "HmacSHA3-384",
+                "com.sun.crypto.provider.HmacCore$HmacSHA3_384",
+                macSHA3_384Aliases, attrs);
+        ps("Mac", "HmacSHA3-512",
+                "com.sun.crypto.provider.HmacCore$HmacSHA3_512",
+                macSHA3_512Aliases, attrs);
+
         ps("Mac", "HmacPBESHA1",
                 "com.sun.crypto.provider.HmacPKCS12PBECore$HmacPKCS12PBE_SHA1",
                 null, attrs);
--- a/test/jdk/com/sun/crypto/provider/Mac/MacKAT.java	Tue Apr 14 22:12:13 2020 +0000
+++ b/test/jdk/com/sun/crypto/provider/Mac/MacKAT.java	Tue Apr 14 22:31:54 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 4846410 6313661 4963723
+ * @bug 4846410 6313661 4963723 8172680
  * @summary Basic known-answer-test for Hmac and SslMac algorithms
  * @author Andreas Sterbenz
  */
@@ -40,6 +40,10 @@
 
     private final static char[] hexDigits = "0123456789abcdef".toCharArray();
 
+    private final static char SEP = ':';
+
+    static boolean testFailed = false;
+
     public static String toString(byte[] b) {
         if (b == null) {
             return "(null)";
@@ -48,7 +52,7 @@
         for (int i = 0; i < b.length; i++) {
             int k = b[i] & 0xff;
             if (i != 0) {
-                sb.append(':');
+                sb.append(SEP);
             }
             sb.append(hexDigits[k >>> 4]);
             sb.append(hexDigits[k & 0xf]);
@@ -59,7 +63,13 @@
     public static byte[] parse(String s) {
         try {
             int n = s.length();
-            ByteArrayOutputStream out = new ByteArrayOutputStream(n / 3);
+            ByteArrayOutputStream out;
+            if (s.indexOf(SEP) == -1) {
+                out = new ByteArrayOutputStream(n / 2);
+            } else {
+                out = new ByteArrayOutputStream(n / 3);
+            }
+
             StringReader r = new StringReader(s);
             while (true) {
                 int b1 = nextNibble(r);
@@ -113,12 +123,38 @@
             this.macvalue = macvalue;
             this.key = key;
         }
-        void run(Provider p) throws Exception {
-            Mac mac = Mac.getInstance(alg, p);
-            SecretKey keySpec = new SecretKeySpec(key, alg);
-            mac.init(keySpec);
-            mac.update(input);
-            byte[] macv = mac.doFinal();
+        void run(Provider p) {
+            Mac mac = null;
+            try {
+                mac = Mac.getInstance(alg, p);
+            } catch (NoSuchAlgorithmException nsae) {
+                System.out.println("Skip test for " + alg +
+                    " due to lack of support");
+                return;
+            }
+            // ensure there is matching KeyGenerator support
+            if (!alg.startsWith("SslMac")) {
+                try {
+                    KeyGenerator.getInstance(alg, p);
+                } catch (NoSuchAlgorithmException nsae) {
+                    System.out.println("Test Failed due to " + nsae);
+                    MacKAT.testFailed = true;
+                    return;
+                }
+            }
+            byte[] macv = null;
+            try {
+                SecretKey keySpec = new SecretKeySpec(key, alg);
+                mac.init(keySpec);
+                mac.update(input);
+                macv = mac.doFinal();
+            } catch (Exception e) {
+                System.out.println("Unexpected ex when testing " + alg + ": ");
+                e.printStackTrace();
+                MacKAT.testFailed = true;
+                return;
+            }
+
             if (Arrays.equals(macvalue, macv) == false) {
                 System.out.println("Mac test for " + alg + " failed:");
                 if (input.length < 256) {
@@ -127,9 +163,10 @@
                 System.out.println("key:        " + toString(key));
                 System.out.println("macvalue:   " + toString(macvalue));
                 System.out.println("calculated: " + toString(macv));
-                throw new Exception("Mac test for " + alg + " failed");
+                MacKAT.testFailed = true;
+            } else {
+                System.out.println("passed: " + alg);
             }
-            System.out.println("passed: " + alg);
         }
         private static String toString(byte[] b) {
             return MacKAT.toString(b);
@@ -157,8 +194,13 @@
     private static Test t(String alg, byte[] input, String macvalue, byte[] key) {
         return new MacTest(alg, input, b(macvalue), key);
     }
-    private final static byte[] ALONG, BLONG, BKEY;
-    private final static byte[] BKEY_20, DDDATA_50, AAKEY_20, CDDATA_50, AAKEY_131;
+    private final static byte[] ALONG, BLONG, DDDATA_50, CDDATA_50;
+    private final static byte[] STR_HI_THERE, STR_WHAT_DO_YA_WANT;
+    private final static byte[] STR_TEST_USING1, STR_TEST_USING2;
+    private final static byte[] STR_NIST1, STR_NIST2, STR_NIST3;
+    private final static byte[] BKEY, BKEY_20, CKEY_20;
+    private final static byte[] AAKEY_20, AAKEY_131, AAKEY_147, INCKEY_25;
+    private final static byte[] NISTKEY_172;
 
     static {
         ALONG = new byte[1024 * 128];
@@ -166,18 +208,41 @@
         BLONG = new byte[1024 * 128];
         Random random = new Random(12345678);
         random.nextBytes(BLONG);
+        DDDATA_50 = new byte[50];
+        Arrays.fill(DDDATA_50, (byte) 0xdd);
+        CDDATA_50 = new byte[50];
+        Arrays.fill(CDDATA_50, (byte) 0xcd);
+
+        STR_HI_THERE = s("Hi There");
+        STR_WHAT_DO_YA_WANT = s("what do ya want for nothing?");
+        STR_TEST_USING1 = s("Test Using Larger Than Block-Size Key - Hash Key First");
+        STR_TEST_USING2 = s("This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.");
+
+        STR_NIST1 = s("Sample message for keylen<blocklen");
+        STR_NIST2 = s("Sample message for keylen=blocklen");
+        STR_NIST3 = s("Sample message for keylen>blocklen");
+
         BKEY = new byte[128];
         random.nextBytes(BKEY);
         BKEY_20 = new byte[20];
         Arrays.fill(BKEY_20, (byte) 0x0b);
-        DDDATA_50 = new byte[50];
-        Arrays.fill(DDDATA_50, (byte) 0xdd);
+        CKEY_20 = new byte[20];
+        Arrays.fill(CKEY_20, (byte) 0x0c);
         AAKEY_20 = new byte[20];
         Arrays.fill(AAKEY_20, (byte) 0xaa);
-        CDDATA_50 = new byte[50];
-        Arrays.fill(CDDATA_50, (byte) 0xcd);
         AAKEY_131 = new byte[131];
         Arrays.fill(AAKEY_131, (byte) 0xaa);
+        AAKEY_147 = new byte[147];
+        Arrays.fill(AAKEY_147, (byte) 0xaa);
+        INCKEY_25 = new byte[25];
+        for (int i = 0; i < INCKEY_25.length; i++) {
+            INCKEY_25[i] = (byte)(i+1);
+        }
+        NISTKEY_172 = new byte[172];
+        for (int i = 0; i < NISTKEY_172.length; i++) {
+            NISTKEY_172[i] = (byte)i;
+        }
+
     }
 
     private final static Test[] tests = {
@@ -216,37 +281,75 @@
         t("HmacSHA512", BLONG, "fb:cf:4b:c6:d5:49:5a:5b:0b:d9:2a:32:f5:fa:68:d2:68:a4:0f:ae:53:fc:49:12:e6:1d:53:cf:b2:cb:c5:c5:f2:2d:86:bd:14:61:30:c3:a6:6f:44:1f:77:9b:aa:a1:22:48:a9:dd:d0:45:86:d1:a1:82:53:13:c4:03:06:a3",
                 BKEY),
         // Test vectors From RFC4231
-        t("HmacSHA224", s("Hi There"), "89:6f:b1:12:8a:bb:df:19:68:32:10:7c:d4:9d:f3:3f:47:b4:b1:16:99:12:ba:4f:53:68:4b:22", BKEY_20),
-        t("HmacSHA224", s("what do ya want for nothing?"), "a3:0e:01:09:8b:c6:db:bf:45:69:0f:3a:7e:9e:6d:0f:8b:be:a2:a3:9e:61:48:00:8f:d0:5e:44", s("Jefe")),
-        t("HmacSHA224", DDDATA_50, "7f:b3:cb:35:88:c6:c1:f6:ff:a9:69:4d:7d:6a:d2:64:93:65:b0:c1:f6:5d:69:d1:ec:83:33:ea", AAKEY_20),
-        t("HmacSHA224", CDDATA_50, "6c:11:50:68:74:01:3c:ac:6a:2a:bc:1b:b3:82:62:7c:ec:6a:90:d8:6e:fc:01:2d:e7:af:ec:5a", "01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19"),
-        t("HmacSHA224", s("Test Using Larger Than Block-Size Key - Hash Key First"), "95:e9:a0:db:96:20:95:ad:ae:be:9b:2d:6f:0d:bc:e2:d4:99:f1:12:f2:d2:b7:27:3f:a6:87:0e", AAKEY_131),
-        t("HmacSHA224", s("This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."), "3a:85:41:66:ac:5d:9f:02:3f:54:d5:17:d0:b3:9d:bd:94:67:70:db:9c:2b:95:c9:f6:f5:65:d1", AAKEY_131),
+        // Test Case 1
+        t("HmacSHA224", STR_HI_THERE, "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22", BKEY_20),
+        t("HmacSHA256", STR_HI_THERE, "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7", BKEY_20),
+        t("HmacSHA384", STR_HI_THERE, "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6", BKEY_20),
+        t("HmacSHA512", STR_HI_THERE, "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854", BKEY_20),
+        // Test Case 2
+        t("HmacSHA224", STR_WHAT_DO_YA_WANT, "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44", s("Jefe")),
+        t("HmacSHA256", STR_WHAT_DO_YA_WANT, "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843", s("Jefe")),
+        t("HmacSHA384", STR_WHAT_DO_YA_WANT, "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649", s("Jefe")),
+        t("HmacSHA512", STR_WHAT_DO_YA_WANT, "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737", s("Jefe")),
+        // Test Case 3
+        t("HmacSHA224", DDDATA_50, "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea", AAKEY_20),
+        t("HmacSHA256", DDDATA_50, "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe", AAKEY_20),
+        t("HmacSHA384", DDDATA_50, "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27", AAKEY_20),
+        t("HmacSHA512", DDDATA_50, "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb", AAKEY_20),
+        // Test Case 4
+        t("HmacSHA224", CDDATA_50, "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a", INCKEY_25),
+        t("HmacSHA256", CDDATA_50, "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b", INCKEY_25),
+        t("HmacSHA384", CDDATA_50, "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb", INCKEY_25),
+        t("HmacSHA512", CDDATA_50, "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd", INCKEY_25),
+        // skip Test Case 5 which truncates all output to 128 bits
+        // Test Case 6
+        t("HmacSHA224", STR_TEST_USING1, "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e", AAKEY_131),
+        t("HmacSHA256", STR_TEST_USING1, "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54", AAKEY_131),
+        t("HmacSHA384", STR_TEST_USING1, "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952", AAKEY_131),
+        t("HmacSHA512", STR_TEST_USING1, "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598", AAKEY_131),
+        // Test Case 7
+        t("HmacSHA224", STR_TEST_USING2, "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1", AAKEY_131),
+        t("HmacSHA256", STR_TEST_USING2, "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2", AAKEY_131),
+        t("HmacSHA384", STR_TEST_USING2, "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e", AAKEY_131),
+        t("HmacSHA512", STR_TEST_USING2, "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58", AAKEY_131),
+        // NIST Example Values
+        // https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values#aMsgAuth
+        t("HmacSHA3-224", STR_NIST1, "332cfd59347fdb8e576e77260be4aba2d6dc53117b3bfb52c6d18c04", Arrays.copyOf(NISTKEY_172, 28)),
+        t("HmacSHA3-224", STR_NIST2, "d8b733bcf66c644a12323d564e24dcf3fc75f231f3b67968359100c7", Arrays.copyOf(NISTKEY_172, 144)),
+        t("HmacSHA3-224", STR_NIST3, "078695eecc227c636ad31d063a15dd05a7e819a66ec6d8de1e193e59", NISTKEY_172),
+
+        t("HmacSHA3-256", STR_NIST1, "4fe8e202c4f058e8dddc23d8c34e467343e23555e24fc2f025d598f558f67205", Arrays.copyOf(NISTKEY_172, 32)),
+        t("HmacSHA3-256", STR_NIST2, "68b94e2e538a9be4103bebb5aa016d47961d4d1aa906061313b557f8af2c3faa", Arrays.copyOf(NISTKEY_172, 136)),
+        t("HmacSHA3-256", STR_NIST3, "9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258", Arrays.copyOf(NISTKEY_172, 168)),
+
+        t("HmacSHA3-384", STR_NIST1, "d588a3c51f3f2d906e8298c1199aa8ff6296218127f6b38a90b6afe2c5617725bc99987f79b22a557b6520db710b7f42", Arrays.copyOf(NISTKEY_172, 48)),
+        t("HmacSHA3-384", STR_NIST2, "a27d24b592e8c8cbf6d4ce6fc5bf62d8fc98bf2d486640d9eb8099e24047837f5f3bffbe92dcce90b4ed5b1e7e44fa90", Arrays.copyOf(NISTKEY_172, 104)),
+        t("HmacSHA3-384", STR_NIST3, "e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac", Arrays.copyOf(NISTKEY_172, 152)),
+
+        t("HmacSHA3-512", STR_NIST1, "4efd629d6c71bf86162658f29943b1c308ce27cdfa6db0d9c3ce81763f9cbce5f7ebe9868031db1a8f8eb7b6b95e5c5e3f657a8996c86a2f6527e307f0213196", Arrays.copyOf(NISTKEY_172, 64)),
+        t("HmacSHA3-512", STR_NIST2, "544e257ea2a3e5ea19a590e6a24b724ce6327757723fe2751b75bf007d80f6b360744bf1b7a88ea585f9765b47911976d3191cf83c039f5ffab0d29cc9d9b6da", Arrays.copyOf(NISTKEY_172, 72)),
+        t("HmacSHA3-512", STR_NIST3, "5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d46b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915", Arrays.copyOf(NISTKEY_172, 136)),
     };
 
     static void runTests(Test[] tests) throws Exception {
         long start = System.currentTimeMillis();
         Provider p = Security.getProvider("SunJCE");
         System.out.println("Testing provider " + p.getName() + "...");
-        Mac.getInstance("HmacSHA224", p);
-        Mac.getInstance("HmacSHA256", p);
-        Mac.getInstance("HmacSHA384", p);
-        Mac.getInstance("HmacSHA512", p);
-        KeyGenerator.getInstance("HmacSHA224", p);
-        KeyGenerator.getInstance("HmacSHA256", p);
-        KeyGenerator.getInstance("HmacSHA384", p);
-        KeyGenerator.getInstance("HmacSHA512", p);
         for (int i = 0; i < tests.length; i++) {
             Test test = tests[i];
             test.run(p);
         }
-        System.out.println("All tests passed");
         long stop = System.currentTimeMillis();
         System.out.println("Done (" + (stop - start) + " ms).");
+
+        if (!testFailed) {
+            System.out.println("All tests passed");
+        } else {
+            throw new RuntimeException("One or more tests failed");
+        }
     }
 
     public static void main(String[] args) throws Exception {
         runTests(tests);
     }
-
 }