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/pkcs11/P11KeyPairGenerator.java
38919 views
1
/*
2
* Copyright (c) 2003, 2017, 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.pkcs11;
27
28
import java.math.BigInteger;
29
30
import java.security.*;
31
import java.security.spec.*;
32
33
import javax.crypto.spec.DHParameterSpec;
34
35
import sun.security.provider.ParameterCache;
36
import static sun.security.util.SecurityProviderConstants.*;
37
38
import static sun.security.pkcs11.TemplateManager.*;
39
import sun.security.pkcs11.wrapper.*;
40
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
41
42
43
import sun.security.rsa.RSAKeyFactory;
44
45
/**
46
* KeyPairGenerator implementation class. This class currently supports
47
* RSA, DSA, DH, and EC.
48
*
49
* Note that for DSA and DH we rely on the Sun and SunJCE providers to
50
* obtain the parameters from.
51
*
52
* @author Andreas Sterbenz
53
* @since 1.5
54
*/
55
final class P11KeyPairGenerator extends KeyPairGeneratorSpi {
56
57
// token instance
58
private final Token token;
59
60
// algorithm name
61
private final String algorithm;
62
63
// mechanism id
64
private final long mechanism;
65
66
// selected or default key size, always valid
67
private int keySize;
68
69
// parameters specified via init, if any
70
private AlgorithmParameterSpec params;
71
72
// for RSA, selected or default value of public exponent, always valid
73
private BigInteger rsaPublicExponent = RSAKeyGenParameterSpec.F4;
74
75
// the supported keysize range of the native PKCS11 library
76
// if the value cannot be retrieved or unspecified, -1 is used.
77
private final int minKeySize;
78
private final int maxKeySize;
79
80
// SecureRandom instance, if specified in init
81
private SecureRandom random;
82
83
P11KeyPairGenerator(Token token, String algorithm, long mechanism)
84
throws PKCS11Exception {
85
super();
86
int minKeyLen = -1;
87
int maxKeyLen = -1;
88
try {
89
CK_MECHANISM_INFO mechInfo = token.getMechanismInfo(mechanism);
90
if (mechInfo != null) {
91
minKeyLen = (int) mechInfo.ulMinKeySize;
92
maxKeyLen = (int) mechInfo.ulMaxKeySize;
93
}
94
} catch (PKCS11Exception p11e) {
95
// Should never happen
96
throw new ProviderException
97
("Unexpected error while getting mechanism info", p11e);
98
}
99
// set default key sizes and apply our own algorithm-specific limits
100
// override lower limit to disallow unsecure keys being generated
101
// override upper limit to deter DOS attack
102
if (algorithm.equals("EC")) {
103
keySize = DEF_EC_KEY_SIZE;
104
if ((minKeyLen == -1) || (minKeyLen < 112)) {
105
minKeyLen = 112;
106
}
107
if ((maxKeyLen == -1) || (maxKeyLen > 2048)) {
108
maxKeyLen = 2048;
109
}
110
} else {
111
if (algorithm.equals("DSA")) {
112
keySize = DEF_DSA_KEY_SIZE;
113
} else if (algorithm.equals("RSA")) {
114
keySize = DEF_RSA_KEY_SIZE;
115
} else {
116
keySize = DEF_DH_KEY_SIZE;
117
}
118
if ((minKeyLen == -1) || (minKeyLen < 512)) {
119
minKeyLen = 512;
120
}
121
if (algorithm.equals("RSA")) {
122
if ((maxKeyLen == -1) || (maxKeyLen > 64 * 1024)) {
123
maxKeyLen = 64 * 1024;
124
}
125
}
126
}
127
128
// auto-adjust default keysize in case it's out-of-range
129
if ((minKeyLen != -1) && (keySize < minKeyLen)) {
130
keySize = minKeyLen;
131
}
132
if ((maxKeyLen != -1) && (keySize > maxKeyLen)) {
133
keySize = maxKeyLen;
134
}
135
this.token = token;
136
this.algorithm = algorithm;
137
this.mechanism = mechanism;
138
this.minKeySize = minKeyLen;
139
this.maxKeySize = maxKeyLen;
140
initialize(keySize, null);
141
}
142
143
// see JCA spec
144
@Override
145
public void initialize(int keySize, SecureRandom random) {
146
token.ensureValid();
147
try {
148
checkKeySize(keySize, null);
149
} catch (InvalidAlgorithmParameterException e) {
150
throw new InvalidParameterException(e.getMessage());
151
}
152
this.params = null;
153
if (algorithm.equals("EC")) {
154
params = P11ECKeyFactory.getECParameterSpec(keySize);
155
if (params == null) {
156
throw new InvalidParameterException(
157
"No EC parameters available for key size "
158
+ keySize + " bits");
159
}
160
}
161
this.keySize = keySize;
162
this.random = random;
163
}
164
165
// see JCA spec
166
@Override
167
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
168
throws InvalidAlgorithmParameterException {
169
token.ensureValid();
170
int tmpKeySize;
171
if (algorithm.equals("DH")) {
172
if (params instanceof DHParameterSpec == false) {
173
throw new InvalidAlgorithmParameterException
174
("DHParameterSpec required for Diffie-Hellman");
175
}
176
DHParameterSpec dhParams = (DHParameterSpec) params;
177
tmpKeySize = dhParams.getP().bitLength();
178
checkKeySize(tmpKeySize, dhParams);
179
// XXX sanity check params
180
} else if (algorithm.equals("RSA")) {
181
if (params instanceof RSAKeyGenParameterSpec == false) {
182
throw new InvalidAlgorithmParameterException
183
("RSAKeyGenParameterSpec required for RSA");
184
}
185
RSAKeyGenParameterSpec rsaParams =
186
(RSAKeyGenParameterSpec) params;
187
tmpKeySize = rsaParams.getKeysize();
188
checkKeySize(tmpKeySize, rsaParams);
189
// override the supplied params to null
190
params = null;
191
this.rsaPublicExponent = rsaParams.getPublicExponent();
192
// XXX sanity check params
193
} else if (algorithm.equals("DSA")) {
194
if (params instanceof DSAParameterSpec == false) {
195
throw new InvalidAlgorithmParameterException
196
("DSAParameterSpec required for DSA");
197
}
198
DSAParameterSpec dsaParams = (DSAParameterSpec) params;
199
tmpKeySize = dsaParams.getP().bitLength();
200
checkKeySize(tmpKeySize, dsaParams);
201
// XXX sanity check params
202
} else if (algorithm.equals("EC")) {
203
ECParameterSpec ecParams;
204
if (params instanceof ECParameterSpec) {
205
ecParams = P11ECKeyFactory.getECParameterSpec(
206
(ECParameterSpec)params);
207
if (ecParams == null) {
208
throw new InvalidAlgorithmParameterException
209
("Unsupported curve: " + params);
210
}
211
} else if (params instanceof ECGenParameterSpec) {
212
String name = ((ECGenParameterSpec) params).getName();
213
ecParams = P11ECKeyFactory.getECParameterSpec(name);
214
if (ecParams == null) {
215
throw new InvalidAlgorithmParameterException
216
("Unknown curve name: " + name);
217
}
218
// override the supplied params with the derived one
219
params = ecParams;
220
} else {
221
throw new InvalidAlgorithmParameterException
222
("ECParameterSpec or ECGenParameterSpec required for EC");
223
}
224
tmpKeySize = ecParams.getCurve().getField().getFieldSize();
225
checkKeySize(tmpKeySize, ecParams);
226
} else {
227
throw new ProviderException("Unknown algorithm: " + algorithm);
228
}
229
this.keySize = tmpKeySize;
230
this.params = params;
231
this.random = random;
232
}
233
234
private void checkKeySize(int keySize, AlgorithmParameterSpec params)
235
throws InvalidAlgorithmParameterException {
236
// check native range first
237
if ((minKeySize != -1) && (keySize < minKeySize)) {
238
throw new InvalidAlgorithmParameterException(algorithm +
239
" key must be at least " + minKeySize + " bits. " +
240
"The specific key size " + keySize + " is not supported");
241
}
242
if ((maxKeySize != -1) && (keySize > maxKeySize)) {
243
throw new InvalidAlgorithmParameterException(algorithm +
244
" key must be at most " + maxKeySize + " bits. " +
245
"The specific key size " + keySize + " is not supported");
246
}
247
248
// check our own algorithm-specific limits also
249
if (algorithm.equals("EC")) {
250
if (keySize < 112) {
251
throw new InvalidAlgorithmParameterException(
252
"EC key size must be at least 112 bit. " +
253
"The specific key size " + keySize + " is not supported");
254
}
255
if (keySize > 2048) {
256
// sanity check, nobody really wants keys this large
257
throw new InvalidAlgorithmParameterException(
258
"EC key size must be at most 2048 bit. " +
259
"The specific key size " + keySize + " is not supported");
260
}
261
} else {
262
// RSA, DH, DSA
263
if (keySize < 512) {
264
throw new InvalidAlgorithmParameterException(algorithm +
265
" key size must be at least 512 bit. " +
266
"The specific key size " + keySize + " is not supported");
267
}
268
if (algorithm.equals("RSA")) {
269
BigInteger tmpExponent = rsaPublicExponent;
270
if (params != null) {
271
tmpExponent =
272
((RSAKeyGenParameterSpec)params).getPublicExponent();
273
}
274
try {
275
// Reuse the checking in SunRsaSign provider.
276
// If maxKeySize is -1, then replace it with
277
// Integer.MAX_VALUE to indicate no limit.
278
RSAKeyFactory.checkKeyLengths(keySize, tmpExponent,
279
minKeySize,
280
(maxKeySize==-1? Integer.MAX_VALUE:maxKeySize));
281
} catch (InvalidKeyException e) {
282
throw new InvalidAlgorithmParameterException(e);
283
}
284
} else if (algorithm.equals("DH")) {
285
if (params != null) { // initialized with specified parameters
286
// sanity check, nobody really wants keys this large
287
if (keySize > 64 * 1024) {
288
throw new InvalidAlgorithmParameterException(
289
"DH key size must be at most 65536 bit. " +
290
"The specific key size " +
291
keySize + " is not supported");
292
}
293
} else { // default parameters will be used.
294
// Range is based on the values in
295
// sun.security.provider.ParameterCache class.
296
if ((keySize > 8192) || (keySize < 512) ||
297
((keySize & 0x3f) != 0)) {
298
throw new InvalidAlgorithmParameterException(
299
"DH key size must be multiple of 64, and can " +
300
"only range from 512 to 8192 (inclusive). " +
301
"The specific key size " +
302
keySize + " is not supported");
303
}
304
305
DHParameterSpec cache =
306
ParameterCache.getCachedDHParameterSpec(keySize);
307
// Except 2048 and 3072, not yet support generation of
308
// parameters bigger than 1024 bits.
309
if ((cache == null) && (keySize > 1024)) {
310
throw new InvalidAlgorithmParameterException(
311
"Unsupported " + keySize +
312
"-bit DH parameter generation");
313
}
314
}
315
} else {
316
// this restriction is in the spec for DSA
317
if ((keySize != 3072) && (keySize != 2048) &&
318
((keySize > 1024) || ((keySize & 0x3f) != 0))) {
319
throw new InvalidAlgorithmParameterException(
320
"DSA key must be multiples of 64 if less than " +
321
"1024 bits, or 2048, 3072 bits. " +
322
"The specific key size " +
323
keySize + " is not supported");
324
}
325
}
326
}
327
}
328
329
// see JCA spec
330
@Override
331
public KeyPair generateKeyPair() {
332
token.ensureValid();
333
CK_ATTRIBUTE[] publicKeyTemplate;
334
CK_ATTRIBUTE[] privateKeyTemplate;
335
long keyType;
336
if (algorithm.equals("RSA")) {
337
keyType = CKK_RSA;
338
publicKeyTemplate = new CK_ATTRIBUTE[] {
339
new CK_ATTRIBUTE(CKA_MODULUS_BITS, keySize),
340
new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT, rsaPublicExponent),
341
};
342
privateKeyTemplate = new CK_ATTRIBUTE[] {
343
// empty
344
};
345
} else if (algorithm.equals("DSA")) {
346
keyType = CKK_DSA;
347
DSAParameterSpec dsaParams;
348
if (params == null) {
349
try {
350
dsaParams = ParameterCache.getDSAParameterSpec
351
(keySize, random);
352
} catch (GeneralSecurityException e) {
353
throw new ProviderException
354
("Could not generate DSA parameters", e);
355
}
356
} else {
357
dsaParams = (DSAParameterSpec)params;
358
}
359
publicKeyTemplate = new CK_ATTRIBUTE[] {
360
new CK_ATTRIBUTE(CKA_PRIME, dsaParams.getP()),
361
new CK_ATTRIBUTE(CKA_SUBPRIME, dsaParams.getQ()),
362
new CK_ATTRIBUTE(CKA_BASE, dsaParams.getG()),
363
};
364
privateKeyTemplate = new CK_ATTRIBUTE[] {
365
// empty
366
};
367
} else if (algorithm.equals("DH")) {
368
keyType = CKK_DH;
369
DHParameterSpec dhParams;
370
int privateBits;
371
if (params == null) {
372
try {
373
dhParams = ParameterCache.getDHParameterSpec
374
(keySize, random);
375
} catch (GeneralSecurityException e) {
376
throw new ProviderException
377
("Could not generate DH parameters", e);
378
}
379
privateBits = 0;
380
} else {
381
dhParams = (DHParameterSpec)params;
382
privateBits = dhParams.getL();
383
}
384
if (privateBits <= 0) {
385
// XXX find better defaults
386
privateBits = (keySize >= 1024) ? 768 : 512;
387
}
388
publicKeyTemplate = new CK_ATTRIBUTE[] {
389
new CK_ATTRIBUTE(CKA_PRIME, dhParams.getP()),
390
new CK_ATTRIBUTE(CKA_BASE, dhParams.getG())
391
};
392
privateKeyTemplate = new CK_ATTRIBUTE[] {
393
new CK_ATTRIBUTE(CKA_VALUE_BITS, privateBits),
394
};
395
} else if (algorithm.equals("EC")) {
396
keyType = CKK_EC;
397
byte[] encodedParams =
398
P11ECKeyFactory.encodeParameters((ECParameterSpec)params);
399
publicKeyTemplate = new CK_ATTRIBUTE[] {
400
new CK_ATTRIBUTE(CKA_EC_PARAMS, encodedParams),
401
};
402
privateKeyTemplate = new CK_ATTRIBUTE[] {
403
// empty
404
};
405
} else {
406
throw new ProviderException("Unknown algorithm: " + algorithm);
407
}
408
Session session = null;
409
try {
410
session = token.getObjSession();
411
publicKeyTemplate = token.getAttributes
412
(O_GENERATE, CKO_PUBLIC_KEY, keyType, publicKeyTemplate);
413
privateKeyTemplate = token.getAttributes
414
(O_GENERATE, CKO_PRIVATE_KEY, keyType, privateKeyTemplate);
415
long[] keyIDs = token.p11.C_GenerateKeyPair
416
(session.id(), new CK_MECHANISM(mechanism),
417
publicKeyTemplate, privateKeyTemplate);
418
PublicKey publicKey = P11Key.publicKey
419
(session, keyIDs[0], algorithm, keySize, publicKeyTemplate);
420
PrivateKey privateKey = P11Key.privateKey
421
(session, keyIDs[1], algorithm, keySize, privateKeyTemplate);
422
return new KeyPair(publicKey, privateKey);
423
} catch (PKCS11Exception e) {
424
throw new ProviderException(e);
425
} finally {
426
token.releaseSession(session);
427
}
428
}
429
}
430
431