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