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/P11KeyGenerator.java
41154 views
1
/*
2
* Copyright (c) 2003, 2021, 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.security.*;
29
import java.security.spec.AlgorithmParameterSpec;
30
31
import javax.crypto.*;
32
33
import static sun.security.pkcs11.TemplateManager.*;
34
import sun.security.pkcs11.wrapper.*;
35
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
36
37
/**
38
* KeyGenerator implementation class. This class currently supports
39
* DES, DESede, AES, ARCFOUR, Blowfish, Hmac using MD5, SHA, SHA-2 family
40
* (SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256), and SHA-3
41
* family (SHA3-224, SHA3-256, SHA3-384, SHA3-512) of digests.
42
*
43
* @author Andreas Sterbenz
44
* @since 1.5
45
*/
46
final class P11KeyGenerator extends KeyGeneratorSpi {
47
48
// token instance
49
private final Token token;
50
51
// algorithm name
52
private final String algorithm;
53
54
// mechanism id
55
private long mechanism;
56
57
// raw key size in bits, e.g. 64 for DES. Always valid.
58
private int keySize;
59
60
// bits of entropy in the key, e.g. 56 for DES. Always valid.
61
private int significantKeySize;
62
63
// keyType (CKK_*), needed for TemplateManager call only.
64
private long keyType;
65
66
// for determining if both 112 and 168 bits of DESede key lengths
67
// are supported.
68
private boolean supportBothKeySizes;
69
70
// for determining if the specified key size is valid
71
private final CK_MECHANISM_INFO range;
72
73
// utility method for query the native key sizes and enforcing the
74
// java-specific lower limit; returned values are in bits
75
private static CK_MECHANISM_INFO getSupportedRange(Token token,
76
long mech) throws ProviderException {
77
// No need to query for fix-length algorithms
78
if (mech == CKM_DES_KEY_GEN || mech == CKM_DES2_KEY_GEN ||
79
mech == CKM_DES3_KEY_GEN) {
80
return null;
81
}
82
83
// Explicitly disallow keys shorter than 40-bits for security
84
int lower = 40;
85
int upper = Integer.MAX_VALUE;
86
try {
87
CK_MECHANISM_INFO info = token.getMechanismInfo(mech);
88
if (info != null) {
89
boolean isBytes = ((mech != CKM_GENERIC_SECRET_KEY_GEN
90
&& mech != CKM_RC4_KEY_GEN) || info.iMinKeySize < 8);
91
lower = Math.max(lower, (isBytes?
92
Math.multiplyExact(info.iMinKeySize, 8) :
93
info.iMinKeySize));
94
// NSS CKM_GENERIC_SECRET_KEY_GEN mech info is not precise;
95
// its upper limit is too low and does not match its impl
96
if (mech == CKM_GENERIC_SECRET_KEY_GEN &&
97
info.iMaxKeySize <= 32) {
98
// ignore and leave upper limit at MAX_VALUE;
99
} else if (info.iMaxKeySize != Integer.MAX_VALUE) {
100
upper = (isBytes?
101
Math.multiplyExact(info.iMaxKeySize, 8) :
102
info.iMaxKeySize);
103
}
104
}
105
} catch (PKCS11Exception p11e) {
106
// Should never happen
107
throw new ProviderException("Cannot retrieve mechanism info", p11e);
108
}
109
return new CK_MECHANISM_INFO(lower, upper, 0 /* flags not used */);
110
}
111
112
/**
113
* Utility method for checking if the specified key size is valid
114
* and within the supported range. Return the significant key size
115
* upon successful validation.
116
* @param keyGenMech the PKCS#11 key generation mechanism.
117
* @param keySize the to-be-checked key size for this mechanism.
118
* @param token token which provides this mechanism.
119
* @return the significant key size (in bits) corresponding to the
120
* specified key size.
121
* @throws InvalidParameterException if the specified key size is invalid.
122
* @throws ProviderException if this mechanism isn't supported by SunPKCS11
123
* or underlying native impl.
124
*/
125
// called by P11SecretKeyFactory to check key size
126
static int checkKeySize(long keyGenMech, int keySize, Token token)
127
throws InvalidAlgorithmParameterException, ProviderException {
128
CK_MECHANISM_INFO range = getSupportedRange(token, keyGenMech);
129
return checkKeySize(keyGenMech, keySize, range);
130
}
131
132
private static int checkKeySize(long keyGenMech, int keySize,
133
CK_MECHANISM_INFO range) throws InvalidAlgorithmParameterException {
134
int sigKeySize;
135
switch ((int)keyGenMech) {
136
case (int)CKM_DES_KEY_GEN:
137
if ((keySize != 64) && (keySize != 56)) {
138
throw new InvalidAlgorithmParameterException
139
("DES key length must be 56 bits");
140
}
141
sigKeySize = 56;
142
break;
143
case (int)CKM_DES2_KEY_GEN:
144
case (int)CKM_DES3_KEY_GEN:
145
if ((keySize == 112) || (keySize == 128)) {
146
sigKeySize = 112;
147
} else if ((keySize == 168) || (keySize == 192)) {
148
sigKeySize = 168;
149
} else {
150
throw new InvalidAlgorithmParameterException
151
("DESede key length must be 112, or 168 bits");
152
}
153
break;
154
default:
155
// Handle all variable-key-length algorithms here
156
if (range != null && keySize < range.iMinKeySize
157
|| keySize > range.iMaxKeySize) {
158
throw new InvalidAlgorithmParameterException
159
("Key length must be between " + range.iMinKeySize +
160
" and " + range.iMaxKeySize + " bits");
161
}
162
if (keyGenMech == CKM_AES_KEY_GEN) {
163
if ((keySize != 128) && (keySize != 192) &&
164
(keySize != 256)) {
165
throw new InvalidAlgorithmParameterException
166
("AES key length must be 128, 192, or 256 bits");
167
}
168
}
169
sigKeySize = keySize;
170
}
171
return sigKeySize;
172
}
173
174
// check the supplied keysize (in bits) and adjust it based on the given
175
// range
176
private static int adjustKeySize(int ks, CK_MECHANISM_INFO mi) {
177
// adjust to fit within the supported range
178
if (mi != null) {
179
if (ks < mi.iMinKeySize) {
180
ks = mi.iMinKeySize;
181
} else if (ks > mi.iMaxKeySize) {
182
ks = mi.iMaxKeySize;
183
}
184
}
185
return ks;
186
}
187
188
P11KeyGenerator(Token token, String algorithm, long mechanism)
189
throws PKCS11Exception {
190
super();
191
this.token = token;
192
this.algorithm = algorithm;
193
this.mechanism = mechanism;
194
195
if (this.mechanism == CKM_DES3_KEY_GEN) {
196
/* Given the current lookup order specified in SunPKCS11.java,
197
if CKM_DES2_KEY_GEN is used to construct this object, it
198
means that CKM_DES3_KEY_GEN is disabled or unsupported.
199
*/
200
supportBothKeySizes =
201
(token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&
202
(token.getMechanismInfo(CKM_DES2_KEY_GEN) != null));
203
}
204
this.range = getSupportedRange(token, mechanism);
205
setDefault();
206
}
207
208
// set default keysize and keyType
209
private void setDefault() {
210
significantKeySize = -1;
211
switch ((int)mechanism) {
212
case (int)CKM_DES_KEY_GEN:
213
keySize = 64;
214
keyType = CKK_DES;
215
significantKeySize = 56;
216
break;
217
case (int)CKM_DES2_KEY_GEN:
218
keySize = 128;
219
keyType = CKK_DES2;
220
significantKeySize = 112;
221
break;
222
case (int)CKM_DES3_KEY_GEN:
223
keySize = 192;
224
keyType = CKK_DES3;
225
significantKeySize = 168;
226
break;
227
case (int)CKM_AES_KEY_GEN:
228
keySize = adjustKeySize(128, range);
229
keyType = CKK_AES;
230
break;
231
case (int)CKM_RC4_KEY_GEN:
232
keySize = adjustKeySize(128, range);
233
keyType = CKK_RC4;
234
break;
235
case (int)CKM_BLOWFISH_KEY_GEN:
236
keySize = adjustKeySize(128, range);
237
keyType = CKK_BLOWFISH;
238
break;
239
case (int)CKM_CHACHA20_KEY_GEN:
240
keySize = 256;
241
keyType = CKK_CHACHA20;
242
break;
243
case (int)CKM_SHA_1_KEY_GEN:
244
keySize = adjustKeySize(160, range);
245
keyType = CKK_SHA_1_HMAC;
246
break;
247
case (int)CKM_SHA224_KEY_GEN:
248
keySize = adjustKeySize(224, range);
249
keyType = CKK_SHA224_HMAC;
250
break;
251
case (int)CKM_SHA256_KEY_GEN:
252
keySize = adjustKeySize(256, range);
253
keyType = CKK_SHA256_HMAC;
254
break;
255
case (int)CKM_SHA384_KEY_GEN:
256
keySize = adjustKeySize(384, range);
257
keyType = CKK_SHA384_HMAC;
258
break;
259
case (int)CKM_SHA512_KEY_GEN:
260
keySize = adjustKeySize(512, range);
261
keyType = CKK_SHA512_HMAC;
262
break;
263
case (int)CKM_SHA512_224_KEY_GEN:
264
keySize = adjustKeySize(224, range);
265
keyType = CKK_SHA512_224_HMAC;
266
break;
267
case (int)CKM_SHA512_256_KEY_GEN:
268
keySize = adjustKeySize(256, range);
269
keyType = CKK_SHA512_256_HMAC;
270
break;
271
case (int)CKM_SHA3_224_KEY_GEN:
272
keySize = adjustKeySize(224, range);
273
keyType = CKK_SHA3_224_HMAC;
274
break;
275
case (int)CKM_SHA3_256_KEY_GEN:
276
keySize = adjustKeySize(256, range);
277
keyType = CKK_SHA3_256_HMAC;
278
break;
279
case (int)CKM_SHA3_384_KEY_GEN:
280
keySize = adjustKeySize(384, range);
281
keyType = CKK_SHA3_384_HMAC;
282
break;
283
case (int)CKM_SHA3_512_KEY_GEN:
284
keySize = adjustKeySize(512, range);
285
keyType = CKK_SHA3_512_HMAC;
286
break;
287
case (int)CKM_GENERIC_SECRET_KEY_GEN:
288
if (algorithm.startsWith("Hmac")) {
289
String digest = algorithm.substring(4);
290
keySize = adjustKeySize(switch (digest) {
291
case "MD5" -> 512;
292
case "SHA1" -> 160;
293
case "SHA224", "SHA512/224", "SHA3-224" -> 224;
294
case "SHA256", "SHA512/256", "SHA3-256" -> 256;
295
case "SHA384", "SHA3-384" -> 384;
296
case "SHA512", "SHA3-512" -> 512;
297
default -> {
298
throw new ProviderException("Unsupported algorithm " +
299
algorithm);
300
}
301
}, range);
302
} else {
303
throw new ProviderException("Unsupported algorithm " +
304
algorithm);
305
}
306
keyType = CKK_GENERIC_SECRET;
307
break;
308
default:
309
throw new ProviderException("Unknown mechanism " + mechanism);
310
}
311
if (significantKeySize == -1) {
312
significantKeySize = keySize;
313
}
314
}
315
316
// see JCE spec
317
protected void engineInit(SecureRandom random) {
318
token.ensureValid();
319
setDefault();
320
}
321
322
// see JCE spec
323
protected void engineInit(AlgorithmParameterSpec params,
324
SecureRandom random) throws InvalidAlgorithmParameterException {
325
throw new InvalidAlgorithmParameterException
326
("AlgorithmParameterSpec not supported");
327
}
328
329
// see JCE spec
330
protected void engineInit(int keySize, SecureRandom random) {
331
token.ensureValid();
332
int newSignificantKeySize;
333
try {
334
newSignificantKeySize = checkKeySize(mechanism, keySize, range);
335
} catch (InvalidAlgorithmParameterException iape) {
336
throw (InvalidParameterException)
337
(new InvalidParameterException().initCause(iape));
338
}
339
if ((mechanism == CKM_DES2_KEY_GEN) ||
340
(mechanism == CKM_DES3_KEY_GEN)) {
341
long newMechanism = (newSignificantKeySize == 112 ?
342
CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN);
343
if (mechanism != newMechanism) {
344
if (supportBothKeySizes) {
345
mechanism = newMechanism;
346
// Adjust keyType to reflect the mechanism change
347
keyType = (mechanism == CKM_DES2_KEY_GEN ?
348
CKK_DES2 : CKK_DES3);
349
} else {
350
throw new InvalidParameterException
351
("Only " + significantKeySize +
352
"-bit DESede is supported");
353
}
354
}
355
}
356
this.keySize = keySize;
357
this.significantKeySize = newSignificantKeySize;
358
}
359
360
// see JCE spec
361
protected SecretKey engineGenerateKey() {
362
Session session = null;
363
try {
364
session = token.getObjSession();
365
CK_ATTRIBUTE[] attributes;
366
367
switch ((int)mechanism) {
368
case (int)CKM_DES_KEY_GEN:
369
case (int)CKM_DES2_KEY_GEN:
370
case (int)CKM_DES3_KEY_GEN:
371
// fixed length, do not specify CKA_VALUE_LEN
372
attributes = new CK_ATTRIBUTE[] {
373
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
374
};
375
break;
376
default:
377
attributes = new CK_ATTRIBUTE[] {
378
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
379
new CK_ATTRIBUTE(CKA_VALUE_LEN, keySize >> 3),
380
};
381
break;
382
}
383
attributes = token.getAttributes
384
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
385
long keyID = token.p11.C_GenerateKey
386
(session.id(), new CK_MECHANISM(mechanism), attributes);
387
return P11Key.secretKey
388
(session, keyID, algorithm, significantKeySize, attributes);
389
} catch (PKCS11Exception e) {
390
throw new ProviderException("Could not generate key", e);
391
} finally {
392
token.releaseSession(session);
393
}
394
}
395
}
396
397