ShortRSAKey512.java revision 14858:0c3d00b560c9
1187962Sdas/* 2187962Sdas * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. 3187962Sdas * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4187962Sdas * 5187962Sdas * This code is free software; you can redistribute it and/or modify it 6187962Sdas * under the terms of the GNU General Public License version 2 only, as 7187962Sdas * published by the Free Software Foundation. Oracle designates this 8187962Sdas * particular file as subject to the "Classpath" exception as provided 9187962Sdas * by Oracle in the LICENSE file that accompanied this code. 10187962Sdas * 11187962Sdas * This code is distributed in the hope that it will be useful, but WITHOUT 12187962Sdas * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13187962Sdas * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14187962Sdas * version 2 for more details (a copy is included in the LICENSE file that 15187962Sdas * accompanied this code). 16187962Sdas * 17187962Sdas * You should have received a copy of the GNU General Public License version 18187962Sdas * 2 along with this work; if not, write to the Free Software Foundation, 19187962Sdas * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20187962Sdas * 21187962Sdas * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22187962Sdas * or visit www.oracle.com if you need additional information or have any 23187962Sdas * questions. 24187962Sdas */ 25187962Sdas 26187962Sdas// This test case relies on updated static security property, no way to re-use 27187962Sdas// security property in samevm/agentvm mode. 28187962Sdas 29187962Sdas/* 30187962Sdas * @test 31187962Sdas * @bug 7106773 32187962Sdas * @summary 512 bits RSA key cannot work with SHA384 and SHA512 33187962Sdas * 34187962Sdas * SunJSSE does not support dynamic system properties, no way to re-use 35187962Sdas * system properties in samevm/agentvm mode. 36187962Sdas * @key intermittent 37187962Sdas * @run main/othervm ShortRSAKey512 PKIX 38187962Sdas * @run main/othervm ShortRSAKey512 SunX509 39187962Sdas */ 40251241Sdas 41251241Sdasimport java.net.*; 42271296Sngieimport java.util.*; 43187962Sdasimport java.io.*; 44187962Sdasimport javax.net.ssl.*; 45187962Sdasimport java.security.Security; 46187962Sdasimport java.security.KeyStore; 47187962Sdasimport java.security.KeyFactory; 48187962Sdasimport java.security.cert.Certificate; 49187962Sdasimport java.security.cert.CertificateFactory; 50187962Sdasimport java.security.spec.*; 51187962Sdasimport java.security.interfaces.*; 52187962Sdasimport java.util.Base64; 53187962Sdas 54187962Sdas 55187962Sdaspublic class ShortRSAKey512 { 56187962Sdas 57187962Sdas /* 58187962Sdas * ============================================================= 59187962Sdas * Set the various variables needed for the tests, then 60187962Sdas * specify what tests to run on each side. 61187962Sdas */ 62187962Sdas 63187962Sdas /* 64187962Sdas * Should we run the client or server in a separate thread? 65187962Sdas * Both sides can throw exceptions, but do you have a preference 66187962Sdas * as to which side should be the main thread. 67187962Sdas */ 68187962Sdas static boolean separateServerThread = false; 69187962Sdas 70187962Sdas /* 71187962Sdas * Where do we find the keystores? 72187962Sdas */ 73187962Sdas // Certificates and key used in the test. 74187962Sdas static String trustedCertStr = 75187962Sdas "-----BEGIN CERTIFICATE-----\n" + 76187962Sdas "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + 77187962Sdas "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + 78187962Sdas "MTEwODE5MDE1MjE5WhcNMzIwNzI5MDE1MjE5WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + 79187962Sdas "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + 80187962Sdas "KoZIhvcNAQEBBQADgY0AMIGJAoGBAM8orG08DtF98TMSscjGsidd1ZoN4jiDpi8U\n" + 81187962Sdas "ICz+9dMm1qM1d7O2T+KH3/mxyox7Rc2ZVSCaUD0a3CkhPMnlAx8V4u0H+E9sqso6\n" + 82187962Sdas "iDW3JpOyzMExvZiRgRG/3nvp55RMIUV4vEHOZ1QbhuqG4ebN0Vz2DkRft7+flthf\n" + 83187962Sdas "vDld6f5JAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLl81dnfp0wDrv0OJ1sxlWzH83Xh\n" + 84187962Sdas "MGMGA1UdIwRcMFqAFLl81dnfp0wDrv0OJ1sxlWzH83XhoT+kPTA7MQswCQYDVQQG\n" + 85187962Sdas "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + 86187962Sdas "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" + 87187962Sdas "BQADgYEALlgaH1gWtoBZ84EW8Hu6YtGLQ/L9zIFmHonUPZwn3Pr//icR9Sqhc3/l\n" + 88187962Sdas "pVTxOINuFHLRz4BBtEylzRIOPzK3tg8XwuLb1zd0db90x3KBCiAL6E6cklGEPwLe\n" + 89187962Sdas "XYMHDn9eDsaq861Tzn6ZwzMgw04zotPMoZN0mVd/3Qca8UJFucE=\n" + 90187962Sdas "-----END CERTIFICATE-----"; 91187962Sdas 92187962Sdas static String targetCertStr = 93187962Sdas "-----BEGIN CERTIFICATE-----\n" + 94187962Sdas "MIICNDCCAZ2gAwIBAgIBDDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + 95187962Sdas "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + 96187962Sdas "MTExMTA3MTM1NTUyWhcNMzEwNzI1MTM1NTUyWjBPMQswCQYDVQQGEwJVUzENMAsG\n" + 97187962Sdas "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" + 98187962Sdas "BAMTCWxvY2FsaG9zdDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC3Pb49OSPfOD2G\n" + 99187962Sdas "HSXFCFx1GJEZfqG9ZUf7xuIi/ra5dLjPGAaoY5QF2QOa8VnOriQCXDfyXHxsuRnE\n" + 100187962Sdas "OomxL7EVAgMBAAGjeDB2MAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQUXNCJK3/dtCIc\n" + 101187962Sdas "xb+zlA/JINlvs/MwHwYDVR0jBBgwFoAUuXzV2d+nTAOu/Q4nWzGVbMfzdeEwJwYD\n" + 102187962Sdas "VR0lBCAwHgYIKwYBBQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDAzANBgkqhkiG9w0B\n" + 103187962Sdas "AQQFAAOBgQB2qIDUxA2caMPpGtUACZAPRUtrGssCINIfItETXJZCx/cRuZ5sP4D9\n" + 104187962Sdas "N1acoNDn0hCULe3lhXAeTC9NZ97680yJzregQMV5wATjo1FGsKY30Ma+sc/nfzQW\n" + 105187962Sdas "+h/7RhYtoG0OTsiaDCvyhI6swkNJzSzrAccPY4+ZgU8HiDLzZTmM3Q==\n" + 106187962Sdas "-----END CERTIFICATE-----"; 107187962Sdas 108187962Sdas // Private key in the format of PKCS#8, key size is 512 bits. 109187962Sdas static String targetPrivateKey = 110187962Sdas "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAtz2+PTkj3zg9hh0l\n" + 111187962Sdas "xQhcdRiRGX6hvWVH+8biIv62uXS4zxgGqGOUBdkDmvFZzq4kAlw38lx8bLkZxDqJ\n" + 112187962Sdas "sS+xFQIDAQABAkByx/5Oo2hQ/w2q4L8z+NTRlJ3vdl8iIDtC/4XPnfYfnGptnpG6\n" + 113187962Sdas "ZThQRvbMZiai0xHQPQMszvAHjZVme1eDl3EBAiEA3aKJHynPVCEJhpfCLWuMwX5J\n" + 114187962Sdas "1LntwJO7NTOyU5m8rPECIQDTpzn5X44r2rzWBDna/Sx7HW9IWCxNgUD2Eyi2nA7W\n" + 115187962Sdas "ZQIgJerEorw4aCAuzQPxiGu57PB6GRamAihEAtoRTBQlH0ECIQDN08FgTtnesgCU\n" + 116187962Sdas "DFYLLcw1CiHvc7fZw4neBDHCrC8NtQIgA8TOUkGnpCZlQ0KaI8KfKWI+vxFcgFnH\n" + 117187962Sdas "3fnqsTgaUs4="; 118187962Sdas 119187962Sdas static char passphrase[] = "passphrase".toCharArray(); 120187962Sdas 121187962Sdas /* 122187962Sdas * Is the server ready to serve? 123187962Sdas */ 124187962Sdas volatile static boolean serverReady = false; 125187962Sdas 126187962Sdas /* 127187962Sdas * Turn on SSL debugging? 128187962Sdas */ 129187962Sdas static boolean debug = true; 130187962Sdas 131187962Sdas /* 132187962Sdas * Define the server side of the test. 133187962Sdas * 134187962Sdas * If the server prematurely exits, serverReady will be set to true 135187962Sdas * to avoid infinite hangs. 136187962Sdas */ 137187962Sdas void doServerSide() throws Exception { 138187962Sdas SSLContext context = generateSSLContext(null, targetCertStr, 139187962Sdas targetPrivateKey); 140 SSLServerSocketFactory sslssf = context.getServerSocketFactory(); 141 try (SSLServerSocket sslServerSocket = 142 (SSLServerSocket) sslssf.createServerSocket(serverPort)) { 143 144 serverPort = sslServerSocket.getLocalPort(); 145 System.out.println("Start server on port " + serverPort); 146 147 /* 148 * Signal Client, we're ready for his connect. 149 */ 150 serverReady = true; 151 152 try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { 153 InputStream sslIS = sslSocket.getInputStream(); 154 OutputStream sslOS = sslSocket.getOutputStream(); 155 156 sslIS.read(); 157 sslOS.write('A'); 158 sslOS.flush(); 159 } 160 } 161 } 162 163 /* 164 * Define the client side of the test. 165 * 166 * If the server prematurely exits, serverReady will be set to true 167 * to avoid infinite hangs. 168 */ 169 void doClientSide() throws Exception { 170 171 /* 172 * Wait for server to get started. 173 */ 174 while (!serverReady) { 175 Thread.sleep(50); 176 } 177 178 SSLContext context = generateSSLContext(trustedCertStr, null, null); 179 SSLSocketFactory sslsf = context.getSocketFactory(); 180 181 System.out.println("Client connects to port " + serverPort); 182 try (SSLSocket sslSocket = 183 (SSLSocket) sslsf.createSocket("localhost", serverPort)) { 184 185 // enable TLSv1.2 only 186 sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"}); 187 188 // enable a block cipher 189 sslSocket.setEnabledCipherSuites( 190 new String[] {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"}); 191 192 InputStream sslIS = sslSocket.getInputStream(); 193 OutputStream sslOS = sslSocket.getOutputStream(); 194 195 sslOS.write('B'); 196 sslOS.flush(); 197 sslIS.read(); 198 } 199 } 200 201 /* 202 * ============================================================= 203 * The remainder is just support stuff 204 */ 205 private static String tmAlgorithm; // trust manager 206 207 private static void parseArguments(String[] args) { 208 tmAlgorithm = args[0]; 209 } 210 211 private static SSLContext generateSSLContext(String trustedCertStr, 212 String keyCertStr, String keySpecStr) throws Exception { 213 214 // generate certificate from cert string 215 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 216 217 // create a key store 218 KeyStore ks = KeyStore.getInstance("JKS"); 219 ks.load(null, null); 220 221 // import the trused cert 222 Certificate trusedCert = null; 223 ByteArrayInputStream is = null; 224 if (trustedCertStr != null) { 225 is = new ByteArrayInputStream(trustedCertStr.getBytes()); 226 trusedCert = cf.generateCertificate(is); 227 is.close(); 228 229 ks.setCertificateEntry("RSA Export Signer", trusedCert); 230 } 231 232 if (keyCertStr != null) { 233 // generate the private key. 234 PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( 235 Base64.getMimeDecoder().decode(keySpecStr)); 236 KeyFactory kf = KeyFactory.getInstance("RSA"); 237 RSAPrivateKey priKey = 238 (RSAPrivateKey)kf.generatePrivate(priKeySpec); 239 240 // generate certificate chain 241 is = new ByteArrayInputStream(keyCertStr.getBytes()); 242 Certificate keyCert = cf.generateCertificate(is); 243 is.close(); 244 245 Certificate[] chain = null; 246 if (trusedCert != null) { 247 chain = new Certificate[2]; 248 chain[0] = keyCert; 249 chain[1] = trusedCert; 250 } else { 251 chain = new Certificate[1]; 252 chain[0] = keyCert; 253 } 254 255 // import the key entry. 256 ks.setKeyEntry("Whatever", priKey, passphrase, chain); 257 } 258 259 // create SSL context 260 TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); 261 tmf.init(ks); 262 263 SSLContext ctx = SSLContext.getInstance("TLS"); 264 if (keyCertStr != null && !keyCertStr.isEmpty()) { 265 KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); 266 kmf.init(ks, passphrase); 267 268 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 269 ks = null; 270 } else { 271 ctx.init(null, tmf.getTrustManagers(), null); 272 } 273 274 return ctx; 275 } 276 277 278 // use any free port by default 279 volatile int serverPort = 0; 280 281 volatile Exception serverException = null; 282 volatile Exception clientException = null; 283 284 public static void main(String[] args) throws Exception { 285 // reset the security property to make sure that the algorithms 286 // and keys used in this test are not disabled. 287 Security.setProperty("jdk.certpath.disabledAlgorithms", "MD2"); 288 Security.setProperty("jdk.tls.disabledAlgorithms", 289 "SSLv3, RC4, DH keySize < 768"); 290 291 if (debug) 292 System.setProperty("javax.net.debug", "all"); 293 294 /* 295 * Get the customized arguments. 296 */ 297 parseArguments(args); 298 299 /* 300 * Start the tests. 301 */ 302 new ShortRSAKey512(); 303 } 304 305 Thread clientThread = null; 306 Thread serverThread = null; 307 308 /* 309 * Primary constructor, used to drive remainder of the test. 310 * 311 * Fork off the other side, then do your work. 312 */ 313 ShortRSAKey512() throws Exception { 314 if (separateServerThread) { 315 startServer(true); 316 startClient(false); 317 } else { 318 startClient(true); 319 startServer(false); 320 } 321 322 /* 323 * Wait for other side to close down. 324 */ 325 if (separateServerThread) { 326 serverThread.join(); 327 } else { 328 clientThread.join(); 329 } 330 331 /* 332 * When we get here, the test is pretty much over. 333 * Which side threw the error? 334 */ 335 Exception local; 336 Exception remote; 337 338 if (separateServerThread) { 339 remote = serverException; 340 local = clientException; 341 } else { 342 remote = clientException; 343 local = serverException; 344 } 345 346 /* 347 * If both failed, return the curthread's exception, but also 348 * print the remote side Exception 349 */ 350 if ((local != null) && (remote != null)) { 351 throw local; 352 } 353 354 if (remote != null) { 355 throw remote; 356 } 357 358 if (local != null) { 359 throw local; 360 } 361 } 362 363 void startServer(boolean newThread) { 364 if (newThread) { 365 serverThread = new Thread() { 366 public void run() { 367 try { 368 doServerSide(); 369 } catch (Exception e) { 370 /* 371 * Our server thread just died. 372 * 373 * Release the client, if not active already... 374 */ 375 System.err.println("Server died..."); 376 e.printStackTrace(System.err); 377 serverReady = true; 378 serverException = e; 379 } 380 } 381 }; 382 serverThread.setDaemon(true); 383 serverThread.start(); 384 } else { 385 try { 386 doServerSide(); 387 } catch (Exception e) { 388 serverException = e; 389 } finally { 390 serverReady = true; 391 } 392 } 393 } 394 395 void startClient(boolean newThread) { 396 if (newThread) { 397 clientThread = new Thread() { 398 public void run() { 399 try { 400 doClientSide(); 401 } catch (Exception e) { 402 /* 403 * Our client thread just died. 404 */ 405 System.err.println("Client died..."); 406 e.printStackTrace(System.err); 407 clientException = e; 408 } 409 } 410 }; 411 clientThread.setDaemon(true); 412 clientThread.start(); 413 } else { 414 try { 415 doClientSide(); 416 } catch (Exception e) { 417 clientException = e; 418 } 419 } 420 } 421} 422