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 
T12CertificateMessage(HandshakeContext handshakeContext, X509Certificate[] certChain)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 
T12CertificateMessage(HandshakeContext handshakeContext, ByteBuffer m)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
handshakeType()148         public SSLHandshake handshakeType() {
149             return SSLHandshake.CERTIFICATE;
150         }
151 
152         @Override
messageLength()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
send(HandshakeOutStream hos)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
toString()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.
T12CertificateProducer()223         private T12CertificateProducer() {
224             // blank
225         }
226 
227         @Override
produce(ConnectionContext context, HandshakeMessage message)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 
onProduceCertificate(ServerHandshakeContext shc, SSLHandshake.HandshakeMessage message)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 
onProduceCertificate(ClientHandshakeContext chc, SSLHandshake.HandshakeMessage message)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.
T12CertificateConsumer()341         private T12CertificateConsumer() {
342             // blank
343         }
344 
345         @Override
consume(ConnectionContext context, ByteBuffer message)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 
onCertificate(ServerHandshakeContext shc, T12CertificateMessage certificateMessage )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 
onCertificate(ClientHandshakeContext chc, T12CertificateMessage certificateMessage)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.isEmpty()) &&
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          */
isIdentityEquivalent(X509Certificate thisCert, X509Certificate prevCert)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          */
getSubjectAltNames( Collection<List<?>> subjectAltNames, int type)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 
isEquivalent(Collection<String> thisSubAltNames, Collection<String> prevSubAltNames)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          */
checkServerCerts(ClientHandshakeContext chc, X509Certificate[] certs)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 
checkClientCerts(ServerHandshakeContext shc, X509Certificate[] certs)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          */
getCertificateAlert( ClientHandshakeContext chc, CertificateException cexc)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 
CertificateEntry(byte[] encoded, SSLExtensions extensions)735         CertificateEntry(byte[] encoded, SSLExtensions extensions) {
736             this.encoded = encoded;
737             this.extensions = extensions;
738         }
739 
getEncodedSize()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
toString()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 
T13CertificateMessage(HandshakeContext context, byte[] requestContext, X509Certificate[] certificates)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 
T13CertificateMessage(HandshakeContext handshakeContext, byte[] requestContext, List<CertificateEntry> certificates)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 
T13CertificateMessage(HandshakeContext handshakeContext, ByteBuffer m)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
handshakeType()857         public SSLHandshake handshakeType() {
858             return SSLHandshake.CERTIFICATE;
859         }
860 
861         @Override
messageLength()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
send(HandshakeOutStream hos)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
toString()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.
T13CertificateProducer()920         private T13CertificateProducer() {
921             // blank
922         }
923 
924         @Override
produce(ConnectionContext context, HandshakeMessage message)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 
onProduceCertificate(ServerHandshakeContext shc, HandshakeMessage message)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 
choosePossession( HandshakeContext hc, ClientHelloMessage clientHello)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 
onProduceCertificate(ClientHandshakeContext chc, HandshakeMessage message)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.
T13CertificateConsumer()1128         private T13CertificateConsumer() {
1129             // blank
1130         }
1131 
1132         @Override
consume(ConnectionContext context, ByteBuffer message)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 
onConsumeCertificate(ServerHandshakeContext shc, T13CertificateMessage certificateMessage )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 
onConsumeCertificate(ClientHandshakeContext chc, T13CertificateMessage certificateMessage )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 
checkClientCerts( ServerHandshakeContext shc, List<CertificateEntry> certEntries)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 
checkServerCerts( ClientHandshakeContext chc, List<CertificateEntry> certEntries)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          */
getCertificateAlert( ClientHandshakeContext chc, CertificateException cexc)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 }
1366