Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: nss/lib/pk11wrap/pk11pbe.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/pk11wrap/pk11pars.c ('k') | nss/lib/pk11wrap/pk11pk12.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_C BC;
271 case 128:
272 case 92:
273 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_C BC;
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 SEC_OID_HMAC_SHA1 is the default */
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 switch (prfAlgTag) {
809 case SEC_OID_HMAC_SHA1:
810 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
811 break;
812 case SEC_OID_HMAC_SHA224:
813 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA224;
814 break;
815 case SEC_OID_HMAC_SHA256:
816 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA256;
817 break;
818 case SEC_OID_HMAC_SHA384:
819 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA384;
820 break;
821 case SEC_OID_HMAC_SHA512:
822 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA512;
823 break;
824 default:
825 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
826 goto loser;
827 }
828
829 /* probably should fetch these from the prfAlgid */
830 pbeV2_params->pPrfData = NULL;
831 pbeV2_params->ulPrfDataLen = 0;
832 pbeV2_params->saltSource = CKZ_SALT_SPECIFIED;
833 pSalt = ((CK_CHAR_PTR) pbeV2_params)+sizeof(CK_PKCS5_PBKD2_PARAMS);
834 PORT_Memcpy(pSalt, salt->data, salt->len);
835 pbeV2_params->pSaltSourceData = pSalt;
836 pbeV2_params->ulSaltSourceDataLen = salt->len;
837 pbeV2_params->iterations = iterations;
838 } else {
839 CK_PBE_PARAMS *pbe_params = NULL;
840 pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS)+
841 salt->len+iv_len);
842 if (pbe_params == NULL) {
843 goto loser;
844 }
845 paramData = (unsigned char *)pbe_params;
846 paramLen = sizeof(CK_PBE_PARAMS);
847
848 pSalt = ((CK_CHAR_PTR) pbe_params)+sizeof(CK_PBE_PARAMS);
849 pbe_params->pSalt = pSalt;
850 PORT_Memcpy(pSalt, salt->data, salt->len);
851 pbe_params->ulSaltLen = salt->len;
852 if (iv_len) {
853 pbe_params->pInitVector =
854 ((CK_CHAR_PTR) pbe_params)+ sizeof(CK_PBE_PARAMS)+salt->len;
855 }
856 pbe_params->ulIteration = iterations;
857 }
858
859 /* copy into the mechanism sec item */
860 mech->data = paramData;
861 mech->len = paramLen;
862 if (arena) {
863 PORT_FreeArena(arena,PR_TRUE);
864 }
865 return SECSuccess;
866
867 loser:
868 if (paramData) {
869 PORT_Free(paramData);
870 }
871 if (arena) {
872 PORT_FreeArena(arena,PR_TRUE);
873 }
874 return SECFailure;
875 }
876
877 /*
878 * public, deprecated, not valid for pkcs5 v2
879 *
880 * use PK11_CreatePBEV2AlgorithmID or PK11_CreatePBEAlgorithmID to create
881 * PBE algorithmID's directly.
882 */
883 SECStatus
884 PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PLArenaPool *arena,
885 SECAlgorithmID *algId)
886 {
887 CK_PBE_PARAMS *pbe_param;
888 SECItem pbeSalt;
889 SECAlgorithmID *pbeAlgID = NULL;
890 SECStatus rv;
891
892 if(!param || !algId) {
893 return SECFailure;
894 }
895
896 pbe_param = (CK_PBE_PARAMS *)param->data;
897 pbeSalt.data = (unsigned char *)pbe_param->pSalt;
898 pbeSalt.len = pbe_param->ulSaltLen;
899 pbeAlgID = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN,
900 SEC_OID_UNKNOWN, NULL, 0, &pbeSalt, (int)pbe_param->ulIteration);
901 if(!pbeAlgID) {
902 return SECFailure;
903 }
904
905 rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID);
906 SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE);
907 return rv;
908 }
909
910 /*
911 * public, Deprecated, This function is only for binary compatibility with
912 * older applications. Does not support PKCS5v2.
913 *
914 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
915 * iv values rather than generating PBE bits directly.
916 */
917 PBEBitGenContext *
918 PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
919 SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
920 unsigned int iterations)
921 {
922 SECItem *context = NULL;
923 SECItem mechItem;
924 CK_PBE_PARAMS pbe_params;
925 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
926 PK11SlotInfo *slot;
927 PK11SymKey *symKey = NULL;
928 unsigned char ivData[8];
929
930
931 /* use the purpose to select the low level keygen algorithm */
932 switch (bitGenPurpose) {
933 case pbeBitGenIntegrityKey:
934 switch (hashAlgorithm) {
935 case SEC_OID_SHA1:
936 mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC;
937 break;
938 case SEC_OID_MD2:
939 mechanism = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN;
940 break;
941 case SEC_OID_MD5:
942 mechanism = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN;
943 break;
944 default:
945 break;
946 }
947 break;
948 case pbeBitGenCipherIV:
949 if (bitsNeeded > 64) {
950 break;
951 }
952 if (hashAlgorithm != SEC_OID_SHA1) {
953 break;
954 }
955 mechanism = CKM_PBE_SHA1_DES3_EDE_CBC;
956 break;
957 case pbeBitGenCipherKey:
958 if (hashAlgorithm != SEC_OID_SHA1) {
959 break;
960 }
961 switch (bitsNeeded) {
962 case 40:
963 mechanism = CKM_PBE_SHA1_RC4_40;
964 break;
965 case 128:
966 mechanism = CKM_PBE_SHA1_RC4_128;
967 break;
968 default:
969 break;
970 }
971 case pbeBitGenIDNull:
972 break;
973 }
974
975 if (mechanism == CKM_INVALID_MECHANISM) {
976 /* we should set an error, but this is a deprecated function, and
977 * we are keeping bug for bug compatibility;)... */
978 return NULL;
979 }
980
981 pbe_params.pInitVector = ivData;
982 pbe_params.pPassword = pwitem->data;
983 pbe_params.ulPasswordLen = pwitem->len;
984 pbe_params.pSalt = salt->data;
985 pbe_params.ulSaltLen = salt->len;
986 pbe_params.ulIteration = iterations;
987 mechItem.data = (unsigned char *) &pbe_params;
988 mechItem.len = sizeof(pbe_params);
989
990
991 slot = PK11_GetInternalSlot();
992 symKey = PK11_RawPBEKeyGen(slot,mechanism,
993 &mechItem, pwitem, PR_FALSE, NULL);
994 PK11_FreeSlot(slot);
995 if (symKey != NULL) {
996 if (bitGenPurpose == pbeBitGenCipherIV) {
997 /* NOTE: this assumes that bitsNeeded is a multiple of 8! */
998 SECItem ivItem;
999
1000 ivItem.data = ivData;
1001 ivItem.len = bitsNeeded/8;
1002 context = SECITEM_DupItem(&ivItem);
1003 } else {
1004 SECItem *keyData;
1005 PK11_ExtractKeyValue(symKey);
1006 keyData = PK11_GetKeyData(symKey);
1007
1008 /* assert bitsNeeded with length? */
1009 if (keyData) {
1010 context = SECITEM_DupItem(keyData);
1011 }
1012 }
1013 PK11_FreeSymKey(symKey);
1014 }
1015
1016 return (PBEBitGenContext *)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_GetIV() for
1024 * iv values rather than generating PBE bits directly.
1025 */
1026 SECItem *
1027 PBE_GenerateBits(PBEBitGenContext *context)
1028 {
1029 return (SECItem *)context;
1030 }
1031
1032 /*
1033 * public, Deprecated, This function is only for binary compatibility with
1034 * older applications. Does not support PKCS5v2.
1035 *
1036 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
1037 * iv values rather than generating PBE bits directly.
1038 */
1039 void
1040 PBE_DestroyContext(PBEBitGenContext *context)
1041 {
1042 SECITEM_FreeItem((SECItem *)context,PR_TRUE);
1043 }
1044
1045 /*
1046 * public, deprecated. Replaced with PK11_GetPBEIV().
1047 */
1048 SECItem *
1049 SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
1050 {
1051 /* pbe stuff */
1052 CK_MECHANISM_TYPE type;
1053 SECItem *param = NULL;
1054 SECItem *iv = NULL;
1055 SECItem src;
1056 int iv_len = 0;
1057 PK11SymKey *symKey;
1058 PK11SlotInfo *slot;
1059 CK_PBE_PARAMS_PTR pPBEparams;
1060 SECOidTag pbeAlg;
1061
1062 pbeAlg = SECOID_GetAlgorithmTag(algid);
1063 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
1064 unsigned char *ivData;
1065 sec_pkcs5V2Parameter *pbeV2_param = NULL;
1066
1067 /* can only return the IV if the crypto Algorithm exists */
1068 if (pbeAlg == SEC_OID_PKCS5_PBKDF2) {
1069 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1070 goto loser;
1071 }
1072 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
1073 if (pbeV2_param == NULL) {
1074 goto loser;
1075 }
1076 /* extract the IV from the cipher algid portion of our pkcs 5 v2
1077 * algorithm id */
1078 type = PK11_AlgtagToMechanism(
1079 SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
1080 param = PK11_ParamFromAlgid(&pbeV2_param->cipherAlgId);
1081 sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
1082 if (!param) {
1083 goto loser;
1084 }
1085 /* NOTE: NULL is a permissible return here */
1086 ivData = PK11_IVFromParam(type, param, &iv_len);
1087 src.data = ivData;
1088 src.len = iv_len;
1089 goto done;
1090 }
1091
1092 type = PK11_AlgtagToMechanism(pbeAlg);
1093 param = PK11_ParamFromAlgid(algid);
1094 if (param == NULL) {
1095 goto done;
1096 }
1097 slot = PK11_GetInternalSlot();
1098 symKey = PK11_RawPBEKeyGen(slot, type, param, pwitem, faulty3DES, NULL);
1099 PK11_FreeSlot(slot);
1100 if (symKey == NULL) {
1101 goto loser;
1102 }
1103 PK11_FreeSymKey(symKey);
1104 pPBEparams = (CK_PBE_PARAMS_PTR)param->data;
1105 iv_len = PK11_GetIVLength(type);
1106
1107 src.data = (unsigned char *)pPBEparams->pInitVector;
1108 src.len = iv_len;
1109
1110 done:
1111 iv = SECITEM_DupItem(&src);
1112
1113 loser:
1114 if (param) {
1115 SECITEM_ZfreeItem(param, PR_TRUE);
1116 }
1117 return iv;
1118 }
1119
1120 /*
1121 * Subs from nss 3.x that are deprecated
1122 */
1123 PBEBitGenContext *
1124 __PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
1125 SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
1126 unsigned int iterations)
1127 {
1128 PORT_Assert("__PBE_CreateContext is Deprecated" == NULL);
1129 return NULL;
1130 }
1131
1132 SECItem *
1133 __PBE_GenerateBits(PBEBitGenContext *context)
1134 {
1135 PORT_Assert("__PBE_GenerateBits is Deprecated" == NULL);
1136 return NULL;
1137 }
1138
1139 void
1140 __PBE_DestroyContext(PBEBitGenContext *context)
1141 {
1142 PORT_Assert("__PBE_DestroyContext is Deprecated" == NULL);
1143 }
1144
1145 SECStatus
1146 RSA_FormatBlock(SECItem *result, unsigned modulusLen,
1147 int blockType, SECItem *data)
1148 {
1149 PORT_Assert("RSA_FormatBlock is Deprecated" == NULL);
1150 return SECFailure;
1151 }
1152
1153 /****************************************************************************
1154 *
1155 * Now Do The PBE Functions Here...
1156 *
1157 ****************************************************************************/
1158
1159 static void
1160 pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params)
1161 {
1162 if (pbe_params) {
1163 if (pbe_params->pPassword)
1164 PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen);
1165 if (pbe_params->pSalt)
1166 PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen);
1167 PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS));
1168 }
1169 }
1170
1171 /*
1172 * public, deprecated. use PK11_CreatePBEAlgorithmID or
1173 * PK11_CreatePBEV2AlgorithmID instead. If you needthe pkcs #11 parameters,
1174 * use PK11_ParamFromAlgid from the algorithm id you created using
1175 * PK11_CreatePBEAlgorithmID or PK11_CreatePBEV2AlgorithmID.
1176 */
1177 SECItem *
1178 PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations)
1179 {
1180 CK_PBE_PARAMS *pbe_params = NULL;
1181 SECItem *paramRV = NULL;
1182
1183 paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS));
1184 if (!paramRV ) {
1185 goto loser;
1186 }
1187 /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */
1188 PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS));
1189
1190 pbe_params = (CK_PBE_PARAMS *)paramRV->data;
1191 pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len);
1192 if (!pbe_params->pPassword) {
1193 goto loser;
1194 }
1195 PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len);
1196 pbe_params->ulPasswordLen = pwd->len;
1197
1198 pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len);
1199 if (!pbe_params->pSalt) {
1200 goto loser;
1201 }
1202 PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len);
1203 pbe_params->ulSaltLen = salt->len;
1204
1205 pbe_params->ulIteration = (CK_ULONG)iterations;
1206 return paramRV;
1207
1208 loser:
1209 if (pbe_params)
1210 pk11_destroy_ck_pbe_params(pbe_params);
1211 if (paramRV)
1212 PORT_ZFree(paramRV, sizeof(SECItem));
1213 return NULL;
1214 }
1215
1216 /*
1217 * public, deprecated.
1218 */
1219 void
1220 PK11_DestroyPBEParams(SECItem *pItem)
1221 {
1222 if (pItem) {
1223 CK_PBE_PARAMS * params = (CK_PBE_PARAMS *)(pItem->data);
1224 if (params)
1225 pk11_destroy_ck_pbe_params(params);
1226 PORT_ZFree(pItem, sizeof(SECItem));
1227 }
1228 }
1229
1230 /*
1231 * public, Partially supports PKCS5 V2 (some parameters are not controllable
1232 * through this interface). Use PK11_CreatePBEV2AlgorithmID() if you need
1233 * finer control these.
1234 */
1235 SECAlgorithmID *
1236 PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt)
1237 {
1238 SECAlgorithmID *algid = NULL;
1239 algid = sec_pkcs5CreateAlgorithmID(algorithm,
1240 SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, NULL, 0, salt, iteration);
1241 return algid;
1242 }
1243
1244 /*
1245 * public, fully support pkcs5v2.
1246 */
1247 SECAlgorithmID *
1248 PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag,
1249 SECOidTag prfAlgTag, int keyLength, int iteration,
1250 SECItem *salt)
1251 {
1252 SECAlgorithmID *algid = NULL;
1253 algid = sec_pkcs5CreateAlgorithmID(pbeAlgTag, cipherAlgTag, prfAlgTag,
1254 NULL, keyLength, salt, iteration);
1255 return algid;
1256 }
1257
1258 /*
1259 * private.
1260 */
1261 PK11SymKey *
1262 pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
1263 SECItem *params, CK_KEY_TYPE keyType, int keyLen,
1264 SECItem *pwitem, void *wincx)
1265 {
1266 CK_ULONG pwLen;
1267 /* do some sanity checks */
1268 if ((params == NULL) || (params->data == NULL)) {
1269 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1270 return NULL;
1271 }
1272
1273 if (type == CKM_INVALID_MECHANISM) {
1274 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1275 return NULL;
1276 }
1277
1278 /* set the password pointer in the parameters... */
1279 if (type == CKM_PKCS5_PBKD2) {
1280 CK_PKCS5_PBKD2_PARAMS *pbev2_params;
1281 if (params->len < sizeof(CK_PKCS5_PBKD2_PARAMS)) {
1282 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1283 return NULL;
1284 }
1285 pbev2_params = (CK_PKCS5_PBKD2_PARAMS *)params->data;
1286 pbev2_params->pPassword = pwitem->data;
1287 pwLen = pwitem->len;
1288 pbev2_params->ulPasswordLen = &pwLen;
1289 } else {
1290 CK_PBE_PARAMS *pbe_params;
1291 if (params->len < sizeof(CK_PBE_PARAMS)) {
1292 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1293 return NULL;
1294 }
1295 pbe_params = (CK_PBE_PARAMS *)params->data;
1296 pbe_params->pPassword = pwitem->data;
1297 pbe_params->ulPasswordLen = pwitem->len;
1298 }
1299
1300 /* generate the key (and sometimes the IV as a side effect...) */
1301 return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType,
1302 keyLen, NULL, CKF_SIGN|CKF_ENCRYPT|CKF_DECRYPT|CKF_UNWRAP|CKF_WRAP,
1303 0, wincx);
1304 }
1305
1306 /*
1307 * public, deprecated. use PK11_PBEKeyGen instead.
1308 */
1309 PK11SymKey *
1310 PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech,
1311 SECItem *pwitem, PRBool faulty3DES, void *wincx)
1312 {
1313 if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
1314 type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
1315 }
1316 return pk11_RawPBEKeyGenWithKeyType(slot, type, mech, -1, 0, pwitem, wincx);
1317 }
1318
1319 /*
1320 * pubic, supports pkcs5 v2.
1321 *
1322 * Create symkey from a PBE key. The algid can be created with
1323 * PK11_CreatePBEV2AlgorithmID and PK11_CreatePBEAlgorithmID, or by
1324 * extraction of der data.
1325 */
1326 PK11SymKey *
1327 PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem,
1328 PRBool faulty3DES, void *wincx)
1329 {
1330 CK_MECHANISM_TYPE type;
1331 SECItem *param = NULL;
1332 PK11SymKey *symKey = NULL;
1333 SECOidTag pbeAlg;
1334 CK_KEY_TYPE keyType = -1;
1335 int keyLen = 0;
1336
1337 pbeAlg = SECOID_GetAlgorithmTag(algid);
1338 /* if we're using PKCS5v2, extract the additional information we need
1339 * (key length, key type, and pbeAlg). */
1340 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
1341 CK_MECHANISM_TYPE cipherMech;
1342 sec_pkcs5V2Parameter *pbeV2_param;
1343
1344 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
1345 if (pbeV2_param == NULL) {
1346 return NULL;
1347 }
1348 cipherMech = PK11_AlgtagToMechanism(
1349 SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
1350 pbeAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId);
1351 param = PK11_ParamFromAlgid(&pbeV2_param->pbeAlgId);
1352 sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
1353 keyLen = SEC_PKCS5GetKeyLength(algid);
1354 if (keyLen == -1) {
1355 keyLen = 0;
1356 }
1357 keyType = PK11_GetKeyType(cipherMech, keyLen);
1358 } else {
1359 param = PK11_ParamFromAlgid(algid);
1360 }
1361
1362 if(param == NULL) {
1363 goto loser;
1364 }
1365
1366 type = PK11_AlgtagToMechanism(pbeAlg);
1367 if (type == CKM_INVALID_MECHANISM) {
1368 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1369 goto loser;
1370 }
1371 if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
1372 type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
1373 }
1374 symKey = pk11_RawPBEKeyGenWithKeyType(slot, type, param, keyType, keyLen,
1375 pwitem, wincx);
1376
1377 loser:
1378 if (param) {
1379 SECITEM_ZfreeItem(param, PR_TRUE);
1380 }
1381 return symKey;
1382 }
1383
1384 /*
1385 * public, supports pkcs5v2
1386 */
1387 SECItem *
1388 PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem)
1389 {
1390 return SEC_PKCS5GetIV(algid, pwitem, PR_FALSE);
1391 }
1392
1393 CK_MECHANISM_TYPE
1394 pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param,
1395 SECItem *pbe_pwd, PRBool faulty3DES)
1396 {
1397 int keyLen = 0;
1398 SECOidTag algTag = SEC_PKCS5GetCryptoAlgorithm(algid);
1399 CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(algTag);
1400 CK_MECHANISM_TYPE returnedMechanism = CKM_INVALID_MECHANISM;
1401 SECItem *iv = NULL;
1402
1403 if (mech == CKM_INVALID_MECHANISM) {
1404 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1405 goto loser;
1406 }
1407 if (PK11_GetIVLength(mech)) {
1408 iv = SEC_PKCS5GetIV(algid, pbe_pwd, faulty3DES);
1409 if (iv == NULL) {
1410 goto loser;
1411 }
1412 }
1413
1414 keyLen = SEC_PKCS5GetKeyLength(algid);
1415
1416 *param = pk11_ParamFromIVWithLen(mech, iv, keyLen);
1417 if (*param == NULL) {
1418 goto loser;
1419 }
1420 returnedMechanism = mech;
1421
1422 loser:
1423 if (iv) {
1424 SECITEM_FreeItem(iv,PR_TRUE);
1425 }
1426 return returnedMechanism;
1427 }
1428
1429 /*
1430 * Public, supports pkcs5 v2
1431 *
1432 * Get the crypto mechanism directly from the pbe algorithmid.
1433 *
1434 * It's important to go directly from the algorithm id so that we can
1435 * handle both the PKCS #5 v1, PKCS #12, and PKCS #5 v2 cases.
1436 *
1437 * This function returns both the mechanism and the parameter for the mechanism.
1438 * The caller is responsible for freeing the parameter.
1439 */
1440 CK_MECHANISM_TYPE
1441 PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param,
1442 SECItem *pbe_pwd)
1443 {
1444 return pk11_GetPBECryptoMechanism(algid, param, pbe_pwd, PR_FALSE);
1445 }
OLDNEW
« no previous file with comments | « nss/lib/pk11wrap/pk11pars.c ('k') | nss/lib/pk11wrap/pk11pk12.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698