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.ByteArrayInputStream;
  29 import java.io.IOException;
  30 import java.nio.ByteBuffer;
  31 import java.security.PublicKey;
  32 import java.security.cert.CertPathValidatorException;
  33 import java.security.cert.CertPathValidatorException.BasicReason;
  34 import java.security.cert.CertPathValidatorException.Reason;
  35 import java.security.cert.CertificateEncodingException;
  36 import java.security.cert.CertificateException;
  37 import java.security.cert.CertificateFactory;
  38 import java.security.cert.CertificateParsingException;
  39 import java.security.cert.X509Certificate;
  40 import java.text.MessageFormat;
  41 import java.util.ArrayList;
  42 import java.util.Arrays;
  43 import java.util.Collection;
  44 import java.util.Collections;
  45 import java.util.HashSet;
  46 import java.util.LinkedList;
  47 import java.util.List;
  48 import java.util.Locale;
  49 import javax.net.ssl.SSLEngine;
  50 import javax.net.ssl.SSLException;
  51 import javax.net.ssl.SSLProtocolException;
  52 import javax.net.ssl.SSLSocket;
  53 import javax.net.ssl.X509ExtendedTrustManager;
  54 import javax.net.ssl.X509TrustManager;
  55 import javax.security.auth.x500.X500Principal;
  56 import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED;
  57 import sun.security.ssl.ClientHello.ClientHelloMessage;
  58 import sun.security.ssl.SSLHandshake.HandshakeMessage;
  59 import sun.security.ssl.X509Authentication.X509Credentials;
  60 import sun.security.ssl.X509Authentication.X509Possession;
  61 
  62 /**
  63  * Pack of the CertificateMessage handshake message.
  64  */
  65 final class CertificateMessage {
  66     static final SSLConsumer t12HandshakeConsumer =
  67         new T12CertificateConsumer();
  68     static final HandshakeProducer t12HandshakeProducer =
  69         new T12CertificateProducer();
  70 
  71     static final SSLConsumer t13HandshakeConsumer =
  72         new T13CertificateConsumer();
  73     static final HandshakeProducer t13HandshakeProducer =
  74         new T13CertificateProducer();
  75 
  76     /**
  77      * The Certificate handshake message for TLS 1.2 and previous
  78      * SSL/TLS protocol versions.
  79      *
  80      * In server mode, the certificate handshake message is sent whenever the
  81      * agreed-upon key exchange method uses certificates for authentication.
  82      * In client mode, this message is only sent if the server requests a
  83      * certificate for client authentication.
  84      *
  85      *       opaque ASN.1Cert<1..2^24-1>;
  86      *
  87      * SSL 3.0:
  88      *       struct {
  89      *           ASN.1Cert certificate_list<1..2^24-1>;
  90      *       } Certificate;
  91      * Note: For SSL 3.0 client authentication, if no suitable certificate
  92      * is available, the client should send a no_certificate alert instead.
  93      * This alert is only a warning; however, the server may respond with
  94      * a fatal handshake failure alert if client authentication is required.
  95      *
  96      * TLS 1.0/1.1/1.2:
  97      *       struct {
  98      *           ASN.1Cert certificate_list<0..2^24-1>;
  99      *       } Certificate;
 100      */
 101     static final class T12CertificateMessage extends HandshakeMessage {
 102         final List<byte[]> encodedCertChain;
 103 
 104         T12CertificateMessage(HandshakeContext handshakeContext,
 105                 X509Certificate[] certChain) throws SSLException {
 106             super(handshakeContext);
 107 
 108             List<byte[]> encodedCerts = new ArrayList<>(certChain.length);
 109             for (X509Certificate cert : certChain) {
 110                 try {
 111                     encodedCerts.add(cert.getEncoded());
 112                 } catch (CertificateEncodingException cee) {
 113                     // unlikely
 114                     handshakeContext.conContext.fatal(Alert.INTERNAL_ERROR,
 115                             "Could not encode certificate (" +
 116                             cert.getSubjectX500Principal() + ")", cee);
 117                     break;
 118                 }
 119             }
 120 
 121             this.encodedCertChain = encodedCerts;
 122         }
 123 
 124         T12CertificateMessage(HandshakeContext handshakeContext,
 125                 ByteBuffer m) throws IOException {
 126             super(handshakeContext);
 127 
 128             int listLen = Record.getInt24(m);
 129             if (listLen > m.remaining()) {
 130                 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
 131                     "Error parsing certificate message:no sufficient data");
 132             }
 133             if (listLen > 0) {
 134                 List<byte[]> encodedCerts = new LinkedList<>();
 135                 while (listLen > 0) {
 136                     byte[] encodedCert = Record.getBytes24(m);
 137                     listLen -= (3 + encodedCert.length);
 138                     encodedCerts.add(encodedCert);
 139                 }
 140                 this.encodedCertChain = encodedCerts;
 141             } else {
 142                 this.encodedCertChain = Collections.emptyList();
 143             }
 144         }
 145 
 146         @Override
 147         public SSLHandshake handshakeType() {
 148             return SSLHandshake.CERTIFICATE;
 149         }
 150 
 151         @Override
 152         public int messageLength() {
 153             int msgLen = 3;
 154             for (byte[] encodedCert : encodedCertChain) {
 155                 msgLen += (encodedCert.length + 3);
 156             }
 157 
 158             return msgLen;
 159         }
 160 
 161         @Override
 162         public void send(HandshakeOutStream hos) throws IOException {
 163             int listLen = 0;
 164             for (byte[] encodedCert : encodedCertChain) {
 165                 listLen += (encodedCert.length + 3);
 166             }
 167 
 168             hos.putInt24(listLen);
 169             for (byte[] encodedCert : encodedCertChain) {
 170                 hos.putBytes24(encodedCert);
 171             }
 172         }
 173 
 174         @Override
 175         public String toString() {
 176             if (encodedCertChain.isEmpty()) {
 177                 return "\"Certificates\": <empty list>";
 178             }
 179 
 180             Object[] x509Certs = new Object[encodedCertChain.size()];
 181             try {
 182                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
 183                 int i = 0;
 184                 for (byte[] encodedCert : encodedCertChain) {
 185                     Object obj;
 186                     try {
 187                         obj = (X509Certificate)cf.generateCertificate(
 188                                     new ByteArrayInputStream(encodedCert));
 189                     } catch (CertificateException ce) {
 190                         obj = encodedCert;
 191                     }
 192                     x509Certs[i++] = obj;
 193                 }
 194             } catch (CertificateException ce) {
 195                 // no X.509 certificate factory service
 196                 int i = 0;
 197                 for (byte[] encodedCert : encodedCertChain) {
 198                     x509Certs[i++] = encodedCert;
 199                 }
 200             }
 201 
 202             MessageFormat messageFormat = new MessageFormat(
 203                     "\"Certificates\": [\n" +
 204                     "{0}\n" +
 205                     "]",
 206                     Locale.ENGLISH);
 207             Object[] messageFields = {
 208                 SSLLogger.toString(x509Certs)
 209             };
 210 
 211             return messageFormat.format(messageFields);
 212         }
 213     }
 214 
 215     /**
 216      * The "Certificate" handshake message producer for TLS 1.2 and
 217      * previous SSL/TLS protocol versions.
 218      */
 219     private static final
 220             class T12CertificateProducer implements HandshakeProducer {
 221         // Prevent instantiation of this class.
 222         private T12CertificateProducer() {
 223             // blank
 224         }
 225 
 226         @Override
 227         public byte[] produce(ConnectionContext context,
 228                 HandshakeMessage message) throws IOException {
 229             // The producing happens in handshake context only.
 230             HandshakeContext hc = (HandshakeContext)context;
 231             if (hc.sslConfig.isClientMode) {
 232                 return onProduceCertificate(
 233                         (ClientHandshakeContext)context, message);
 234             } else {
 235                 return onProduceCertificate(
 236                         (ServerHandshakeContext)context, message);
 237             }
 238         }
 239 
 240         private byte[] onProduceCertificate(ServerHandshakeContext shc,
 241                 SSLHandshake.HandshakeMessage message) throws IOException {
 242             X509Possession x509Possession = null;
 243             for (SSLPossession possession : shc.handshakePossessions) {
 244                 if (possession instanceof X509Possession) {
 245                     x509Possession = (X509Possession)possession;
 246                     break;
 247                 }
 248             }
 249 
 250             if (x509Possession == null) {       // unlikely
 251                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
 252                     "No expected X.509 certificate for server authentication");
 253 
 254                 return null;        // make the compiler happy
 255             }
 256 
 257             shc.handshakeSession.setLocalPrivateKey(
 258                     x509Possession.popPrivateKey);
 259             shc.handshakeSession.setLocalCertificates(x509Possession.popCerts);
 260             T12CertificateMessage cm =
 261                     new T12CertificateMessage(shc, x509Possession.popCerts);
 262             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 263                 SSLLogger.fine(
 264                     "Produced server Certificate handshake message", cm);
 265             }
 266 
 267             // Output the handshake message.
 268             cm.write(shc.handshakeOutput);
 269             shc.handshakeOutput.flush();
 270 
 271             // The handshake message has been delivered.
 272             return null;
 273         }
 274 
 275         private byte[] onProduceCertificate(ClientHandshakeContext chc,
 276                 SSLHandshake.HandshakeMessage message) throws IOException {
 277             X509Possession x509Possession = null;
 278             for (SSLPossession possession : chc.handshakePossessions) {
 279                 if (possession instanceof X509Possession) {
 280                     x509Possession = (X509Possession)possession;
 281                     break;
 282                 }
 283             }
 284 
 285             // Report to the server if no appropriate cert was found.  For
 286             // SSL 3.0, send a no_certificate alert;  TLS 1.0/1.1/1.2 uses
 287             // an empty cert chain instead.
 288             if (x509Possession == null) {
 289                 if (chc.negotiatedProtocol.useTLS10PlusSpec()) {
 290                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 291                         SSLLogger.fine(
 292                             "No X.509 certificate for client authentication, " +
 293                             "use empty Certificate message instead");
 294                     }
 295 
 296                     x509Possession =
 297                             new X509Possession(null, new X509Certificate[0]);
 298                 } else {
 299                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 300                         SSLLogger.fine(
 301                             "No X.509 certificate for client authentication, " +
 302                             "send a no_certificate alert");
 303                     }
 304 
 305                     chc.conContext.warning(Alert.NO_CERTIFICATE);
 306                     return null;
 307                 }
 308             }
 309 
 310             chc.handshakeSession.setLocalPrivateKey(
 311                     x509Possession.popPrivateKey);
 312             if (x509Possession.popCerts != null &&
 313                     x509Possession.popCerts.length != 0) {
 314                 chc.handshakeSession.setLocalCertificates(
 315                         x509Possession.popCerts);
 316             } else {
 317                 chc.handshakeSession.setLocalCertificates(null);
 318             }
 319             T12CertificateMessage cm =
 320                     new T12CertificateMessage(chc, x509Possession.popCerts);
 321             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 322                 SSLLogger.fine(
 323                     "Produced client Certificate handshake message", cm);
 324             }
 325 
 326             // Output the handshake message.
 327             cm.write(chc.handshakeOutput);
 328             chc.handshakeOutput.flush();
 329 
 330             // The handshake message has been delivered.
 331             return null;
 332         }
 333     }
 334 
 335     /**
 336      * The "Certificate" handshake message consumer for TLS 1.2 and
 337      * previous SSL/TLS protocol versions.
 338      */
 339     static final
 340             class T12CertificateConsumer implements SSLConsumer {
 341         // Prevent instantiation of this class.
 342         private T12CertificateConsumer() {
 343             // blank
 344         }
 345 
 346         @Override
 347         public void consume(ConnectionContext context,
 348                 ByteBuffer message) throws IOException {
 349             // The consuming happens in handshake context only.
 350             HandshakeContext hc = (HandshakeContext)context;
 351 
 352             // clean up this consumer
 353             hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id);
 354 
 355             T12CertificateMessage cm = new T12CertificateMessage(hc, message);
 356             if (hc.sslConfig.isClientMode) {
 357                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 358                     SSLLogger.fine(
 359                         "Consuming server Certificate handshake message", cm);
 360                 }
 361                 onCertificate((ClientHandshakeContext)context, cm);
 362             } else {
 363                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 364                     SSLLogger.fine(
 365                         "Consuming client Certificate handshake message", cm);
 366                 }
 367                 onCertificate((ServerHandshakeContext)context, cm);
 368             }
 369         }
 370 
 371         private void onCertificate(ServerHandshakeContext shc,
 372                 T12CertificateMessage certificateMessage )throws IOException {
 373             List<byte[]> encodedCerts = certificateMessage.encodedCertChain;
 374             if (encodedCerts == null || encodedCerts.isEmpty()) {
 375                 if (shc.sslConfig.clientAuthType !=
 376                         ClientAuthType.CLIENT_AUTH_REQUESTED) {
 377                     // unexpected or require client authentication
 378                     shc.conContext.fatal(Alert.BAD_CERTIFICATE,
 379                         "Empty server certificate chain");
 380                 } else {
 381                     return;
 382                 }
 383             }
 384 
 385             X509Certificate[] x509Certs =
 386                     new X509Certificate[encodedCerts.size()];
 387             try {
 388                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
 389                 int i = 0;
 390                 for (byte[] encodedCert : encodedCerts) {
 391                     x509Certs[i++] = (X509Certificate)cf.generateCertificate(
 392                                     new ByteArrayInputStream(encodedCert));
 393                 }
 394             } catch (CertificateException ce) {
 395                 shc.conContext.fatal(Alert.BAD_CERTIFICATE,
 396                     "Failed to parse server certificates", ce);
 397             }
 398 
 399             checkClientCerts(shc, x509Certs);
 400 
 401             //
 402             // update
 403             //
 404             shc.handshakeCredentials.add(
 405                 new X509Credentials(x509Certs[0].getPublicKey(), x509Certs));
 406             shc.handshakeSession.setPeerCertificates(x509Certs);
 407         }
 408 
 409         private void onCertificate(ClientHandshakeContext chc,
 410                 T12CertificateMessage certificateMessage) throws IOException {
 411             List<byte[]> encodedCerts = certificateMessage.encodedCertChain;
 412             if (encodedCerts == null || encodedCerts.isEmpty()) {
 413                 chc.conContext.fatal(Alert.BAD_CERTIFICATE,
 414                     "Empty server certificate chain");
 415             }
 416 
 417             X509Certificate[] x509Certs =
 418                     new X509Certificate[encodedCerts.size()];
 419             try {
 420                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
 421                 int i = 0;
 422                 for (byte[] encodedCert : encodedCerts) {
 423                     x509Certs[i++] = (X509Certificate)cf.generateCertificate(
 424                                     new ByteArrayInputStream(encodedCert));
 425                 }
 426             } catch (CertificateException ce) {
 427                 chc.conContext.fatal(Alert.BAD_CERTIFICATE,
 428                     "Failed to parse server certificates", ce);
 429             }
 430 
 431             // Allow server certificate change in client side during
 432             // renegotiation after a session-resumption abbreviated
 433             // initial handshake?
 434             //
 435             // DO NOT need to check allowUnsafeServerCertChange here. We only
 436             // reserve server certificates when allowUnsafeServerCertChange is
 437             // false.
 438             if (chc.reservedServerCerts != null &&
 439                     !chc.handshakeSession.useExtendedMasterSecret) {
 440                 // It is not necessary to check the certificate update if
 441                 // endpoint identification is enabled.
 442                 String identityAlg = chc.sslConfig.identificationProtocol;
 443                 if ((identityAlg == null || identityAlg.isEmpty()) &&
 444                         !isIdentityEquivalent(x509Certs[0],
 445                                 chc.reservedServerCerts[0])) {
 446                     chc.conContext.fatal(Alert.BAD_CERTIFICATE,
 447                             "server certificate change is restricted " +
 448                             "during renegotiation");
 449                 }
 450             }
 451 
 452             // ask the trust manager to verify the chain
 453             if (chc.staplingActive) {
 454                 // Defer the certificate check until after we've received the
 455                 // CertificateStatus message.  If that message doesn't come in
 456                 // immediately following this message we will execute the
 457                 // check from CertificateStatus' absent handler.
 458                 chc.deferredCerts = x509Certs;
 459             } else {
 460                 // We're not doing stapling, so perform the check right now
 461                 checkServerCerts(chc, x509Certs);
 462             }
 463 
 464             //
 465             // update
 466             //
 467             chc.handshakeCredentials.add(
 468                 new X509Credentials(x509Certs[0].getPublicKey(), x509Certs));
 469             chc.handshakeSession.setPeerCertificates(x509Certs);
 470         }
 471 
 472         /*
 473          * Whether the certificates can represent the same identity?
 474          *
 475          * The certificates can be used to represent the same identity:
 476          *     1. If the subject alternative names of IP address are present
 477          *        in both certificates, they should be identical; otherwise,
 478          *     2. if the subject alternative names of DNS name are present in
 479          *        both certificates, they should be identical; otherwise,
 480          *     3. if the subject fields are present in both certificates, the
 481          *        certificate subjects and issuers should be identical.
 482          */
 483         private static boolean isIdentityEquivalent(X509Certificate thisCert,
 484                 X509Certificate prevCert) {
 485             if (thisCert.equals(prevCert)) {
 486                 return true;
 487             }
 488 
 489             // check subject alternative names
 490             Collection<List<?>> thisSubjectAltNames = null;
 491             try {
 492                 thisSubjectAltNames = thisCert.getSubjectAlternativeNames();
 493             } catch (CertificateParsingException cpe) {
 494                 if (SSLLogger.isOn && SSLLogger.isOn("handshake")) {
 495                     SSLLogger.fine(
 496                         "Attempt to obtain subjectAltNames extension failed!");
 497                 }
 498             }
 499 
 500             Collection<List<?>> prevSubjectAltNames = null;
 501             try {
 502                 prevSubjectAltNames = prevCert.getSubjectAlternativeNames();
 503             } catch (CertificateParsingException cpe) {
 504                 if (SSLLogger.isOn && SSLLogger.isOn("handshake")) {
 505                     SSLLogger.fine(
 506                         "Attempt to obtain subjectAltNames extension failed!");
 507                 }
 508             }
 509 
 510             if (thisSubjectAltNames != null && prevSubjectAltNames != null) {
 511                 // check the iPAddress field in subjectAltName extension
 512                 //
 513                 // 7: subject alternative name of type IP.
 514                 Collection<String> thisSubAltIPAddrs =
 515                             getSubjectAltNames(thisSubjectAltNames, 7);
 516                 Collection<String> prevSubAltIPAddrs =
 517                             getSubjectAltNames(prevSubjectAltNames, 7);
 518                 if (thisSubAltIPAddrs != null && prevSubAltIPAddrs != null &&
 519                     isEquivalent(thisSubAltIPAddrs, prevSubAltIPAddrs)) {
 520                     return true;
 521                 }
 522 
 523                 // check the dNSName field in subjectAltName extension
 524                 // 2: subject alternative name of type IP.
 525                 Collection<String> thisSubAltDnsNames =
 526                             getSubjectAltNames(thisSubjectAltNames, 2);
 527                 Collection<String> prevSubAltDnsNames =
 528                             getSubjectAltNames(prevSubjectAltNames, 2);
 529                 if (thisSubAltDnsNames != null && prevSubAltDnsNames != null &&
 530                     isEquivalent(thisSubAltDnsNames, prevSubAltDnsNames)) {
 531                     return true;
 532                 }
 533             }
 534 
 535             // check the certificate subject and issuer
 536             X500Principal thisSubject = thisCert.getSubjectX500Principal();
 537             X500Principal prevSubject = prevCert.getSubjectX500Principal();
 538             X500Principal thisIssuer = thisCert.getIssuerX500Principal();
 539             X500Principal prevIssuer = prevCert.getIssuerX500Principal();
 540 
 541             return (!thisSubject.getName().isEmpty() &&
 542                     !prevSubject.getName().isEmpty() &&
 543                     thisSubject.equals(prevSubject) &&
 544                     thisIssuer.equals(prevIssuer));
 545         }
 546 
 547         /*
 548          * Returns the subject alternative name of the specified type in the
 549          * subjectAltNames extension of a certificate.
 550          *
 551          * Note that only those subjectAltName types that use String data
 552          * should be passed into this function.
 553          */
 554         private static Collection<String> getSubjectAltNames(
 555                 Collection<List<?>> subjectAltNames, int type) {
 556             HashSet<String> subAltDnsNames = null;
 557             for (List<?> subjectAltName : subjectAltNames) {
 558                 int subjectAltNameType = (Integer)subjectAltName.get(0);
 559                 if (subjectAltNameType == type) {
 560                     String subAltDnsName = (String)subjectAltName.get(1);
 561                     if ((subAltDnsName != null) && !subAltDnsName.isEmpty()) {
 562                         if (subAltDnsNames == null) {
 563                             subAltDnsNames =
 564                                     new HashSet<>(subjectAltNames.size());
 565                         }
 566                         subAltDnsNames.add(subAltDnsName);
 567                     }
 568                 }
 569             }
 570 
 571             return subAltDnsNames;
 572         }
 573 
 574         private static boolean isEquivalent(Collection<String> thisSubAltNames,
 575                 Collection<String> prevSubAltNames) {
 576             for (String thisSubAltName : thisSubAltNames) {
 577                 for (String prevSubAltName : prevSubAltNames) {
 578                     // Only allow the exactly match.  No wildcard character
 579                     // checking.
 580                     if (thisSubAltName.equalsIgnoreCase(prevSubAltName)) {
 581                         return true;
 582                     }
 583                 }
 584             }
 585 
 586             return false;
 587         }
 588 
 589         /**
 590          * Perform client-side checking of server certificates.
 591          *
 592          * @param certs an array of {@code X509Certificate} objects presented
 593          *      by the server in the ServerCertificate message.
 594          *
 595          * @throws IOException if a failure occurs during validation or
 596          *      the trust manager associated with the {@code SSLContext} is not
 597          *      an {@code X509ExtendedTrustManager}.
 598          */
 599         static void checkServerCerts(ClientHandshakeContext chc,
 600                 X509Certificate[] certs) throws IOException {
 601 
 602             X509TrustManager tm = chc.sslContext.getX509TrustManager();
 603 
 604             // find out the key exchange algorithm used
 605             // use "RSA" for non-ephemeral "RSA_EXPORT"
 606             String keyExchangeString;
 607             if (chc.negotiatedCipherSuite.keyExchange ==
 608                     CipherSuite.KeyExchange.K_RSA_EXPORT ||
 609                     chc.negotiatedCipherSuite.keyExchange ==
 610                             CipherSuite.KeyExchange.K_DHE_RSA_EXPORT) {
 611                 keyExchangeString = CipherSuite.KeyExchange.K_RSA.name;
 612             } else {
 613                 keyExchangeString = chc.negotiatedCipherSuite.keyExchange.name;
 614             }
 615 
 616             try {
 617                 if (tm instanceof X509ExtendedTrustManager) {
 618                     if (chc.conContext.transport instanceof SSLEngine) {
 619                         SSLEngine engine = (SSLEngine)chc.conContext.transport;
 620                         ((X509ExtendedTrustManager)tm).checkServerTrusted(
 621                             certs.clone(),
 622                             keyExchangeString,
 623                             engine);
 624                     } else {
 625                         SSLSocket socket = (SSLSocket)chc.conContext.transport;
 626                         ((X509ExtendedTrustManager)tm).checkServerTrusted(
 627                             certs.clone(),
 628                             keyExchangeString,
 629                             socket);
 630                     }
 631                 } else {
 632                     // Unlikely to happen, because we have wrapped the old
 633                     // X509TrustManager with the new X509ExtendedTrustManager.
 634                     throw new CertificateException(
 635                             "Improper X509TrustManager implementation");
 636                 }
 637 
 638                 // Once the server certificate chain has been validated, set
 639                 // the certificate chain in the TLS session.
 640                 chc.handshakeSession.setPeerCertificates(certs);
 641             } catch (CertificateException ce) {
 642                 chc.conContext.fatal(getCertificateAlert(chc, ce), ce);
 643             }
 644         }
 645 
 646         private static void checkClientCerts(ServerHandshakeContext shc,
 647                 X509Certificate[] certs) throws IOException {
 648             X509TrustManager tm = shc.sslContext.getX509TrustManager();
 649 
 650             // find out the types of client authentication used
 651             PublicKey key = certs[0].getPublicKey();
 652             String keyAlgorithm = key.getAlgorithm();
 653             String authType;
 654             switch (keyAlgorithm) {
 655                 case "RSA":
 656                 case "DSA":
 657                 case "EC":
 658                 case "RSASSA-PSS":
 659                     authType = keyAlgorithm;
 660                     break;
 661                 default:
 662                     // unknown public key type
 663                     authType = "UNKNOWN";
 664             }
 665 
 666             try {
 667                 if (tm instanceof X509ExtendedTrustManager) {
 668                     if (shc.conContext.transport instanceof SSLEngine) {
 669                         SSLEngine engine = (SSLEngine)shc.conContext.transport;
 670                         ((X509ExtendedTrustManager)tm).checkClientTrusted(
 671                             certs.clone(),
 672                             authType,
 673                             engine);
 674                     } else {
 675                         SSLSocket socket = (SSLSocket)shc.conContext.transport;
 676                         ((X509ExtendedTrustManager)tm).checkClientTrusted(
 677                             certs.clone(),
 678                             authType,
 679                             socket);
 680                     }
 681                 } else {
 682                     // Unlikely to happen, because we have wrapped the old
 683                     // X509TrustManager with the new X509ExtendedTrustManager.
 684                     throw new CertificateException(
 685                             "Improper X509TrustManager implementation");
 686                 }
 687             } catch (CertificateException ce) {
 688                 shc.conContext.fatal(Alert.CERTIFICATE_UNKNOWN, ce);
 689             }
 690         }
 691 
 692         /**
 693          * When a failure happens during certificate checking from an
 694          * {@link X509TrustManager}, determine what TLS alert description
 695          * to use.
 696          *
 697          * @param cexc The exception thrown by the {@link X509TrustManager}
 698          *
 699          * @return A byte value corresponding to a TLS alert description number.
 700          */
 701         private static Alert getCertificateAlert(
 702                 ClientHandshakeContext chc, CertificateException cexc) {
 703             // The specific reason for the failure will determine how to
 704             // set the alert description value
 705             Alert alert = Alert.CERTIFICATE_UNKNOWN;
 706 
 707             Throwable baseCause = cexc.getCause();
 708             if (baseCause instanceof CertPathValidatorException) {
 709                 CertPathValidatorException cpve =
 710                         (CertPathValidatorException)baseCause;
 711                 Reason reason = cpve.getReason();
 712                 if (reason == BasicReason.REVOKED) {
 713                     alert = chc.staplingActive ?
 714                             Alert.BAD_CERT_STATUS_RESPONSE :
 715                             Alert.CERTIFICATE_REVOKED;
 716                 } else if (
 717                         reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) {
 718                     alert = chc.staplingActive ?
 719                             Alert.BAD_CERT_STATUS_RESPONSE :
 720                             Alert.CERTIFICATE_UNKNOWN;
 721                 }
 722             }
 723 
 724             return alert;
 725         }
 726 
 727     }
 728 
 729     /**
 730      * The certificate entry used in Certificate handshake message for TLS 1.3.
 731      */
 732     static final class CertificateEntry {
 733         final byte[] encoded;       // encoded cert or public key
 734         private final SSLExtensions extensions;
 735 
 736         CertificateEntry(byte[] encoded, SSLExtensions extensions) {
 737             this.encoded = encoded;
 738             this.extensions = extensions;
 739         }
 740 
 741         private int getEncodedSize() {
 742             int extLen = extensions.length();
 743             if (extLen == 0) {
 744                 extLen = 2;     // empty extensions
 745             }
 746             return 3 + encoded.length + extLen;
 747         }
 748 
 749         @Override
 750         public String toString() {
 751             MessageFormat messageFormat = new MessageFormat(
 752                 "\n'{'\n" +
 753                 "{0}\n" +                       // X.509 certificate
 754                 "  \"extensions\": '{'\n" +
 755                 "{1}\n" +
 756                 "  '}'\n" +
 757                 "'}',", Locale.ENGLISH);
 758 
 759             Object x509Certs;
 760             try {
 761                 // Don't support certificate type extension (RawPublicKey) yet.
 762                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
 763                 x509Certs =
 764                     cf.generateCertificate(new ByteArrayInputStream(encoded));
 765             } catch (CertificateException ce) {
 766                 // no X.509 certificate factory service
 767                 x509Certs = encoded;
 768             }
 769 
 770             Object[] messageFields = {
 771                 SSLLogger.toString(x509Certs),
 772                 Utilities.indent(extensions.toString(), "    ")
 773             };
 774 
 775             return messageFormat.format(messageFields);
 776         }
 777     }
 778 
 779     /**
 780      * The Certificate handshake message for TLS 1.3.
 781      */
 782     static final class T13CertificateMessage extends HandshakeMessage {
 783         private final byte[] requestContext;
 784         private final List<CertificateEntry> certEntries;
 785 
 786         T13CertificateMessage(HandshakeContext context,
 787                 byte[] requestContext, X509Certificate[] certificates)
 788                 throws SSLException, CertificateException  {
 789             super(context);
 790 
 791             this.requestContext = requestContext.clone();
 792             this.certEntries = new LinkedList<>();
 793             for (X509Certificate cert : certificates) {
 794                 byte[] encoded = cert.getEncoded();
 795                 SSLExtensions extensions = new SSLExtensions(this);
 796                 certEntries.add(new CertificateEntry(encoded, extensions));
 797             }
 798         }
 799 
 800         T13CertificateMessage(HandshakeContext handshakeContext,
 801                 byte[] requestContext, List<CertificateEntry> certificates) {
 802             super(handshakeContext);
 803 
 804             this.requestContext = requestContext.clone();
 805             this.certEntries = certificates;
 806         }
 807 
 808         T13CertificateMessage(HandshakeContext handshakeContext,
 809                 ByteBuffer m) throws IOException {
 810             super(handshakeContext);
 811 
 812             // struct {
 813             //      opaque certificate_request_context<0..2^8-1>;
 814             //      CertificateEntry certificate_list<0..2^24-1>;
 815             //  } Certificate;
 816             if (m.remaining() < 4) {
 817                 throw new SSLProtocolException(
 818                         "Invalid Certificate message: " +
 819                         "insufficient data (length=" + m.remaining() + ")");
 820             }
 821             this.requestContext = Record.getBytes8(m);
 822 
 823             if (m.remaining() < 3) {
 824                 throw new SSLProtocolException(
 825                         "Invalid Certificate message: " +
 826                         "insufficient certificate entries data (length=" +
 827                         m.remaining() + ")");
 828             }
 829 
 830             int listLen = Record.getInt24(m);
 831             if (listLen != m.remaining()) {
 832                 throw new SSLProtocolException(
 833                     "Invalid Certificate message: " +
 834                     "incorrect list length (length=" + listLen + ")");
 835             }
 836 
 837             SSLExtension[] enabledExtensions =
 838                 handshakeContext.sslConfig.getEnabledExtensions(
 839                         SSLHandshake.CERTIFICATE);
 840             List<CertificateEntry> certList = new LinkedList<>();
 841             while (m.hasRemaining()) {
 842                 // Note: support only X509 CertificateType right now.
 843                 byte[] encodedCert = Record.getBytes24(m);
 844                 if (encodedCert.length == 0) {
 845                     throw new SSLProtocolException(
 846                         "Invalid Certificate message: empty cert_data");
 847                 }
 848 
 849                 SSLExtensions extensions =
 850                         new SSLExtensions(this, m, enabledExtensions);
 851                 certList.add(new CertificateEntry(encodedCert, extensions));
 852             }
 853 
 854             this.certEntries = Collections.unmodifiableList(certList);
 855         }
 856 
 857         @Override
 858         public SSLHandshake handshakeType() {
 859             return SSLHandshake.CERTIFICATE;
 860         }
 861 
 862         @Override
 863         public int messageLength() {
 864             int msgLen = 4 + requestContext.length;
 865             for (CertificateEntry entry : certEntries) {
 866                 msgLen += entry.getEncodedSize();
 867             }
 868 
 869             return msgLen;
 870         }
 871 
 872         @Override
 873         public void send(HandshakeOutStream hos) throws IOException {
 874             int entryListLen = 0;
 875             for (CertificateEntry entry : certEntries) {
 876                 entryListLen += entry.getEncodedSize();
 877             }
 878 
 879             hos.putBytes8(requestContext);
 880             hos.putInt24(entryListLen);
 881             for (CertificateEntry entry : certEntries) {
 882                 hos.putBytes24(entry.encoded);
 883                 // Is it an empty extensions?
 884                 if (entry.extensions.length() == 0) {
 885                     hos.putInt16(0);
 886                 } else {
 887                     entry.extensions.send(hos);
 888                 }
 889             }
 890         }
 891 
 892         @Override
 893         public String toString() {
 894             MessageFormat messageFormat = new MessageFormat(
 895                 "\"Certificate\": '{'\n" +
 896                 "  \"certificate_request_context\": \"{0}\",\n" +
 897                 "  \"certificate_list\": [{1}\n]\n" +
 898                 "'}'",
 899                 Locale.ENGLISH);
 900 
 901             StringBuilder builder = new StringBuilder(512);
 902             for (CertificateEntry entry : certEntries) {
 903                 builder.append(entry.toString());
 904             }
 905 
 906             Object[] messageFields = {
 907                 Utilities.toHexString(requestContext),
 908                 Utilities.indent(builder.toString())
 909             };
 910 
 911             return messageFormat.format(messageFields);
 912         }
 913     }
 914 
 915     /**
 916      * The "Certificate" handshake message producer for TLS 1.3.
 917      */
 918     private static final
 919             class T13CertificateProducer implements HandshakeProducer {
 920         // Prevent instantiation of this class.
 921         private T13CertificateProducer() {
 922             // blank
 923         }
 924 
 925         @Override
 926         public byte[] produce(ConnectionContext context,
 927                 HandshakeMessage message) throws IOException {
 928             // The producing happens in handshake context only.
 929             HandshakeContext hc = (HandshakeContext)context;
 930             if (hc.sslConfig.isClientMode) {
 931                 return onProduceCertificate(
 932                         (ClientHandshakeContext)context, message);
 933             } else {
 934                 return onProduceCertificate(
 935                         (ServerHandshakeContext)context, message);
 936             }
 937         }
 938 
 939         private byte[] onProduceCertificate(ServerHandshakeContext shc,
 940                 HandshakeMessage message) throws IOException {
 941             ClientHelloMessage clientHello = (ClientHelloMessage)message;
 942 
 943             SSLPossession pos = choosePossession(shc, clientHello);
 944             if (pos == null) {
 945                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 946                         "No available authentication scheme");
 947                 return null;    // make the complier happy
 948             }
 949 
 950             if (!(pos instanceof X509Possession)) {
 951                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 952                         "No X.509 certificate for server authentication");
 953             }
 954 
 955             X509Possession x509Possession = (X509Possession)pos;
 956             X509Certificate[] localCerts = x509Possession.popCerts;
 957             if (localCerts == null || localCerts.length == 0) {
 958                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 959                         "No X.509 certificate for server authentication");
 960                 return null;    // make the complier happy
 961             }
 962 
 963             // update the context
 964             shc.handshakePossessions.add(x509Possession);
 965             shc.handshakeSession.setLocalPrivateKey(
 966                     x509Possession.popPrivateKey);
 967             shc.handshakeSession.setLocalCertificates(localCerts);
 968             T13CertificateMessage cm;
 969             try {
 970                 cm = new T13CertificateMessage(shc, (new byte[0]), localCerts);
 971             } catch (SSLException | CertificateException ce) {
 972                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 973                         "Failed to produce server Certificate message", ce);
 974                 return null;    // make the complier happy
 975             }
 976 
 977             // Check the OCSP stapling extensions and attempt
 978             // to get responses.  If the resulting stapleParams is non
 979             // null, it implies that stapling is enabled on the server side.
 980             shc.stapleParams = StatusResponseManager.processStapling(shc);
 981             shc.staplingActive = (shc.stapleParams != null);
 982 
 983             // Process extensions for each CertificateEntry.
 984             // Since there can be multiple CertificateEntries within a
 985             // single CT message, we will pin a specific CertificateEntry
 986             // into the ServerHandshakeContext so individual extension
 987             // producers know which X509Certificate it is processing in
 988             // each call.
 989             SSLExtension[] enabledCTExts = shc.sslConfig.getEnabledExtensions(
 990                     SSLHandshake.CERTIFICATE,
 991                     Arrays.asList(ProtocolVersion.PROTOCOLS_OF_13));
 992             for (CertificateEntry certEnt : cm.certEntries) {
 993                 shc.currentCertEntry = certEnt;
 994                 certEnt.extensions.produce(shc, enabledCTExts);
 995             }
 996 
 997             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 998                 SSLLogger.fine("Produced server Certificate message", cm);
 999             }
1000 
1001             // Output the handshake message.
1002             cm.write(shc.handshakeOutput);
1003             shc.handshakeOutput.flush();
1004 
1005             // The handshake message has been delivered.
1006             return null;
1007         }
1008 
1009         private static SSLPossession choosePossession(
1010                 HandshakeContext hc,
1011                 ClientHelloMessage clientHello) throws IOException {
1012             if (hc.peerRequestedCertSignSchemes == null ||
1013                     hc.peerRequestedCertSignSchemes.isEmpty()) {
1014                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1015                     SSLLogger.warning(
1016                             "No signature_algorithms(_cert) in ClientHello");
1017                 }
1018                 return null;
1019             }
1020 
1021             Collection<String> checkedKeyTypes = new HashSet<>();
1022             for (SignatureScheme ss : hc.peerRequestedCertSignSchemes) {
1023                 if (checkedKeyTypes.contains(ss.keyAlgorithm)) {
1024                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1025                         SSLLogger.warning(
1026                             "Unsupported authentication scheme: " + ss.name);
1027                     }
1028                     continue;
1029                 }
1030 
1031                 // Don't select a signature scheme unless we will be able to
1032                 // produce a CertificateVerify message later
1033                 if (SignatureScheme.getPreferableAlgorithm(
1034                         hc.peerRequestedSignatureSchemes,
1035                         ss, hc.negotiatedProtocol) == null) {
1036 
1037                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1038                         SSLLogger.warning(
1039                             "Unable to produce CertificateVerify for " +
1040                             "signature scheme: " + ss.name);
1041                     }
1042                     checkedKeyTypes.add(ss.keyAlgorithm);
1043                     continue;
1044                 }
1045 
1046                 SSLAuthentication ka = X509Authentication.valueOf(ss);
1047                 if (ka == null) {
1048                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1049                         SSLLogger.warning(
1050                             "Unsupported authentication scheme: " + ss.name);
1051                     }
1052                     checkedKeyTypes.add(ss.keyAlgorithm);
1053                     continue;
1054                 }
1055 
1056                 SSLPossession pos = ka.createPossession(hc);
1057                 if (pos == null) {
1058                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1059                         SSLLogger.warning(
1060                             "Unavailable authentication scheme: " + ss.name);
1061                     }
1062                     continue;
1063                 }
1064 
1065                 return pos;
1066             }
1067 
1068             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1069                 SSLLogger.warning("No available authentication scheme");
1070             }
1071             return null;
1072         }
1073 
1074         private byte[] onProduceCertificate(ClientHandshakeContext chc,
1075                 HandshakeMessage message) throws IOException {
1076             ClientHelloMessage clientHello = (ClientHelloMessage)message;
1077             SSLPossession pos = choosePossession(chc, clientHello);
1078             X509Certificate[] localCerts;
1079             if (pos == null) {
1080                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1081                     SSLLogger.fine("No available client authentication scheme");
1082                 }
1083                 localCerts = new X509Certificate[0];
1084             } else {
1085                 chc.handshakePossessions.add(pos);
1086                 if (!(pos instanceof X509Possession)) {
1087                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1088                         SSLLogger.fine(
1089                             "No X.509 certificate for client authentication");
1090                     }
1091                     localCerts = new X509Certificate[0];
1092                 } else {
1093                     X509Possession x509Possession = (X509Possession)pos;
1094                     localCerts = x509Possession.popCerts;
1095                     chc.handshakeSession.setLocalPrivateKey(
1096                             x509Possession.popPrivateKey);
1097                 }
1098             }
1099 
1100             if (localCerts != null && localCerts.length != 0) {
1101                 chc.handshakeSession.setLocalCertificates(localCerts);
1102             } else {
1103                 chc.handshakeSession.setLocalCertificates(null);
1104             }
1105 
1106             T13CertificateMessage cm;
1107             try {
1108                 cm = new T13CertificateMessage(
1109                         chc, chc.certRequestContext, localCerts);
1110             } catch (SSLException | CertificateException ce) {
1111                 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1112                         "Failed to produce client Certificate message", ce);
1113                 return null;
1114             }
1115             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1116                 SSLLogger.fine("Produced client Certificate message", cm);
1117             }
1118 
1119             // Output the handshake message.
1120             cm.write(chc.handshakeOutput);
1121             chc.handshakeOutput.flush();
1122 
1123             // The handshake message has been delivered.
1124             return null;
1125         }
1126     }
1127 
1128     /**
1129      * The "Certificate" handshake message consumer for TLS 1.3.
1130      */
1131     private static final class T13CertificateConsumer implements SSLConsumer {
1132         // Prevent instantiation of this class.
1133         private T13CertificateConsumer() {
1134             // blank
1135         }
1136 
1137         @Override
1138         public void consume(ConnectionContext context,
1139                 ByteBuffer message) throws IOException {
1140             // The consuming happens in handshake context only.
1141             HandshakeContext hc = (HandshakeContext)context;
1142 
1143             // clean up this consumer
1144             hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id);
1145             T13CertificateMessage cm = new T13CertificateMessage(hc, message);
1146             if (hc.sslConfig.isClientMode) {
1147                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1148                     SSLLogger.fine(
1149                         "Consuming server Certificate handshake message", cm);
1150                 }
1151                 onConsumeCertificate((ClientHandshakeContext)context, cm);
1152             } else {
1153                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1154                     SSLLogger.fine(
1155                         "Consuming client Certificate handshake message", cm);
1156                 }
1157                 onConsumeCertificate((ServerHandshakeContext)context, cm);
1158             }
1159         }
1160 
1161         private void onConsumeCertificate(ServerHandshakeContext shc,
1162                 T13CertificateMessage certificateMessage )throws IOException {
1163             if (certificateMessage.certEntries == null ||
1164                     certificateMessage.certEntries.isEmpty()) {
1165                 if (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED) {
1166                     shc.conContext.fatal(Alert.BAD_CERTIFICATE,
1167                         "Empty client certificate chain");
1168                 } else {
1169                     // optional client authentication
1170                     return;
1171                 }
1172             }
1173 
1174             // check client certificate entries
1175             X509Certificate[] cliCerts =
1176                     checkClientCerts(shc, certificateMessage.certEntries);
1177 
1178             //
1179             // update
1180             //
1181             shc.handshakeCredentials.add(
1182                 new X509Credentials(cliCerts[0].getPublicKey(), cliCerts));
1183             shc.handshakeSession.setPeerCertificates(cliCerts);
1184         }
1185 
1186         private void onConsumeCertificate(ClientHandshakeContext chc,
1187                 T13CertificateMessage certificateMessage )throws IOException {
1188             if (certificateMessage.certEntries == null ||
1189                     certificateMessage.certEntries.isEmpty()) {
1190                 chc.conContext.fatal(Alert.BAD_CERTIFICATE,
1191                     "Empty server certificate chain");
1192             }
1193 
1194             // Each CertificateEntry will have its own set of extensions
1195             // which must be consumed.
1196             SSLExtension[] enabledExtensions =
1197                 chc.sslConfig.getEnabledExtensions(SSLHandshake.CERTIFICATE);
1198             for (CertificateEntry certEnt : certificateMessage.certEntries) {
1199                 certEnt.extensions.consumeOnLoad(chc, enabledExtensions);
1200             }
1201 
1202             // check server certificate entries
1203             X509Certificate[] srvCerts =
1204                     checkServerCerts(chc, certificateMessage.certEntries);
1205 
1206             //
1207             // update
1208             //
1209             chc.handshakeCredentials.add(
1210                 new X509Credentials(srvCerts[0].getPublicKey(), srvCerts));
1211             chc.handshakeSession.setPeerCertificates(srvCerts);
1212         }
1213 
1214         private static X509Certificate[] checkClientCerts(
1215                 ServerHandshakeContext shc,
1216                 List<CertificateEntry> certEntries) throws IOException {
1217             X509Certificate[] certs =
1218                     new X509Certificate[certEntries.size()];
1219             try {
1220                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
1221                 int i = 0;
1222                 for (CertificateEntry entry : certEntries) {
1223                     certs[i++] = (X509Certificate)cf.generateCertificate(
1224                                     new ByteArrayInputStream(entry.encoded));
1225                 }
1226             } catch (CertificateException ce) {
1227                 shc.conContext.fatal(Alert.BAD_CERTIFICATE,
1228                     "Failed to parse server certificates", ce);
1229             }
1230 
1231             // find out the types of client authentication used
1232             String keyAlgorithm = certs[0].getPublicKey().getAlgorithm();
1233             String authType;
1234             switch (keyAlgorithm) {
1235                 case "RSA":
1236                 case "DSA":
1237                 case "EC":
1238                 case "RSASSA-PSS":
1239                     authType = keyAlgorithm;
1240                     break;
1241                 default:
1242                     // unknown public key type
1243                     authType = "UNKNOWN";
1244             }
1245 
1246             try {
1247                 X509TrustManager tm = shc.sslContext.getX509TrustManager();
1248                 if (tm instanceof X509ExtendedTrustManager) {
1249                     if (shc.conContext.transport instanceof SSLEngine) {
1250                         SSLEngine engine = (SSLEngine)shc.conContext.transport;
1251                         ((X509ExtendedTrustManager)tm).checkClientTrusted(
1252                             certs.clone(),
1253                             authType,
1254                             engine);
1255                     } else {
1256                         SSLSocket socket = (SSLSocket)shc.conContext.transport;
1257                         ((X509ExtendedTrustManager)tm).checkClientTrusted(
1258                             certs.clone(),
1259                             authType,
1260                             socket);
1261                     }
1262                 } else {
1263                     // Unlikely to happen, because we have wrapped the old
1264                     // X509TrustManager with the new X509ExtendedTrustManager.
1265                     throw new CertificateException(
1266                             "Improper X509TrustManager implementation");
1267                 }
1268 
1269                 // Once the client certificate chain has been validated, set
1270                 // the certificate chain in the TLS session.
1271                 shc.handshakeSession.setPeerCertificates(certs);
1272             } catch (CertificateException ce) {
1273                 shc.conContext.fatal(Alert.CERTIFICATE_UNKNOWN, ce);
1274             }
1275 
1276             return certs;
1277         }
1278 
1279         private static X509Certificate[] checkServerCerts(
1280                 ClientHandshakeContext chc,
1281                 List<CertificateEntry> certEntries) throws IOException {
1282             X509Certificate[] certs =
1283                     new X509Certificate[certEntries.size()];
1284             try {
1285                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
1286                 int i = 0;
1287                 for (CertificateEntry entry : certEntries) {
1288                     certs[i++] = (X509Certificate)cf.generateCertificate(
1289                                     new ByteArrayInputStream(entry.encoded));
1290                 }
1291             } catch (CertificateException ce) {
1292                 chc.conContext.fatal(Alert.BAD_CERTIFICATE,
1293                     "Failed to parse server certificates", ce);
1294             }
1295 
1296             // find out the types of server authentication used
1297             //
1298             // Note that the "UNKNOWN" authentication type is sufficient to
1299             // check the required digitalSignature KeyUsage for TLS 1.3.
1300             String authType = "UNKNOWN";
1301 
1302             try {
1303                 X509TrustManager tm = chc.sslContext.getX509TrustManager();
1304                 if (tm instanceof X509ExtendedTrustManager) {
1305                     if (chc.conContext.transport instanceof SSLEngine) {
1306                         SSLEngine engine = (SSLEngine)chc.conContext.transport;
1307                         ((X509ExtendedTrustManager)tm).checkServerTrusted(
1308                             certs.clone(),
1309                             authType,
1310                             engine);
1311                     } else {
1312                         SSLSocket socket = (SSLSocket)chc.conContext.transport;
1313                         ((X509ExtendedTrustManager)tm).checkServerTrusted(
1314                             certs.clone(),
1315                             authType,
1316                             socket);
1317                     }
1318                 } else {
1319                     // Unlikely to happen, because we have wrapped the old
1320                     // X509TrustManager with the new X509ExtendedTrustManager.
1321                     throw new CertificateException(
1322                             "Improper X509TrustManager implementation");
1323                 }
1324 
1325                 // Once the server certificate chain has been validated, set
1326                 // the certificate chain in the TLS session.
1327                 chc.handshakeSession.setPeerCertificates(certs);
1328             } catch (CertificateException ce) {
1329                 chc.conContext.fatal(getCertificateAlert(chc, ce), ce);
1330             }
1331 
1332             return certs;
1333         }
1334 
1335         /**
1336          * When a failure happens during certificate checking from an
1337          * {@link X509TrustManager}, determine what TLS alert description
1338          * to use.
1339          *
1340          * @param cexc The exception thrown by the {@link X509TrustManager}
1341          *
1342          * @return A byte value corresponding to a TLS alert description number.
1343          */
1344         private static Alert getCertificateAlert(
1345                 ClientHandshakeContext chc, CertificateException cexc) {
1346             // The specific reason for the failure will determine how to
1347             // set the alert description value
1348             Alert alert = Alert.CERTIFICATE_UNKNOWN;
1349 
1350             Throwable baseCause = cexc.getCause();
1351             if (baseCause instanceof CertPathValidatorException) {
1352                 CertPathValidatorException cpve =
1353                         (CertPathValidatorException)baseCause;
1354                 Reason reason = cpve.getReason();
1355                 if (reason == BasicReason.REVOKED) {
1356                     alert = chc.staplingActive ?
1357                             Alert.BAD_CERT_STATUS_RESPONSE :
1358                             Alert.CERTIFICATE_REVOKED;
1359                 } else if (
1360                         reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) {
1361                     alert = chc.staplingActive ?
1362                             Alert.BAD_CERT_STATUS_RESPONSE :
1363                             Alert.CERTIFICATE_UNKNOWN;
1364                 }
1365             }
1366 
1367             return alert;
1368         }
1369     }
1370 }