Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/pk11wrap/pk11pbe.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 #include "plarena.h" | |
6 | |
7 #include "seccomon.h" | |
8 #include "secitem.h" | |
9 #include "secport.h" | |
10 #include "hasht.h" | |
11 #include "pkcs11t.h" | |
12 #include "sechash.h" | |
13 #include "secasn1.h" | |
14 #include "secder.h" | |
15 #include "secoid.h" | |
16 #include "secerr.h" | |
17 #include "secmod.h" | |
18 #include "pk11func.h" | |
19 #include "secpkcs5.h" | |
20 #include "secmodi.h" | |
21 #include "secmodti.h" | |
22 #include "pkcs11.h" | |
23 #include "pk11func.h" | |
24 #include "secitem.h" | |
25 #include "key.h" | |
26 | |
27 typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter; | |
28 struct SEC_PKCS5PBEParameterStr { | |
29 PLArenaPool *poolp; | |
30 SECItem salt; /* octet string */ | |
31 SECItem iteration; /* integer */ | |
32 SECItem keyLength; /* PKCS5v2 only */ | |
33 SECAlgorithmID *pPrfAlgId; /* PKCS5v2 only */ | |
34 SECAlgorithmID prfAlgId; /* PKCS5v2 only */ | |
35 }; | |
36 | |
37 /* PKCS5 V2 has an algorithm ID for the encryption and for | |
38 * the key generation. This is valid for SEC_OID_PKCS5_PBES2 | |
39 * and SEC_OID_PKCS5_PBMAC1 | |
40 */ | |
41 struct sec_pkcs5V2ParameterStr { | |
42 PLArenaPool *poolp; | |
43 SECAlgorithmID pbeAlgId; /* real pbe algorithms */ | |
44 SECAlgorithmID cipherAlgId; /* encryption/mac */ | |
45 }; | |
46 | |
47 typedef struct sec_pkcs5V2ParameterStr sec_pkcs5V2Parameter; | |
48 | |
49 | |
50 /* template for PKCS 5 PBE Parameter. This template has been expanded | |
51 * based upon the additions in PKCS 12. This should eventually be moved | |
52 * if RSA updates PKCS 5. | |
53 */ | |
54 const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] = | |
55 { | |
56 { SEC_ASN1_SEQUENCE, | |
57 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, | |
58 { SEC_ASN1_OCTET_STRING, | |
59 offsetof(SEC_PKCS5PBEParameter, salt) }, | |
60 { SEC_ASN1_INTEGER, | |
61 offsetof(SEC_PKCS5PBEParameter, iteration) }, | |
62 { 0 } | |
63 }; | |
64 | |
65 const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] = | |
66 { | |
67 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, | |
68 { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) }, | |
69 { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) }, | |
70 { 0 } | |
71 }; | |
72 | |
73 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) | |
74 | |
75 /* SECOID_PKCS5_PBKDF2 */ | |
76 const SEC_ASN1Template SEC_PKCS5V2PBEParameterTemplate[] = | |
77 { | |
78 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, | |
79 /* This is really a choice, but since we only understand this | |
80 * choice, just inline it */ | |
81 { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) }, | |
82 { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) }, | |
83 { SEC_ASN1_INTEGER|SEC_ASN1_OPTIONAL, | |
84 offsetof(SEC_PKCS5PBEParameter, keyLength) }, | |
85 { SEC_ASN1_POINTER | SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL, | |
86 offsetof(SEC_PKCS5PBEParameter, pPrfAlgId), | |
87 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
88 { 0 } | |
89 }; | |
90 | |
91 /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */ | |
92 const SEC_ASN1Template SEC_PKCS5V2ParameterTemplate[] = | |
93 { | |
94 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, | |
95 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(sec_pkcs5V2Parameter, pbeAlgId), | |
96 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
97 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
98 offsetof(sec_pkcs5V2Parameter, cipherAlgId), | |
99 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
100 { 0 } | |
101 }; | |
102 | |
103 | |
104 /* | |
105 * maps a PBE algorithm to a crypto algorithm. for PKCS12 and PKCS5v1 | |
106 * for PKCS5v2 it returns SEC_OID_PKCS5_PBKDF2. | |
107 */ | |
108 SECOidTag | |
109 sec_pkcs5GetCryptoFromAlgTag(SECOidTag algorithm) | |
110 { | |
111 switch(algorithm) | |
112 { | |
113 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: | |
114 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: | |
115 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: | |
116 return SEC_OID_DES_EDE3_CBC; | |
117 case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: | |
118 case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: | |
119 case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: | |
120 return SEC_OID_DES_CBC; | |
121 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
122 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
123 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
124 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
125 return SEC_OID_RC2_CBC; | |
126 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
127 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
128 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
129 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
130 return SEC_OID_RC4; | |
131 case SEC_OID_PKCS5_PBKDF2: | |
132 case SEC_OID_PKCS5_PBES2: | |
133 case SEC_OID_PKCS5_PBMAC1: | |
134 return SEC_OID_PKCS5_PBKDF2; | |
135 default: | |
136 break; | |
137 } | |
138 | |
139 return SEC_OID_UNKNOWN; | |
140 } | |
141 | |
142 /* | |
143 * get a new PKCS5 V2 Parameter from the algorithm id. | |
144 * if arena is passed in, use it, otherwise create a new arena. | |
145 */ | |
146 sec_pkcs5V2Parameter * | |
147 sec_pkcs5_v2_get_v2_param(PLArenaPool *arena, SECAlgorithmID *algid) | |
148 { | |
149 PLArenaPool *localArena = NULL; | |
150 sec_pkcs5V2Parameter *pbeV2_param; | |
151 SECStatus rv; | |
152 | |
153 if (arena == NULL) { | |
154 localArena = arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
155 if (arena == NULL) { | |
156 return NULL; | |
157 } | |
158 } | |
159 pbeV2_param = PORT_ArenaZNew(arena, sec_pkcs5V2Parameter); | |
160 if (pbeV2_param == NULL) { | |
161 goto loser; | |
162 } | |
163 | |
164 rv = SEC_ASN1DecodeItem(arena, pbeV2_param, | |
165 SEC_PKCS5V2ParameterTemplate, &algid->parameters); | |
166 if (rv == SECFailure) { | |
167 goto loser; | |
168 } | |
169 | |
170 pbeV2_param->poolp = arena; | |
171 return pbeV2_param; | |
172 loser: | |
173 if (localArena) { | |
174 PORT_FreeArena(arena, PR_FALSE); | |
175 } | |
176 return NULL; | |
177 } | |
178 | |
179 void | |
180 sec_pkcs5_v2_destroy_v2_param(sec_pkcs5V2Parameter *param) | |
181 { | |
182 if (param && param->poolp) { | |
183 PORT_FreeArena(param->poolp, PR_TRUE); | |
184 } | |
185 } | |
186 | |
187 | |
188 /* maps crypto algorithm from PBE algorithm. | |
189 */ | |
190 SECOidTag | |
191 SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid) | |
192 { | |
193 | |
194 SECOidTag pbeAlg; | |
195 SECOidTag cipherAlg; | |
196 | |
197 if(algid == NULL) | |
198 return SEC_OID_UNKNOWN; | |
199 | |
200 pbeAlg = SECOID_GetAlgorithmTag(algid); | |
201 cipherAlg = sec_pkcs5GetCryptoFromAlgTag(pbeAlg); | |
202 if ((cipherAlg == SEC_OID_PKCS5_PBKDF2) && | |
203 (pbeAlg != SEC_OID_PKCS5_PBKDF2)) { | |
204 sec_pkcs5V2Parameter *pbeV2_param; | |
205 cipherAlg = SEC_OID_UNKNOWN; | |
206 | |
207 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); | |
208 if (pbeV2_param != NULL) { | |
209 cipherAlg = SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId); | |
210 sec_pkcs5_v2_destroy_v2_param(pbeV2_param); | |
211 } | |
212 } | |
213 | |
214 return cipherAlg; | |
215 } | |
216 | |
217 /* check to see if an oid is a pbe algorithm | |
218 */ | |
219 PRBool | |
220 SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid) | |
221 { | |
222 return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN); | |
223 } | |
224 | |
225 PRBool | |
226 SEC_PKCS5IsAlgorithmPBEAlgTag(SECOidTag algtag) | |
227 { | |
228 return (PRBool)(sec_pkcs5GetCryptoFromAlgTag(algtag) != SEC_OID_UNKNOWN); | |
229 } | |
230 | |
231 /* | |
232 * find the most appropriate PKCS5v2 overall oid tag from a regular | |
233 * cipher/hash algorithm tag. | |
234 */ | |
235 static SECOidTag | |
236 sec_pkcs5v2_get_pbe(SECOidTag algTag) | |
237 { | |
238 /* if it's a valid hash oid... */ | |
239 if (HASH_GetHashOidTagByHMACOidTag(algTag) != SEC_OID_UNKNOWN) { | |
240 /* use the MAC tag */ | |
241 return SEC_OID_PKCS5_PBMAC1; | |
242 } | |
243 if (HASH_GetHashTypeByOidTag(algTag) != HASH_AlgNULL) { | |
244 /* eliminate Hash algorithms */ | |
245 return SEC_OID_UNKNOWN; | |
246 } | |
247 if (PK11_AlgtagToMechanism(algTag) != CKM_INVALID_MECHANISM) { | |
248 /* it's not a hash, if it has a PKCS #11 mechanism associated | |
249 * with it, assume it's a cipher. (NOTE this will generate | |
250 * some false positives). */ | |
251 return SEC_OID_PKCS5_PBES2; | |
252 } | |
253 return SEC_OID_UNKNOWN; | |
254 } | |
255 | |
256 /* | |
257 * maps PBE algorithm from crypto algorithm, assumes SHA1 hashing. | |
258 * input keyLen in bits. | |
259 */ | |
260 SECOidTag | |
261 SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen) | |
262 { | |
263 switch(algTag) | |
264 { | |
265 case SEC_OID_DES_EDE3_CBC: | |
266 switch(keyLen) { | |
267 case 168: | |
268 case 192: | |
269 case 0: | |
270 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC; | |
271 case 128: | |
272 case 92: | |
273 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC; | |
274 default: | |
275 break; | |
276 } | |
277 break; | |
278 case SEC_OID_DES_CBC: | |
279 return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC; | |
280 case SEC_OID_RC2_CBC: | |
281 switch(keyLen) { | |
282 case 40: | |
283 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; | |
284 case 128: | |
285 case 0: | |
286 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; | |
287 default: | |
288 break; | |
289 } | |
290 break; | |
291 case SEC_OID_RC4: | |
292 switch(keyLen) { | |
293 case 40: | |
294 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4; | |
295 case 128: | |
296 case 0: | |
297 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4; | |
298 default: | |
299 break; | |
300 } | |
301 break; | |
302 default: | |
303 return sec_pkcs5v2_get_pbe(algTag); | |
304 } | |
305 | |
306 return SEC_OID_UNKNOWN; | |
307 } | |
308 | |
309 /* | |
310 * get the key length in bytes from a PKCS5 PBE | |
311 */ | |
312 int | |
313 sec_pkcs5v2_key_length(SECAlgorithmID *algid) | |
314 { | |
315 SECOidTag algorithm; | |
316 PLArenaPool *arena = NULL; | |
317 SEC_PKCS5PBEParameter p5_param; | |
318 SECStatus rv; | |
319 int length = -1; | |
320 | |
321 algorithm = SECOID_GetAlgorithmTag(algid); | |
322 /* sanity check, they should all be PBKDF2 here */ | |
323 if (algorithm != SEC_OID_PKCS5_PBKDF2) { | |
324 return -1; | |
325 } | |
326 | |
327 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
328 if (arena == NULL) { | |
329 goto loser; | |
330 } | |
331 PORT_Memset(&p5_param, 0, sizeof(p5_param)); | |
332 rv = SEC_ASN1DecodeItem(arena,&p5_param, | |
333 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters); | |
334 if (rv != SECSuccess) { | |
335 goto loser; | |
336 } | |
337 | |
338 if (p5_param.keyLength.data != NULL) { | |
339 length = DER_GetInteger(&p5_param.keyLength); | |
340 } | |
341 | |
342 loser: | |
343 if (arena) { | |
344 PORT_FreeArena(arena, PR_FALSE); | |
345 } | |
346 return length; | |
347 } | |
348 | |
349 /* | |
350 * get the key length in bytes needed for the PBE algorithm | |
351 */ | |
352 int | |
353 SEC_PKCS5GetKeyLength(SECAlgorithmID *algid) | |
354 { | |
355 | |
356 SECOidTag algorithm; | |
357 | |
358 if(algid == NULL) | |
359 return SEC_OID_UNKNOWN; | |
360 | |
361 algorithm = SECOID_GetAlgorithmTag(algid); | |
362 | |
363 switch(algorithm) | |
364 { | |
365 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: | |
366 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: | |
367 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: | |
368 return 24; | |
369 case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: | |
370 case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: | |
371 case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: | |
372 return 8; | |
373 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
374 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
375 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
376 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
377 return 5; | |
378 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
379 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
380 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
381 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
382 return 16; | |
383 case SEC_OID_PKCS5_PBKDF2: | |
384 return sec_pkcs5v2_key_length(algid); | |
385 case SEC_OID_PKCS5_PBES2: | |
386 case SEC_OID_PKCS5_PBMAC1: | |
387 { | |
388 sec_pkcs5V2Parameter *pbeV2_param; | |
389 int length = -1; | |
390 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); | |
391 if (pbeV2_param != NULL) { | |
392 length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId); | |
393 sec_pkcs5_v2_destroy_v2_param(pbeV2_param); | |
394 } | |
395 return length; | |
396 } | |
397 | |
398 default: | |
399 break; | |
400 } | |
401 return -1; | |
402 } | |
403 | |
404 | |
405 /* the PKCS12 V2 algorithms only encode the salt, there is no iteration | |
406 * count so we need a check for V2 algorithm parameters. | |
407 */ | |
408 static PRBool | |
409 sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm) | |
410 { | |
411 switch(algorithm) | |
412 { | |
413 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: | |
414 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: | |
415 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: | |
416 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: | |
417 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: | |
418 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: | |
419 return PR_TRUE; | |
420 default: | |
421 break; | |
422 } | |
423 | |
424 return PR_FALSE; | |
425 } | |
426 | |
427 static PRBool | |
428 sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(SECOidTag algorithm) | |
429 { | |
430 switch(algorithm) | |
431 { | |
432 case SEC_OID_PKCS5_PBES2: | |
433 case SEC_OID_PKCS5_PBMAC1: | |
434 case SEC_OID_PKCS5_PBKDF2: | |
435 return PR_TRUE; | |
436 default: | |
437 break; | |
438 } | |
439 | |
440 return PR_FALSE; | |
441 } | |
442 | |
443 /* destroy a pbe parameter. it assumes that the parameter was | |
444 * generated using the appropriate create function and therefor | |
445 * contains an arena pool. | |
446 */ | |
447 static void | |
448 sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param) | |
449 { | |
450 if(pbe_param != NULL) | |
451 PORT_FreeArena(pbe_param->poolp, PR_TRUE); | |
452 } | |
453 | |
454 /* creates a PBE parameter based on the PBE algorithm. the only required | |
455 * parameters are algorithm and interation. the return is a PBE parameter | |
456 * which conforms to PKCS 5 parameter unless an extended parameter is needed. | |
457 * this is primarily if keyLength and a variable key length algorithm are | |
458 * specified. | |
459 * salt - if null, a salt will be generated from random bytes. | |
460 * iteration - number of iterations to perform hashing. | |
461 * keyLength - only used in variable key length algorithms. if specified, | |
462 * should be in bytes. | |
463 * once a parameter is allocated, it should be destroyed calling | |
464 * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter. | |
465 */ | |
466 #define DEFAULT_SALT_LENGTH 16 | |
467 static SEC_PKCS5PBEParameter * | |
468 sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, | |
469 SECItem *salt, | |
470 int iteration, | |
471 int keyLength, | |
472 SECOidTag prfAlg) | |
473 { | |
474 PLArenaPool *poolp = NULL; | |
475 SEC_PKCS5PBEParameter *pbe_param = NULL; | |
476 SECStatus rv= SECSuccess; | |
477 void *dummy = NULL; | |
478 | |
479 if(iteration < 0) { | |
480 return NULL; | |
481 } | |
482 | |
483 poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
484 if(poolp == NULL) | |
485 return NULL; | |
486 | |
487 pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp, | |
488 sizeof(SEC_PKCS5PBEParameter)); | |
489 if(!pbe_param) { | |
490 PORT_FreeArena(poolp, PR_TRUE); | |
491 return NULL; | |
492 } | |
493 | |
494 pbe_param->poolp = poolp; | |
495 | |
496 rv = SECFailure; | |
497 if (salt && salt->data) { | |
498 rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt); | |
499 } else { | |
500 /* sigh, the old interface generated salt on the fly, so we have to | |
501 * preserve the semantics */ | |
502 pbe_param->salt.len = DEFAULT_SALT_LENGTH; | |
503 pbe_param->salt.data = PORT_ArenaZAlloc(poolp,DEFAULT_SALT_LENGTH); | |
504 if (pbe_param->salt.data) { | |
505 rv = PK11_GenerateRandom(pbe_param->salt.data,DEFAULT_SALT_LENGTH); | |
506 } | |
507 } | |
508 | |
509 if(rv != SECSuccess) { | |
510 PORT_FreeArena(poolp, PR_TRUE); | |
511 return NULL; | |
512 } | |
513 | |
514 /* encode the integer */ | |
515 dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, | |
516 iteration); | |
517 rv = (dummy) ? SECSuccess : SECFailure; | |
518 | |
519 if(rv != SECSuccess) { | |
520 PORT_FreeArena(poolp, PR_FALSE); | |
521 return NULL; | |
522 } | |
523 | |
524 /* | |
525 * for PKCS5 v2 Add the keylength and the prf | |
526 */ | |
527 if (algorithm == SEC_OID_PKCS5_PBKDF2) { | |
528 dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->keyLength, | |
529 keyLength); | |
530 rv = (dummy) ? SECSuccess : SECFailure; | |
531 if (rv != SECSuccess) { | |
532 PORT_FreeArena(poolp, PR_FALSE); | |
533 return NULL; | |
534 } | |
535 rv = SECOID_SetAlgorithmID(poolp, &pbe_param->prfAlgId, prfAlg, NULL); | |
536 if (rv != SECSuccess) { | |
537 PORT_FreeArena(poolp, PR_FALSE); | |
538 return NULL; | |
539 } | |
540 pbe_param->pPrfAlgId = &pbe_param->prfAlgId; | |
541 } | |
542 | |
543 return pbe_param; | |
544 } | |
545 | |
546 /* creates a algorithm ID containing the PBE algorithm and appropriate | |
547 * parameters. the required parameter is the algorithm. if salt is | |
548 * not specified, it is generated randomly. | |
549 * | |
550 * the returned SECAlgorithmID should be destroyed using | |
551 * SECOID_DestroyAlgorithmID | |
552 */ | |
553 SECAlgorithmID * | |
554 sec_pkcs5CreateAlgorithmID(SECOidTag algorithm, | |
555 SECOidTag cipherAlgorithm, | |
556 SECOidTag prfAlg, | |
557 SECOidTag *pPbeAlgorithm, | |
558 int keyLength, | |
559 SECItem *salt, | |
560 int iteration) | |
561 { | |
562 PLArenaPool *poolp = NULL; | |
563 SECAlgorithmID *algid, *ret_algid = NULL; | |
564 SECOidTag pbeAlgorithm = algorithm; | |
565 SECItem der_param; | |
566 void *dummy; | |
567 SECStatus rv = SECFailure; | |
568 SEC_PKCS5PBEParameter *pbe_param = NULL; | |
569 sec_pkcs5V2Parameter pbeV2_param; | |
570 | |
571 if(iteration <= 0) { | |
572 return NULL; | |
573 } | |
574 | |
575 poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
576 if(!poolp) { | |
577 goto loser; | |
578 } | |
579 | |
580 if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm) || | |
581 sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) { | |
582 /* use PKCS 5 v2 */ | |
583 SECItem *cipherParams; | |
584 | |
585 /* | |
586 * if we ask for pkcs5 Algorithms directly, then the | |
587 * application needs to supply the cipher algorithm, | |
588 * otherwise we are implicitly using pkcs5 v2 and the | |
589 * passed in algorithm is the encryption algorithm. | |
590 */ | |
591 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) { | |
592 if (cipherAlgorithm == SEC_OID_UNKNOWN) { | |
593 goto loser; | |
594 } | |
595 } else { | |
596 cipherAlgorithm = algorithm; | |
597 /* force algorithm to be chosen below */ | |
598 algorithm = SEC_OID_PKCS5_PBKDF2; | |
599 } | |
600 | |
601 pbeAlgorithm = SEC_OID_PKCS5_PBKDF2; | |
602 /* | |
603 * 'algorithm' is the overall algorithm oid tag used to wrap the | |
604 * entire algoithm ID block. For PKCS5v1 and PKCS12, this | |
605 * algorithm OID has encoded in it both the PBE KDF function | |
606 * and the encryption algorithm. For PKCS 5v2, PBE KDF and | |
607 * encryption/macing oids are encoded as parameters in | |
608 * the algorithm ID block. | |
609 * | |
610 * Thus in PKCS5 v1 and PKCS12, this algorithm maps to a pkcs #11 | |
611 * mechanism, where as in PKCS 5v2, this alogithm tag does not map | |
612 * directly to a PKCS #11 mechanim, instead the 2 oids in the | |
613 * algorithm ID block map the the actual PKCS #11 mechanism. | |
614 * gorithm is). We use choose this algorithm oid based on the | |
615 * cipherAlgorithm to determine what this should be (MAC1 or PBES2). | |
616 */ | |
617 if (algorithm == SEC_OID_PKCS5_PBKDF2) { | |
618 /* choose mac or pbes */ | |
619 algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm); | |
620 } | |
621 | |
622 /* set the PKCS5v2 specific parameters */ | |
623 if (keyLength == 0) { | |
624 SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm); | |
625 if (hashAlg != SEC_OID_UNKNOWN) { | |
626 keyLength = HASH_ResultLenByOidTag(hashAlg); | |
627 } else { | |
628 CK_MECHANISM_TYPE cryptoMech; | |
629 cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm); | |
630 if (cryptoMech == CKM_INVALID_MECHANISM) { | |
631 goto loser; | |
632 } | |
633 keyLength = PK11_GetMaxKeyLength(cryptoMech); | |
634 } | |
635 if (keyLength == 0) { | |
636 goto loser; | |
637 } | |
638 } | |
639 /* currently only SEC_OID_HMAC_SHA1 is defined */ | |
640 if (prfAlg == SEC_OID_UNKNOWN) { | |
641 prfAlg = SEC_OID_HMAC_SHA1; | |
642 } | |
643 | |
644 /* build the PKCS5v2 cipher algorithm id */ | |
645 cipherParams = pk11_GenerateNewParamWithKeyLen( | |
646 PK11_AlgtagToMechanism(cipherAlgorithm), keyLength); | |
647 if (!cipherParams) { | |
648 goto loser; | |
649 } | |
650 | |
651 PORT_Memset(&pbeV2_param, 0, sizeof (pbeV2_param)); | |
652 | |
653 rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams, | |
654 poolp, &pbeV2_param.cipherAlgId); | |
655 SECITEM_FreeItem(cipherParams, PR_TRUE); | |
656 if (rv != SECSuccess) { | |
657 goto loser; | |
658 } | |
659 } | |
660 | |
661 | |
662 /* generate the parameter */ | |
663 pbe_param = sec_pkcs5_create_pbe_parameter(pbeAlgorithm, salt, iteration, | |
664 keyLength, prfAlg); | |
665 if(!pbe_param) { | |
666 goto loser; | |
667 } | |
668 | |
669 /* generate the algorithm id */ | |
670 algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID)); | |
671 if(algid == NULL) { | |
672 goto loser; | |
673 } | |
674 | |
675 der_param.data = NULL; | |
676 der_param.len = 0; | |
677 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) { | |
678 /* first encode the PBE algorithm ID */ | |
679 dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, | |
680 SEC_PKCS5V2PBEParameterTemplate); | |
681 if (dummy == NULL) { | |
682 goto loser; | |
683 } | |
684 rv = SECOID_SetAlgorithmID(poolp, &pbeV2_param.pbeAlgId, | |
685 pbeAlgorithm, &der_param); | |
686 if (rv != SECSuccess) { | |
687 goto loser; | |
688 } | |
689 | |
690 /* now encode the Full PKCS 5 parameter */ | |
691 der_param.data = NULL; | |
692 der_param.len = 0; | |
693 dummy = SEC_ASN1EncodeItem(poolp, &der_param, &pbeV2_param, | |
694 SEC_PKCS5V2ParameterTemplate); | |
695 } else if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { | |
696 dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, | |
697 SEC_PKCS5PBEParameterTemplate); | |
698 } else { | |
699 dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, | |
700 SEC_V2PKCS12PBEParameterTemplate); | |
701 } | |
702 if (dummy == NULL) { | |
703 goto loser; | |
704 } | |
705 | |
706 rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param); | |
707 if (rv != SECSuccess) { | |
708 goto loser; | |
709 } | |
710 | |
711 ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID)); | |
712 if (ret_algid == NULL) { | |
713 goto loser; | |
714 } | |
715 | |
716 rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid); | |
717 if (rv != SECSuccess) { | |
718 SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE); | |
719 ret_algid = NULL; | |
720 } else if (pPbeAlgorithm) { | |
721 *pPbeAlgorithm = pbeAlgorithm; | |
722 } | |
723 | |
724 loser: | |
725 if (poolp != NULL) { | |
726 PORT_FreeArena(poolp, PR_TRUE); | |
727 algid = NULL; | |
728 } | |
729 | |
730 if (pbe_param) { | |
731 sec_pkcs5_destroy_pbe_param(pbe_param); | |
732 } | |
733 | |
734 return ret_algid; | |
735 } | |
736 | |
737 SECStatus | |
738 pbe_PK11AlgidToParam(SECAlgorithmID *algid,SECItem *mech) | |
739 { | |
740 SEC_PKCS5PBEParameter p5_param; | |
741 SECItem *salt = NULL; | |
742 SECOidTag algorithm = SECOID_GetAlgorithmTag(algid); | |
743 PLArenaPool *arena = NULL; | |
744 SECStatus rv = SECFailure; | |
745 unsigned char *paramData = NULL; | |
746 unsigned char *pSalt = NULL; | |
747 CK_ULONG iterations; | |
748 int paramLen = 0; | |
749 int iv_len; | |
750 | |
751 | |
752 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); | |
753 if (arena == NULL) { | |
754 goto loser; | |
755 } | |
756 | |
757 | |
758 /* | |
759 * decode the algid based on the pbe type | |
760 */ | |
761 PORT_Memset(&p5_param, 0, sizeof(p5_param)); | |
762 if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { | |
763 iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm)); | |
764 rv = SEC_ASN1DecodeItem(arena, &p5_param, | |
765 SEC_V2PKCS12PBEParameterTemplate, &algid->parameters); | |
766 } else if (algorithm == SEC_OID_PKCS5_PBKDF2) { | |
767 iv_len = 0; | |
768 rv = SEC_ASN1DecodeItem(arena,&p5_param, | |
769 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters); | |
770 } else { | |
771 iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm)); | |
772 rv = SEC_ASN1DecodeItem(arena,&p5_param,SEC_PKCS5PBEParameterTemplate, | |
773 &algid->parameters); | |
774 } | |
775 | |
776 if (iv_len < 0) { | |
777 goto loser; | |
778 } | |
779 | |
780 if (rv != SECSuccess) { | |
781 goto loser; | |
782 } | |
783 | |
784 /* get salt */ | |
785 salt = &p5_param.salt; | |
786 iterations = (CK_ULONG) DER_GetInteger(&p5_param.iteration); | |
787 | |
788 /* allocate and fill in the PKCS #11 parameters | |
789 * based on the algorithm. */ | |
790 if (algorithm == SEC_OID_PKCS5_PBKDF2) { | |
791 SECOidTag prfAlgTag; | |
792 CK_PKCS5_PBKD2_PARAMS *pbeV2_params = | |
793 (CK_PKCS5_PBKD2_PARAMS *)PORT_ZAlloc( | |
794 sizeof(CK_PKCS5_PBKD2_PARAMS)+ salt->len); | |
795 | |
796 if (pbeV2_params == NULL) { | |
797 goto loser; | |
798 } | |
799 paramData = (unsigned char *)pbeV2_params; | |
800 paramLen = sizeof(CK_PKCS5_PBKD2_PARAMS); | |
801 | |
802 /* set the prf */ | |
803 prfAlgTag = SEC_OID_HMAC_SHA1; | |
804 if (p5_param.pPrfAlgId && | |
805 p5_param.pPrfAlgId->algorithm.data != 0) { | |
806 prfAlgTag = SECOID_GetAlgorithmTag(p5_param.pPrfAlgId); | |
807 } | |
808 if (prfAlgTag == SEC_OID_HMAC_SHA1) { | |
809 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA1; | |
810 } else { | |
811 /* only SHA1_HMAC is currently supported by PKCS #11 */ | |
812 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
813 goto loser; | |
814 } | |
815 | |
816 /* probably should fetch these from the prfAlgid */ | |
817 pbeV2_params->pPrfData = NULL; | |
818 pbeV2_params->ulPrfDataLen = 0; | |
819 pbeV2_params->saltSource = CKZ_SALT_SPECIFIED; | |
820 pSalt = ((CK_CHAR_PTR) pbeV2_params)+sizeof(CK_PKCS5_PBKD2_PARAMS); | |
821 PORT_Memcpy(pSalt, salt->data, salt->len); | |
822 pbeV2_params->pSaltSourceData = pSalt; | |
823 pbeV2_params->ulSaltSourceDataLen = salt->len; | |
824 pbeV2_params->iterations = iterations; | |
825 } else { | |
826 CK_PBE_PARAMS *pbe_params = NULL; | |
827 pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS)+ | |
828 salt->len+iv_len); | |
829 if (pbe_params == NULL) { | |
830 goto loser; | |
831 } | |
832 paramData = (unsigned char *)pbe_params; | |
833 paramLen = sizeof(CK_PBE_PARAMS); | |
834 | |
835 pSalt = ((CK_CHAR_PTR) pbe_params)+sizeof(CK_PBE_PARAMS); | |
836 pbe_params->pSalt = pSalt; | |
837 PORT_Memcpy(pSalt, salt->data, salt->len); | |
838 pbe_params->ulSaltLen = salt->len; | |
839 if (iv_len) { | |
840 pbe_params->pInitVector = | |
841 ((CK_CHAR_PTR) pbe_params)+ sizeof(CK_PBE_PARAMS)+salt->len; | |
842 } | |
843 pbe_params->ulIteration = iterations; | |
844 } | |
845 | |
846 /* copy into the mechanism sec item */ | |
847 mech->data = paramData; | |
848 mech->len = paramLen; | |
849 if (arena) { | |
850 PORT_FreeArena(arena,PR_TRUE); | |
851 } | |
852 return SECSuccess; | |
853 | |
854 loser: | |
855 if (paramData) { | |
856 PORT_Free(paramData); | |
857 } | |
858 if (arena) { | |
859 PORT_FreeArena(arena,PR_TRUE); | |
860 } | |
861 return SECFailure; | |
862 } | |
863 | |
864 /* | |
865 * public, deprecated, not valid for pkcs5 v2 | |
866 * | |
867 * use PK11_CreatePBEV2AlgorithmID or PK11_CreatePBEAlgorithmID to create | |
868 * PBE algorithmID's directly. | |
869 */ | |
870 SECStatus | |
871 PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PLArenaPool *arena, | |
872 SECAlgorithmID *algId) | |
873 { | |
874 CK_PBE_PARAMS *pbe_param; | |
875 SECItem pbeSalt; | |
876 SECAlgorithmID *pbeAlgID = NULL; | |
877 SECStatus rv; | |
878 | |
879 if(!param || !algId) { | |
880 return SECFailure; | |
881 } | |
882 | |
883 pbe_param = (CK_PBE_PARAMS *)param->data; | |
884 pbeSalt.data = (unsigned char *)pbe_param->pSalt; | |
885 pbeSalt.len = pbe_param->ulSaltLen; | |
886 pbeAlgID = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN, | |
887 SEC_OID_UNKNOWN, NULL, 0, &pbeSalt, (int)pbe_param->ulIteration); | |
888 if(!pbeAlgID) { | |
889 return SECFailure; | |
890 } | |
891 | |
892 rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID); | |
893 SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE); | |
894 return rv; | |
895 } | |
896 | |
897 /* | |
898 * public, Deprecated, This function is only for binary compatibility with | |
899 * older applications. Does not support PKCS5v2. | |
900 * | |
901 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for | |
902 * iv values rather than generating PBE bits directly. | |
903 */ | |
904 PBEBitGenContext * | |
905 PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, | |
906 SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, | |
907 unsigned int iterations) | |
908 { | |
909 SECItem *context = NULL; | |
910 SECItem mechItem; | |
911 CK_PBE_PARAMS pbe_params; | |
912 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; | |
913 PK11SlotInfo *slot; | |
914 PK11SymKey *symKey = NULL; | |
915 unsigned char ivData[8]; | |
916 | |
917 | |
918 /* use the purpose to select the low level keygen algorithm */ | |
919 switch (bitGenPurpose) { | |
920 case pbeBitGenIntegrityKey: | |
921 switch (hashAlgorithm) { | |
922 case SEC_OID_SHA1: | |
923 mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC; | |
924 break; | |
925 case SEC_OID_MD2: | |
926 mechanism = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN; | |
927 break; | |
928 case SEC_OID_MD5: | |
929 mechanism = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN; | |
930 break; | |
931 default: | |
932 break; | |
933 } | |
934 break; | |
935 case pbeBitGenCipherIV: | |
936 if (bitsNeeded > 64) { | |
937 break; | |
938 } | |
939 if (hashAlgorithm != SEC_OID_SHA1) { | |
940 break; | |
941 } | |
942 mechanism = CKM_PBE_SHA1_DES3_EDE_CBC; | |
943 break; | |
944 case pbeBitGenCipherKey: | |
945 if (hashAlgorithm != SEC_OID_SHA1) { | |
946 break; | |
947 } | |
948 switch (bitsNeeded) { | |
949 case 40: | |
950 mechanism = CKM_PBE_SHA1_RC4_40; | |
951 break; | |
952 case 128: | |
953 mechanism = CKM_PBE_SHA1_RC4_128; | |
954 break; | |
955 default: | |
956 break; | |
957 } | |
958 case pbeBitGenIDNull: | |
959 break; | |
960 } | |
961 | |
962 if (mechanism == CKM_INVALID_MECHANISM) { | |
963 /* we should set an error, but this is a deprecated function, and | |
964 * we are keeping bug for bug compatibility;)... */ | |
965 return NULL; | |
966 } | |
967 | |
968 pbe_params.pInitVector = ivData; | |
969 pbe_params.pPassword = pwitem->data; | |
970 pbe_params.ulPasswordLen = pwitem->len; | |
971 pbe_params.pSalt = salt->data; | |
972 pbe_params.ulSaltLen = salt->len; | |
973 pbe_params.ulIteration = iterations; | |
974 mechItem.data = (unsigned char *) &pbe_params; | |
975 mechItem.len = sizeof(pbe_params); | |
976 | |
977 | |
978 slot = PK11_GetInternalSlot(); | |
979 symKey = PK11_RawPBEKeyGen(slot,mechanism, | |
980 &mechItem, pwitem, PR_FALSE, NULL); | |
981 PK11_FreeSlot(slot); | |
982 if (symKey != NULL) { | |
983 if (bitGenPurpose == pbeBitGenCipherIV) { | |
984 /* NOTE: this assumes that bitsNeeded is a multiple of 8! */ | |
985 SECItem ivItem; | |
986 | |
987 ivItem.data = ivData; | |
988 ivItem.len = bitsNeeded/8; | |
989 context = SECITEM_DupItem(&ivItem); | |
990 } else { | |
991 SECItem *keyData; | |
992 PK11_ExtractKeyValue(symKey); | |
993 keyData = PK11_GetKeyData(symKey); | |
994 | |
995 /* assert bitsNeeded with length? */ | |
996 if (keyData) { | |
997 context = SECITEM_DupItem(keyData); | |
998 } | |
999 } | |
1000 PK11_FreeSymKey(symKey); | |
1001 } | |
1002 | |
1003 return (PBEBitGenContext *)context; | |
1004 } | |
1005 | |
1006 /* | |
1007 * public, Deprecated, This function is only for binary compatibility with | |
1008 * older applications. Does not support PKCS5v2. | |
1009 * | |
1010 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetIV() for | |
1011 * iv values rather than generating PBE bits directly. | |
1012 */ | |
1013 SECItem * | |
1014 PBE_GenerateBits(PBEBitGenContext *context) | |
1015 { | |
1016 return (SECItem *)context; | |
1017 } | |
1018 | |
1019 /* | |
1020 * public, Deprecated, This function is only for binary compatibility with | |
1021 * older applications. Does not support PKCS5v2. | |
1022 * | |
1023 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for | |
1024 * iv values rather than generating PBE bits directly. | |
1025 */ | |
1026 void | |
1027 PBE_DestroyContext(PBEBitGenContext *context) | |
1028 { | |
1029 SECITEM_FreeItem((SECItem *)context,PR_TRUE); | |
1030 } | |
1031 | |
1032 /* | |
1033 * public, deprecated. Replaced with PK11_GetPBEIV(). | |
1034 */ | |
1035 SECItem * | |
1036 SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) | |
1037 { | |
1038 /* pbe stuff */ | |
1039 CK_MECHANISM_TYPE type; | |
1040 SECItem *param = NULL; | |
1041 SECItem *iv = NULL; | |
1042 SECItem src; | |
1043 int iv_len = 0; | |
1044 PK11SymKey *symKey; | |
1045 PK11SlotInfo *slot; | |
1046 CK_PBE_PARAMS_PTR pPBEparams; | |
1047 SECOidTag pbeAlg; | |
1048 | |
1049 pbeAlg = SECOID_GetAlgorithmTag(algid); | |
1050 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) { | |
1051 unsigned char *ivData; | |
1052 sec_pkcs5V2Parameter *pbeV2_param = NULL; | |
1053 | |
1054 /* can only return the IV if the crypto Algorithm exists */ | |
1055 if (pbeAlg == SEC_OID_PKCS5_PBKDF2) { | |
1056 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
1057 goto loser; | |
1058 } | |
1059 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); | |
1060 if (pbeV2_param == NULL) { | |
1061 goto loser; | |
1062 } | |
1063 /* extract the IV from the cipher algid portion of our pkcs 5 v2 | |
1064 * algorithm id */ | |
1065 type = PK11_AlgtagToMechanism( | |
1066 SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId)); | |
1067 param = PK11_ParamFromAlgid(&pbeV2_param->cipherAlgId); | |
1068 sec_pkcs5_v2_destroy_v2_param(pbeV2_param); | |
1069 if (!param) { | |
1070 goto loser; | |
1071 } | |
1072 /* NOTE: NULL is a permissible return here */ | |
1073 ivData = PK11_IVFromParam(type, param, &iv_len); | |
1074 src.data = ivData; | |
1075 src.len = iv_len; | |
1076 goto done; | |
1077 } | |
1078 | |
1079 type = PK11_AlgtagToMechanism(pbeAlg); | |
1080 param = PK11_ParamFromAlgid(algid); | |
1081 if (param == NULL) { | |
1082 goto done; | |
1083 } | |
1084 slot = PK11_GetInternalSlot(); | |
1085 symKey = PK11_RawPBEKeyGen(slot, type, param, pwitem, faulty3DES, NULL); | |
1086 PK11_FreeSlot(slot); | |
1087 if (symKey == NULL) { | |
1088 goto loser; | |
1089 } | |
1090 PK11_FreeSymKey(symKey); | |
1091 pPBEparams = (CK_PBE_PARAMS_PTR)param->data; | |
1092 iv_len = PK11_GetIVLength(type); | |
1093 | |
1094 src.data = (unsigned char *)pPBEparams->pInitVector; | |
1095 src.len = iv_len; | |
1096 | |
1097 done: | |
1098 iv = SECITEM_DupItem(&src); | |
1099 | |
1100 loser: | |
1101 if (param) { | |
1102 SECITEM_ZfreeItem(param, PR_TRUE); | |
1103 } | |
1104 return iv; | |
1105 } | |
1106 | |
1107 /* | |
1108 * Subs from nss 3.x that are deprecated | |
1109 */ | |
1110 PBEBitGenContext * | |
1111 __PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, | |
1112 SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, | |
1113 unsigned int iterations) | |
1114 { | |
1115 PORT_Assert("__PBE_CreateContext is Deprecated" == NULL); | |
1116 return NULL; | |
1117 } | |
1118 | |
1119 SECItem * | |
1120 __PBE_GenerateBits(PBEBitGenContext *context) | |
1121 { | |
1122 PORT_Assert("__PBE_GenerateBits is Deprecated" == NULL); | |
1123 return NULL; | |
1124 } | |
1125 | |
1126 void | |
1127 __PBE_DestroyContext(PBEBitGenContext *context) | |
1128 { | |
1129 PORT_Assert("__PBE_DestroyContext is Deprecated" == NULL); | |
1130 } | |
1131 | |
1132 SECStatus | |
1133 RSA_FormatBlock(SECItem *result, unsigned modulusLen, | |
1134 int blockType, SECItem *data) | |
1135 { | |
1136 PORT_Assert("RSA_FormatBlock is Deprecated" == NULL); | |
1137 return SECFailure; | |
1138 } | |
1139 | |
1140 /**************************************************************************** | |
1141 * | |
1142 * Now Do The PBE Functions Here... | |
1143 * | |
1144 ****************************************************************************/ | |
1145 | |
1146 static void | |
1147 pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params) | |
1148 { | |
1149 if (pbe_params) { | |
1150 if (pbe_params->pPassword) | |
1151 PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen); | |
1152 if (pbe_params->pSalt) | |
1153 PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen); | |
1154 PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS)); | |
1155 } | |
1156 } | |
1157 | |
1158 /* | |
1159 * public, deprecated. use PK11_CreatePBEAlgorithmID or | |
1160 * PK11_CreatePBEV2AlgorithmID instead. If you needthe pkcs #11 parameters, | |
1161 * use PK11_ParamFromAlgid from the algorithm id you created using | |
1162 * PK11_CreatePBEAlgorithmID or PK11_CreatePBEV2AlgorithmID. | |
1163 */ | |
1164 SECItem * | |
1165 PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations) | |
1166 { | |
1167 CK_PBE_PARAMS *pbe_params = NULL; | |
1168 SECItem *paramRV = NULL; | |
1169 | |
1170 paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS)); | |
1171 if (!paramRV ) { | |
1172 goto loser; | |
1173 } | |
1174 /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */ | |
1175 PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS)); | |
1176 | |
1177 pbe_params = (CK_PBE_PARAMS *)paramRV->data; | |
1178 pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len); | |
1179 if (!pbe_params->pPassword) { | |
1180 goto loser; | |
1181 } | |
1182 PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len); | |
1183 pbe_params->ulPasswordLen = pwd->len; | |
1184 | |
1185 pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len); | |
1186 if (!pbe_params->pSalt) { | |
1187 goto loser; | |
1188 } | |
1189 PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len); | |
1190 pbe_params->ulSaltLen = salt->len; | |
1191 | |
1192 pbe_params->ulIteration = (CK_ULONG)iterations; | |
1193 return paramRV; | |
1194 | |
1195 loser: | |
1196 if (pbe_params) | |
1197 pk11_destroy_ck_pbe_params(pbe_params); | |
1198 if (paramRV) | |
1199 PORT_ZFree(paramRV, sizeof(SECItem)); | |
1200 return NULL; | |
1201 } | |
1202 | |
1203 /* | |
1204 * public, deprecated. | |
1205 */ | |
1206 void | |
1207 PK11_DestroyPBEParams(SECItem *pItem) | |
1208 { | |
1209 if (pItem) { | |
1210 CK_PBE_PARAMS * params = (CK_PBE_PARAMS *)(pItem->data); | |
1211 if (params) | |
1212 pk11_destroy_ck_pbe_params(params); | |
1213 PORT_ZFree(pItem, sizeof(SECItem)); | |
1214 } | |
1215 } | |
1216 | |
1217 /* | |
1218 * public, Partially supports PKCS5 V2 (some parameters are not controllable | |
1219 * through this interface). Use PK11_CreatePBEV2AlgorithmID() if you need | |
1220 * finer control these. | |
1221 */ | |
1222 SECAlgorithmID * | |
1223 PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt) | |
1224 { | |
1225 SECAlgorithmID *algid = NULL; | |
1226 algid = sec_pkcs5CreateAlgorithmID(algorithm, | |
1227 SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, NULL, 0, salt, iteration); | |
1228 return algid; | |
1229 } | |
1230 | |
1231 /* | |
1232 * public, fully support pkcs5v2. | |
1233 */ | |
1234 SECAlgorithmID * | |
1235 PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag, | |
1236 SECOidTag prfAlgTag, int keyLength, int iteration, | |
1237 SECItem *salt) | |
1238 { | |
1239 SECAlgorithmID *algid = NULL; | |
1240 algid = sec_pkcs5CreateAlgorithmID(pbeAlgTag, cipherAlgTag, prfAlgTag, | |
1241 NULL, keyLength, salt, iteration); | |
1242 return algid; | |
1243 } | |
1244 | |
1245 /* | |
1246 * private. | |
1247 */ | |
1248 PK11SymKey * | |
1249 pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, | |
1250 SECItem *params, CK_KEY_TYPE keyType, int keyLen, | |
1251 SECItem *pwitem, void *wincx) | |
1252 { | |
1253 CK_ULONG pwLen; | |
1254 /* do some sanity checks */ | |
1255 if ((params == NULL) || (params->data == NULL)) { | |
1256 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1257 return NULL; | |
1258 } | |
1259 | |
1260 if (type == CKM_INVALID_MECHANISM) { | |
1261 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
1262 return NULL; | |
1263 } | |
1264 | |
1265 /* set the password pointer in the parameters... */ | |
1266 if (type == CKM_PKCS5_PBKD2) { | |
1267 CK_PKCS5_PBKD2_PARAMS *pbev2_params; | |
1268 if (params->len < sizeof(CK_PKCS5_PBKD2_PARAMS)) { | |
1269 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1270 return NULL; | |
1271 } | |
1272 pbev2_params = (CK_PKCS5_PBKD2_PARAMS *)params->data; | |
1273 pbev2_params->pPassword = pwitem->data; | |
1274 pwLen = pwitem->len; | |
1275 pbev2_params->ulPasswordLen = &pwLen; | |
1276 } else { | |
1277 CK_PBE_PARAMS *pbe_params; | |
1278 if (params->len < sizeof(CK_PBE_PARAMS)) { | |
1279 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1280 return NULL; | |
1281 } | |
1282 pbe_params = (CK_PBE_PARAMS *)params->data; | |
1283 pbe_params->pPassword = pwitem->data; | |
1284 pbe_params->ulPasswordLen = pwitem->len; | |
1285 } | |
1286 | |
1287 /* generate the key (and sometimes the IV as a side effect...) */ | |
1288 return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType, | |
1289 keyLen, NULL, CKF_SIGN|CKF_ENCRYPT|CKF_DECRYPT|CKF_UNWRAP|CKF_WRAP, | |
1290 0, wincx); | |
1291 } | |
1292 | |
1293 /* | |
1294 * public, deprecated. use PK11_PBEKeyGen instead. | |
1295 */ | |
1296 PK11SymKey * | |
1297 PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech, | |
1298 SECItem *pwitem, PRBool faulty3DES, void *wincx) | |
1299 { | |
1300 if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) { | |
1301 type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC; | |
1302 } | |
1303 return pk11_RawPBEKeyGenWithKeyType(slot, type, mech, -1, 0, pwitem, wincx); | |
1304 } | |
1305 | |
1306 /* | |
1307 * pubic, supports pkcs5 v2. | |
1308 * | |
1309 * Create symkey from a PBE key. The algid can be created with | |
1310 * PK11_CreatePBEV2AlgorithmID and PK11_CreatePBEAlgorithmID, or by | |
1311 * extraction of der data. | |
1312 */ | |
1313 PK11SymKey * | |
1314 PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem, | |
1315 PRBool faulty3DES, void *wincx) | |
1316 { | |
1317 CK_MECHANISM_TYPE type; | |
1318 SECItem *param = NULL; | |
1319 PK11SymKey *symKey = NULL; | |
1320 SECOidTag pbeAlg; | |
1321 CK_KEY_TYPE keyType = -1; | |
1322 int keyLen = 0; | |
1323 | |
1324 pbeAlg = SECOID_GetAlgorithmTag(algid); | |
1325 /* if we're using PKCS5v2, extract the additional information we need | |
1326 * (key length, key type, and pbeAlg). */ | |
1327 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) { | |
1328 CK_MECHANISM_TYPE cipherMech; | |
1329 sec_pkcs5V2Parameter *pbeV2_param; | |
1330 | |
1331 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid); | |
1332 if (pbeV2_param == NULL) { | |
1333 return NULL; | |
1334 } | |
1335 cipherMech = PK11_AlgtagToMechanism( | |
1336 SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId)); | |
1337 pbeAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId); | |
1338 param = PK11_ParamFromAlgid(&pbeV2_param->pbeAlgId); | |
1339 sec_pkcs5_v2_destroy_v2_param(pbeV2_param); | |
1340 keyLen = SEC_PKCS5GetKeyLength(algid); | |
1341 if (keyLen == -1) { | |
1342 keyLen = 0; | |
1343 } | |
1344 keyType = PK11_GetKeyType(cipherMech, keyLen); | |
1345 } else { | |
1346 param = PK11_ParamFromAlgid(algid); | |
1347 } | |
1348 | |
1349 if(param == NULL) { | |
1350 goto loser; | |
1351 } | |
1352 | |
1353 type = PK11_AlgtagToMechanism(pbeAlg); | |
1354 if (type == CKM_INVALID_MECHANISM) { | |
1355 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
1356 goto loser; | |
1357 } | |
1358 if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) { | |
1359 type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC; | |
1360 } | |
1361 symKey = pk11_RawPBEKeyGenWithKeyType(slot, type, param, keyType, keyLen, | |
1362 pwitem, wincx); | |
1363 | |
1364 loser: | |
1365 if (param) { | |
1366 SECITEM_ZfreeItem(param, PR_TRUE); | |
1367 } | |
1368 return symKey; | |
1369 } | |
1370 | |
1371 /* | |
1372 * public, supports pkcs5v2 | |
1373 */ | |
1374 SECItem * | |
1375 PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem) | |
1376 { | |
1377 return SEC_PKCS5GetIV(algid, pwitem, PR_FALSE); | |
1378 } | |
1379 | |
1380 CK_MECHANISM_TYPE | |
1381 pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, | |
1382 SECItem *pbe_pwd, PRBool faulty3DES) | |
1383 { | |
1384 int keyLen = 0; | |
1385 SECOidTag algTag = SEC_PKCS5GetCryptoAlgorithm(algid); | |
1386 CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(algTag); | |
1387 CK_MECHANISM_TYPE returnedMechanism = CKM_INVALID_MECHANISM; | |
1388 SECItem *iv = NULL; | |
1389 | |
1390 if (mech == CKM_INVALID_MECHANISM) { | |
1391 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
1392 goto loser; | |
1393 } | |
1394 if (PK11_GetIVLength(mech)) { | |
1395 iv = SEC_PKCS5GetIV(algid, pbe_pwd, faulty3DES); | |
1396 if (iv == NULL) { | |
1397 goto loser; | |
1398 } | |
1399 } | |
1400 | |
1401 keyLen = SEC_PKCS5GetKeyLength(algid); | |
1402 | |
1403 *param = pk11_ParamFromIVWithLen(mech, iv, keyLen); | |
1404 if (*param == NULL) { | |
1405 goto loser; | |
1406 } | |
1407 returnedMechanism = mech; | |
1408 | |
1409 loser: | |
1410 if (iv) { | |
1411 SECITEM_FreeItem(iv,PR_TRUE); | |
1412 } | |
1413 return returnedMechanism; | |
1414 } | |
1415 | |
1416 /* | |
1417 * Public, supports pkcs5 v2 | |
1418 * | |
1419 * Get the crypto mechanism directly from the pbe algorithmid. | |
1420 * | |
1421 * It's important to go directly from the algorithm id so that we can | |
1422 * handle both the PKCS #5 v1, PKCS #12, and PKCS #5 v2 cases. | |
1423 * | |
1424 * This function returns both the mechanism and the parameter for the mechanism. | |
1425 * The caller is responsible for freeing the parameter. | |
1426 */ | |
1427 CK_MECHANISM_TYPE | |
1428 PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param, | |
1429 SECItem *pbe_pwd) | |
1430 { | |
1431 return pk11_GetPBECryptoMechanism(algid, param, pbe_pwd, PR_FALSE); | |
1432 } |