1 /* 2 * Copyright (c) 2015, Red Hat, Inc. 3 * Copyright (c) 2015, Oracle, Inc. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * @test 27 * @bug 8069072 28 * @summary Test vectors for com.sun.crypto.provider.GHASH. 29 * 30 * Single iteration to verify software-only GHASH algorithm. 31 * @run main TestGHASH 32 * 33 * Multi-iteration to verify test intrinsics GHASH, if available. 34 * Many iterations are needed so we are sure hotspot will use intrinsic 35 * @run main TestGHASH -n 10000 36 */ 37 import java.lang.reflect.Constructor; 38 import java.lang.reflect.Method; 39 import java.nio.ByteBuffer; 40 41 public class TestGHASH { 42 43 private final Constructor<?> GHASH; 44 private final Method UPDATE; 45 private final Method DIGEST; 46 47 TestGHASH(String className) throws Exception { 48 Class<?> cls = Class.forName(className); 49 GHASH = cls.getDeclaredConstructor(byte[].class); 50 GHASH.setAccessible(true); 51 UPDATE = cls.getDeclaredMethod("update", byte[].class); 52 UPDATE.setAccessible(true); 53 DIGEST = cls.getDeclaredMethod("digest"); 54 DIGEST.setAccessible(true); 55 } 56 57 58 private Object newGHASH(byte[] H) throws Exception { 59 return GHASH.newInstance(H); 60 } 61 62 private void updateGHASH(Object hash, byte[] data) 63 throws Exception { 64 UPDATE.invoke(hash, data); 65 } 66 67 private byte[] digestGHASH(Object hash) throws Exception { 68 return (byte[]) DIGEST.invoke(hash); 69 } 70 71 private static final String HEX_DIGITS = "0123456789abcdef"; 72 73 private static String hex(byte[] bs) { 74 StringBuilder sb = new StringBuilder(2 * bs.length); 75 for (byte b : bs) { 76 sb.append(HEX_DIGITS.charAt((b >> 4) & 0xF)); 77 sb.append(HEX_DIGITS.charAt(b & 0xF)); 78 } 79 return sb.toString(); 80 } 81 82 private static byte[] bytes(String hex) { 83 if ((hex.length() & 1) != 0) { 84 throw new AssertionError(); 85 } 86 byte[] result = new byte[hex.length() / 2]; 87 for (int i = 0; i < result.length; ++i) { 88 int a = HEX_DIGITS.indexOf(hex.charAt(2 * i)); 89 int b = HEX_DIGITS.indexOf(hex.charAt(2 * i + 1)); 90 if ((a | b) < 0) { 91 if (a < 0) { 92 throw new AssertionError( 93 "bad character " + (int) hex.charAt(2 * i)); 94 } 95 throw new AssertionError( 96 "bad character " + (int) hex.charAt(2 * i + 1)); 97 } 98 result[i] = (byte) ((a << 4) | b); 99 } 100 return result; 101 } 102 103 private static byte[] bytes(long L0, long L1) { 104 return ByteBuffer.allocate(16) 105 .putLong(L0) 106 .putLong(L1) 107 .array(); 108 } 109 110 private void check(int testCase, String H, String A, 111 String C, String expected) throws Exception { 112 int lenA = A.length() * 4; 113 while ((A.length() % 32) != 0) { 114 A += '0'; 115 } 116 int lenC = C.length() * 4; 117 while ((C.length() % 32) != 0) { 118 C += '0'; 119 } 120 121 Object hash = newGHASH(bytes(H)); 122 updateGHASH(hash, bytes(A)); 123 updateGHASH(hash, bytes(C)); 124 updateGHASH(hash, bytes(lenA, lenC)); 125 byte[] digest = digestGHASH(hash); 126 String actual = hex(digest); 127 if (!expected.equals(actual)) { 128 throw new AssertionError(String.format("%d: expected %s, got %s", 129 testCase, expected, actual)); 130 } 131 } 132 133 public static void main(String[] args) throws Exception { 134 TestGHASH test; 135 String test_class = "com.sun.crypto.provider.GHASH"; 136 int i = 0; 137 int num_of_loops = 1; 138 while (args.length > i) { 139 if (args[i].compareTo("-c") == 0) { 140 test_class = args[++i]; 141 } else if (args[i].compareTo("-n") == 0) { 142 num_of_loops = Integer.parseInt(args[++i]); 143 } 144 i++; 145 } 146 147 System.out.println("Running " + num_of_loops + " iterations."); 148 test = new TestGHASH(test_class); 149 i = 0; 150 151 while (num_of_loops > i) { 152 // Test vectors from David A. McGrew, John Viega, 153 // "The Galois/Counter Mode of Operation (GCM)", 2005. 154 // <http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf> 155 test.check(1, "66e94bd4ef8a2c3b884cfa59ca342b2e", "", "", 156 "00000000000000000000000000000000"); 157 test.check(2, 158 "66e94bd4ef8a2c3b884cfa59ca342b2e", "", 159 "0388dace60b6a392f328c2b971b2fe78", 160 "f38cbb1ad69223dcc3457ae5b6b0f885"); 161 test.check(3, 162 "b83b533708bf535d0aa6e52980d53b78", "", 163 "42831ec2217774244b7221b784d0d49c" + 164 "e3aa212f2c02a4e035c17e2329aca12e" + 165 "21d514b25466931c7d8f6a5aac84aa05" + 166 "1ba30b396a0aac973d58e091473f5985", 167 "7f1b32b81b820d02614f8895ac1d4eac"); 168 test.check(4, 169 "b83b533708bf535d0aa6e52980d53b78", 170 "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", 171 "42831ec2217774244b7221b784d0d49c" + 172 "e3aa212f2c02a4e035c17e2329aca12e" + 173 "21d514b25466931c7d8f6a5aac84aa05" + 174 "1ba30b396a0aac973d58e091", 175 "698e57f70e6ecc7fd9463b7260a9ae5f"); 176 test.check(5, "b83b533708bf535d0aa6e52980d53b78", 177 "feedfacedeadbeeffeedfacedeadbeef" + "abaddad2", 178 "61353b4c2806934a777ff51fa22a4755" + 179 "699b2a714fcdc6f83766e5f97b6c7423" + 180 "73806900e49f24b22b097544d4896b42" + 181 "4989b5e1ebac0f07c23f4598", 182 "df586bb4c249b92cb6922877e444d37b"); 183 i++; 184 } 185 } 186 }