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/KeyUpdate.java
38830 views
1
/*
2
* Copyright (c) 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.text.MessageFormat;
32
import java.util.Locale;
33
34
import sun.security.ssl.SSLHandshake.HandshakeMessage;
35
import sun.security.ssl.SSLCipher.SSLReadCipher;
36
import sun.security.ssl.SSLCipher.SSLWriteCipher;
37
38
import javax.crypto.SecretKey;
39
import javax.crypto.spec.IvParameterSpec;
40
41
/**
42
* Pack of the KeyUpdate handshake message.
43
*/
44
final class KeyUpdate {
45
static final SSLProducer kickstartProducer =
46
new KeyUpdateKickstartProducer();
47
48
static final SSLConsumer handshakeConsumer =
49
new KeyUpdateConsumer();
50
static final HandshakeProducer handshakeProducer =
51
new KeyUpdateProducer();
52
53
/**
54
* The KeyUpdate handshake message.
55
*
56
* The KeyUpdate handshake message is used to indicate that the sender is
57
* updating its sending cryptographic keys.
58
*
59
* enum {
60
* update_not_requested(0), update_requested(1), (255)
61
* } KeyUpdateRequest;
62
*
63
* struct {
64
* KeyUpdateRequest request_update;
65
* } KeyUpdate;
66
*/
67
static final class KeyUpdateMessage extends HandshakeMessage {
68
private final KeyUpdateRequest status;
69
70
KeyUpdateMessage(PostHandshakeContext context,
71
KeyUpdateRequest status) {
72
super(context);
73
this.status = status;
74
}
75
76
KeyUpdateMessage(PostHandshakeContext context,
77
ByteBuffer m) throws IOException {
78
super(context);
79
80
if (m.remaining() != 1) {
81
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
82
"KeyUpdate has an unexpected length of "+
83
m.remaining());
84
}
85
86
byte request = m.get();
87
this.status = KeyUpdateRequest.valueOf(request);
88
if (status == null) {
89
throw context.conContext.fatal(Alert.ILLEGAL_PARAMETER,
90
"Invalid KeyUpdate message value: " +
91
KeyUpdateRequest.nameOf(request));
92
}
93
}
94
95
@Override
96
public SSLHandshake handshakeType() {
97
return SSLHandshake.KEY_UPDATE;
98
}
99
100
@Override
101
public int messageLength() {
102
// one byte enum
103
return 1;
104
}
105
106
@Override
107
public void send(HandshakeOutStream s) throws IOException {
108
s.putInt8(status.id);
109
}
110
111
@Override
112
public String toString() {
113
MessageFormat messageFormat = new MessageFormat(
114
"\"KeyUpdate\": '{'\n" +
115
" \"request_update\": {0}\n" +
116
"'}'",
117
Locale.ENGLISH);
118
119
Object[] messageFields = {
120
status.name
121
};
122
123
return messageFormat.format(messageFields);
124
}
125
}
126
127
enum KeyUpdateRequest {
128
NOTREQUESTED ((byte)0, "update_not_requested"),
129
REQUESTED ((byte)1, "update_requested");
130
131
final byte id;
132
final String name;
133
134
private KeyUpdateRequest(byte id, String name) {
135
this.id = id;
136
this.name = name;
137
}
138
139
static KeyUpdateRequest valueOf(byte id) {
140
for (KeyUpdateRequest kur : KeyUpdateRequest.values()) {
141
if (kur.id == id) {
142
return kur;
143
}
144
}
145
146
return null;
147
}
148
149
static String nameOf(byte id) {
150
for (KeyUpdateRequest kur : KeyUpdateRequest.values()) {
151
if (kur.id == id) {
152
return kur.name;
153
}
154
}
155
156
return "<UNKNOWN KeyUpdateRequest TYPE: " + (id & 0x0FF) + ">";
157
}
158
}
159
160
private static final
161
class KeyUpdateKickstartProducer implements SSLProducer {
162
// Prevent instantiation of this class.
163
private KeyUpdateKickstartProducer() {
164
// blank
165
}
166
167
// Produce kickstart handshake message.
168
@Override
169
public byte[] produce(ConnectionContext context) throws IOException {
170
PostHandshakeContext hc = (PostHandshakeContext)context;
171
return handshakeProducer.produce(context,
172
new KeyUpdateMessage(hc, KeyUpdateRequest.REQUESTED));
173
}
174
}
175
176
/**
177
* The "KeyUpdate" handshake message consumer.
178
*/
179
private static final class KeyUpdateConsumer implements SSLConsumer {
180
// Prevent instantiation of this class.
181
private KeyUpdateConsumer() {
182
// blank
183
}
184
185
@Override
186
public void consume(ConnectionContext context,
187
ByteBuffer message) throws IOException {
188
// The consuming happens in client side only.
189
PostHandshakeContext hc = (PostHandshakeContext)context;
190
KeyUpdateMessage km = new KeyUpdateMessage(hc, message);
191
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
192
SSLLogger.fine(
193
"Consuming KeyUpdate post-handshake message", km);
194
}
195
196
// Update read key and IV.
197
SSLTrafficKeyDerivation kdg =
198
SSLTrafficKeyDerivation.valueOf(hc.conContext.protocolVersion);
199
if (kdg == null) {
200
// unlikely
201
throw hc.conContext.fatal(Alert.INTERNAL_ERROR,
202
"Not supported key derivation: " +
203
hc.conContext.protocolVersion);
204
}
205
206
SSLKeyDerivation skd = kdg.createKeyDerivation(hc,
207
hc.conContext.inputRecord.readCipher.baseSecret);
208
if (skd == null) {
209
// unlikely
210
throw hc.conContext.fatal(
211
Alert.INTERNAL_ERROR, "no key derivation");
212
}
213
214
SecretKey nplus1 = skd.deriveKey("TlsUpdateNplus1", null);
215
SSLKeyDerivation kd = kdg.createKeyDerivation(hc, nplus1);
216
SecretKey key = kd.deriveKey("TlsKey", null);
217
IvParameterSpec ivSpec = new IvParameterSpec(
218
kd.deriveKey("TlsIv", null).getEncoded());
219
try {
220
SSLReadCipher rc =
221
hc.negotiatedCipherSuite.bulkCipher.createReadCipher(
222
Authenticator.valueOf(hc.conContext.protocolVersion),
223
hc.conContext.protocolVersion, key, ivSpec,
224
hc.sslContext.getSecureRandom());
225
226
if (rc == null) {
227
throw hc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
228
"Illegal cipher suite (" + hc.negotiatedCipherSuite +
229
") and protocol version (" + hc.negotiatedProtocol +
230
")");
231
}
232
233
rc.baseSecret = nplus1;
234
hc.conContext.inputRecord.changeReadCiphers(rc);
235
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
236
SSLLogger.fine("KeyUpdate: read key updated");
237
}
238
} catch (GeneralSecurityException gse) {
239
throw hc.conContext.fatal(Alert.INTERNAL_ERROR,
240
"Failure to derive read secrets", gse);
241
}
242
243
if (km.status == KeyUpdateRequest.REQUESTED) {
244
// Update the write key and IV.
245
handshakeProducer.produce(hc,
246
new KeyUpdateMessage(hc, KeyUpdateRequest.NOTREQUESTED));
247
return;
248
}
249
250
// clean handshake context
251
hc.conContext.finishPostHandshake();
252
}
253
}
254
255
/**
256
* The "KeyUpdate" handshake message producer.
257
*/
258
private static final class KeyUpdateProducer implements HandshakeProducer {
259
// Prevent instantiation of this class.
260
private KeyUpdateProducer() {
261
// blank
262
}
263
264
@Override
265
public byte[] produce(ConnectionContext context,
266
HandshakeMessage message) throws IOException {
267
// The producing happens in server side only.
268
PostHandshakeContext hc = (PostHandshakeContext)context;
269
KeyUpdateMessage km = (KeyUpdateMessage)message;
270
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
271
SSLLogger.fine(
272
"Produced KeyUpdate post-handshake message", km);
273
}
274
275
// Update the write key and IV.
276
SSLTrafficKeyDerivation kdg =
277
SSLTrafficKeyDerivation.valueOf(hc.conContext.protocolVersion);
278
if (kdg == null) {
279
// unlikely
280
throw hc.conContext.fatal(Alert.INTERNAL_ERROR,
281
"Not supported key derivation: " +
282
hc.conContext.protocolVersion);
283
}
284
285
SSLKeyDerivation skd = kdg.createKeyDerivation(hc,
286
hc.conContext.outputRecord.writeCipher.baseSecret);
287
if (skd == null) {
288
// unlikely
289
throw hc.conContext.fatal(
290
Alert.INTERNAL_ERROR, "no key derivation");
291
}
292
293
SecretKey nplus1 = skd.deriveKey("TlsUpdateNplus1", null);
294
SSLKeyDerivation kd = kdg.createKeyDerivation(hc, nplus1);
295
SecretKey key = kd.deriveKey("TlsKey", null);
296
IvParameterSpec ivSpec = new IvParameterSpec(
297
kd.deriveKey("TlsIv", null).getEncoded());
298
299
SSLWriteCipher wc;
300
try {
301
wc = hc.negotiatedCipherSuite.bulkCipher.createWriteCipher(
302
Authenticator.valueOf(hc.conContext.protocolVersion),
303
hc.conContext.protocolVersion, key, ivSpec,
304
hc.sslContext.getSecureRandom());
305
} catch (GeneralSecurityException gse) {
306
throw hc.conContext.fatal(Alert.INTERNAL_ERROR,
307
"Failure to derive write secrets", gse);
308
}
309
310
if (wc == null) {
311
throw hc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
312
"Illegal cipher suite (" + hc.negotiatedCipherSuite +
313
") and protocol version (" + hc.negotiatedProtocol + ")");
314
}
315
316
// Output the handshake message and change the write cipher.
317
//
318
// The KeyUpdate handshake message SHALL be delivered in the
319
// changeWriteCiphers() implementation.
320
wc.baseSecret = nplus1;
321
hc.conContext.outputRecord.changeWriteCiphers(wc, km.status.id);
322
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
323
SSLLogger.fine("KeyUpdate: write key updated");
324
}
325
326
// clean handshake context
327
hc.conContext.finishPostHandshake();
328
329
// The handshake message has been delivered.
330
return null;
331
}
332
}
333
}
334
335