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