diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java index 1512b52800368..2f3a8e2699dbc 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -689,13 +689,16 @@ public void consume(ConnectionContext context, chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id, SSLHandshake.CERTIFICATE); - List sss = new LinkedList<>(); - for (int id : crm.algorithmIds) { - SignatureScheme ss = SignatureScheme.valueOf(id); - if (ss != null) { - sss.add(ss); - } + List sss = + SignatureScheme.getSupportedAlgorithms( + chc.sslConfig, + chc.algorithmConstraints, chc.negotiatedProtocol, + crm.algorithmIds); + if (sss == null || sss.isEmpty()) { + throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE, + "No supported signature algorithm"); } + chc.peerRequestedSignatureSchemes = sss; chc.peerRequestedCertSignSchemes = sss; // use the same schemes chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss); diff --git a/test/jdk/javax/net/ssl/templates/SSLContextTemplate.java b/test/jdk/javax/net/ssl/templates/SSLContextTemplate.java index f3cad4ddfe16d..fd2fcd8099d51 100644 --- a/test/jdk/javax/net/ssl/templates/SSLContextTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLContextTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -478,7 +478,7 @@ private SSLContext createSSLContext( /* * Create an instance of KeyManager with the specified key materials. */ - private KeyManager createKeyManager( + static KeyManager createKeyManager( String[] keyMaterialCerts, String[] keyMaterialKeys, String[] keyMaterialKeyAlgs, @@ -534,7 +534,7 @@ private KeyManager createKeyManager( /* * Create an instance of TrustManager with the specified trust materials. */ - private TrustManager createTrustManager( + static TrustManager createTrustManager( String[] trustedMaterials, ContextParameters params) throws Exception { diff --git a/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java b/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java index 48a7c19df74aa..621aaea354634 100644 --- a/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java @@ -197,7 +197,7 @@ private void runTest() throws Exception { } } - private static boolean isOpen(SSLEngine engine) { + static boolean isOpen(SSLEngine engine) { return (!engine.isOutboundDone() || !engine.isInboundDone()); } @@ -240,7 +240,7 @@ protected static void runDelegatedTasks(SSLEngine engine) throws Exception { } // Simple check to make sure everything came across as expected. - private static void checkTransfer(ByteBuffer a, ByteBuffer b) + static void checkTransfer(ByteBuffer a, ByteBuffer b) throws Exception { a.flip(); b.flip(); diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java new file mode 100644 index 0000000000000..d7d068f339d6a --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 8263188 + * @summary If TLS the server and client has no common signature algorithms, + * the connection should fail fast with "No supported signature algorithm". + * This test only covers TLS 1.2. + * + * @library /test/lib + * /javax/net/ssl/templates + * + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256,ecdsa_secp384r1_sha384 + * -Dtest.clientAuth=false + * -Dtest.expectFail=false + * SigAlgosExtTestWithTLS12 + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Dtest.clientAuth=false + * -Dtest.expectFail=true + * SigAlgosExtTestWithTLS12 + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Dtest.clientAuth=true + * -Dtest.expectFail=true + * SigAlgosExtTestWithTLS12 + */ + +import javax.net.ssl.*; +import java.nio.ByteBuffer; +import java.util.*; + +public class SigAlgosExtTestWithTLS12 extends SSLEngineTemplate { + + private static final boolean CLIENT_AUTH + = Boolean.getBoolean("test.clientAuth"); + private static final boolean EXPECT_FAIL + = Boolean.getBoolean("test.expectFail"); + + private static final String[] CA_CERTS = new String[] { + // SHA256withECDSA, curve secp256r1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Subject Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" + + "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" + + "LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" + + "A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" + + "MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" + + "6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" + + "2YEHlSQUAbwwqCDEVB5KxaqP\n" + + "-----END CERTIFICATE-----", + + // SHA384withECDSA, curve secp384r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Subject Key Identifier: + // 0a:93:a9:a0:bf:e7:d5:48:9d:4f:89:15:c6:51:98:80:05:51:4e:4e + "-----BEGIN CERTIFICATE-----\n" + + "MIICCDCCAY6gAwIBAgIUCpOpoL/n1UidT4kVxlGYgAVRTk4wCgYIKoZIzj0EAwMw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowOzEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENVQN1wXWFdgC6u/dDdiC\n" + + "y+WtMTF66oL/0BSm+1ZqsogamzCryawOcHgiuXgWzx5CQ3LuOC+tDFyXpGfHuCvb\n" + + "dkzxPrP5n9NrR8/uRPe5l1KOUbchviU8z9cTP+LZxnZDo1MwUTAdBgNVHQ4EFgQU\n" + + "SktSFArR1p/5mXV0kyo0RxIVa/UwHwYDVR0jBBgwFoAUSktSFArR1p/5mXV0kyo0\n" + + "RxIVa/UwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjBZvoNmq3/v\n" + + "RD2gBTyvxjS9h0rsMRLHDnvul/KWngytwGPTOBo0Y8ixQXSjdKoc3rkCMQDkiNgx\n" + + "IDxuHedmrLQKIPnVcthTmwv7//jHiqGoKofwChMo2a1P+DQdhszmeHD/ARQ=\n" + + "-----END CERTIFICATE-----" + }; + + private static final String[] EE_CERTS = new String[] { + // SHA256withECDSA, curve secp256r1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Authority Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" + + "MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" + + "QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" + + "xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" + + "SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" + + "1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" + + "-----END CERTIFICATE-----", + + // SHA384withECDSA, curve secp384r1 + // Validity + // Not Before: Jun 24 08:15:06 2019 GMT + // Not After : Jun 19 08:15:06 2039 GMT + // Authority Key Identifier: + // 40:2D:AA:EE:66:AA:33:27:AD:9B:5D:52:9B:60:67:6A:2B:AD:52:D2 + "-----BEGIN CERTIFICATE-----\n" + + "MIICEjCCAZegAwIBAgIUS3F0AqAXWRg07CnbknJzxofyBQMwCgYIKoZIzj0EAwMw\n" + + "OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" + + "VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowVTEL\n" + + "MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" + + "dCBTZXJpdmNlMRgwFgYDVQQDDA9SZWdyZXNzaW9uIFRlc3QwdjAQBgcqhkjOPQIB\n" + + "BgUrgQQAIgNiAARqElz8b6T07eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/w\n" + + "G8ASSevpgqgpi6EzpBZaaJxE3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEj\n" + + "iLjYmt3O0pwpklijQjBAMB0GA1UdDgQWBBRALaruZqozJ62bXVKbYGdqK61S0jAf\n" + + "BgNVHSMEGDAWgBRKS1IUCtHWn/mZdXSTKjRHEhVr9TAKBggqhkjOPQQDAwNpADBm\n" + + "AjEArVDFKf48xijN6huVUJzKCOP0zlWB5Js+DItIkZmLQuhciPLhLIB/rChf3Y4C\n" + + "xuP4AjEAmfLhQRI0O3pifpYzYSVh2G7/jHNG4eO+2dvgAcU+Lh2IIj/cpLaPFSvL\n" + + "J8FXY9Nj\n" + + "-----END CERTIFICATE-----" + }; + + private static final String[] EE_KEYS = new String[] { + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" + + "JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" + + "59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6", + "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDASuI9EtK29APXPipkc\n" + + "qDA+qwlewMjv/OcjUJ77kP1Vz62oVF9iY9SRIyFIUju8wt+hZANiAARqElz8b6T0\n" + + "7eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/wG8ASSevpgqgpi6EzpBZaaJxE\n" + + "3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEjiLjYmt3O0pwpklg=" + }; + + private static final String[] EE_ALGS = new String[] { + "EC", + "EC" + }; + + private static final String[] EE_ALIASES = new String[] { + "EC-SHA256", + "EC-SHA384" + }; + + private static final Map SIG_SCHEMES_MAP = Map.of( + 0x0403, "ecdsa_secp256r1_sha256", + 0x0503, "ecdsa_secp384r1_sha384"); + + private static final int TLS_HS_CLI_HELLO = 1; + private static final int TLS_HS_CERT_REQ = 13; + private static final int HELLO_EXT_SIG_ALGS = 13; + + public SigAlgosExtTestWithTLS12() throws Exception { + super(); + } + + /* + * Create an instance of KeyManager for client use. + */ + public KeyManager createClientKeyManager() throws Exception { + return SSLContextTemplate.createKeyManager( + EE_CERTS, + EE_KEYS, + EE_ALGS, + EE_ALIASES, + getServerContextParameters()); + } + + @Override + public TrustManager createClientTrustManager() throws Exception { + return SSLContextTemplate.createTrustManager( + CA_CERTS, + getServerContextParameters()); + } + + @Override + public KeyManager createServerKeyManager() throws Exception { + return SSLContextTemplate.createKeyManager( + EE_CERTS, + EE_KEYS, + EE_ALGS, + EE_ALIASES, + getServerContextParameters()); + } + + @Override + public TrustManager createServerTrustManager() throws Exception { + return SSLContextTemplate.createTrustManager( + CA_CERTS, + getServerContextParameters()); + } + + @Override + protected SSLEngine configureServerEngine(SSLEngine serverEngine) { + serverEngine.setUseClientMode(false); + serverEngine.setNeedClientAuth(CLIENT_AUTH); + return serverEngine; + } + + @Override + protected SSLEngine configureClientEngine(SSLEngine clientEngine) { + clientEngine.setUseClientMode(true); + clientEngine.setEnabledProtocols(new String[] { "TLSv1.2" }); + return clientEngine; + } + + public static void main(String[] args) throws Exception { + System.setProperty("javax.net.debug", "ssl:handshake"); + + try { + new SigAlgosExtTestWithTLS12().run(); + if (EXPECT_FAIL) { + throw new RuntimeException( + "Expected SSLHandshakeException wasn't thrown"); + } + } catch (SSLHandshakeException e) { + if (EXPECT_FAIL && e.getMessage().equals( + "No supported signature algorithm")) { + System.out.println("Expected SSLHandshakeException"); + } else { + throw e; + } + } + } + + private void run() throws Exception { + boolean dataDone = false; + while (isOpen(clientEngine) || isOpen(serverEngine)) { + clientEngine.wrap(clientOut, cTOs); + cTOs.flip(); + + // Consume the ClientHello and get the server flight of handshake + // messages. We expect that it will be one TLS record containing + // multiple handshake messages, one of which is a CertificateRequest + // when the client authentication is required. + serverEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverEngine); + + // Wrap the server flight + serverEngine.wrap(serverOut, sTOc); + sTOc.flip(); + + if (CLIENT_AUTH && EXPECT_FAIL) { + twistCertReqMsg(sTOc); + } + + clientEngine.unwrap(sTOc, clientIn); + runDelegatedTasks(clientEngine); + + serverEngine.unwrap(cTOs, serverIn); + runDelegatedTasks(serverEngine); + + cTOs.compact(); + sTOc.compact(); + + if (!dataDone && (clientOut.limit() == serverIn.position()) && + (serverOut.limit() == clientIn.position())) { + checkTransfer(serverOut, clientIn); + checkTransfer(clientOut, serverIn); + + clientEngine.closeOutbound(); + dataDone = true; + serverEngine.closeOutbound(); + } + } + } + + /** + * Twists signature schemes in CertificateRequest message for negative + * client authentication cases. + * + * @param tlsRecord a ByteBuffer containing a TLS record. It is assumed + * that the position of the ByteBuffer is on the first byte of the TLS + * record header. + * + * @throws SSLException if the incoming ByteBuffer does not contain a + * well-formed TLS message. + */ + private static void twistCertReqMsg( + ByteBuffer tlsRecord) throws SSLException { + Objects.requireNonNull(tlsRecord); + tlsRecord.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(tlsRecord.get()); + int ver_major = Byte.toUnsignedInt(tlsRecord.get()); + int ver_minor = Byte.toUnsignedInt(tlsRecord.get()); + int recLen = Short.toUnsignedInt(tlsRecord.getShort()); + + // Simple sanity checks + if (type != 22) { + throw new SSLException("Not a handshake: Type = " + type); + } else if (recLen > tlsRecord.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + ", Remaining = " + + tlsRecord.remaining()); + } + + while (tlsRecord.hasRemaining()) { + // Grab the handshake message header. + int msgHdr = tlsRecord.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + + if (msgType == TLS_HS_CERT_REQ) { + // Slice the buffer such that it contains the entire + // handshake message (less the handshake header). + int bufPos = tlsRecord.position(); + ByteBuffer buf = tlsRecord.slice(bufPos, msgLen); + + // Replace the signature scheme with an unknown value + twistSigSchemesCertReq(buf, (short) 0x0000); + byte[] bufBytes = new byte[buf.limit()]; + buf.get(bufBytes); + tlsRecord.put(bufPos, bufBytes); + + break; + } else { + // Skip to the next handshake message, if there is one + tlsRecord.position(tlsRecord.position() + msgLen); + } + } + + tlsRecord.reset(); + } + + /** + * Replace the signature schemes in CertificateRequest message with an + * alternative value. It is assumed that the provided ByteBuffer has its + * position set at the first byte of the CertificateRequest message body + * (AFTER the handshake header) and contains the entire CR message. Upon + * successful completion of this method the ByteBuffer will have its + * position reset to the initial offset in the buffer. + * If an exception is thrown the position at the time of the exception + * will be preserved. + * + * @param data the ByteBuffer containing the CertificateRequest bytes + * @param altSigScheme an alternative signature scheme + */ + private static void twistSigSchemesCertReq(ByteBuffer data, + Short altSigScheme) { + Objects.requireNonNull(data); + data.mark(); + + // Jump past the certificate types + int certTypeLen = Byte.toUnsignedInt(data.get()); + if (certTypeLen != 0) { + data.position(data.position() + certTypeLen); + } + + int sigSchemeLen = Short.toUnsignedInt(data.getShort()); + for (int ssOff = 0; ssOff < sigSchemeLen; ssOff += 2) { + System.err.println( + "Use alternative signature scheme: " + altSigScheme); + data.putShort(data.position(), altSigScheme); + } + + data.reset(); + } +} diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java new file mode 100644 index 0000000000000..49e8da8af781d --- /dev/null +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 8263188 + * @summary If TLS the server and client has no common signature algorithms, + * the connection should fail fast with "No supported signature algorithm". + * This test only covers TLS 1.3, but doesn't cover client authentication. + * + * @library /test/lib + * /javax/net/ssl/templates + * + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256,ecdsa_secp384r1_sha384 + * -Dtest.expectFail=false + * SigAlgosExtTestWithTLS13 + * @run main/othervm + * -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha384 + * -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256 + * -Dtest.expectFail=true + * SigAlgosExtTestWithTLS13 + */ + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLSocket; + +public class SigAlgosExtTestWithTLS13 extends SSLSocketTemplate { + + @Override + protected SSLContext createServerSSLContext() throws Exception { + return createSSLContext( + new Cert[] { Cert.CA_ECDSA_SECP256R1, Cert.CA_ECDSA_SECP384R1 }, + new Cert[] { Cert.EE_ECDSA_SECP256R1, Cert.EE_ECDSA_SECP384R1 }, + getServerContextParameters()); + } + + @Override + protected SSLContext createClientSSLContext() throws Exception { + return createSSLContext( + new Cert[] { Cert.CA_ECDSA_SECP256R1, Cert.CA_ECDSA_SECP384R1 }, + new Cert[] { Cert.EE_ECDSA_SECP256R1, Cert.EE_ECDSA_SECP384R1 }, + getClientContextParameters()); + } + + @Override + protected void configureClientSocket(SSLSocket socket) { + socket.setEnabledProtocols(new String[] { "TLSv1.3" }); + } + + public static void main(String[] args) throws Exception { + boolean expectFail = Boolean.getBoolean("test.expectFail"); + try { + new SigAlgosExtTestWithTLS13().run(); + if (expectFail) { + throw new RuntimeException( + "Expected SSLHandshakeException wasn't thrown"); + } + } catch (SSLHandshakeException e) { + if (expectFail && e.getMessage().equals( + "No supported signature algorithm")) { + System.out.println("Expected SSLHandshakeException"); + } else { + throw e; + } + } + } +}