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