Path: blob/master/test/jdk/javax/net/ssl/TLSv12/DisabledShortDSAKeys.java
41152 views
/*1* Copyright (c) 2016, 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. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425// SunJSSE does not support dynamic system properties, no way to re-use26// system properties in samevm/agentvm mode.2728/*29* @test30* @bug 813956531* @summary Restrict certificates with DSA keys less than 1024 bits32*33* @run main/othervm DisabledShortDSAKeys PKIX TLSv1.234* @run main/othervm DisabledShortDSAKeys SunX509 TLSv1.235* @run main/othervm DisabledShortDSAKeys PKIX TLSv1.136* @run main/othervm DisabledShortDSAKeys SunX509 TLSv1.137* @run main/othervm DisabledShortDSAKeys PKIX TLSv138* @run main/othervm DisabledShortDSAKeys SunX509 TLSv139* @run main/othervm DisabledShortDSAKeys PKIX SSLv340* @run main/othervm DisabledShortDSAKeys SunX509 SSLv341*/4243import java.net.*;44import java.util.*;45import java.io.*;46import javax.net.ssl.*;47import java.security.Security;48import java.security.KeyStore;49import java.security.KeyFactory;50import java.security.cert.Certificate;51import java.security.cert.CertificateFactory;52import java.security.spec.*;53import java.security.interfaces.*;54import java.util.Base64;555657public class DisabledShortDSAKeys {5859/*60* =============================================================61* Set the various variables needed for the tests, then62* specify what tests to run on each side.63*/6465/*66* Should we run the client or server in a separate thread?67* Both sides can throw exceptions, but do you have a preference68* as to which side should be the main thread.69*/70static boolean separateServerThread = true;7172/*73* Where do we find the keystores?74*/75// Certificates and key used in the test.76static String trustedCertStr =77"-----BEGIN CERTIFICATE-----\n" +78"MIIDDjCCAs2gAwIBAgIJAO5/hbm1ByJOMAkGByqGSM44BAMwHzELMAkGA1UEBhMC\n" +79"VVMxEDAOBgNVBAoTB0V4YW1wbGUwHhcNMTYwMjE2MDQzNTQ2WhcNMzcwMTI2MDQz\n" +80"NTQ2WjAfMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXhhbXBsZTCCAbgwggEsBgcq\n" +81"hkjOOAQBMIIBHwKBgQC4aSK8nBYdWJtuBkz6yoDyjZnNuGFSpDmx1ggKpLpcnPuw\n" +82"YKAbUhqdYhZtaIqQ4aO0T1ZS/HuOM0zvddnMUidFNX3RUvDkvdD/JYOnjqzCm+xW\n" +83"U0NFuPHZdapQY5KFk3ugkqZpHLY1StZbu0qugZOZjbBOMwB7cHAbMDuVpEr8DQIV\n" +84"AOi+ig+h3okFbWEE9MztiI2+DqNrAoGBAKh2EZbuWU9NoHglhVzfDUoz8CeyW6W6\n" +85"rUZuIOQsjWaYOeRPWX0UVAGq9ykIOfamEpurKt4H8ge/pHaL9iazJjonMHOXG12A\n" +86"0lALsMDGv22zVaJzXjOBvdPzc87opr0LIVgHASKOcDYjsICKNYPlS2cL3MJoD+bj\n" +87"NAR67b90VBbEA4GFAAKBgQCGrkRp2tdj2mZF7Qz0tO6p3xSysbEfN6QZxOJYPTvM\n" +88"yIYfLV9Yoy7XaRd/mCpJo/dqmsZMzowtyi+u+enuVpOLKiq/lyCktL+xUzZAjLT+\n" +89"9dafHlS1wR3pDSa1spo9xTEi4Ff/DQDHcdGalBxSXX/UdRtSecIYAp5/fkt3QZ5v\n" +90"0aOBkTCBjjAdBgNVHQ4EFgQUX4qbP5PgBx1J8BJ8qEgfoKVLSnQwTwYDVR0jBEgw\n" +91"RoAUX4qbP5PgBx1J8BJ8qEgfoKVLSnShI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +92"VQQKEwdFeGFtcGxlggkA7n+FubUHIk4wDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8E\n" +93"BAMCAgQwCQYHKoZIzjgEAwMwADAtAhUAkr5bINXyy/McAx6qwhb6r0/QJUgCFFUP\n" +94"CZokA4/NqJIgq8ThpTQAE8SB\n" +95"-----END CERTIFICATE-----";9697static String targetCertStr =98"-----BEGIN CERTIFICATE-----\n" +99"MIICUjCCAhGgAwIBAgIJAIiDrs/4W8rtMAkGByqGSM44BAMwHzELMAkGA1UEBhMC\n" +100"VVMxEDAOBgNVBAoTB0V4YW1wbGUwHhcNMTYwMjE2MDQzNTQ2WhcNMzUxMTAzMDQz\n" +101"NTQ2WjA5MQswCQYDVQQGEwJVUzEQMA4GA1UECgwHRXhhbXBsZTEYMBYGA1UEAwwP\n" +102"d3d3LmV4YW1wbGUuY29tMIHwMIGoBgcqhkjOOAQBMIGcAkEAs6A0p3TysTtVXGSv\n" +103"ThR/8GHpbL49KyWRJBMIlmLc5jl/wxJgnL1t07p4YTOEa6ecyTFos04Z8n2GARmp\n" +104"zYlUywIVAJLDcf4JXhZbguRFSQdWwWhZkh+LAkBLCzh3Xvpmc/5CDqU+QHqDcuSk\n" +105"5B8+ZHaHRi2KQ00ejilpF2qZpW5JdHe4m3Pggh0MIuaAGX+leM4JKlnObj14A0MA\n" +106"AkAYb+DYlFgStFhF1ip7rFzY8K6i/3ellkXI2umI/XVwxUQTHSlk5nFOep5Dfzm9\n" +107"pADJwuSe1qGHsHB5LpMZPVpto4GEMIGBMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgPo\n" +108"MB0GA1UdDgQWBBT8nsFyccF4q1dtpWE1dkNK5UiXtTAfBgNVHSMEGDAWgBRfips/\n" +109"k+AHHUnwEnyoSB+gpUtKdDAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" +110"CCsGAQUFBwMDMAkGByqGSM44BAMDMAAwLQIUIcIlxpIwaZXdpMC+U076unR1Mp8C\n" +111"FQCD/NE8O0xwq57nwFfp7tUvUHYMMA==\n" +112"-----END CERTIFICATE-----";113114// Private key in the format of PKCS#8, key size is 512 bits.115static String targetPrivateKey =116"MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEAs6A0p3TysTtVXGSvThR/8GHpbL49KyWR\n" +117"JBMIlmLc5jl/wxJgnL1t07p4YTOEa6ecyTFos04Z8n2GARmpzYlUywIVAJLDcf4J\n" +118"XhZbguRFSQdWwWhZkh+LAkBLCzh3Xvpmc/5CDqU+QHqDcuSk5B8+ZHaHRi2KQ00e\n" +119"jilpF2qZpW5JdHe4m3Pggh0MIuaAGX+leM4JKlnObj14BBYCFHB2Wek2g5hpNj5y\n" +120"RQfCc6CFO0dv";121122static char passphrase[] = "passphrase".toCharArray();123124/*125* Is the server ready to serve?126*/127volatile static boolean serverReady = false;128129/*130* Turn on SSL debugging?131*/132static boolean debug = false;133134/*135* Define the server side of the test.136*137* If the server prematurely exits, serverReady will be set to true138* to avoid infinite hangs.139*/140void doServerSide() throws Exception {141SSLContext context = generateSSLContext(null, targetCertStr,142targetPrivateKey);143SSLServerSocketFactory sslssf = context.getServerSocketFactory();144SSLServerSocket sslServerSocket =145(SSLServerSocket)sslssf.createServerSocket(serverPort);146serverPort = sslServerSocket.getLocalPort();147148/*149* Signal Client, we're ready for his connect.150*/151serverReady = true;152153try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {154try (InputStream sslIS = sslSocket.getInputStream()) {155sslIS.read();156}157158throw new Exception(159"DSA keys shorter than 1024 bits should be disabled");160} catch (SSLHandshakeException sslhe) {161// the expected exception, ignore162}163}164165/*166* Define the client side of the test.167*168* If the server prematurely exits, serverReady will be set to true169* to avoid infinite hangs.170*/171void doClientSide() throws Exception {172173/*174* Wait for server to get started.175*/176while (!serverReady) {177Thread.sleep(50);178}179180SSLContext context = generateSSLContext(trustedCertStr, null, null);181SSLSocketFactory sslsf = context.getSocketFactory();182183try (SSLSocket sslSocket =184(SSLSocket)sslsf.createSocket("localhost", serverPort)) {185186// only enable the target protocol187sslSocket.setEnabledProtocols(new String[] {enabledProtocol});188189// enable a block cipher190sslSocket.setEnabledCipherSuites(191new String[] {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA"});192193try (OutputStream sslOS = sslSocket.getOutputStream()) {194sslOS.write('B');195sslOS.flush();196}197198throw new Exception(199"DSA keys shorter than 1024 bits should be disabled");200} catch (SSLHandshakeException sslhe) {201// the expected exception, ignore202}203}204205/*206* =============================================================207* The remainder is just support stuff208*/209private static String tmAlgorithm; // trust manager210private static String enabledProtocol; // the target protocol211212private static void parseArguments(String[] args) {213tmAlgorithm = args[0];214enabledProtocol = args[1];215}216217private static SSLContext generateSSLContext(String trustedCertStr,218String keyCertStr, String keySpecStr) throws Exception {219220// generate certificate from cert string221CertificateFactory cf = CertificateFactory.getInstance("X.509");222223// create a key store224KeyStore ks = KeyStore.getInstance("JKS");225ks.load(null, null);226227// import the trused cert228Certificate trusedCert = null;229ByteArrayInputStream is = null;230if (trustedCertStr != null) {231is = new ByteArrayInputStream(trustedCertStr.getBytes());232trusedCert = cf.generateCertificate(is);233is.close();234235ks.setCertificateEntry("DSA Export Signer", trusedCert);236}237238if (keyCertStr != null) {239// generate the private key.240PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(241Base64.getMimeDecoder().decode(keySpecStr));242KeyFactory kf = KeyFactory.getInstance("DSA");243DSAPrivateKey priKey =244(DSAPrivateKey)kf.generatePrivate(priKeySpec);245246// generate certificate chain247is = new ByteArrayInputStream(keyCertStr.getBytes());248Certificate keyCert = cf.generateCertificate(is);249is.close();250251Certificate[] chain = null;252if (trusedCert != null) {253chain = new Certificate[2];254chain[0] = keyCert;255chain[1] = trusedCert;256} else {257chain = new Certificate[1];258chain[0] = keyCert;259}260261// import the key entry.262ks.setKeyEntry("Whatever", priKey, passphrase, chain);263}264265// create SSL context266TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);267tmf.init(ks);268269SSLContext ctx = SSLContext.getInstance("TLS");270if (keyCertStr != null && !keyCertStr.isEmpty()) {271KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");272kmf.init(ks, passphrase);273274ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);275ks = null;276} else {277ctx.init(null, tmf.getTrustManagers(), null);278}279280return ctx;281}282283284// use any free port by default285volatile int serverPort = 0;286287volatile Exception serverException = null;288volatile Exception clientException = null;289290public static void main(String[] args) throws Exception {291Security.setProperty("jdk.certpath.disabledAlgorithms",292"DSA keySize < 1024");293Security.setProperty("jdk.tls.disabledAlgorithms",294"DSA keySize < 1024");295296if (debug) {297System.setProperty("javax.net.debug", "all");298}299300/*301* Get the customized arguments.302*/303parseArguments(args);304305/*306* Start the tests.307*/308new DisabledShortDSAKeys();309}310311Thread clientThread = null;312Thread serverThread = null;313314/*315* Primary constructor, used to drive remainder of the test.316*317* Fork off the other side, then do your work.318*/319DisabledShortDSAKeys() throws Exception {320Exception startException = null;321try {322if (separateServerThread) {323startServer(true);324startClient(false);325} else {326startClient(true);327startServer(false);328}329} catch (Exception e) {330startException = e;331}332333/*334* Wait for other side to close down.335*/336if (separateServerThread) {337if (serverThread != null) {338serverThread.join();339}340} else {341if (clientThread != null) {342clientThread.join();343}344}345346/*347* When we get here, the test is pretty much over.348* Which side threw the error?349*/350Exception local;351Exception remote;352353if (separateServerThread) {354remote = serverException;355local = clientException;356} else {357remote = clientException;358local = serverException;359}360361Exception exception = null;362363/*364* Check various exception conditions.365*/366if ((local != null) && (remote != null)) {367// If both failed, return the curthread's exception.368local.initCause(remote);369exception = local;370} else if (local != null) {371exception = local;372} else if (remote != null) {373exception = remote;374} else if (startException != null) {375exception = startException;376}377378/*379* If there was an exception *AND* a startException,380* output it.381*/382if (exception != null) {383if (exception != startException && startException != null) {384exception.addSuppressed(startException);385}386throw exception;387}388389// Fall-through: no exception to throw!390}391392void startServer(boolean newThread) throws Exception {393if (newThread) {394serverThread = new Thread() {395public void run() {396try {397doServerSide();398} catch (Exception e) {399/*400* Our server thread just died.401*402* Release the client, if not active already...403*/404System.err.println("Server died...");405serverReady = true;406serverException = e;407}408}409};410serverThread.start();411} else {412try {413doServerSide();414} catch (Exception e) {415serverException = e;416} finally {417serverReady = true;418}419}420}421422void startClient(boolean newThread) throws Exception {423if (newThread) {424clientThread = new Thread() {425public void run() {426try {427doClientSide();428} catch (Exception e) {429/*430* Our client thread just died.431*/432System.err.println("Client died...");433clientException = e;434}435}436};437clientThread.start();438} else {439try {440doClientSide();441} catch (Exception e) {442clientException = e;443}444}445}446}447448449