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/ClientHello.java
67766 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.SecureRandom;
31
import java.security.cert.X509Certificate;
32
import java.text.MessageFormat;
33
import java.util.Arrays;
34
import java.util.Collections;
35
import java.util.LinkedList;
36
import java.util.List;
37
import java.util.Locale;
38
import javax.net.ssl.SSLException;
39
import javax.net.ssl.SSLHandshakeException;
40
import javax.net.ssl.SSLPeerUnverifiedException;
41
import javax.net.ssl.SSLProtocolException;
42
import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED;
43
import sun.security.ssl.SSLHandshake.HandshakeMessage;
44
import sun.security.ssl.SupportedVersionsExtension.CHSupportedVersionsSpec;
45
46
/**
47
* Pack of the ClientHello handshake message.
48
*/
49
final class ClientHello {
50
static final SSLProducer kickstartProducer =
51
new ClientHelloKickstartProducer();
52
static final SSLConsumer handshakeConsumer =
53
new ClientHelloConsumer();
54
static final HandshakeProducer handshakeProducer =
55
new ClientHelloProducer();
56
57
private static final HandshakeConsumer t12HandshakeConsumer =
58
new T12ClientHelloConsumer();
59
private static final HandshakeConsumer t13HandshakeConsumer =
60
new T13ClientHelloConsumer();
61
private static final HandshakeConsumer d12HandshakeConsumer =
62
new D12ClientHelloConsumer();
63
private static final HandshakeConsumer d13HandshakeConsumer =
64
new D13ClientHelloConsumer();
65
66
/**
67
* The ClientHello handshake message.
68
*
69
* See RFC 5264/4346/2246/6347 for the specifications.
70
*/
71
static final class ClientHelloMessage extends HandshakeMessage {
72
private final boolean isDTLS;
73
74
final int clientVersion;
75
final RandomCookie clientRandom;
76
final SessionId sessionId;
77
private byte[] cookie; // DTLS only
78
final int[] cipherSuiteIds;
79
final List<CipherSuite> cipherSuites; // known cipher suites only
80
final byte[] compressionMethod;
81
final SSLExtensions extensions;
82
83
private static final byte[] NULL_COMPRESSION = new byte[] {0};
84
85
ClientHelloMessage(HandshakeContext handshakeContext,
86
int clientVersion, SessionId sessionId,
87
List<CipherSuite> cipherSuites, SecureRandom generator) {
88
super(handshakeContext);
89
this.isDTLS = handshakeContext.sslContext.isDTLS();
90
91
this.clientVersion = clientVersion;
92
this.clientRandom = new RandomCookie(generator);
93
this.sessionId = sessionId;
94
if (isDTLS) {
95
this.cookie = new byte[0];
96
} else {
97
this.cookie = null;
98
}
99
100
this.cipherSuites = cipherSuites;
101
this.cipherSuiteIds = getCipherSuiteIds(cipherSuites);
102
this.extensions = new SSLExtensions(this);
103
104
// Don't support compression.
105
this.compressionMethod = NULL_COMPRESSION;
106
}
107
108
/* Read up to the binders in the PSK extension. After this method
109
* returns, the ByteBuffer position will be at end of the message
110
* fragment that should be hashed to produce the PSK binder values.
111
* The client of this method can use this position to determine the
112
* message fragment and produce the binder values.
113
*/
114
static void readPartial(TransportContext tc,
115
ByteBuffer m) throws IOException {
116
boolean isDTLS = tc.sslContext.isDTLS();
117
118
// version
119
Record.getInt16(m);
120
121
new RandomCookie(m);
122
123
// session ID
124
Record.getBytes8(m);
125
126
// DTLS cookie
127
if (isDTLS) {
128
Record.getBytes8(m);
129
}
130
131
// cipher suite IDs
132
Record.getBytes16(m);
133
// compression method
134
Record.getBytes8(m);
135
// read extensions, if present
136
if (m.remaining() >= 2) {
137
int remaining = Record.getInt16(m);
138
while (remaining > 0) {
139
int id = Record.getInt16(m);
140
int extLen = Record.getInt16(m);
141
remaining -= extLen + 4;
142
143
if (id == SSLExtension.CH_PRE_SHARED_KEY.id) {
144
// ensure pre_shared_key is the last extension
145
if (remaining > 0) {
146
throw tc.fatal(Alert.ILLEGAL_PARAMETER,
147
"pre_shared_key extension is not last");
148
}
149
// read only up to the IDs
150
Record.getBytes16(m);
151
return;
152
} else {
153
m.position(m.position() + extLen);
154
155
}
156
}
157
} // Otherwise, ignore the remaining bytes.
158
}
159
160
ClientHelloMessage(HandshakeContext handshakeContext, ByteBuffer m,
161
SSLExtension[] supportedExtensions) throws IOException {
162
super(handshakeContext);
163
this.isDTLS = handshakeContext.sslContext.isDTLS();
164
165
this.clientVersion = ((m.get() & 0xFF) << 8) | (m.get() & 0xFF);
166
this.clientRandom = new RandomCookie(m);
167
this.sessionId = new SessionId(Record.getBytes8(m));
168
try {
169
sessionId.checkLength(clientVersion);
170
} catch (SSLProtocolException ex) {
171
throw handshakeContext.conContext.fatal(
172
Alert.ILLEGAL_PARAMETER, ex);
173
}
174
if (isDTLS) {
175
this.cookie = Record.getBytes8(m);
176
} else {
177
this.cookie = null;
178
}
179
180
byte[] encodedIds = Record.getBytes16(m);
181
if (encodedIds.length == 0 || (encodedIds.length & 0x01) != 0) {
182
throw handshakeContext.conContext.fatal(
183
Alert.ILLEGAL_PARAMETER,
184
"Invalid ClientHello message");
185
}
186
187
this.cipherSuiteIds = new int[encodedIds.length >> 1];
188
for (int i = 0, j = 0; i < encodedIds.length; i++, j++) {
189
cipherSuiteIds[j] =
190
((encodedIds[i++] & 0xFF) << 8) | (encodedIds[i] & 0xFF);
191
}
192
this.cipherSuites = getCipherSuites(cipherSuiteIds);
193
194
this.compressionMethod = Record.getBytes8(m);
195
// In TLS 1.3, use of certain extensions is mandatory.
196
if (m.hasRemaining()) {
197
this.extensions =
198
new SSLExtensions(this, m, supportedExtensions);
199
} else {
200
this.extensions = new SSLExtensions(this);
201
}
202
}
203
204
void setHelloCookie(byte[] cookie) {
205
this.cookie = cookie;
206
}
207
208
// DTLS 1.0/1.2, for cookie generation.
209
byte[] getHelloCookieBytes() {
210
HandshakeOutStream hos = new HandshakeOutStream(null);
211
try {
212
// copied from send() method
213
hos.putInt8((byte)((clientVersion >>> 8) & 0xFF));
214
hos.putInt8((byte)(clientVersion & 0xFF));
215
hos.write(clientRandom.randomBytes, 0, 32);
216
hos.putBytes8(sessionId.getId());
217
// ignore cookie
218
hos.putBytes16(getEncodedCipherSuites());
219
hos.putBytes8(compressionMethod);
220
extensions.send(hos); // In TLS 1.3, use of certain
221
// extensions is mandatory.
222
} catch (IOException ioe) {
223
// unlikely
224
}
225
226
return hos.toByteArray();
227
}
228
229
// (D)TLS 1.3, for cookie generation.
230
byte[] getHeaderBytes() {
231
HandshakeOutStream hos = new HandshakeOutStream(null);
232
try {
233
// copied from send() method
234
hos.putInt8((byte)((clientVersion >>> 8) & 0xFF));
235
hos.putInt8((byte)(clientVersion & 0xFF));
236
hos.write(clientRandom.randomBytes, 0, 32);
237
hos.putBytes8(sessionId.getId());
238
hos.putBytes16(getEncodedCipherSuites());
239
hos.putBytes8(compressionMethod);
240
} catch (IOException ioe) {
241
// unlikely
242
}
243
244
return hos.toByteArray();
245
}
246
247
private static int[] getCipherSuiteIds(
248
List<CipherSuite> cipherSuites) {
249
if (cipherSuites != null) {
250
int[] ids = new int[cipherSuites.size()];
251
int i = 0;
252
for (CipherSuite cipherSuite : cipherSuites) {
253
ids[i++] = cipherSuite.id;
254
}
255
256
return ids;
257
}
258
259
return new int[0];
260
}
261
262
private static List<CipherSuite> getCipherSuites(int[] ids) {
263
List<CipherSuite> cipherSuites = new LinkedList<>();
264
for (int id : ids) {
265
CipherSuite cipherSuite = CipherSuite.valueOf(id);
266
if (cipherSuite != null) {
267
cipherSuites.add(cipherSuite);
268
}
269
}
270
271
return Collections.unmodifiableList(cipherSuites);
272
}
273
274
private List<String> getCipherSuiteNames() {
275
List<String> names = new LinkedList<>();
276
for (int id : cipherSuiteIds) {
277
names.add(CipherSuite.nameOf(id) +
278
"(" + Utilities.byte16HexString(id) + ")"); }
279
280
return names;
281
}
282
283
private byte[] getEncodedCipherSuites() {
284
byte[] encoded = new byte[cipherSuiteIds.length << 1];
285
int i = 0;
286
for (int id : cipherSuiteIds) {
287
encoded[i++] = (byte)(id >> 8);
288
encoded[i++] = (byte)id;
289
}
290
return encoded;
291
}
292
293
@Override
294
public SSLHandshake handshakeType() {
295
return SSLHandshake.CLIENT_HELLO;
296
}
297
298
@Override
299
public int messageLength() {
300
/*
301
* Add fixed size parts of each field...
302
* version + random + session + cipher + compress
303
*/
304
return (2 + 32 + 1 + 2 + 1
305
+ sessionId.length() /* ... + variable parts */
306
+ (isDTLS ? (1 + cookie.length) : 0)
307
+ (cipherSuiteIds.length * 2)
308
+ compressionMethod.length)
309
+ extensions.length(); // In TLS 1.3, use of certain
310
// extensions is mandatory.
311
}
312
313
@Override
314
public void send(HandshakeOutStream hos) throws IOException {
315
sendCore(hos);
316
extensions.send(hos); // In TLS 1.3, use of certain
317
// extensions is mandatory.
318
}
319
320
void sendCore(HandshakeOutStream hos) throws IOException {
321
hos.putInt8((byte) (clientVersion >>> 8));
322
hos.putInt8((byte) clientVersion);
323
hos.write(clientRandom.randomBytes, 0, 32);
324
hos.putBytes8(sessionId.getId());
325
if (isDTLS) {
326
hos.putBytes8(cookie);
327
}
328
hos.putBytes16(getEncodedCipherSuites());
329
hos.putBytes8(compressionMethod);
330
}
331
332
@Override
333
public String toString() {
334
if (isDTLS) {
335
MessageFormat messageFormat = new MessageFormat(
336
"\"ClientHello\": '{'\n" +
337
" \"client version\" : \"{0}\",\n" +
338
" \"random\" : \"{1}\",\n" +
339
" \"session id\" : \"{2}\",\n" +
340
" \"cookie\" : \"{3}\",\n" +
341
" \"cipher suites\" : \"{4}\",\n" +
342
" \"compression methods\" : \"{5}\",\n" +
343
" \"extensions\" : [\n" +
344
"{6}\n" +
345
" ]\n" +
346
"'}'",
347
Locale.ENGLISH);
348
Object[] messageFields = {
349
ProtocolVersion.nameOf(clientVersion),
350
Utilities.toHexString(clientRandom.randomBytes),
351
sessionId.toString(),
352
Utilities.toHexString(cookie),
353
getCipherSuiteNames().toString(),
354
Utilities.toHexString(compressionMethod),
355
Utilities.indent(Utilities.indent(extensions.toString()))
356
};
357
358
return messageFormat.format(messageFields);
359
} else {
360
MessageFormat messageFormat = new MessageFormat(
361
"\"ClientHello\": '{'\n" +
362
" \"client version\" : \"{0}\",\n" +
363
" \"random\" : \"{1}\",\n" +
364
" \"session id\" : \"{2}\",\n" +
365
" \"cipher suites\" : \"{3}\",\n" +
366
" \"compression methods\" : \"{4}\",\n" +
367
" \"extensions\" : [\n" +
368
"{5}\n" +
369
" ]\n" +
370
"'}'",
371
Locale.ENGLISH);
372
Object[] messageFields = {
373
ProtocolVersion.nameOf(clientVersion),
374
Utilities.toHexString(clientRandom.randomBytes),
375
sessionId.toString(),
376
getCipherSuiteNames().toString(),
377
Utilities.toHexString(compressionMethod),
378
Utilities.indent(Utilities.indent(extensions.toString()))
379
};
380
381
return messageFormat.format(messageFields);
382
}
383
}
384
}
385
386
/**
387
* The "ClientHello" handshake message kick start producer.
388
*/
389
private static final
390
class ClientHelloKickstartProducer implements SSLProducer {
391
// Prevent instantiation of this class.
392
private ClientHelloKickstartProducer() {
393
// blank
394
}
395
396
// Produce kickstart handshake message.
397
@Override
398
public byte[] produce(ConnectionContext context) throws IOException {
399
// The producing happens in client side only.
400
ClientHandshakeContext chc = (ClientHandshakeContext)context;
401
402
// clean up this producer
403
chc.handshakeProducers.remove(SSLHandshake.CLIENT_HELLO.id);
404
405
// session ID of the ClientHello message
406
SessionId sessionId = new SessionId(new byte[0]);
407
408
// a list of cipher suites sent by the client
409
List<CipherSuite> cipherSuites = chc.activeCipherSuites;
410
411
//
412
// Try to resume an existing session.
413
//
414
SSLSessionContextImpl ssci = (SSLSessionContextImpl)
415
chc.sslContext.engineGetClientSessionContext();
416
SSLSessionImpl session = ssci.get(
417
chc.conContext.transport.getPeerHost(),
418
chc.conContext.transport.getPeerPort());
419
if (session != null) {
420
// If unsafe server certificate change is not allowed, reserve
421
// current server certificates if the previous handshake is a
422
// session-resumption abbreviated initial handshake.
423
if (!ClientHandshakeContext.allowUnsafeServerCertChange &&
424
session.isSessionResumption()) {
425
try {
426
// If existing, peer certificate chain cannot be null.
427
chc.reservedServerCerts =
428
(X509Certificate[])session.getPeerCertificates();
429
} catch (SSLPeerUnverifiedException puve) {
430
// Maybe not certificate-based, ignore the exception.
431
}
432
}
433
434
if (!session.isRejoinable()) {
435
session = null;
436
if (SSLLogger.isOn &&
437
SSLLogger.isOn("ssl,handshake,verbose")) {
438
SSLLogger.finest(
439
"Can't resume, the session is not rejoinable");
440
}
441
}
442
}
443
444
CipherSuite sessionSuite = null;
445
if (session != null) {
446
sessionSuite = session.getSuite();
447
if (!chc.isNegotiable(sessionSuite)) {
448
session = null;
449
if (SSLLogger.isOn &&
450
SSLLogger.isOn("ssl,handshake,verbose")) {
451
SSLLogger.finest(
452
"Can't resume, unavailable session cipher suite");
453
}
454
}
455
}
456
457
ProtocolVersion sessionVersion = null;
458
if (session != null) {
459
sessionVersion = session.getProtocolVersion();
460
if (!chc.isNegotiable(sessionVersion)) {
461
session = null;
462
if (SSLLogger.isOn &&
463
SSLLogger.isOn("ssl,handshake,verbose")) {
464
SSLLogger.finest(
465
"Can't resume, unavailable protocol version");
466
}
467
}
468
}
469
470
if (session != null &&
471
!sessionVersion.useTLS13PlusSpec() &&
472
SSLConfiguration.useExtendedMasterSecret) {
473
474
boolean isEmsAvailable = chc.sslConfig.isAvailable(
475
SSLExtension.CH_EXTENDED_MASTER_SECRET, sessionVersion);
476
if (isEmsAvailable && !session.useExtendedMasterSecret &&
477
!SSLConfiguration.allowLegacyResumption) {
478
// perform full handshake instead
479
//
480
// The client SHOULD NOT offer an abbreviated handshake
481
// to resume a session that does not use an extended
482
// master secret. Instead, it SHOULD offer a full
483
// handshake.
484
session = null;
485
}
486
487
if ((session != null) &&
488
!ClientHandshakeContext.allowUnsafeServerCertChange) {
489
// It is fine to move on with abbreviate handshake if
490
// endpoint identification is enabled.
491
String identityAlg = chc.sslConfig.identificationProtocol;
492
if (identityAlg == null || identityAlg.isEmpty()) {
493
if (isEmsAvailable) {
494
if (!session.useExtendedMasterSecret) {
495
// perform full handshake instead
496
session = null;
497
} // Otherwise, use extended master secret.
498
} else {
499
// The extended master secret extension does not
500
// apply to SSL 3.0. Perform a full handshake
501
// instead.
502
//
503
// Note that the useExtendedMasterSecret is
504
// extended to protect SSL 3.0 connections,
505
// by discarding abbreviate handshake.
506
session = null;
507
}
508
}
509
}
510
}
511
512
// ensure that the endpoint identification algorithm matches the
513
// one in the session
514
String identityAlg = chc.sslConfig.identificationProtocol;
515
if (session != null && identityAlg != null) {
516
String sessionIdentityAlg =
517
session.getIdentificationProtocol();
518
if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) {
519
if (SSLLogger.isOn &&
520
SSLLogger.isOn("ssl,handshake,verbose")) {
521
SSLLogger.finest("Can't resume, endpoint id" +
522
" algorithm does not match, requested: " +
523
identityAlg + ", cached: " + sessionIdentityAlg);
524
}
525
session = null;
526
}
527
}
528
529
if (session != null) {
530
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) {
531
SSLLogger.finest("Try resuming session", session);
532
}
533
534
// only set session id if session is 1.2 or earlier
535
if (!session.getProtocolVersion().useTLS13PlusSpec()) {
536
sessionId = session.getSessionId();
537
}
538
539
// If no new session is allowed, force use of the previous
540
// session ciphersuite, and add the renegotiation SCSV if
541
// necessary.
542
if (!chc.sslConfig.enableSessionCreation) {
543
if (!chc.conContext.isNegotiated &&
544
!sessionVersion.useTLS13PlusSpec() &&
545
cipherSuites.contains(
546
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) {
547
cipherSuites = Arrays.asList(sessionSuite,
548
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
549
} else { // otherwise, use renegotiation_info extension
550
cipherSuites = List.of(sessionSuite);
551
}
552
553
if (SSLLogger.isOn &&
554
SSLLogger.isOn("ssl,handshake,verbose")) {
555
SSLLogger.finest(
556
"No new session is allowed, so try to resume " +
557
"the session cipher suite only", sessionSuite);
558
}
559
}
560
561
chc.isResumption = true;
562
chc.resumingSession = session;
563
}
564
565
if (session == null) {
566
if (!chc.sslConfig.enableSessionCreation) {
567
throw new SSLHandshakeException(
568
"No new session is allowed and " +
569
"no existing session can be resumed");
570
}
571
572
if (chc.maximumActiveProtocol.useTLS13PlusSpec() &&
573
SSLConfiguration.useCompatibilityMode) {
574
// In compatibility mode, the TLS 1.3 legacy_session_id
575
// field MUST be non-empty, so a client not offering a
576
// pre-TLS 1.3 session MUST generate a new 32-byte value.
577
sessionId =
578
new SessionId(true, chc.sslContext.getSecureRandom());
579
}
580
}
581
582
ProtocolVersion minimumVersion = ProtocolVersion.NONE;
583
for (ProtocolVersion pv : chc.activeProtocols) {
584
if (minimumVersion == ProtocolVersion.NONE ||
585
pv.compare(minimumVersion) < 0) {
586
minimumVersion = pv;
587
}
588
}
589
590
// exclude SCSV for secure renegotiation
591
if (!minimumVersion.useTLS13PlusSpec()) {
592
if (chc.conContext.secureRenegotiation &&
593
cipherSuites.contains(
594
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) {
595
// The cipherSuites may be unmodifiable
596
cipherSuites = new LinkedList<>(cipherSuites);
597
cipherSuites.remove(
598
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
599
}
600
}
601
602
// make sure there is a negotiable cipher suite.
603
boolean negotiable = false;
604
for (CipherSuite suite : cipherSuites) {
605
if (chc.isNegotiable(suite)) {
606
negotiable = true;
607
break;
608
}
609
}
610
if (!negotiable) {
611
throw new SSLHandshakeException("No negotiable cipher suite");
612
}
613
614
// Create the handshake message.
615
ProtocolVersion clientHelloVersion = chc.maximumActiveProtocol;
616
if (clientHelloVersion.useTLS13PlusSpec()) {
617
// In (D)TLS 1.3, the client indicates its version preferences
618
// in the "supported_versions" extension and the client_version
619
// (legacy_version) field MUST be set to (D)TLS 1.2.
620
if (clientHelloVersion.isDTLS) {
621
clientHelloVersion = ProtocolVersion.DTLS12;
622
} else {
623
clientHelloVersion = ProtocolVersion.TLS12;
624
}
625
}
626
627
ClientHelloMessage chm = new ClientHelloMessage(chc,
628
clientHelloVersion.id, sessionId, cipherSuites,
629
chc.sslContext.getSecureRandom());
630
631
// cache the client random number for further using
632
chc.clientHelloRandom = chm.clientRandom;
633
chc.clientHelloVersion = clientHelloVersion.id;
634
635
// Produce extensions for ClientHello handshake message.
636
SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
637
SSLHandshake.CLIENT_HELLO, chc.activeProtocols);
638
chm.extensions.produce(chc, extTypes);
639
640
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
641
SSLLogger.fine("Produced ClientHello handshake message", chm);
642
}
643
644
// Output the handshake message.
645
chm.write(chc.handshakeOutput);
646
chc.handshakeOutput.flush();
647
648
// Reserve the initial ClientHello message for the follow on
649
// cookie exchange if needed.
650
chc.initialClientHelloMsg = chm;
651
652
// What's the expected response?
653
chc.handshakeConsumers.put(
654
SSLHandshake.SERVER_HELLO.id, SSLHandshake.SERVER_HELLO);
655
if (chc.sslContext.isDTLS() &&
656
!minimumVersion.useTLS13PlusSpec()) {
657
chc.handshakeConsumers.put(
658
SSLHandshake.HELLO_VERIFY_REQUEST.id,
659
SSLHandshake.HELLO_VERIFY_REQUEST);
660
}
661
662
// The handshake message has been delivered.
663
return null;
664
}
665
}
666
667
private static final
668
class ClientHelloProducer implements HandshakeProducer {
669
// Prevent instantiation of this class.
670
private ClientHelloProducer() {
671
// blank
672
}
673
674
// Response to one of the following handshake message:
675
// HelloRequest (SSL 3.0/TLS 1.0/1.1/1.2)
676
// ServerHello(HelloRetryRequest) (TLS 1.3)
677
// HelloVerifyRequest (DTLS 1.0/1.2)
678
@Override
679
public byte[] produce(ConnectionContext context,
680
HandshakeMessage message) throws IOException {
681
// The producing happens in client side only.
682
ClientHandshakeContext chc = (ClientHandshakeContext)context;
683
684
SSLHandshake ht = message.handshakeType();
685
if (ht == null) {
686
throw new UnsupportedOperationException("Not supported yet.");
687
}
688
689
switch (ht) {
690
case HELLO_REQUEST:
691
// SSL 3.0/TLS 1.0/1.1/1.2
692
try {
693
chc.kickstart();
694
} catch (IOException ioe) {
695
throw chc.conContext.fatal(
696
Alert.HANDSHAKE_FAILURE, ioe);
697
}
698
699
// The handshake message has been delivered.
700
return null;
701
case HELLO_VERIFY_REQUEST:
702
// DTLS 1.0/1.2
703
//
704
// The HelloVerifyRequest consumer should have updated the
705
// ClientHello handshake message with cookie.
706
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
707
SSLLogger.fine(
708
"Produced ClientHello(cookie) handshake message",
709
chc.initialClientHelloMsg);
710
}
711
712
// Output the handshake message.
713
chc.initialClientHelloMsg.write(chc.handshakeOutput);
714
chc.handshakeOutput.flush();
715
716
// What's the expected response?
717
chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO.id,
718
SSLHandshake.SERVER_HELLO);
719
720
ProtocolVersion minimumVersion = ProtocolVersion.NONE;
721
for (ProtocolVersion pv : chc.activeProtocols) {
722
if (minimumVersion == ProtocolVersion.NONE ||
723
pv.compare(minimumVersion) < 0) {
724
minimumVersion = pv;
725
}
726
}
727
if (chc.sslContext.isDTLS() &&
728
!minimumVersion.useTLS13PlusSpec()) {
729
chc.handshakeConsumers.put(
730
SSLHandshake.HELLO_VERIFY_REQUEST.id,
731
SSLHandshake.HELLO_VERIFY_REQUEST);
732
}
733
734
// The handshake message has been delivered.
735
return null;
736
case HELLO_RETRY_REQUEST:
737
// TLS 1.3
738
// The HelloRetryRequest consumer should have updated the
739
// ClientHello handshake message with cookie.
740
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
741
SSLLogger.fine(
742
"Produced ClientHello(HRR) handshake message",
743
chc.initialClientHelloMsg);
744
}
745
746
// Output the handshake message.
747
chc.initialClientHelloMsg.write(chc.handshakeOutput);
748
chc.handshakeOutput.flush();
749
750
// What's the expected response?
751
chc.conContext.consumers.putIfAbsent(
752
ContentType.CHANGE_CIPHER_SPEC.id,
753
ChangeCipherSpec.t13Consumer);
754
chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO.id,
755
SSLHandshake.SERVER_HELLO);
756
757
// The handshake message has been delivered.
758
return null;
759
default:
760
throw new UnsupportedOperationException(
761
"Not supported yet.");
762
}
763
}
764
}
765
766
/**
767
* The "ClientHello" handshake message consumer.
768
*/
769
private static final class ClientHelloConsumer implements SSLConsumer {
770
// Prevent instantiation of this class.
771
private ClientHelloConsumer() {
772
// blank
773
}
774
775
@Override
776
public void consume(ConnectionContext context,
777
ByteBuffer message) throws IOException {
778
// The consuming happens in server side only.
779
ServerHandshakeContext shc = (ServerHandshakeContext)context;
780
781
// clean up this consumer
782
shc.handshakeConsumers.remove(SSLHandshake.CLIENT_HELLO.id);
783
if (!shc.handshakeConsumers.isEmpty()) {
784
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
785
"No more handshake message allowed " +
786
"in a ClientHello flight");
787
}
788
789
// Get enabled extension types in ClientHello handshake message.
790
SSLExtension[] enabledExtensions =
791
shc.sslConfig.getEnabledExtensions(
792
SSLHandshake.CLIENT_HELLO);
793
794
ClientHelloMessage chm =
795
new ClientHelloMessage(shc, message, enabledExtensions);
796
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
797
SSLLogger.fine("Consuming ClientHello handshake message", chm);
798
}
799
800
shc.clientHelloVersion = chm.clientVersion;
801
onClientHello(shc, chm);
802
}
803
804
private void onClientHello(ServerHandshakeContext context,
805
ClientHelloMessage clientHello) throws IOException {
806
// Negotiate protocol version.
807
//
808
// Check and launch SupportedVersions.
809
SSLExtension[] extTypes = new SSLExtension[] {
810
SSLExtension.CH_SUPPORTED_VERSIONS
811
};
812
clientHello.extensions.consumeOnLoad(context, extTypes);
813
814
ProtocolVersion negotiatedProtocol;
815
CHSupportedVersionsSpec svs =
816
(CHSupportedVersionsSpec)context.handshakeExtensions.get(
817
SSLExtension.CH_SUPPORTED_VERSIONS);
818
if (svs != null) {
819
negotiatedProtocol =
820
negotiateProtocol(context, svs.requestedProtocols);
821
} else {
822
negotiatedProtocol =
823
negotiateProtocol(context, clientHello.clientVersion);
824
}
825
context.negotiatedProtocol = negotiatedProtocol;
826
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
827
SSLLogger.fine(
828
"Negotiated protocol version: " + negotiatedProtocol.name);
829
}
830
831
// Consume the handshake message for the specific protocol version.
832
if (negotiatedProtocol.isDTLS) {
833
if (negotiatedProtocol.useTLS13PlusSpec()) {
834
d13HandshakeConsumer.consume(context, clientHello);
835
} else {
836
d12HandshakeConsumer.consume(context, clientHello);
837
}
838
} else {
839
if (negotiatedProtocol.useTLS13PlusSpec()) {
840
t13HandshakeConsumer.consume(context, clientHello);
841
} else {
842
t12HandshakeConsumer.consume(context, clientHello);
843
}
844
}
845
}
846
847
// Select a protocol version according to the
848
// ClientHello.client_version.
849
private ProtocolVersion negotiateProtocol(
850
ServerHandshakeContext context,
851
int clientHelloVersion) throws SSLException {
852
853
// Per TLS 1.3 specification, server MUST negotiate TLS 1.2 or prior
854
// even if ClientHello.client_version is 0x0304 or later.
855
int chv = clientHelloVersion;
856
if (context.sslContext.isDTLS()) {
857
if (chv < ProtocolVersion.DTLS12.id) {
858
chv = ProtocolVersion.DTLS12.id;
859
}
860
} else {
861
if (chv > ProtocolVersion.TLS12.id) {
862
chv = ProtocolVersion.TLS12.id;
863
}
864
}
865
866
// Select a protocol version from the activated protocols.
867
ProtocolVersion pv = ProtocolVersion.selectedFrom(
868
context.activeProtocols, chv);
869
if (pv == null || pv == ProtocolVersion.NONE ||
870
pv == ProtocolVersion.SSL20Hello) {
871
throw context.conContext.fatal(Alert.PROTOCOL_VERSION,
872
"Client requested protocol " +
873
ProtocolVersion.nameOf(clientHelloVersion) +
874
" is not enabled or supported in server context");
875
}
876
877
return pv;
878
}
879
880
// Select a protocol version according to the
881
// supported_versions extension.
882
private ProtocolVersion negotiateProtocol(
883
ServerHandshakeContext context,
884
int[] clientSupportedVersions) throws SSLException {
885
886
// The client supported protocol versions are present in client
887
// preference order. This implementation chooses to use the server
888
// preference of protocol versions instead.
889
for (ProtocolVersion spv : context.activeProtocols) {
890
if (spv == ProtocolVersion.SSL20Hello) {
891
continue;
892
}
893
for (int cpv : clientSupportedVersions) {
894
if (cpv == ProtocolVersion.SSL20Hello.id) {
895
continue;
896
}
897
if (spv.id == cpv) {
898
return spv;
899
}
900
}
901
}
902
903
// No protocol version can be negotiated.
904
throw context.conContext.fatal(Alert.PROTOCOL_VERSION,
905
"The client supported protocol versions " + Arrays.toString(
906
ProtocolVersion.toStringArray(clientSupportedVersions)) +
907
" are not accepted by server preferences " +
908
context.activeProtocols);
909
}
910
}
911
912
/**
913
* The "ClientHello" handshake message consumer for TLS 1.2 and
914
* prior SSL/TLS protocol versions.
915
*/
916
private static final
917
class T12ClientHelloConsumer implements HandshakeConsumer {
918
// Prevent instantiation of this class.
919
private T12ClientHelloConsumer() {
920
// blank
921
}
922
923
@Override
924
public void consume(ConnectionContext context,
925
HandshakeMessage message) throws IOException {
926
// The consuming happens in server side only.
927
ServerHandshakeContext shc = (ServerHandshakeContext)context;
928
ClientHelloMessage clientHello = (ClientHelloMessage)message;
929
930
//
931
// validate
932
//
933
934
// Reject client initiated renegotiation?
935
//
936
// If server side should reject client-initiated renegotiation,
937
// send an Alert.HANDSHAKE_FAILURE fatal alert, not a
938
// no_renegotiation warning alert (no_renegotiation must be a
939
// warning: RFC 2246). no_renegotiation might seem more
940
// natural at first, but warnings are not appropriate because
941
// the sending party does not know how the receiving party
942
// will behave. This state must be treated as a fatal server
943
// condition.
944
//
945
// This will not have any impact on server initiated renegotiation.
946
if (shc.conContext.isNegotiated) {
947
if (!shc.conContext.secureRenegotiation &&
948
!HandshakeContext.allowUnsafeRenegotiation) {
949
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
950
"Unsafe renegotiation is not allowed");
951
}
952
953
if (ServerHandshakeContext.rejectClientInitiatedRenego &&
954
!shc.kickstartMessageDelivered) {
955
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
956
"Client initiated renegotiation is not allowed");
957
}
958
}
959
960
// Consume a Session Ticket Extension if it exists
961
SSLExtension[] ext = new SSLExtension[]{
962
SSLExtension.CH_SESSION_TICKET
963
};
964
clientHello.extensions.consumeOnLoad(shc, ext);
965
966
// Does the client want to resume a session?
967
if (clientHello.sessionId.length() != 0 || shc.statelessResumption) {
968
SSLSessionContextImpl cache = (SSLSessionContextImpl)shc.sslContext
969
.engineGetServerSessionContext();
970
971
SSLSessionImpl previous;
972
// Use the stateless session ticket if provided
973
if (shc.statelessResumption) {
974
previous = shc.resumingSession;
975
} else {
976
previous = cache.get(clientHello.sessionId.getId());
977
}
978
979
boolean resumingSession =
980
(previous != null) && previous.isRejoinable();
981
if (!resumingSession) {
982
if (SSLLogger.isOn &&
983
SSLLogger.isOn("ssl,handshake,verbose")) {
984
SSLLogger.finest(
985
"Can't resume, " +
986
"the existing session is not rejoinable");
987
}
988
}
989
// Validate the negotiated protocol version.
990
if (resumingSession) {
991
ProtocolVersion sessionProtocol =
992
previous.getProtocolVersion();
993
if (sessionProtocol != shc.negotiatedProtocol) {
994
resumingSession = false;
995
if (SSLLogger.isOn &&
996
SSLLogger.isOn("ssl,handshake,verbose")) {
997
SSLLogger.finest(
998
"Can't resume, not the same protocol version");
999
}
1000
}
1001
}
1002
1003
// Validate the required client authentication.
1004
if (resumingSession &&
1005
(shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) {
1006
try {
1007
previous.getPeerPrincipal();
1008
} catch (SSLPeerUnverifiedException e) {
1009
resumingSession = false;
1010
if (SSLLogger.isOn &&
1011
SSLLogger.isOn("ssl,handshake,verbose")) {
1012
SSLLogger.finest(
1013
"Can't resume, " +
1014
"client authentication is required");
1015
}
1016
}
1017
}
1018
1019
// Validate that the cached cipher suite.
1020
if (resumingSession) {
1021
CipherSuite suite = previous.getSuite();
1022
if ((!shc.isNegotiable(suite)) ||
1023
(!clientHello.cipherSuites.contains(suite))) {
1024
resumingSession = false;
1025
if (SSLLogger.isOn &&
1026
SSLLogger.isOn("ssl,handshake,verbose")) {
1027
SSLLogger.finest(
1028
"Can't resume, " +
1029
"the session cipher suite is absent");
1030
}
1031
}
1032
}
1033
1034
// ensure that the endpoint identification algorithm matches the
1035
// one in the session
1036
String identityAlg = shc.sslConfig.identificationProtocol;
1037
if (resumingSession && identityAlg != null) {
1038
String sessionIdentityAlg =
1039
previous.getIdentificationProtocol();
1040
if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) {
1041
if (SSLLogger.isOn &&
1042
SSLLogger.isOn("ssl,handshake,verbose")) {
1043
SSLLogger.finest("Can't resume, endpoint id" +
1044
" algorithm does not match, requested: " +
1045
identityAlg + ", cached: " + sessionIdentityAlg);
1046
}
1047
resumingSession = false;
1048
}
1049
}
1050
1051
// So far so good. Note that the handshake extensions may reset
1052
// the resuming options later.
1053
shc.isResumption = resumingSession;
1054
shc.resumingSession = resumingSession ? previous : null;
1055
1056
if (!resumingSession && SSLLogger.isOn &&
1057
SSLLogger.isOn("ssl,handshake")) {
1058
SSLLogger.fine("Session not resumed.");
1059
}
1060
}
1061
1062
// cache the client random number for further using
1063
shc.clientHelloRandom = clientHello.clientRandom;
1064
1065
// Check and launch ClientHello extensions.
1066
SSLExtension[] extTypes = shc.sslConfig.getExclusiveExtensions(
1067
SSLHandshake.CLIENT_HELLO,
1068
List.of(SSLExtension.CH_SESSION_TICKET));
1069
clientHello.extensions.consumeOnLoad(shc, extTypes);
1070
1071
//
1072
// update
1073
//
1074
if (!shc.conContext.isNegotiated) {
1075
shc.conContext.protocolVersion = shc.negotiatedProtocol;
1076
shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol);
1077
}
1078
1079
// update the responders
1080
//
1081
// Only need to ServerHello, which may add more responders later.
1082
// Note that ServerHello and HelloRetryRequest share the same
1083
// handshake type/id. The ServerHello producer may be replaced
1084
// by HelloRetryRequest producer if needed.
1085
shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
1086
SSLHandshake.SERVER_HELLO);
1087
1088
//
1089
// produce
1090
//
1091
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
1092
SSLHandshake.SERVER_HELLO,
1093
1094
// full handshake messages
1095
SSLHandshake.CERTIFICATE,
1096
SSLHandshake.CERTIFICATE_STATUS,
1097
SSLHandshake.SERVER_KEY_EXCHANGE,
1098
SSLHandshake.CERTIFICATE_REQUEST,
1099
SSLHandshake.SERVER_HELLO_DONE,
1100
1101
// abbreviated handshake messages
1102
SSLHandshake.FINISHED
1103
};
1104
1105
for (SSLHandshake hs : probableHandshakeMessages) {
1106
HandshakeProducer handshakeProducer =
1107
shc.handshakeProducers.remove(hs.id);
1108
if (handshakeProducer != null) {
1109
handshakeProducer.produce(context, clientHello);
1110
}
1111
}
1112
}
1113
}
1114
1115
/**
1116
* The "ClientHello" handshake message consumer for TLS 1.3.
1117
*/
1118
private static final
1119
class T13ClientHelloConsumer implements HandshakeConsumer {
1120
// Prevent instantiation of this class.
1121
private T13ClientHelloConsumer() {
1122
// blank
1123
}
1124
1125
@Override
1126
public void consume(ConnectionContext context,
1127
HandshakeMessage message) throws IOException {
1128
// The consuming happens in server side only.
1129
ServerHandshakeContext shc = (ServerHandshakeContext)context;
1130
ClientHelloMessage clientHello = (ClientHelloMessage)message;
1131
1132
// [RFC 8446] TLS 1.3 forbids renegotiation. If a server has
1133
// negotiated TLS 1.3 and receives a ClientHello at any other
1134
// time, it MUST terminate the connection with an
1135
// "unexpected_message" alert.
1136
if (shc.conContext.isNegotiated) {
1137
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
1138
"Received unexpected renegotiation handshake message");
1139
}
1140
1141
if (clientHello.clientVersion != ProtocolVersion.TLS12.id) {
1142
throw shc.conContext.fatal(Alert.PROTOCOL_VERSION,
1143
"The ClientHello.legacy_version field is not TLS 1.2");
1144
}
1145
1146
// The client may send a dummy change_cipher_spec record
1147
// immediately after the first ClientHello.
1148
shc.conContext.consumers.putIfAbsent(
1149
ContentType.CHANGE_CIPHER_SPEC.id,
1150
ChangeCipherSpec.t13Consumer);
1151
1152
// Is it a resumption?
1153
//
1154
// Check and launch the "psk_key_exchange_modes" and
1155
// "pre_shared_key" extensions first, which will reset the
1156
// resuming session, no matter the extensions present or not.
1157
shc.isResumption = true;
1158
SSLExtension[] extTypes = new SSLExtension[] {
1159
SSLExtension.PSK_KEY_EXCHANGE_MODES,
1160
SSLExtension.CH_PRE_SHARED_KEY
1161
};
1162
clientHello.extensions.consumeOnLoad(shc, extTypes);
1163
1164
// Check and launch ClientHello extensions other than
1165
// "psk_key_exchange_modes", "pre_shared_key", "protocol_version"
1166
// and "key_share" extensions.
1167
//
1168
// These extensions may discard session resumption, or ask for
1169
// hello retry.
1170
extTypes = shc.sslConfig.getExclusiveExtensions(
1171
SSLHandshake.CLIENT_HELLO,
1172
Arrays.asList(
1173
SSLExtension.PSK_KEY_EXCHANGE_MODES,
1174
SSLExtension.CH_PRE_SHARED_KEY,
1175
SSLExtension.CH_SUPPORTED_VERSIONS));
1176
clientHello.extensions.consumeOnLoad(shc, extTypes);
1177
1178
if (!shc.handshakeProducers.isEmpty()) {
1179
// Should be HelloRetryRequest producer.
1180
goHelloRetryRequest(shc, clientHello);
1181
} else {
1182
goServerHello(shc, clientHello);
1183
}
1184
}
1185
1186
private void goHelloRetryRequest(ServerHandshakeContext shc,
1187
ClientHelloMessage clientHello) throws IOException {
1188
HandshakeProducer handshakeProducer =
1189
shc.handshakeProducers.remove(
1190
SSLHandshake.HELLO_RETRY_REQUEST.id);
1191
if (handshakeProducer != null) {
1192
handshakeProducer.produce(shc, clientHello);
1193
} else {
1194
// unlikely
1195
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1196
"No HelloRetryRequest producer: " + shc.handshakeProducers);
1197
}
1198
1199
if (!shc.handshakeProducers.isEmpty()) {
1200
// unlikely, but please double check.
1201
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1202
"unknown handshake producers: " + shc.handshakeProducers);
1203
}
1204
}
1205
1206
private void goServerHello(ServerHandshakeContext shc,
1207
ClientHelloMessage clientHello) throws IOException {
1208
//
1209
// validate
1210
//
1211
shc.clientHelloRandom = clientHello.clientRandom;
1212
1213
//
1214
// update
1215
//
1216
if (!shc.conContext.isNegotiated) {
1217
shc.conContext.protocolVersion = shc.negotiatedProtocol;
1218
shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol);
1219
}
1220
1221
// update the responders
1222
//
1223
// Only ServerHello/HelloRetryRequest producer, which adds
1224
// more responders later.
1225
shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
1226
SSLHandshake.SERVER_HELLO);
1227
1228
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
1229
SSLHandshake.SERVER_HELLO,
1230
1231
// full handshake messages
1232
SSLHandshake.ENCRYPTED_EXTENSIONS,
1233
SSLHandshake.CERTIFICATE_REQUEST,
1234
SSLHandshake.CERTIFICATE,
1235
SSLHandshake.CERTIFICATE_VERIFY,
1236
SSLHandshake.FINISHED
1237
};
1238
1239
//
1240
// produce
1241
//
1242
for (SSLHandshake hs : probableHandshakeMessages) {
1243
HandshakeProducer handshakeProducer =
1244
shc.handshakeProducers.remove(hs.id);
1245
if (handshakeProducer != null) {
1246
handshakeProducer.produce(shc, clientHello);
1247
}
1248
}
1249
}
1250
}
1251
1252
/**
1253
* The "ClientHello" handshake message consumer for DTLS 1.2 and
1254
* previous DTLS protocol versions.
1255
*/
1256
private static final
1257
class D12ClientHelloConsumer implements HandshakeConsumer {
1258
// Prevent instantiation of this class.
1259
private D12ClientHelloConsumer() {
1260
// blank
1261
}
1262
1263
@Override
1264
public void consume(ConnectionContext context,
1265
HandshakeMessage message) throws IOException {
1266
// The consuming happens in server side only.
1267
ServerHandshakeContext shc = (ServerHandshakeContext)context;
1268
ClientHelloMessage clientHello = (ClientHelloMessage)message;
1269
1270
//
1271
// validate
1272
//
1273
1274
// Reject client initiated renegotiation?
1275
//
1276
// If server side should reject client-initiated renegotiation,
1277
// send an Alert.HANDSHAKE_FAILURE fatal alert, not a
1278
// no_renegotiation warning alert (no_renegotiation must be a
1279
// warning: RFC 2246). no_renegotiation might seem more
1280
// natural at first, but warnings are not appropriate because
1281
// the sending party does not know how the receiving party
1282
// will behave. This state must be treated as a fatal server
1283
// condition.
1284
//
1285
// This will not have any impact on server initiated renegotiation.
1286
if (shc.conContext.isNegotiated) {
1287
if (!shc.conContext.secureRenegotiation &&
1288
!HandshakeContext.allowUnsafeRenegotiation) {
1289
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1290
"Unsafe renegotiation is not allowed");
1291
}
1292
1293
if (ServerHandshakeContext.rejectClientInitiatedRenego &&
1294
!shc.kickstartMessageDelivered) {
1295
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1296
"Client initiated renegotiation is not allowed");
1297
}
1298
}
1299
1300
1301
// Does the client want to resume a session?
1302
if (clientHello.sessionId.length() != 0) {
1303
SSLSessionContextImpl cache = (SSLSessionContextImpl)shc.sslContext
1304
.engineGetServerSessionContext();
1305
1306
// Consume a Session Ticket Extension if it exists
1307
SSLExtension[] ext = new SSLExtension[]{
1308
SSLExtension.CH_SESSION_TICKET
1309
};
1310
clientHello.extensions.consumeOnLoad(shc, ext);
1311
1312
SSLSessionImpl previous;
1313
// Use stateless session ticket if provided.
1314
if (shc.statelessResumption) {
1315
previous = shc.resumingSession;
1316
} else {
1317
previous = cache.get(clientHello.sessionId.getId());
1318
}
1319
1320
boolean resumingSession =
1321
(previous != null) && previous.isRejoinable();
1322
if (!resumingSession) {
1323
if (SSLLogger.isOn &&
1324
SSLLogger.isOn("ssl,handshake,verbose")) {
1325
SSLLogger.finest(
1326
"Can't resume, " +
1327
"the existing session is not rejoinable");
1328
}
1329
}
1330
// Validate the negotiated protocol version.
1331
if (resumingSession) {
1332
ProtocolVersion sessionProtocol =
1333
previous.getProtocolVersion();
1334
if (sessionProtocol != shc.negotiatedProtocol) {
1335
resumingSession = false;
1336
if (SSLLogger.isOn &&
1337
SSLLogger.isOn("ssl,handshake,verbose")) {
1338
SSLLogger.finest(
1339
"Can't resume, not the same protocol version");
1340
}
1341
}
1342
}
1343
1344
// Validate the required client authentication.
1345
if (resumingSession &&
1346
(shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) {
1347
1348
try {
1349
previous.getPeerPrincipal();
1350
} catch (SSLPeerUnverifiedException e) {
1351
resumingSession = false;
1352
if (SSLLogger.isOn &&
1353
SSLLogger.isOn("ssl,handshake,verbose")) {
1354
SSLLogger.finest(
1355
"Can't resume, " +
1356
"client authentication is required");
1357
}
1358
}
1359
}
1360
1361
// Validate that the cached cipher suite.
1362
if (resumingSession) {
1363
CipherSuite suite = previous.getSuite();
1364
if ((!shc.isNegotiable(suite)) ||
1365
(!clientHello.cipherSuites.contains(suite))) {
1366
resumingSession = false;
1367
if (SSLLogger.isOn &&
1368
SSLLogger.isOn("ssl,handshake,verbose")) {
1369
SSLLogger.finest(
1370
"Can't resume, " +
1371
"the session cipher suite is absent");
1372
}
1373
}
1374
}
1375
1376
// So far so good. Note that the handshake extensions may reset
1377
// the resuming options later.
1378
shc.isResumption = resumingSession;
1379
shc.resumingSession = resumingSession ? previous : null;
1380
}
1381
1382
HelloCookieManager hcm =
1383
shc.sslContext.getHelloCookieManager(ProtocolVersion.DTLS10);
1384
if (!shc.isResumption &&
1385
!hcm.isCookieValid(shc, clientHello, clientHello.cookie)) {
1386
//
1387
// Perform cookie exchange for DTLS handshaking if no cookie
1388
// or the cookie is invalid in the ClientHello message.
1389
//
1390
// update the responders
1391
shc.handshakeProducers.put(
1392
SSLHandshake.HELLO_VERIFY_REQUEST.id,
1393
SSLHandshake.HELLO_VERIFY_REQUEST);
1394
1395
//
1396
// produce response handshake message
1397
//
1398
SSLHandshake.HELLO_VERIFY_REQUEST.produce(context, clientHello);
1399
1400
return;
1401
}
1402
1403
// cache the client random number for further using
1404
shc.clientHelloRandom = clientHello.clientRandom;
1405
1406
// Check and launch ClientHello extensions.
1407
SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(
1408
SSLHandshake.CLIENT_HELLO);
1409
clientHello.extensions.consumeOnLoad(shc, extTypes);
1410
1411
//
1412
// update
1413
//
1414
if (!shc.conContext.isNegotiated) {
1415
shc.conContext.protocolVersion = shc.negotiatedProtocol;
1416
shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol);
1417
}
1418
1419
// update the responders
1420
//
1421
// Only need to ServerHello, which may add more responders later.
1422
shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
1423
SSLHandshake.SERVER_HELLO);
1424
1425
//
1426
// produce
1427
//
1428
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
1429
SSLHandshake.SERVER_HELLO,
1430
1431
// full handshake messages
1432
SSLHandshake.CERTIFICATE,
1433
SSLHandshake.CERTIFICATE_STATUS,
1434
SSLHandshake.SERVER_KEY_EXCHANGE,
1435
SSLHandshake.CERTIFICATE_REQUEST,
1436
SSLHandshake.SERVER_HELLO_DONE,
1437
1438
// abbreviated handshake messages
1439
SSLHandshake.FINISHED
1440
};
1441
1442
for (SSLHandshake hs : probableHandshakeMessages) {
1443
HandshakeProducer handshakeProducer =
1444
shc.handshakeProducers.remove(hs.id);
1445
if (handshakeProducer != null) {
1446
handshakeProducer.produce(context, clientHello);
1447
}
1448
}
1449
}
1450
}
1451
1452
/**
1453
* The "ClientHello" handshake message consumer for DTLS 1.3.
1454
*/
1455
private static final
1456
class D13ClientHelloConsumer implements HandshakeConsumer {
1457
// Prevent instantiation of this class.
1458
private D13ClientHelloConsumer() {
1459
// blank
1460
}
1461
1462
@Override
1463
public void consume(ConnectionContext context,
1464
HandshakeMessage message) throws IOException {
1465
throw new UnsupportedOperationException("Not supported yet.");
1466
}
1467
}
1468
}
1469
1470