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