1/* 2 * Copyright (c) 2010, 2016, 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 24import java.io.ByteArrayInputStream; 25import java.io.EOFException; 26import java.io.File; 27import java.io.FileInputStream; 28import java.io.FileNotFoundException; 29import java.io.IOException; 30import java.io.InputStream; 31import java.io.OutputStream; 32import java.net.Socket; 33import java.security.KeyFactory; 34import java.security.KeyStore; 35import java.security.KeyStoreException; 36import java.security.NoSuchAlgorithmException; 37import java.security.Principal; 38import java.security.PrivateKey; 39import java.security.SecureRandom; 40import java.security.UnrecoverableKeyException; 41import java.security.cert.Certificate; 42import java.security.cert.CertificateException; 43import java.security.cert.CertificateFactory; 44import java.security.cert.X509Certificate; 45import java.security.interfaces.RSAPrivateKey; 46import java.security.spec.InvalidKeySpecException; 47import java.security.spec.PKCS8EncodedKeySpec; 48import java.util.ArrayList; 49import java.util.Arrays; 50import java.util.Base64; 51import java.util.Collections; 52import java.util.List; 53import javax.net.ssl.KeyManagerFactory; 54import javax.net.ssl.SSLEngine; 55import javax.net.ssl.SSLServerSocket; 56import javax.net.ssl.SSLSocket; 57import javax.net.ssl.SSLSocketFactory; 58import javax.net.ssl.TrustManager; 59import javax.net.ssl.TrustManagerFactory; 60import javax.net.ssl.X509ExtendedKeyManager; 61import javax.net.ssl.X509TrustManager; 62 63/** 64 * Test that all ciphersuites work in all versions and all client authentication 65 * types. The way this is setup the server is stateless and all checking is done 66 * on the client side. 67 */ 68 69public class CipherTestUtils { 70 71 public static final int TIMEOUT = 20 * 1000; 72 public static final SecureRandom secureRandom = new SecureRandom(); 73 public static char[] PASSWORD = "passphrase".toCharArray(); 74 private static final List<TestParameters> TESTS = new ArrayList<>(3); 75 private static final List<Exception> EXCEPTIONS 76 = Collections.synchronizedList(new ArrayList<>(1)); 77 78 private static final String CLIENT_PUBLIC_KEY 79 = "-----BEGIN CERTIFICATE-----\n" 80 + "MIICtTCCAh4CCQDkYJ46DMcGRjANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMC\n" 81 + "VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MR8wHQYDVQQK\n" 82 + "DBZTdW4gTWljcm9zeXN0ZW1zLCBJbmMuMSYwJAYDVQQLDB1TdW4gTWljcm9zeXN0\n" 83 + "ZW1zIExhYm9yYXRvcmllczEfMB0GA1UEAwwWVGVzdCBDQSAoMTAyNCBiaXQgUlNB\n" 84 + "KTAeFw0wOTA0MjcwNDA0MDhaFw0xMzA2MDUwNDA0MDhaMIGgMQswCQYDVQQGEwJV\n" 85 + "UzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHzAdBgNVBAoM\n" 86 + "FlN1biBNaWNyb3N5c3RlbXMsIEluYy4xJjAkBgNVBAsMHVN1biBNaWNyb3N5c3Rl\n" 87 + "bXMgTGFib3JhdG9yaWVzMSMwIQYDVQQDDBpUZXN0IENsaWVudCAoMTAyNCBiaXQg\n" 88 + "UlNBKTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAm5rwjmhO7Nwd5GWs+KvQ\n" 89 + "UnDiqpRDvRriOUFdF0rCI2Op24C+iwUMDGxPsgP7VkUpOdJhw3c72aP0CAWcZ5dN\n" 90 + "UCW7WVDAxnogCahLCir1jjoGdEjiNGOy0L9sypsM9UvBzJN8uvXsxsTZX4Z88cKU\n" 91 + "G7RUvN8LQ88zDljk5zr3c2MCAwEAATANBgkqhkiG9w0BAQUFAAOBgQA7LUDrzHln\n" 92 + "EXuGmwZeeroACB6DVtkClMskF/Pj5GnTxoeNN9DggycX/eOeIDKRloHuMpBeZPJH\n" 93 + "NUwFu4LB6HBDeldQD9iRp8zD/fPakOdN+1Gk5hciIZZJ5hQmeCl7Va2Gr64vUqZG\n" 94 + "MkVU755t+7ByLgzWuhPhhsX9QCuPR5FjvQ==\n" 95 + "-----END CERTIFICATE-----"; 96 97 private static final String CLIENT_PRIVATE_KEY 98 = "-----BEGIN PRIVATE KEY-----\n" 99 + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJua8I5oTuzcHeRl\n" 100 + "rPir0FJw4qqUQ70a4jlBXRdKwiNjqduAvosFDAxsT7ID+1ZFKTnSYcN3O9mj9AgF\n" 101 + "nGeXTVAlu1lQwMZ6IAmoSwoq9Y46BnRI4jRjstC/bMqbDPVLwcyTfLr17MbE2V+G\n" 102 + "fPHClBu0VLzfC0PPMw5Y5Oc693NjAgMBAAECgYA5w73zj8Nk6J3sMNaShe3S/PcY\n" 103 + "TewLopRCnwI46FbDnnbq9pNFtnzvi7HWKuY983THc1M5peTA+b1Y0QRr7F4Vg4x9\n" 104 + "9UM0B/tZcIIcJJ3LS+9fXKCbYLQWq5F05JqeZu+i+QLmJFO5+2p7laeQ4oQfW7QE\n" 105 + "YR4u2mSaLe0SsqHvOQJBAMhgcye9C6pJO0eo2/VtRxAXI7zxNAIjHwKo1cva7bhu\n" 106 + "GdrMaEAJBAsMJ1GEk7/WDI+3KEbTjQdfIJuAvOR4FXUCQQDGzNn/tl2k93v/ugyM\n" 107 + "/tBhCKDipYDIbyJMoG2AOtOGmCsiGo5L7idO4OAcm/QiHBQMXjFIVgTUcH8MhGj4\n" 108 + "blJ3AkA5fUqsxRV6tuYWKkFpif/QgwMS65VDY7Y6+hvVECwSNSyf1PO4I54QWV1S\n" 109 + "ixok+RHDjgY1Q+77hXSCiQ4o8rcdAkBHvjfR+5sx5IpgUGElJPRIgFenU3j1XH3x\n" 110 + "T1gVFaWuhg3S4eiGaGzRH4BhcrqY8K8fg4Kfi0N08yA2gTZsqUujAkEAjuNPTuKx\n" 111 + "ti0LXI09kbGUqOpRMm1zW5TD6LFeEaUN6oxrSZI2YUvu7VyotAqsxX5O0u0f3VQw\n" 112 + "ySF0Q1oZ6qu7cg==\n" 113 + "-----END PRIVATE KEY-----"; 114 private static final String SERVER_PUBLIC_KEY 115 = "-----BEGIN CERTIFICATE-----\n" 116 + "MIICtTCCAh4CCQDkYJ46DMcGRTANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMC\n" 117 + "VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MR8wHQYDVQQK\n" 118 + "DBZTdW4gTWljcm9zeXN0ZW1zLCBJbmMuMSYwJAYDVQQLDB1TdW4gTWljcm9zeXN0\n" 119 + "ZW1zIExhYm9yYXRvcmllczEfMB0GA1UEAwwWVGVzdCBDQSAoMTAyNCBiaXQgUlNB\n" 120 + "KTAeFw0wOTA0MjcwNDA0MDhaFw0xMzA2MDUwNDA0MDhaMIGgMQswCQYDVQQGEwJV\n" 121 + "UzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHzAdBgNVBAoM\n" 122 + "FlN1biBNaWNyb3N5c3RlbXMsIEluYy4xJjAkBgNVBAsMHVN1biBNaWNyb3N5c3Rl\n" 123 + "bXMgTGFib3JhdG9yaWVzMSMwIQYDVQQDDBpUZXN0IFNlcnZlciAoMTAyNCBiaXQg\n" 124 + "UlNBKTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsHHeZ1O67yuxQKDSAOC\n" 125 + "Xm271ViwBrXkxe5cvhG8MCCem6Z3XeZ/m6c2ucRwLaQxnmG1m0G6/OYaUXTivjcG\n" 126 + "/K4bc1I+yjghAWQNLBtsOiP9w0LKibg3TSDehpeuuz/lmB5A4HMqQr8KkY4K7peD\n" 127 + "1QkJ2Dn3zhbwQ/0d8f5CCbkCAwEAATANBgkqhkiG9w0BAQUFAAOBgQBOd8XojEnu\n" 128 + "eTUHBwqfmnvRQvbICFDNbbL4KuX/JNPSy1WMGAEbNCTLZ+5yP69js8aUYqAk5vVf\n" 129 + "dWRLU3MDiEzW7zxE1ubuKWjVuyGbG8Me0G01Hw+evBcZqB64Fz3OFISVfQh7MqE/\n" 130 + "O0AeakRMH350FRLNl4o6KBSXmF/AADfqQQ==\n" 131 + "-----END CERTIFICATE-----"; 132 133 private static final String SERVER_PRIVATE_KEY 134 = "-----BEGIN PRIVATE KEY-----\n" 135 + "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAK7Bx3mdTuu8rsUC\n" 136 + "g0gDgl5tu9VYsAa15MXuXL4RvDAgnpumd13mf5unNrnEcC2kMZ5htZtBuvzmGlF0\n" 137 + "4r43BvyuG3NSPso4IQFkDSwbbDoj/cNCyom4N00g3oaXrrs/5ZgeQOBzKkK/CpGO\n" 138 + "Cu6Xg9UJCdg5984W8EP9HfH+Qgm5AgMBAAECgYAXUv+3qJo+9mjxHHu/IdDFn6nB\n" 139 + "ONwNmTtWe5DfQWi3l7LznU0zOC9x6+hu9NvwC4kf1XSyqxw04tVCZ/JXZurEmEBz\n" 140 + "YtcQ5idRQDkKYXEDOeVUfvtHO6xilzrhPKxxd0GG/sei2pozikkqnYF3OcP0qL+a\n" 141 + "3nWixZQBRoF2nIRLcQJBAN97TJBr0XTRmE7OCKLUy1+ws7vZB9uQ2efHMsgwOpsY\n" 142 + "3cEW5qd95hrxLU72sBeu9loHQgBrT2Q3OAxnsPXmgO0CQQDIL3u9kS/O3Ukx+n1H\n" 143 + "JdPFQCRxrDm/vtJpQEmq+mLqxxnxCFRIYQ2ieAPokBxWeMDtdWJGD3VxhahjPfZm\n" 144 + "5K59AkEAuDVl0tVMfUIWjT5/F9jXGjUIsZofQ/iN5OLpFOHMLPO+Nd6umPjJpwON\n" 145 + "GT11wM/S+DprSPUrJ6vsYy1FTCuHsQJBAMXtnO07xgdE6AAQaRmVnyMiXmY+IQMj\n" 146 + "CyuhsrToyDDWFyIoWB0QSMjg3QxuoHYnAqpGK5qV4ksSGgG13BCz/okCQQCRHTgn\n" 147 + "DuFG2f7GYLFjI4NaTEzHGp+J9LiNYY1kYYLonpwAC3Z5hzJVanYT3/g23AUZ/fdF\n" 148 + "v5PDIViuPo5ZB1eD\n" 149 + "-----END PRIVATE KEY-----"; 150 151 private static final String CA_PUBLIC_KEY 152 = "-----BEGIN CERTIFICATE-----\n" 153 + "MIIDCDCCAnGgAwIBAgIJAIYlGfwNBY6NMA0GCSqGSIb3DQEBBQUAMIGcMQswCQYD\n" 154 + "VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHzAd\n" 155 + "BgNVBAoMFlN1biBNaWNyb3N5c3RlbXMsIEluYy4xJjAkBgNVBAsMHVN1biBNaWNy\n" 156 + "b3N5c3RlbXMgTGFib3JhdG9yaWVzMR8wHQYDVQQDDBZUZXN0IENBICgxMDI0IGJp\n" 157 + "dCBSU0EpMB4XDTA5MDQyNzA0MDQwOFoXDTEzMDYwNTA0MDQwOFowgZwxCzAJBgNV\n" 158 + "BAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEfMB0G\n" 159 + "A1UECgwWU3VuIE1pY3Jvc3lzdGVtcywgSW5jLjEmMCQGA1UECwwdU3VuIE1pY3Jv\n" 160 + "c3lzdGVtcyBMYWJvcmF0b3JpZXMxHzAdBgNVBAMMFlRlc3QgQ0EgKDEwMjQgYml0\n" 161 + "IFJTQSkwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOK4DJxxb0XX6MJ1CVjp\n" 162 + "9Gmr/Ua8MS12R58F9lDpSKuq8cFexA4W7OdZ4jtbKv0tRHX5YxmbnXedwS+gdcOA\n" 163 + "GRgXMoeXlgTFGpdL+TR8xKIlMGRSjnR7MpR2tRyIYI2p+UTEiD6LTlIm5Wh4z1q8\n" 164 + "LYbxyMVD1XNNNymvPM44OjsBAgMBAAGjUDBOMB0GA1UdDgQWBBT27BLUflmfdtbi\n" 165 + "WTgjwWnoxop2MTAfBgNVHSMEGDAWgBT27BLUflmfdtbiWTgjwWnoxop2MTAMBgNV\n" 166 + "HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAEQELNzhZpjnSgigd+QJ6I/3CPDo\n" 167 + "SDkMLdP1BHlT/DkMIZvABm+M09ePNlWiLYCNCsL9nWmX0gw0rFDKsTklZyKTUzaM\n" 168 + "oy/AZCrAaoIc6SO5m1xE1RMyVxd/Y/kg6cbfWxxCJFlMeU5rsSdC97HTE/lDyuoh\n" 169 + "BmlOBB7SdR+1ScjA\n" 170 + "-----END CERTIFICATE-----"; 171 172 private static final String CA_PRIVATE_KEY 173 = "-----BEGIN PRIVATE KEY-----\n" 174 + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOK4DJxxb0XX6MJ1\n" 175 + "CVjp9Gmr/Ua8MS12R58F9lDpSKuq8cFexA4W7OdZ4jtbKv0tRHX5YxmbnXedwS+g\n" 176 + "dcOAGRgXMoeXlgTFGpdL+TR8xKIlMGRSjnR7MpR2tRyIYI2p+UTEiD6LTlIm5Wh4\n" 177 + "z1q8LYbxyMVD1XNNNymvPM44OjsBAgMBAAECgYEApmMOlk3FrQtsvjGof4GLp3Xa\n" 178 + "tmvs54FzxKhagj0C4UHelNyYpAJ9MLjNiGQ7I31yTeaNrUCAi0XSfsKTSrwbLSnJ\n" 179 + "qsUPKMBrnzcWrOyui2+cupHZXaTlNeYB97teLJYpa6Ql9CZLoTHoim1+//s7diBh\n" 180 + "03Vls+M6Poi5PMvv59UCQQD+k/BiokmbBgWHfBY5cZSlx3Z4VTwSHJmHDTO3Tjso\n" 181 + "EVErXUSVvqD/KHX6eM4VPM8lySV5djWV8lDsESCWMtiLAkEA4/xFNsiOLMQpxW/O\n" 182 + "bt2tukxJkAxldD4lPoFZR+zbXtMtt8OjERtX2wD+nj6h7jfIeSyVuBEcBN8Uj8xe\n" 183 + "kgfgIwJAPbKG4LCqHAsCjgpRrIxNVTwZByLJEy6hOqzFathn19cSj+rjs1Lm28/n\n" 184 + "f9OFRnpdTbAJB/3REM0QNZYVCrG57wJBAN0KuTytZJNouaswhPCew5Kt5mDgc/kp\n" 185 + "S8j3dk2zCto8W8Ygy1iJrzuqEjPxO+UQdrFtlde51vWuKGxnVIW3VwsCQEldqk7r\n" 186 + "8y7PgquPP+k3L0OXno5wGBrPcW1+U0mhIZGnwSzE4SPX2ddqUSEUA/Av4RjAckL/\n" 187 + "fpqmCkpTanyYW9U=\n" 188 + "-----END PRIVATE KEY-----"; 189 190 private final SSLSocketFactory factory; 191 private final X509ExtendedKeyManager clientKeyManager; 192 private final X509ExtendedKeyManager serverKeyManager; 193 private final X509TrustManager clientTrustManager; 194 private final X509TrustManager serverTrustManager; 195 196 static abstract class Server implements Runnable, AutoCloseable { 197 198 final CipherTestUtils cipherTest; 199 200 Server(CipherTestUtils cipherTest) throws Exception { 201 this.cipherTest = cipherTest; 202 } 203 204 @Override 205 public abstract void run(); 206 207 abstract int getPort(); 208 209 void handleRequest(InputStream in, OutputStream out) 210 throws IOException { 211 boolean newline = false; 212 StringBuilder sb = new StringBuilder(); 213 while (true) { 214 int ch = in.read(); 215 if (ch < 0) { 216 throw new EOFException(); 217 } 218 sb.append((char) ch); 219 if (ch == '\r') { 220 // empty 221 } else if (ch == '\n') { 222 if (newline) { 223 // 2nd newline in a row, end of request 224 break; 225 } 226 newline = true; 227 } else { 228 newline = false; 229 } 230 } 231 String request = sb.toString(); 232 if (request.startsWith("GET / HTTP/1.") == false) { 233 throw new IOException("Invalid request: " + request); 234 } 235 out.write("HTTP/1.0 200 OK\r\n\r\n".getBytes()); 236 out.write("Tested Scenario: ".getBytes()); 237 TestParameters tp = (TestParameters) CipherTestUtils.TESTS.get(0); 238 out.write(tp.toString().getBytes()); 239 out.write(" Test PASSED.".getBytes()); 240 } 241 } 242 243 public static class TestParameters { 244 245 final String cipherSuite; 246 final String protocol; 247 final String clientAuth; 248 249 TestParameters(String cipherSuite, String protocol, String clientAuth) { 250 this.cipherSuite = cipherSuite; 251 this.protocol = protocol; 252 this.clientAuth = clientAuth; 253 } 254 255 boolean isEnabled() { 256 return true; 257 } 258 259 @Override 260 public String toString() { 261 String s = cipherSuite + " in " + protocol + " mode"; 262 if (clientAuth != null) { 263 s += " with " + clientAuth + " client authentication"; 264 } 265 return s; 266 } 267 } 268 269 private static volatile CipherTestUtils instance = null; 270 271 public static CipherTestUtils getInstance() throws Exception { 272 if (instance == null) { 273 synchronized (CipherTestUtils.class) { 274 if (instance == null) { 275 instance = new CipherTestUtils(); 276 } 277 } 278 } 279 return instance; 280 } 281 282 public static void setTestedArguments(String protocol, String ciphersuite) { 283 ciphersuite = ciphersuite.trim(); 284 TestParameters params = new TestParameters(ciphersuite, protocol, null); 285 TESTS.add(params); 286 } 287 288 public X509ExtendedKeyManager getClientKeyManager() { 289 return clientKeyManager; 290 } 291 292 public X509TrustManager getClientTrustManager() { 293 return clientTrustManager; 294 } 295 296 public X509ExtendedKeyManager getServerKeyManager() { 297 return serverKeyManager; 298 } 299 300 public X509TrustManager getServerTrustManager() { 301 return serverTrustManager; 302 } 303 304 public static void addFailure(Exception e) { 305 EXCEPTIONS.add(e); 306 } 307 308 private CipherTestUtils() throws Exception { 309 factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); 310 KeyStore serverKeyStore = createServerKeyStore(SERVER_PUBLIC_KEY, 311 SERVER_PRIVATE_KEY); 312 KeyStore serverTrustStore = createServerKeyStore(CA_PUBLIC_KEY, 313 CA_PRIVATE_KEY); 314 315 if (serverKeyStore != null) { 316 KeyManagerFactory keyFactory = KeyManagerFactory.getInstance( 317 KeyManagerFactory.getDefaultAlgorithm()); 318 keyFactory.init(serverKeyStore, PASSWORD); 319 serverKeyManager = (X509ExtendedKeyManager) 320 keyFactory.getKeyManagers()[0]; 321 } else { 322 serverKeyManager = null; 323 } 324 serverTrustManager = serverTrustStore != null 325 ? new AlwaysTrustManager(serverTrustStore) : null; 326 327 KeyStore clientKeyStore, clientTrustStore; 328 clientTrustStore = serverTrustStore; 329 clientKeyStore = 330 createServerKeyStore(CLIENT_PUBLIC_KEY,CLIENT_PRIVATE_KEY); 331 if (clientKeyStore != null) { 332 KeyManagerFactory keyFactory = KeyManagerFactory.getInstance( 333 KeyManagerFactory.getDefaultAlgorithm()); 334 keyFactory.init(clientKeyStore, PASSWORD); 335 clientKeyManager = (X509ExtendedKeyManager) 336 keyFactory.getKeyManagers()[0]; 337 } else { 338 clientKeyManager = null; 339 } 340 clientTrustManager = (clientTrustStore != null) 341 ? new AlwaysTrustManager(clientTrustStore) : null; 342 } 343 344 void checkResult(String exception) throws Exception { 345 if (EXCEPTIONS.size() >= 1) { 346 Exception actualException = EXCEPTIONS.get(0); 347 if (exception == null) { 348 throw new RuntimeException("FAILED: got unexpected exception: " 349 + actualException); 350 } 351 if (!exception.equals(actualException.getClass().getName())) { 352 throw new RuntimeException("FAILED: got unexpected exception: " 353 + actualException); 354 } 355 356 System.out.println("PASSED: got expected exception: " 357 + actualException); 358 } else { 359 if (exception != null) { 360 throw new RuntimeException("FAILED: " + exception 361 + " was expected"); 362 } 363 System.out.println("PASSED"); 364 } 365 } 366 367 SSLSocketFactory getFactory() { 368 return factory; 369 } 370 371 static abstract class Client implements Runnable { 372 373 final CipherTestUtils cipherTest; 374 TestParameters testedParams; 375 376 Client(CipherTestUtils cipherTest) throws Exception { 377 this.cipherTest = cipherTest; 378 } 379 380 Client(CipherTestUtils cipherTest, String testedCipherSuite) 381 throws Exception { 382 this.cipherTest = cipherTest; 383 } 384 385 @Override 386 public final void run() { 387 388 TESTS.stream().map((params) -> { 389 if (!params.isEnabled()) { 390 System.out.println("Skipping disabled test " + params); 391 } 392 return params; 393 }).forEach((params) -> { 394 try { 395 System.out.println("Testing " + params); 396 runTest(params); 397 System.out.println("Passed " + params); 398 } catch (Exception e) { 399 CipherTestUtils.addFailure(e); 400 System.out.println("** Failed " + params 401 + "**, got exception:"); 402 e.printStackTrace(System.out); 403 } 404 }); 405 } 406 407 abstract void runTest(TestParameters params) throws Exception; 408 409 void sendRequest(InputStream in, OutputStream out) throws IOException { 410 out.write("GET / HTTP/1.0\r\n\r\n".getBytes()); 411 out.flush(); 412 StringBuilder sb = new StringBuilder(); 413 while (true) { 414 int ch = in.read(); 415 if (ch < 0) { 416 break; 417 } 418 sb.append((char) ch); 419 } 420 String response = sb.toString(); 421 if (response.startsWith("HTTP/1.0 200 ") == false) { 422 throw new IOException("Invalid response: " + response); 423 } else { 424 System.out.println(); 425 System.out.println("--- Response --- "); 426 System.out.println(response); 427 System.out.println("---------------- "); 428 } 429 } 430 } 431 432 public static void printStringArray(String[] stringArray) { 433 System.out.println(Arrays.toString(stringArray)); 434 System.out.println(); 435 } 436 437 public static void printInfo(SSLServerSocket socket) { 438 System.out.println(); 439 System.out.println("--- SSL ServerSocket Info ---"); 440 System.out.print("SupportedProtocols : "); 441 printStringArray(socket.getSupportedProtocols()); 442 System.out.print("SupportedCipherSuites : "); 443 printStringArray(socket.getSupportedCipherSuites()); 444 System.out.print("EnabledProtocols : "); 445 printStringArray(socket.getEnabledProtocols()); 446 System.out.print("EnabledCipherSuites : "); 447 String[] supportedCipherSuites = socket.getEnabledCipherSuites(); 448 Arrays.sort(supportedCipherSuites); 449 printStringArray(supportedCipherSuites); 450 System.out.println("NeedClientAuth : " 451 + socket.getNeedClientAuth()); 452 System.out.println("WantClientAuth : " 453 + socket.getWantClientAuth()); 454 System.out.println("-----------------------"); 455 } 456 457 public static void printInfo(SSLSocket socket) { 458 System.out.println(); 459 System.out.println("--- SSL Socket Info ---"); 460 System.out.print(" SupportedProtocols : "); 461 printStringArray(socket.getSupportedProtocols()); 462 System.out.println(" EnabledProtocols : " 463 + socket.getEnabledProtocols()[0]); 464 System.out.print(" SupportedCipherSuites : "); 465 String[] supportedCipherSuites = socket.getEnabledCipherSuites(); 466 Arrays.sort(supportedCipherSuites); 467 printStringArray(supportedCipherSuites); 468 System.out.println(" EnabledCipherSuites : " 469 + socket.getEnabledCipherSuites()[0]); 470 System.out.println(" NeedClientAuth : " 471 + socket.getNeedClientAuth()); 472 System.out.println(" WantClientAuth : " 473 + socket.getWantClientAuth()); 474 System.out.println("-----------------------"); 475 } 476 477 private static KeyStore createServerKeyStore(String publicKey, 478 String keySpecStr) throws KeyStoreException, IOException, 479 NoSuchAlgorithmException, CertificateException, 480 InvalidKeySpecException { 481 482 KeyStore ks = KeyStore.getInstance("JKS"); 483 ks.load(null, null); 484 if (publicKey == null || keySpecStr == null) { 485 throw new IllegalArgumentException("publicKey or " 486 + "keySpecStr cannot be null"); 487 } 488 String strippedPrivateKey = keySpecStr.substring( 489 keySpecStr.indexOf("\n"), keySpecStr.lastIndexOf("\n")); 490 491 // generate the private key. 492 PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( 493 Base64.getMimeDecoder().decode(strippedPrivateKey)); 494 KeyFactory kf = KeyFactory.getInstance("RSA"); 495 RSAPrivateKey priKey 496 = (RSAPrivateKey) kf.generatePrivate(priKeySpec); 497 498 // generate certificate chain 499 try (InputStream is = new ByteArrayInputStream(publicKey.getBytes())) { 500 // generate certificate from cert string 501 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 502 Certificate keyCert = cf.generateCertificate(is); 503 Certificate[] chain = {keyCert}; 504 ks.setKeyEntry("TestEntry", priKey, PASSWORD, chain); 505 } 506 507 return ks; 508 } 509 510 public static Server mainServer(PeerFactory peerFactory, 511 String expectedException) throws Exception { 512 513 setTestedArguments(peerFactory.getTestedProtocol(), 514 peerFactory.getTestedCipher()); 515 516 System.out.print( 517 " Initializing test '" + peerFactory.getName() + "'..."); 518 secureRandom.nextInt(); 519 520 CipherTestUtils cipherTest = CipherTestUtils.getInstance(); 521 Server srv = peerFactory.newServer(cipherTest, PeerFactory.FREE_PORT); 522 Thread serverThread = new Thread(srv, "Server"); 523 serverThread.start(); 524 525 return srv; 526 } 527 528 public static void mainClient(PeerFactory peerFactory, int port, 529 String expectedException) throws Exception { 530 531 long time = System.currentTimeMillis(); 532 setTestedArguments(peerFactory.getTestedProtocol(), 533 peerFactory.getTestedCipher()); 534 535 System.out.print( 536 " Initializing test '" + peerFactory.getName() + "'..."); 537 secureRandom.nextInt(); 538 539 CipherTestUtils cipherTest = CipherTestUtils.getInstance(); 540 peerFactory.newClient(cipherTest, port).run(); 541 cipherTest.checkResult(expectedException); 542 543 time = System.currentTimeMillis() - time; 544 System.out.println("Elapsed time " + time); 545 } 546 547 public static abstract class PeerFactory { 548 549 public static final int FREE_PORT = 0; 550 551 abstract String getName(); 552 553 abstract String getTestedProtocol(); 554 555 abstract String getTestedCipher(); 556 557 abstract Client newClient(CipherTestUtils cipherTest, int testPort) 558 throws Exception; 559 560 abstract Server newServer(CipherTestUtils cipherTest, int testPort) 561 throws Exception; 562 563 boolean isSupported(String cipherSuite) { 564 return true; 565 } 566 } 567} 568 569class AlwaysTrustManager implements X509TrustManager { 570 571 X509TrustManager trustManager; 572 573 public AlwaysTrustManager(KeyStore keyStore) 574 throws NoSuchAlgorithmException, KeyStoreException { 575 576 TrustManagerFactory tmf 577 = TrustManagerFactory.getInstance(TrustManagerFactory. 578 getDefaultAlgorithm()); 579 tmf.init(keyStore); 580 581 TrustManager tms[] = tmf.getTrustManagers(); 582 for (TrustManager tm : tms) { 583 trustManager = (X509TrustManager) tm; 584 return; 585 } 586 587 } 588 589 @Override 590 public void checkClientTrusted(X509Certificate[] chain, String authType) 591 throws CertificateException { 592 try { 593 trustManager.checkClientTrusted(chain, authType); 594 } catch (CertificateException excep) { 595 System.out.println("ERROR in client trust manager: " + excep); 596 } 597 } 598 599 @Override 600 public void checkServerTrusted(X509Certificate[] chain, String authType) 601 throws CertificateException { 602 try { 603 trustManager.checkServerTrusted(chain, authType); 604 } catch (CertificateException excep) { 605 System.out.println("ERROR in server trust manager: " + excep); 606 } 607 } 608 609 @Override 610 public X509Certificate[] getAcceptedIssuers() { 611 return trustManager.getAcceptedIssuers(); 612 } 613} 614 615class MyX509KeyManager extends X509ExtendedKeyManager { 616 617 private final X509ExtendedKeyManager keyManager; 618 private String authType; 619 620 MyX509KeyManager(X509ExtendedKeyManager keyManager) { 621 this.keyManager = keyManager; 622 } 623 624 void setAuthType(String authType) { 625 this.authType = "ECDSA".equals(authType) ? "EC" : authType; 626 } 627 628 @Override 629 public String[] getClientAliases(String keyType, Principal[] issuers) { 630 if (authType == null) { 631 return null; 632 } 633 return keyManager.getClientAliases(authType, issuers); 634 } 635 636 @Override 637 public String chooseClientAlias(String[] keyType, Principal[] issuers, 638 Socket socket) { 639 if (authType == null) { 640 return null; 641 } 642 return keyManager.chooseClientAlias(new String[]{authType}, 643 issuers, socket); 644 } 645 646 @Override 647 public String chooseEngineClientAlias(String[] keyType, 648 Principal[] issuers, SSLEngine engine) { 649 if (authType == null) { 650 return null; 651 } 652 return keyManager.chooseEngineClientAlias(new String[]{authType}, 653 issuers, engine); 654 } 655 656 @Override 657 public String[] getServerAliases(String keyType, Principal[] issuers) { 658 throw new UnsupportedOperationException("Servers not supported"); 659 } 660 661 @Override 662 public String chooseServerAlias(String keyType, Principal[] issuers, 663 Socket socket) { 664 throw new UnsupportedOperationException("Servers not supported"); 665 } 666 667 @Override 668 public String chooseEngineServerAlias(String keyType, Principal[] issuers, 669 SSLEngine engine) { 670 throw new UnsupportedOperationException("Servers not supported"); 671 } 672 673 @Override 674 public X509Certificate[] getCertificateChain(String alias) { 675 return keyManager.getCertificateChain(alias); 676 } 677 678 @Override 679 public PrivateKey getPrivateKey(String alias) { 680 return keyManager.getPrivateKey(alias); 681 } 682} 683