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