1 /* 2 * Copyright (c) 2009, 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 // SunJSSE does not support dynamic system properties, no way to re-use 26 // system properties in samevm/agentvm mode. 27 // 28 29 /* 30 * @test 31 * @bug 6822460 32 * @summary support self-issued certificate 33 * @run main/othervm SelfIssuedCert PKIX 34 * @run main/othervm SelfIssuedCert SunX509 35 * @author Xuelei Fan 36 */ 37 38 import java.net.*; 39 import java.util.*; 40 import java.io.*; 41 import javax.net.ssl.*; 42 import java.security.Security; 43 import java.security.KeyStore; 44 import java.security.KeyFactory; 45 import java.security.cert.Certificate; 46 import java.security.cert.CertificateFactory; 47 import java.security.spec.*; 48 import java.security.interfaces.*; 49 import java.math.BigInteger; 50 51 import java.util.Base64; 52 53 public class SelfIssuedCert { 54 55 /* 56 * ============================================================= 57 * Set the various variables needed for the tests, then 58 * specify what tests to run on each side. 59 */ 60 61 /* 62 * Should we run the client or server in a separate thread? 63 * Both sides can throw exceptions, but do you have a preference 64 * as to which side should be the main thread. 65 */ 66 static boolean separateServerThread = true; 67 68 /* 69 * Where do we find the keystores? 70 */ 71 // Certificate information: 72 // Issuer: C=US, O=Example, CN=localhost 73 // Validity 74 // Not Before: May 25 00:35:58 2009 GMT 75 // Not After : May 5 00:35:58 2030 GMT 76 // Subject: C=US, O=Example, CN=localhost 77 // X509v3 Subject Key Identifier: 78 // 56:AB:FE:15:4C:9C:4A:70:90:DC:0B:9B:EB:BE:DC:03:CC:7F:CE:CF 79 // X509v3 Authority Key Identifier: 80 // keyid:56:AB:FE:15:4C:9C:4A:70:90:DC:0B:9B:EB:BE:DC:03:CC:7F:CE:CF 81 // DirName:/C=US/O=Example/CN=localhost 82 // serial:00 83 static String trusedCertStr = 84 "-----BEGIN CERTIFICATE-----\n" + 85 "MIICejCCAeOgAwIBAgIBADANBgkqhkiG9w0BAQQFADAzMQswCQYDVQQGEwJVUzEQ\n" + 86 "MA4GA1UEChMHRXhhbXBsZTESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTA5MDUyNTAw\n" + 87 "MDQ0M1oXDTMwMDUwNTAwMDQ0M1owMzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4\n" + 88 "YW1wbGUxEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw\n" + 89 "gYkCgYEA0Wvh3FHYGQ3vvw59yTjUxT6QuY0fzwCGQTM9evXr/V9+pjWmaTkNDW+7\n" + 90 "S/LErlWz64gOWTgcMZN162sVgx4ct/q27brY+SlUO5eSud1fSac6SfefhOPBa965\n" + 91 "Xc4mnpDt5sgQPMDCuFK7Le6A+/S9J42BO2WYmNcmvcwWWrv+ehcCAwEAAaOBnTCB\n" + 92 "mjAdBgNVHQ4EFgQUq3q5fYEibdvLpab+JY4pmifj2vYwWwYDVR0jBFQwUoAUq3q5\n" + 93 "fYEibdvLpab+JY4pmifj2vahN6Q1MDMxCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdF\n" + 94 "eGFtcGxlMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAwDwYDVR0TAQH/BAUwAwEB/zAL\n" + 95 "BgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEEBQADgYEAHL8BSwtX6s8WPPG2FbQBX+K8\n" + 96 "GquAyQNtgfJNm60B4i+fVBkJiQJtLmE0emvHx/3sIaHmB0Gd0HKnk/cIQXY304vr\n" + 97 "QpqwudKcIZuzmj+pa7807joV+WzRDVIlt4HpYg7tiUvEoyw+X8jwY2lgiGR7mWu6\n" + 98 "jQU8PN/06+qgtvSGFpo=\n" + 99 "-----END CERTIFICATE-----"; 100 101 // Certificate information: 102 // Issuer: C=US, O=Example, CN=localhost 103 // Validity 104 // Not Before: May 25 00:35:58 2009 GMT 105 // Not After : May 5 00:35:58 2030 GMT 106 // Subject: C=US, O=Example, CN=localhost 107 // X509v3 Subject Key Identifier: 108 // 0D:30:76:22:D6:9D:75:EF:FD:83:50:31:18:08:83:CD:01:4E:6A:C4 109 // X509v3 Authority Key Identifier: 110 // keyid:56:AB:FE:15:4C:9C:4A:70:90:DC:0B:9B:EB:BE:DC:03:CC:7F:CE:CF 111 // DirName:/C=US/O=Example/CN=localhost 112 // serial:00 113 static String targetCertStr = 114 "-----BEGIN CERTIFICATE-----\n" + 115 "MIICaTCCAdKgAwIBAgIBAjANBgkqhkiG9w0BAQQFADAzMQswCQYDVQQGEwJVUzEQ\n" + 116 "MA4GA1UEChMHRXhhbXBsZTESMBAGA1UEAxMJbG9jYWxob3N0MB4XDTA5MDUyNTAw\n" + 117 "MDQ0M1oXDTI5MDIwOTAwMDQ0M1owMzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4\n" + 118 "YW1wbGUxEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw\n" + 119 "gYkCgYEAzmPahrH9LTQv3HEWsua+hIpzyU1ACooSd5BtDjc7XnVzSdGW8QD9R8EA\n" + 120 "xko7TvfJo6IH6wwgHBspySwsl+6xvHhbwQjgtWlT71ksrUbqcUzmvSvcycQYA8RC\n" + 121 "yk9HK5pEJQgSxldpR3Kmy0V6CHC4dCm15trnJYWisTuezY3fjXECAwEAAaOBjDCB\n" + 122 "iTAdBgNVHQ4EFgQUQkiWFRkjKsfwFo7UMQfGEzNNW60wWwYDVR0jBFQwUoAUq3q5\n" + 123 "fYEibdvLpab+JY4pmifj2vahN6Q1MDMxCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdF\n" + 124 "eGFtcGxlMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAwCwYDVR0PBAQDAgPoMA0GCSqG\n" + 125 "SIb3DQEBBAUAA4GBAIMz7c1R+6KEO7FmH4rnv9XE62xkg03ff0vKXLZMjjs0CX2z\n" + 126 "ybRttuTFafHA6/JS+Wz0G83FCRVeiw2WPU6BweMwwejzzIrQ/K6mbp6w6sRFcbNa\n" + 127 "eLBtzkjEtI/htOSSq3/0mbKmWn5uVJckO4QiB8kUR4F7ngM9l1uuI46ZfUsk\n" + 128 "-----END CERTIFICATE-----"; 129 130 // Private key in the format of PKCS#8 131 static String targetPrivateKey = 132 "MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAM5j2oax/S00L9xx\n" + 133 "FrLmvoSKc8lNQAqKEneQbQ43O151c0nRlvEA/UfBAMZKO073yaOiB+sMIBwbKcks\n" + 134 "LJfusbx4W8EI4LVpU+9ZLK1G6nFM5r0r3MnEGAPEQspPRyuaRCUIEsZXaUdypstF\n" + 135 "eghwuHQpteba5yWForE7ns2N341xAgMBAAECgYEAgZ8k98OBhopoJMLBxso0jXmH\n" + 136 "Dr59oiDlSEJku7DkkIajSZFggyxj5lTI78BfT1FASozQ/EY5RG2q6LXdq+41oU/U\n" + 137 "JVEQWhdIE1mQDwE0vgaYdjzMaVIsC3cZYOCOmCYvNxCiTt7e/z8yBMmAE5udqJMB\n" + 138 "pim4WXDfpy0ssK81oCECQQDwMC4xu+kn0yD/Qyi9Zn26gIRDv4bjzDQoJfSvMhrY\n" + 139 "a4duxLzh9u4gCDd0+wHxpPQvNxGCk0c1JUxBJ2rb4G3HAkEA2/oVRV6+xiRXUnoo\n" + 140 "bdPEO27zEJmdpE42yU/JLIy6DPu2IUhEqY45fU2ZERmwMdhpiK/vsf/CZKJ2j/ZU\n" + 141 "PdMLBwJBAJIYTFDWAqjFpCGAASzLRZiGiW0H941h7Suqgp159ZhEN5mps1Yis47q\n" + 142 "UIkoEHOiKSD69vychsiNykcrKbVaWosCQQC1UrYX4Vo1r5z/EkyjAwzcxL68rzM/\n" + 143 "TW1hkU/NVg7CRvXBB3X5oY+H1t/WNauD2tRa5FMbESwmkbhTQIP+FikfAkEA4goD\n" + 144 "HCxUn0Z1OQq9QL6y1Yoof6sHxicUwABosuCLJnDJmA5vhpemvdXQTzFII8g1hyQf\n" + 145 "z1yyDoxhddcleKlJvQ=="; 146 147 static char passphrase[] = "passphrase".toCharArray(); 148 149 /* 150 * Is the server ready to serve? 151 */ 152 volatile static boolean serverReady = false; 153 154 /* 155 * Turn on SSL debugging? 156 */ 157 static boolean debug = false; 158 159 /* 160 * Define the server side of the test. 161 * 162 * If the server prematurely exits, serverReady will be set to true 163 * to avoid infinite hangs. 164 */ 165 void doServerSide() throws Exception { 166 SSLContext context = getSSLContext(null, targetCertStr, 167 targetPrivateKey); 168 SSLServerSocketFactory sslssf = context.getServerSocketFactory(); 169 170 SSLServerSocket sslServerSocket = 171 (SSLServerSocket)sslssf.createServerSocket(serverPort); 172 serverPort = sslServerSocket.getLocalPort(); 173 174 /* 175 * Signal Client, we're ready for his connect. 176 */ 177 serverReady = true; 178 179 SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); 180 sslSocket.setNeedClientAuth(false); 181 182 InputStream sslIS = sslSocket.getInputStream(); 183 OutputStream sslOS = sslSocket.getOutputStream(); 184 185 sslIS.read(); 186 sslOS.write(85); 187 sslOS.flush(); 188 189 sslSocket.close(); 190 191 } 192 193 /* 194 * Define the client side of the test. 195 * 196 * If the server prematurely exits, serverReady will be set to true 197 * to avoid infinite hangs. 198 */ 199 void doClientSide() throws Exception { 200 /* 201 * Wait for server to get started. 202 */ 203 while (!serverReady) { 204 Thread.sleep(50); 205 } 206 207 SSLContext context = getSSLContext(trusedCertStr, null, null); 208 SSLSocketFactory sslsf = context.getSocketFactory(); 209 210 SSLSocket sslSocket = 211 (SSLSocket)sslsf.createSocket("localhost", serverPort); 212 sslSocket.setEnabledProtocols(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2" }); 213 214 InputStream sslIS = sslSocket.getInputStream(); 215 OutputStream sslOS = sslSocket.getOutputStream(); 216 217 sslOS.write(280); 218 sslOS.flush(); 219 sslIS.read(); 220 221 sslSocket.close(); 222 } 223 224 // get the ssl context 225 private static SSLContext getSSLContext(String trusedCertStr, 226 String keyCertStr, String keySpecStr) throws Exception { 227 228 // generate certificate from cert string 229 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 230 231 // create a key store 232 KeyStore ks = KeyStore.getInstance("JKS"); 233 ks.load(null, null); 234 235 // import the trused cert 236 Certificate trusedCert = null; 237 ByteArrayInputStream is = null; 238 if (trusedCertStr != null) { 239 is = new ByteArrayInputStream(trusedCertStr.getBytes()); 240 trusedCert = cf.generateCertificate(is); 241 is.close(); 242 243 ks.setCertificateEntry("RSA Export Signer", trusedCert); 244 } 245 246 if (keyCertStr != null) { 247 // generate the private key. 248 PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( 249 Base64.getMimeDecoder().decode(keySpecStr)); 250 KeyFactory kf = KeyFactory.getInstance("RSA"); 251 RSAPrivateKey priKey = 252 (RSAPrivateKey)kf.generatePrivate(priKeySpec); 253 254 // generate certificate chain 255 is = new ByteArrayInputStream(keyCertStr.getBytes()); 256 Certificate keyCert = cf.generateCertificate(is); 257 is.close(); 258 259 Certificate[] chain = null; 260 if (trusedCert != null) { 261 chain = new Certificate[2]; 262 chain[0] = keyCert; 263 chain[1] = trusedCert; 264 } else { 265 chain = new Certificate[1]; 266 chain[0] = keyCert; 267 } 268 269 // import the key entry. 270 ks.setKeyEntry("Whatever", priKey, passphrase, chain); 271 } 272 273 // create SSL context 274 TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); 275 tmf.init(ks); 276 277 SSLContext ctx = SSLContext.getInstance("TLS"); 278 if (keyCertStr != null && !keyCertStr.isEmpty()) { 279 KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); 280 kmf.init(ks, passphrase); 281 282 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 283 ks = null; 284 } else { 285 ctx.init(null, tmf.getTrustManagers(), null); 286 } 287 288 return ctx; 289 } 290 291 private static String tmAlgorithm; // trust manager 292 293 private static void parseArguments(String[] args) { 294 tmAlgorithm = args[0]; 295 } 296 297 /* 298 * ============================================================= 299 * The remainder is just support stuff 300 */ 301 302 // use any free port by default 303 volatile int serverPort = 0; 304 305 volatile Exception serverException = null; 306 volatile Exception clientException = null; 307 308 public static void main(String args[]) throws Exception { 309 // MD5 is used in this test case, don't disable MD5 algorithm. 310 Security.setProperty("jdk.certpath.disabledAlgorithms", 311 "MD2, RSA keySize < 1024"); 312 Security.setProperty("jdk.tls.disabledAlgorithms", 313 "SSLv3, RC4, DH keySize < 768"); 314 315 if (debug) 316 System.setProperty("javax.net.debug", "all"); 317 318 319 /* 320 * Get the customized arguments. 321 */ 322 parseArguments(args); 323 324 /* 325 * Start the tests. 326 */ 327 new SelfIssuedCert(); 328 } 329 330 Thread clientThread = null; 331 Thread serverThread = null; 332 /* 333 * Primary constructor, used to drive remainder of the test. 334 * 335 * Fork off the other side, then do your work. 336 */ 337 SelfIssuedCert() throws Exception { 338 if (separateServerThread) { 339 startServer(true); 340 startClient(false); 341 } else { 342 startClient(true); 343 startServer(false); 344 } 345 346 /* 347 * Wait for other side to close down. 348 */ 349 if (separateServerThread) { 350 serverThread.join(); 351 } else { 352 clientThread.join(); 353 } 354 355 /* 356 * When we get here, the test is pretty much over. 357 * 358 * If the main thread excepted, that propagates back 359 * immediately. If the other thread threw an exception, we 360 * should report back. 361 */ 362 if (serverException != null) 363 throw serverException; 364 if (clientException != null) 365 throw clientException; 366 } 367 368 void startServer(boolean newThread) throws Exception { 369 if (newThread) { 370 serverThread = new Thread() { 371 public void run() { 372 try { 373 doServerSide(); 374 } catch (Exception e) { 375 /* 376 * Our server thread just died. 377 * 378 * Release the client, if not active already... 379 */ 380 System.err.println("Server died..."); 381 serverReady = true; 382 serverException = e; 383 } 384 } 385 }; 386 serverThread.start(); 387 } else { 388 doServerSide(); 389 } 390 } 391 392 void startClient(boolean newThread) throws Exception { 393 if (newThread) { 394 clientThread = new Thread() { 395 public void run() { 396 try { 397 doClientSide(); 398 } catch (Exception e) { 399 /* 400 * Our client thread just died. 401 */ 402 System.err.println("Client died..."); 403 clientException = e; 404 } 405 } 406 }; 407 clientThread.start(); 408 } else { 409 doClientSide(); 410 } 411 } 412 413 }