1 /* 2 * Copyright (c) 2012, 2018, 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 7106773 8180570 27 * @summary 512 bits RSA key cannot work with SHA384 and SHA512 28 * @requires os.family == "windows" 29 * @modules java.base/sun.security.util 30 * java.base/sun.security.tools.keytool 31 * java.base/sun.security.x509 32 * @run main ShortRSAKeyWithinTLS 1024 33 * @run main ShortRSAKeyWithinTLS 768 34 * @run main ShortRSAKeyWithinTLS 512 35 */ 36 import java.io.*; 37 import java.net.*; 38 import java.security.cert.Certificate; 39 import java.util.*; 40 import java.security.*; 41 import java.security.cert.*; 42 import javax.net.*; 43 import javax.net.ssl.*; 44 45 import sun.security.tools.keytool.CertAndKeyGen; 46 import sun.security.util.KeyUtil; 47 import sun.security.x509.X500Name; 48 49 public class ShortRSAKeyWithinTLS { 50 51 /* 52 * ============================================================= 53 * Set the various variables needed for the tests, then 54 * specify what tests to run on each side. 55 */ 56 57 /* 58 * Should we run the client or server in a separate thread? 59 * Both sides can throw exceptions, but do you have a preference 60 * as to which side should be the main thread. 61 */ 62 static boolean separateServerThread = false; 63 64 /* 65 * Is the server ready to serve? 66 */ 67 volatile static boolean serverReady = false; 68 69 /* 70 * Turn on SSL debugging? 71 */ 72 static boolean debug = false; 73 74 /* 75 * If the client or server is doing some kind of object creation 76 * that the other side depends on, and that thread prematurely 77 * exits, you may experience a hang. The test harness will 78 * terminate all hung threads after its timeout has expired, 79 * currently 3 minutes by default, but you might try to be 80 * smart about it.... 81 */ 82 83 /* 84 * Define the server side of the test. 85 * 86 * If the server prematurely exits, serverReady will be set to true 87 * to avoid infinite hangs. 88 */ doServerSide()89 void doServerSide() throws Exception { 90 91 // load the key store 92 serverKS = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); 93 serverKS.load(null, null); 94 System.out.println("Loaded keystore: Windows-MY"); 95 96 // check key size 97 checkKeySize(serverKS); 98 99 // initialize the SSLContext 100 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 101 kmf.init(serverKS, null); 102 103 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 104 tmf.init(serverKS); 105 TrustManager[] tms = tmf.getTrustManagers(); 106 if (tms == null || tms.length == 0) { 107 throw new Exception("unexpected trust manager implementation"); 108 } else { 109 if (!(tms[0] instanceof X509TrustManager)) { 110 throw new Exception("unexpected trust manager" + 111 " implementation: " + 112 tms[0].getClass().getCanonicalName()); 113 } 114 } 115 serverTM = new MyExtendedX509TM((X509TrustManager)tms[0]); 116 tms = new TrustManager[] {serverTM}; 117 118 SSLContext ctx = SSLContext.getInstance("TLS"); 119 ctx.init(kmf.getKeyManagers(), tms, null); 120 121 ServerSocketFactory ssf = ctx.getServerSocketFactory(); 122 SSLServerSocket sslServerSocket = (SSLServerSocket) 123 ssf.createServerSocket(serverPort); 124 sslServerSocket.setNeedClientAuth(true); 125 serverPort = sslServerSocket.getLocalPort(); 126 System.out.println("serverPort = " + serverPort); 127 128 /* 129 * Signal Client, we're ready for his connect. 130 */ 131 serverReady = true; 132 133 SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); 134 InputStream sslIS = sslSocket.getInputStream(); 135 OutputStream sslOS = sslSocket.getOutputStream(); 136 137 sslIS.read(); 138 sslOS.write(85); 139 sslOS.flush(); 140 141 sslSocket.close(); 142 } 143 144 /* 145 * Define the client side of the test. 146 * 147 * If the server prematurely exits, serverReady will be set to true 148 * to avoid infinite hangs. 149 */ doClientSide()150 void doClientSide() throws Exception { 151 152 /* 153 * Wait for server to get started. 154 */ 155 while (!serverReady) { 156 Thread.sleep(50); 157 } 158 159 // load the key store 160 KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI"); 161 ks.load(null, null); 162 System.out.println("Loaded keystore: Windows-MY"); 163 164 // initialize the SSLContext 165 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 166 kmf.init(ks, null); 167 168 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 169 tmf.init(ks); 170 171 SSLContext ctx = SSLContext.getInstance("TLS"); 172 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 173 174 SSLSocketFactory sslsf = ctx.getSocketFactory(); 175 SSLSocket sslSocket = (SSLSocket) 176 sslsf.createSocket("localhost", serverPort); 177 178 if (clientProtocol != null) { 179 sslSocket.setEnabledProtocols(new String[] {clientProtocol}); 180 } 181 182 if (clientCiperSuite != null) { 183 sslSocket.setEnabledCipherSuites(new String[] {clientCiperSuite}); 184 } 185 186 InputStream sslIS = sslSocket.getInputStream(); 187 OutputStream sslOS = sslSocket.getOutputStream(); 188 189 sslOS.write(280); 190 sslOS.flush(); 191 sslIS.read(); 192 193 sslSocket.close(); 194 } 195 checkKeySize(KeyStore ks)196 private void checkKeySize(KeyStore ks) throws Exception { 197 PrivateKey privateKey = null; 198 PublicKey publicKey = null; 199 200 if (ks.containsAlias(keyAlias)) { 201 System.out.println("Loaded entry: " + keyAlias); 202 privateKey = (PrivateKey)ks.getKey(keyAlias, null); 203 publicKey = (PublicKey)ks.getCertificate(keyAlias).getPublicKey(); 204 205 int privateKeySize = KeyUtil.getKeySize(privateKey); 206 if (privateKeySize != keySize) { 207 throw new Exception("Expected key size is " + keySize + 208 ", but the private key size is " + privateKeySize); 209 } 210 211 int publicKeySize = KeyUtil.getKeySize(publicKey); 212 if (publicKeySize != keySize) { 213 throw new Exception("Expected key size is " + keySize + 214 ", but the public key size is " + publicKeySize); 215 } 216 } 217 } 218 219 /* 220 * ============================================================= 221 * The remainder is just support stuff 222 */ 223 224 // use any free port by default 225 volatile int serverPort = 0; 226 227 volatile Exception serverException = null; 228 volatile Exception clientException = null; 229 230 private static String keyAlias; 231 private static int keySize; 232 private static String clientProtocol = null; 233 private static String clientCiperSuite = null; 234 main(String[] args)235 public static void main(String[] args) throws Exception { 236 if (debug) { 237 System.setProperty("javax.net.debug", "all"); 238 } 239 240 keyAlias = "7106773." + args[0]; 241 keySize = Integer.parseInt(args[0]); 242 243 KeyStore ks = KeyStore.getInstance("Windows-MY"); 244 ks.load(null, null); 245 if (ks.containsAlias(keyAlias)) { 246 ks.deleteEntry(keyAlias); 247 } 248 249 CertAndKeyGen gen = new CertAndKeyGen("RSA", "SHA256withRSA"); 250 gen.generate(keySize); 251 252 ks.setKeyEntry(keyAlias, gen.getPrivateKey(), null, 253 new Certificate[] { 254 gen.getSelfCertificate(new X500Name("cn=localhost,c=US"), 100) 255 }); 256 257 clientProtocol = "TLSv1.2"; 258 clientCiperSuite = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; 259 260 try { 261 new ShortRSAKeyWithinTLS(); 262 } finally { 263 ks.deleteEntry(keyAlias); 264 ks.store(null, null); 265 } 266 } 267 268 Thread clientThread = null; 269 Thread serverThread = null; 270 KeyStore serverKS; 271 MyExtendedX509TM serverTM; 272 273 /* 274 * Primary constructor, used to drive remainder of the test. 275 * 276 * Fork off the other side, then do your work. 277 */ ShortRSAKeyWithinTLS()278 ShortRSAKeyWithinTLS() throws Exception { 279 try { 280 if (separateServerThread) { 281 startServer(true); 282 startClient(false); 283 } else { 284 startClient(true); 285 startServer(false); 286 } 287 } catch (Exception e) { 288 // swallow for now. Show later 289 } 290 291 /* 292 * Wait for other side to close down. 293 */ 294 if (separateServerThread) { 295 serverThread.join(); 296 } else { 297 clientThread.join(); 298 } 299 300 /* 301 * When we get here, the test is pretty much over. 302 * Which side threw the error? 303 */ 304 Exception local; 305 Exception remote; 306 String whichRemote; 307 308 if (separateServerThread) { 309 remote = serverException; 310 local = clientException; 311 whichRemote = "server"; 312 } else { 313 remote = clientException; 314 local = serverException; 315 whichRemote = "client"; 316 } 317 318 /* 319 * If both failed, return the curthread's exception, but also 320 * print the remote side Exception 321 */ 322 if ((local != null) && (remote != null)) { 323 System.out.println(whichRemote + " also threw:"); 324 remote.printStackTrace(); 325 System.out.println(); 326 throw local; 327 } 328 329 if (remote != null) { 330 throw remote; 331 } 332 333 if (local != null) { 334 throw local; 335 } 336 } 337 startServer(boolean newThread)338 void startServer(boolean newThread) throws Exception { 339 if (newThread) { 340 serverThread = new Thread() { 341 public void run() { 342 try { 343 doServerSide(); 344 } catch (Exception e) { 345 /* 346 * Our server thread just died. 347 * 348 * Release the client, if not active already... 349 */ 350 System.err.println("Server died..."); 351 serverReady = true; 352 serverException = e; 353 } 354 } 355 }; 356 serverThread.start(); 357 } else { 358 try { 359 doServerSide(); 360 } catch (Exception e) { 361 serverException = e; 362 } finally { 363 serverReady = true; 364 } 365 } 366 } 367 startClient(boolean newThread)368 void startClient(boolean newThread) throws Exception { 369 if (newThread) { 370 clientThread = new Thread() { 371 public void run() { 372 try { 373 doClientSide(); 374 } catch (Exception e) { 375 /* 376 * Our client thread just died. 377 */ 378 System.err.println("Client died..."); 379 clientException = e; 380 } 381 } 382 }; 383 clientThread.start(); 384 } else { 385 try { 386 doClientSide(); 387 } catch (Exception e) { 388 clientException = e; 389 } 390 } 391 } 392 393 394 class MyExtendedX509TM extends X509ExtendedTrustManager 395 implements X509TrustManager { 396 397 X509TrustManager tm; 398 MyExtendedX509TM(X509TrustManager tm)399 MyExtendedX509TM(X509TrustManager tm) { 400 this.tm = tm; 401 } 402 checkClientTrusted(X509Certificate chain[], String authType)403 public void checkClientTrusted(X509Certificate chain[], String authType) 404 throws CertificateException { 405 tm.checkClientTrusted(chain, authType); 406 } 407 checkServerTrusted(X509Certificate chain[], String authType)408 public void checkServerTrusted(X509Certificate chain[], String authType) 409 throws CertificateException { 410 tm.checkServerTrusted(chain, authType); 411 } 412 getAcceptedIssuers()413 public X509Certificate[] getAcceptedIssuers() { 414 List<X509Certificate> certs = new ArrayList<>(); 415 try { 416 for (X509Certificate c : tm.getAcceptedIssuers()) { 417 if (serverKS.getCertificateAlias(c).equals(keyAlias)) 418 certs.add(c); 419 } 420 } catch (KeyStoreException kse) { 421 throw new RuntimeException(kse); 422 } 423 return certs.toArray(new X509Certificate[certs.size()]); 424 } 425 checkClientTrusted(X509Certificate[] chain, String authType, Socket socket)426 public void checkClientTrusted(X509Certificate[] chain, String authType, 427 Socket socket) throws CertificateException { 428 tm.checkClientTrusted(chain, authType); 429 } 430 checkServerTrusted(X509Certificate[] chain, String authType, Socket socket)431 public void checkServerTrusted(X509Certificate[] chain, String authType, 432 Socket socket) throws CertificateException { 433 tm.checkServerTrusted(chain, authType); 434 } 435 checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine)436 public void checkClientTrusted(X509Certificate[] chain, String authType, 437 SSLEngine engine) throws CertificateException { 438 tm.checkClientTrusted(chain, authType); 439 } 440 checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine)441 public void checkServerTrusted(X509Certificate[] chain, String authType, 442 SSLEngine engine) throws CertificateException { 443 tm.checkServerTrusted(chain, authType); 444 } 445 } 446 447 } 448 449