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