src/java.base/share/classes/sun/security/ssl/CertificateMessage.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
child 56559 a423173d0578
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
       
     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 sun.security.ssl.CertificateMessage.T12CertificateMessage;
       
    57 import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED;
       
    58 import sun.security.ssl.ClientHello.ClientHelloMessage;
       
    59 import sun.security.ssl.SSLHandshake.HandshakeMessage;
       
    60 import sun.security.ssl.X509Authentication.X509Credentials;
       
    61 import sun.security.ssl.X509Authentication.X509Possession;
       
    62 
       
    63 /**
       
    64  * Pack of the CertificateMessage handshake message.
       
    65  */
       
    66 final class CertificateMessage {
       
    67     static final SSLConsumer t12HandshakeConsumer =
       
    68         new T12CertificateConsumer();
       
    69     static final HandshakeProducer t12HandshakeProducer =
       
    70         new T12CertificateProducer();
       
    71 
       
    72     static final SSLConsumer t13HandshakeConsumer =
       
    73         new T13CertificateConsumer();
       
    74     static final HandshakeProducer t13HandshakeProducer =
       
    75         new T13CertificateProducer();
       
    76 
       
    77     /**
       
    78      * The Certificate handshake message for TLS 1.2 and previous
       
    79      * SSL/TLS protocol versions.
       
    80      *
       
    81      * In server mode, the certificate handshake message is sent whenever the
       
    82      * agreed-upon key exchange method uses certificates for authentication.
       
    83      * In client mode, this message is only sent if the server requests a
       
    84      * certificate for client authentication.
       
    85      *
       
    86      *       opaque ASN.1Cert<1..2^24-1>;
       
    87      *
       
    88      * SSL 3.0:
       
    89      *       struct {
       
    90      *           ASN.1Cert certificate_list<1..2^24-1>;
       
    91      *       } Certificate;
       
    92      * Note: For SSL 3.0 client authentication, if no suitable certificate
       
    93      * is available, the client should send a no_certificate alert instead.
       
    94      * This alert is only a warning; however, the server may respond with
       
    95      * a fatal handshake failure alert if client authentication is required.
       
    96      *
       
    97      * TLS 1.0/1.1/1.2:
       
    98      *       struct {
       
    99      *           ASN.1Cert certificate_list<0..2^24-1>;
       
   100      *       } Certificate;
       
   101      */
       
   102     static final class T12CertificateMessage extends HandshakeMessage {
       
   103         final List<byte[]> encodedCertChain;
       
   104 
       
   105         T12CertificateMessage(HandshakeContext handshakeContext,
       
   106                 X509Certificate[] certChain) throws SSLException {
       
   107             super(handshakeContext);
       
   108 
       
   109             List<byte[]> encodedCerts = new ArrayList<>(certChain.length);
       
   110             for (X509Certificate cert : certChain) {
       
   111                 try {
       
   112                     encodedCerts.add(cert.getEncoded());
       
   113                 } catch (CertificateEncodingException cee) {
       
   114                     // unlikely
       
   115                     handshakeContext.conContext.fatal(Alert.INTERNAL_ERROR,
       
   116                             "Could not encode certificate (" +
       
   117                             cert.getSubjectX500Principal() + ")", cee);
       
   118                     break;      // make the complier happy
       
   119                 }
       
   120             }
       
   121 
       
   122             this.encodedCertChain = encodedCerts;
       
   123         }
       
   124 
       
   125         T12CertificateMessage(HandshakeContext handshakeContext,
       
   126                 ByteBuffer m) throws IOException {
       
   127             super(handshakeContext);
       
   128 
       
   129             int listLen = Record.getInt24(m);
       
   130             if (listLen > m.remaining()) {
       
   131                 handshakeContext.conContext.fatal(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                 shc.conContext.fatal(Alert.INTERNAL_ERROR,
       
   253                     "No expected X.509 certificate for server authentication");
       
   254 
       
   255                 return null;        // make the compiler happy
       
   256             }
       
   257 
       
   258             shc.handshakeSession.setLocalPrivateKey(
       
   259                     x509Possession.popPrivateKey);
       
   260             shc.handshakeSession.setLocalCertificates(x509Possession.popCerts);
       
   261             T12CertificateMessage cm =
       
   262                     new T12CertificateMessage(shc, x509Possession.popCerts);
       
   263             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   264                 SSLLogger.fine(
       
   265                     "Produced server Certificate handshake message", cm);
       
   266             }
       
   267 
       
   268             // Output the handshake message.
       
   269             cm.write(shc.handshakeOutput);
       
   270             shc.handshakeOutput.flush();
       
   271 
       
   272             // The handshake message has been delivered.
       
   273             return null;
       
   274         }
       
   275 
       
   276         private byte[] onProduceCertificate(ClientHandshakeContext chc,
       
   277                 SSLHandshake.HandshakeMessage message) throws IOException {
       
   278             X509Possession x509Possession = null;
       
   279             for (SSLPossession possession : chc.handshakePossessions) {
       
   280                 if (possession instanceof X509Possession) {
       
   281                     x509Possession = (X509Possession)possession;
       
   282                     break;
       
   283                 }
       
   284             }
       
   285 
       
   286             // Report to the server if no appropriate cert was found.  For
       
   287             // SSL 3.0, send a no_certificate alert;  TLS 1.0/1.1/1.2 uses
       
   288             // an empty cert chain instead.
       
   289             if (x509Possession == null) {
       
   290                 if (chc.negotiatedProtocol.useTLS10PlusSpec()) {
       
   291                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   292                         SSLLogger.fine(
       
   293                             "No X.509 certificate for client authentication, " +
       
   294                             "use empty Certificate message instead");
       
   295                     }
       
   296 
       
   297                     x509Possession =
       
   298                             new X509Possession(null, new X509Certificate[0]);
       
   299                 } else {
       
   300                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   301                         SSLLogger.fine(
       
   302                             "No X.509 certificate for client authentication, " +
       
   303                             "send a no_certificate alert");
       
   304                     }
       
   305 
       
   306                     chc.conContext.warning(Alert.NO_CERTIFICATE);
       
   307                     return null;
       
   308                 }
       
   309             }
       
   310 
       
   311             chc.handshakeSession.setLocalPrivateKey(
       
   312                     x509Possession.popPrivateKey);
       
   313             if (x509Possession.popCerts != null &&
       
   314                     x509Possession.popCerts.length != 0) {
       
   315                 chc.handshakeSession.setLocalCertificates(
       
   316                         x509Possession.popCerts);
       
   317             } else {
       
   318                 chc.handshakeSession.setLocalCertificates(null);
       
   319             }
       
   320             T12CertificateMessage cm =
       
   321                     new T12CertificateMessage(chc, x509Possession.popCerts);
       
   322             if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   323                 SSLLogger.fine(
       
   324                     "Produced client Certificate handshake message", cm);
       
   325             }
       
   326 
       
   327             // Output the handshake message.
       
   328             cm.write(chc.handshakeOutput);
       
   329             chc.handshakeOutput.flush();
       
   330 
       
   331             // The handshake message has been delivered.
       
   332             return null;
       
   333         }
       
   334     }
       
   335 
       
   336     /**
       
   337      * The "Certificate" handshake message consumer for TLS 1.2 and
       
   338      * previous SSL/TLS protocol versions.
       
   339      */
       
   340     static final
       
   341             class T12CertificateConsumer implements SSLConsumer {
       
   342         // Prevent instantiation of this class.
       
   343         private T12CertificateConsumer() {
       
   344             // blank
       
   345         }
       
   346 
       
   347         @Override
       
   348         public void consume(ConnectionContext context,
       
   349                 ByteBuffer message) throws IOException {
       
   350             // The consuming happens in handshake context only.
       
   351             HandshakeContext hc = (HandshakeContext)context;
       
   352 
       
   353             // clean up this consumer
       
   354             hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id);
       
   355 
       
   356             T12CertificateMessage cm = new T12CertificateMessage(hc, message);
       
   357             if (hc.sslConfig.isClientMode) {
       
   358                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   359                     SSLLogger.fine(
       
   360                         "Consuming server Certificate handshake message", cm);
       
   361                 }
       
   362                 onCertificate((ClientHandshakeContext)context, cm);
       
   363             } else {
       
   364                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   365                     SSLLogger.fine(
       
   366                         "Consuming client Certificate handshake message", cm);
       
   367                 }
       
   368                 onCertificate((ServerHandshakeContext)context, cm);
       
   369             }
       
   370         }
       
   371 
       
   372         private void onCertificate(ServerHandshakeContext shc,
       
   373                 T12CertificateMessage certificateMessage )throws IOException {
       
   374             List<byte[]> encodedCerts = certificateMessage.encodedCertChain;
       
   375             if (encodedCerts == null || encodedCerts.isEmpty()) {
       
   376                 if (shc.sslConfig.clientAuthType !=
       
   377                         ClientAuthType.CLIENT_AUTH_REQUESTED) {
       
   378                     // unexpected or require client authentication
       
   379                     shc.conContext.fatal(Alert.BAD_CERTIFICATE,
       
   380                         "Empty server certificate chain");
       
   381                 } else {
       
   382                     return;
       
   383                 }
       
   384             }
       
   385 
       
   386             X509Certificate[] x509Certs =
       
   387                     new X509Certificate[encodedCerts.size()];
       
   388             try {
       
   389                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
       
   390                 int i = 0;
       
   391                 for (byte[] encodedCert : encodedCerts) {
       
   392                     x509Certs[i++] = (X509Certificate)cf.generateCertificate(
       
   393                                     new ByteArrayInputStream(encodedCert));
       
   394                 }
       
   395             } catch (CertificateException ce) {
       
   396                 shc.conContext.fatal(Alert.BAD_CERTIFICATE,
       
   397                     "Failed to parse server certificates", ce);
       
   398             }
       
   399 
       
   400             checkClientCerts(shc, x509Certs);
       
   401 
       
   402             //
       
   403             // update
       
   404             //
       
   405             shc.handshakeCredentials.add(
       
   406                 new X509Credentials(x509Certs[0].getPublicKey(), x509Certs));
       
   407             shc.handshakeSession.setPeerCertificates(x509Certs);
       
   408         }
       
   409 
       
   410         private void onCertificate(ClientHandshakeContext chc,
       
   411                 T12CertificateMessage certificateMessage) throws IOException {
       
   412             List<byte[]> encodedCerts = certificateMessage.encodedCertChain;
       
   413             if (encodedCerts == null || encodedCerts.isEmpty()) {
       
   414                 chc.conContext.fatal(Alert.BAD_CERTIFICATE,
       
   415                     "Empty server certificate chain");
       
   416             }
       
   417 
       
   418             X509Certificate[] x509Certs =
       
   419                     new X509Certificate[encodedCerts.size()];
       
   420             try {
       
   421                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
       
   422                 int i = 0;
       
   423                 for (byte[] encodedCert : encodedCerts) {
       
   424                     x509Certs[i++] = (X509Certificate)cf.generateCertificate(
       
   425                                     new ByteArrayInputStream(encodedCert));
       
   426                 }
       
   427             } catch (CertificateException ce) {
       
   428                 chc.conContext.fatal(Alert.BAD_CERTIFICATE,
       
   429                     "Failed to parse server certificates", ce);
       
   430             }
       
   431 
       
   432             // Allow server certificate change in client side during
       
   433             // renegotiation after a session-resumption abbreviated
       
   434             // initial handshake?
       
   435             //
       
   436             // DO NOT need to check allowUnsafeServerCertChange here. We only
       
   437             // reserve server certificates when allowUnsafeServerCertChange is
       
   438             // flase.
       
   439             if (chc.reservedServerCerts != null) {
       
   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.length() == 0) &&
       
   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             if (keyAlgorithm.equals("RSA")) {
       
   655                 authType = "RSA";
       
   656             } else if (keyAlgorithm.equals("DSA")) {
       
   657                 authType = "DSA";
       
   658             } else if (keyAlgorithm.equals("EC")) {
       
   659                 authType = "EC";
       
   660             } else {
       
   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                 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                 // TODO: shall we use the Certificate for the session?
       
   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 scheme: " + ss.name);
       
  1040                     }
       
  1041                     checkedKeyTypes.add(ss.keyAlgorithm);
       
  1042                     continue;
       
  1043                 }
       
  1044 
       
  1045                 SSLAuthentication ka =
       
  1046                         X509Authentication.nameOf(ss.keyAlgorithm);
       
  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;    // make the complier happy
       
  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                     // TODO: check extensions
       
  1226                 }
       
  1227             } catch (CertificateException ce) {
       
  1228                 shc.conContext.fatal(Alert.BAD_CERTIFICATE,
       
  1229                     "Failed to parse server certificates", ce);
       
  1230             }
       
  1231 
       
  1232             // find out the types of client authentication used
       
  1233             String keyAlgorithm = certs[0].getPublicKey().getAlgorithm();
       
  1234             String authType;
       
  1235             switch (keyAlgorithm) {
       
  1236                 case "RSA":
       
  1237                     authType = "RSA";
       
  1238                     break;
       
  1239                 case "DSA":
       
  1240                     authType = "DSA";
       
  1241                     break;
       
  1242                 case "EC":
       
  1243                     authType = "EC";
       
  1244                     break;
       
  1245                 default:
       
  1246                     // unknown public key type
       
  1247                     authType = "UNKNOWN";
       
  1248                     break;
       
  1249             }
       
  1250 
       
  1251             try {
       
  1252                 X509TrustManager tm = shc.sslContext.getX509TrustManager();
       
  1253                 if (tm instanceof X509ExtendedTrustManager) {
       
  1254                     if (shc.conContext.transport instanceof SSLEngine) {
       
  1255                         SSLEngine engine = (SSLEngine)shc.conContext.transport;
       
  1256                         ((X509ExtendedTrustManager)tm).checkClientTrusted(
       
  1257                             certs.clone(),
       
  1258                             authType,
       
  1259                             engine);
       
  1260                     } else {
       
  1261                         SSLSocket socket = (SSLSocket)shc.conContext.transport;
       
  1262                         ((X509ExtendedTrustManager)tm).checkClientTrusted(
       
  1263                             certs.clone(),
       
  1264                             authType,
       
  1265                             socket);
       
  1266                     }
       
  1267                 } else {
       
  1268                     // Unlikely to happen, because we have wrapped the old
       
  1269                     // X509TrustManager with the new X509ExtendedTrustManager.
       
  1270                     throw new CertificateException(
       
  1271                             "Improper X509TrustManager implementation");
       
  1272                 }
       
  1273 
       
  1274                 // Once the client certificate chain has been validated, set
       
  1275                 // the certificate chain in the TLS session.
       
  1276                 shc.handshakeSession.setPeerCertificates(certs);
       
  1277             } catch (CertificateException ce) {
       
  1278                 // TODO: A more precise alert should be used.
       
  1279                 shc.conContext.fatal(Alert.CERTIFICATE_UNKNOWN, ce);
       
  1280             }
       
  1281 
       
  1282             return certs;
       
  1283         }
       
  1284 
       
  1285         private static X509Certificate[] checkServerCerts(
       
  1286                 ClientHandshakeContext chc,
       
  1287                 List<CertificateEntry> certEntries) throws IOException {
       
  1288             X509Certificate[] certs =
       
  1289                     new X509Certificate[certEntries.size()];
       
  1290             try {
       
  1291                 CertificateFactory cf = CertificateFactory.getInstance("X.509");
       
  1292                 int i = 0;
       
  1293                 for (CertificateEntry entry : certEntries) {
       
  1294                     certs[i++] = (X509Certificate)cf.generateCertificate(
       
  1295                                     new ByteArrayInputStream(entry.encoded));
       
  1296                     // TODO: check extensions
       
  1297                 }
       
  1298             } catch (CertificateException ce) {
       
  1299                 chc.conContext.fatal(Alert.BAD_CERTIFICATE,
       
  1300                     "Failed to parse server certificates", ce);
       
  1301             }
       
  1302 
       
  1303             // find out the types of client authentication used
       
  1304             /*
       
  1305             String keyAlgorithm = certs[0].getPublicKey().getAlgorithm();
       
  1306             String authType;
       
  1307             switch (keyAlgorithm) {
       
  1308                 case "RSA":
       
  1309                     authType = "RSA";
       
  1310                     break;
       
  1311                 case "DSA":
       
  1312                     authType = "DSA";
       
  1313                     break;
       
  1314                 case "EC":
       
  1315                     authType = "EC";
       
  1316                     break;
       
  1317                 default:
       
  1318                     // unknown public key type
       
  1319                     authType = "UNKNOWN";
       
  1320                     break;
       
  1321             }
       
  1322             */
       
  1323             String authType = "UNKNOWN";
       
  1324 
       
  1325             try {
       
  1326                 X509TrustManager tm = chc.sslContext.getX509TrustManager();
       
  1327                 if (tm instanceof X509ExtendedTrustManager) {
       
  1328                     if (chc.conContext.transport instanceof SSLEngine) {
       
  1329                         SSLEngine engine = (SSLEngine)chc.conContext.transport;
       
  1330                         ((X509ExtendedTrustManager)tm).checkServerTrusted(
       
  1331                             certs.clone(),
       
  1332                             authType,
       
  1333                             engine);
       
  1334                     } else {
       
  1335                         SSLSocket socket = (SSLSocket)chc.conContext.transport;
       
  1336                         ((X509ExtendedTrustManager)tm).checkServerTrusted(
       
  1337                             certs.clone(),
       
  1338                             authType,
       
  1339                             socket);
       
  1340                     }
       
  1341                 } else {
       
  1342                     // Unlikely to happen, because we have wrapped the old
       
  1343                     // X509TrustManager with the new X509ExtendedTrustManager.
       
  1344                     throw new CertificateException(
       
  1345                             "Improper X509TrustManager implementation");
       
  1346                 }
       
  1347 
       
  1348                 // Once the server certificate chain has been validated, set
       
  1349                 // the certificate chain in the TLS session.
       
  1350                 chc.handshakeSession.setPeerCertificates(certs);
       
  1351             } catch (CertificateException ce) {
       
  1352                 chc.conContext.fatal(getCertificateAlert(chc, ce), ce);
       
  1353             }
       
  1354 
       
  1355             return certs;
       
  1356         }
       
  1357 
       
  1358         /**
       
  1359          * When a failure happens during certificate checking from an
       
  1360          * {@link X509TrustManager}, determine what TLS alert description
       
  1361          * to use.
       
  1362          *
       
  1363          * @param cexc The exception thrown by the {@link X509TrustManager}
       
  1364          *
       
  1365          * @return A byte value corresponding to a TLS alert description number.
       
  1366          */
       
  1367         private static Alert getCertificateAlert(
       
  1368                 ClientHandshakeContext chc, CertificateException cexc) {
       
  1369             // The specific reason for the failure will determine how to
       
  1370             // set the alert description value
       
  1371             Alert alert = Alert.CERTIFICATE_UNKNOWN;
       
  1372 
       
  1373             Throwable baseCause = cexc.getCause();
       
  1374             if (baseCause instanceof CertPathValidatorException) {
       
  1375                 CertPathValidatorException cpve =
       
  1376                         (CertPathValidatorException)baseCause;
       
  1377                 Reason reason = cpve.getReason();
       
  1378                 if (reason == BasicReason.REVOKED) {
       
  1379                     alert = chc.staplingActive ?
       
  1380                             Alert.BAD_CERT_STATUS_RESPONSE :
       
  1381                             Alert.CERTIFICATE_REVOKED;
       
  1382                 } else if (
       
  1383                         reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) {
       
  1384                     alert = chc.staplingActive ?
       
  1385                             Alert.BAD_CERT_STATUS_RESPONSE :
       
  1386                             Alert.CERTIFICATE_UNKNOWN;
       
  1387                 }
       
  1388             }
       
  1389 
       
  1390             return alert;
       
  1391         }
       
  1392     }
       
  1393 }