1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 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 * @test 25 * @bug 8014628 26 * @modules java.base/sun.security.util 27 * java.security.jgss/sun.security.krb5.internal.crypto.dk:+open 28 * @summary https://tools.ietf.org/html/rfc8009 Test Vectors 29 */ 30 31 import javax.crypto.Cipher; 32 import java.lang.reflect.Method; 33 import java.util.Arrays; 34 35 import sun.security.krb5.internal.crypto.dk.AesSha2DkCrypto; 36 import sun.security.util.HexDumpEncoder; 37 38 public class KerberosAesSha2 { 39 40 public static void main(String[] args) throws Exception { 41 42 AesSha2DkCrypto dk128 = new AesSha2DkCrypto(128); 43 AesSha2DkCrypto dk256 = new AesSha2DkCrypto(256); 44 45 boolean aes256ok = Cipher.getMaxAllowedKeyLength("AES") >= 256; 46 47 // Sample results for string-to-key conversion: 48 char[] pass = "password".toCharArray(); 49 byte[] salt = cat( 50 hex("10 DF 9D D7 83 E5 BC 8A CE A1 73 0E 74 35 5F 61"), 51 "ATHENA.MIT.EDUraeburn".getBytes()); 52 53 check(stringToKey(dk128, pass, salt, null), 54 hex("08 9B CA 48 B1 05 EA 6E A7 7C A5 D2 F3 9D C5 E7")); 55 56 check(stringToKey(dk256, pass, salt, null), 57 hex("45 BD 80 6D BF 6A 83 3A 9C FF C1 C9 45 89 A2 22\n" + 58 "36 7A 79 BC 21 C4 13 71 89 06 E9 F5 78 A7 84 67")); 59 60 // Sample results for key derivation: 61 byte[] bk16 = hex("37 05 D9 60 80 C1 77 28 A0 E8 00 EA B6 E0 D2 3C"); 62 63 check(deriveKey(dk128, bk16, 2, (byte) 0x99), 64 hex("B3 1A 01 8A 48 F5 47 76 F4 03 E9 A3 96 32 5D C3")); 65 check(deriveKey(dk128, bk16, 2, (byte) 0xaa), 66 hex("9B 19 7D D1 E8 C5 60 9D 6E 67 C3 E3 7C 62 C7 2E")); 67 check(deriveKey(dk128, bk16, 2, (byte) 0x55), 68 hex("9F DA 0E 56 AB 2D 85 E1 56 9A 68 86 96 C2 6A 6C")); 69 70 byte[] bk32 = hex( 71 "6D 40 4D 37 FA F7 9F 9D F0 D3 35 68 D3 20 66 98\n" + 72 "00 EB 48 36 47 2E A8 A0 26 D1 6B 71 82 46 0C 52"); 73 74 check(deriveKey(dk256, bk32, 2, (byte) 0x99), hex( 75 "EF 57 18 BE 86 CC 84 96 3D 8B BB 50 31 E9 F5 C4\n" + 76 "BA 41 F2 8F AF 69 E7 3D")); 77 check(deriveKey(dk256, bk32, 2, (byte) 0xaa), hex( 78 "56 AB 22 BE E6 3D 82 D7 BC 52 27 F6 77 3F 8E A7\n" + 79 "A5 EB 1C 82 51 60 C3 83 12 98 0C 44 2E 5C 7E 49")); 80 check(deriveKey(dk256, bk32, 2, (byte) 0x55), hex( 81 "69 B1 65 14 E3 CD 8E 56 B8 20 10 D5 C7 30 12 B6\n" + 82 "22 C4 D0 0F FC 23 ED 1F")); 83 84 // Sample encryptions (all using the default cipher state): 85 86 check(enc(dk128, hex("7E 58 95 EA F2 67 24 35 BA D8 17 F5 45 A3 71 48"), 87 bk16, hex("")), 88 hex("EF 85 FB 89 0B B8 47 2F 4D AB 20 39 4D CA 78 1D\n" + 89 "AD 87 7E DA 39 D5 0C 87 0C 0D 5A 0A 8E 48 C7 18")); 90 91 check(enc(dk128, hex("7B CA 28 5E 2F D4 13 0F B5 5B 1A 5C 83 BC 5B 24"), 92 bk16, hex("00 01 02 03 04 05")), 93 hex("84 D7 F3 07 54 ED 98 7B AB 0B F3 50 6B EB 09 CF\n" + 94 "B5 54 02 CE F7 E6 87 7C E9 9E 24 7E 52 D1 6E D4\n" + 95 "42 1D FD F8 97 6C")); 96 97 check(enc(dk128, hex("56 AB 21 71 3F F6 2C 0A 14 57 20 0F 6F A9 94 8F"), 98 bk16, hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F")), 99 hex("35 17 D6 40 F5 0D DC 8A D3 62 87 22 B3 56 9D 2A\n" + 100 "E0 74 93 FA 82 63 25 40 80 EA 65 C1 00 8E 8F C2\n" + 101 "95 FB 48 52 E7 D8 3E 1E 7C 48 C3 7E EB E6 B0 D3")); 102 103 check(enc(dk128, hex("A7 A4 E2 9A 47 28 CE 10 66 4F B6 4E 49 AD 3F AC"), 104 bk16, hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" + 105 "10 11 12 13 14")), 106 hex("72 0F 73 B1 8D 98 59 CD 6C CB 43 46 11 5C D3 36\n" + 107 "C7 0F 58 ED C0 C4 43 7C 55 73 54 4C 31 C8 13 BC\n" + 108 "E1 E6 D0 72 C1 86 B3 9A 41 3C 2F 92 CA 9B 83 34\n" + 109 "A2 87 FF CB FC\n")); 110 111 if (aes256ok) { 112 check(enc(dk256, hex("F7 64 E9 FA 15 C2 76 47 8B 2C 7D 0C 4E 5F 58 E4"), 113 bk32, hex("")), 114 hex("41 F5 3F A5 BF E7 02 6D 91 FA F9 BE 95 91 95 A0\n" + 115 "58 70 72 73 A9 6A 40 F0 A0 19 60 62 1A C6 12 74\n" + 116 "8B 9B BF BE 7E B4 CE 3C\n")); 117 118 check(enc(dk256, hex("B8 0D 32 51 C1 F6 47 14 94 25 6F FE 71 2D 0B 9A"), 119 bk32, hex("00 01 02 03 04 05")), 120 hex("4E D7 B3 7C 2B CA C8 F7 4F 23 C1 CF 07 E6 2B C7\n" + 121 "B7 5F B3 F6 37 B9 F5 59 C7 F6 64 F6 9E AB 7B 60\n" + 122 "92 23 75 26 EA 0D 1F 61 CB 20 D6 9D 10 F2\n")); 123 124 check(enc(dk256, hex("53 BF 8A 0D 10 52 65 D4 E2 76 42 86 24 CE 5E 63"), 125 bk32, hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F")), 126 hex("BC 47 FF EC 79 98 EB 91 E8 11 5C F8 D1 9D AC 4B\n" + 127 "BB E2 E1 63 E8 7D D3 7F 49 BE CA 92 02 77 64 F6\n" + 128 "8C F5 1F 14 D7 98 C2 27 3F 35 DF 57 4D 1F 93 2E\n" + 129 "40 C4 FF 25 5B 36 A2 66\n")); 130 131 check(enc(dk256, hex("76 3E 65 36 7E 86 4F 02 F5 51 53 C7 E3 B5 8A F1"), 132 bk32, hex("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" + 133 "10 11 12 13 14")), 134 hex("40 01 3E 2D F5 8E 87 51 95 7D 28 78 BC D2 D6 FE\n" + 135 "10 1C CF D5 56 CB 1E AE 79 DB 3C 3E E8 64 29 F2\n" + 136 "B2 A6 02 AC 86 FE F6 EC B6 47 D6 29 5F AE 07 7A\n" + 137 "1F EB 51 75 08 D2 C1 6B 41 92 E0 1F 62\n")); 138 } 139 140 // Sample checksums: 141 142 byte[] msg = hex( 143 "00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n" + 144 "10 11 12 13 14"); 145 146 check(checksum(dk128, bk16, msg), hex( 147 "D7 83 67 18 66 43 D6 7B 41 1C BA 91 39 FC 1D EE")); 148 149 check(checksum(dk256, bk32, msg), hex( 150 "45 EE 79 15 67 EE FC A3 7F 4A C1 E0 22 2D E8 0D\n" + 151 "43 C3 BF A0 66 99 67 2A")); 152 153 // Sample pseudorandom function (PRF) invocations: 154 // Java does not support PRF. Skipped. 155 } 156 157 private static byte[] stringToKey(AesSha2DkCrypto dk, 158 char[] pass, byte[] salt, byte[] params) throws Exception { 159 Method m = AesSha2DkCrypto.class.getDeclaredMethod("stringToKey", 160 char[].class, byte[].class, byte[].class); 161 m.setAccessible(true); 162 return (byte[])m.invoke(dk, pass, salt, params); 163 } 164 165 private static byte[] deriveKey(AesSha2DkCrypto dk, byte[] baseKey, 166 int usage, byte type) throws Exception { 167 Method m = AesSha2DkCrypto.class.getDeclaredMethod("deriveKey", 168 byte[].class, int.class, byte.class); 169 m.setAccessible(true); 170 return (byte[]) m.invoke(dk, baseKey, usage, type); 171 } 172 173 private static byte[] cat(byte[] b1, byte[] b2) { 174 byte[] result = Arrays.copyOf(b1, b1.length + b2.length); 175 System.arraycopy(b2, 0, result, b1.length, b2.length); 176 return result; 177 } 178 179 private static byte[] enc(AesSha2DkCrypto dk, byte[] confounder, 180 byte[] bk, byte[] text) throws Exception { 181 return dk.encryptRaw(bk, 2, new byte[16], cat(confounder, text), 182 0, confounder.length + text.length); 183 } 184 185 private static byte[] checksum(AesSha2DkCrypto dk, byte[] baseKey, byte[] text) 186 throws Exception { 187 return dk.calculateChecksum(baseKey, 2, text, 0, text.length); 188 } 189 190 private static byte[] hex(String var) { 191 var = var.replaceAll("\\s", ""); 192 byte[] data = new byte[var.length()/2]; 193 for (int i=0; i<data.length; i++) { 194 data[i] = Integer.valueOf(var.substring(2*i,2*i+2), 16).byteValue(); 195 } 196 return data; 197 } 198 199 private static void check(byte[] b1, byte[] b2) throws Exception { 200 if (!Arrays.equals(b1, b2)) { 201 dump(b1); dump(b2); 202 throw new Exception("Failure"); 203 } 204 } 205 206 private static void dump(byte[] data) throws Exception { 207 new HexDumpEncoder().encodeBuffer(data, System.err); 208 } 209 }