1
1
/*
2
- * Copyright (c) 2003, 2019 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2003, 2020 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
36
36
37
37
/**
38
38
* KeyGenerator implementation class. This class currently supports
39
- * DES, DESede, AES, ARCFOUR, and Blowfish.
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.
40
42
*
41
43
* @author Andreas Sterbenz
42
44
* @since 1.5
@@ -65,6 +67,48 @@ final class P11KeyGenerator extends KeyGeneratorSpi {
65
67
// are supported.
66
68
private boolean supportBothKeySizes ;
67
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
+
68
112
/**
69
113
* Utility method for checking if the specified key size is valid
70
114
* and within the supported range. Return the significant key size
@@ -78,8 +122,15 @@ final class P11KeyGenerator extends KeyGeneratorSpi {
78
122
* @throws ProviderException if this mechanism isn't supported by SunPKCS11
79
123
* or underlying native impl.
80
124
*/
125
+ // called by P11SecretKeyFactory to check key size
81
126
static int checkKeySize (long keyGenMech , int keySize , Token token )
82
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 {
83
134
int sigKeySize ;
84
135
switch ((int )keyGenMech ) {
85
136
case (int )CKM_DES_KEY_GEN :
@@ -102,52 +153,38 @@ static int checkKeySize(long keyGenMech, int keySize, Token token)
102
153
break ;
103
154
default :
104
155
// Handle all variable-key-length algorithms here
105
- CK_MECHANISM_INFO info = null ;
106
- try {
107
- info = token .getMechanismInfo (keyGenMech );
108
- } catch (PKCS11Exception p11e ) {
109
- // Should never happen
110
- throw new ProviderException
111
- ("Cannot retrieve mechanism info" , p11e );
112
- }
113
- if (info == null ) {
114
- // XXX Unable to retrieve the supported key length from
115
- // the underlying native impl. Skip the checking for now.
116
- return keySize ;
117
- }
118
- // PKCS#11 defines these to be in number of bytes except for
119
- // RC4 which is in bits. However, some PKCS#11 impls still use
120
- // bytes for all mechs, e.g. NSS. We try to detect this
121
- // inconsistency if the minKeySize seems unreasonably small.
122
- int minKeySize = info .iMinKeySize ;
123
- int maxKeySize = info .iMaxKeySize ;
124
- if (keyGenMech != CKM_RC4_KEY_GEN || minKeySize < 8 ) {
125
- minKeySize = Math .multiplyExact (minKeySize , 8 );
126
- if (maxKeySize != Integer .MAX_VALUE ) {
127
- maxKeySize = Math .multiplyExact (maxKeySize , 8 );
128
- }
129
- }
130
- // Explicitly disallow keys shorter than 40-bits for security
131
- if (minKeySize < 40 ) minKeySize = 40 ;
132
- if (keySize < minKeySize || keySize > maxKeySize ) {
156
+ if (range != null && keySize < range .iMinKeySize
157
+ || keySize > range .iMaxKeySize ) {
133
158
throw new InvalidAlgorithmParameterException
134
- ("Key length must be between " + minKeySize +
135
- " and " + maxKeySize + " bits" );
159
+ ("Key length must be between " + range . iMinKeySize +
160
+ " and " + range . iMaxKeySize + " bits" );
136
161
}
137
162
if (keyGenMech == CKM_AES_KEY_GEN ) {
138
163
if ((keySize != 128 ) && (keySize != 192 ) &&
139
164
(keySize != 256 )) {
140
165
throw new InvalidAlgorithmParameterException
141
- ("AES key length must be " + minKeySize +
142
- (maxKeySize >= 192 ? ", 192" :"" ) +
143
- (maxKeySize >= 256 ? ", or 256" :"" ) + " bits" );
166
+ ("AES key length must be 128, 192, or 256 bits" );
144
167
}
145
168
}
146
169
sigKeySize = keySize ;
147
170
}
148
171
return sigKeySize ;
149
172
}
150
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
+
151
188
P11KeyGenerator (Token token , String algorithm , long mechanism )
152
189
throws PKCS11Exception {
153
190
super ();
@@ -164,50 +201,118 @@ static int checkKeySize(long keyGenMech, int keySize, Token token)
164
201
(token .provider .config .isEnabled (CKM_DES2_KEY_GEN ) &&
165
202
(token .getMechanismInfo (CKM_DES2_KEY_GEN ) != null ));
166
203
}
167
- setDefaultKeySize ();
204
+ this .range = getSupportedRange (token , mechanism );
205
+ setDefault ();
168
206
}
169
207
170
- // set default keysize and also initialize keyType
171
- private void setDefaultKeySize () {
208
+ // set default keysize and keyType
209
+ private void setDefault () {
210
+ significantKeySize = -1 ;
172
211
switch ((int )mechanism ) {
173
212
case (int )CKM_DES_KEY_GEN :
174
213
keySize = 64 ;
175
214
keyType = CKK_DES ;
215
+ significantKeySize = 56 ;
176
216
break ;
177
217
case (int )CKM_DES2_KEY_GEN :
178
218
keySize = 128 ;
179
219
keyType = CKK_DES2 ;
220
+ significantKeySize = 112 ;
180
221
break ;
181
222
case (int )CKM_DES3_KEY_GEN :
182
223
keySize = 192 ;
183
224
keyType = CKK_DES3 ;
225
+ significantKeySize = 168 ;
184
226
break ;
185
227
case (int )CKM_AES_KEY_GEN :
186
- keySize = 128 ;
228
+ keySize = adjustKeySize ( 128 , range ) ;
187
229
keyType = CKK_AES ;
188
230
break ;
189
231
case (int )CKM_RC4_KEY_GEN :
190
- keySize = 128 ;
232
+ keySize = adjustKeySize ( 128 , range ) ;
191
233
keyType = CKK_RC4 ;
192
234
break ;
193
235
case (int )CKM_BLOWFISH_KEY_GEN :
194
- keySize = 128 ;
236
+ keySize = adjustKeySize ( 128 , range ) ;
195
237
keyType = CKK_BLOWFISH ;
196
238
break ;
239
+ case (int )CKM_SHA_1_KEY_GEN :
240
+ keySize = adjustKeySize (160 , range );
241
+ keyType = CKK_SHA_1_HMAC ;
242
+ break ;
243
+ case (int )CKM_SHA224_KEY_GEN :
244
+ keySize = adjustKeySize (224 , range );
245
+ keyType = CKK_SHA224_HMAC ;
246
+ break ;
247
+ case (int )CKM_SHA256_KEY_GEN :
248
+ keySize = adjustKeySize (256 , range );
249
+ keyType = CKK_SHA256_HMAC ;
250
+ break ;
251
+ case (int )CKM_SHA384_KEY_GEN :
252
+ keySize = adjustKeySize (384 , range );
253
+ keyType = CKK_SHA384_HMAC ;
254
+ break ;
255
+ case (int )CKM_SHA512_KEY_GEN :
256
+ keySize = adjustKeySize (512 , range );
257
+ keyType = CKK_SHA512_HMAC ;
258
+ break ;
259
+ case (int )CKM_SHA512_224_KEY_GEN :
260
+ keySize = adjustKeySize (224 , range );
261
+ keyType = CKK_SHA512_224_HMAC ;
262
+ break ;
263
+ case (int )CKM_SHA512_256_KEY_GEN :
264
+ keySize = adjustKeySize (256 , range );
265
+ keyType = CKK_SHA512_256_HMAC ;
266
+ break ;
267
+ case (int )CKM_SHA3_224_KEY_GEN :
268
+ keySize = adjustKeySize (224 , range );
269
+ keyType = CKK_SHA3_224_HMAC ;
270
+ break ;
271
+ case (int )CKM_SHA3_256_KEY_GEN :
272
+ keySize = adjustKeySize (256 , range );
273
+ keyType = CKK_SHA3_256_HMAC ;
274
+ break ;
275
+ case (int )CKM_SHA3_384_KEY_GEN :
276
+ keySize = adjustKeySize (384 , range );
277
+ keyType = CKK_SHA3_384_HMAC ;
278
+ break ;
279
+ case (int )CKM_SHA3_512_KEY_GEN :
280
+ keySize = adjustKeySize (512 , range );
281
+ keyType = CKK_SHA3_512_HMAC ;
282
+ break ;
283
+ case (int )CKM_GENERIC_SECRET_KEY_GEN :
284
+ if (algorithm .startsWith ("Hmac" )) {
285
+ String digest = algorithm .substring (4 );
286
+ keySize = adjustKeySize (switch (digest ) {
287
+ case "MD5" -> 512 ;
288
+ case "SHA1" -> 160 ;
289
+ case "SHA224" , "SHA512/224" , "SHA3-224" -> 224 ;
290
+ case "SHA256" , "SHA512/256" , "SHA3-256" -> 256 ;
291
+ case "SHA384" , "SHA3-384" -> 384 ;
292
+ case "SHA512" , "SHA3-512" -> 512 ;
293
+ default -> {
294
+ throw new ProviderException ("Unsupported algorithm " +
295
+ algorithm );
296
+ }
297
+ }, range );
298
+ } else {
299
+ throw new ProviderException ("Unsupported algorithm " +
300
+ algorithm );
301
+ }
302
+ keyType = CKK_GENERIC_SECRET ;
303
+ break ;
197
304
default :
198
305
throw new ProviderException ("Unknown mechanism " + mechanism );
199
306
}
200
- try {
201
- significantKeySize = checkKeySize (mechanism , keySize , token );
202
- } catch (InvalidAlgorithmParameterException iape ) {
203
- throw new ProviderException ("Unsupported default key size" , iape );
307
+ if (significantKeySize == -1 ) {
308
+ significantKeySize = keySize ;
204
309
}
205
310
}
206
311
207
312
// see JCE spec
208
313
protected void engineInit (SecureRandom random ) {
209
314
token .ensureValid ();
210
- setDefaultKeySize ();
315
+ setDefault ();
211
316
}
212
317
213
318
// see JCE spec
@@ -222,7 +327,7 @@ protected void engineInit(int keySize, SecureRandom random) {
222
327
token .ensureValid ();
223
328
int newSignificantKeySize ;
224
329
try {
225
- newSignificantKeySize = checkKeySize (mechanism , keySize , token );
330
+ newSignificantKeySize = checkKeySize (mechanism , keySize , range );
226
331
} catch (InvalidAlgorithmParameterException iape ) {
227
332
throw (InvalidParameterException )
228
333
(new InvalidParameterException ().initCause (iape ));
@@ -254,10 +359,11 @@ protected SecretKey engineGenerateKey() {
254
359
try {
255
360
session = token .getObjSession ();
256
361
CK_ATTRIBUTE [] attributes ;
257
- switch ((int )keyType ) {
258
- case (int )CKK_DES :
259
- case (int )CKK_DES2 :
260
- case (int )CKK_DES3 :
362
+
363
+ switch ((int )mechanism ) {
364
+ case (int )CKM_DES_KEY_GEN :
365
+ case (int )CKM_DES2_KEY_GEN :
366
+ case (int )CKM_DES3_KEY_GEN :
261
367
// fixed length, do not specify CKA_VALUE_LEN
262
368
attributes = new CK_ATTRIBUTE [] {
263
369
new CK_ATTRIBUTE (CKA_CLASS , CKO_SECRET_KEY ),
@@ -282,5 +388,4 @@ protected SecretKey engineGenerateKey() {
282
388
token .releaseSession (session );
283
389
}
284
390
}
285
-
286
391
}
0 commit comments