Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/ssl/Finished.java
38830 views
1
/*
2
* Copyright (c) 2015, 2018, 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.GeneralSecurityException;
31
import java.security.InvalidKeyException;
32
import java.security.MessageDigest;
33
import java.security.NoSuchAlgorithmException;
34
import java.security.ProviderException;
35
import java.security.spec.AlgorithmParameterSpec;
36
import java.text.MessageFormat;
37
import java.util.Locale;
38
import javax.crypto.KeyGenerator;
39
import javax.crypto.Mac;
40
import javax.crypto.SecretKey;
41
import javax.crypto.spec.IvParameterSpec;
42
import javax.crypto.spec.SecretKeySpec;
43
44
import sun.security.internal.spec.TlsPrfParameterSpec;
45
import sun.security.ssl.CipherSuite.HashAlg;
46
import static sun.security.ssl.CipherSuite.HashAlg.H_NONE;
47
import sun.security.ssl.SSLBasicKeyDerivation.SecretSizeSpec;
48
import sun.security.ssl.SSLCipher.SSLReadCipher;
49
import sun.security.ssl.SSLCipher.SSLWriteCipher;
50
import sun.security.ssl.SSLHandshake.HandshakeMessage;
51
import sun.misc.HexDumpEncoder;
52
53
/**
54
* Pack of the Finished handshake message.
55
*/
56
final class Finished {
57
static final SSLConsumer t12HandshakeConsumer =
58
new T12FinishedConsumer();
59
static final HandshakeProducer t12HandshakeProducer =
60
new T12FinishedProducer();
61
62
static final SSLConsumer t13HandshakeConsumer =
63
new T13FinishedConsumer();
64
static final HandshakeProducer t13HandshakeProducer =
65
new T13FinishedProducer();
66
67
/**
68
* The Finished handshake message.
69
*/
70
private static final class FinishedMessage extends HandshakeMessage {
71
private final byte[] verifyData;
72
73
FinishedMessage(HandshakeContext context) throws IOException {
74
super(context);
75
76
VerifyDataScheme vds =
77
VerifyDataScheme.valueOf(context.negotiatedProtocol);
78
79
byte[] vd = null;
80
try {
81
vd = vds.createVerifyData(context, false);
82
} catch (IOException ioe) {
83
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
84
"Failed to generate verify_data", ioe);
85
}
86
87
this.verifyData = vd;
88
}
89
90
FinishedMessage(HandshakeContext context,
91
ByteBuffer m) throws IOException {
92
super(context);
93
int verifyDataLen = 12;
94
if (context.negotiatedProtocol == ProtocolVersion.SSL30) {
95
verifyDataLen = 36;
96
} else if (context.negotiatedProtocol.useTLS13PlusSpec()) {
97
verifyDataLen =
98
context.negotiatedCipherSuite.hashAlg.hashLength;
99
}
100
101
if (m.remaining() != verifyDataLen) {
102
throw context.conContext.fatal(Alert.DECODE_ERROR,
103
"Inappropriate finished message: need " + verifyDataLen +
104
" but remaining " + m.remaining() + " bytes verify_data");
105
}
106
107
this.verifyData = new byte[verifyDataLen];
108
m.get(verifyData);
109
110
VerifyDataScheme vd =
111
VerifyDataScheme.valueOf(context.negotiatedProtocol);
112
byte[] myVerifyData;
113
try {
114
myVerifyData = vd.createVerifyData(context, true);
115
} catch (IOException ioe) {
116
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
117
"Failed to generate verify_data", ioe);
118
}
119
if (!MessageDigest.isEqual(myVerifyData, verifyData)) {
120
throw context.conContext.fatal(Alert.DECRYPT_ERROR,
121
"The Finished message cannot be verified.");
122
}
123
}
124
125
@Override
126
public SSLHandshake handshakeType() {
127
return SSLHandshake.FINISHED;
128
}
129
130
@Override
131
public int messageLength() {
132
return verifyData.length;
133
}
134
135
@Override
136
public void send(HandshakeOutStream hos) throws IOException {
137
hos.write(verifyData);
138
}
139
140
@Override
141
public String toString() {
142
MessageFormat messageFormat = new MessageFormat(
143
"\"Finished\": '{'\n" +
144
" \"verify data\": '{'\n" +
145
"{0}\n" +
146
" '}'" +
147
"'}'",
148
Locale.ENGLISH);
149
150
HexDumpEncoder hexEncoder = new HexDumpEncoder();
151
Object[] messageFields = {
152
Utilities.indent(hexEncoder.encode(verifyData), " "),
153
};
154
return messageFormat.format(messageFields);
155
}
156
}
157
158
interface VerifyDataGenerator {
159
byte[] createVerifyData(HandshakeContext context,
160
boolean isValidation) throws IOException;
161
}
162
163
enum VerifyDataScheme {
164
SSL30 ("kdf_ssl30", new S30VerifyDataGenerator()),
165
TLS10 ("kdf_tls10", new T10VerifyDataGenerator()),
166
TLS12 ("kdf_tls12", new T12VerifyDataGenerator()),
167
TLS13 ("kdf_tls13", new T13VerifyDataGenerator());
168
169
final String name;
170
final VerifyDataGenerator generator;
171
172
VerifyDataScheme(String name, VerifyDataGenerator verifyDataGenerator) {
173
this.name = name;
174
this.generator = verifyDataGenerator;
175
}
176
177
static VerifyDataScheme valueOf(ProtocolVersion protocolVersion) {
178
switch (protocolVersion) {
179
case SSL30:
180
return VerifyDataScheme.SSL30;
181
case TLS10:
182
case TLS11:
183
return VerifyDataScheme.TLS10;
184
case TLS12:
185
return VerifyDataScheme.TLS12;
186
case TLS13:
187
return VerifyDataScheme.TLS13;
188
default:
189
return null;
190
}
191
}
192
193
public byte[] createVerifyData(HandshakeContext context,
194
boolean isValidation) throws IOException {
195
if (generator != null) {
196
return generator.createVerifyData(context, isValidation);
197
}
198
199
throw new UnsupportedOperationException("Not supported yet.");
200
}
201
}
202
203
// SSL 3.0
204
private static final
205
class S30VerifyDataGenerator implements VerifyDataGenerator {
206
@Override
207
public byte[] createVerifyData(HandshakeContext context,
208
boolean isValidation) throws IOException {
209
HandshakeHash handshakeHash = context.handshakeHash;
210
SecretKey masterSecretKey =
211
context.handshakeSession.getMasterSecret();
212
213
boolean useClientLabel =
214
(context.sslConfig.isClientMode && !isValidation) ||
215
(!context.sslConfig.isClientMode && isValidation);
216
return handshakeHash.digest(useClientLabel, masterSecretKey);
217
}
218
}
219
220
// TLS 1.0, TLS 1.1
221
private static final
222
class T10VerifyDataGenerator implements VerifyDataGenerator {
223
@Override
224
public byte[] createVerifyData(HandshakeContext context,
225
boolean isValidation) throws IOException {
226
HandshakeHash handshakeHash = context.handshakeHash;
227
SecretKey masterSecretKey =
228
context.handshakeSession.getMasterSecret();
229
230
boolean useClientLabel =
231
(context.sslConfig.isClientMode && !isValidation) ||
232
(!context.sslConfig.isClientMode && isValidation);
233
String tlsLabel;
234
if (useClientLabel) {
235
tlsLabel = "client finished";
236
} else {
237
tlsLabel = "server finished";
238
}
239
240
try {
241
byte[] seed = handshakeHash.digest();
242
String prfAlg = "SunTlsPrf";
243
HashAlg hashAlg = H_NONE;
244
245
/*
246
* RFC 5246/7.4.9 says that finished messages can
247
* be ciphersuite-specific in both length/PRF hash
248
* algorithm. If we ever run across a different
249
* length, this call will need to be updated.
250
*/
251
@SuppressWarnings("deprecation")
252
TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
253
masterSecretKey, tlsLabel, seed, 12,
254
hashAlg.name, hashAlg.hashLength, hashAlg.blockSize);
255
KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
256
kg.init(spec);
257
SecretKey prfKey = kg.generateKey();
258
if (!"RAW".equals(prfKey.getFormat())) {
259
throw new ProviderException(
260
"Invalid PRF output, format must be RAW. " +
261
"Format received: " + prfKey.getFormat());
262
}
263
byte[] finished = prfKey.getEncoded();
264
return finished;
265
} catch (GeneralSecurityException e) {
266
throw new RuntimeException("PRF failed", e);
267
}
268
}
269
}
270
271
// TLS 1.2
272
private static final
273
class T12VerifyDataGenerator implements VerifyDataGenerator {
274
@Override
275
public byte[] createVerifyData(HandshakeContext context,
276
boolean isValidation) throws IOException {
277
CipherSuite cipherSuite = context.negotiatedCipherSuite;
278
HandshakeHash handshakeHash = context.handshakeHash;
279
SecretKey masterSecretKey =
280
context.handshakeSession.getMasterSecret();
281
282
boolean useClientLabel =
283
(context.sslConfig.isClientMode && !isValidation) ||
284
(!context.sslConfig.isClientMode && isValidation);
285
String tlsLabel;
286
if (useClientLabel) {
287
tlsLabel = "client finished";
288
} else {
289
tlsLabel = "server finished";
290
}
291
292
try {
293
byte[] seed = handshakeHash.digest();
294
String prfAlg = "SunTls12Prf";
295
HashAlg hashAlg = cipherSuite.hashAlg;
296
297
/*
298
* RFC 5246/7.4.9 says that finished messages can
299
* be ciphersuite-specific in both length/PRF hash
300
* algorithm. If we ever run across a different
301
* length, this call will need to be updated.
302
*/
303
@SuppressWarnings("deprecation")
304
TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
305
masterSecretKey, tlsLabel, seed, 12,
306
hashAlg.name, hashAlg.hashLength, hashAlg.blockSize);
307
KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
308
kg.init(spec);
309
SecretKey prfKey = kg.generateKey();
310
if (!"RAW".equals(prfKey.getFormat())) {
311
throw new ProviderException(
312
"Invalid PRF output, format must be RAW. " +
313
"Format received: " + prfKey.getFormat());
314
}
315
byte[] finished = prfKey.getEncoded();
316
return finished;
317
} catch (GeneralSecurityException e) {
318
throw new RuntimeException("PRF failed", e);
319
}
320
}
321
}
322
323
// TLS 1.2
324
private static final
325
class T13VerifyDataGenerator implements VerifyDataGenerator {
326
private static final byte[] hkdfLabel = "tls13 finished".getBytes();
327
private static final byte[] hkdfContext = new byte[0];
328
329
@Override
330
public byte[] createVerifyData(HandshakeContext context,
331
boolean isValidation) throws IOException {
332
// create finished secret key
333
HashAlg hashAlg =
334
context.negotiatedCipherSuite.hashAlg;
335
SecretKey secret = isValidation ?
336
context.baseReadSecret : context.baseWriteSecret;
337
SSLBasicKeyDerivation kdf = new SSLBasicKeyDerivation(
338
secret, hashAlg.name,
339
hkdfLabel, hkdfContext, hashAlg.hashLength);
340
AlgorithmParameterSpec keySpec =
341
new SecretSizeSpec(hashAlg.hashLength);
342
SecretKey finishedSecret =
343
kdf.deriveKey("TlsFinishedSecret", keySpec);
344
345
String hmacAlg =
346
"Hmac" + hashAlg.name.replace("-", "");
347
try {
348
Mac hmac = JsseJce.getMac(hmacAlg);
349
hmac.init(finishedSecret);
350
return hmac.doFinal(context.handshakeHash.digest());
351
} catch (NoSuchAlgorithmException |InvalidKeyException ex) {
352
throw new ProviderException(
353
"Failed to generate verify_data", ex);
354
}
355
}
356
}
357
358
/**
359
* The "Finished" handshake message producer.
360
*/
361
private static final
362
class T12FinishedProducer implements HandshakeProducer {
363
// Prevent instantiation of this class.
364
private T12FinishedProducer() {
365
// blank
366
}
367
368
@Override
369
public byte[] produce(ConnectionContext context,
370
HandshakeMessage message) throws IOException {
371
// The consuming happens in handshake context only.
372
HandshakeContext hc = (HandshakeContext)context;
373
if (hc.sslConfig.isClientMode) {
374
return onProduceFinished(
375
(ClientHandshakeContext)context, message);
376
} else {
377
return onProduceFinished(
378
(ServerHandshakeContext)context, message);
379
}
380
}
381
382
private byte[] onProduceFinished(ClientHandshakeContext chc,
383
HandshakeMessage message) throws IOException {
384
// Refresh handshake hash
385
chc.handshakeHash.update();
386
387
FinishedMessage fm = new FinishedMessage(chc);
388
389
// Change write cipher and delivery ChangeCipherSpec message.
390
ChangeCipherSpec.t10Producer.produce(chc, message);
391
392
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
393
SSLLogger.fine(
394
"Produced client Finished handshake message", fm);
395
}
396
397
// Output the handshake message.
398
fm.write(chc.handshakeOutput);
399
chc.handshakeOutput.flush();
400
401
/*
402
* save server verify data for secure renegotiation
403
*/
404
if (chc.conContext.secureRenegotiation) {
405
chc.conContext.clientVerifyData = fm.verifyData;
406
}
407
408
// update the consumers and producers
409
if (!chc.isResumption) {
410
chc.conContext.consumers.put(ContentType.CHANGE_CIPHER_SPEC.id,
411
ChangeCipherSpec.t10Consumer);
412
chc.handshakeConsumers.put(
413
SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
414
} else {
415
if (chc.handshakeSession.isRejoinable()) {
416
((SSLSessionContextImpl)chc.sslContext.
417
engineGetClientSessionContext()).put(
418
chc.handshakeSession);
419
}
420
chc.conContext.conSession = chc.handshakeSession.finish();
421
chc.conContext.protocolVersion = chc.negotiatedProtocol;
422
423
// handshake context cleanup.
424
chc.handshakeFinished = true;
425
426
chc.conContext.finishHandshake();
427
}
428
429
// The handshake message has been delivered.
430
return null;
431
}
432
433
private byte[] onProduceFinished(ServerHandshakeContext shc,
434
HandshakeMessage message) throws IOException {
435
// Refresh handshake hash
436
shc.handshakeHash.update();
437
438
FinishedMessage fm = new FinishedMessage(shc);
439
440
// Change write cipher and delivery ChangeCipherSpec message.
441
ChangeCipherSpec.t10Producer.produce(shc, message);
442
443
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
444
SSLLogger.fine(
445
"Produced server Finished handshake message", fm);
446
}
447
448
// Output the handshake message.
449
fm.write(shc.handshakeOutput);
450
shc.handshakeOutput.flush();
451
452
/*
453
* save client verify data for secure renegotiation
454
*/
455
if (shc.conContext.secureRenegotiation) {
456
shc.conContext.serverVerifyData = fm.verifyData;
457
}
458
459
// update the consumers and producers
460
if (shc.isResumption) {
461
shc.conContext.consumers.put(ContentType.CHANGE_CIPHER_SPEC.id,
462
ChangeCipherSpec.t10Consumer);
463
shc.handshakeConsumers.put(
464
SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
465
} else {
466
if (shc.handshakeSession.isRejoinable()) {
467
((SSLSessionContextImpl)shc.sslContext.
468
engineGetServerSessionContext()).put(
469
shc.handshakeSession);
470
}
471
shc.conContext.conSession = shc.handshakeSession.finish();
472
shc.conContext.protocolVersion = shc.negotiatedProtocol;
473
474
// handshake context cleanup.
475
shc.handshakeFinished = true;
476
477
shc.conContext.finishHandshake();
478
}
479
480
// The handshake message has been delivered.
481
return null;
482
}
483
}
484
485
/**
486
* The "Finished" handshake message consumer.
487
*/
488
private static final class T12FinishedConsumer implements SSLConsumer {
489
// Prevent instantiation of this class.
490
private T12FinishedConsumer() {
491
// blank
492
}
493
494
@Override
495
public void consume(ConnectionContext context,
496
ByteBuffer message) throws IOException {
497
// The consuming happens in handshake context only.
498
HandshakeContext hc = (HandshakeContext)context;
499
500
// This consumer can be used only once.
501
hc.handshakeConsumers.remove(SSLHandshake.FINISHED.id);
502
503
// We should not be processing finished messages unless
504
// we have received ChangeCipherSpec
505
if (hc.conContext.consumers.containsKey(
506
ContentType.CHANGE_CIPHER_SPEC.id)) {
507
throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
508
"Missing ChangeCipherSpec message");
509
}
510
511
if (hc.sslConfig.isClientMode) {
512
onConsumeFinished((ClientHandshakeContext)context, message);
513
} else {
514
onConsumeFinished((ServerHandshakeContext)context, message);
515
}
516
}
517
518
private void onConsumeFinished(ClientHandshakeContext chc,
519
ByteBuffer message) throws IOException {
520
FinishedMessage fm = new FinishedMessage(chc, message);
521
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
522
SSLLogger.fine(
523
"Consuming server Finished handshake message", fm);
524
}
525
526
if (chc.conContext.secureRenegotiation) {
527
chc.conContext.serverVerifyData = fm.verifyData;
528
}
529
530
if (!chc.isResumption) {
531
if (chc.handshakeSession.isRejoinable()) {
532
((SSLSessionContextImpl)chc.sslContext.
533
engineGetClientSessionContext()).put(
534
chc.handshakeSession);
535
}
536
chc.conContext.conSession = chc.handshakeSession.finish();
537
chc.conContext.protocolVersion = chc.negotiatedProtocol;
538
539
// handshake context cleanup.
540
chc.handshakeFinished = true;
541
542
chc.conContext.finishHandshake();
543
} else {
544
chc.handshakeProducers.put(SSLHandshake.FINISHED.id,
545
SSLHandshake.FINISHED);
546
}
547
548
//
549
// produce
550
//
551
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
552
SSLHandshake.FINISHED
553
};
554
555
for (SSLHandshake hs : probableHandshakeMessages) {
556
HandshakeProducer handshakeProducer =
557
chc.handshakeProducers.remove(hs.id);
558
if (handshakeProducer != null) {
559
handshakeProducer.produce(chc, fm);
560
}
561
}
562
}
563
564
private void onConsumeFinished(ServerHandshakeContext shc,
565
ByteBuffer message) throws IOException {
566
// Make sure that any expected CertificateVerify message
567
// has been received and processed.
568
if (!shc.isResumption) {
569
if (shc.handshakeConsumers.containsKey(
570
SSLHandshake.CERTIFICATE_VERIFY.id)) {
571
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
572
"Unexpected Finished handshake message");
573
}
574
}
575
576
FinishedMessage fm = new FinishedMessage(shc, message);
577
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
578
SSLLogger.fine(
579
"Consuming client Finished handshake message", fm);
580
}
581
582
if (shc.conContext.secureRenegotiation) {
583
shc.conContext.clientVerifyData = fm.verifyData;
584
}
585
586
if (shc.isResumption) {
587
if (shc.handshakeSession.isRejoinable()) {
588
((SSLSessionContextImpl)shc.sslContext.
589
engineGetServerSessionContext()).put(
590
shc.handshakeSession);
591
}
592
shc.conContext.conSession = shc.handshakeSession.finish();
593
shc.conContext.protocolVersion = shc.negotiatedProtocol;
594
595
// handshake context cleanup.
596
shc.handshakeFinished = true;
597
598
shc.conContext.finishHandshake();
599
} else {
600
shc.handshakeProducers.put(SSLHandshake.FINISHED.id,
601
SSLHandshake.FINISHED);
602
}
603
604
//
605
// produce
606
//
607
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
608
SSLHandshake.FINISHED
609
};
610
611
for (SSLHandshake hs : probableHandshakeMessages) {
612
HandshakeProducer handshakeProducer =
613
shc.handshakeProducers.remove(hs.id);
614
if (handshakeProducer != null) {
615
handshakeProducer.produce(shc, fm);
616
}
617
}
618
}
619
}
620
621
/**
622
* The "Finished" handshake message producer.
623
*/
624
private static final
625
class T13FinishedProducer implements HandshakeProducer {
626
// Prevent instantiation of this class.
627
private T13FinishedProducer() {
628
// blank
629
}
630
631
@Override
632
public byte[] produce(ConnectionContext context,
633
HandshakeMessage message) throws IOException {
634
// The consuming happens in handshake context only.
635
HandshakeContext hc = (HandshakeContext)context;
636
if (hc.sslConfig.isClientMode) {
637
return onProduceFinished(
638
(ClientHandshakeContext)context, message);
639
} else {
640
return onProduceFinished(
641
(ServerHandshakeContext)context, message);
642
}
643
}
644
645
private byte[] onProduceFinished(ClientHandshakeContext chc,
646
HandshakeMessage message) throws IOException {
647
// Refresh handshake hash
648
chc.handshakeHash.update();
649
650
FinishedMessage fm = new FinishedMessage(chc);
651
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
652
SSLLogger.fine(
653
"Produced client Finished handshake message", fm);
654
}
655
656
// Output the handshake message.
657
fm.write(chc.handshakeOutput);
658
chc.handshakeOutput.flush();
659
660
// save server verify data for secure renegotiation
661
if (chc.conContext.secureRenegotiation) {
662
chc.conContext.clientVerifyData = fm.verifyData;
663
}
664
665
// update the context
666
// Change client/server application traffic secrets.
667
SSLKeyDerivation kd = chc.handshakeKeyDerivation;
668
if (kd == null) {
669
// unlikely
670
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
671
"no key derivation");
672
}
673
674
SSLTrafficKeyDerivation kdg =
675
SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
676
if (kdg == null) {
677
// unlikely
678
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
679
"Not supported key derivation: " +
680
chc.negotiatedProtocol);
681
}
682
683
try {
684
// update the application traffic read keys.
685
SecretKey writeSecret = kd.deriveKey(
686
"TlsClientAppTrafficSecret", null);
687
688
SSLKeyDerivation writeKD =
689
kdg.createKeyDerivation(chc, writeSecret);
690
SecretKey writeKey = writeKD.deriveKey(
691
"TlsKey", null);
692
SecretKey writeIvSecret = writeKD.deriveKey(
693
"TlsIv", null);
694
IvParameterSpec writeIv =
695
new IvParameterSpec(writeIvSecret.getEncoded());
696
SSLWriteCipher writeCipher =
697
chc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
698
Authenticator.valueOf(chc.negotiatedProtocol),
699
chc.negotiatedProtocol, writeKey, writeIv,
700
chc.sslContext.getSecureRandom());
701
702
if (writeCipher == null) {
703
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
704
"Illegal cipher suite (" + chc.negotiatedCipherSuite +
705
") and protocol version (" + chc.negotiatedProtocol +
706
")");
707
}
708
709
chc.baseWriteSecret = writeSecret;
710
chc.conContext.outputRecord.changeWriteCiphers(
711
writeCipher, false);
712
713
} catch (GeneralSecurityException gse) {
714
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
715
"Failure to derive application secrets", gse);
716
}
717
718
// The resumption master secret is stored in the session so
719
// it can be used after the handshake is completed.
720
SSLSecretDerivation sd = ((SSLSecretDerivation) kd).forContext(chc);
721
SecretKey resumptionMasterSecret = sd.deriveKey(
722
"TlsResumptionMasterSecret", null);
723
chc.handshakeSession.setResumptionMasterSecret(
724
resumptionMasterSecret);
725
726
chc.conContext.conSession = chc.handshakeSession.finish();
727
chc.conContext.protocolVersion = chc.negotiatedProtocol;
728
729
// handshake context cleanup.
730
chc.handshakeFinished = true;
731
chc.conContext.finishHandshake();
732
733
734
// The handshake message has been delivered.
735
return null;
736
}
737
738
private byte[] onProduceFinished(ServerHandshakeContext shc,
739
HandshakeMessage message) throws IOException {
740
// Refresh handshake hash
741
shc.handshakeHash.update();
742
743
FinishedMessage fm = new FinishedMessage(shc);
744
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
745
SSLLogger.fine(
746
"Produced server Finished handshake message", fm);
747
}
748
749
// Output the handshake message.
750
fm.write(shc.handshakeOutput);
751
shc.handshakeOutput.flush();
752
753
// Change client/server application traffic secrets.
754
SSLKeyDerivation kd = shc.handshakeKeyDerivation;
755
if (kd == null) {
756
// unlikely
757
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
758
"no key derivation");
759
}
760
761
SSLTrafficKeyDerivation kdg =
762
SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
763
if (kdg == null) {
764
// unlikely
765
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
766
"Not supported key derivation: " +
767
shc.negotiatedProtocol);
768
}
769
770
// derive salt secret
771
try {
772
SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
773
774
// derive application secrets
775
HashAlg hashAlg = shc.negotiatedCipherSuite.hashAlg;
776
HKDF hkdf = new HKDF(hashAlg.name);
777
byte[] zeros = new byte[hashAlg.hashLength];
778
SecretKeySpec sharedSecret =
779
new SecretKeySpec(zeros, "TlsZeroSecret");
780
SecretKey masterSecret =
781
hkdf.extract(saltSecret, sharedSecret, "TlsMasterSecret");
782
783
SSLKeyDerivation secretKD =
784
new SSLSecretDerivation(shc, masterSecret);
785
786
// update the handshake traffic write keys.
787
SecretKey writeSecret = secretKD.deriveKey(
788
"TlsServerAppTrafficSecret", null);
789
SSLKeyDerivation writeKD =
790
kdg.createKeyDerivation(shc, writeSecret);
791
SecretKey writeKey = writeKD.deriveKey(
792
"TlsKey", null);
793
SecretKey writeIvSecret = writeKD.deriveKey(
794
"TlsIv", null);
795
IvParameterSpec writeIv =
796
new IvParameterSpec(writeIvSecret.getEncoded());
797
SSLWriteCipher writeCipher =
798
shc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
799
Authenticator.valueOf(shc.negotiatedProtocol),
800
shc.negotiatedProtocol, writeKey, writeIv,
801
shc.sslContext.getSecureRandom());
802
803
if (writeCipher == null) {
804
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
805
"Illegal cipher suite (" + shc.negotiatedCipherSuite +
806
") and protocol version (" + shc.negotiatedProtocol +
807
")");
808
}
809
810
shc.baseWriteSecret = writeSecret;
811
shc.conContext.outputRecord.changeWriteCiphers(
812
writeCipher, false);
813
814
// update the context for the following key derivation
815
shc.handshakeKeyDerivation = secretKD;
816
} catch (GeneralSecurityException gse) {
817
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
818
"Failure to derive application secrets", gse);
819
}
820
821
/*
822
* save client verify data for secure renegotiation
823
*/
824
if (shc.conContext.secureRenegotiation) {
825
shc.conContext.serverVerifyData = fm.verifyData;
826
}
827
828
// update the context
829
shc.handshakeConsumers.put(
830
SSLHandshake.FINISHED.id, SSLHandshake.FINISHED);
831
832
// The handshake message has been delivered.
833
return null;
834
}
835
}
836
837
/**
838
* The "Finished" handshake message consumer.
839
*/
840
private static final class T13FinishedConsumer implements SSLConsumer {
841
// Prevent instantiation of this class.
842
private T13FinishedConsumer() {
843
// blank
844
}
845
846
@Override
847
public void consume(ConnectionContext context,
848
ByteBuffer message) throws IOException {
849
// The consuming happens in handshake context only.
850
HandshakeContext hc = (HandshakeContext)context;
851
if (hc.sslConfig.isClientMode) {
852
onConsumeFinished(
853
(ClientHandshakeContext)context, message);
854
} else {
855
onConsumeFinished(
856
(ServerHandshakeContext)context, message);
857
}
858
}
859
860
private void onConsumeFinished(ClientHandshakeContext chc,
861
ByteBuffer message) throws IOException {
862
// Make sure that any expected CertificateVerify message
863
// has been received and processed.
864
if (!chc.isResumption) {
865
if (chc.handshakeConsumers.containsKey(
866
SSLHandshake.CERTIFICATE.id) ||
867
chc.handshakeConsumers.containsKey(
868
SSLHandshake.CERTIFICATE_VERIFY.id)) {
869
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
870
"Unexpected Finished handshake message");
871
}
872
}
873
874
FinishedMessage fm = new FinishedMessage(chc, message);
875
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
876
SSLLogger.fine(
877
"Consuming server Finished handshake message", fm);
878
}
879
880
// Save client verify data for secure renegotiation.
881
if (chc.conContext.secureRenegotiation) {
882
chc.conContext.serverVerifyData = fm.verifyData;
883
}
884
885
//
886
// validate
887
//
888
// blank
889
890
//
891
// update
892
//
893
// A change_cipher_spec record received after the peer's Finished
894
// message MUST be treated as an unexpected record type.
895
chc.conContext.consumers.remove(ContentType.CHANGE_CIPHER_SPEC.id);
896
897
// Change client/server application traffic secrets.
898
// Refresh handshake hash
899
chc.handshakeHash.update();
900
SSLKeyDerivation kd = chc.handshakeKeyDerivation;
901
if (kd == null) {
902
// unlikely
903
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
904
"no key derivation");
905
}
906
907
SSLTrafficKeyDerivation kdg =
908
SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
909
if (kdg == null) {
910
// unlikely
911
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
912
"Not supported key derivation: " +
913
chc.negotiatedProtocol);
914
}
915
916
// save the session
917
if (!chc.isResumption && chc.handshakeSession.isRejoinable()) {
918
SSLSessionContextImpl sessionContext = (SSLSessionContextImpl)
919
chc.sslContext.engineGetClientSessionContext();
920
sessionContext.put(chc.handshakeSession);
921
}
922
923
// derive salt secret
924
try {
925
SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
926
927
// derive application secrets
928
HashAlg hashAlg = chc.negotiatedCipherSuite.hashAlg;
929
HKDF hkdf = new HKDF(hashAlg.name);
930
byte[] zeros = new byte[hashAlg.hashLength];
931
SecretKeySpec sharedSecret =
932
new SecretKeySpec(zeros, "TlsZeroSecret");
933
SecretKey masterSecret =
934
hkdf.extract(saltSecret, sharedSecret, "TlsMasterSecret");
935
936
SSLKeyDerivation secretKD =
937
new SSLSecretDerivation(chc, masterSecret);
938
939
// update the handshake traffic read keys.
940
SecretKey readSecret = secretKD.deriveKey(
941
"TlsServerAppTrafficSecret", null);
942
SSLKeyDerivation writeKD =
943
kdg.createKeyDerivation(chc, readSecret);
944
SecretKey readKey = writeKD.deriveKey(
945
"TlsKey", null);
946
SecretKey readIvSecret = writeKD.deriveKey(
947
"TlsIv", null);
948
IvParameterSpec readIv =
949
new IvParameterSpec(readIvSecret.getEncoded());
950
SSLReadCipher readCipher =
951
chc.negotiatedCipherSuite.bulkCipher.createReadCipher(
952
Authenticator.valueOf(chc.negotiatedProtocol),
953
chc.negotiatedProtocol, readKey, readIv,
954
chc.sslContext.getSecureRandom());
955
956
if (readCipher == null) {
957
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
958
"Illegal cipher suite (" + chc.negotiatedCipherSuite +
959
") and protocol version (" + chc.negotiatedProtocol +
960
")");
961
}
962
963
chc.baseReadSecret = readSecret;
964
chc.conContext.inputRecord.changeReadCiphers(readCipher);
965
966
// update the context for the following key derivation
967
chc.handshakeKeyDerivation = secretKD;
968
} catch (GeneralSecurityException gse) {
969
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
970
"Failure to derive application secrets", gse);
971
}
972
973
//
974
// produce
975
//
976
chc.handshakeProducers.put(SSLHandshake.FINISHED.id,
977
SSLHandshake.FINISHED);
978
SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] {
979
// full handshake messages
980
SSLHandshake.CERTIFICATE,
981
SSLHandshake.CERTIFICATE_VERIFY,
982
SSLHandshake.FINISHED
983
};
984
985
for (SSLHandshake hs : probableHandshakeMessages) {
986
HandshakeProducer handshakeProducer =
987
chc.handshakeProducers.remove(hs.id);
988
if (handshakeProducer != null) {
989
handshakeProducer.produce(chc, null);
990
}
991
}
992
}
993
994
private void onConsumeFinished(ServerHandshakeContext shc,
995
ByteBuffer message) throws IOException {
996
// Make sure that any expected CertificateVerify message
997
// has been received and processed.
998
if (!shc.isResumption) {
999
if (shc.handshakeConsumers.containsKey(
1000
SSLHandshake.CERTIFICATE.id) ||
1001
shc.handshakeConsumers.containsKey(
1002
SSLHandshake.CERTIFICATE_VERIFY.id)) {
1003
throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
1004
"Unexpected Finished handshake message");
1005
}
1006
}
1007
1008
FinishedMessage fm = new FinishedMessage(shc, message);
1009
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1010
SSLLogger.fine(
1011
"Consuming client Finished handshake message", fm);
1012
}
1013
1014
if (shc.conContext.secureRenegotiation) {
1015
shc.conContext.clientVerifyData = fm.verifyData;
1016
}
1017
1018
//
1019
// validate
1020
//
1021
// blank
1022
1023
//
1024
// update
1025
//
1026
// Change client/server application traffic secrets.
1027
SSLKeyDerivation kd = shc.handshakeKeyDerivation;
1028
if (kd == null) {
1029
// unlikely
1030
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
1031
"no key derivation");
1032
}
1033
1034
SSLTrafficKeyDerivation kdg =
1035
SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
1036
if (kdg == null) {
1037
// unlikely
1038
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
1039
"Not supported key derivation: " +
1040
shc.negotiatedProtocol);
1041
}
1042
1043
// save the session
1044
if (!shc.isResumption && shc.handshakeSession.isRejoinable()) {
1045
SSLSessionContextImpl sessionContext = (SSLSessionContextImpl)
1046
shc.sslContext.engineGetServerSessionContext();
1047
sessionContext.put(shc.handshakeSession);
1048
}
1049
1050
try {
1051
// update the application traffic read keys.
1052
SecretKey readSecret = kd.deriveKey(
1053
"TlsClientAppTrafficSecret", null);
1054
1055
SSLKeyDerivation readKD =
1056
kdg.createKeyDerivation(shc, readSecret);
1057
SecretKey readKey = readKD.deriveKey(
1058
"TlsKey", null);
1059
SecretKey readIvSecret = readKD.deriveKey(
1060
"TlsIv", null);
1061
IvParameterSpec readIv =
1062
new IvParameterSpec(readIvSecret.getEncoded());
1063
SSLReadCipher readCipher =
1064
shc.negotiatedCipherSuite.bulkCipher.createReadCipher(
1065
Authenticator.valueOf(shc.negotiatedProtocol),
1066
shc.negotiatedProtocol, readKey, readIv,
1067
shc.sslContext.getSecureRandom());
1068
1069
if (readCipher == null) {
1070
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
1071
"Illegal cipher suite (" + shc.negotiatedCipherSuite +
1072
") and protocol version (" + shc.negotiatedProtocol +
1073
")");
1074
}
1075
1076
shc.baseReadSecret = readSecret;
1077
shc.conContext.inputRecord.changeReadCiphers(readCipher);
1078
1079
// The resumption master secret is stored in the session so
1080
// it can be used after the handshake is completed.
1081
shc.handshakeHash.update();
1082
SSLSecretDerivation sd =
1083
((SSLSecretDerivation)kd).forContext(shc);
1084
SecretKey resumptionMasterSecret = sd.deriveKey(
1085
"TlsResumptionMasterSecret", null);
1086
shc.handshakeSession.setResumptionMasterSecret(
1087
resumptionMasterSecret);
1088
} catch (GeneralSecurityException gse) {
1089
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
1090
"Failure to derive application secrets", gse);
1091
}
1092
1093
// update connection context
1094
shc.conContext.conSession = shc.handshakeSession.finish();
1095
shc.conContext.protocolVersion = shc.negotiatedProtocol;
1096
1097
// handshake context cleanup.
1098
shc.handshakeFinished = true;
1099
1100
shc.conContext.finishHandshake();
1101
1102
//
1103
// produce
1104
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
1105
SSLLogger.fine(
1106
"Sending new session ticket");
1107
}
1108
NewSessionTicket.kickstartProducer.produce(shc);
1109
1110
}
1111
}
1112
1113
}
1114
1115