src/java.base/share/classes/sun/security/ssl/CertificateRequest.java
changeset 50768 68fa3d4026ea
child 52153 3b17277860e7
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
       
     1 /*
       
     2  * Copyright (c) 2015, 2018, 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.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 package sun.security.ssl;
       
    27 
       
    28 import java.io.IOException;
       
    29 import java.nio.ByteBuffer;
       
    30 import java.security.PrivateKey;
       
    31 import java.security.cert.X509Certificate;
       
    32 import java.text.MessageFormat;
       
    33 import java.util.ArrayList;
       
    34 import java.util.Collections;
       
    35 import java.util.LinkedList;
       
    36 import java.util.List;
       
    37 import java.util.Locale;
       
    38 import javax.net.ssl.SSLEngine;
       
    39 import javax.net.ssl.SSLSocket;
       
    40 import javax.net.ssl.X509ExtendedKeyManager;
       
    41 import javax.security.auth.x500.X500Principal;
       
    42 import sun.security.ssl.CipherSuite.KeyExchange;
       
    43 import sun.security.ssl.SSLHandshake.HandshakeMessage;
       
    44 import sun.security.ssl.X509Authentication.X509Possession;
       
    45 
       
    46 /**
       
    47  * Pack of the CertificateRequest handshake message.
       
    48  */
       
    49 final class CertificateRequest {
       
    50     static final SSLConsumer t10HandshakeConsumer =
       
    51         new T10CertificateRequestConsumer();
       
    52     static final HandshakeProducer t10HandshakeProducer =
       
    53         new T10CertificateRequestProducer();
       
    54 
       
    55     static final SSLConsumer t12HandshakeConsumer =
       
    56         new T12CertificateRequestConsumer();
       
    57     static final HandshakeProducer t12HandshakeProducer =
       
    58         new T12CertificateRequestProducer();
       
    59 
       
    60     static final SSLConsumer t13HandshakeConsumer =
       
    61         new T13CertificateRequestConsumer();
       
    62     static final HandshakeProducer t13HandshakeProducer =
       
    63         new T13CertificateRequestProducer();
       
    64 
       
    65     // TLS 1.2 and prior versions
       
    66     private static enum ClientCertificateType {
       
    67         // RFC 2246
       
    68         RSA_SIGN            ((byte)0x01, "rsa_sign", "RSA", true),
       
    69         DSS_SIGN            ((byte)0x02, "dss_sign", "DSA", true),
       
    70         RSA_FIXED_DH        ((byte)0x03, "rsa_fixed_dh"),
       
    71         DSS_FIXED_DH        ((byte)0x04, "dss_fixed_dh"),
       
    72 
       
    73         // RFC 4346
       
    74         RSA_EPHEMERAL_DH    ((byte)0x05, "rsa_ephemeral_dh"),
       
    75         DSS_EPHEMERAL_DH    ((byte)0x06, "dss_ephemeral_dh"),
       
    76         FORTEZZA_DMS        ((byte)0x14, "fortezza_dms"),
       
    77 
       
    78         // RFC 4492
       
    79         ECDSA_SIGN          ((byte)0x40, "ecdsa_sign",
       
    80                                              "EC", JsseJce.isEcAvailable()),
       
    81         RSA_FIXED_ECDH      ((byte)0x41, "rsa_fixed_ecdh"),
       
    82         ECDSA_FIXED_ECDH    ((byte)0x42, "ecdsa_fixed_ecdh");
       
    83 
       
    84         private static final byte[] CERT_TYPES =
       
    85                 JsseJce.isEcAvailable() ? new byte[] {
       
    86                         ECDSA_SIGN.id,
       
    87                         RSA_SIGN.id,
       
    88                         DSS_SIGN.id
       
    89                     } :  new byte[] {
       
    90                         RSA_SIGN.id,
       
    91                         DSS_SIGN.id
       
    92                     };
       
    93 
       
    94         final byte id;
       
    95         final String name;
       
    96         final String keyAlgorithm;
       
    97         final boolean isAvailable;
       
    98 
       
    99         private ClientCertificateType(byte id, String name) {
       
   100             this(id, name, null, false);
       
   101         }
       
   102 
       
   103         private ClientCertificateType(byte id, String name,
       
   104                 String keyAlgorithm, boolean isAvailable) {
       
   105             this.id = id;
       
   106             this.name = name;
       
   107             this.keyAlgorithm = keyAlgorithm;
       
   108             this.isAvailable = isAvailable;
       
   109         }
       
   110 
       
   111         private static String nameOf(byte id) {
       
   112             for (ClientCertificateType cct : ClientCertificateType.values()) {
       
   113                 if (cct.id == id) {
       
   114                     return cct.name;
       
   115                 }
       
   116             }
       
   117             return "UNDEFINED-CLIENT-CERTIFICATE-TYPE(" + (int)id + ")";
       
   118         }
       
   119 
       
   120         private static ClientCertificateType valueOf(byte id) {
       
   121             for (ClientCertificateType cct : ClientCertificateType.values()) {
       
   122                 if (cct.id == id) {
       
   123                     return cct;
       
   124                 }
       
   125             }
       
   126 
       
   127             return null;
       
   128         }
       
   129 
       
   130         private static String[] getKeyTypes(byte[] ids) {
       
   131             ArrayList<String> keyTypes = new ArrayList<>(3);
       
   132             for (byte id : ids) {
       
   133                 ClientCertificateType cct = ClientCertificateType.valueOf(id);
       
   134                 if (cct.isAvailable) {
       
   135                     keyTypes.add(cct.keyAlgorithm);
       
   136                 }
       
   137             }
       
   138 
       
   139             return keyTypes.toArray(new String[0]);
       
   140         }
       
   141     }
       
   142 
       
   143     /**
       
   144      * The "CertificateRequest" handshake message for SSL 3.0 and TLS 1.0/1.1.
       
   145      */
       
   146     static final class T10CertificateRequestMessage extends HandshakeMessage {
       
   147         final byte[] types;                 // certificate types
       
   148         final List<byte[]> authorities;     // certificate authorities
       
   149 
       
   150         T10CertificateRequestMessage(HandshakeContext handshakeContext,
       
   151                 X509Certificate[] trustedCerts, KeyExchange keyExchange) {
       
   152             super(handshakeContext);
       
   153 
       
   154             this.authorities = new ArrayList<>(trustedCerts.length);
       
   155             for (X509Certificate cert : trustedCerts) {
       
   156                 X500Principal x500Principal = cert.getSubjectX500Principal();
       
   157                 authorities.add(x500Principal.getEncoded());
       
   158             }
       
   159 
       
   160             this.types = ClientCertificateType.CERT_TYPES;
       
   161         }
       
   162 
       
   163         T10CertificateRequestMessage(HandshakeContext handshakeContext,
       
   164                 ByteBuffer m) throws IOException {
       
   165             super(handshakeContext);
       
   166 
       
   167             // struct {
       
   168             //     ClientCertificateType certificate_types<1..2^8-1>;
       
   169             //     DistinguishedName certificate_authorities<0..2^16-1>;
       
   170             // } CertificateRequest;
       
   171             if (m.remaining() < 4) {
       
   172                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   173                     "Incorrect CertificateRequest message: no sufficient data");
       
   174             }
       
   175             this.types = Record.getBytes8(m);
       
   176 
       
   177             int listLen = Record.getInt16(m);
       
   178             if (listLen > m.remaining()) {
       
   179                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   180                     "Incorrect CertificateRequest message:no sufficient data");
       
   181             }
       
   182 
       
   183             if (listLen > 0) {
       
   184                 this.authorities = new LinkedList<>();
       
   185                 while (listLen > 0) {
       
   186                     // opaque DistinguishedName<1..2^16-1>;
       
   187                     byte[] encoded = Record.getBytes16(m);
       
   188                     listLen -= (2 + encoded.length);
       
   189                     authorities.add(encoded);
       
   190                 }
       
   191             } else {
       
   192                 this.authorities = Collections.emptyList();
       
   193             }
       
   194         }
       
   195 
       
   196         String[] getKeyTypes() {
       
   197             return  ClientCertificateType.getKeyTypes(types);
       
   198         }
       
   199 
       
   200         X500Principal[] getAuthorities() {
       
   201             List<X500Principal> principals =
       
   202                     new ArrayList<>(authorities.size());
       
   203             for (byte[] encoded : authorities) {
       
   204                 X500Principal principal = new X500Principal(encoded);
       
   205                 principals.add(principal);
       
   206             }
       
   207 
       
   208             return principals.toArray(new X500Principal[0]);
       
   209         }
       
   210 
       
   211         @Override
       
   212         public SSLHandshake handshakeType() {
       
   213             return SSLHandshake.CERTIFICATE_REQUEST;
       
   214         }
       
   215 
       
   216         @Override
       
   217         public int messageLength() {
       
   218             int len = 1 + types.length + 2;
       
   219             for (byte[] encoded : authorities) {
       
   220                 len += encoded.length + 2;
       
   221             }
       
   222             return len;
       
   223         }
       
   224 
       
   225         @Override
       
   226         public void send(HandshakeOutStream hos) throws IOException {
       
   227             hos.putBytes8(types);
       
   228 
       
   229             int listLen = 0;
       
   230             for (byte[] encoded : authorities) {
       
   231                 listLen += encoded.length + 2;
       
   232             }
       
   233 
       
   234             hos.putInt16(listLen);
       
   235             for (byte[] encoded : authorities) {
       
   236                 hos.putBytes16(encoded);
       
   237             }
       
   238         }
       
   239 
       
   240         @Override
       
   241         public String toString() {
       
   242             MessageFormat messageFormat = new MessageFormat(
       
   243                     "\"CertificateRequest\": '{'\n" +
       
   244                     "  \"certificate types\": {0}\n" +
       
   245                     "  \"certificate authorities\": {1}\n" +
       
   246                     "'}'",
       
   247                     Locale.ENGLISH);
       
   248 
       
   249             List<String> typeNames = new ArrayList<>(types.length);
       
   250             for (byte type : types) {
       
   251                 typeNames.add(ClientCertificateType.nameOf(type));
       
   252             }
       
   253 
       
   254             List<String> authorityNames = new ArrayList<>(authorities.size());
       
   255             for (byte[] encoded : authorities) {
       
   256                 X500Principal principal = new X500Principal(encoded);
       
   257                 authorityNames.add(principal.toString());
       
   258             }
       
   259             Object[] messageFields = {
       
   260                 typeNames,
       
   261                 authorityNames
       
   262             };
       
   263 
       
   264             return messageFormat.format(messageFields);
       
   265         }
       
   266     }
       
   267 
       
   268     /**
       
   269      * The "CertificateRequest" handshake message producer for SSL 3.0 and
       
   270      * TLS 1.0/1.1.
       
   271      */
       
   272     private static final
       
   273             class T10CertificateRequestProducer implements HandshakeProducer {
       
   274         // Prevent instantiation of this class.
       
   275         private T10CertificateRequestProducer() {
       
   276             // blank
       
   277         }
       
   278 
       
   279         @Override
       
   280         public byte[] produce(ConnectionContext context,
       
   281                 HandshakeMessage message) throws IOException {
       
   282             // The producing happens in server side only.
       
   283             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   284 
       
   285             X509Certificate[] caCerts =
       
   286                     shc.sslContext.getX509TrustManager().getAcceptedIssuers();
       
   287             T10CertificateRequestMessage crm = new T10CertificateRequestMessage(
       
   288                     shc, caCerts, shc.negotiatedCipherSuite.keyExchange);
       
   289             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   290                 SSLLogger.fine(
       
   291                     "Produced CertificateRequest handshake message", crm);
       
   292             }
       
   293 
       
   294             // Output the handshake message.
       
   295             crm.write(shc.handshakeOutput);
       
   296             shc.handshakeOutput.flush();
       
   297 
       
   298             //
       
   299             // update
       
   300             //
       
   301             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,
       
   302                     SSLHandshake.CERTIFICATE);
       
   303             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
       
   304                     SSLHandshake.CERTIFICATE_VERIFY);
       
   305 
       
   306             // The handshake message has been delivered.
       
   307             return null;
       
   308         }
       
   309     }
       
   310 
       
   311     /**
       
   312      * The "CertificateRequest" handshake message consumer for SSL 3.0 and
       
   313      * TLS 1.0/1.1.
       
   314      */
       
   315     private static final
       
   316             class T10CertificateRequestConsumer implements SSLConsumer {
       
   317         // Prevent instantiation of this class.
       
   318         private T10CertificateRequestConsumer() {
       
   319             // blank
       
   320         }
       
   321 
       
   322         @Override
       
   323         public void consume(ConnectionContext context,
       
   324                 ByteBuffer message) throws IOException {
       
   325             // The consuming happens in client side only.
       
   326             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   327 
       
   328             // clean up this consumer
       
   329             chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);
       
   330 
       
   331             T10CertificateRequestMessage crm =
       
   332                     new T10CertificateRequestMessage(chc, message);
       
   333             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   334                 SSLLogger.fine(
       
   335                         "Consuming CertificateRequest handshake message", crm);
       
   336             }
       
   337 
       
   338             //
       
   339             // validate
       
   340             //
       
   341             // blank
       
   342 
       
   343             //
       
   344             // update
       
   345             //
       
   346 
       
   347             // An empty client Certificate handshake message may be allow.
       
   348             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,
       
   349                     SSLHandshake.CERTIFICATE);
       
   350 
       
   351             X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
       
   352             String clientAlias = null;
       
   353             if (chc.conContext.transport instanceof SSLSocketImpl) {
       
   354                 clientAlias = km.chooseClientAlias(crm.getKeyTypes(),
       
   355                     crm.getAuthorities(), (SSLSocket)chc.conContext.transport);
       
   356             } else if (chc.conContext.transport instanceof SSLEngineImpl) {
       
   357                 clientAlias = km.chooseEngineClientAlias(crm.getKeyTypes(),
       
   358                     crm.getAuthorities(), (SSLEngine)chc.conContext.transport);
       
   359             }
       
   360 
       
   361 
       
   362             if (clientAlias == null) {
       
   363                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   364                     SSLLogger.warning("No available client authentication");
       
   365                 }
       
   366                 return;
       
   367             }
       
   368 
       
   369             PrivateKey clientPrivateKey = km.getPrivateKey(clientAlias);
       
   370             if (clientPrivateKey == null) {
       
   371                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   372                     SSLLogger.warning("No available client private key");
       
   373                 }
       
   374                 return;
       
   375             }
       
   376 
       
   377             X509Certificate[] clientCerts = km.getCertificateChain(clientAlias);
       
   378             if ((clientCerts == null) || (clientCerts.length == 0)) {
       
   379                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   380                     SSLLogger.warning("No available client certificate");
       
   381                 }
       
   382                 return;
       
   383             }
       
   384 
       
   385             chc.handshakePossessions.add(
       
   386                     new X509Possession(clientPrivateKey, clientCerts));
       
   387             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
       
   388                     SSLHandshake.CERTIFICATE_VERIFY);
       
   389         }
       
   390     }
       
   391 
       
   392     /**
       
   393      * The CertificateRequest handshake message for TLS 1.2.
       
   394      */
       
   395     static final class T12CertificateRequestMessage extends HandshakeMessage {
       
   396         final byte[] types;                 // certificate types
       
   397         final int[] algorithmIds;           // supported signature algorithms
       
   398         final List<byte[]> authorities;     // certificate authorities
       
   399 
       
   400         T12CertificateRequestMessage(HandshakeContext handshakeContext,
       
   401                 X509Certificate[] trustedCerts, KeyExchange keyExchange,
       
   402                 List<SignatureScheme> signatureSchemes) throws IOException {
       
   403             super(handshakeContext);
       
   404 
       
   405             this.types = ClientCertificateType.CERT_TYPES;
       
   406 
       
   407             if (signatureSchemes == null || signatureSchemes.isEmpty()) {
       
   408                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   409                         "No signature algorithms specified for " +
       
   410                         "CertificateRequest hanshake message");
       
   411             }
       
   412             this.algorithmIds = new int[signatureSchemes.size()];
       
   413             int i = 0;
       
   414             for (SignatureScheme scheme : signatureSchemes) {
       
   415                 algorithmIds[i++] = scheme.id;
       
   416             }
       
   417 
       
   418             this.authorities = new ArrayList<>(trustedCerts.length);
       
   419             for (X509Certificate cert : trustedCerts) {
       
   420                 X500Principal x500Principal = cert.getSubjectX500Principal();
       
   421                 authorities.add(x500Principal.getEncoded());
       
   422             }
       
   423         }
       
   424 
       
   425         T12CertificateRequestMessage(HandshakeContext handshakeContext,
       
   426                 ByteBuffer m) throws IOException {
       
   427             super(handshakeContext);
       
   428 
       
   429             // struct {
       
   430             //     ClientCertificateType certificate_types<1..2^8-1>;
       
   431             //     SignatureAndHashAlgorithm
       
   432             //       supported_signature_algorithms<2..2^16-2>;
       
   433             //     DistinguishedName certificate_authorities<0..2^16-1>;
       
   434             // } CertificateRequest;
       
   435 
       
   436             // certificate_authorities
       
   437             if (m.remaining() < 8) {
       
   438                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   439                         "Invalid CertificateRequest handshake message: " +
       
   440                         "no sufficient data");
       
   441             }
       
   442             this.types = Record.getBytes8(m);
       
   443 
       
   444             // supported_signature_algorithms
       
   445             if (m.remaining() < 6) {
       
   446                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   447                         "Invalid CertificateRequest handshake message: " +
       
   448                         "no sufficient data");
       
   449             }
       
   450 
       
   451             byte[] algs = Record.getBytes16(m);
       
   452             if (algs == null || algs.length == 0 || (algs.length & 0x01) != 0) {
       
   453                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   454                         "Invalid CertificateRequest handshake message: " +
       
   455                         "incomplete signature algorithms");
       
   456             }
       
   457 
       
   458             this.algorithmIds = new int[(algs.length >> 1)];
       
   459             for (int i = 0, j = 0; i < algs.length;) {
       
   460                 byte hash = algs[i++];
       
   461                 byte sign = algs[i++];
       
   462                 algorithmIds[j++] = ((hash & 0xFF) << 8) | (sign & 0xFF);
       
   463             }
       
   464 
       
   465             // certificate_authorities
       
   466             if (m.remaining() < 2) {
       
   467                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   468                         "Invalid CertificateRequest handshake message: " +
       
   469                         "no sufficient data");
       
   470             }
       
   471 
       
   472             int listLen = Record.getInt16(m);
       
   473             if (listLen > m.remaining()) {
       
   474                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   475                     "Invalid CertificateRequest message: no sufficient data");
       
   476             }
       
   477 
       
   478             if (listLen > 0) {
       
   479                 this.authorities = new LinkedList<>();
       
   480                 while (listLen > 0) {
       
   481                     // opaque DistinguishedName<1..2^16-1>;
       
   482                     byte[] encoded = Record.getBytes16(m);
       
   483                     listLen -= (2 + encoded.length);
       
   484                     authorities.add(encoded);
       
   485                 }
       
   486             } else {
       
   487                 this.authorities = Collections.emptyList();
       
   488             }
       
   489         }
       
   490 
       
   491         String[] getKeyTypes() {
       
   492             return ClientCertificateType.getKeyTypes(types);
       
   493         }
       
   494 
       
   495         X500Principal[] getAuthorities() {
       
   496             List<X500Principal> principals =
       
   497                     new ArrayList<>(authorities.size());
       
   498             for (byte[] encoded : authorities) {
       
   499                 X500Principal principal = new X500Principal(encoded);
       
   500                 principals.add(principal);
       
   501             }
       
   502 
       
   503             return principals.toArray(new X500Principal[0]);
       
   504         }
       
   505 
       
   506         @Override
       
   507         public SSLHandshake handshakeType() {
       
   508             return SSLHandshake.CERTIFICATE_REQUEST;
       
   509         }
       
   510 
       
   511         @Override
       
   512         public int messageLength() {
       
   513             int len = 1 + types.length + 2 + (algorithmIds.length << 1) + 2;
       
   514             for (byte[] encoded : authorities) {
       
   515                 len += encoded.length + 2;
       
   516             }
       
   517             return len;
       
   518         }
       
   519 
       
   520         @Override
       
   521         public void send(HandshakeOutStream hos) throws IOException {
       
   522             hos.putBytes8(types);
       
   523 
       
   524             int listLen = 0;
       
   525             for (byte[] encoded : authorities) {
       
   526                 listLen += encoded.length + 2;
       
   527             }
       
   528 
       
   529             hos.putInt16(algorithmIds.length << 1);
       
   530             for (int algorithmId : algorithmIds) {
       
   531                 hos.putInt16(algorithmId);
       
   532             }
       
   533 
       
   534             hos.putInt16(listLen);
       
   535             for (byte[] encoded : authorities) {
       
   536                 hos.putBytes16(encoded);
       
   537             }
       
   538         }
       
   539 
       
   540         @Override
       
   541         public String toString() {
       
   542             MessageFormat messageFormat = new MessageFormat(
       
   543                     "\"CertificateRequest\": '{'\n" +
       
   544                     "  \"certificate types\": {0}\n" +
       
   545                     "  \"supported signature algorithms\": {1}\n" +
       
   546                     "  \"certificate authorities\": {2}\n" +
       
   547                     "'}'",
       
   548                     Locale.ENGLISH);
       
   549 
       
   550             List<String> typeNames = new ArrayList<>(types.length);
       
   551             for (byte type : types) {
       
   552                 typeNames.add(ClientCertificateType.nameOf(type));
       
   553             }
       
   554 
       
   555             List<String> algorithmNames = new ArrayList<>(algorithmIds.length);
       
   556             for (int algorithmId : algorithmIds) {
       
   557                 algorithmNames.add(SignatureScheme.nameOf(algorithmId));
       
   558             }
       
   559 
       
   560             List<String> authorityNames = new ArrayList<>(authorities.size());
       
   561             for (byte[] encoded : authorities) {
       
   562                 X500Principal principal = new X500Principal(encoded);
       
   563                 authorityNames.add(principal.toString());
       
   564             }
       
   565             Object[] messageFields = {
       
   566                 typeNames,
       
   567                 algorithmNames,
       
   568                 authorityNames
       
   569             };
       
   570 
       
   571             return messageFormat.format(messageFields);
       
   572         }
       
   573     }
       
   574 
       
   575     /**
       
   576      * The "CertificateRequest" handshake message producer for TLS 1.2.
       
   577      */
       
   578     private static final
       
   579             class T12CertificateRequestProducer implements HandshakeProducer {
       
   580         // Prevent instantiation of this class.
       
   581         private T12CertificateRequestProducer() {
       
   582             // blank
       
   583         }
       
   584 
       
   585         @Override
       
   586         public byte[] produce(ConnectionContext context,
       
   587                 HandshakeMessage message) throws IOException {
       
   588             // The producing happens in server side only.
       
   589             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   590             if (shc.localSupportedSignAlgs == null) {
       
   591                 shc.localSupportedSignAlgs =
       
   592                     SignatureScheme.getSupportedAlgorithms(
       
   593                             shc.algorithmConstraints, shc.activeProtocols);
       
   594             }
       
   595 
       
   596             if (shc.localSupportedSignAlgs == null ||
       
   597                     shc.localSupportedSignAlgs.isEmpty()) {
       
   598                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   599                     "No supported signature algorithm");
       
   600             }
       
   601 
       
   602             X509Certificate[] caCerts =
       
   603                     shc.sslContext.getX509TrustManager().getAcceptedIssuers();
       
   604             T12CertificateRequestMessage crm = new T12CertificateRequestMessage(
       
   605                     shc, caCerts, shc.negotiatedCipherSuite.keyExchange,
       
   606                     shc.localSupportedSignAlgs);
       
   607             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   608                 SSLLogger.fine(
       
   609                     "Produced CertificateRequest handshake message", crm);
       
   610             }
       
   611 
       
   612             // Output the handshake message.
       
   613             crm.write(shc.handshakeOutput);
       
   614             shc.handshakeOutput.flush();
       
   615 
       
   616             //
       
   617             // update
       
   618             //
       
   619             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,
       
   620                     SSLHandshake.CERTIFICATE);
       
   621             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
       
   622                     SSLHandshake.CERTIFICATE_VERIFY);
       
   623 
       
   624             // The handshake message has been delivered.
       
   625             return null;
       
   626         }
       
   627     }
       
   628 
       
   629     /**
       
   630      * The "CertificateRequest" handshake message consumer for TLS 1.2.
       
   631      */
       
   632     private static final
       
   633             class T12CertificateRequestConsumer implements SSLConsumer {
       
   634         // Prevent instantiation of this class.
       
   635         private T12CertificateRequestConsumer() {
       
   636             // blank
       
   637         }
       
   638 
       
   639         @Override
       
   640         public void consume(ConnectionContext context,
       
   641                 ByteBuffer message) throws IOException {
       
   642             // The consuming happens in client side only.
       
   643             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   644 
       
   645             // clean up this consumer
       
   646             chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);
       
   647 
       
   648             T12CertificateRequestMessage crm =
       
   649                     new T12CertificateRequestMessage(chc, message);
       
   650             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   651                 SSLLogger.fine(
       
   652                         "Consuming CertificateRequest handshake message", crm);
       
   653             }
       
   654 
       
   655             //
       
   656             // validate
       
   657             //
       
   658             // blank
       
   659 
       
   660             //
       
   661             // update
       
   662             //
       
   663 
       
   664             // An empty client Certificate handshake message may be allow.
       
   665             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,
       
   666                     SSLHandshake.CERTIFICATE);
       
   667 
       
   668             List<SignatureScheme> sss = new LinkedList<>();
       
   669             for (int id : crm.algorithmIds) {
       
   670                 SignatureScheme ss = SignatureScheme.valueOf(id);
       
   671                 if (ss != null) {
       
   672                     sss.add(ss);
       
   673                 }
       
   674             }
       
   675             chc.peerRequestedSignatureSchemes = sss;
       
   676             chc.peerRequestedCertSignSchemes = sss;     // use the same schemes
       
   677             chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss);
       
   678 
       
   679             X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
       
   680             String clientAlias = null;
       
   681             if (chc.conContext.transport instanceof SSLSocketImpl) {
       
   682                 clientAlias = km.chooseClientAlias(crm.getKeyTypes(),
       
   683                     crm.getAuthorities(), (SSLSocket)chc.conContext.transport);
       
   684             } else if (chc.conContext.transport instanceof SSLEngineImpl) {
       
   685                 clientAlias = km.chooseEngineClientAlias(crm.getKeyTypes(),
       
   686                     crm.getAuthorities(), (SSLEngine)chc.conContext.transport);
       
   687             }
       
   688 
       
   689             if (clientAlias == null) {
       
   690                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   691                     SSLLogger.warning("No available client authentication");
       
   692                 }
       
   693                 return;
       
   694             }
       
   695 
       
   696             PrivateKey clientPrivateKey = km.getPrivateKey(clientAlias);
       
   697             if (clientPrivateKey == null) {
       
   698                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   699                     SSLLogger.warning("No available client private key");
       
   700                 }
       
   701                 return;
       
   702             }
       
   703 
       
   704             X509Certificate[] clientCerts = km.getCertificateChain(clientAlias);
       
   705             if ((clientCerts == null) || (clientCerts.length == 0)) {
       
   706                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   707                     SSLLogger.warning("No available client certificate");
       
   708                 }
       
   709                 return;
       
   710             }
       
   711 
       
   712             chc.handshakePossessions.add(
       
   713                     new X509Possession(clientPrivateKey, clientCerts));
       
   714             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
       
   715                     SSLHandshake.CERTIFICATE_VERIFY);
       
   716         }
       
   717     }
       
   718 
       
   719     /**
       
   720      * The CertificateRequest handshake message for TLS 1.3.
       
   721      */
       
   722     static final class T13CertificateRequestMessage extends HandshakeMessage {
       
   723         private final byte[] requestContext;
       
   724         private final SSLExtensions extensions;
       
   725 
       
   726         T13CertificateRequestMessage(
       
   727                 HandshakeContext handshakeContext) throws IOException {
       
   728             super(handshakeContext);
       
   729 
       
   730             this.requestContext = new byte[0];
       
   731             this.extensions = new SSLExtensions(this);
       
   732         }
       
   733 
       
   734         T13CertificateRequestMessage(HandshakeContext handshakeContext,
       
   735                 ByteBuffer m) throws IOException {
       
   736             super(handshakeContext);
       
   737 
       
   738             // struct {
       
   739             //      opaque certificate_request_context<0..2^8-1>;
       
   740             //      Extension extensions<2..2^16-1>;
       
   741             //  } CertificateRequest;
       
   742             if (m.remaining() < 5) {
       
   743                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   744                         "Invalid CertificateRequest handshake message: " +
       
   745                         "no sufficient data");
       
   746             }
       
   747             this.requestContext = Record.getBytes8(m);
       
   748 
       
   749             if (m.remaining() < 4) {
       
   750                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
       
   751                         "Invalid CertificateRequest handshake message: " +
       
   752                         "no sufficient extensions data");
       
   753             }
       
   754             SSLExtension[] enabledExtensions =
       
   755                 handshakeContext.sslConfig.getEnabledExtensions(
       
   756                         SSLHandshake.CERTIFICATE_REQUEST);
       
   757             this.extensions = new SSLExtensions(this, m, enabledExtensions);
       
   758         }
       
   759 
       
   760         @Override
       
   761         SSLHandshake handshakeType() {
       
   762             return SSLHandshake.CERTIFICATE_REQUEST;
       
   763         }
       
   764 
       
   765         @Override
       
   766         int messageLength() {
       
   767             // In TLS 1.3, use of certain extensions is mandatory.
       
   768             return 1 + requestContext.length + extensions.length();
       
   769         }
       
   770 
       
   771         @Override
       
   772         void send(HandshakeOutStream hos) throws IOException {
       
   773             hos.putBytes8(requestContext);
       
   774 
       
   775             // In TLS 1.3, use of certain extensions is mandatory.
       
   776             extensions.send(hos);
       
   777         }
       
   778 
       
   779         @Override
       
   780         public String toString() {
       
   781             MessageFormat messageFormat = new MessageFormat(
       
   782                 "\"CertificateRequest\": '{'\n" +
       
   783                 "  \"certificate_request_context\": \"{0}\",\n" +
       
   784                 "  \"extensions\": [\n" +
       
   785                 "{1}\n" +
       
   786                 "  ]\n" +
       
   787                 "'}'",
       
   788                 Locale.ENGLISH);
       
   789             Object[] messageFields = {
       
   790                 Utilities.toHexString(requestContext),
       
   791                 Utilities.indent(Utilities.indent(extensions.toString()))
       
   792             };
       
   793 
       
   794             return messageFormat.format(messageFields);
       
   795         }
       
   796     }
       
   797 
       
   798     /**
       
   799      * The "CertificateRequest" handshake message producer for TLS 1.3.
       
   800      */
       
   801     private static final
       
   802             class T13CertificateRequestProducer implements HandshakeProducer {
       
   803         // Prevent instantiation of this class.
       
   804         private T13CertificateRequestProducer() {
       
   805             // blank
       
   806         }
       
   807 
       
   808         @Override
       
   809         public byte[] produce(ConnectionContext context,
       
   810                 HandshakeMessage message) throws IOException {
       
   811             // The producing happens in server side only.
       
   812             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   813 
       
   814             T13CertificateRequestMessage crm =
       
   815                     new T13CertificateRequestMessage(shc);
       
   816             // Produce extensions for CertificateRequest handshake message.
       
   817             SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(
       
   818                     SSLHandshake.CERTIFICATE_REQUEST, shc.negotiatedProtocol);
       
   819             crm.extensions.produce(shc, extTypes);
       
   820             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   821                 SSLLogger.fine("Produced CertificateRequest message", crm);
       
   822             }
       
   823 
       
   824             // Output the handshake message.
       
   825             crm.write(shc.handshakeOutput);
       
   826             shc.handshakeOutput.flush();
       
   827 
       
   828             //
       
   829             // update
       
   830             //
       
   831             shc.certRequestContext = crm.requestContext.clone();
       
   832             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,
       
   833                     SSLHandshake.CERTIFICATE);
       
   834             shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
       
   835                     SSLHandshake.CERTIFICATE_VERIFY);
       
   836 
       
   837             // The handshake message has been delivered.
       
   838             return null;
       
   839         }
       
   840     }
       
   841 
       
   842     /**
       
   843      * The "CertificateRequest" handshake message consumer for TLS 1.3.
       
   844      */
       
   845     private static final
       
   846             class T13CertificateRequestConsumer implements SSLConsumer {
       
   847         // Prevent instantiation of this class.
       
   848         private T13CertificateRequestConsumer() {
       
   849             // blank
       
   850         }
       
   851 
       
   852         @Override
       
   853         public void consume(ConnectionContext context,
       
   854                 ByteBuffer message) throws IOException {
       
   855             // The consuming happens in client side only.
       
   856             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   857 
       
   858             // clean up this consumer
       
   859             chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);
       
   860 
       
   861             T13CertificateRequestMessage crm =
       
   862                     new T13CertificateRequestMessage(chc, message);
       
   863             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   864                 SSLLogger.fine(
       
   865                         "Consuming CertificateRequest handshake message", crm);
       
   866             }
       
   867 
       
   868             //
       
   869             // validate
       
   870             //
       
   871             SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
       
   872                     SSLHandshake.CERTIFICATE_REQUEST);
       
   873             crm.extensions.consumeOnLoad(chc, extTypes);
       
   874 
       
   875             //
       
   876             // update
       
   877             //
       
   878             crm.extensions.consumeOnTrade(chc, extTypes);
       
   879 
       
   880             //
       
   881             // produce
       
   882             //
       
   883             chc.certRequestContext = crm.requestContext.clone();
       
   884             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,
       
   885                     SSLHandshake.CERTIFICATE);
       
   886             chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
       
   887                     SSLHandshake.CERTIFICATE_VERIFY);
       
   888         }
       
   889     }
       
   890 }