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