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/util/KeyUtil.java
38830 views
1
/*
2
* Copyright (c) 2012, 2016, 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.util;
27
28
import java.security.AlgorithmParameters;
29
import java.security.Key;
30
import java.security.PrivilegedAction;
31
import java.security.AccessController;
32
import java.security.InvalidKeyException;
33
import java.security.interfaces.ECKey;
34
import java.security.interfaces.RSAKey;
35
import java.security.interfaces.DSAKey;
36
import java.security.interfaces.DSAParams;
37
import java.security.SecureRandom;
38
import java.security.spec.KeySpec;
39
import java.security.spec.ECParameterSpec;
40
import java.security.spec.InvalidParameterSpecException;
41
import javax.crypto.SecretKey;
42
import javax.crypto.interfaces.DHKey;
43
import javax.crypto.interfaces.DHPublicKey;
44
import javax.crypto.spec.DHParameterSpec;
45
import javax.crypto.spec.DHPublicKeySpec;
46
import java.math.BigInteger;
47
48
import sun.security.jca.JCAUtil;
49
50
/**
51
* A utility class to get key length, valiate keys, etc.
52
*/
53
public final class KeyUtil {
54
55
/**
56
* Returns the key size of the given key object in bits.
57
*
58
* @param key the key object, cannot be null
59
* @return the key size of the given key object in bits, or -1 if the
60
* key size is not accessible
61
*/
62
public static final int getKeySize(Key key) {
63
int size = -1;
64
65
if (key instanceof Length) {
66
try {
67
Length ruler = (Length)key;
68
size = ruler.length();
69
} catch (UnsupportedOperationException usoe) {
70
// ignore the exception
71
}
72
73
if (size >= 0) {
74
return size;
75
}
76
}
77
78
// try to parse the length from key specification
79
if (key instanceof SecretKey) {
80
SecretKey sk = (SecretKey)key;
81
String format = sk.getFormat();
82
if ("RAW".equals(format) && sk.getEncoded() != null) {
83
size = (sk.getEncoded().length * 8);
84
} // Otherwise, it may be a unextractable key of PKCS#11, or
85
// a key we are not able to handle.
86
} else if (key instanceof RSAKey) {
87
RSAKey pubk = (RSAKey)key;
88
size = pubk.getModulus().bitLength();
89
} else if (key instanceof ECKey) {
90
ECKey pubk = (ECKey)key;
91
size = pubk.getParams().getOrder().bitLength();
92
} else if (key instanceof DSAKey) {
93
DSAKey pubk = (DSAKey)key;
94
DSAParams params = pubk.getParams(); // params can be null
95
size = (params != null) ? params.getP().bitLength() : -1;
96
} else if (key instanceof DHKey) {
97
DHKey pubk = (DHKey)key;
98
size = pubk.getParams().getP().bitLength();
99
} // Otherwise, it may be a unextractable key of PKCS#11, or
100
// a key we are not able to handle.
101
102
return size;
103
}
104
105
/**
106
* Returns the key size of the given cryptographic parameters in bits.
107
*
108
* @param parameters the cryptographic parameters, cannot be null
109
* @return the key size of the given cryptographic parameters in bits,
110
* or -1 if the key size is not accessible
111
*/
112
public static final int getKeySize(AlgorithmParameters parameters) {
113
114
String algorithm = parameters.getAlgorithm();
115
switch (algorithm) {
116
case "EC":
117
try {
118
ECKeySizeParameterSpec ps = parameters.getParameterSpec(
119
ECKeySizeParameterSpec.class);
120
if (ps != null) {
121
return ps.getKeySize();
122
}
123
} catch (InvalidParameterSpecException ipse) {
124
// ignore
125
}
126
127
try {
128
ECParameterSpec ps = parameters.getParameterSpec(
129
ECParameterSpec.class);
130
if (ps != null) {
131
return ps.getOrder().bitLength();
132
}
133
} catch (InvalidParameterSpecException ipse) {
134
// ignore
135
}
136
137
// Note: the ECGenParameterSpec case should be covered by the
138
// ECParameterSpec case above.
139
// See ECUtil.getECParameterSpec(Provider, String).
140
141
break;
142
case "DiffieHellman":
143
try {
144
DHParameterSpec ps = parameters.getParameterSpec(
145
DHParameterSpec.class);
146
if (ps != null) {
147
return ps.getP().bitLength();
148
}
149
} catch (InvalidParameterSpecException ipse) {
150
// ignore
151
}
152
break;
153
154
// May support more AlgorithmParameters algorithms in the future.
155
}
156
157
return -1;
158
}
159
160
/**
161
* Returns whether the key is valid or not.
162
* <P>
163
* Note that this method is only apply to DHPublicKey at present.
164
*
165
* @param publicKey
166
* the key object, cannot be null
167
*
168
* @throws NullPointerException if {@code publicKey} is null
169
* @throws InvalidKeyException if {@code publicKey} is invalid
170
*/
171
public static final void validate(Key key)
172
throws InvalidKeyException {
173
if (key == null) {
174
throw new NullPointerException(
175
"The key to be validated cannot be null");
176
}
177
178
if (key instanceof DHPublicKey) {
179
validateDHPublicKey((DHPublicKey)key);
180
}
181
}
182
183
184
/**
185
* Returns whether the key spec is valid or not.
186
* <P>
187
* Note that this method is only apply to DHPublicKeySpec at present.
188
*
189
* @param keySpec
190
* the key spec object, cannot be null
191
*
192
* @throws NullPointerException if {@code keySpec} is null
193
* @throws InvalidKeyException if {@code keySpec} is invalid
194
*/
195
public static final void validate(KeySpec keySpec)
196
throws InvalidKeyException {
197
if (keySpec == null) {
198
throw new NullPointerException(
199
"The key spec to be validated cannot be null");
200
}
201
202
if (keySpec instanceof DHPublicKeySpec) {
203
validateDHPublicKey((DHPublicKeySpec)keySpec);
204
}
205
}
206
207
/**
208
* Returns whether the specified provider is Oracle provider or not.
209
*
210
* @param providerName
211
* the provider name
212
* @return true if, and only if, the provider of the specified
213
* {@code providerName} is Oracle provider
214
*/
215
public static final boolean isOracleJCEProvider(String providerName) {
216
return providerName != null &&
217
(providerName.equals("SunJCE") ||
218
providerName.equals("SunMSCAPI") ||
219
providerName.equals("OracleUcrypto") ||
220
providerName.startsWith("SunPKCS11"));
221
}
222
223
/**
224
* Check the format of TLS PreMasterSecret.
225
* <P>
226
* To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
227
* treating incorrectly formatted message blocks and/or mismatched
228
* version numbers in a manner indistinguishable from correctly
229
* formatted RSA blocks.
230
*
231
* RFC 5246 describes the approach as :
232
*
233
* 1. Generate a string R of 48 random bytes
234
*
235
* 2. Decrypt the message to recover the plaintext M
236
*
237
* 3. If the PKCS#1 padding is not correct, or the length of message
238
* M is not exactly 48 bytes:
239
* pre_master_secret = R
240
* else If ClientHello.client_version <= TLS 1.0, and version
241
* number check is explicitly disabled:
242
* premaster secret = M
243
* else If M[0..1] != ClientHello.client_version:
244
* premaster secret = R
245
* else:
246
* premaster secret = M
247
*
248
* Note that #2 should have completed before the call to this method.
249
*
250
* @param clientVersion the version of the TLS protocol by which the
251
* client wishes to communicate during this session
252
* @param serverVersion the negotiated version of the TLS protocol which
253
* contains the lower of that suggested by the client in the client
254
* hello and the highest supported by the server.
255
* @param encoded the encoded key in its "RAW" encoding format
256
* @param isFailover whether or not the previous decryption of the
257
* encrypted PreMasterSecret message run into problem
258
* @return the polished PreMasterSecret key in its "RAW" encoding format
259
*/
260
public static byte[] checkTlsPreMasterSecretKey(
261
int clientVersion, int serverVersion, SecureRandom random,
262
byte[] encoded, boolean isFailOver) {
263
264
if (random == null) {
265
random = JCAUtil.getSecureRandom();
266
}
267
byte[] replacer = new byte[48];
268
random.nextBytes(replacer);
269
270
if (!isFailOver && (encoded != null)) {
271
// check the length
272
if (encoded.length != 48) {
273
// private, don't need to clone the byte array.
274
return replacer;
275
}
276
277
int encodedVersion =
278
((encoded[0] & 0xFF) << 8) | (encoded[1] & 0xFF);
279
if (clientVersion != encodedVersion) {
280
if (clientVersion > 0x0301 || // 0x0301: TLSv1
281
serverVersion != encodedVersion) {
282
encoded = replacer;
283
} // Otherwise, For compatibility, we maintain the behavior
284
// that the version in pre_master_secret can be the
285
// negotiated version for TLS v1.0 and SSL v3.0.
286
}
287
288
// private, don't need to clone the byte array.
289
return encoded;
290
}
291
292
// private, don't need to clone the byte array.
293
return replacer;
294
}
295
296
/**
297
* Returns whether the Diffie-Hellman public key is valid or not.
298
*
299
* Per RFC 2631 and NIST SP800-56A, the following algorithm is used to
300
* validate Diffie-Hellman public keys:
301
* 1. Verify that y lies within the interval [2,p-1]. If it does not,
302
* the key is invalid.
303
* 2. Compute y^q mod p. If the result == 1, the key is valid.
304
* Otherwise the key is invalid.
305
*/
306
private static void validateDHPublicKey(DHPublicKey publicKey)
307
throws InvalidKeyException {
308
DHParameterSpec paramSpec = publicKey.getParams();
309
310
BigInteger p = paramSpec.getP();
311
BigInteger g = paramSpec.getG();
312
BigInteger y = publicKey.getY();
313
314
validateDHPublicKey(p, g, y);
315
}
316
317
private static void validateDHPublicKey(DHPublicKeySpec publicKeySpec)
318
throws InvalidKeyException {
319
validateDHPublicKey(publicKeySpec.getP(),
320
publicKeySpec.getG(), publicKeySpec.getY());
321
}
322
323
private static void validateDHPublicKey(BigInteger p,
324
BigInteger g, BigInteger y) throws InvalidKeyException {
325
326
// For better interoperability, the interval is limited to [2, p-2].
327
BigInteger leftOpen = BigInteger.ONE;
328
BigInteger rightOpen = p.subtract(BigInteger.ONE);
329
if (y.compareTo(leftOpen) <= 0) {
330
throw new InvalidKeyException(
331
"Diffie-Hellman public key is too small");
332
}
333
if (y.compareTo(rightOpen) >= 0) {
334
throw new InvalidKeyException(
335
"Diffie-Hellman public key is too large");
336
}
337
338
// y^q mod p == 1?
339
// Unable to perform this check as q is unknown in this circumstance.
340
341
// p is expected to be prime. However, it is too expensive to check
342
// that p is prime. Instead, in order to mitigate the impact of
343
// non-prime values, we check that y is not a factor of p.
344
BigInteger r = p.remainder(y);
345
if (r.equals(BigInteger.ZERO)) {
346
throw new InvalidKeyException("Invalid Diffie-Hellman parameters");
347
}
348
}
349
350
/**
351
* Trim leading (most significant) zeroes from the result.
352
*
353
* @throws NullPointerException if {@code b} is null
354
*/
355
public static byte[] trimZeroes(byte[] b) {
356
int i = 0;
357
while ((i < b.length - 1) && (b[i] == 0)) {
358
i++;
359
}
360
if (i == 0) {
361
return b;
362
}
363
byte[] t = new byte[b.length - i];
364
System.arraycopy(b, i, t, 0, t.length);
365
return t;
366
}
367
368
}
369
370
371