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