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/P11SecretKeyFactory.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.util.*;
29
30
import java.security.*;
31
import java.security.spec.*;
32
33
import javax.crypto.*;
34
import javax.crypto.spec.*;
35
36
import static sun.security.pkcs11.TemplateManager.*;
37
import sun.security.pkcs11.wrapper.*;
38
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
39
40
/**
41
* SecretKeyFactory implementation class. This class currently supports
42
* DES, DESede, AES, ARCFOUR, and Blowfish.
43
*
44
* @author Andreas Sterbenz
45
* @since 1.5
46
*/
47
final class P11SecretKeyFactory extends SecretKeyFactorySpi {
48
49
// token instance
50
private final Token token;
51
52
// algorithm name
53
private final String algorithm;
54
55
P11SecretKeyFactory(Token token, String algorithm) {
56
super();
57
this.token = token;
58
this.algorithm = algorithm;
59
}
60
61
private static final Map<String,Long> keyTypes;
62
63
static {
64
keyTypes = new HashMap<String,Long>();
65
addKeyType("RC4", CKK_RC4);
66
addKeyType("ARCFOUR", CKK_RC4);
67
addKeyType("DES", CKK_DES);
68
addKeyType("DESede", CKK_DES3);
69
addKeyType("AES", CKK_AES);
70
addKeyType("Blowfish", CKK_BLOWFISH);
71
addKeyType("ChaCha20", CKK_CHACHA20);
72
73
// we don't implement RC2 or IDEA, but we want to be able to generate
74
// keys for those SSL/TLS ciphersuites.
75
addKeyType("RC2", CKK_RC2);
76
addKeyType("IDEA", CKK_IDEA);
77
78
addKeyType("TlsPremasterSecret", PCKK_TLSPREMASTER);
79
addKeyType("TlsRsaPremasterSecret", PCKK_TLSRSAPREMASTER);
80
addKeyType("TlsMasterSecret", PCKK_TLSMASTER);
81
addKeyType("Generic", CKK_GENERIC_SECRET);
82
}
83
84
private static void addKeyType(String name, long id) {
85
Long l = Long.valueOf(id);
86
keyTypes.put(name, l);
87
keyTypes.put(name.toUpperCase(Locale.ENGLISH), l);
88
}
89
90
// returns the PKCS11 key type of the specified algorithm
91
// no psuedo KeyTypes
92
static long getPKCS11KeyType(String algorithm) {
93
long kt = getKeyType(algorithm);
94
if (kt == -1 || kt > PCKK_ANY) {
95
kt = CKK_GENERIC_SECRET;
96
}
97
return kt;
98
}
99
100
// returns direct lookup result of keyTypes using algorithm
101
static long getKeyType(String algorithm) {
102
Long l = keyTypes.get(algorithm);
103
if (l == null) {
104
algorithm = algorithm.toUpperCase(Locale.ENGLISH);
105
l = keyTypes.get(algorithm);
106
if (l == null) {
107
if (algorithm.startsWith("HMAC")) {
108
return PCKK_HMAC;
109
} else if (algorithm.startsWith("SSLMAC")) {
110
return PCKK_SSLMAC;
111
}
112
}
113
}
114
return (l != null) ? l.longValue() : -1;
115
}
116
117
/**
118
* Convert an arbitrary key of algorithm into a P11Key of provider.
119
* Used in engineTranslateKey(), P11Cipher.init(), and P11Mac.init().
120
*/
121
static P11Key convertKey(Token token, Key key, String algo)
122
throws InvalidKeyException {
123
return convertKey(token, key, algo, null);
124
}
125
126
/**
127
* Convert an arbitrary key of algorithm w/ custom attributes into a
128
* P11Key of provider.
129
* Used in P11KeyStore.storeSkey.
130
*/
131
static P11Key convertKey(Token token, Key key, String algo,
132
CK_ATTRIBUTE[] extraAttrs)
133
throws InvalidKeyException {
134
token.ensureValid();
135
if (key == null) {
136
throw new InvalidKeyException("Key must not be null");
137
}
138
if (key instanceof SecretKey == false) {
139
throw new InvalidKeyException("Key must be a SecretKey");
140
}
141
long algoType;
142
if (algo == null) {
143
algo = key.getAlgorithm();
144
algoType = getKeyType(algo);
145
} else {
146
algoType = getKeyType(algo);
147
long keyAlgorithmType = getKeyType(key.getAlgorithm());
148
if (algoType != keyAlgorithmType) {
149
if ((algoType == PCKK_HMAC) || (algoType == PCKK_SSLMAC)) {
150
// ignore key algorithm for MACs
151
} else {
152
throw new InvalidKeyException
153
("Key algorithm must be " + algo);
154
}
155
}
156
}
157
if (key instanceof P11Key) {
158
P11Key p11Key = (P11Key)key;
159
if (p11Key.token == token) {
160
if (extraAttrs != null) {
161
P11Key newP11Key = null;
162
Session session = null;
163
long p11KeyID = p11Key.getKeyID();
164
try {
165
session = token.getObjSession();
166
long newKeyID = token.p11.C_CopyObject(session.id(),
167
p11KeyID, extraAttrs);
168
newP11Key = (P11Key) (P11Key.secretKey(session,
169
newKeyID, p11Key.algorithm, p11Key.keyLength,
170
extraAttrs));
171
} catch (PKCS11Exception p11e) {
172
throw new InvalidKeyException
173
("Cannot duplicate the PKCS11 key", p11e);
174
} finally {
175
p11Key.releaseKeyID();
176
token.releaseSession(session);
177
}
178
p11Key = newP11Key;
179
}
180
return p11Key;
181
}
182
}
183
P11Key p11Key = token.secretCache.get(key);
184
if (p11Key != null) {
185
return p11Key;
186
}
187
if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {
188
throw new InvalidKeyException("Encoded format must be RAW");
189
}
190
byte[] encoded = key.getEncoded();
191
p11Key = createKey(token, encoded, algo, algoType, extraAttrs);
192
token.secretCache.put(key, p11Key);
193
return p11Key;
194
}
195
196
static void fixDESParity(byte[] key, int offset) {
197
for (int i = 0; i < 8; i++) {
198
int b = key[offset] & 0xfe;
199
b |= (Integer.bitCount(b) & 1) ^ 1;
200
key[offset++] = (byte)b;
201
}
202
}
203
204
private static P11Key createKey(Token token, byte[] encoded,
205
String algorithm, long keyType, CK_ATTRIBUTE[] extraAttrs)
206
throws InvalidKeyException {
207
int n = encoded.length << 3;
208
int keyLength = n;
209
try {
210
switch ((int)keyType) {
211
case (int)CKK_DES:
212
keyLength =
213
P11KeyGenerator.checkKeySize(CKM_DES_KEY_GEN, n, token);
214
fixDESParity(encoded, 0);
215
break;
216
case (int)CKK_DES3:
217
keyLength =
218
P11KeyGenerator.checkKeySize(CKM_DES3_KEY_GEN, n, token);
219
fixDESParity(encoded, 0);
220
fixDESParity(encoded, 8);
221
if (keyLength == 112) {
222
keyType = CKK_DES2;
223
} else {
224
keyType = CKK_DES3;
225
fixDESParity(encoded, 16);
226
}
227
break;
228
case (int)CKK_AES:
229
keyLength =
230
P11KeyGenerator.checkKeySize(CKM_AES_KEY_GEN, n, token);
231
break;
232
case (int)CKK_RC4:
233
keyLength =
234
P11KeyGenerator.checkKeySize(CKM_RC4_KEY_GEN, n, token);
235
break;
236
case (int)CKK_BLOWFISH:
237
keyLength =
238
P11KeyGenerator.checkKeySize(CKM_BLOWFISH_KEY_GEN, n,
239
token);
240
break;
241
case (int)CKK_CHACHA20:
242
keyLength = P11KeyGenerator.checkKeySize(
243
CKM_CHACHA20_KEY_GEN, n, token);
244
break;
245
case (int)CKK_GENERIC_SECRET:
246
case (int)PCKK_TLSPREMASTER:
247
case (int)PCKK_TLSRSAPREMASTER:
248
case (int)PCKK_TLSMASTER:
249
keyType = CKK_GENERIC_SECRET;
250
break;
251
case (int)PCKK_SSLMAC:
252
case (int)PCKK_HMAC:
253
if (n == 0) {
254
throw new InvalidKeyException
255
("MAC keys must not be empty");
256
}
257
keyType = CKK_GENERIC_SECRET;
258
break;
259
default:
260
throw new InvalidKeyException("Unknown algorithm " +
261
algorithm);
262
}
263
} catch (InvalidAlgorithmParameterException iape) {
264
throw new InvalidKeyException("Invalid key for " + algorithm,
265
iape);
266
} catch (ProviderException pe) {
267
throw new InvalidKeyException("Could not create key", pe);
268
}
269
Session session = null;
270
try {
271
CK_ATTRIBUTE[] attributes;
272
if (extraAttrs != null) {
273
attributes = new CK_ATTRIBUTE[3 + extraAttrs.length];
274
System.arraycopy(extraAttrs, 0, attributes, 3,
275
extraAttrs.length);
276
} else {
277
attributes = new CK_ATTRIBUTE[3];
278
}
279
attributes[0] = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY);
280
attributes[1] = new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType);
281
attributes[2] = new CK_ATTRIBUTE(CKA_VALUE, encoded);
282
attributes = token.getAttributes
283
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
284
session = token.getObjSession();
285
long keyID = token.p11.C_CreateObject(session.id(), attributes);
286
P11Key p11Key = (P11Key)P11Key.secretKey
287
(session, keyID, algorithm, keyLength, attributes);
288
return p11Key;
289
} catch (PKCS11Exception e) {
290
throw new InvalidKeyException("Could not create key", e);
291
} finally {
292
token.releaseSession(session);
293
}
294
}
295
296
// see JCE spec
297
protected SecretKey engineGenerateSecret(KeySpec keySpec)
298
throws InvalidKeySpecException {
299
token.ensureValid();
300
if (keySpec == null) {
301
throw new InvalidKeySpecException("KeySpec must not be null");
302
}
303
if (keySpec instanceof SecretKeySpec) {
304
try {
305
Key key = convertKey(token, (SecretKey)keySpec, algorithm);
306
return (SecretKey)key;
307
} catch (InvalidKeyException e) {
308
throw new InvalidKeySpecException(e);
309
}
310
} else if (algorithm.equalsIgnoreCase("DES")) {
311
if (keySpec instanceof DESKeySpec) {
312
byte[] keyBytes = ((DESKeySpec)keySpec).getKey();
313
keySpec = new SecretKeySpec(keyBytes, "DES");
314
return engineGenerateSecret(keySpec);
315
}
316
} else if (algorithm.equalsIgnoreCase("DESede")) {
317
if (keySpec instanceof DESedeKeySpec) {
318
byte[] keyBytes = ((DESedeKeySpec)keySpec).getKey();
319
keySpec = new SecretKeySpec(keyBytes, "DESede");
320
return engineGenerateSecret(keySpec);
321
}
322
}
323
throw new InvalidKeySpecException
324
("Unsupported spec: " + keySpec.getClass().getName());
325
}
326
327
private byte[] getKeyBytes(SecretKey key) throws InvalidKeySpecException {
328
try {
329
key = engineTranslateKey(key);
330
if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {
331
throw new InvalidKeySpecException
332
("Could not obtain key bytes");
333
}
334
byte[] k = key.getEncoded();
335
return k;
336
} catch (InvalidKeyException e) {
337
throw new InvalidKeySpecException(e);
338
}
339
}
340
341
// see JCE spec
342
protected KeySpec engineGetKeySpec(SecretKey key, Class<?> keySpec)
343
throws InvalidKeySpecException {
344
token.ensureValid();
345
if ((key == null) || (keySpec == null)) {
346
throw new InvalidKeySpecException
347
("key and keySpec must not be null");
348
}
349
if (keySpec.isAssignableFrom(SecretKeySpec.class)) {
350
return new SecretKeySpec(getKeyBytes(key), algorithm);
351
} else if (algorithm.equalsIgnoreCase("DES")) {
352
try {
353
if (keySpec.isAssignableFrom(DESKeySpec.class)) {
354
return new DESKeySpec(getKeyBytes(key));
355
}
356
} catch (InvalidKeyException e) {
357
throw new InvalidKeySpecException(e);
358
}
359
} else if (algorithm.equalsIgnoreCase("DESede")) {
360
try {
361
if (keySpec.isAssignableFrom(DESedeKeySpec.class)) {
362
return new DESedeKeySpec(getKeyBytes(key));
363
}
364
} catch (InvalidKeyException e) {
365
throw new InvalidKeySpecException(e);
366
}
367
}
368
throw new InvalidKeySpecException
369
("Unsupported spec: " + keySpec.getName());
370
}
371
372
// see JCE spec
373
protected SecretKey engineTranslateKey(SecretKey key)
374
throws InvalidKeyException {
375
return (SecretKey)convertKey(token, key, algorithm);
376
}
377
378
}
379
380