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/ClientHello.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.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
// the max protocol version this client is supporting.
406
ProtocolVersion maxProtocolVersion = chc.maximumActiveProtocol;
407
408
// session ID of the ClientHello message
409
SessionId sessionId = new SessionId(new byte[0]);
410
411
// a list of cipher suites sent by the client
412
List<CipherSuite> cipherSuites = chc.activeCipherSuites;
413
414
//
415
// Try to resume an existing session.
416
//
417
SSLSessionContextImpl ssci = (SSLSessionContextImpl)
418
chc.sslContext.engineGetClientSessionContext();
419
SSLSessionImpl session = ssci.get(
420
chc.conContext.transport.getPeerHost(),
421
chc.conContext.transport.getPeerPort());
422
if (session != null) {
423
// If unsafe server certificate change is not allowed, reserve
424
// current server certificates if the previous handshake is a
425
// session-resumption abbreviated initial handshake.
426
if (!ClientHandshakeContext.allowUnsafeServerCertChange &&
427
session.isSessionResumption()) {
428
try {
429
// If existing, peer certificate chain cannot be null.
430
chc.reservedServerCerts =
431
(X509Certificate[])session.getPeerCertificates();
432
} catch (SSLPeerUnverifiedException puve) {
433
// Maybe not certificate-based, ignore the exception.
434
}
435
}
436
437
if (!session.isRejoinable()) {
438
session = null;
439
if (SSLLogger.isOn &&
440
SSLLogger.isOn("ssl,handshake,verbose")) {
441
SSLLogger.finest(
442
"Can't resume, the session is not rejoinable");
443
}
444
}
445
}
446
447
CipherSuite sessionSuite = null;
448
if (session != null) {
449
sessionSuite = session.getSuite();
450
if (!chc.isNegotiable(sessionSuite)) {
451
session = null;
452
if (SSLLogger.isOn &&
453
SSLLogger.isOn("ssl,handshake,verbose")) {
454
SSLLogger.finest(
455
"Can't resume, unavailable session cipher suite");
456
}
457
}
458
}
459
460
ProtocolVersion sessionVersion = null;
461
if (session != null) {
462
sessionVersion = session.getProtocolVersion();
463
if (!chc.isNegotiable(sessionVersion)) {
464
session = null;
465
if (SSLLogger.isOn &&
466
SSLLogger.isOn("ssl,handshake,verbose")) {
467
SSLLogger.finest(
468
"Can't resume, unavailable protocol version");
469
}
470
}
471
}
472
473
if (session != null &&
474
!sessionVersion.useTLS13PlusSpec() &&
475
SSLConfiguration.useExtendedMasterSecret) {
476
477
boolean isEmsAvailable = chc.sslConfig.isAvailable(
478
SSLExtension.CH_EXTENDED_MASTER_SECRET, sessionVersion);
479
if (isEmsAvailable && !session.useExtendedMasterSecret &&
480
!SSLConfiguration.allowLegacyResumption) {
481
// perform full handshake instead
482
//
483
// The client SHOULD NOT offer an abbreviated handshake
484
// to resume a session that does not use an extended
485
// master secret. Instead, it SHOULD offer a full
486
// handshake.
487
session = null;
488
}
489
490
if ((session != null) &&
491
!ClientHandshakeContext.allowUnsafeServerCertChange) {
492
// It is fine to move on with abbreviate handshake if
493
// endpoint identification is enabled.
494
String identityAlg = chc.sslConfig.identificationProtocol;
495
if (identityAlg == null || identityAlg.isEmpty()) {
496
if (isEmsAvailable) {
497
if (!session.useExtendedMasterSecret) {
498
// perform full handshake instead
499
session = null;
500
} // Otherwise, use extended master secret.
501
} else {
502
// The extended master secret extension does not
503
// apply to SSL 3.0. Perform a full handshake
504
// instead.
505
//
506
// Note that the useExtendedMasterSecret is
507
// extended to protect SSL 3.0 connections,
508
// by discarding abbreviate handshake.
509
session = null;
510
}
511
}
512
}
513
}
514
515
// ensure that the endpoint identification algorithm matches the
516
// one in the session
517
String identityAlg = chc.sslConfig.identificationProtocol;
518
if (session != null && identityAlg != null) {
519
String sessionIdentityAlg =
520
session.getIdentificationProtocol();
521
if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) {
522
if (SSLLogger.isOn &&
523
SSLLogger.isOn("ssl,handshake,verbose")) {
524
SSLLogger.finest("Can't resume, endpoint id" +
525
" algorithm does not match, requested: " +
526
identityAlg + ", cached: " + sessionIdentityAlg);
527
}
528
session = null;
529
}
530
}
531
532
if (session != null) {
533
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) {
534
SSLLogger.finest("Try resuming session", session);
535
}
536
537
// only set session id if session is 1.2 or earlier
538
if (!session.getProtocolVersion().useTLS13PlusSpec()) {
539
sessionId = session.getSessionId();
540
}
541
if (!maxProtocolVersion.equals(sessionVersion)) {
542
maxProtocolVersion = sessionVersion;
543
544
// Update protocol version number in underlying socket and
545
// handshake output stream, so that the output records
546
// (at the record layer) have the correct version
547
chc.setVersion(sessionVersion);
548
}
549
550
// If no new session is allowed, force use of the previous
551
// session ciphersuite, and add the renegotiation SCSV if
552
// necessary.
553
if (!chc.sslConfig.enableSessionCreation) {
554
if (!chc.conContext.isNegotiated &&
555
!sessionVersion.useTLS13PlusSpec() &&
556
cipherSuites.contains(
557
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) {
558
cipherSuites = Arrays.asList(sessionSuite,
559
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
560
} else { // otherwise, use renegotiation_info extension
561
cipherSuites = List.of(sessionSuite);
562
}
563
564
if (SSLLogger.isOn &&
565
SSLLogger.isOn("ssl,handshake,verbose")) {
566
SSLLogger.finest(
567
"No new session is allowed, so try to resume " +
568
"the session cipher suite only", sessionSuite);
569
}
570
}
571
572
chc.isResumption = true;
573
chc.resumingSession = session;
574
}
575
576
if (session == null) {
577
if (!chc.sslConfig.enableSessionCreation) {
578
throw new SSLHandshakeException(
579
"No new session is allowed and " +
580
"no existing session can be resumed");
581
}
582
583
if (maxProtocolVersion.useTLS13PlusSpec() &&
584
SSLConfiguration.useCompatibilityMode) {
585
// In compatibility mode, the TLS 1.3 legacy_session_id
586
// field MUST be non-empty, so a client not offering a
587
// pre-TLS 1.3 session MUST generate a new 32-byte value.
588
sessionId =
589
new SessionId(true, chc.sslContext.getSecureRandom());
590
}
591
}
592
593
ProtocolVersion minimumVersion = ProtocolVersion.NONE;
594
for (ProtocolVersion pv : chc.activeProtocols) {
595
if (minimumVersion == ProtocolVersion.NONE ||
596
pv.compare(minimumVersion) < 0) {
597
minimumVersion = pv;
598
}
599
}
600
601
// exclude SCSV for secure renegotiation
602
if (!minimumVersion.useTLS13PlusSpec()) {
603
if (chc.conContext.secureRenegotiation &&
604
cipherSuites.contains(
605
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) {
606
// The cipherSuites may be unmodifiable
607
cipherSuites = new LinkedList<>(cipherSuites);
608
cipherSuites.remove(
609
CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
610
}
611
}
612
613
// make sure there is a negotiable cipher suite.
614
boolean negotiable = false;
615
for (CipherSuite suite : cipherSuites) {
616
if (chc.isNegotiable(suite)) {
617
negotiable = true;
618
break;
619
}
620
}
621
if (!negotiable) {
622
throw new SSLHandshakeException("No negotiable cipher suite");
623
}
624
625
// Create the handshake message.
626
ProtocolVersion clientHelloVersion = maxProtocolVersion;
627
if (clientHelloVersion.useTLS13PlusSpec()) {
628
// In (D)TLS 1.3, the client indicates its version preferences
629
// in the "supported_versions" extension and the client_version
630
// (legacy_version) field MUST be set to (D)TLS 1.2.
631
if (clientHelloVersion.isDTLS) {
632
clientHelloVersion = ProtocolVersion.DTLS12;
633
} else {
634
clientHelloVersion = ProtocolVersion.TLS12;
635
}
636
}
637
638
ClientHelloMessage chm = new ClientHelloMessage(chc,
639
clientHelloVersion.id, sessionId, cipherSuites,
640
chc.sslContext.getSecureRandom());
641
642
// cache the client random number for further using
643
chc.clientHelloRandom = chm.clientRandom;
644
chc.clientHelloVersion = clientHelloVersion.id;
645
646
// Produce extensions for ClientHello handshake message.
647
SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions(
648
SSLHandshake.CLIENT_HELLO, chc.activeProtocols);
649
chm.extensions.produce(chc, extTypes);
650
651
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
652
SSLLogger.fine("Produced ClientHello handshake message", chm);
653
}
654
655
// Output the handshake message.
656
chm.write(chc.handshakeOutput);
657
chc.handshakeOutput.flush();
658
659
// Reserve the initial ClientHello message for the follow on
660
// cookie exchange if needed.
661
chc.initialClientHelloMsg = chm;
662
663
// What's the expected response?
664
chc.handshakeConsumers.put(
665
SSLHandshake.SERVER_HELLO.id, SSLHandshake.SERVER_HELLO);
666
if (chc.sslContext.isDTLS() &&
667
!minimumVersion.useTLS13PlusSpec()) {
668
chc.handshakeConsumers.put(
669
SSLHandshake.HELLO_VERIFY_REQUEST.id,
670
SSLHandshake.HELLO_VERIFY_REQUEST);
671
}
672
673
// The handshake message has been delivered.
674
return null;
675
}
676
}
677
678
private static final
679
class ClientHelloProducer implements HandshakeProducer {
680
// Prevent instantiation of this class.
681
private ClientHelloProducer() {
682
// blank
683
}
684
685
// Response to one of the following handshake message:
686
// HelloRequest (SSL 3.0/TLS 1.0/1.1/1.2)
687
// ServerHello(HelloRetryRequest) (TLS 1.3)
688
// HelloVerifyRequest (DTLS 1.0/1.2)
689
@Override
690
public byte[] produce(ConnectionContext context,
691
HandshakeMessage message) throws IOException {
692
// The producing happens in client side only.
693
ClientHandshakeContext chc = (ClientHandshakeContext)context;
694
695
SSLHandshake ht = message.handshakeType();
696
if (ht == null) {
697
throw new UnsupportedOperationException("Not supported yet.");
698
}
699
700
switch (ht) {
701
case HELLO_REQUEST:
702
// SSL 3.0/TLS 1.0/1.1/1.2
703
try {
704
chc.kickstart();
705
} catch (IOException ioe) {
706
throw chc.conContext.fatal(
707
Alert.HANDSHAKE_FAILURE, ioe);
708
}
709
710
// The handshake message has been delivered.
711
return null;
712
case HELLO_VERIFY_REQUEST:
713
// DTLS 1.0/1.2
714
//
715
// The HelloVerifyRequest consumer should have updated the
716
// ClientHello handshake message with cookie.
717
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
718
SSLLogger.fine(
719
"Produced ClientHello(cookie) handshake message",
720
chc.initialClientHelloMsg);
721
}
722
723
// Output the handshake message.
724
chc.initialClientHelloMsg.write(chc.handshakeOutput);
725
chc.handshakeOutput.flush();
726
727
// What's the expected response?
728
chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO.id,
729
SSLHandshake.SERVER_HELLO);
730
731
ProtocolVersion minimumVersion = ProtocolVersion.NONE;
732
for (ProtocolVersion pv : chc.activeProtocols) {
733
if (minimumVersion == ProtocolVersion.NONE ||
734
pv.compare(minimumVersion) < 0) {
735
minimumVersion = pv;
736
}
737
}
738
if (chc.sslContext.isDTLS() &&
739
!minimumVersion.useTLS13PlusSpec()) {
740
chc.handshakeConsumers.put(
741
SSLHandshake.HELLO_VERIFY_REQUEST.id,
742
SSLHandshake.HELLO_VERIFY_REQUEST);
743
}
744
745
// The handshake message has been delivered.
746
return null;
747
case HELLO_RETRY_REQUEST:
748
// TLS 1.3
749
// The HelloRetryRequest consumer should have updated the
750
// ClientHello handshake message with cookie.
751
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
752
SSLLogger.fine(
753
"Produced ClientHello(HRR) handshake message",
754
chc.initialClientHelloMsg);
755
}
756
757
// Output the handshake message.
758
chc.initialClientHelloMsg.write(chc.handshakeOutput);
759
chc.handshakeOutput.flush();
760
761
// What's the expected response?
762
chc.conContext.consumers.putIfAbsent(
763
ContentType.CHANGE_CIPHER_SPEC.id,
764
ChangeCipherSpec.t13Consumer);
765
chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO.id,
766
SSLHandshake.SERVER_HELLO);
767
768
// The handshake message has been delivered.
769
return null;
770
default:
771
throw new UnsupportedOperationException(
772
"Not supported yet.");
773
}
774
}
775
}
776
777
/**
778
* The "ClientHello" handshake message consumer.
779
*/
780
private static final class ClientHelloConsumer implements SSLConsumer {
781
// Prevent instantiation of this class.
782
private ClientHelloConsumer() {
783
// blank
784
}
785
786
@Override
787
public void consume(ConnectionContext context,
788
ByteBuffer message) throws IOException {
789
// The consuming happens in server side only.
790
ServerHandshakeContext shc = (ServerHandshakeContext)context;
791
792
// clean up this consumer
793
shc.handshakeConsumers.remove(SSLHandshake.CLIENT_HELLO.id);
794
if (!shc.handshakeConsumers.isEmpty()) {
795
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
796
"No more handshake message allowed " +
797
"in a ClientHello flight");
798
}
799
800
// Get enabled extension types in ClientHello handshake message.
801
SSLExtension[] enabledExtensions =
802
shc.sslConfig.getEnabledExtensions(
803
SSLHandshake.CLIENT_HELLO);
804
805
ClientHelloMessage chm =
806
new ClientHelloMessage(shc, message, enabledExtensions);
807
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
808
SSLLogger.fine("Consuming ClientHello handshake message", chm);
809
}
810
811
shc.clientHelloVersion = chm.clientVersion;
812
onClientHello(shc, chm);
813
}
814
815
private void onClientHello(ServerHandshakeContext context,
816
ClientHelloMessage clientHello) throws IOException {
817
// Negotiate protocol version.
818
//
819
// Check and launch SupportedVersions.
820
SSLExtension[] extTypes = new SSLExtension[] {
821
SSLExtension.CH_SUPPORTED_VERSIONS
822
};
823
clientHello.extensions.consumeOnLoad(context, extTypes);
824
825
ProtocolVersion negotiatedProtocol;
826
CHSupportedVersionsSpec svs =
827
(CHSupportedVersionsSpec)context.handshakeExtensions.get(
828
SSLExtension.CH_SUPPORTED_VERSIONS);
829
if (svs != null) {
830
negotiatedProtocol =
831
negotiateProtocol(context, svs.requestedProtocols);
832
} else {
833
negotiatedProtocol =
834
negotiateProtocol(context, clientHello.clientVersion);
835
}
836
context.negotiatedProtocol = negotiatedProtocol;
837
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
838
SSLLogger.fine(
839
"Negotiated protocol version: " + negotiatedProtocol.name);
840
}
841
842
// Consume the handshake message for the specific protocol version.
843
if (negotiatedProtocol.isDTLS) {
844
if (negotiatedProtocol.useTLS13PlusSpec()) {
845
d13HandshakeConsumer.consume(context, clientHello);
846
} else {
847
d12HandshakeConsumer.consume(context, clientHello);
848
}
849
} else {
850
if (negotiatedProtocol.useTLS13PlusSpec()) {
851
t13HandshakeConsumer.consume(context, clientHello);
852
} else {
853
t12HandshakeConsumer.consume(context, clientHello);
854
}
855
}
856
}
857
858
// Select a protocol version according to the
859
// ClientHello.client_version.
860
private ProtocolVersion negotiateProtocol(
861
ServerHandshakeContext context,
862
int clientHelloVersion) throws SSLException {
863
864
// Per TLS 1.3 specification, server MUST negotiate TLS 1.2 or prior
865
// even if ClientHello.client_version is 0x0304 or later.
866
int chv = clientHelloVersion;
867
if (context.sslContext.isDTLS()) {
868
if (chv < ProtocolVersion.DTLS12.id) {
869
chv = ProtocolVersion.DTLS12.id;
870
}
871
} else {
872
if (chv > ProtocolVersion.TLS12.id) {
873
chv = ProtocolVersion.TLS12.id;
874
}
875
}
876
877
// Select a protocol version from the activated protocols.
878
ProtocolVersion pv = ProtocolVersion.selectedFrom(
879
context.activeProtocols, chv);
880
if (pv == null || pv == ProtocolVersion.NONE ||
881
pv == ProtocolVersion.SSL20Hello) {
882
throw context.conContext.fatal(Alert.PROTOCOL_VERSION,
883
"Client requested protocol " +
884
ProtocolVersion.nameOf(clientHelloVersion) +
885
" is not enabled or supported in server context");
886
}
887
888
return pv;
889
}
890
891
// Select a protocol version according to the
892
// supported_versions extension.
893
private ProtocolVersion negotiateProtocol(
894
ServerHandshakeContext context,
895
int[] clientSupportedVersions) throws SSLException {
896
897
// The client supported protocol versions are present in client
898
// preference order. This implementation chooses to use the server
899
// preference of protocol versions instead.
900
for (ProtocolVersion spv : context.activeProtocols) {
901
if (spv == ProtocolVersion.SSL20Hello) {
902
continue;
903
}
904
for (int cpv : clientSupportedVersions) {
905
if (cpv == ProtocolVersion.SSL20Hello.id) {
906
continue;
907
}
908
if (spv.id == cpv) {
909
return spv;
910
}
911
}
912
}
913
914
// No protocol version can be negotiated.
915
throw context.conContext.fatal(Alert.PROTOCOL_VERSION,
916
"The client supported protocol versions " + Arrays.toString(
917
ProtocolVersion.toStringArray(clientSupportedVersions)) +
918
" are not accepted by server preferences " +
919
context.activeProtocols);
920
}
921
}
922
923
/**
924
* The "ClientHello" handshake message consumer for TLS 1.2 and
925
* prior SSL/TLS protocol versions.
926
*/
927
private static final
928
class T12ClientHelloConsumer implements HandshakeConsumer {
929
// Prevent instantiation of this class.
930
private T12ClientHelloConsumer() {
931
// blank
932
}
933
934
@Override
935
public void consume(ConnectionContext context,
936
HandshakeMessage message) throws IOException {
937
// The consuming happens in server side only.
938
ServerHandshakeContext shc = (ServerHandshakeContext)context;
939
ClientHelloMessage clientHello = (ClientHelloMessage)message;
940
941
//
942
// validate
943
//
944
945
// Reject client initiated renegotiation?
946
//
947
// If server side should reject client-initiated renegotiation,
948
// send an Alert.HANDSHAKE_FAILURE fatal alert, not a
949
// no_renegotiation warning alert (no_renegotiation must be a
950
// warning: RFC 2246). no_renegotiation might seem more
951
// natural at first, but warnings are not appropriate because
952
// the sending party does not know how the receiving party
953
// will behave. This state must be treated as a fatal server
954
// condition.
955
//
956
// This will not have any impact on server initiated renegotiation.
957
if (shc.conContext.isNegotiated) {
958
if (!shc.conContext.secureRenegotiation &&
959
!HandshakeContext.allowUnsafeRenegotiation) {
960
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
961
"Unsafe renegotiation is not allowed");
962
}
963
964
if (ServerHandshakeContext.rejectClientInitiatedRenego &&
965
!shc.kickstartMessageDelivered) {
966
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
967
"Client initiated renegotiation is not allowed");
968
}
969
}
970
971
// Consume a Session Ticket Extension if it exists
972
SSLExtension[] ext = new SSLExtension[]{
973
SSLExtension.CH_SESSION_TICKET
974
};
975
clientHello.extensions.consumeOnLoad(shc, ext);
976
977
// Does the client want to resume a session?
978
if (clientHello.sessionId.length() != 0 || shc.statelessResumption) {
979
SSLSessionContextImpl cache = (SSLSessionContextImpl)shc.sslContext
980
.engineGetServerSessionContext();
981
982
SSLSessionImpl previous;
983
// Use the stateless session ticket if provided
984
if (shc.statelessResumption) {
985
previous = shc.resumingSession;
986
} else {
987
previous = cache.get(clientHello.sessionId.getId());
988
}
989
990
boolean resumingSession =
991
(previous != null) && previous.isRejoinable();
992
if (!resumingSession) {
993
if (SSLLogger.isOn &&
994
SSLLogger.isOn("ssl,handshake,verbose")) {
995
SSLLogger.finest(
996
"Can't resume, " +
997
"the existing session is not rejoinable");
998
}
999
}
1000
// Validate the negotiated protocol version.
1001
if (resumingSession) {
1002
ProtocolVersion sessionProtocol =
1003
previous.getProtocolVersion();
1004
if (sessionProtocol != shc.negotiatedProtocol) {
1005
resumingSession = false;
1006
if (SSLLogger.isOn &&
1007
SSLLogger.isOn("ssl,handshake,verbose")) {
1008
SSLLogger.finest(
1009
"Can't resume, not the same protocol version");
1010
}
1011
}
1012
}
1013
1014
// Validate the required client authentication.
1015
if (resumingSession &&
1016
(shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) {
1017
try {
1018
previous.getPeerPrincipal();
1019
} catch (SSLPeerUnverifiedException e) {
1020
resumingSession = false;
1021
if (SSLLogger.isOn &&
1022
SSLLogger.isOn("ssl,handshake,verbose")) {
1023
SSLLogger.finest(
1024
"Can't resume, " +
1025
"client authentication is required");
1026
}
1027
}
1028
}
1029
1030
// Validate that the cached cipher suite.
1031
if (resumingSession) {
1032
CipherSuite suite = previous.getSuite();
1033
if ((!shc.isNegotiable(suite)) ||
1034
(!clientHello.cipherSuites.contains(suite))) {
1035
resumingSession = false;
1036
if (SSLLogger.isOn &&
1037
SSLLogger.isOn("ssl,handshake,verbose")) {
1038
SSLLogger.finest(
1039
"Can't resume, " +
1040
"the session cipher suite is absent");
1041
}
1042
}
1043
}
1044
1045
// ensure that the endpoint identification algorithm matches the
1046
// one in the session
1047
String identityAlg = shc.sslConfig.identificationProtocol;
1048
if (resumingSession && identityAlg != null) {
1049
String sessionIdentityAlg =
1050
previous.getIdentificationProtocol();
1051
if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) {
1052
if (SSLLogger.isOn &&
1053
SSLLogger.isOn("ssl,handshake,verbose")) {
1054
SSLLogger.finest("Can't resume, endpoint id" +
1055
" algorithm does not match, requested: " +
1056
identityAlg + ", cached: " + sessionIdentityAlg);
1057
}
1058
resumingSession = false;
1059
}
1060
}
1061
1062
// So far so good. Note that the handshake extensions may reset
1063
// the resuming options later.
1064
shc.isResumption = resumingSession;
1065
shc.resumingSession = resumingSession ? previous : null;
1066
1067
if (!resumingSession && SSLLogger.isOn &&
1068
SSLLogger.isOn("ssl,handshake")) {
1069
SSLLogger.fine("Session not resumed.");
1070
}
1071
}
1072
1073
// cache the client random number for further using
1074
shc.clientHelloRandom = clientHello.clientRandom;
1075
1076
// Check and launch ClientHello extensions.
1077
SSLExtension[] extTypes = shc.sslConfig.getExclusiveExtensions(
1078
SSLHandshake.CLIENT_HELLO,
1079
List.of(SSLExtension.CH_SESSION_TICKET));
1080
clientHello.extensions.consumeOnLoad(shc, extTypes);
1081
1082
//
1083
// update
1084
//
1085
if (!shc.conContext.isNegotiated) {
1086
shc.conContext.protocolVersion = shc.negotiatedProtocol;
1087
shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol);
1088
}
1089
1090
// update the responders
1091
//
1092
// Only need to ServerHello, which may add more responders later.
1093
// Note that ServerHello and HelloRetryRequest share the same
1094
// handshake type/id. The ServerHello producer may be replaced
1095
// by HelloRetryRequest producer if needed.
1096
shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
1097
SSLHandshake.SERVER_HELLO);
1098
1099
//
1100
// produce
1101
//
1102
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
1103
SSLHandshake.SERVER_HELLO,
1104
1105
// full handshake messages
1106
SSLHandshake.CERTIFICATE,
1107
SSLHandshake.CERTIFICATE_STATUS,
1108
SSLHandshake.SERVER_KEY_EXCHANGE,
1109
SSLHandshake.CERTIFICATE_REQUEST,
1110
SSLHandshake.SERVER_HELLO_DONE,
1111
1112
// abbreviated handshake messages
1113
SSLHandshake.FINISHED
1114
};
1115
1116
for (SSLHandshake hs : probableHandshakeMessages) {
1117
HandshakeProducer handshakeProducer =
1118
shc.handshakeProducers.remove(hs.id);
1119
if (handshakeProducer != null) {
1120
handshakeProducer.produce(context, clientHello);
1121
}
1122
}
1123
}
1124
}
1125
1126
/**
1127
* The "ClientHello" handshake message consumer for TLS 1.3.
1128
*/
1129
private static final
1130
class T13ClientHelloConsumer implements HandshakeConsumer {
1131
// Prevent instantiation of this class.
1132
private T13ClientHelloConsumer() {
1133
// blank
1134
}
1135
1136
@Override
1137
public void consume(ConnectionContext context,
1138
HandshakeMessage message) throws IOException {
1139
// The consuming happens in server side only.
1140
ServerHandshakeContext shc = (ServerHandshakeContext)context;
1141
ClientHelloMessage clientHello = (ClientHelloMessage)message;
1142
1143
// [RFC 8446] TLS 1.3 forbids renegotiation. If a server has
1144
// negotiated TLS 1.3 and receives a ClientHello at any other
1145
// time, it MUST terminate the connection with an
1146
// "unexpected_message" alert.
1147
if (shc.conContext.isNegotiated) {
1148
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
1149
"Received unexpected renegotiation handshake message");
1150
}
1151
1152
if (clientHello.clientVersion != ProtocolVersion.TLS12.id) {
1153
throw shc.conContext.fatal(Alert.PROTOCOL_VERSION,
1154
"The ClientHello.legacy_version field is not TLS 1.2");
1155
}
1156
1157
// The client may send a dummy change_cipher_spec record
1158
// immediately after the first ClientHello.
1159
shc.conContext.consumers.putIfAbsent(
1160
ContentType.CHANGE_CIPHER_SPEC.id,
1161
ChangeCipherSpec.t13Consumer);
1162
1163
// Is it a resumption?
1164
//
1165
// Check and launch the "psk_key_exchange_modes" and
1166
// "pre_shared_key" extensions first, which will reset the
1167
// resuming session, no matter the extensions present or not.
1168
shc.isResumption = true;
1169
SSLExtension[] extTypes = new SSLExtension[] {
1170
SSLExtension.PSK_KEY_EXCHANGE_MODES,
1171
SSLExtension.CH_PRE_SHARED_KEY
1172
};
1173
clientHello.extensions.consumeOnLoad(shc, extTypes);
1174
1175
// Check and launch ClientHello extensions other than
1176
// "psk_key_exchange_modes", "pre_shared_key", "protocol_version"
1177
// and "key_share" extensions.
1178
//
1179
// These extensions may discard session resumption, or ask for
1180
// hello retry.
1181
extTypes = shc.sslConfig.getExclusiveExtensions(
1182
SSLHandshake.CLIENT_HELLO,
1183
Arrays.asList(
1184
SSLExtension.PSK_KEY_EXCHANGE_MODES,
1185
SSLExtension.CH_PRE_SHARED_KEY,
1186
SSLExtension.CH_SUPPORTED_VERSIONS));
1187
clientHello.extensions.consumeOnLoad(shc, extTypes);
1188
1189
if (!shc.handshakeProducers.isEmpty()) {
1190
// Should be HelloRetryRequest producer.
1191
goHelloRetryRequest(shc, clientHello);
1192
} else {
1193
goServerHello(shc, clientHello);
1194
}
1195
}
1196
1197
private void goHelloRetryRequest(ServerHandshakeContext shc,
1198
ClientHelloMessage clientHello) throws IOException {
1199
HandshakeProducer handshakeProducer =
1200
shc.handshakeProducers.remove(
1201
SSLHandshake.HELLO_RETRY_REQUEST.id);
1202
if (handshakeProducer != null) {
1203
handshakeProducer.produce(shc, clientHello);
1204
} else {
1205
// unlikely
1206
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1207
"No HelloRetryRequest producer: " + shc.handshakeProducers);
1208
}
1209
1210
if (!shc.handshakeProducers.isEmpty()) {
1211
// unlikely, but please double check.
1212
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1213
"unknown handshake producers: " + shc.handshakeProducers);
1214
}
1215
}
1216
1217
private void goServerHello(ServerHandshakeContext shc,
1218
ClientHelloMessage clientHello) throws IOException {
1219
//
1220
// validate
1221
//
1222
shc.clientHelloRandom = clientHello.clientRandom;
1223
1224
//
1225
// update
1226
//
1227
if (!shc.conContext.isNegotiated) {
1228
shc.conContext.protocolVersion = shc.negotiatedProtocol;
1229
shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol);
1230
}
1231
1232
// update the responders
1233
//
1234
// Only ServerHello/HelloRetryRequest producer, which adds
1235
// more responders later.
1236
shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
1237
SSLHandshake.SERVER_HELLO);
1238
1239
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
1240
SSLHandshake.SERVER_HELLO,
1241
1242
// full handshake messages
1243
SSLHandshake.ENCRYPTED_EXTENSIONS,
1244
SSLHandshake.CERTIFICATE_REQUEST,
1245
SSLHandshake.CERTIFICATE,
1246
SSLHandshake.CERTIFICATE_VERIFY,
1247
SSLHandshake.FINISHED
1248
};
1249
1250
//
1251
// produce
1252
//
1253
for (SSLHandshake hs : probableHandshakeMessages) {
1254
HandshakeProducer handshakeProducer =
1255
shc.handshakeProducers.remove(hs.id);
1256
if (handshakeProducer != null) {
1257
handshakeProducer.produce(shc, clientHello);
1258
}
1259
}
1260
}
1261
}
1262
1263
/**
1264
* The "ClientHello" handshake message consumer for DTLS 1.2 and
1265
* previous DTLS protocol versions.
1266
*/
1267
private static final
1268
class D12ClientHelloConsumer implements HandshakeConsumer {
1269
// Prevent instantiation of this class.
1270
private D12ClientHelloConsumer() {
1271
// blank
1272
}
1273
1274
@Override
1275
public void consume(ConnectionContext context,
1276
HandshakeMessage message) throws IOException {
1277
// The consuming happens in server side only.
1278
ServerHandshakeContext shc = (ServerHandshakeContext)context;
1279
ClientHelloMessage clientHello = (ClientHelloMessage)message;
1280
1281
//
1282
// validate
1283
//
1284
1285
// Reject client initiated renegotiation?
1286
//
1287
// If server side should reject client-initiated renegotiation,
1288
// send an Alert.HANDSHAKE_FAILURE fatal alert, not a
1289
// no_renegotiation warning alert (no_renegotiation must be a
1290
// warning: RFC 2246). no_renegotiation might seem more
1291
// natural at first, but warnings are not appropriate because
1292
// the sending party does not know how the receiving party
1293
// will behave. This state must be treated as a fatal server
1294
// condition.
1295
//
1296
// This will not have any impact on server initiated renegotiation.
1297
if (shc.conContext.isNegotiated) {
1298
if (!shc.conContext.secureRenegotiation &&
1299
!HandshakeContext.allowUnsafeRenegotiation) {
1300
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1301
"Unsafe renegotiation is not allowed");
1302
}
1303
1304
if (ServerHandshakeContext.rejectClientInitiatedRenego &&
1305
!shc.kickstartMessageDelivered) {
1306
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
1307
"Client initiated renegotiation is not allowed");
1308
}
1309
}
1310
1311
1312
// Does the client want to resume a session?
1313
if (clientHello.sessionId.length() != 0) {
1314
SSLSessionContextImpl cache = (SSLSessionContextImpl)shc.sslContext
1315
.engineGetServerSessionContext();
1316
1317
// Consume a Session Ticket Extension if it exists
1318
SSLExtension[] ext = new SSLExtension[]{
1319
SSLExtension.CH_SESSION_TICKET
1320
};
1321
clientHello.extensions.consumeOnLoad(shc, ext);
1322
1323
SSLSessionImpl previous;
1324
// Use stateless session ticket if provided.
1325
if (shc.statelessResumption) {
1326
previous = shc.resumingSession;
1327
} else {
1328
previous = cache.get(clientHello.sessionId.getId());
1329
}
1330
1331
boolean resumingSession =
1332
(previous != null) && previous.isRejoinable();
1333
if (!resumingSession) {
1334
if (SSLLogger.isOn &&
1335
SSLLogger.isOn("ssl,handshake,verbose")) {
1336
SSLLogger.finest(
1337
"Can't resume, " +
1338
"the existing session is not rejoinable");
1339
}
1340
}
1341
// Validate the negotiated protocol version.
1342
if (resumingSession) {
1343
ProtocolVersion sessionProtocol =
1344
previous.getProtocolVersion();
1345
if (sessionProtocol != shc.negotiatedProtocol) {
1346
resumingSession = false;
1347
if (SSLLogger.isOn &&
1348
SSLLogger.isOn("ssl,handshake,verbose")) {
1349
SSLLogger.finest(
1350
"Can't resume, not the same protocol version");
1351
}
1352
}
1353
}
1354
1355
// Validate the required client authentication.
1356
if (resumingSession &&
1357
(shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) {
1358
1359
try {
1360
previous.getPeerPrincipal();
1361
} catch (SSLPeerUnverifiedException e) {
1362
resumingSession = false;
1363
if (SSLLogger.isOn &&
1364
SSLLogger.isOn("ssl,handshake,verbose")) {
1365
SSLLogger.finest(
1366
"Can't resume, " +
1367
"client authentication is required");
1368
}
1369
}
1370
}
1371
1372
// Validate that the cached cipher suite.
1373
if (resumingSession) {
1374
CipherSuite suite = previous.getSuite();
1375
if ((!shc.isNegotiable(suite)) ||
1376
(!clientHello.cipherSuites.contains(suite))) {
1377
resumingSession = false;
1378
if (SSLLogger.isOn &&
1379
SSLLogger.isOn("ssl,handshake,verbose")) {
1380
SSLLogger.finest(
1381
"Can't resume, " +
1382
"the session cipher suite is absent");
1383
}
1384
}
1385
}
1386
1387
// So far so good. Note that the handshake extensions may reset
1388
// the resuming options later.
1389
shc.isResumption = resumingSession;
1390
shc.resumingSession = resumingSession ? previous : null;
1391
}
1392
1393
HelloCookieManager hcm =
1394
shc.sslContext.getHelloCookieManager(ProtocolVersion.DTLS10);
1395
if (!shc.isResumption &&
1396
!hcm.isCookieValid(shc, clientHello, clientHello.cookie)) {
1397
//
1398
// Perform cookie exchange for DTLS handshaking if no cookie
1399
// or the cookie is invalid in the ClientHello message.
1400
//
1401
// update the responders
1402
shc.handshakeProducers.put(
1403
SSLHandshake.HELLO_VERIFY_REQUEST.id,
1404
SSLHandshake.HELLO_VERIFY_REQUEST);
1405
1406
//
1407
// produce response handshake message
1408
//
1409
SSLHandshake.HELLO_VERIFY_REQUEST.produce(context, clientHello);
1410
1411
return;
1412
}
1413
1414
// cache the client random number for further using
1415
shc.clientHelloRandom = clientHello.clientRandom;
1416
1417
// Check and launch ClientHello extensions.
1418
SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions(
1419
SSLHandshake.CLIENT_HELLO);
1420
clientHello.extensions.consumeOnLoad(shc, extTypes);
1421
1422
//
1423
// update
1424
//
1425
if (!shc.conContext.isNegotiated) {
1426
shc.conContext.protocolVersion = shc.negotiatedProtocol;
1427
shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol);
1428
}
1429
1430
// update the responders
1431
//
1432
// Only need to ServerHello, which may add more responders later.
1433
shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id,
1434
SSLHandshake.SERVER_HELLO);
1435
1436
//
1437
// produce
1438
//
1439
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
1440
SSLHandshake.SERVER_HELLO,
1441
1442
// full handshake messages
1443
SSLHandshake.CERTIFICATE,
1444
SSLHandshake.CERTIFICATE_STATUS,
1445
SSLHandshake.SERVER_KEY_EXCHANGE,
1446
SSLHandshake.CERTIFICATE_REQUEST,
1447
SSLHandshake.SERVER_HELLO_DONE,
1448
1449
// abbreviated handshake messages
1450
SSLHandshake.FINISHED
1451
};
1452
1453
for (SSLHandshake hs : probableHandshakeMessages) {
1454
HandshakeProducer handshakeProducer =
1455
shc.handshakeProducers.remove(hs.id);
1456
if (handshakeProducer != null) {
1457
handshakeProducer.produce(context, clientHello);
1458
}
1459
}
1460
}
1461
}
1462
1463
/**
1464
* The "ClientHello" handshake message consumer for DTLS 1.3.
1465
*/
1466
private static final
1467
class D13ClientHelloConsumer implements HandshakeConsumer {
1468
// Prevent instantiation of this class.
1469
private D13ClientHelloConsumer() {
1470
// blank
1471
}
1472
1473
@Override
1474
public void consume(ConnectionContext context,
1475
HandshakeMessage message) throws IOException {
1476
throw new UnsupportedOperationException("Not supported yet.");
1477
}
1478
}
1479
}
1480
1481