Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java
41154 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.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 mechanism info is unavailable, 0/Integer.MAX_VALUE 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 = 0;
87
int maxKeyLen = Integer.MAX_VALUE;
88
try {
89
CK_MECHANISM_INFO mechInfo = token.getMechanismInfo(mechanism);
90
if (mechInfo != null) {
91
minKeyLen = mechInfo.iMinKeySize;
92
maxKeyLen = mechInfo.iMaxKeySize;
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 < 112) {
105
minKeyLen = 112;
106
}
107
if (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
if (maxKeyLen > 64 * 1024) {
116
maxKeyLen = 64 * 1024;
117
}
118
} else {
119
keySize = DEF_DH_KEY_SIZE;
120
}
121
if (minKeyLen < 512) {
122
minKeyLen = 512;
123
}
124
}
125
126
// auto-adjust default keysize in case it's out-of-range
127
if (keySize < minKeyLen) {
128
keySize = minKeyLen;
129
}
130
if (keySize > maxKeyLen) {
131
keySize = maxKeyLen;
132
}
133
this.token = token;
134
this.algorithm = algorithm;
135
this.mechanism = mechanism;
136
this.minKeySize = minKeyLen;
137
this.maxKeySize = maxKeyLen;
138
initialize(keySize, null);
139
}
140
141
// see JCA spec
142
@Override
143
public void initialize(int keySize, SecureRandom random) {
144
token.ensureValid();
145
try {
146
checkKeySize(keySize, null);
147
} catch (InvalidAlgorithmParameterException e) {
148
throw new InvalidParameterException(e.getMessage());
149
}
150
this.params = null;
151
if (algorithm.equals("EC")) {
152
params = P11ECKeyFactory.getECParameterSpec(keySize);
153
if (params == null) {
154
throw new InvalidParameterException(
155
"No EC parameters available for key size "
156
+ keySize + " bits");
157
}
158
}
159
this.keySize = keySize;
160
this.random = random;
161
}
162
163
// see JCA spec
164
@Override
165
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
166
throws InvalidAlgorithmParameterException {
167
token.ensureValid();
168
int tmpKeySize;
169
if (algorithm.equals("DH")) {
170
if (params instanceof DHParameterSpec == false) {
171
throw new InvalidAlgorithmParameterException
172
("DHParameterSpec required for Diffie-Hellman");
173
}
174
DHParameterSpec dhParams = (DHParameterSpec) params;
175
tmpKeySize = dhParams.getP().bitLength();
176
checkKeySize(tmpKeySize, dhParams);
177
// XXX sanity check params
178
} else if (algorithm.equals("RSA")) {
179
if (params instanceof RSAKeyGenParameterSpec == false) {
180
throw new InvalidAlgorithmParameterException
181
("RSAKeyGenParameterSpec required for RSA");
182
}
183
RSAKeyGenParameterSpec rsaParams =
184
(RSAKeyGenParameterSpec) params;
185
tmpKeySize = rsaParams.getKeysize();
186
checkKeySize(tmpKeySize, rsaParams);
187
// override the supplied params to null
188
params = null;
189
this.rsaPublicExponent = rsaParams.getPublicExponent();
190
// XXX sanity check params
191
} else if (algorithm.equals("DSA")) {
192
if (params instanceof DSAParameterSpec == false) {
193
throw new InvalidAlgorithmParameterException
194
("DSAParameterSpec required for DSA");
195
}
196
DSAParameterSpec dsaParams = (DSAParameterSpec) params;
197
tmpKeySize = dsaParams.getP().bitLength();
198
checkKeySize(tmpKeySize, dsaParams);
199
// XXX sanity check params
200
} else if (algorithm.equals("EC")) {
201
ECParameterSpec ecParams;
202
if (params instanceof ECParameterSpec) {
203
ecParams = P11ECKeyFactory.getECParameterSpec(
204
(ECParameterSpec)params);
205
if (ecParams == null) {
206
throw new InvalidAlgorithmParameterException
207
("Unsupported curve: " + params);
208
}
209
} else if (params instanceof ECGenParameterSpec) {
210
String name = ((ECGenParameterSpec) params).getName();
211
ecParams = P11ECKeyFactory.getECParameterSpec(name);
212
if (ecParams == null) {
213
throw new InvalidAlgorithmParameterException
214
("Unknown curve name: " + name);
215
}
216
// override the supplied params with the derived one
217
params = ecParams;
218
} else {
219
throw new InvalidAlgorithmParameterException
220
("ECParameterSpec or ECGenParameterSpec required for EC");
221
}
222
tmpKeySize = ecParams.getCurve().getField().getFieldSize();
223
checkKeySize(tmpKeySize, ecParams);
224
} else {
225
throw new ProviderException("Unknown algorithm: " + algorithm);
226
}
227
this.keySize = tmpKeySize;
228
this.params = params;
229
this.random = random;
230
}
231
232
private void checkKeySize(int keySize, AlgorithmParameterSpec params)
233
throws InvalidAlgorithmParameterException {
234
if (keySize <= 0) {
235
throw new InvalidAlgorithmParameterException
236
("key size must be positive, got " + keySize);
237
}
238
// check native range first
239
if (keySize < minKeySize) {
240
throw new InvalidAlgorithmParameterException(algorithm +
241
" key must be at least " + minKeySize + " bits. " +
242
"The specific key size " + keySize + " is not supported");
243
}
244
if (keySize > maxKeySize) {
245
throw new InvalidAlgorithmParameterException(algorithm +
246
" key must be at most " + maxKeySize + " bits. " +
247
"The specific key size " + keySize + " is not supported");
248
}
249
250
// check our own algorithm-specific limits also
251
if (algorithm.equals("EC")) {
252
if (keySize < 112) {
253
throw new InvalidAlgorithmParameterException(
254
"EC key size must be at least 112 bit. " +
255
"The specific key size " + keySize + " is not supported");
256
}
257
if (keySize > 2048) {
258
// sanity check, nobody really wants keys this large
259
throw new InvalidAlgorithmParameterException(
260
"EC key size must be at most 2048 bit. " +
261
"The specific key size " + keySize + " is not supported");
262
}
263
} else {
264
// RSA, DH, DSA
265
if (keySize < 512) {
266
throw new InvalidAlgorithmParameterException(algorithm +
267
" key size must be at least 512 bit. " +
268
"The specific key size " + keySize + " is not supported");
269
}
270
if (algorithm.equals("RSA")) {
271
BigInteger tmpExponent = rsaPublicExponent;
272
if (params != null) {
273
tmpExponent =
274
((RSAKeyGenParameterSpec)params).getPublicExponent();
275
}
276
try {
277
RSAKeyFactory.checkKeyLengths(keySize, tmpExponent,
278
minKeySize, maxKeySize);
279
} catch (InvalidKeyException e) {
280
throw new InvalidAlgorithmParameterException(e);
281
}
282
} else if (algorithm.equals("DH")) {
283
if (params != null) { // initialized with specified parameters
284
// sanity check, nobody really wants keys this large
285
if (keySize > 64 * 1024) {
286
throw new InvalidAlgorithmParameterException(
287
"DH key size must be at most 65536 bit. " +
288
"The specific key size " +
289
keySize + " is not supported");
290
}
291
} else { // default parameters will be used.
292
// Range is based on the values in
293
// sun.security.provider.ParameterCache class.
294
if ((keySize > 8192) || (keySize < 512) ||
295
((keySize & 0x3f) != 0)) {
296
throw new InvalidAlgorithmParameterException(
297
"DH key size must be multiple of 64, and can " +
298
"only range from 512 to 8192 (inclusive). " +
299
"The specific key size " +
300
keySize + " is not supported");
301
}
302
303
DHParameterSpec cache =
304
ParameterCache.getCachedDHParameterSpec(keySize);
305
// Except 2048 and 3072, not yet support generation of
306
// parameters bigger than 1024 bits.
307
if ((cache == null) && (keySize > 1024)) {
308
throw new InvalidAlgorithmParameterException(
309
"Unsupported " + keySize +
310
"-bit DH parameter generation");
311
}
312
}
313
} else {
314
// this restriction is in the spec for DSA
315
if ((keySize != 3072) && (keySize != 2048) &&
316
((keySize > 1024) || ((keySize & 0x3f) != 0))) {
317
throw new InvalidAlgorithmParameterException(
318
"DSA key must be multiples of 64 if less than " +
319
"1024 bits, or 2048, 3072 bits. " +
320
"The specific key size " +
321
keySize + " is not supported");
322
}
323
}
324
}
325
}
326
327
// see JCA spec
328
@Override
329
public KeyPair generateKeyPair() {
330
token.ensureValid();
331
CK_ATTRIBUTE[] publicKeyTemplate;
332
CK_ATTRIBUTE[] privateKeyTemplate;
333
long keyType;
334
if (algorithm.equals("RSA")) {
335
keyType = CKK_RSA;
336
publicKeyTemplate = new CK_ATTRIBUTE[] {
337
new CK_ATTRIBUTE(CKA_MODULUS_BITS, keySize),
338
new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT, rsaPublicExponent),
339
};
340
privateKeyTemplate = new CK_ATTRIBUTE[] {
341
// empty
342
};
343
} else if (algorithm.equals("DSA")) {
344
keyType = CKK_DSA;
345
DSAParameterSpec dsaParams;
346
if (params == null) {
347
try {
348
dsaParams = ParameterCache.getDSAParameterSpec
349
(keySize, random);
350
} catch (GeneralSecurityException e) {
351
throw new ProviderException
352
("Could not generate DSA parameters", e);
353
}
354
} else {
355
dsaParams = (DSAParameterSpec)params;
356
}
357
publicKeyTemplate = new CK_ATTRIBUTE[] {
358
new CK_ATTRIBUTE(CKA_PRIME, dsaParams.getP()),
359
new CK_ATTRIBUTE(CKA_SUBPRIME, dsaParams.getQ()),
360
new CK_ATTRIBUTE(CKA_BASE, dsaParams.getG()),
361
};
362
privateKeyTemplate = new CK_ATTRIBUTE[] {
363
// empty
364
};
365
} else if (algorithm.equals("DH")) {
366
keyType = CKK_DH;
367
DHParameterSpec dhParams;
368
int privateBits;
369
if (params == null) {
370
try {
371
dhParams = ParameterCache.getDHParameterSpec
372
(keySize, random);
373
} catch (GeneralSecurityException e) {
374
throw new ProviderException
375
("Could not generate DH parameters", e);
376
}
377
privateBits = 0;
378
} else {
379
dhParams = (DHParameterSpec)params;
380
privateBits = dhParams.getL();
381
}
382
if (privateBits <= 0) {
383
// XXX find better defaults
384
privateBits = (keySize >= 1024) ? 768 : 512;
385
}
386
publicKeyTemplate = new CK_ATTRIBUTE[] {
387
new CK_ATTRIBUTE(CKA_PRIME, dhParams.getP()),
388
new CK_ATTRIBUTE(CKA_BASE, dhParams.getG())
389
};
390
privateKeyTemplate = new CK_ATTRIBUTE[] {
391
new CK_ATTRIBUTE(CKA_VALUE_BITS, privateBits),
392
};
393
} else if (algorithm.equals("EC")) {
394
keyType = CKK_EC;
395
byte[] encodedParams =
396
P11ECKeyFactory.encodeParameters((ECParameterSpec)params);
397
publicKeyTemplate = new CK_ATTRIBUTE[] {
398
new CK_ATTRIBUTE(CKA_EC_PARAMS, encodedParams),
399
};
400
privateKeyTemplate = new CK_ATTRIBUTE[] {
401
// empty
402
};
403
} else {
404
throw new ProviderException("Unknown algorithm: " + algorithm);
405
}
406
Session session = null;
407
try {
408
session = token.getObjSession();
409
publicKeyTemplate = token.getAttributes
410
(O_GENERATE, CKO_PUBLIC_KEY, keyType, publicKeyTemplate);
411
privateKeyTemplate = token.getAttributes
412
(O_GENERATE, CKO_PRIVATE_KEY, keyType, privateKeyTemplate);
413
long[] keyIDs = token.p11.C_GenerateKeyPair
414
(session.id(), new CK_MECHANISM(mechanism),
415
publicKeyTemplate, privateKeyTemplate);
416
PublicKey publicKey = P11Key.publicKey
417
(session, keyIDs[0], algorithm, keySize, publicKeyTemplate);
418
PrivateKey privateKey = P11Key.privateKey
419
(session, keyIDs[1], algorithm, keySize, privateKeyTemplate);
420
return new KeyPair(publicKey, privateKey);
421
} catch (PKCS11Exception e) {
422
throw new ProviderException(e);
423
} finally {
424
token.releaseSession(session);
425
}
426
}
427
}
428
429