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 }