Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/share/classes/sun/security/ssl/CertificateRequest.java
67767 views
1
/*
2
* Copyright (c) 2015, 2021, 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.IOException;
29
import java.nio.ByteBuffer;
30
import java.security.PrivateKey;
31
import java.security.cert.X509Certificate;
32
import java.text.MessageFormat;
33
import java.util.ArrayList;
34
import java.util.Arrays;
35
import java.util.Collection;
36
import java.util.Collections;
37
import java.util.HashSet;
38
import java.util.LinkedList;
39
import java.util.List;
40
import java.util.Locale;
41
import javax.net.ssl.SSLEngine;
42
import javax.net.ssl.SSLSocket;
43
import javax.net.ssl.X509ExtendedKeyManager;
44
import javax.security.auth.x500.X500Principal;
45
import sun.security.ssl.CipherSuite.KeyExchange;
46
import sun.security.ssl.SSLHandshake.HandshakeMessage;
47
import sun.security.ssl.X509Authentication.X509Possession;
48
import sun.security.ssl.X509Authentication.X509PossessionGenerator;
49
50
/**
51
* Pack of the CertificateRequest handshake message.
52
*/
53
final class CertificateRequest {
54
static final SSLConsumer t10HandshakeConsumer =
55
new T10CertificateRequestConsumer();
56
static final HandshakeProducer t10HandshakeProducer =
57
new T10CertificateRequestProducer();
58
59
static final SSLConsumer t12HandshakeConsumer =
60
new T12CertificateRequestConsumer();
61
static final HandshakeProducer t12HandshakeProducer =
62
new T12CertificateRequestProducer();
63
64
static final SSLConsumer t13HandshakeConsumer =
65
new T13CertificateRequestConsumer();
66
static final HandshakeProducer t13HandshakeProducer =
67
new T13CertificateRequestProducer();
68
69
// TLS 1.2 and prior versions
70
private static enum ClientCertificateType {
71
// RFC 2246
72
RSA_SIGN ((byte)0x01, "rsa_sign", List.of("RSA"), true),
73
DSS_SIGN ((byte)0x02, "dss_sign", List.of("DSA"), true),
74
RSA_FIXED_DH ((byte)0x03, "rsa_fixed_dh"),
75
DSS_FIXED_DH ((byte)0x04, "dss_fixed_dh"),
76
77
// RFC 4346
78
RSA_EPHEMERAL_DH ((byte)0x05, "rsa_ephemeral_dh"),
79
DSS_EPHEMERAL_DH ((byte)0x06, "dss_ephemeral_dh"),
80
FORTEZZA_DMS ((byte)0x14, "fortezza_dms"),
81
82
// RFC 4492 and 8442
83
ECDSA_SIGN ((byte)0x40, "ecdsa_sign",
84
List.of("EC", "EdDSA"),
85
JsseJce.isEcAvailable()),
86
RSA_FIXED_ECDH ((byte)0x41, "rsa_fixed_ecdh"),
87
ECDSA_FIXED_ECDH ((byte)0x42, "ecdsa_fixed_ecdh");
88
89
private static final byte[] CERT_TYPES =
90
JsseJce.isEcAvailable() ? new byte[] {
91
ECDSA_SIGN.id,
92
RSA_SIGN.id,
93
DSS_SIGN.id
94
} : new byte[] {
95
RSA_SIGN.id,
96
DSS_SIGN.id
97
};
98
99
final byte id;
100
final String name;
101
final List<String> keyAlgorithm;
102
final boolean isAvailable;
103
104
private ClientCertificateType(byte id, String name) {
105
this(id, name, null, false);
106
}
107
108
private ClientCertificateType(byte id, String name,
109
List<String> keyAlgorithm, boolean isAvailable) {
110
this.id = id;
111
this.name = name;
112
this.keyAlgorithm = keyAlgorithm;
113
this.isAvailable = isAvailable;
114
}
115
116
private static String nameOf(byte id) {
117
for (ClientCertificateType cct : ClientCertificateType.values()) {
118
if (cct.id == id) {
119
return cct.name;
120
}
121
}
122
return "UNDEFINED-CLIENT-CERTIFICATE-TYPE(" + (int)id + ")";
123
}
124
125
private static ClientCertificateType valueOf(byte id) {
126
for (ClientCertificateType cct : ClientCertificateType.values()) {
127
if (cct.id == id) {
128
return cct;
129
}
130
}
131
132
return null;
133
}
134
135
private static String[] getKeyTypes(byte[] ids) {
136
ArrayList<String> keyTypes = new ArrayList<>(3);
137
for (byte id : ids) {
138
ClientCertificateType cct = ClientCertificateType.valueOf(id);
139
if (cct.isAvailable) {
140
cct.keyAlgorithm.forEach(key -> {
141
if (!keyTypes.contains(key)) {
142
keyTypes.add(key);
143
}
144
});
145
}
146
}
147
148
return keyTypes.toArray(new String[0]);
149
}
150
}
151
152
/**
153
* The "CertificateRequest" handshake message for SSL 3.0 and TLS 1.0/1.1.
154
*/
155
static final class T10CertificateRequestMessage extends HandshakeMessage {
156
final byte[] types; // certificate types
157
final List<byte[]> authorities; // certificate authorities
158
159
T10CertificateRequestMessage(HandshakeContext handshakeContext,
160
X509Certificate[] trustedCerts, KeyExchange keyExchange) {
161
super(handshakeContext);
162
163
this.authorities = new ArrayList<>(trustedCerts.length);
164
for (X509Certificate cert : trustedCerts) {
165
X500Principal x500Principal = cert.getSubjectX500Principal();
166
authorities.add(x500Principal.getEncoded());
167
}
168
169
this.types = ClientCertificateType.CERT_TYPES;
170
}
171
172
T10CertificateRequestMessage(HandshakeContext handshakeContext,
173
ByteBuffer m) throws IOException {
174
super(handshakeContext);
175
176
// struct {
177
// ClientCertificateType certificate_types<1..2^8-1>;
178
// DistinguishedName certificate_authorities<0..2^16-1>;
179
// } CertificateRequest;
180
if (m.remaining() < 4) {
181
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
182
"Incorrect CertificateRequest message: no sufficient data");
183
}
184
this.types = Record.getBytes8(m);
185
186
int listLen = Record.getInt16(m);
187
if (listLen > m.remaining()) {
188
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
189
"Incorrect CertificateRequest message:no sufficient data");
190
}
191
192
if (listLen > 0) {
193
this.authorities = new LinkedList<>();
194
while (listLen > 0) {
195
// opaque DistinguishedName<1..2^16-1>;
196
byte[] encoded = Record.getBytes16(m);
197
listLen -= (2 + encoded.length);
198
authorities.add(encoded);
199
}
200
} else {
201
this.authorities = Collections.emptyList();
202
}
203
}
204
205
String[] getKeyTypes() {
206
return ClientCertificateType.getKeyTypes(types);
207
}
208
209
X500Principal[] getAuthorities() {
210
X500Principal[] principals = new X500Principal[authorities.size()];
211
int i = 0;
212
for (byte[] encoded : authorities) {
213
principals[i++] = new X500Principal(encoded);
214
}
215
216
return principals;
217
}
218
219
@Override
220
public SSLHandshake handshakeType() {
221
return SSLHandshake.CERTIFICATE_REQUEST;
222
}
223
224
@Override
225
public int messageLength() {
226
int len = 1 + types.length + 2;
227
for (byte[] encoded : authorities) {
228
len += encoded.length + 2;
229
}
230
return len;
231
}
232
233
@Override
234
public void send(HandshakeOutStream hos) throws IOException {
235
hos.putBytes8(types);
236
237
int listLen = 0;
238
for (byte[] encoded : authorities) {
239
listLen += encoded.length + 2;
240
}
241
242
hos.putInt16(listLen);
243
for (byte[] encoded : authorities) {
244
hos.putBytes16(encoded);
245
}
246
}
247
248
@Override
249
public String toString() {
250
MessageFormat messageFormat = new MessageFormat(
251
"\"CertificateRequest\": '{'\n" +
252
" \"certificate types\": {0}\n" +
253
" \"certificate authorities\": {1}\n" +
254
"'}'",
255
Locale.ENGLISH);
256
257
List<String> typeNames = new ArrayList<>(types.length);
258
for (byte type : types) {
259
typeNames.add(ClientCertificateType.nameOf(type));
260
}
261
262
List<String> authorityNames = new ArrayList<>(authorities.size());
263
for (byte[] encoded : authorities) {
264
X500Principal principal = new X500Principal(encoded);
265
authorityNames.add(principal.toString());
266
}
267
Object[] messageFields = {
268
typeNames,
269
authorityNames
270
};
271
272
return messageFormat.format(messageFields);
273
}
274
}
275
276
/**
277
* The "CertificateRequest" handshake message producer for SSL 3.0 and
278
* TLS 1.0/1.1.
279
*/
280
private static final
281
class T10CertificateRequestProducer implements HandshakeProducer {
282
// Prevent instantiation of this class.
283
private T10CertificateRequestProducer() {
284
// blank
285
}
286
287
@Override
288
public byte[] produce(ConnectionContext context,
289
HandshakeMessage message) throws IOException {
290
// The producing happens in server side only.
291
ServerHandshakeContext shc = (ServerHandshakeContext)context;
292
293
X509Certificate[] caCerts =
294
shc.sslContext.getX509TrustManager().getAcceptedIssuers();
295
T10CertificateRequestMessage crm = new T10CertificateRequestMessage(
296
shc, caCerts, shc.negotiatedCipherSuite.keyExchange);
297
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
298
SSLLogger.fine(
299
"Produced CertificateRequest handshake message", crm);
300
}
301
302
// Output the handshake message.
303
crm.write(shc.handshakeOutput);
304
shc.handshakeOutput.flush();
305
306
//
307
// update
308
//
309
shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,
310
SSLHandshake.CERTIFICATE);
311
shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
312
SSLHandshake.CERTIFICATE_VERIFY);
313
314
// The handshake message has been delivered.
315
return null;
316
}
317
}
318
319
/**
320
* The "CertificateRequest" handshake message consumer for SSL 3.0 and
321
* TLS 1.0/1.1.
322
*/
323
private static final
324
class T10CertificateRequestConsumer implements SSLConsumer {
325
// Prevent instantiation of this class.
326
private T10CertificateRequestConsumer() {
327
// blank
328
}
329
330
@Override
331
public void consume(ConnectionContext context,
332
ByteBuffer message) throws IOException {
333
// The consuming happens in client side only.
334
ClientHandshakeContext chc = (ClientHandshakeContext)context;
335
336
// clean up this consumer
337
chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);
338
chc.receivedCertReq = true;
339
340
// If we're processing this message and the server's certificate
341
// message consumer has not already run then this is a state
342
// machine violation.
343
if (chc.handshakeConsumers.containsKey(
344
SSLHandshake.CERTIFICATE.id)) {
345
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
346
"Unexpected CertificateRequest handshake message");
347
}
348
349
SSLConsumer certStatCons = chc.handshakeConsumers.remove(
350
SSLHandshake.CERTIFICATE_STATUS.id);
351
if (certStatCons != null) {
352
// Stapling was active but no certificate status message
353
// was sent. We need to run the absence handler which will
354
// check the certificate chain.
355
CertificateStatus.handshakeAbsence.absent(context, null);
356
}
357
358
T10CertificateRequestMessage crm =
359
new T10CertificateRequestMessage(chc, message);
360
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
361
SSLLogger.fine(
362
"Consuming CertificateRequest handshake message", crm);
363
}
364
365
//
366
// validate
367
//
368
// blank
369
370
//
371
// update
372
//
373
374
// An empty client Certificate handshake message may be allow.
375
chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,
376
SSLHandshake.CERTIFICATE);
377
378
X509ExtendedKeyManager km = chc.sslContext.getX509KeyManager();
379
String clientAlias = null;
380
if (chc.conContext.transport instanceof SSLSocketImpl) {
381
clientAlias = km.chooseClientAlias(crm.getKeyTypes(),
382
crm.getAuthorities(), (SSLSocket)chc.conContext.transport);
383
} else if (chc.conContext.transport instanceof SSLEngineImpl) {
384
clientAlias = km.chooseEngineClientAlias(crm.getKeyTypes(),
385
crm.getAuthorities(), (SSLEngine)chc.conContext.transport);
386
}
387
388
389
if (clientAlias == null) {
390
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
391
SSLLogger.warning("No available client authentication");
392
}
393
return;
394
}
395
396
PrivateKey clientPrivateKey = km.getPrivateKey(clientAlias);
397
if (clientPrivateKey == null) {
398
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
399
SSLLogger.warning("No available client private key");
400
}
401
return;
402
}
403
404
X509Certificate[] clientCerts = km.getCertificateChain(clientAlias);
405
if ((clientCerts == null) || (clientCerts.length == 0)) {
406
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
407
SSLLogger.warning("No available client certificate");
408
}
409
return;
410
}
411
412
chc.handshakePossessions.add(
413
new X509Possession(clientPrivateKey, clientCerts));
414
chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
415
SSLHandshake.CERTIFICATE_VERIFY);
416
}
417
}
418
419
/**
420
* The CertificateRequest handshake message for TLS 1.2.
421
*/
422
static final class T12CertificateRequestMessage extends HandshakeMessage {
423
final byte[] types; // certificate types
424
final int[] algorithmIds; // supported signature algorithms
425
final List<byte[]> authorities; // certificate authorities
426
427
T12CertificateRequestMessage(HandshakeContext handshakeContext,
428
X509Certificate[] trustedCerts, KeyExchange keyExchange,
429
List<SignatureScheme> signatureSchemes) throws IOException {
430
super(handshakeContext);
431
432
this.types = ClientCertificateType.CERT_TYPES;
433
434
if (signatureSchemes == null || signatureSchemes.isEmpty()) {
435
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
436
"No signature algorithms specified for " +
437
"CertificateRequest hanshake message");
438
}
439
this.algorithmIds = new int[signatureSchemes.size()];
440
int i = 0;
441
for (SignatureScheme scheme : signatureSchemes) {
442
algorithmIds[i++] = scheme.id;
443
}
444
445
this.authorities = new ArrayList<>(trustedCerts.length);
446
for (X509Certificate cert : trustedCerts) {
447
X500Principal x500Principal = cert.getSubjectX500Principal();
448
authorities.add(x500Principal.getEncoded());
449
}
450
}
451
452
T12CertificateRequestMessage(HandshakeContext handshakeContext,
453
ByteBuffer m) throws IOException {
454
super(handshakeContext);
455
456
// struct {
457
// ClientCertificateType certificate_types<1..2^8-1>;
458
// SignatureAndHashAlgorithm
459
// supported_signature_algorithms<2..2^16-2>;
460
// DistinguishedName certificate_authorities<0..2^16-1>;
461
// } CertificateRequest;
462
463
// certificate_authorities
464
if (m.remaining() < 8) {
465
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
466
"Invalid CertificateRequest handshake message: " +
467
"no sufficient data");
468
}
469
this.types = Record.getBytes8(m);
470
471
// supported_signature_algorithms
472
if (m.remaining() < 6) {
473
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
474
"Invalid CertificateRequest handshake message: " +
475
"no sufficient data");
476
}
477
478
byte[] algs = Record.getBytes16(m);
479
if (algs == null || algs.length == 0 || (algs.length & 0x01) != 0) {
480
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
481
"Invalid CertificateRequest handshake message: " +
482
"incomplete signature algorithms");
483
}
484
485
this.algorithmIds = new int[(algs.length >> 1)];
486
for (int i = 0, j = 0; i < algs.length;) {
487
byte hash = algs[i++];
488
byte sign = algs[i++];
489
algorithmIds[j++] = ((hash & 0xFF) << 8) | (sign & 0xFF);
490
}
491
492
// certificate_authorities
493
if (m.remaining() < 2) {
494
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
495
"Invalid CertificateRequest handshake message: " +
496
"no sufficient data");
497
}
498
499
int listLen = Record.getInt16(m);
500
if (listLen > m.remaining()) {
501
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
502
"Invalid CertificateRequest message: no sufficient data");
503
}
504
505
if (listLen > 0) {
506
this.authorities = new LinkedList<>();
507
while (listLen > 0) {
508
// opaque DistinguishedName<1..2^16-1>;
509
byte[] encoded = Record.getBytes16(m);
510
listLen -= (2 + encoded.length);
511
authorities.add(encoded);
512
}
513
} else {
514
this.authorities = Collections.emptyList();
515
}
516
}
517
518
String[] getKeyTypes() {
519
return ClientCertificateType.getKeyTypes(types);
520
}
521
522
X500Principal[] getAuthorities() {
523
X500Principal[] principals = new X500Principal[authorities.size()];
524
int i = 0;
525
for (byte[] encoded : authorities) {
526
principals[i++] = new X500Principal(encoded);
527
}
528
529
return principals;
530
}
531
532
@Override
533
public SSLHandshake handshakeType() {
534
return SSLHandshake.CERTIFICATE_REQUEST;
535
}
536
537
@Override
538
public int messageLength() {
539
int len = 1 + types.length + 2 + (algorithmIds.length << 1) + 2;
540
for (byte[] encoded : authorities) {
541
len += encoded.length + 2;
542
}
543
return len;
544
}
545
546
@Override
547
public void send(HandshakeOutStream hos) throws IOException {
548
hos.putBytes8(types);
549
550
int listLen = 0;
551
for (byte[] encoded : authorities) {
552
listLen += encoded.length + 2;
553
}
554
555
hos.putInt16(algorithmIds.length << 1);
556
for (int algorithmId : algorithmIds) {
557
hos.putInt16(algorithmId);
558
}
559
560
hos.putInt16(listLen);
561
for (byte[] encoded : authorities) {
562
hos.putBytes16(encoded);
563
}
564
}
565
566
@Override
567
public String toString() {
568
MessageFormat messageFormat = new MessageFormat(
569
"\"CertificateRequest\": '{'\n" +
570
" \"certificate types\": {0}\n" +
571
" \"supported signature algorithms\": {1}\n" +
572
" \"certificate authorities\": {2}\n" +
573
"'}'",
574
Locale.ENGLISH);
575
576
List<String> typeNames = new ArrayList<>(types.length);
577
for (byte type : types) {
578
typeNames.add(ClientCertificateType.nameOf(type));
579
}
580
581
List<String> algorithmNames = new ArrayList<>(algorithmIds.length);
582
for (int algorithmId : algorithmIds) {
583
algorithmNames.add(SignatureScheme.nameOf(algorithmId));
584
}
585
586
List<String> authorityNames = new ArrayList<>(authorities.size());
587
for (byte[] encoded : authorities) {
588
X500Principal principal = new X500Principal(encoded);
589
authorityNames.add(principal.toString());
590
}
591
Object[] messageFields = {
592
typeNames,
593
algorithmNames,
594
authorityNames
595
};
596
597
return messageFormat.format(messageFields);
598
}
599
}
600
601
/**
602
* The "CertificateRequest" handshake message producer for TLS 1.2.
603
*/
604
private static final
605
class T12CertificateRequestProducer implements HandshakeProducer {
606
// Prevent instantiation of this class.
607
private T12CertificateRequestProducer() {
608
// blank
609
}
610
611
@Override
612
public byte[] produce(ConnectionContext context,
613
HandshakeMessage message) throws IOException {
614
// The producing happens in server side only.
615
ServerHandshakeContext shc = (ServerHandshakeContext)context;
616
if (shc.localSupportedSignAlgs == null) {
617
shc.localSupportedSignAlgs =
618
SignatureScheme.getSupportedAlgorithms(
619
shc.sslConfig,
620
shc.algorithmConstraints, shc.activeProtocols);
621
}
622
623
if (shc.localSupportedSignAlgs == null ||
624
shc.localSupportedSignAlgs.isEmpty()) {
625
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
626
"No supported signature algorithm");
627
}
628
629
X509Certificate[] caCerts =
630
shc.sslContext.getX509TrustManager().getAcceptedIssuers();
631
T12CertificateRequestMessage crm = new T12CertificateRequestMessage(
632
shc, caCerts, shc.negotiatedCipherSuite.keyExchange,
633
shc.localSupportedSignAlgs);
634
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
635
SSLLogger.fine(
636
"Produced CertificateRequest handshake message", crm);
637
}
638
639
// Output the handshake message.
640
crm.write(shc.handshakeOutput);
641
shc.handshakeOutput.flush();
642
643
//
644
// update
645
//
646
shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,
647
SSLHandshake.CERTIFICATE);
648
shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
649
SSLHandshake.CERTIFICATE_VERIFY);
650
651
// The handshake message has been delivered.
652
return null;
653
}
654
}
655
656
/**
657
* The "CertificateRequest" handshake message consumer for TLS 1.2.
658
*/
659
private static final
660
class T12CertificateRequestConsumer implements SSLConsumer {
661
// Prevent instantiation of this class.
662
private T12CertificateRequestConsumer() {
663
// blank
664
}
665
666
@Override
667
public void consume(ConnectionContext context,
668
ByteBuffer message) throws IOException {
669
// The consuming happens in client side only.
670
ClientHandshakeContext chc = (ClientHandshakeContext)context;
671
672
// clean up this consumer
673
chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);
674
chc.receivedCertReq = true;
675
676
// If we're processing this message and the server's certificate
677
// message consumer has not already run then this is a state
678
// machine violation.
679
if (chc.handshakeConsumers.containsKey(
680
SSLHandshake.CERTIFICATE.id)) {
681
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
682
"Unexpected CertificateRequest handshake message");
683
}
684
685
SSLConsumer certStatCons = chc.handshakeConsumers.remove(
686
SSLHandshake.CERTIFICATE_STATUS.id);
687
if (certStatCons != null) {
688
// Stapling was active but no certificate status message
689
// was sent. We need to run the absence handler which will
690
// check the certificate chain.
691
CertificateStatus.handshakeAbsence.absent(context, null);
692
}
693
694
T12CertificateRequestMessage crm =
695
new T12CertificateRequestMessage(chc, message);
696
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
697
SSLLogger.fine(
698
"Consuming CertificateRequest handshake message", crm);
699
}
700
701
//
702
// validate
703
//
704
// blank
705
706
//
707
// update
708
//
709
710
// An empty client Certificate handshake message may be allow.
711
chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,
712
SSLHandshake.CERTIFICATE);
713
714
List<SignatureScheme> sss =
715
SignatureScheme.getSupportedAlgorithms(
716
chc.sslConfig,
717
chc.algorithmConstraints, chc.negotiatedProtocol,
718
crm.algorithmIds);
719
if (sss == null || sss.isEmpty()) {
720
throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
721
"No supported signature algorithm");
722
}
723
724
chc.peerRequestedSignatureSchemes = sss;
725
chc.peerRequestedCertSignSchemes = sss; // use the same schemes
726
chc.handshakeSession.setPeerSupportedSignatureAlgorithms(sss);
727
chc.peerSupportedAuthorities = crm.getAuthorities();
728
729
// For TLS 1.2, we need to use a combination of the CR message's
730
// allowed key types and the signature algorithms in order to
731
// find a certificate chain that has the right key and all certs
732
// using one or more of the allowed cert signature schemes.
733
SSLPossession pos = choosePossession(chc, crm);
734
if (pos == null) {
735
return;
736
}
737
738
chc.handshakePossessions.add(pos);
739
chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
740
SSLHandshake.CERTIFICATE_VERIFY);
741
}
742
743
private static SSLPossession choosePossession(HandshakeContext hc,
744
T12CertificateRequestMessage crm) throws IOException {
745
if (hc.peerRequestedCertSignSchemes == null ||
746
hc.peerRequestedCertSignSchemes.isEmpty()) {
747
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
748
SSLLogger.warning("No signature and hash algorithms " +
749
"in CertificateRequest");
750
}
751
return null;
752
}
753
754
// Put the CR key type into a more friendly format for searching
755
List<String> crKeyTypes = new ArrayList<>(
756
Arrays.asList(crm.getKeyTypes()));
757
// For TLS 1.2 only if RSA is a requested key type then we
758
// should also allow RSASSA-PSS.
759
if (crKeyTypes.contains("RSA")) {
760
crKeyTypes.add("RSASSA-PSS");
761
}
762
763
Collection<String> checkedKeyTypes = new HashSet<>();
764
for (SignatureScheme ss : hc.peerRequestedCertSignSchemes) {
765
if (checkedKeyTypes.contains(ss.keyAlgorithm)) {
766
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
767
SSLLogger.warning(
768
"Unsupported authentication scheme: " + ss.name);
769
}
770
continue;
771
}
772
773
// Don't select a signature scheme unless we will be able to
774
// produce a CertificateVerify message later
775
if (SignatureScheme.getPreferableAlgorithm(
776
hc.algorithmConstraints,
777
hc.peerRequestedSignatureSchemes,
778
ss, hc.negotiatedProtocol) == null) {
779
780
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
781
SSLLogger.warning(
782
"Unable to produce CertificateVerify for " +
783
"signature scheme: " + ss.name);
784
}
785
checkedKeyTypes.add(ss.keyAlgorithm);
786
continue;
787
}
788
789
X509Authentication ka = X509Authentication.valueOf(ss);
790
if (ka == null) {
791
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
792
SSLLogger.warning(
793
"Unsupported authentication scheme: " + ss.name);
794
}
795
checkedKeyTypes.add(ss.keyAlgorithm);
796
continue;
797
} else {
798
// Any auth object will have a possession generator and
799
// we need to make sure the key types for that generator
800
// share at least one common algorithm with the CR's
801
// allowed key types.
802
if (ka.possessionGenerator instanceof
803
X509PossessionGenerator xpg) {
804
if (Collections.disjoint(crKeyTypes,
805
Arrays.asList(xpg.keyTypes))) {
806
if (SSLLogger.isOn &&
807
SSLLogger.isOn("ssl,handshake")) {
808
SSLLogger.warning(
809
"Unsupported authentication scheme: " +
810
ss.name);
811
}
812
checkedKeyTypes.add(ss.keyAlgorithm);
813
continue;
814
}
815
}
816
}
817
818
SSLPossession pos = ka.createPossession(hc);
819
if (pos == null) {
820
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
821
SSLLogger.warning(
822
"Unavailable authentication scheme: " + ss.name);
823
}
824
continue;
825
}
826
827
return pos;
828
}
829
830
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
831
SSLLogger.warning("No available authentication scheme");
832
}
833
return null;
834
}
835
}
836
837
/**
838
* The CertificateRequest handshake message for TLS 1.3.
839
*/
840
static final class T13CertificateRequestMessage extends HandshakeMessage {
841
private final byte[] requestContext;
842
private final SSLExtensions extensions;
843
844
T13CertificateRequestMessage(
845
HandshakeContext handshakeContext) throws IOException {
846
super(handshakeContext);
847
848
this.requestContext = new byte[0];
849
this.extensions = new SSLExtensions(this);
850
}
851
852
T13CertificateRequestMessage(HandshakeContext handshakeContext,
853
ByteBuffer m) throws IOException {
854
super(handshakeContext);
855
856
// struct {
857
// opaque certificate_request_context<0..2^8-1>;
858
// Extension extensions<2..2^16-1>;
859
// } CertificateRequest;
860
if (m.remaining() < 5) {
861
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
862
"Invalid CertificateRequest handshake message: " +
863
"no sufficient data");
864
}
865
this.requestContext = Record.getBytes8(m);
866
867
if (m.remaining() < 4) {
868
throw handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER,
869
"Invalid CertificateRequest handshake message: " +
870
"no sufficient extensions data");
871
}
872
SSLExtension[] enabledExtensions =
873
handshakeContext.sslConfig.getEnabledExtensions(
874
SSLHandshake.CERTIFICATE_REQUEST);
875
this.extensions = new SSLExtensions(this, m, enabledExtensions);
876
}
877
878
@Override
879
SSLHandshake handshakeType() {
880
return SSLHandshake.CERTIFICATE_REQUEST;
881
}
882
883
@Override
884
int messageLength() {
885
// In TLS 1.3, use of certain extensions is mandatory.
886
return 1 + requestContext.length + extensions.length();
887
}
888
889
@Override
890
void send(HandshakeOutStream hos) throws IOException {
891
hos.putBytes8(requestContext);
892
893
// In TLS 1.3, use of certain extensions is mandatory.
894
extensions.send(hos);
895
}
896
897
@Override
898
public String toString() {
899
MessageFormat messageFormat = new MessageFormat(
900
"\"CertificateRequest\": '{'\n" +
901
" \"certificate_request_context\": \"{0}\",\n" +
902
" \"extensions\": [\n" +
903
"{1}\n" +
904
" ]\n" +
905
"'}'",
906
Locale.ENGLISH);
907
Object[] messageFields = {
908
Utilities.toHexString(requestContext),
909
Utilities.indent(Utilities.indent(extensions.toString()))
910
};
911
912
return messageFormat.format(messageFields);
913
}
914
}
915
916
/**
917
* The "CertificateRequest" handshake message producer for TLS 1.3.
918
*/
919
private static final
920
class T13CertificateRequestProducer implements HandshakeProducer {
921
// Prevent instantiation of this class.
922
private T13CertificateRequestProducer() {
923
// blank
924
}
925
926
@Override
927
public byte[] produce(ConnectionContext context,
928
HandshakeMessage message) throws IOException {
929
// The producing happens in server side only.
930
ServerHandshakeContext shc = (ServerHandshakeContext)context;
931
932
T13CertificateRequestMessage crm =
933
new T13CertificateRequestMessage(shc);
934
// Produce extensions for CertificateRequest handshake message.
935
SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(
936
SSLHandshake.CERTIFICATE_REQUEST, shc.negotiatedProtocol);
937
crm.extensions.produce(shc, extTypes);
938
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
939
SSLLogger.fine("Produced CertificateRequest message", crm);
940
}
941
942
// Output the handshake message.
943
crm.write(shc.handshakeOutput);
944
shc.handshakeOutput.flush();
945
946
//
947
// update
948
//
949
shc.certRequestContext = crm.requestContext.clone();
950
shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE.id,
951
SSLHandshake.CERTIFICATE);
952
shc.handshakeConsumers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
953
SSLHandshake.CERTIFICATE_VERIFY);
954
955
// The handshake message has been delivered.
956
return null;
957
}
958
}
959
960
/**
961
* The "CertificateRequest" handshake message consumer for TLS 1.3.
962
*/
963
private static final
964
class T13CertificateRequestConsumer implements SSLConsumer {
965
// Prevent instantiation of this class.
966
private T13CertificateRequestConsumer() {
967
// blank
968
}
969
970
@Override
971
public void consume(ConnectionContext context,
972
ByteBuffer message) throws IOException {
973
// The consuming happens in client side only.
974
ClientHandshakeContext chc = (ClientHandshakeContext)context;
975
976
// clean up this consumer
977
chc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_REQUEST.id);
978
chc.receivedCertReq = true;
979
980
// Ensure that the CertificateRequest has not been sent prior
981
// to EncryptedExtensions
982
if (chc.handshakeConsumers.containsKey(
983
SSLHandshake.ENCRYPTED_EXTENSIONS.id)) {
984
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
985
"Unexpected CertificateRequest handshake message");
986
}
987
988
T13CertificateRequestMessage crm =
989
new T13CertificateRequestMessage(chc, message);
990
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
991
SSLLogger.fine(
992
"Consuming CertificateRequest handshake message", crm);
993
}
994
995
//
996
// validate
997
//
998
SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
999
SSLHandshake.CERTIFICATE_REQUEST);
1000
crm.extensions.consumeOnLoad(chc, extTypes);
1001
1002
//
1003
// update
1004
//
1005
crm.extensions.consumeOnTrade(chc, extTypes);
1006
1007
//
1008
// produce
1009
//
1010
chc.certRequestContext = crm.requestContext.clone();
1011
chc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id,
1012
SSLHandshake.CERTIFICATE);
1013
chc.handshakeProducers.put(SSLHandshake.CERTIFICATE_VERIFY.id,
1014
SSLHandshake.CERTIFICATE_VERIFY);
1015
}
1016
}
1017
}
1018
1019