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/ECDHClientKeyExchange.java
38830 views
1
/*
2
* Copyright (c) 2003, 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.AlgorithmConstraints;
31
import java.security.CryptoPrimitive;
32
import java.security.GeneralSecurityException;
33
import java.security.KeyFactory;
34
import java.security.PublicKey;
35
import java.security.interfaces.ECPublicKey;
36
import java.security.spec.ECParameterSpec;
37
import java.security.spec.ECPoint;
38
import java.security.spec.ECPublicKeySpec;
39
import java.text.MessageFormat;
40
import java.util.EnumSet;
41
import java.util.Locale;
42
import javax.crypto.SecretKey;
43
import javax.net.ssl.SSLHandshakeException;
44
import sun.security.ssl.ECDHKeyExchange.ECDHECredentials;
45
import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
46
import sun.security.ssl.SSLHandshake.HandshakeMessage;
47
import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
48
import sun.security.ssl.X509Authentication.X509Credentials;
49
import sun.security.ssl.X509Authentication.X509Possession;
50
import sun.misc.HexDumpEncoder;
51
52
/**
53
* Pack of the "ClientKeyExchange" handshake message.
54
*/
55
final class ECDHClientKeyExchange {
56
static final SSLConsumer ecdhHandshakeConsumer =
57
new ECDHClientKeyExchangeConsumer();
58
static final HandshakeProducer ecdhHandshakeProducer =
59
new ECDHClientKeyExchangeProducer();
60
61
static final SSLConsumer ecdheHandshakeConsumer =
62
new ECDHEClientKeyExchangeConsumer();
63
static final HandshakeProducer ecdheHandshakeProducer =
64
new ECDHEClientKeyExchangeProducer();
65
66
/**
67
* The ECDH/ECDHE ClientKeyExchange handshake message.
68
*/
69
private static final
70
class ECDHClientKeyExchangeMessage extends HandshakeMessage {
71
private final byte[] encodedPoint;
72
73
ECDHClientKeyExchangeMessage(HandshakeContext handshakeContext,
74
ECPublicKey publicKey) {
75
super(handshakeContext);
76
77
ECPoint point = publicKey.getW();
78
ECParameterSpec params = publicKey.getParams();
79
encodedPoint = JsseJce.encodePoint(point, params.getCurve());
80
}
81
82
ECDHClientKeyExchangeMessage(HandshakeContext handshakeContext,
83
ByteBuffer m) throws IOException {
84
super(handshakeContext);
85
if (m.remaining() != 0) { // explicit PublicValueEncoding
86
this.encodedPoint = Record.getBytes8(m);
87
} else {
88
this.encodedPoint = new byte[0];
89
}
90
}
91
92
// Check constraints of the specified EC public key.
93
static void checkConstraints(AlgorithmConstraints constraints,
94
ECPublicKey publicKey,
95
byte[] encodedPoint) throws SSLHandshakeException {
96
97
try {
98
ECParameterSpec params = publicKey.getParams();
99
ECPoint point =
100
JsseJce.decodePoint(encodedPoint, params.getCurve());
101
ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
102
103
KeyFactory kf = JsseJce.getKeyFactory("EC");
104
ECPublicKey peerPublicKey =
105
(ECPublicKey)kf.generatePublic(spec);
106
107
// check constraints of ECPublicKey
108
if (!constraints.permits(
109
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
110
peerPublicKey)) {
111
throw new SSLHandshakeException(
112
"ECPublicKey does not comply to algorithm constraints");
113
}
114
} catch (GeneralSecurityException | java.io.IOException e) {
115
throw (SSLHandshakeException) new SSLHandshakeException(
116
"Could not generate ECPublicKey").initCause(e);
117
}
118
}
119
120
@Override
121
public SSLHandshake handshakeType() {
122
return SSLHandshake.CLIENT_KEY_EXCHANGE;
123
}
124
125
@Override
126
public int messageLength() {
127
if (encodedPoint == null || encodedPoint.length == 0) {
128
return 0;
129
} else {
130
return 1 + encodedPoint.length;
131
}
132
}
133
134
@Override
135
public void send(HandshakeOutStream hos) throws IOException {
136
if (encodedPoint != null && encodedPoint.length != 0) {
137
hos.putBytes8(encodedPoint);
138
}
139
}
140
141
@Override
142
public String toString() {
143
MessageFormat messageFormat = new MessageFormat(
144
"\"ECDH ClientKeyExchange\": '{'\n" +
145
" \"ecdh public\": '{'\n" +
146
"{0}\n" +
147
" '}',\n" +
148
"'}'",
149
Locale.ENGLISH);
150
if (encodedPoint == null || encodedPoint.length == 0) {
151
Object[] messageFields = {
152
" <implicit>"
153
};
154
return messageFormat.format(messageFields);
155
} else {
156
HexDumpEncoder hexEncoder = new HexDumpEncoder();
157
Object[] messageFields = {
158
Utilities.indent(
159
hexEncoder.encodeBuffer(encodedPoint), " "),
160
};
161
return messageFormat.format(messageFields);
162
}
163
}
164
}
165
166
/**
167
* The ECDH "ClientKeyExchange" handshake message producer.
168
*/
169
private static final
170
class ECDHClientKeyExchangeProducer implements HandshakeProducer {
171
// Prevent instantiation of this class.
172
private ECDHClientKeyExchangeProducer() {
173
// blank
174
}
175
176
@Override
177
public byte[] produce(ConnectionContext context,
178
HandshakeMessage message) throws IOException {
179
// The producing happens in client side only.
180
ClientHandshakeContext chc = (ClientHandshakeContext)context;
181
182
X509Credentials x509Credentials = null;
183
for (SSLCredentials credential : chc.handshakeCredentials) {
184
if (credential instanceof X509Credentials) {
185
x509Credentials = (X509Credentials)credential;
186
break;
187
}
188
}
189
190
if (x509Credentials == null) {
191
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
192
"No server certificate for ECDH client key exchange");
193
}
194
195
PublicKey publicKey = x509Credentials.popPublicKey;
196
if (!publicKey.getAlgorithm().equals("EC")) {
197
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
198
"Not EC server certificate for ECDH client key exchange");
199
}
200
201
ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
202
NamedGroup namedGroup = NamedGroup.valueOf(params);
203
if (namedGroup == null) {
204
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
205
"Unsupported EC server cert for ECDH client key exchange");
206
}
207
208
ECDHEPossession ecdhePossession = new ECDHEPossession(
209
namedGroup, chc.sslContext.getSecureRandom());
210
chc.handshakePossessions.add(ecdhePossession);
211
ECDHClientKeyExchangeMessage cke =
212
new ECDHClientKeyExchangeMessage(
213
chc, ecdhePossession.publicKey);
214
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
215
SSLLogger.fine(
216
"Produced ECDH ClientKeyExchange handshake message", cke);
217
}
218
219
// Output the handshake message.
220
cke.write(chc.handshakeOutput);
221
chc.handshakeOutput.flush();
222
223
// update the states
224
SSLKeyExchange ke = SSLKeyExchange.valueOf(
225
chc.negotiatedCipherSuite.keyExchange,
226
chc.negotiatedProtocol);
227
if (ke == null) {
228
// unlikely
229
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
230
"Not supported key exchange type");
231
} else {
232
SSLKeyDerivation masterKD = ke.createKeyDerivation(chc);
233
SecretKey masterSecret =
234
masterKD.deriveKey("MasterSecret", null);
235
chc.handshakeSession.setMasterSecret(masterSecret);
236
237
SSLTrafficKeyDerivation kd =
238
SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
239
if (kd == null) {
240
// unlikely
241
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
242
"Not supported key derivation: " +
243
chc.negotiatedProtocol);
244
} else {
245
chc.handshakeKeyDerivation =
246
kd.createKeyDerivation(chc, masterSecret);
247
}
248
}
249
250
// The handshake message has been delivered.
251
return null;
252
}
253
}
254
255
/**
256
* The ECDH "ClientKeyExchange" handshake message consumer.
257
*/
258
private static final
259
class ECDHClientKeyExchangeConsumer implements SSLConsumer {
260
// Prevent instantiation of this class.
261
private ECDHClientKeyExchangeConsumer() {
262
// blank
263
}
264
265
@Override
266
public void consume(ConnectionContext context,
267
ByteBuffer message) throws IOException {
268
// The consuming happens in server side only.
269
ServerHandshakeContext shc = (ServerHandshakeContext)context;
270
271
X509Possession x509Possession = null;
272
for (SSLPossession possession : shc.handshakePossessions) {
273
if (possession instanceof X509Possession) {
274
x509Possession = (X509Possession)possession;
275
break;
276
}
277
}
278
279
if (x509Possession == null) {
280
// unlikely, have been checked during cipher suite negotiation.
281
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
282
"No expected EC server cert for ECDH client key exchange");
283
}
284
285
ECParameterSpec params = x509Possession.getECParameterSpec();
286
if (params == null) {
287
// unlikely, have been checked during cipher suite negotiation.
288
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
289
"Not EC server cert for ECDH client key exchange");
290
}
291
292
NamedGroup namedGroup = NamedGroup.valueOf(params);
293
if (namedGroup == null) {
294
// unlikely, have been checked during cipher suite negotiation.
295
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
296
"Unsupported EC server cert for ECDH client key exchange");
297
}
298
299
SSLKeyExchange ke = SSLKeyExchange.valueOf(
300
shc.negotiatedCipherSuite.keyExchange,
301
shc.negotiatedProtocol);
302
if (ke == null) {
303
// unlikely
304
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
305
"Not supported key exchange type");
306
}
307
308
// parse the handshake message
309
ECDHClientKeyExchangeMessage cke =
310
new ECDHClientKeyExchangeMessage(shc, message);
311
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
312
SSLLogger.fine(
313
"Consuming ECDH ClientKeyExchange handshake message", cke);
314
}
315
316
// create the credentials
317
try {
318
ECPoint point =
319
JsseJce.decodePoint(cke.encodedPoint, params.getCurve());
320
ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
321
322
KeyFactory kf = JsseJce.getKeyFactory("EC");
323
ECPublicKey peerPublicKey =
324
(ECPublicKey)kf.generatePublic(spec);
325
326
// check constraints of peer ECPublicKey
327
if (!shc.algorithmConstraints.permits(
328
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
329
peerPublicKey)) {
330
throw new SSLHandshakeException(
331
"ECPublicKey does not comply to algorithm constraints");
332
}
333
334
shc.handshakeCredentials.add(new ECDHECredentials(
335
peerPublicKey, namedGroup));
336
} catch (GeneralSecurityException | java.io.IOException e) {
337
throw (SSLHandshakeException)(new SSLHandshakeException(
338
"Could not generate ECPublicKey").initCause(e));
339
}
340
341
// update the states
342
SSLKeyDerivation masterKD = ke.createKeyDerivation(shc);
343
SecretKey masterSecret =
344
masterKD.deriveKey("MasterSecret", null);
345
shc.handshakeSession.setMasterSecret(masterSecret);
346
347
SSLTrafficKeyDerivation kd =
348
SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
349
if (kd == null) {
350
// unlikely
351
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
352
"Not supported key derivation: " + shc.negotiatedProtocol);
353
} else {
354
shc.handshakeKeyDerivation =
355
kd.createKeyDerivation(shc, masterSecret);
356
}
357
}
358
}
359
360
/**
361
* The ECDHE "ClientKeyExchange" handshake message producer.
362
*/
363
private static final
364
class ECDHEClientKeyExchangeProducer implements HandshakeProducer {
365
// Prevent instantiation of this class.
366
private ECDHEClientKeyExchangeProducer() {
367
// blank
368
}
369
370
@Override
371
public byte[] produce(ConnectionContext context,
372
HandshakeMessage message) throws IOException {
373
// The producing happens in client side only.
374
ClientHandshakeContext chc = (ClientHandshakeContext)context;
375
376
ECDHECredentials ecdheCredentials = null;
377
for (SSLCredentials cd : chc.handshakeCredentials) {
378
if (cd instanceof ECDHECredentials) {
379
ecdheCredentials = (ECDHECredentials)cd;
380
break;
381
}
382
}
383
384
if (ecdheCredentials == null) {
385
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
386
"No ECDHE credentials negotiated for client key exchange");
387
}
388
389
ECDHEPossession ecdhePossession = new ECDHEPossession(
390
ecdheCredentials, chc.sslContext.getSecureRandom());
391
chc.handshakePossessions.add(ecdhePossession);
392
ECDHClientKeyExchangeMessage cke =
393
new ECDHClientKeyExchangeMessage(
394
chc, ecdhePossession.publicKey);
395
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
396
SSLLogger.fine(
397
"Produced ECDHE ClientKeyExchange handshake message", cke);
398
}
399
400
// Output the handshake message.
401
cke.write(chc.handshakeOutput);
402
chc.handshakeOutput.flush();
403
404
// update the states
405
SSLKeyExchange ke = SSLKeyExchange.valueOf(
406
chc.negotiatedCipherSuite.keyExchange,
407
chc.negotiatedProtocol);
408
if (ke == null) {
409
// unlikely
410
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
411
"Not supported key exchange type");
412
} else {
413
SSLKeyDerivation masterKD = ke.createKeyDerivation(chc);
414
SecretKey masterSecret =
415
masterKD.deriveKey("MasterSecret", null);
416
chc.handshakeSession.setMasterSecret(masterSecret);
417
418
SSLTrafficKeyDerivation kd =
419
SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
420
if (kd == null) {
421
// unlikely
422
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
423
"Not supported key derivation: " +
424
chc.negotiatedProtocol);
425
} else {
426
chc.handshakeKeyDerivation =
427
kd.createKeyDerivation(chc, masterSecret);
428
}
429
}
430
431
// The handshake message has been delivered.
432
return null;
433
}
434
}
435
436
/**
437
* The ECDHE "ClientKeyExchange" handshake message consumer.
438
*/
439
private static final
440
class ECDHEClientKeyExchangeConsumer implements SSLConsumer {
441
// Prevent instantiation of this class.
442
private ECDHEClientKeyExchangeConsumer() {
443
// blank
444
}
445
446
@Override
447
public void consume(ConnectionContext context,
448
ByteBuffer message) throws IOException {
449
// The consuming happens in server side only.
450
ServerHandshakeContext shc = (ServerHandshakeContext)context;
451
452
ECDHEPossession ecdhePossession = null;
453
for (SSLPossession possession : shc.handshakePossessions) {
454
if (possession instanceof ECDHEPossession) {
455
ecdhePossession = (ECDHEPossession)possession;
456
break;
457
}
458
}
459
if (ecdhePossession == null) {
460
// unlikely
461
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
462
"No expected ECDHE possessions for client key exchange");
463
}
464
465
ECParameterSpec params = ecdhePossession.publicKey.getParams();
466
NamedGroup namedGroup = NamedGroup.valueOf(params);
467
if (namedGroup == null) {
468
// unlikely, have been checked during cipher suite negotiation.
469
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
470
"Unsupported EC server cert for ECDHE client key exchange");
471
}
472
473
SSLKeyExchange ke = SSLKeyExchange.valueOf(
474
shc.negotiatedCipherSuite.keyExchange,
475
shc.negotiatedProtocol);
476
if (ke == null) {
477
// unlikely
478
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
479
"Not supported key exchange type");
480
}
481
482
// parse the handshake message
483
ECDHClientKeyExchangeMessage cke =
484
new ECDHClientKeyExchangeMessage(shc, message);
485
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
486
SSLLogger.fine(
487
"Consuming ECDHE ClientKeyExchange handshake message", cke);
488
}
489
490
// create the credentials
491
try {
492
ECPoint point =
493
JsseJce.decodePoint(cke.encodedPoint, params.getCurve());
494
ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
495
496
KeyFactory kf = JsseJce.getKeyFactory("EC");
497
ECPublicKey peerPublicKey =
498
(ECPublicKey)kf.generatePublic(spec);
499
500
// check constraints of peer ECPublicKey
501
if (!shc.algorithmConstraints.permits(
502
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
503
peerPublicKey)) {
504
throw new SSLHandshakeException(
505
"ECPublicKey does not comply to algorithm constraints");
506
}
507
508
shc.handshakeCredentials.add(new ECDHECredentials(
509
peerPublicKey, namedGroup));
510
} catch (GeneralSecurityException | java.io.IOException e) {
511
throw (SSLHandshakeException)(new SSLHandshakeException(
512
"Could not generate ECPublicKey").initCause(e));
513
}
514
515
// update the states
516
SSLKeyDerivation masterKD = ke.createKeyDerivation(shc);
517
SecretKey masterSecret =
518
masterKD.deriveKey("MasterSecret", null);
519
shc.handshakeSession.setMasterSecret(masterSecret);
520
521
SSLTrafficKeyDerivation kd =
522
SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
523
if (kd == null) {
524
// unlikely
525
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
526
"Not supported key derivation: " + shc.negotiatedProtocol);
527
} else {
528
shc.handshakeKeyDerivation =
529
kd.createKeyDerivation(shc, masterSecret);
530
}
531
}
532
}
533
}
534
535