1 /* 2 * Copyright (c) 2005, 2016, 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 /* 25 * @test 26 * @bug 6316539 8136355 27 * @summary Known-answer-test for TlsKeyMaterial generator 28 * @author Andreas Sterbenz 29 * @library .. 30 * @modules java.base/sun.security.internal.spec 31 * jdk.crypto.token 32 * @run main/othervm TestKeyMaterial 33 * @run main/othervm TestKeyMaterial sm policy 34 */ 35 36 import java.io.BufferedReader; 37 import java.nio.file.Files; 38 import java.nio.file.Paths; 39 import java.security.Provider; 40 import java.security.InvalidAlgorithmParameterException; 41 import java.util.Arrays; 42 import javax.crypto.KeyGenerator; 43 import javax.crypto.SecretKey; 44 import javax.crypto.spec.IvParameterSpec; 45 import javax.crypto.spec.SecretKeySpec; 46 import sun.security.internal.spec.TlsKeyMaterialParameterSpec; 47 import sun.security.internal.spec.TlsKeyMaterialSpec; 48 49 public class TestKeyMaterial extends PKCS11Test { 50 51 private static final int PREFIX_LENGTH = "km-master: ".length(); 52 53 public static void main(String[] args) throws Exception { 54 main(new TestKeyMaterial(), args); 55 } 56 57 @Override 58 public void main(Provider provider) throws Exception { 59 if (provider.getService("KeyGenerator", "SunTlsKeyMaterial") == null) { 60 System.out.println("Provider does not support algorithm, skipping"); 61 return; 62 } 63 64 try (BufferedReader reader = Files.newBufferedReader( 65 Paths.get(BASE, "keymatdata.txt"))) { 66 67 int n = 0; 68 int lineNumber = 0; 69 70 byte[] master = null; 71 int major = 0; 72 int minor = 0; 73 byte[] clientRandom = null; 74 byte[] serverRandom = null; 75 String cipherAlgorithm = null; 76 int keyLength = 0; 77 int expandedKeyLength = 0; 78 int ivLength = 0; 79 int macLength = 0; 80 byte[] clientCipherBytes = null; 81 byte[] serverCipherBytes = null; 82 byte[] clientIv = null; 83 byte[] serverIv = null; 84 byte[] clientMacBytes = null; 85 byte[] serverMacBytes = null; 86 87 while (true) { 88 String line = reader.readLine(); 89 lineNumber++; 90 if (line == null) { 91 break; 92 } 93 if (line.startsWith("km-") == false) { 94 continue; 95 } 96 String data = line.substring(PREFIX_LENGTH); 97 if (line.startsWith("km-master:")) { 98 master = parse(data); 99 } else if (line.startsWith("km-major:")) { 100 major = Integer.parseInt(data); 101 } else if (line.startsWith("km-minor:")) { 102 minor = Integer.parseInt(data); 103 } else if (line.startsWith("km-crandom:")) { 104 clientRandom = parse(data); 105 } else if (line.startsWith("km-srandom:")) { 106 serverRandom = parse(data); 107 } else if (line.startsWith("km-cipalg:")) { 108 cipherAlgorithm = data; 109 } else if (line.startsWith("km-keylen:")) { 110 keyLength = Integer.parseInt(data); 111 } else if (line.startsWith("km-explen:")) { 112 expandedKeyLength = Integer.parseInt(data); 113 } else if (line.startsWith("km-ivlen:")) { 114 ivLength = Integer.parseInt(data); 115 } else if (line.startsWith("km-maclen:")) { 116 macLength = Integer.parseInt(data); 117 } else if (line.startsWith("km-ccipkey:")) { 118 clientCipherBytes = parse(data); 119 } else if (line.startsWith("km-scipkey:")) { 120 serverCipherBytes = parse(data); 121 } else if (line.startsWith("km-civ:")) { 122 clientIv = parse(data); 123 } else if (line.startsWith("km-siv:")) { 124 serverIv = parse(data); 125 } else if (line.startsWith("km-cmackey:")) { 126 clientMacBytes = parse(data); 127 } else if (line.startsWith("km-smackey:")) { 128 serverMacBytes = parse(data); 129 130 System.out.print("."); 131 n++; 132 133 KeyGenerator kg = 134 KeyGenerator.getInstance("SunTlsKeyMaterial", provider); 135 SecretKey masterKey = 136 new SecretKeySpec(master, "TlsMasterSecret"); 137 TlsKeyMaterialParameterSpec spec = 138 new TlsKeyMaterialParameterSpec(masterKey, major, minor, 139 clientRandom, serverRandom, cipherAlgorithm, 140 keyLength, expandedKeyLength, ivLength, macLength, 141 null, -1, -1); 142 143 try { 144 kg.init(spec); 145 TlsKeyMaterialSpec result = 146 (TlsKeyMaterialSpec)kg.generateKey(); 147 match(lineNumber, clientCipherBytes, 148 result.getClientCipherKey(), cipherAlgorithm); 149 match(lineNumber, serverCipherBytes, 150 result.getServerCipherKey(), cipherAlgorithm); 151 match(lineNumber, clientIv, result.getClientIv(), ""); 152 match(lineNumber, serverIv, result.getServerIv(), ""); 153 match(lineNumber, clientMacBytes, result.getClientMacKey(), ""); 154 match(lineNumber, serverMacBytes, result.getServerMacKey(), ""); 155 } catch (InvalidAlgorithmParameterException iape) { 156 // SSLv3 support is removed in S12 157 if (major == 3 && minor == 0) { 158 System.out.println("Skip testing SSLv3"); 159 continue; 160 } 161 } 162 } else { 163 throw new Exception("Unknown line: " + line); 164 } 165 } 166 if (n == 0) { 167 throw new Exception("no tests"); 168 } 169 System.out.println(); 170 System.out.println("OK: " + n + " tests"); 171 } 172 } 173 174 private static void stripParity(byte[] b) { 175 for (int i = 0; i < b.length; i++) { 176 b[i] &= 0xfe; 177 } 178 } 179 180 private static void match(int lineNumber, byte[] out, Object res, 181 String cipherAlgorithm) throws Exception { 182 if ((out == null) || (res == null)) { 183 if (out != res) { 184 throw new Exception("null mismatch line " + lineNumber); 185 } else { 186 return; 187 } 188 } 189 byte[] b; 190 if (res instanceof SecretKey) { 191 b = ((SecretKey)res).getEncoded(); 192 if (cipherAlgorithm.equalsIgnoreCase("DES") || 193 cipherAlgorithm.equalsIgnoreCase("DESede")) { 194 // strip DES parity bits before comparision 195 stripParity(out); 196 stripParity(b); 197 } 198 } else if (res instanceof IvParameterSpec) { 199 b = ((IvParameterSpec)res).getIV(); 200 } else { 201 throw new Exception(res.getClass().getName()); 202 } 203 if (Arrays.equals(out, b) == false) { 204 System.out.println(); 205 System.out.println("out: " + toString(out)); 206 System.out.println("b: " + toString(b)); 207 throw new Exception("mismatch line " + lineNumber); 208 } 209 } 210 211 }