Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java
41159 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.algorithmConstraints,
1059
hc.peerRequestedSignatureSchemes,
1060
ss, hc.negotiatedProtocol) == null) {
1061
1062
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1063
SSLLogger.warning(
1064
"Unable to produce CertificateVerify for " +
1065
"signature scheme: " + ss.name);
1066
}
1067
checkedKeyTypes.add(ss.keyAlgorithm);
1068
continue;
1069
}
1070
1071
SSLAuthentication ka = X509Authentication.valueOf(ss);
1072
if (ka == null) {
1073
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1074
SSLLogger.warning(
1075
"Unsupported authentication scheme: " + ss.name);
1076
}
1077
checkedKeyTypes.add(ss.keyAlgorithm);
1078
continue;
1079
}
1080
1081
SSLPossession pos = ka.createPossession(hc);
1082
if (pos == null) {
1083
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1084
SSLLogger.warning(
1085
"Unavailable authentication scheme: " + ss.name);
1086
}
1087
continue;
1088
}
1089
1090
return pos;
1091
}
1092
1093
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1094
SSLLogger.warning("No available authentication scheme");
1095
}
1096
return null;
1097
}
1098
1099
private byte[] onProduceCertificate(ClientHandshakeContext chc,
1100
HandshakeMessage message) throws IOException {
1101
ClientHelloMessage clientHello = (ClientHelloMessage)message;
1102
SSLPossession pos = choosePossession(chc, clientHello);
1103
X509Certificate[] localCerts;
1104
if (pos == null) {
1105
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1106
SSLLogger.fine("No available client authentication scheme");
1107
}
1108
localCerts = new X509Certificate[0];
1109
} else {
1110
chc.handshakePossessions.add(pos);
1111
if (!(pos instanceof X509Possession)) {
1112
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1113
SSLLogger.fine(
1114
"No X.509 certificate for client authentication");
1115
}
1116
localCerts = new X509Certificate[0];
1117
} else {
1118
X509Possession x509Possession = (X509Possession)pos;
1119
localCerts = x509Possession.popCerts;
1120
chc.handshakeSession.setLocalPrivateKey(
1121
x509Possession.popPrivateKey);
1122
}
1123
}
1124
1125
if (localCerts != null && localCerts.length != 0) {
1126
chc.handshakeSession.setLocalCertificates(localCerts);
1127
} else {
1128
chc.handshakeSession.setLocalCertificates(null);
1129
}
1130
1131
T13CertificateMessage cm;
1132
try {
1133
cm = new T13CertificateMessage(
1134
chc, chc.certRequestContext, localCerts);
1135
} catch (SSLException | CertificateException ce) {
1136
throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1137
"Failed to produce client Certificate message", ce);
1138
}
1139
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1140
SSLLogger.fine("Produced client Certificate message", cm);
1141
}
1142
1143
// Output the handshake message.
1144
cm.write(chc.handshakeOutput);
1145
chc.handshakeOutput.flush();
1146
1147
// The handshake message has been delivered.
1148
return null;
1149
}
1150
}
1151
1152
/**
1153
* The "Certificate" handshake message consumer for TLS 1.3.
1154
*/
1155
private static final class T13CertificateConsumer implements SSLConsumer {
1156
// Prevent instantiation of this class.
1157
private T13CertificateConsumer() {
1158
// blank
1159
}
1160
1161
@Override
1162
public void consume(ConnectionContext context,
1163
ByteBuffer message) throws IOException {
1164
// The consuming happens in handshake context only.
1165
HandshakeContext hc = (HandshakeContext)context;
1166
1167
// clean up this consumer
1168
hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id);
1169
T13CertificateMessage cm = new T13CertificateMessage(hc, message);
1170
if (hc.sslConfig.isClientMode) {
1171
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1172
SSLLogger.fine(
1173
"Consuming server Certificate handshake message", cm);
1174
}
1175
onConsumeCertificate((ClientHandshakeContext)context, cm);
1176
} else {
1177
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1178
SSLLogger.fine(
1179
"Consuming client Certificate handshake message", cm);
1180
}
1181
onConsumeCertificate((ServerHandshakeContext)context, cm);
1182
}
1183
}
1184
1185
private void onConsumeCertificate(ServerHandshakeContext shc,
1186
T13CertificateMessage certificateMessage )throws IOException {
1187
if (certificateMessage.certEntries == null ||
1188
certificateMessage.certEntries.isEmpty()) {
1189
// For empty Certificate messages, we should not expect
1190
// a CertificateVerify message to follow
1191
shc.handshakeConsumers.remove(
1192
SSLHandshake.CERTIFICATE_VERIFY.id);
1193
if (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED) {
1194
throw shc.conContext.fatal(Alert.BAD_CERTIFICATE,
1195
"Empty client certificate chain");
1196
} else {
1197
// optional client authentication
1198
return;
1199
}
1200
}
1201
1202
// check client certificate entries
1203
X509Certificate[] cliCerts =
1204
checkClientCerts(shc, certificateMessage.certEntries);
1205
1206
//
1207
// update
1208
//
1209
shc.handshakeCredentials.add(
1210
new X509Credentials(cliCerts[0].getPublicKey(), cliCerts));
1211
shc.handshakeSession.setPeerCertificates(cliCerts);
1212
}
1213
1214
private void onConsumeCertificate(ClientHandshakeContext chc,
1215
T13CertificateMessage certificateMessage )throws IOException {
1216
if (certificateMessage.certEntries == null ||
1217
certificateMessage.certEntries.isEmpty()) {
1218
throw chc.conContext.fatal(Alert.BAD_CERTIFICATE,
1219
"Empty server certificate chain");
1220
}
1221
1222
// Each CertificateEntry will have its own set of extensions
1223
// which must be consumed.
1224
SSLExtension[] enabledExtensions =
1225
chc.sslConfig.getEnabledExtensions(SSLHandshake.CERTIFICATE);
1226
for (CertificateEntry certEnt : certificateMessage.certEntries) {
1227
certEnt.extensions.consumeOnLoad(chc, enabledExtensions);
1228
}
1229
1230
// check server certificate entries
1231
X509Certificate[] srvCerts =
1232
checkServerCerts(chc, certificateMessage.certEntries);
1233
1234
//
1235
// update
1236
//
1237
chc.handshakeCredentials.add(
1238
new X509Credentials(srvCerts[0].getPublicKey(), srvCerts));
1239
chc.handshakeSession.setPeerCertificates(srvCerts);
1240
}
1241
1242
private static X509Certificate[] checkClientCerts(
1243
ServerHandshakeContext shc,
1244
List<CertificateEntry> certEntries) throws IOException {
1245
X509Certificate[] certs =
1246
new X509Certificate[certEntries.size()];
1247
try {
1248
CertificateFactory cf = CertificateFactory.getInstance("X.509");
1249
int i = 0;
1250
for (CertificateEntry entry : certEntries) {
1251
certs[i++] = (X509Certificate)cf.generateCertificate(
1252
new ByteArrayInputStream(entry.encoded));
1253
}
1254
} catch (CertificateException ce) {
1255
throw shc.conContext.fatal(Alert.BAD_CERTIFICATE,
1256
"Failed to parse server certificates", ce);
1257
}
1258
1259
// find out the types of client authentication used
1260
String keyAlgorithm = certs[0].getPublicKey().getAlgorithm();
1261
String authType;
1262
switch (keyAlgorithm) {
1263
case "RSA":
1264
case "DSA":
1265
case "EC":
1266
case "RSASSA-PSS":
1267
authType = keyAlgorithm;
1268
break;
1269
default:
1270
// unknown public key type
1271
authType = "UNKNOWN";
1272
}
1273
1274
try {
1275
X509TrustManager tm = shc.sslContext.getX509TrustManager();
1276
if (tm instanceof X509ExtendedTrustManager) {
1277
if (shc.conContext.transport instanceof SSLEngine) {
1278
SSLEngine engine = (SSLEngine)shc.conContext.transport;
1279
((X509ExtendedTrustManager)tm).checkClientTrusted(
1280
certs.clone(),
1281
authType,
1282
engine);
1283
} else {
1284
SSLSocket socket = (SSLSocket)shc.conContext.transport;
1285
((X509ExtendedTrustManager)tm).checkClientTrusted(
1286
certs.clone(),
1287
authType,
1288
socket);
1289
}
1290
} else {
1291
// Unlikely to happen, because we have wrapped the old
1292
// X509TrustManager with the new X509ExtendedTrustManager.
1293
throw new CertificateException(
1294
"Improper X509TrustManager implementation");
1295
}
1296
1297
// Once the client certificate chain has been validated, set
1298
// the certificate chain in the TLS session.
1299
shc.handshakeSession.setPeerCertificates(certs);
1300
} catch (CertificateException ce) {
1301
throw shc.conContext.fatal(Alert.CERTIFICATE_UNKNOWN, ce);
1302
}
1303
1304
return certs;
1305
}
1306
1307
private static X509Certificate[] checkServerCerts(
1308
ClientHandshakeContext chc,
1309
List<CertificateEntry> certEntries) throws IOException {
1310
X509Certificate[] certs =
1311
new X509Certificate[certEntries.size()];
1312
try {
1313
CertificateFactory cf = CertificateFactory.getInstance("X.509");
1314
int i = 0;
1315
for (CertificateEntry entry : certEntries) {
1316
certs[i++] = (X509Certificate)cf.generateCertificate(
1317
new ByteArrayInputStream(entry.encoded));
1318
}
1319
} catch (CertificateException ce) {
1320
throw chc.conContext.fatal(Alert.BAD_CERTIFICATE,
1321
"Failed to parse server certificates", ce);
1322
}
1323
1324
// find out the types of server authentication used
1325
//
1326
// Note that the "UNKNOWN" authentication type is sufficient to
1327
// check the required digitalSignature KeyUsage for TLS 1.3.
1328
String authType = "UNKNOWN";
1329
1330
try {
1331
X509TrustManager tm = chc.sslContext.getX509TrustManager();
1332
if (tm instanceof X509ExtendedTrustManager) {
1333
if (chc.conContext.transport instanceof SSLEngine) {
1334
SSLEngine engine = (SSLEngine)chc.conContext.transport;
1335
((X509ExtendedTrustManager)tm).checkServerTrusted(
1336
certs.clone(),
1337
authType,
1338
engine);
1339
} else {
1340
SSLSocket socket = (SSLSocket)chc.conContext.transport;
1341
((X509ExtendedTrustManager)tm).checkServerTrusted(
1342
certs.clone(),
1343
authType,
1344
socket);
1345
}
1346
} else {
1347
// Unlikely to happen, because we have wrapped the old
1348
// X509TrustManager with the new X509ExtendedTrustManager.
1349
throw new CertificateException(
1350
"Improper X509TrustManager implementation");
1351
}
1352
1353
// Once the server certificate chain has been validated, set
1354
// the certificate chain in the TLS session.
1355
chc.handshakeSession.setPeerCertificates(certs);
1356
} catch (CertificateException ce) {
1357
throw chc.conContext.fatal(getCertificateAlert(chc, ce), ce);
1358
}
1359
1360
return certs;
1361
}
1362
1363
/**
1364
* When a failure happens during certificate checking from an
1365
* {@link X509TrustManager}, determine what TLS alert description
1366
* to use.
1367
*
1368
* @param cexc The exception thrown by the {@link X509TrustManager}
1369
*
1370
* @return A byte value corresponding to a TLS alert description number.
1371
*/
1372
private static Alert getCertificateAlert(
1373
ClientHandshakeContext chc, CertificateException cexc) {
1374
// The specific reason for the failure will determine how to
1375
// set the alert description value
1376
Alert alert = Alert.CERTIFICATE_UNKNOWN;
1377
1378
Throwable baseCause = cexc.getCause();
1379
if (baseCause instanceof CertPathValidatorException) {
1380
CertPathValidatorException cpve =
1381
(CertPathValidatorException)baseCause;
1382
Reason reason = cpve.getReason();
1383
if (reason == BasicReason.REVOKED) {
1384
alert = chc.staplingActive ?
1385
Alert.BAD_CERT_STATUS_RESPONSE :
1386
Alert.CERTIFICATE_REVOKED;
1387
} else if (
1388
reason == BasicReason.UNDETERMINED_REVOCATION_STATUS) {
1389
alert = chc.staplingActive ?
1390
Alert.BAD_CERT_STATUS_RESPONSE :
1391
Alert.CERTIFICATE_UNKNOWN;
1392
}
1393
}
1394
1395
return alert;
1396
}
1397
}
1398
}
1399
1400