1 /* 2 * Copyright (c) 2011, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 // 27 // SunJSSE does not support dynamic system properties, no way to re-use 28 // system properties in samevm/agentvm mode. 29 // 30 31 /* 32 * @test 33 * @bug 7113275 8164846 34 * @summary compatibility issue with MD2 trust anchor and old X509TrustManager 35 * @library /javax/net/ssl/templates 36 * @run main/othervm TrustTrustedCert PKIX TLSv1.1 true 37 * @run main/othervm TrustTrustedCert PKIX TLSv1.1 false 38 * @run main/othervm TrustTrustedCert SunX509 TLSv1.1 false 39 * @run main/othervm TrustTrustedCert PKIX TLSv1.2 false 40 * @run main/othervm TrustTrustedCert SunX509 TLSv1.2 false 41 */ 42 43 import java.net.*; 44 import java.io.*; 45 import javax.net.ssl.*; 46 import java.security.*; 47 import java.security.cert.*; 48 import java.security.spec.*; 49 import java.security.interfaces.*; 50 import java.util.Base64; 51 52 public class TrustTrustedCert extends SSLSocketTemplate { 53 54 /* 55 * Certificates and key used in the test. 56 */ 57 58 // It's a trust anchor signed with MD2 hash function. 59 static String trustedCertStr = 60 "-----BEGIN CERTIFICATE-----\n" + 61 "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQIFADA7MQswCQYDVQQGEwJVUzEN\n" + 62 "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + 63 "MTExMTE4MTExNDA0WhcNMzIxMDI4MTExNDA0WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + 64 "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + 65 "KoZIhvcNAQEBBQADgY0AMIGJAoGBAPGyB9tugUGgxtdeqe0qJEwf9x1Gy4BOi1yR\n" + 66 "wzDZY4H5LquvIfQ2V3J9X1MQENVsFvkvp65ZcFcy+ObOucXUUPFcd/iw2DVb5QXA\n" + 67 "ffyeVqWD56GPi8Qe37wrJO3L6fBhN9oxp/BbdRLgjU81zx8qLEyPODhPMxV4OkcA\n" + 68 "SDwZTSxxAgMBAAGjgaUwgaIwHQYDVR0OBBYEFLOAtr/YrYj9H04EDLA0fd14jisF\n" + 69 "MGMGA1UdIwRcMFqAFLOAtr/YrYj9H04EDLA0fd14jisFoT+kPTA7MQswCQYDVQQG\n" + 70 "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + 71 "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEC\n" + 72 "BQADgYEAr8ExpXu/FTIRiMzPm0ubqwME4lniilwQUiEOD/4DbksNjEIcUyS2hIk1\n" + 73 "qsmjJz3SHBnwhxl9dhJVwk2tZLkPGW86Zn0TPVRsttK4inTgCC9GFGeqQBdrU/uf\n" + 74 "lipBzXWljrfbg4N/kK8m2LabtKUMMnGysM8rN0Fx2PYm5xxGvtM=\n" + 75 "-----END CERTIFICATE-----"; 76 77 // The certificate issued by above trust anchor, signed with MD5 78 static String targetCertStr = 79 "-----BEGIN CERTIFICATE-----\n" + 80 "MIICeDCCAeGgAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + 81 "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + 82 "MTExMTE4MTExNDA2WhcNMzEwODA1MTExNDA2WjBPMQswCQYDVQQGEwJVUzENMAsG\n" + 83 "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxEjAQBgNV\n" + 84 "BAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwDnm96mw\n" + 85 "fXCH4bgXk1US0VcJsQVxUtGMyncAveMuzBzNzOmKZPeqyYX1Fuh4q+cuza03WTJd\n" + 86 "G9nOkNr364e3Rn1aaHjCMcBmFflObnGnhhufNmIGYogJ9dJPmhUVPEVAXrMG+Ces\n" + 87 "NKy2E8woGnLMrqu6yiuTClbLBPK8fWzTXrECAwEAAaN4MHYwCwYDVR0PBAQDAgPo\n" + 88 "MB0GA1UdDgQWBBSdRrpocLPJXyGfDmMWJrcEf29WGDAfBgNVHSMEGDAWgBSzgLa/\n" + 89 "2K2I/R9OBAywNH3deI4rBTAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" + 90 "CCsGAQUFBwMDMA0GCSqGSIb3DQEBBAUAA4GBAKJ71ZiCUykkJrCLYUxlFlhvUcr9\n" + 91 "sTcOc67QdroW5f412NI15SXWDiley/JOasIiuIFPjaJBjOKoHOvTjG/snVu9wEgq\n" + 92 "YNR8dPsO+NM8r79C6jO+Jx5fYAC7os2XxS75h3NX0ElJcbwIXGBJ6xRrsFh/BGYH\n" + 93 "yvudOlX4BkVR0l1K\n" + 94 "-----END CERTIFICATE-----"; 95 96 // Private key in the format of PKCS#8. 97 static String targetPrivateKey = 98 "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMA55vepsH1wh+G4\n" + 99 "F5NVEtFXCbEFcVLRjMp3AL3jLswczczpimT3qsmF9RboeKvnLs2tN1kyXRvZzpDa\n" + 100 "9+uHt0Z9Wmh4wjHAZhX5Tm5xp4YbnzZiBmKICfXST5oVFTxFQF6zBvgnrDSsthPM\n" + 101 "KBpyzK6rusorkwpWywTyvH1s016xAgMBAAECgYEAn9bF3oRkdDoBU0i/mcww5I+K\n" + 102 "SH9tFt+WQbiojjz9ac49trkvUfu7MO1Jui2+QbrvaSkyj+HYGFOJd1wMsPXeB7ck\n" + 103 "5mOIYV4uZK8jfNMSQ8v0tFEeIPp5lKdw1XnrQfSe+abo2eL5Lwso437Y4s3w37+H\n" + 104 "aY3d76hR5qly+Ys+Ww0CQQDjeOoX89d/xhRqGXKjCx8ImE/dPmsI8O27cwtKrDYJ\n" + 105 "6t0v/xryVIdvOYcRBvKnqEogOH7T1kI+LnWKUTJ2ehJ7AkEA2FVloPVqCehXcc7e\n" + 106 "z3TDpU9w1B0JXklcV5HddYsRqp9RukN/VK4szKE7F1yoarIUtfE9Lr9082Jwyp3M\n" + 107 "L11xwwJBAKsZ+Hur3x0tUY29No2Nf/pnFyvEF57SGwA0uPmiL8Ol9lpz+UDudDEl\n" + 108 "hIM6Rqv12kwCMuQE9i7vo1o3WU3k5KECQEqhg1L49yD935TqiiFFpe0Ur9btQXse\n" + 109 "kdXAA4d2d5zGI7q/aGD9SYU6phkUJSHR16VA2RuUfzMrpb+wmm1IrmMCQFtLoKRT\n" + 110 "A5kokFb+E3Gplu29tJvCUpfwgBFRS+wmkvtiaU/tiyDcVgDO+An5DwedxxdVzqiE\n" + 111 "njWHoKY3axDQ8OU=\n"; 112 113 static char passphrase[] = "passphrase".toCharArray(); 114 115 @Override 116 protected SSLContext createServerSSLContext() throws Exception { 117 return generateSSLContext(); 118 } 119 120 @Override 121 protected void configureServerSocket(SSLServerSocket socket) { 122 socket.setNeedClientAuth(true); 123 } 124 125 @Override 126 protected void runServerApplication(SSLSocket socket) throws Exception { 127 InputStream sslIS = socket.getInputStream(); 128 OutputStream sslOS = socket.getOutputStream(); 129 130 try { 131 sslIS.read(); 132 sslOS.write('A'); 133 sslOS.flush(); 134 } catch (SSLException ssle) { 135 if (!expectFail) { 136 throw ssle; 137 } // Otherwise, ignore. 138 } 139 } 140 141 @Override 142 protected SSLContext createClientSSLContext() throws Exception { 143 return generateSSLContext(); 144 } 145 146 @Override 147 protected void runClientApplication(SSLSocket socket) throws Exception { 148 // enable the specified TLS protocol 149 socket.setEnabledProtocols(new String[] { tlsProtocol }); 150 151 InputStream sslIS = socket.getInputStream(); 152 OutputStream sslOS = socket.getOutputStream(); 153 154 try { 155 sslOS.write('B'); 156 sslOS.flush(); 157 sslIS.read(); 158 } catch (SSLHandshakeException e) { 159 if (expectFail) { 160 // focus on the CertPathValidatorException 161 Throwable t = e.getCause().getCause(); 162 if (t == null || !t.toString().contains("MD5withRSA")) { 163 throw new RuntimeException( 164 "Expected to see MD5withRSA in exception output", t); 165 } 166 } else { 167 throw e; 168 } 169 } 170 } 171 172 /* 173 * ============================================================= 174 * The remainder is just support stuff 175 */ 176 private static String tmAlgorithm; // trust manager 177 private static String tlsProtocol; // trust manager 178 // set this flag to test context of CertificateException 179 private static boolean expectFail; 180 181 private static void parseArguments(String[] args) { 182 tmAlgorithm = args[0]; 183 tlsProtocol = args[1]; 184 expectFail = Boolean.parseBoolean(args[2]); 185 } 186 187 private static SSLContext generateSSLContext() throws Exception { 188 189 // generate certificate from cert string 190 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 191 192 // create a key store 193 KeyStore ks = KeyStore.getInstance("JKS"); 194 ks.load(null, null); 195 196 // import the trused cert 197 X509Certificate trusedCert = null; 198 ByteArrayInputStream is = 199 new ByteArrayInputStream(trustedCertStr.getBytes()); 200 trusedCert = (X509Certificate)cf.generateCertificate(is); 201 is.close(); 202 203 ks.setCertificateEntry("Trusted RSA Signer", trusedCert); 204 205 // generate the private key. 206 PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( 207 Base64.getMimeDecoder().decode(targetPrivateKey)); 208 KeyFactory kf = KeyFactory.getInstance("RSA"); 209 RSAPrivateKey priKey = 210 (RSAPrivateKey)kf.generatePrivate(priKeySpec); 211 212 // generate certificate chain 213 is = new ByteArrayInputStream(targetCertStr.getBytes()); 214 X509Certificate keyCert = (X509Certificate)cf.generateCertificate(is); 215 is.close(); 216 217 X509Certificate[] chain = new X509Certificate[2]; 218 chain[0] = keyCert; 219 chain[1] = trusedCert; 220 221 // import the key entry and the chain 222 ks.setKeyEntry("TheKey", priKey, passphrase, chain); 223 224 // create SSL context 225 TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); 226 tmf.init(ks); 227 228 // create the customized KM and TM 229 NoneExtendedX509TM myTM = 230 new NoneExtendedX509TM(tmf.getTrustManagers()[0]); 231 NoneExtendedX509KM myKM = 232 new NoneExtendedX509KM("TheKey", chain, priKey); 233 234 SSLContext ctx = SSLContext.getInstance(tlsProtocol); 235 // KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); 236 // kmf.init(ks, passphrase); 237 // ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 238 ctx.init(new KeyManager[]{myKM}, new TrustManager[]{myTM}, null); 239 ks = null; 240 241 return ctx; 242 } 243 244 static class NoneExtendedX509TM implements X509TrustManager { 245 X509TrustManager tm; 246 247 NoneExtendedX509TM(TrustManager tm) { 248 this.tm = (X509TrustManager)tm; 249 } 250 251 public void checkClientTrusted(X509Certificate chain[], String authType) 252 throws CertificateException { 253 tm.checkClientTrusted(chain, authType); 254 } 255 256 public void checkServerTrusted(X509Certificate chain[], String authType) 257 throws CertificateException { 258 tm.checkServerTrusted(chain, authType); 259 } 260 261 public X509Certificate[] getAcceptedIssuers() { 262 return tm.getAcceptedIssuers(); 263 } 264 } 265 266 static class NoneExtendedX509KM implements X509KeyManager { 267 private String keyAlias; 268 private X509Certificate[] chain; 269 private PrivateKey privateKey; 270 271 NoneExtendedX509KM(String keyAlias, X509Certificate[] chain, 272 PrivateKey privateKey) { 273 this.keyAlias = keyAlias; 274 this.chain = chain; 275 this.privateKey = privateKey; 276 } 277 278 public String[] getClientAliases(String keyType, Principal[] issuers) { 279 return new String[] {keyAlias}; 280 } 281 282 public String chooseClientAlias(String[] keyType, Principal[] issuers, 283 Socket socket) { 284 return keyAlias; 285 } 286 287 public String[] getServerAliases(String keyType, Principal[] issuers) { 288 return new String[] {keyAlias}; 289 } 290 291 public String chooseServerAlias(String keyType, Principal[] issuers, 292 Socket socket) { 293 return keyAlias; 294 } 295 296 public X509Certificate[] getCertificateChain(String alias) { 297 return chain; 298 } 299 300 public PrivateKey getPrivateKey(String alias) { 301 return privateKey; 302 } 303 } 304 305 public static void main(String[] args) throws Exception { 306 /* 307 * Get the customized arguments. 308 */ 309 parseArguments(args); 310 311 /* 312 * MD5 is used in this test case, don't disable MD5 algorithm. 313 * if expectFail is set, we're testing exception message 314 */ 315 if (!expectFail) { 316 Security.setProperty("jdk.certpath.disabledAlgorithms", 317 "MD2, RSA keySize < 1024"); 318 } 319 Security.setProperty("jdk.tls.disabledAlgorithms", 320 "SSLv3, RC4, DH keySize < 768"); 321 322 /* 323 * Start the tests. 324 */ 325 new TrustTrustedCert().run(); 326 } 327 }