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