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/* 25 * @test 26 * @bug 8173783 27 * @summary 6u141 IllegalArgumentException: jdk.tls.namedGroups 28 * run main/othervm HelloExtensionsTest 29 * run main/othervm HelloExtensionsTest -Djdk.tls.namedGroups="bug, bug" 30 * run main/othervm HelloExtensionsTest -Djdk.tls.namedGroups="secp521r1" 31 * 32 */ 33import javax.crypto.*; 34import javax.net.ssl.*; 35import javax.net.ssl.SSLEngineResult.*; 36import java.io.*; 37import java.nio.*; 38import java.security.*; 39 40public class HelloExtensionsTest { 41 42 private static boolean debug = false; 43 private static boolean proceed = true; 44 private static boolean EcAvailable = isEcAvailable(); 45 46 static String pathToStores = "../../../../javax/net/ssl/etc"; 47 private static String keyStoreFile = "keystore"; 48 private static String trustStoreFile = "truststore"; 49 private static String passwd = "passphrase"; 50 51 private static String keyFilename = 52 System.getProperty("test.src", "./") + "/" + pathToStores + 53 "/" + keyStoreFile; 54 private static String trustFilename = 55 System.getProperty("test.src", "./") + "/" + pathToStores + 56 "/" + trustStoreFile; 57 58 private static void checkDone(SSLEngine ssle) throws Exception { 59 if (!ssle.isInboundDone()) { 60 throw new Exception("isInboundDone isn't done"); 61 } 62 if (!ssle.isOutboundDone()) { 63 throw new Exception("isOutboundDone isn't done"); 64 } 65 } 66 67 private static void runTest(SSLEngine ssle) throws Exception { 68 69 /* 70 71 A client hello message captured via wireshark by selecting 72 a TLSv1.2 Client Hello record and clicking through to the 73 TLSv1.2 Record Layer line and then selecting the hex stream 74 via "copy -> bytes -> hex stream". 75 76 For Record purposes, here's the ClientHello : 77 78 *** ClientHello, TLSv1.2 79 RandomCookie: GMT: 1469560450 bytes = { 108, 140, 12, 202, 80 2, 213, 10, 236, 143, 223, 58, 162, 228, 155, 239, 3, 98, 81 232, 89, 41, 116, 120, 13, 37, 105, 153, 97, 241 } 82 Session ID: {} 83 Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 84 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, 85 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, 86 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, 87 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 88 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, 89 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 90 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 91 TLS_RSA_WITH_AES_128_CBC_SHA, 92 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, 93 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, 94 TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 95 TLS_DHE_DSS_WITH_AES_128_CBC_SHA, 96 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 97 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 98 TLS_RSA_WITH_AES_128_GCM_SHA256, 99 TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, 100 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, 101 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 102 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, 103 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, 104 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 105 SSL_RSA_WITH_3DES_EDE_CBC_SHA, 106 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, 107 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, 108 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 109 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, 110 TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 111 Compression Methods: { 0 } 112 Extension elliptic_curves, curve names: {secp256r1, 113 sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, 114 sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, 115 sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, 116 secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1} 117 Extension ec_point_formats, formats: [uncompressed] 118 Extension signature_algorithms, signature_algorithms: 119 SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, 120 SHA256withECDSA, SHA256withRSA, Unknown (hash:0x3, signature:0x3), 121 Unknown (hash:0x3, signature:0x1), SHA1withECDSA, 122 SHA1withRSA, SHA1withDSA 123 Extension server_name, server_name: 124 [host_name: bugs.openjdk.java.net] 125 */ 126 127 String hello = "16030300df010000db03035898b7826c8c0cc" + 128 "a02d50aec8fdf3aa2e49bef0362e8592974780d25699961f" + 129 "100003ac023c027003cc025c02900670040c009c013002fc" + 130 "004c00e00330032c02bc02f009cc02dc031009e00a2c008c" + 131 "012000ac003c00d0016001300ff01000078000a003400320" + 132 "0170001000300130015000600070009000a0018000b000c0" + 133 "019000d000e000f001000110002001200040005001400080" + 134 "016000b00020100000d00180016060306010503050104030" + 135 "401030303010203020102020000001a00180000156275677" + 136 "32e6f70656e6a646b2e6a6176612e6e6574"; 137 138 byte[] msg_clihello = hexStringToByteArray(hello); 139 ByteBuffer bf_clihello = ByteBuffer.wrap(msg_clihello); 140 141 SSLSession session = ssle.getSession(); 142 int appBufferMax = session.getApplicationBufferSize(); 143 int netBufferMax = session.getPacketBufferSize(); 144 145 ByteBuffer serverIn = ByteBuffer.allocate(appBufferMax + 50); 146 ByteBuffer serverOut = ByteBuffer.wrap("I'm Server".getBytes()); 147 ByteBuffer sTOc = ByteBuffer.allocate(netBufferMax); 148 149 ssle.beginHandshake(); 150 151 // unwrap the clientHello message. 152 SSLEngineResult result = ssle.unwrap(bf_clihello, serverIn); 153 System.out.println("server unwrap " + result); 154 runDelegatedTasks(result, ssle); 155 156 if (!proceed) { 157 //expected exception occurred. Don't process anymore 158 return; 159 } 160 161 // one more step, ensure the clientHello message is parsed. 162 SSLEngineResult.HandshakeStatus status = ssle.getHandshakeStatus(); 163 if ( status == HandshakeStatus.NEED_UNWRAP) { 164 result = ssle.unwrap(bf_clihello, serverIn); 165 System.out.println("server unwrap " + result); 166 runDelegatedTasks(result, ssle); 167 } else if ( status == HandshakeStatus.NEED_WRAP) { 168 result = ssle.wrap(serverOut, sTOc); 169 System.out.println("server wrap " + result); 170 runDelegatedTasks(result, ssle); 171 } else { 172 throw new Exception("unexpected handshake status " + status); 173 } 174 175 // enough, stop 176 } 177 178 /* 179 * If the result indicates that we have outstanding tasks to do, 180 * go ahead and run them in this thread. 181 */ 182 private static void runDelegatedTasks(SSLEngineResult result, 183 SSLEngine engine) throws Exception { 184 185 if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { 186 Runnable runnable; 187 try { 188 while ((runnable = engine.getDelegatedTask()) != null) { 189 log("\trunning delegated task..."); 190 runnable.run(); 191 } 192 } catch (ExceptionInInitializerError e) { 193 String v = System.getProperty("jdk.tls.namedGroups"); 194 if (!EcAvailable || v == null) { 195 // we weren't expecting this if no EC providers 196 throw new RuntimeException("Unexpected Error :" + e); 197 } 198 if (v != null && v.contains("bug")) { 199 // OK - we were expecting this Error 200 log("got expected error for bad jdk.tls.namedGroups"); 201 proceed = false; 202 return; 203 } else { 204 System.out.println("Unexpected error. " + 205 "jdk.tls.namedGroups value: " + v); 206 throw e; 207 } 208 } 209 HandshakeStatus hsStatus = engine.getHandshakeStatus(); 210 if (hsStatus == HandshakeStatus.NEED_TASK) { 211 throw new Exception( 212 "handshake shouldn't need additional tasks"); 213 } 214 log("\tnew HandshakeStatus: " + hsStatus); 215 } 216 } 217 218 private static byte[] hexStringToByteArray(String s) { 219 int len = s.length(); 220 byte[] data = new byte[len / 2]; 221 for (int i = 0; i < len; i += 2) { 222 data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 223 + Character.digit(s.charAt(i+1), 16)); 224 } 225 return data; 226 } 227 228 private static boolean isEcAvailable() { 229 try { 230 Signature.getInstance("SHA1withECDSA"); 231 Signature.getInstance("NONEwithECDSA"); 232 KeyAgreement.getInstance("ECDH"); 233 KeyFactory.getInstance("EC"); 234 KeyPairGenerator.getInstance("EC"); 235 AlgorithmParameters.getInstance("EC"); 236 } catch (Exception e) { 237 log("EC not available. Received: " + e); 238 return false; 239 } 240 return true; 241 } 242 243 public static void main(String args[]) throws Exception { 244 SSLEngine ssle = createSSLEngine(keyFilename, trustFilename); 245 runTest(ssle); 246 System.out.println("Test Passed."); 247 } 248 249 /* 250 * Create an initialized SSLContext to use for this test. 251 */ 252 static private SSLEngine createSSLEngine(String keyFile, String trustFile) 253 throws Exception { 254 255 SSLEngine ssle; 256 257 KeyStore ks = KeyStore.getInstance("JKS"); 258 KeyStore ts = KeyStore.getInstance("JKS"); 259 260 char[] passphrase = "passphrase".toCharArray(); 261 262 ks.load(new FileInputStream(keyFile), passphrase); 263 ts.load(new FileInputStream(trustFile), passphrase); 264 265 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 266 kmf.init(ks, passphrase); 267 268 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 269 tmf.init(ts); 270 271 SSLContext sslCtx = SSLContext.getInstance("TLS"); 272 273 sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 274 275 ssle = sslCtx.createSSLEngine(); 276 ssle.setUseClientMode(false); 277 278 return ssle; 279 } 280 281 282 private static void log(String str) { 283 if (debug) { 284 System.out.println(str); 285 } 286 } 287} 288