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/DHClientKeyExchange.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.math.BigInteger;
30
import java.nio.ByteBuffer;
31
import java.security.CryptoPrimitive;
32
import java.security.GeneralSecurityException;
33
import java.security.KeyFactory;
34
import java.text.MessageFormat;
35
import java.util.EnumSet;
36
import java.util.Locale;
37
import javax.crypto.SecretKey;
38
import javax.crypto.interfaces.DHPublicKey;
39
import javax.crypto.spec.DHParameterSpec;
40
import javax.crypto.spec.DHPublicKeySpec;
41
import javax.net.ssl.SSLHandshakeException;
42
import sun.security.ssl.DHKeyExchange.DHECredentials;
43
import sun.security.ssl.DHKeyExchange.DHEPossession;
44
import sun.security.ssl.SSLHandshake.HandshakeMessage;
45
import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
46
import sun.misc.HexDumpEncoder;
47
48
/**
49
* Pack of the "ClientKeyExchange" handshake message.
50
*/
51
final class DHClientKeyExchange {
52
static final DHClientKeyExchangeConsumer dhHandshakeConsumer =
53
new DHClientKeyExchangeConsumer();
54
static final DHClientKeyExchangeProducer dhHandshakeProducer =
55
new DHClientKeyExchangeProducer();
56
57
/**
58
* The DiffieHellman ClientKeyExchange handshake message.
59
*
60
* If the client has sent a certificate which contains a suitable
61
* DiffieHellman key (for fixed_dh client authentication), then the
62
* client public value is implicit and does not need to be sent again.
63
* In this case, the client key exchange message will be sent, but it
64
* MUST be empty.
65
*
66
* Currently, we don't support cipher suite that requires implicit public
67
* key of client.
68
*/
69
private static final
70
class DHClientKeyExchangeMessage extends HandshakeMessage {
71
private byte[] y; // 1 to 2^16 - 1 bytes
72
73
DHClientKeyExchangeMessage(
74
HandshakeContext handshakeContext) throws IOException {
75
super(handshakeContext);
76
// This happens in client side only.
77
ClientHandshakeContext chc =
78
(ClientHandshakeContext)handshakeContext;
79
80
DHEPossession dhePossession = null;
81
for (SSLPossession possession : chc.handshakePossessions) {
82
if (possession instanceof DHEPossession) {
83
dhePossession = (DHEPossession)possession;
84
break;
85
}
86
}
87
88
if (dhePossession == null) {
89
// unlikely
90
throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
91
"No DHE credentials negotiated for client key exchange");
92
}
93
94
DHPublicKey publicKey = dhePossession.publicKey;
95
DHParameterSpec params = publicKey.getParams();
96
this.y = Utilities.toByteArray(publicKey.getY());
97
}
98
99
DHClientKeyExchangeMessage(HandshakeContext handshakeContext,
100
ByteBuffer m) throws IOException {
101
super(handshakeContext);
102
// This happens in server side only.
103
ServerHandshakeContext shc =
104
(ServerHandshakeContext)handshakeContext;
105
106
if (m.remaining() < 3) {
107
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
108
"Invalid DH ClientKeyExchange message: insufficient data");
109
}
110
111
this.y = Record.getBytes16(m);
112
113
if (m.hasRemaining()) {
114
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
115
"Invalid DH ClientKeyExchange message: unknown extra data");
116
}
117
}
118
119
@Override
120
public SSLHandshake handshakeType() {
121
return SSLHandshake.CLIENT_KEY_EXCHANGE;
122
}
123
124
@Override
125
public int messageLength() {
126
return y.length + 2; // 2: length filed
127
}
128
129
@Override
130
public void send(HandshakeOutStream hos) throws IOException {
131
hos.putBytes16(y);
132
}
133
134
@Override
135
public String toString() {
136
MessageFormat messageFormat = new MessageFormat(
137
"\"DH ClientKeyExchange\": '{'\n" +
138
" \"parameters\": '{'\n" +
139
" \"dh_Yc\": '{'\n" +
140
"{0}\n" +
141
" '}',\n" +
142
" '}'\n" +
143
"'}'",
144
Locale.ENGLISH);
145
146
HexDumpEncoder hexEncoder = new HexDumpEncoder();
147
Object[] messageFields = {
148
Utilities.indent(
149
hexEncoder.encodeBuffer(y), " "),
150
};
151
return messageFormat.format(messageFields);
152
}
153
}
154
155
/**
156
* The DiffieHellman "ClientKeyExchange" handshake message producer.
157
*/
158
private static final
159
class DHClientKeyExchangeProducer implements HandshakeProducer {
160
// Prevent instantiation of this class.
161
private DHClientKeyExchangeProducer() {
162
// blank
163
}
164
165
@Override
166
public byte[] produce(ConnectionContext context,
167
HandshakeMessage message) throws IOException {
168
// The producing happens in client side only.
169
ClientHandshakeContext chc = (ClientHandshakeContext)context;
170
171
DHECredentials dheCredentials = null;
172
for (SSLCredentials cd : chc.handshakeCredentials) {
173
if (cd instanceof DHECredentials) {
174
dheCredentials = (DHECredentials)cd;
175
break;
176
}
177
}
178
179
if (dheCredentials == null) {
180
throw chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
181
"No DHE credentials negotiated for client key exchange");
182
}
183
184
185
DHEPossession dhePossession = new DHEPossession(
186
dheCredentials, chc.sslContext.getSecureRandom());
187
chc.handshakePossessions.add(dhePossession);
188
DHClientKeyExchangeMessage ckem =
189
new DHClientKeyExchangeMessage(chc);
190
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
191
SSLLogger.fine(
192
"Produced DH ClientKeyExchange handshake message", ckem);
193
}
194
195
// Output the handshake message.
196
ckem.write(chc.handshakeOutput);
197
chc.handshakeOutput.flush();
198
199
// update the states
200
SSLKeyExchange ke = SSLKeyExchange.valueOf(
201
chc.negotiatedCipherSuite.keyExchange,
202
chc.negotiatedProtocol);
203
if (ke == null) {
204
// unlikely
205
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
206
"Not supported key exchange type");
207
} else {
208
SSLKeyDerivation masterKD = ke.createKeyDerivation(chc);
209
SecretKey masterSecret =
210
masterKD.deriveKey("MasterSecret", null);
211
chc.handshakeSession.setMasterSecret(masterSecret);
212
213
SSLTrafficKeyDerivation kd =
214
SSLTrafficKeyDerivation.valueOf(chc.negotiatedProtocol);
215
if (kd == null) {
216
// unlikely
217
throw chc.conContext.fatal(Alert.INTERNAL_ERROR,
218
"Not supported key derivation: " +
219
chc.negotiatedProtocol);
220
} else {
221
chc.handshakeKeyDerivation =
222
kd.createKeyDerivation(chc, masterSecret);
223
}
224
}
225
226
// The handshake message has been delivered.
227
return null;
228
}
229
}
230
231
/**
232
* The DiffieHellman "ClientKeyExchange" handshake message consumer.
233
*/
234
private static final
235
class DHClientKeyExchangeConsumer implements SSLConsumer {
236
// Prevent instantiation of this class.
237
private DHClientKeyExchangeConsumer() {
238
// blank
239
}
240
241
@Override
242
public void consume(ConnectionContext context,
243
ByteBuffer message) throws IOException {
244
// The consuming happens in server side only.
245
ServerHandshakeContext shc = (ServerHandshakeContext)context;
246
247
DHEPossession dhePossession = null;
248
for (SSLPossession possession : shc.handshakePossessions) {
249
if (possession instanceof DHEPossession) {
250
dhePossession = (DHEPossession)possession;
251
break;
252
}
253
}
254
255
if (dhePossession == null) {
256
// unlikely
257
throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
258
"No expected DHE possessions for client key exchange");
259
}
260
261
SSLKeyExchange ke = SSLKeyExchange.valueOf(
262
shc.negotiatedCipherSuite.keyExchange,
263
shc.negotiatedProtocol);
264
if (ke == null) {
265
// unlikely
266
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
267
"Not supported key exchange type");
268
}
269
270
DHClientKeyExchangeMessage ckem =
271
new DHClientKeyExchangeMessage(shc, message);
272
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
273
SSLLogger.fine(
274
"Consuming DH ClientKeyExchange handshake message", ckem);
275
}
276
277
// create the credentials
278
try {
279
DHParameterSpec params = dhePossession.publicKey.getParams();
280
DHPublicKeySpec spec = new DHPublicKeySpec(
281
new BigInteger(1, ckem.y),
282
params.getP(), params.getG());
283
KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
284
DHPublicKey peerPublicKey =
285
(DHPublicKey)kf.generatePublic(spec);
286
287
// check constraints of peer DHPublicKey
288
if (!shc.algorithmConstraints.permits(
289
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
290
peerPublicKey)) {
291
throw new SSLHandshakeException(
292
"DHPublicKey does not comply to algorithm constraints");
293
}
294
295
NamedGroup namedGroup = NamedGroup.valueOf(params);
296
shc.handshakeCredentials.add(
297
new DHECredentials(peerPublicKey, namedGroup));
298
} catch (GeneralSecurityException | java.io.IOException e) {
299
throw (SSLHandshakeException)(new SSLHandshakeException(
300
"Could not generate DHPublicKey").initCause(e));
301
}
302
303
// update the states
304
SSLKeyDerivation masterKD = ke.createKeyDerivation(shc);
305
SecretKey masterSecret =
306
masterKD.deriveKey("MasterSecret", null);
307
shc.handshakeSession.setMasterSecret(masterSecret);
308
309
SSLTrafficKeyDerivation kd =
310
SSLTrafficKeyDerivation.valueOf(shc.negotiatedProtocol);
311
if (kd == null) {
312
// unlikely
313
throw shc.conContext.fatal(Alert.INTERNAL_ERROR,
314
"Not supported key derivation: " + shc.negotiatedProtocol);
315
} else {
316
shc.handshakeKeyDerivation =
317
kd.createKeyDerivation(shc, masterSecret);
318
}
319
}
320
}
321
}
322
323