Path: blob/master/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java
41152 views
/*1* Copyright (C) 2021 THL A29 Limited, a Tencent company. 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*/2223/*24* @test 826318825* @summary If TLS the server and client has no common signature algorithms,26* the connection should fail fast with "No supported signature algorithm".27* This test only covers TLS 1.2.28*29* @library /test/lib30* /javax/net/ssl/templates31*32* @run main/othervm33* -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha38434* -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha256,ecdsa_secp384r1_sha38435* -Dtest.clientAuth=false36* -Dtest.expectFail=false37* SigAlgosExtTestWithTLS1238* @run main/othervm39* -Djdk.tls.server.SignatureSchemes=ecdsa_secp384r1_sha38440* -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha25641* -Dtest.clientAuth=false42* -Dtest.expectFail=true43* SigAlgosExtTestWithTLS1244* @run main/othervm45* -Djdk.tls.server.SignatureSchemes=ecdsa_secp256r1_sha25646* -Djdk.tls.client.SignatureSchemes=ecdsa_secp256r1_sha25647* -Dtest.clientAuth=true48* -Dtest.expectFail=true49* SigAlgosExtTestWithTLS1250*/5152import javax.net.ssl.*;53import java.nio.ByteBuffer;54import java.util.*;5556public class SigAlgosExtTestWithTLS12 extends SSLEngineTemplate {5758private static final boolean CLIENT_AUTH59= Boolean.getBoolean("test.clientAuth");60private static final boolean EXPECT_FAIL61= Boolean.getBoolean("test.expectFail");6263private static final String[] CA_CERTS = new String[] {64// SHA256withECDSA, curve secp256r165// Validity66// Not Before: May 22 07:18:16 2018 GMT67// Not After : May 17 07:18:16 2038 GMT68// Subject Key Identifier:69// 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:8670"-----BEGIN CERTIFICATE-----\n" +71"MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +72"AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +73"ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" +74"MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" +75"MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" +76"LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" +77"A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" +78"MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" +79"6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" +80"2YEHlSQUAbwwqCDEVB5KxaqP\n" +81"-----END CERTIFICATE-----",8283// SHA384withECDSA, curve secp384r184// Validity85// Not Before: Jun 24 08:15:06 2019 GMT86// Not After : Jun 19 08:15:06 2039 GMT87// Subject Key Identifier:88// 0a:93:a9:a0:bf:e7:d5:48:9d:4f:89:15:c6:51:98:80:05:51:4e:4e89"-----BEGIN CERTIFICATE-----\n" +90"MIICCDCCAY6gAwIBAgIUCpOpoL/n1UidT4kVxlGYgAVRTk4wCgYIKoZIzj0EAwMw\n" +91"OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" +92"VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowOzEL\n" +93"MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" +94"dCBTZXJpdmNlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENVQN1wXWFdgC6u/dDdiC\n" +95"y+WtMTF66oL/0BSm+1ZqsogamzCryawOcHgiuXgWzx5CQ3LuOC+tDFyXpGfHuCvb\n" +96"dkzxPrP5n9NrR8/uRPe5l1KOUbchviU8z9cTP+LZxnZDo1MwUTAdBgNVHQ4EFgQU\n" +97"SktSFArR1p/5mXV0kyo0RxIVa/UwHwYDVR0jBBgwFoAUSktSFArR1p/5mXV0kyo0\n" +98"RxIVa/UwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjBZvoNmq3/v\n" +99"RD2gBTyvxjS9h0rsMRLHDnvul/KWngytwGPTOBo0Y8ixQXSjdKoc3rkCMQDkiNgx\n" +100"IDxuHedmrLQKIPnVcthTmwv7//jHiqGoKofwChMo2a1P+DQdhszmeHD/ARQ=\n" +101"-----END CERTIFICATE-----"102};103104private static final String[] EE_CERTS = new String[] {105// SHA256withECDSA, curve secp256r1106// Validity107// Not Before: May 22 07:18:16 2018 GMT108// Not After : May 17 07:18:16 2038 GMT109// Authority Key Identifier:110// 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86111"-----BEGIN CERTIFICATE-----\n" +112"MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" +113"AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" +114"ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" +115"MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" +116"MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" +117"QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" +118"xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" +119"SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" +120"1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" +121"-----END CERTIFICATE-----",122123// SHA384withECDSA, curve secp384r1124// Validity125// Not Before: Jun 24 08:15:06 2019 GMT126// Not After : Jun 19 08:15:06 2039 GMT127// Authority Key Identifier:128// 40:2D:AA:EE:66:AA:33:27:AD:9B:5D:52:9B:60:67:6A:2B:AD:52:D2129"-----BEGIN CERTIFICATE-----\n" +130"MIICEjCCAZegAwIBAgIUS3F0AqAXWRg07CnbknJzxofyBQMwCgYIKoZIzj0EAwMw\n" +131"OzELMAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0Ug\n" +132"VGVzdCBTZXJpdmNlMB4XDTE5MDYyNDA4MTUwNloXDTM5MDYxOTA4MTUwNlowVTEL\n" +133"MAkGA1UEBhMCVVMxDTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVz\n" +134"dCBTZXJpdmNlMRgwFgYDVQQDDA9SZWdyZXNzaW9uIFRlc3QwdjAQBgcqhkjOPQIB\n" +135"BgUrgQQAIgNiAARqElz8b6T07eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/w\n" +136"G8ASSevpgqgpi6EzpBZaaJxE3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEj\n" +137"iLjYmt3O0pwpklijQjBAMB0GA1UdDgQWBBRALaruZqozJ62bXVKbYGdqK61S0jAf\n" +138"BgNVHSMEGDAWgBRKS1IUCtHWn/mZdXSTKjRHEhVr9TAKBggqhkjOPQQDAwNpADBm\n" +139"AjEArVDFKf48xijN6huVUJzKCOP0zlWB5Js+DItIkZmLQuhciPLhLIB/rChf3Y4C\n" +140"xuP4AjEAmfLhQRI0O3pifpYzYSVh2G7/jHNG4eO+2dvgAcU+Lh2IIj/cpLaPFSvL\n" +141"J8FXY9Nj\n" +142"-----END CERTIFICATE-----"143};144145private static final String[] EE_KEYS = new String[] {146"MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" +147"JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" +148"59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6",149"MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDASuI9EtK29APXPipkc\n" +150"qDA+qwlewMjv/OcjUJ77kP1Vz62oVF9iY9SRIyFIUju8wt+hZANiAARqElz8b6T0\n" +151"7eyKomIinhztV3/3XBk9bKGtJ0W+JOltjuhMmP/wG8ASSevpgqgpi6EzpBZaaJxE\n" +152"3zNfkNnxXOZmQi2Ypd1uK0zRdbEOKg0XOcTTZwEjiLjYmt3O0pwpklg="153};154155private static final String[] EE_ALGS = new String[] {156"EC",157"EC"158};159160private static final String[] EE_ALIASES = new String[] {161"EC-SHA256",162"EC-SHA384"163};164165private static final Map<Integer, String> SIG_SCHEMES_MAP = Map.of(1660x0403, "ecdsa_secp256r1_sha256",1670x0503, "ecdsa_secp384r1_sha384");168169private static final int TLS_HS_CLI_HELLO = 1;170private static final int TLS_HS_CERT_REQ = 13;171private static final int HELLO_EXT_SIG_ALGS = 13;172173public SigAlgosExtTestWithTLS12() throws Exception {174super();175}176177/*178* Create an instance of KeyManager for client use.179*/180public KeyManager createClientKeyManager() throws Exception {181return SSLContextTemplate.createKeyManager(182EE_CERTS,183EE_KEYS,184EE_ALGS,185EE_ALIASES,186getServerContextParameters());187}188189@Override190public TrustManager createClientTrustManager() throws Exception {191return SSLContextTemplate.createTrustManager(192CA_CERTS,193getServerContextParameters());194}195196@Override197public KeyManager createServerKeyManager() throws Exception {198return SSLContextTemplate.createKeyManager(199EE_CERTS,200EE_KEYS,201EE_ALGS,202EE_ALIASES,203getServerContextParameters());204}205206@Override207public TrustManager createServerTrustManager() throws Exception {208return SSLContextTemplate.createTrustManager(209CA_CERTS,210getServerContextParameters());211}212213@Override214protected SSLEngine configureServerEngine(SSLEngine serverEngine) {215serverEngine.setUseClientMode(false);216serverEngine.setNeedClientAuth(CLIENT_AUTH);217return serverEngine;218}219220@Override221protected SSLEngine configureClientEngine(SSLEngine clientEngine) {222clientEngine.setUseClientMode(true);223clientEngine.setEnabledProtocols(new String[] { "TLSv1.2" });224return clientEngine;225}226227public static void main(String[] args) throws Exception {228System.setProperty("javax.net.debug", "ssl:handshake");229230try {231new SigAlgosExtTestWithTLS12().run();232if (EXPECT_FAIL) {233throw new RuntimeException(234"Expected SSLHandshakeException wasn't thrown");235}236} catch (SSLHandshakeException e) {237if (EXPECT_FAIL && e.getMessage().equals(238"No supported signature algorithm")) {239System.out.println("Expected SSLHandshakeException");240} else {241throw e;242}243}244}245246private void run() throws Exception {247boolean dataDone = false;248while (isOpen(clientEngine) || isOpen(serverEngine)) {249clientEngine.wrap(clientOut, cTOs);250cTOs.flip();251252// Consume the ClientHello and get the server flight of handshake253// messages. We expect that it will be one TLS record containing254// multiple handshake messages, one of which is a CertificateRequest255// when the client authentication is required.256serverEngine.unwrap(cTOs, serverIn);257runDelegatedTasks(serverEngine);258259// Wrap the server flight260serverEngine.wrap(serverOut, sTOc);261sTOc.flip();262263if (CLIENT_AUTH && EXPECT_FAIL) {264twistCertReqMsg(sTOc);265}266267clientEngine.unwrap(sTOc, clientIn);268runDelegatedTasks(clientEngine);269270serverEngine.unwrap(cTOs, serverIn);271runDelegatedTasks(serverEngine);272273cTOs.compact();274sTOc.compact();275276if (!dataDone && (clientOut.limit() == serverIn.position()) &&277(serverOut.limit() == clientIn.position())) {278checkTransfer(serverOut, clientIn);279checkTransfer(clientOut, serverIn);280281clientEngine.closeOutbound();282dataDone = true;283serverEngine.closeOutbound();284}285}286}287288/**289* Twists signature schemes in CertificateRequest message for negative290* client authentication cases.291*292* @param tlsRecord a ByteBuffer containing a TLS record. It is assumed293* that the position of the ByteBuffer is on the first byte of the TLS294* record header.295*296* @throws SSLException if the incoming ByteBuffer does not contain a297* well-formed TLS message.298*/299private static void twistCertReqMsg(300ByteBuffer tlsRecord) throws SSLException {301Objects.requireNonNull(tlsRecord);302tlsRecord.mark();303304// Process the TLS record header305int type = Byte.toUnsignedInt(tlsRecord.get());306int ver_major = Byte.toUnsignedInt(tlsRecord.get());307int ver_minor = Byte.toUnsignedInt(tlsRecord.get());308int recLen = Short.toUnsignedInt(tlsRecord.getShort());309310// Simple sanity checks311if (type != 22) {312throw new SSLException("Not a handshake: Type = " + type);313} else if (recLen > tlsRecord.remaining()) {314throw new SSLException("Incomplete record in buffer: " +315"Record length = " + recLen + ", Remaining = " +316tlsRecord.remaining());317}318319while (tlsRecord.hasRemaining()) {320// Grab the handshake message header.321int msgHdr = tlsRecord.getInt();322int msgType = (msgHdr >> 24) & 0x000000FF;323int msgLen = msgHdr & 0x00FFFFFF;324325if (msgType == TLS_HS_CERT_REQ) {326// Slice the buffer such that it contains the entire327// handshake message (less the handshake header).328int bufPos = tlsRecord.position();329ByteBuffer buf = tlsRecord.slice(bufPos, msgLen);330331// Replace the signature scheme with an unknown value332twistSigSchemesCertReq(buf, (short) 0x0000);333byte[] bufBytes = new byte[buf.limit()];334buf.get(bufBytes);335tlsRecord.put(bufPos, bufBytes);336337break;338} else {339// Skip to the next handshake message, if there is one340tlsRecord.position(tlsRecord.position() + msgLen);341}342}343344tlsRecord.reset();345}346347/**348* Replace the signature schemes in CertificateRequest message with an349* alternative value. It is assumed that the provided ByteBuffer has its350* position set at the first byte of the CertificateRequest message body351* (AFTER the handshake header) and contains the entire CR message. Upon352* successful completion of this method the ByteBuffer will have its353* position reset to the initial offset in the buffer.354* If an exception is thrown the position at the time of the exception355* will be preserved.356*357* @param data the ByteBuffer containing the CertificateRequest bytes358* @param altSigScheme an alternative signature scheme359*/360private static void twistSigSchemesCertReq(ByteBuffer data,361Short altSigScheme) {362Objects.requireNonNull(data);363data.mark();364365// Jump past the certificate types366int certTypeLen = Byte.toUnsignedInt(data.get());367if (certTypeLen != 0) {368data.position(data.position() + certTypeLen);369}370371int sigSchemeLen = Short.toUnsignedInt(data.getShort());372for (int ssOff = 0; ssOff < sigSchemeLen; ssOff += 2) {373System.err.println(374"Use alternative signature scheme: " + altSigScheme);375data.putShort(data.position(), altSigScheme);376}377378data.reset();379}380}381382383