Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/security/pkcs11/fips/CipherTest.java
38854 views
/*1* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.*;24import java.net.*;25import java.util.*;26import java.util.concurrent.*;2728import java.security.*;29import java.security.cert.*;30import java.security.cert.Certificate;3132import javax.net.ssl.*;3334/**35* Test that all ciphersuites work in all versions and all client36* authentication types. The way this is setup the server is stateless and37* all checking is done on the client side.38*39* The test is multithreaded to speed it up, especially on multiprocessor40* machines. To simplify debugging, run with -DnumThreads=1.41*42* @author Andreas Sterbenz43*/44public class CipherTest {4546// use any available port for the server socket47static int serverPort = 0;4849final int THREADS;5051// assume that if we do not read anything for 20 seconds, something52// has gone wrong53final static int TIMEOUT = 20 * 1000;5455static KeyStore /* trustStore, */ keyStore;56static X509ExtendedKeyManager keyManager;57static X509TrustManager trustManager;58static SecureRandom secureRandom;5960private static PeerFactory peerFactory;6162static abstract class Server implements Runnable {6364final CipherTest cipherTest;6566Server(CipherTest cipherTest) throws Exception {67this.cipherTest = cipherTest;68}6970public abstract void run();7172void handleRequest(InputStream in, OutputStream out) throws IOException {73boolean newline = false;74StringBuilder sb = new StringBuilder();75while (true) {76int ch = in.read();77if (ch < 0) {78throw new EOFException();79}80sb.append((char)ch);81if (ch == '\r') {82// empty83} else if (ch == '\n') {84if (newline) {85// 2nd newline in a row, end of request86break;87}88newline = true;89} else {90newline = false;91}92}93String request = sb.toString();94if (request.startsWith("GET / HTTP/1.") == false) {95throw new IOException("Invalid request: " + request);96}97out.write("HTTP/1.0 200 OK\r\n\r\n".getBytes());98}99100}101102public static class TestParameters {103104String cipherSuite;105String protocol;106String clientAuth;107108TestParameters(String cipherSuite, String protocol,109String clientAuth) {110this.cipherSuite = cipherSuite;111this.protocol = protocol;112this.clientAuth = clientAuth;113}114115boolean isEnabled() {116return TLSCipherStatus.isEnabled(cipherSuite, protocol);117}118119public String toString() {120String s = cipherSuite + " in " + protocol + " mode";121if (clientAuth != null) {122s += " with " + clientAuth + " client authentication";123}124return s;125}126127static enum TLSCipherStatus {128// cipher suites supported since TLS 1.2129CS_01("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", 0x0303, 0xFFFF),130CS_02("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", 0x0303, 0xFFFF),131CS_03("TLS_RSA_WITH_AES_256_CBC_SHA256", 0x0303, 0xFFFF),132CS_04("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", 0x0303, 0xFFFF),133CS_05("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", 0x0303, 0xFFFF),134CS_06("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", 0x0303, 0xFFFF),135CS_07("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", 0x0303, 0xFFFF),136137CS_08("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),138CS_09("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),139CS_10("TLS_RSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),140CS_11("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),141CS_12("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),142CS_13("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),143CS_14("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),144145CS_15("TLS_DH_anon_WITH_AES_256_CBC_SHA256", 0x0303, 0xFFFF),146CS_16("TLS_DH_anon_WITH_AES_128_CBC_SHA256", 0x0303, 0xFFFF),147CS_17("TLS_RSA_WITH_NULL_SHA256", 0x0303, 0xFFFF),148149CS_20("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),150CS_21("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),151CS_22("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),152CS_23("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),153CS_24("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),154CS_25("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),155CS_26("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),156CS_27("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),157158CS_28("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),159CS_29("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),160CS_30("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),161CS_31("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),162CS_32("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),163CS_33("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),164165CS_34("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x0303, 0xFFFF),166CS_35("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x0303, 0xFFFF),167168// cipher suites obsoleted since TLS 1.2169CS_50("SSL_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),170CS_51("SSL_DHE_RSA_WITH_DES_CBC_SHA", 0x0000, 0x0303),171CS_52("SSL_DHE_DSS_WITH_DES_CBC_SHA", 0x0000, 0x0303),172CS_53("SSL_DH_anon_WITH_DES_CBC_SHA", 0x0000, 0x0303),173CS_54("TLS_KRB5_WITH_DES_CBC_SHA", 0x0000, 0x0303),174CS_55("TLS_KRB5_WITH_DES_CBC_MD5", 0x0000, 0x0303),175176// cipher suites obsoleted since TLS 1.1177CS_60("SSL_RSA_EXPORT_WITH_RC4_40_MD5", 0x0000, 0x0302),178CS_61("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", 0x0000, 0x0302),179CS_62("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0000, 0x0302),180CS_63("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x0000, 0x0302),181CS_64("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x0000, 0x0302),182CS_65("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", 0x0000, 0x0302),183CS_66("TLS_KRB5_EXPORT_WITH_RC4_40_SHA", 0x0000, 0x0302),184CS_67("TLS_KRB5_EXPORT_WITH_RC4_40_MD5", 0x0000, 0x0302),185CS_68("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", 0x0000, 0x0302),186CS_69("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", 0x0000, 0x0302),187188// ignore TLS_EMPTY_RENEGOTIATION_INFO_SCSV always189CS_99("TLS_EMPTY_RENEGOTIATION_INFO_SCSV", 0xFFFF, 0x0000);190191// the cipher suite name192final String cipherSuite;193194// supported since protocol version195final int supportedSince;196197// obsoleted since protocol version198final int obsoletedSince;199200TLSCipherStatus(String cipherSuite,201int supportedSince, int obsoletedSince) {202this.cipherSuite = cipherSuite;203this.supportedSince = supportedSince;204this.obsoletedSince = obsoletedSince;205}206207static boolean isEnabled(String cipherSuite, String protocol) {208int versionNumber = toVersionNumber(protocol);209210if (versionNumber < 0) {211return true; // unlikely to happen212}213214for (TLSCipherStatus status : TLSCipherStatus.values()) {215if (cipherSuite.equals(status.cipherSuite)) {216if ((versionNumber < status.supportedSince) ||217(versionNumber >= status.obsoletedSince)) {218return false;219}220221return true;222}223}224225return true;226}227228private static int toVersionNumber(String protocol) {229int versionNumber = -1;230231switch (protocol) {232case "SSLv2Hello":233versionNumber = 0x0002;234break;235case "SSLv3":236versionNumber = 0x0300;237break;238case "TLSv1":239versionNumber = 0x0301;240break;241case "TLSv1.1":242versionNumber = 0x0302;243break;244case "TLSv1.2":245versionNumber = 0x0303;246break;247default:248// unlikely to happen249}250251return versionNumber;252}253}254}255256private List<TestParameters> tests;257private Iterator<TestParameters> testIterator;258private SSLSocketFactory factory;259private boolean failed;260261private CipherTest(PeerFactory peerFactory) throws IOException {262THREADS = Integer.parseInt(System.getProperty("numThreads", "4"));263factory = (SSLSocketFactory)SSLSocketFactory.getDefault();264SSLSocket socket = (SSLSocket)factory.createSocket();265String[] cipherSuites = socket.getSupportedCipherSuites();266String[] protocols = socket.getSupportedProtocols();267// String[] clientAuths = {null, "RSA", "DSA"};268String[] clientAuths = {null};269tests = new ArrayList<TestParameters>(270cipherSuites.length * protocols.length * clientAuths.length);271for (int i = 0; i < cipherSuites.length; i++) {272String cipherSuite = cipherSuites[i];273274for (int j = 0; j < protocols.length; j++) {275String protocol = protocols[j];276277if (!peerFactory.isSupported(cipherSuite, protocol)) {278continue;279}280281for (int k = 0; k < clientAuths.length; k++) {282String clientAuth = clientAuths[k];283if ((clientAuth != null) &&284(cipherSuite.indexOf("DH_anon") != -1)) {285// no client with anonymous ciphersuites286continue;287}288tests.add(new TestParameters(cipherSuite, protocol,289clientAuth));290}291}292}293testIterator = tests.iterator();294}295296synchronized void setFailed() {297failed = true;298}299300public void run() throws Exception {301Thread[] threads = new Thread[THREADS];302for (int i = 0; i < THREADS; i++) {303try {304threads[i] = new Thread(peerFactory.newClient(this),305"Client " + i);306} catch (Exception e) {307e.printStackTrace();308return;309}310threads[i].start();311}312try {313for (int i = 0; i < THREADS; i++) {314threads[i].join();315}316} catch (InterruptedException e) {317setFailed();318e.printStackTrace();319}320if (failed) {321throw new Exception("*** Test '" + peerFactory.getName() +322"' failed ***");323} else {324System.out.println("Test '" + peerFactory.getName() +325"' completed successfully");326}327}328329synchronized TestParameters getTest() {330if (failed) {331return null;332}333if (testIterator.hasNext()) {334return (TestParameters)testIterator.next();335}336return null;337}338339SSLSocketFactory getFactory() {340return factory;341}342343static abstract class Client implements Runnable {344345final CipherTest cipherTest;346347Client(CipherTest cipherTest) throws Exception {348this.cipherTest = cipherTest;349}350351public final void run() {352while (true) {353TestParameters params = cipherTest.getTest();354if (params == null) {355// no more tests356break;357}358if (params.isEnabled() == false) {359System.out.println("Skipping disabled test " + params);360continue;361}362try {363runTest(params);364System.out.println("Passed " + params);365} catch (Exception e) {366cipherTest.setFailed();367System.out.println("** Failed " + params + "**");368e.printStackTrace();369}370}371}372373abstract void runTest(TestParameters params) throws Exception;374375void sendRequest(InputStream in, OutputStream out) throws IOException {376out.write("GET / HTTP/1.0\r\n\r\n".getBytes());377out.flush();378StringBuilder sb = new StringBuilder();379while (true) {380int ch = in.read();381if (ch < 0) {382break;383}384sb.append((char)ch);385}386String response = sb.toString();387if (response.startsWith("HTTP/1.0 200 ") == false) {388throw new IOException("Invalid response: " + response);389}390}391392}393394// for some reason, ${test.src} has a different value when the395// test is called from the script and when it is called directly...396static String pathToStores = ".";397static String pathToStoresSH = ".";398static String keyStoreFile = "keystore";399static String trustStoreFile = "truststore";400static char[] passwd = "passphrase".toCharArray();401402static File PATH;403404private static KeyStore readKeyStore(String name) throws Exception {405File file = new File(PATH, name);406InputStream in = new FileInputStream(file);407KeyStore ks = KeyStore.getInstance("JKS");408ks.load(in, passwd);409in.close();410return ks;411}412413public static void main(PeerFactory peerFactory, KeyStore keyStore,414String[] args) throws Exception {415long time = System.currentTimeMillis();416String relPath;417if ((args != null) && (args.length > 0) && args[0].equals("sh")) {418relPath = pathToStoresSH;419} else {420relPath = pathToStores;421}422PATH = new File(System.getProperty("test.src", "."), relPath);423CipherTest.peerFactory = peerFactory;424System.out.print(425"Initializing test '" + peerFactory.getName() + "'...");426// secureRandom = new SecureRandom();427// secureRandom.nextInt();428// trustStore = readKeyStore(trustStoreFile);429CipherTest.keyStore = keyStore;430// keyStore = readKeyStore(keyStoreFile);431KeyManagerFactory keyFactory =432KeyManagerFactory.getInstance(433KeyManagerFactory.getDefaultAlgorithm());434keyFactory.init(keyStore, "test12".toCharArray());435keyManager = (X509ExtendedKeyManager)keyFactory.getKeyManagers()[0];436437TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());438tmf.init(keyStore);439trustManager = (X509TrustManager)tmf.getTrustManagers()[0];440441// trustManager = new AlwaysTrustManager();442SSLContext context = SSLContext.getInstance("TLS");443context.init(new KeyManager[] {keyManager},444new TrustManager[] {trustManager}, null);445SSLContext.setDefault(context);446447CipherTest cipherTest = new CipherTest(peerFactory);448Thread serverThread = new Thread(peerFactory.newServer(cipherTest),449"Server");450serverThread.setDaemon(true);451serverThread.start();452System.out.println("Done");453cipherTest.run();454time = System.currentTimeMillis() - time;455System.out.println("Done. (" + time + " ms)");456}457458static abstract class PeerFactory {459460abstract String getName();461462abstract Client newClient(CipherTest cipherTest) throws Exception;463464abstract Server newServer(CipherTest cipherTest) throws Exception;465466boolean isSupported(String cipherSuite, String protocol) {467// skip kerberos cipher suites468if (cipherSuite.startsWith("TLS_KRB5")) {469System.out.println("Skipping unsupported test for " +470cipherSuite + " of " + protocol);471return false;472}473474// No ECDH-capable certificate in key store. May restructure475// this in the future.476if (cipherSuite.contains("ECDHE_ECDSA") ||477cipherSuite.contains("ECDH_ECDSA") ||478cipherSuite.contains("ECDH_RSA")) {479System.out.println("Skipping unsupported test for " +480cipherSuite + " of " + protocol);481return false;482}483484// skip SSLv2Hello protocol485//486// skip TLSv1.2 protocol, we have not implement "SunTls12Prf" and487// SunTls12RsaPremasterSecret in SunPKCS11 provider488if (protocol.equals("SSLv2Hello") || protocol.equals("TLSv1.2")) {489System.out.println("Skipping unsupported test for " +490cipherSuite + " of " + protocol);491return false;492}493494// ignore exportable cipher suite for TLSv1.1495if (protocol.equals("TLSv1.1")) {496if (cipherSuite.indexOf("_EXPORT_WITH") != -1) {497System.out.println("Skipping obsoleted test for " +498cipherSuite + " of " + protocol);499return false;500}501}502503return true;504}505}506507}508509// we currently don't do any chain verification. we assume that works ok510// and we can speed up the test. we could also just add a plain certificate511// chain comparision with our trusted certificates.512class AlwaysTrustManager implements X509TrustManager {513514public AlwaysTrustManager() {515516}517518public void checkClientTrusted(X509Certificate[] chain, String authType)519throws CertificateException {520// empty521}522523public void checkServerTrusted(X509Certificate[] chain, String authType)524throws CertificateException {525// empty526}527528public X509Certificate[] getAcceptedIssuers() {529return new X509Certificate[0];530}531}532533class MyX509KeyManager extends X509ExtendedKeyManager {534535private final X509ExtendedKeyManager keyManager;536private String authType;537538MyX509KeyManager(X509ExtendedKeyManager keyManager) {539this.keyManager = keyManager;540}541542void setAuthType(String authType) {543this.authType = authType;544}545546public String[] getClientAliases(String keyType, Principal[] issuers) {547if (authType == null) {548return null;549}550return keyManager.getClientAliases(authType, issuers);551}552553public String chooseClientAlias(String[] keyType, Principal[] issuers,554Socket socket) {555if (authType == null) {556return null;557}558return keyManager.chooseClientAlias(new String[] {authType},559issuers, socket);560}561562public String chooseEngineClientAlias(String[] keyType,563Principal[] issuers, SSLEngine engine) {564if (authType == null) {565return null;566}567return keyManager.chooseEngineClientAlias(new String[] {authType},568issuers, engine);569}570571public String[] getServerAliases(String keyType, Principal[] issuers) {572throw new UnsupportedOperationException("Servers not supported");573}574575public String chooseServerAlias(String keyType, Principal[] issuers,576Socket socket) {577throw new UnsupportedOperationException("Servers not supported");578}579580public String chooseEngineServerAlias(String keyType, Principal[] issuers,581SSLEngine engine) {582throw new UnsupportedOperationException("Servers not supported");583}584585public X509Certificate[] getCertificateChain(String alias) {586return keyManager.getCertificateChain(alias);587}588589public PrivateKey getPrivateKey(String alias) {590return keyManager.getPrivateKey(alias);591}592593}594595class DaemonThreadFactory implements ThreadFactory {596597final static ThreadFactory INSTANCE = new DaemonThreadFactory();598599private final static ThreadFactory DEFAULT = Executors.defaultThreadFactory();600601public Thread newThread(Runnable r) {602Thread t = DEFAULT.newThread(r);603t.setDaemon(true);604return t;605}606607}608609610