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