Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / security / nss / lib / pk11wrap / pk11pbe.c
blobfa35f02e3b43401e02642bb5ce9be86ae189f10c
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #include "plarena.h"
39 #include "seccomon.h"
40 #include "secitem.h"
41 #include "secport.h"
42 #include "hasht.h"
43 #include "pkcs11t.h"
44 #include "sechash.h"
45 #include "secasn1.h"
46 #include "secder.h"
47 #include "secoid.h"
48 #include "secerr.h"
49 #include "secmod.h"
50 #include "pk11func.h"
51 #include "secpkcs5.h"
52 #include "secmodi.h"
53 #include "secmodti.h"
54 #include "pkcs11.h"
55 #include "pk11func.h"
56 #include "secitem.h"
57 #include "key.h"
59 typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter;
60 struct SEC_PKCS5PBEParameterStr {
61 PRArenaPool *poolp;
62 SECItem salt; /* octet string */
63 SECItem iteration; /* integer */
64 SECItem keyLength; /* PKCS5v2 only */
65 SECAlgorithmID *pPrfAlgId; /* PKCS5v2 only */
66 SECAlgorithmID prfAlgId; /* PKCS5v2 only */
69 /* PKCS5 V2 has an algorithm ID for the encryption and for
70 * the key generation. This is valid for SEC_OID_PKCS5_PBES2
71 * and SEC_OID_PKCS5_PBMAC1
73 struct sec_pkcs5V2ParameterStr {
74 PRArenaPool *poolp;
75 SECAlgorithmID pbeAlgId; /* real pbe algorithms */
76 SECAlgorithmID cipherAlgId; /* encryption/mac */
79 typedef struct sec_pkcs5V2ParameterStr sec_pkcs5V2Parameter;
82 /* template for PKCS 5 PBE Parameter. This template has been expanded
83 * based upon the additions in PKCS 12. This should eventually be moved
84 * if RSA updates PKCS 5.
86 const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] =
88 { SEC_ASN1_SEQUENCE,
89 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
90 { SEC_ASN1_OCTET_STRING,
91 offsetof(SEC_PKCS5PBEParameter, salt) },
92 { SEC_ASN1_INTEGER,
93 offsetof(SEC_PKCS5PBEParameter, iteration) },
94 { 0 }
97 const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] =
99 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
100 { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
101 { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
102 { 0 }
105 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
107 /* SECOID_PKCS5_PBKDF2 */
108 const SEC_ASN1Template SEC_PKCS5V2PBEParameterTemplate[] =
110 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
111 /* This is really a choice, but since we only understand this
112 * choice, just inline it */
113 { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
114 { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
115 { SEC_ASN1_INTEGER|SEC_ASN1_OPTIONAL,
116 offsetof(SEC_PKCS5PBEParameter, keyLength) },
117 { SEC_ASN1_POINTER | SEC_ASN1_XTRN | SEC_ASN1_OPTIONAL,
118 offsetof(SEC_PKCS5PBEParameter, pPrfAlgId),
119 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
120 { 0 }
123 /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
124 const SEC_ASN1Template SEC_PKCS5V2ParameterTemplate[] =
126 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
127 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(sec_pkcs5V2Parameter, pbeAlgId),
128 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
129 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
130 offsetof(sec_pkcs5V2Parameter, cipherAlgId),
131 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
132 { 0 }
137 * maps a PBE algorithm to a crypto algorithm. for PKCS12 and PKCS5v1
138 * for PKCS5v2 it returns SEC_OID_PKCS5_PBKDF2.
140 SECOidTag
141 sec_pkcs5GetCryptoFromAlgTag(SECOidTag algorithm)
143 switch(algorithm)
145 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
146 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
147 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
148 return SEC_OID_DES_EDE3_CBC;
149 case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
150 case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
151 case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
152 return SEC_OID_DES_CBC;
153 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
154 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
155 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
156 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
157 return SEC_OID_RC2_CBC;
158 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
159 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
160 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
161 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
162 return SEC_OID_RC4;
163 case SEC_OID_PKCS5_PBKDF2:
164 case SEC_OID_PKCS5_PBES2:
165 case SEC_OID_PKCS5_PBMAC1:
166 return SEC_OID_PKCS5_PBKDF2;
167 default:
168 break;
171 return SEC_OID_UNKNOWN;
175 * get a new PKCS5 V2 Parameter from the algorithm id.
176 * if arena is passed in, use it, otherwise create a new arena.
178 sec_pkcs5V2Parameter *
179 sec_pkcs5_v2_get_v2_param(PRArenaPool *arena, SECAlgorithmID *algid)
181 PRArenaPool *localArena = NULL;
182 sec_pkcs5V2Parameter *pbeV2_param;
183 SECStatus rv;
185 if (arena == NULL) {
186 localArena = arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
187 if (arena == NULL) {
188 return NULL;
191 pbeV2_param = PORT_ArenaZNew(arena, sec_pkcs5V2Parameter);
192 if (pbeV2_param == NULL) {
193 goto loser;
196 rv = SEC_ASN1DecodeItem(arena, pbeV2_param,
197 SEC_PKCS5V2ParameterTemplate, &algid->parameters);
198 if (rv == SECFailure) {
199 goto loser;
202 pbeV2_param->poolp = arena;
203 return pbeV2_param;
204 loser:
205 if (localArena) {
206 PORT_FreeArena(arena, PR_FALSE);
208 return NULL;
211 void
212 sec_pkcs5_v2_destroy_v2_param(sec_pkcs5V2Parameter *param)
214 if (param && param->poolp) {
215 PORT_FreeArena(param->poolp, PR_TRUE);
220 /* maps crypto algorithm from PBE algorithm.
222 SECOidTag
223 SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid)
226 SECOidTag pbeAlg;
227 SECOidTag cipherAlg;
229 if(algid == NULL)
230 return SEC_OID_UNKNOWN;
232 pbeAlg = SECOID_GetAlgorithmTag(algid);
233 cipherAlg = sec_pkcs5GetCryptoFromAlgTag(pbeAlg);
234 if ((cipherAlg == SEC_OID_PKCS5_PBKDF2) &&
235 (pbeAlg != SEC_OID_PKCS5_PBKDF2)) {
236 sec_pkcs5V2Parameter *pbeV2_param;
237 cipherAlg = SEC_OID_UNKNOWN;
239 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
240 if (pbeV2_param != NULL) {
241 cipherAlg = SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId);
242 sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
246 return cipherAlg;
249 /* check to see if an oid is a pbe algorithm
251 PRBool
252 SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid)
254 return (PRBool)(SEC_PKCS5GetCryptoAlgorithm(algid) != SEC_OID_UNKNOWN);
257 PRBool
258 SEC_PKCS5IsAlgorithmPBEAlgTag(SECOidTag algtag)
260 return (PRBool)(sec_pkcs5GetCryptoFromAlgTag(algtag) != SEC_OID_UNKNOWN);
264 * find the most appropriate PKCS5v2 overall oid tag from a regular
265 * cipher/hash algorithm tag.
267 static SECOidTag
268 sec_pkcs5v2_get_pbe(SECOidTag algTag)
270 /* if it's a valid hash oid... */
271 if (HASH_GetHashOidTagByHMACOidTag(algTag) != SEC_OID_UNKNOWN) {
272 /* use the MAC tag */
273 return SEC_OID_PKCS5_PBMAC1;
275 if (HASH_GetHashTypeByOidTag(algTag) != HASH_AlgNULL) {
276 /* eliminate Hash algorithms */
277 return SEC_OID_UNKNOWN;
279 if (PK11_AlgtagToMechanism(algTag) != CKM_INVALID_MECHANISM) {
280 /* it's not a hash, if it has a PKCS #11 mechanism associated
281 * with it, assume it's a cipher. (NOTE this will generate
282 * some false positives). */
283 return SEC_OID_PKCS5_PBES2;
285 return SEC_OID_UNKNOWN;
289 * maps PBE algorithm from crypto algorithm, assumes SHA1 hashing.
290 * input keyLen in bits.
292 SECOidTag
293 SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen)
295 switch(algTag)
297 case SEC_OID_DES_EDE3_CBC:
298 switch(keyLen) {
299 case 168:
300 case 192:
301 case 0:
302 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
303 case 128:
304 case 92:
305 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
306 default:
307 break;
309 break;
310 case SEC_OID_DES_CBC:
311 return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
312 case SEC_OID_RC2_CBC:
313 switch(keyLen) {
314 case 40:
315 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
316 case 128:
317 case 0:
318 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
319 default:
320 break;
322 break;
323 case SEC_OID_RC4:
324 switch(keyLen) {
325 case 40:
326 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
327 case 128:
328 case 0:
329 return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
330 default:
331 break;
333 break;
334 default:
335 return sec_pkcs5v2_get_pbe(algTag);
338 return SEC_OID_UNKNOWN;
342 * get the key length in bytes from a PKCS5 PBE
345 sec_pkcs5v2_key_length(SECAlgorithmID *algid)
347 SECOidTag algorithm;
348 PRArenaPool *arena = NULL;
349 SEC_PKCS5PBEParameter p5_param;
350 SECStatus rv;
351 int length = -1;
353 algorithm = SECOID_GetAlgorithmTag(algid);
354 /* sanity check, they should all be PBKDF2 here */
355 if (algorithm != SEC_OID_PKCS5_PBKDF2) {
356 return -1;
359 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
360 if (arena == NULL) {
361 goto loser;
363 PORT_Memset(&p5_param, 0, sizeof(p5_param));
364 rv = SEC_ASN1DecodeItem(arena,&p5_param,
365 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
366 if (rv != SECSuccess) {
367 goto loser;
370 if (p5_param.keyLength.data != NULL) {
371 length = DER_GetInteger(&p5_param.keyLength);
374 loser:
375 if (arena) {
376 PORT_FreeArena(arena, PR_FALSE);
378 return length;
382 * get the key length in bytes needed for the PBE algorithm
384 int
385 SEC_PKCS5GetKeyLength(SECAlgorithmID *algid)
388 SECOidTag algorithm;
390 if(algid == NULL)
391 return SEC_OID_UNKNOWN;
393 algorithm = SECOID_GetAlgorithmTag(algid);
395 switch(algorithm)
397 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
398 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
399 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
400 return 24;
401 case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
402 case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
403 case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
404 return 8;
405 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
406 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
407 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
408 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
409 return 5;
410 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
411 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
412 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
413 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
414 return 16;
415 case SEC_OID_PKCS5_PBKDF2:
416 return sec_pkcs5v2_key_length(algid);
417 case SEC_OID_PKCS5_PBES2:
418 case SEC_OID_PKCS5_PBMAC1:
420 sec_pkcs5V2Parameter *pbeV2_param;
421 int length = -1;
422 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
423 if (pbeV2_param != NULL) {
424 length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId);
425 sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
427 return length;
430 default:
431 break;
433 return -1;
437 /* the PKCS12 V2 algorithms only encode the salt, there is no iteration
438 * count so we need a check for V2 algorithm parameters.
440 static PRBool
441 sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm)
443 switch(algorithm)
445 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
446 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
447 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
448 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
449 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
450 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
451 return PR_TRUE;
452 default:
453 break;
456 return PR_FALSE;
459 static PRBool
460 sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(SECOidTag algorithm)
462 switch(algorithm)
464 case SEC_OID_PKCS5_PBES2:
465 case SEC_OID_PKCS5_PBMAC1:
466 case SEC_OID_PKCS5_PBKDF2:
467 return PR_TRUE;
468 default:
469 break;
472 return PR_FALSE;
475 /* destroy a pbe parameter. it assumes that the parameter was
476 * generated using the appropriate create function and therefor
477 * contains an arena pool.
479 static void
480 sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param)
482 if(pbe_param != NULL)
483 PORT_FreeArena(pbe_param->poolp, PR_TRUE);
486 /* creates a PBE parameter based on the PBE algorithm. the only required
487 * parameters are algorithm and interation. the return is a PBE parameter
488 * which conforms to PKCS 5 parameter unless an extended parameter is needed.
489 * this is primarily if keyLength and a variable key length algorithm are
490 * specified.
491 * salt - if null, a salt will be generated from random bytes.
492 * iteration - number of iterations to perform hashing.
493 * keyLength - only used in variable key length algorithms. if specified,
494 * should be in bytes.
495 * once a parameter is allocated, it should be destroyed calling
496 * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter.
498 #define DEFAULT_SALT_LENGTH 16
499 static SEC_PKCS5PBEParameter *
500 sec_pkcs5_create_pbe_parameter(SECOidTag algorithm,
501 SECItem *salt,
502 int iteration,
503 int keyLength,
504 SECOidTag prfAlg)
506 PRArenaPool *poolp = NULL;
507 SEC_PKCS5PBEParameter *pbe_param = NULL;
508 SECStatus rv= SECSuccess;
509 void *dummy = NULL;
511 if(iteration < 0) {
512 return NULL;
515 poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
516 if(poolp == NULL)
517 return NULL;
519 pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp,
520 sizeof(SEC_PKCS5PBEParameter));
521 if(!pbe_param) {
522 PORT_FreeArena(poolp, PR_TRUE);
523 return NULL;
526 pbe_param->poolp = poolp;
528 rv = SECFailure;
529 if (salt && salt->data) {
530 rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt);
531 } else {
532 /* sigh, the old interface generated salt on the fly, so we have to
533 * preserve the semantics */
534 pbe_param->salt.len = DEFAULT_SALT_LENGTH;
535 pbe_param->salt.data = PORT_ArenaZAlloc(poolp,DEFAULT_SALT_LENGTH);
536 if (pbe_param->salt.data) {
537 rv = PK11_GenerateRandom(pbe_param->salt.data,DEFAULT_SALT_LENGTH);
541 if(rv != SECSuccess) {
542 PORT_FreeArena(poolp, PR_TRUE);
543 return NULL;
546 /* encode the integer */
547 dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration,
548 iteration);
549 rv = (dummy) ? SECSuccess : SECFailure;
551 if(rv != SECSuccess) {
552 PORT_FreeArena(poolp, PR_FALSE);
553 return NULL;
557 * for PKCS5 v2 Add the keylength and the prf
559 if (algorithm == SEC_OID_PKCS5_PBKDF2) {
560 dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->keyLength,
561 keyLength);
562 rv = (dummy) ? SECSuccess : SECFailure;
563 if (rv != SECSuccess) {
564 PORT_FreeArena(poolp, PR_FALSE);
565 return NULL;
567 rv = SECOID_SetAlgorithmID(poolp, &pbe_param->prfAlgId, prfAlg, NULL);
568 if (rv != SECSuccess) {
569 PORT_FreeArena(poolp, PR_FALSE);
570 return NULL;
572 pbe_param->pPrfAlgId = &pbe_param->prfAlgId;
575 return pbe_param;
578 /* creates a algorithm ID containing the PBE algorithm and appropriate
579 * parameters. the required parameter is the algorithm. if salt is
580 * not specified, it is generated randomly.
582 * the returned SECAlgorithmID should be destroyed using
583 * SECOID_DestroyAlgorithmID
585 SECAlgorithmID *
586 sec_pkcs5CreateAlgorithmID(SECOidTag algorithm,
587 SECOidTag cipherAlgorithm,
588 SECOidTag prfAlg,
589 SECOidTag *pPbeAlgorithm,
590 int keyLength,
591 SECItem *salt,
592 int iteration)
594 PRArenaPool *poolp = NULL;
595 SECAlgorithmID *algid, *ret_algid = NULL;
596 SECOidTag pbeAlgorithm = algorithm;
597 SECItem der_param;
598 void *dummy;
599 SECStatus rv = SECFailure;
600 SEC_PKCS5PBEParameter *pbe_param = NULL;
601 sec_pkcs5V2Parameter pbeV2_param;
603 if(iteration <= 0) {
604 return NULL;
607 poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
608 if(!poolp) {
609 goto loser;
612 if (!SEC_PKCS5IsAlgorithmPBEAlgTag(algorithm) ||
613 sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
614 /* use PKCS 5 v2 */
615 SECItem *cipherParams;
618 * if we ask for pkcs5 Algorithms directly, then the
619 * application needs to supply the cipher algorithm,
620 * otherwise we are implicitly using pkcs5 v2 and the
621 * passed in algorithm is the encryption algorithm.
623 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
624 if (cipherAlgorithm == SEC_OID_UNKNOWN) {
625 goto loser;
627 } else {
628 cipherAlgorithm = algorithm;
629 /* force algorithm to be chosen below */
630 algorithm = SEC_OID_PKCS5_PBKDF2;
633 pbeAlgorithm = SEC_OID_PKCS5_PBKDF2;
635 * 'algorithm' is the overall algorithm oid tag used to wrap the
636 * entire algoithm ID block. For PKCS5v1 and PKCS12, this
637 * algorithm OID has encoded in it both the PBE KDF function
638 * and the encryption algorithm. For PKCS 5v2, PBE KDF and
639 * encryption/macing oids are encoded as parameters in
640 * the algorithm ID block.
642 * Thus in PKCS5 v1 and PKCS12, this algorithm maps to a pkcs #11
643 * mechanism, where as in PKCS 5v2, this alogithm tag does not map
644 * directly to a PKCS #11 mechanim, instead the 2 oids in the
645 * algorithm ID block map the the actual PKCS #11 mechanism.
646 * gorithm is). We use choose this algorithm oid based on the
647 * cipherAlgorithm to determine what this should be (MAC1 or PBES2).
649 if (algorithm == SEC_OID_PKCS5_PBKDF2) {
650 /* choose mac or pbes */
651 algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm);
654 /* set the PKCS5v2 specific parameters */
655 if (keyLength == 0) {
656 SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
657 if (hashAlg != SEC_OID_UNKNOWN) {
658 keyLength = HASH_ResultLenByOidTag(hashAlg);
659 } else {
660 CK_MECHANISM_TYPE cryptoMech;
661 cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm);
662 if (cryptoMech == CKM_INVALID_MECHANISM) {
663 goto loser;
665 keyLength = PK11_GetMaxKeyLength(cryptoMech);
667 if (keyLength == 0) {
668 goto loser;
671 /* currently only SEC_OID_HMAC_SHA1 is defined */
672 if (prfAlg == SEC_OID_UNKNOWN) {
673 prfAlg = SEC_OID_HMAC_SHA1;
676 /* build the PKCS5v2 cipher algorithm id */
677 cipherParams = pk11_GenerateNewParamWithKeyLen(
678 PK11_AlgtagToMechanism(cipherAlgorithm), keyLength);
679 if (!cipherParams) {
680 goto loser;
683 PORT_Memset(&pbeV2_param, 0, sizeof (pbeV2_param));
685 rv = PK11_ParamToAlgid(cipherAlgorithm, cipherParams,
686 poolp, &pbeV2_param.cipherAlgId);
687 SECITEM_FreeItem(cipherParams, PR_TRUE);
688 if (rv != SECSuccess) {
689 goto loser;
694 /* generate the parameter */
695 pbe_param = sec_pkcs5_create_pbe_parameter(pbeAlgorithm, salt, iteration,
696 keyLength, prfAlg);
697 if(!pbe_param) {
698 goto loser;
701 /* generate the algorithm id */
702 algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
703 if(algid == NULL) {
704 goto loser;
707 der_param.data = NULL;
708 der_param.len = 0;
709 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(algorithm)) {
710 /* first encode the PBE algorithm ID */
711 dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
712 SEC_PKCS5V2PBEParameterTemplate);
713 if (dummy == NULL) {
714 goto loser;
716 rv = SECOID_SetAlgorithmID(poolp, &pbeV2_param.pbeAlgId,
717 pbeAlgorithm, &der_param);
718 if (rv != SECSuccess) {
719 goto loser;
722 /* now encode the Full PKCS 5 parameter */
723 der_param.data = NULL;
724 der_param.len = 0;
725 dummy = SEC_ASN1EncodeItem(poolp, &der_param, &pbeV2_param,
726 SEC_PKCS5V2ParameterTemplate);
727 } else if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
728 dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
729 SEC_PKCS5PBEParameterTemplate);
730 } else {
731 dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
732 SEC_V2PKCS12PBEParameterTemplate);
734 if (dummy == NULL) {
735 goto loser;
738 rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param);
739 if (rv != SECSuccess) {
740 goto loser;
743 ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
744 if (ret_algid == NULL) {
745 goto loser;
748 rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
749 if (rv != SECSuccess) {
750 SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
751 ret_algid = NULL;
752 } else if (pPbeAlgorithm) {
753 *pPbeAlgorithm = pbeAlgorithm;
756 loser:
757 if (poolp != NULL) {
758 PORT_FreeArena(poolp, PR_TRUE);
759 algid = NULL;
762 if (pbe_param) {
763 sec_pkcs5_destroy_pbe_param(pbe_param);
766 return ret_algid;
769 SECStatus
770 pbe_PK11AlgidToParam(SECAlgorithmID *algid,SECItem *mech)
772 SEC_PKCS5PBEParameter p5_param;
773 SECItem *salt = NULL;
774 SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);
775 PRArenaPool *arena = NULL;
776 SECStatus rv = SECFailure;
777 unsigned char *paramData = NULL;
778 unsigned char *pSalt = NULL;
779 CK_ULONG iterations;
780 int paramLen = 0;
781 int iv_len;
784 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
785 if (arena == NULL) {
786 goto loser;
791 * decode the algid based on the pbe type
793 if (sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
794 iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
795 rv = SEC_ASN1DecodeItem(arena, &p5_param,
796 SEC_V2PKCS12PBEParameterTemplate, &algid->parameters);
797 } else if (algorithm == SEC_OID_PKCS5_PBKDF2) {
798 iv_len = 0;
799 PORT_Memset(&p5_param, 0, sizeof(p5_param));
800 rv = SEC_ASN1DecodeItem(arena,&p5_param,
801 SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
802 } else {
803 iv_len = PK11_GetIVLength(PK11_AlgtagToMechanism(algorithm));
804 rv = SEC_ASN1DecodeItem(arena,&p5_param,SEC_PKCS5PBEParameterTemplate,
805 &algid->parameters);
808 if (iv_len < 0) {
809 goto loser;
812 if (rv != SECSuccess) {
813 goto loser;
816 /* get salt */
817 salt = &p5_param.salt;
818 iterations = (CK_ULONG) DER_GetInteger(&p5_param.iteration);
820 /* allocate and fill in the PKCS #11 parameters
821 * based on the algorithm. */
822 if (algorithm == SEC_OID_PKCS5_PBKDF2) {
823 SECOidTag prfAlgTag;
824 CK_PKCS5_PBKD2_PARAMS *pbeV2_params =
825 (CK_PKCS5_PBKD2_PARAMS *)PORT_ZAlloc(
826 sizeof(CK_PKCS5_PBKD2_PARAMS)+ salt->len);
828 if (pbeV2_params == NULL) {
829 goto loser;
831 paramData = (unsigned char *)pbeV2_params;
832 paramLen = sizeof(CK_PKCS5_PBKD2_PARAMS);
834 /* set the prf */
835 prfAlgTag = SEC_OID_HMAC_SHA1;
836 if (p5_param.pPrfAlgId &&
837 p5_param.pPrfAlgId->algorithm.data != 0) {
838 prfAlgTag = SECOID_GetAlgorithmTag(p5_param.pPrfAlgId);
840 if (prfAlgTag == SEC_OID_HMAC_SHA1) {
841 pbeV2_params->prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
842 } else {
843 /* only SHA1_HMAC is currently supported by PKCS #11 */
844 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
845 goto loser;
848 /* probably should fetch these from the prfAlgid */
849 pbeV2_params->pPrfData = NULL;
850 pbeV2_params->ulPrfDataLen = 0;
851 pbeV2_params->saltSource = CKZ_SALT_SPECIFIED;
852 pSalt = ((CK_CHAR_PTR) pbeV2_params)+sizeof(CK_PKCS5_PBKD2_PARAMS);
853 PORT_Memcpy(pSalt, salt->data, salt->len);
854 pbeV2_params->pSaltSourceData = pSalt;
855 pbeV2_params->ulSaltSourceDataLen = salt->len;
856 pbeV2_params->iterations = iterations;
857 } else {
858 CK_PBE_PARAMS *pbe_params = NULL;
859 pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS)+
860 salt->len+iv_len);
861 if (pbe_params == NULL) {
862 goto loser;
864 paramData = (unsigned char *)pbe_params;
865 paramLen = sizeof(CK_PBE_PARAMS);
867 pSalt = ((CK_CHAR_PTR) pbe_params)+sizeof(CK_PBE_PARAMS);
868 pbe_params->pSalt = pSalt;
869 PORT_Memcpy(pSalt, salt->data, salt->len);
870 pbe_params->ulSaltLen = salt->len;
871 if (iv_len) {
872 pbe_params->pInitVector =
873 ((CK_CHAR_PTR) pbe_params)+ sizeof(CK_PBE_PARAMS)+salt->len;
875 pbe_params->ulIteration = iterations;
878 /* copy into the mechanism sec item */
879 mech->data = paramData;
880 mech->len = paramLen;
881 if (arena) {
882 PORT_FreeArena(arena,PR_TRUE);
884 return SECSuccess;
886 loser:
887 if (paramData) {
888 PORT_Free(paramData);
890 if (arena) {
891 PORT_FreeArena(arena,PR_TRUE);
893 return SECFailure;
897 * public, deprecated, not valid for pkcs5 v2
899 * use PK11_CreatePBEV2AlgorithmID or PK11_CreatePBEAlgorithmID to create
900 * PBE algorithmID's directly.
902 SECStatus
903 PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PRArenaPool *arena,
904 SECAlgorithmID *algId)
906 CK_PBE_PARAMS *pbe_param;
907 SECItem pbeSalt;
908 SECAlgorithmID *pbeAlgID = NULL;
909 SECStatus rv;
911 if(!param || !algId) {
912 return SECFailure;
915 pbe_param = (CK_PBE_PARAMS *)param->data;
916 pbeSalt.data = (unsigned char *)pbe_param->pSalt;
917 pbeSalt.len = pbe_param->ulSaltLen;
918 pbeAlgID = sec_pkcs5CreateAlgorithmID(algTag, SEC_OID_UNKNOWN,
919 SEC_OID_UNKNOWN, NULL, 0, &pbeSalt, (int)pbe_param->ulIteration);
920 if(!pbeAlgID) {
921 return SECFailure;
924 rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID);
925 SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE);
926 return rv;
930 * public, Deprecated, This function is only for binary compatibility with
931 * older applications. Does not support PKCS5v2.
933 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
934 * iv values rather than generating PBE bits directly.
936 PBEBitGenContext *
937 PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
938 SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
939 unsigned int iterations)
941 SECItem *context = NULL;
942 SECItem mechItem;
943 CK_PBE_PARAMS pbe_params;
944 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
945 PK11SlotInfo *slot;
946 PK11SymKey *symKey = NULL;
947 unsigned char ivData[8];
950 /* use the purpose to select the low level keygen algorithm */
951 switch (bitGenPurpose) {
952 case pbeBitGenIntegrityKey:
953 switch (hashAlgorithm) {
954 case SEC_OID_SHA1:
955 mechanism = CKM_PBA_SHA1_WITH_SHA1_HMAC;
956 break;
957 case SEC_OID_MD2:
958 mechanism = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN;
959 break;
960 case SEC_OID_MD5:
961 mechanism = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN;
962 break;
963 default:
964 break;
966 break;
967 case pbeBitGenCipherIV:
968 if (bitsNeeded > 64) {
969 break;
971 if (hashAlgorithm != SEC_OID_SHA1) {
972 break;
974 mechanism = CKM_PBE_SHA1_DES3_EDE_CBC;
975 break;
976 case pbeBitGenCipherKey:
977 if (hashAlgorithm != SEC_OID_SHA1) {
978 break;
980 switch (bitsNeeded) {
981 case 40:
982 mechanism = CKM_PBE_SHA1_RC4_40;
983 break;
984 case 128:
985 mechanism = CKM_PBE_SHA1_RC4_128;
986 break;
987 default:
988 break;
990 case pbeBitGenIDNull:
991 break;
994 if (mechanism == CKM_INVALID_MECHANISM) {
995 /* we should set an error, but this is a deprecated function, and
996 * we are keeping bug for bug compatibility;)... */
997 return NULL;
1000 pbe_params.pInitVector = ivData;
1001 pbe_params.pPassword = pwitem->data;
1002 pbe_params.ulPasswordLen = pwitem->len;
1003 pbe_params.pSalt = salt->data;
1004 pbe_params.ulSaltLen = salt->len;
1005 pbe_params.ulIteration = iterations;
1006 mechItem.data = (unsigned char *) &pbe_params;
1007 mechItem.len = sizeof(pbe_params);
1010 slot = PK11_GetInternalSlot();
1011 symKey = PK11_RawPBEKeyGen(slot,mechanism,
1012 &mechItem, pwitem, PR_FALSE, NULL);
1013 PK11_FreeSlot(slot);
1014 if (symKey != NULL) {
1015 if (bitGenPurpose == pbeBitGenCipherIV) {
1016 /* NOTE: this assumes that bitsNeeded is a multiple of 8! */
1017 SECItem ivItem;
1019 ivItem.data = ivData;
1020 ivItem.len = bitsNeeded/8;
1021 context = SECITEM_DupItem(&ivItem);
1022 } else {
1023 SECItem *keyData;
1024 PK11_ExtractKeyValue(symKey);
1025 keyData = PK11_GetKeyData(symKey);
1027 /* assert bitsNeeded with length? */
1028 if (keyData) {
1029 context = SECITEM_DupItem(keyData);
1032 PK11_FreeSymKey(symKey);
1035 return (PBEBitGenContext *)context;
1039 * public, Deprecated, This function is only for binary compatibility with
1040 * older applications. Does not support PKCS5v2.
1042 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetIV() for
1043 * iv values rather than generating PBE bits directly.
1045 SECItem *
1046 PBE_GenerateBits(PBEBitGenContext *context)
1048 return (SECItem *)context;
1052 * public, Deprecated, This function is only for binary compatibility with
1053 * older applications. Does not support PKCS5v2.
1055 * Applications should use PK11_PBEKeyGen() for keys and PK11_GetPBEIV() for
1056 * iv values rather than generating PBE bits directly.
1058 void
1059 PBE_DestroyContext(PBEBitGenContext *context)
1061 SECITEM_FreeItem((SECItem *)context,PR_TRUE);
1065 * public, deprecated. Replaced with PK11_GetPBEIV().
1067 SECItem *
1068 SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
1070 /* pbe stuff */
1071 CK_MECHANISM_TYPE type;
1072 SECItem *param = NULL;
1073 SECItem *iv = NULL;
1074 SECItem src;
1075 int iv_len = 0;
1076 PK11SymKey *symKey;
1077 PK11SlotInfo *slot;
1078 CK_PBE_PARAMS_PTR pPBEparams;
1079 SECOidTag pbeAlg;
1081 pbeAlg = SECOID_GetAlgorithmTag(algid);
1082 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
1083 unsigned char *ivData;
1084 sec_pkcs5V2Parameter *pbeV2_param = NULL;
1086 /* can only return the IV if the crypto Algorithm exists */
1087 if (pbeAlg == SEC_OID_PKCS5_PBKDF2) {
1088 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1089 goto loser;
1091 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
1092 if (pbeV2_param == NULL) {
1093 goto loser;
1095 /* extract the IV from the cipher algid portion of our pkcs 5 v2
1096 * algorithm id */
1097 type = PK11_AlgtagToMechanism(
1098 SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
1099 param = PK11_ParamFromAlgid(&pbeV2_param->cipherAlgId);
1100 sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
1101 if (!param) {
1102 goto loser;
1104 /* NOTE: NULL is a permissible return here */
1105 ivData = PK11_IVFromParam(type, param, &iv_len);
1106 src.data = ivData;
1107 src.len = iv_len;
1108 goto done;
1111 type = PK11_AlgtagToMechanism(pbeAlg);
1112 param = PK11_ParamFromAlgid(algid);
1113 if (param == NULL) {
1114 goto done;
1116 slot = PK11_GetInternalSlot();
1117 symKey = PK11_RawPBEKeyGen(slot, type, param, pwitem, faulty3DES, NULL);
1118 PK11_FreeSlot(slot);
1119 if (symKey == NULL) {
1120 goto loser;
1122 PK11_FreeSymKey(symKey);
1123 pPBEparams = (CK_PBE_PARAMS_PTR)param->data;
1124 iv_len = PK11_GetIVLength(type);
1126 src.data = (unsigned char *)pPBEparams->pInitVector;
1127 src.len = iv_len;
1129 done:
1130 iv = SECITEM_DupItem(&src);
1132 loser:
1133 if (param) {
1134 SECITEM_ZfreeItem(param, PR_TRUE);
1136 return iv;
1140 * Subs from nss 3.x that are deprecated
1142 PBEBitGenContext *
1143 __PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
1144 SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
1145 unsigned int iterations)
1147 PORT_Assert("__PBE_CreateContext is Deprecated" == NULL);
1148 return NULL;
1151 SECItem *
1152 __PBE_GenerateBits(PBEBitGenContext *context)
1154 PORT_Assert("__PBE_GenerateBits is Deprecated" == NULL);
1155 return NULL;
1158 void
1159 __PBE_DestroyContext(PBEBitGenContext *context)
1161 PORT_Assert("__PBE_DestroyContext is Deprecated" == NULL);
1164 SECStatus
1165 RSA_FormatBlock(SECItem *result, unsigned modulusLen,
1166 int blockType, SECItem *data)
1168 PORT_Assert("RSA_FormatBlock is Deprecated" == NULL);
1169 return SECFailure;
1172 /****************************************************************************
1174 * Now Do The PBE Functions Here...
1176 ****************************************************************************/
1178 static void
1179 pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params)
1181 if (pbe_params) {
1182 if (pbe_params->pPassword)
1183 PORT_ZFree(pbe_params->pPassword, pbe_params->ulPasswordLen);
1184 if (pbe_params->pSalt)
1185 PORT_ZFree(pbe_params->pSalt, pbe_params->ulSaltLen);
1186 PORT_ZFree(pbe_params, sizeof(CK_PBE_PARAMS));
1191 * public, deprecated. use PK11_CreatePBEAlgorithmID or
1192 * PK11_CreatePBEV2AlgorithmID instead. If you needthe pkcs #11 parameters,
1193 * use PK11_ParamFromAlgid from the algorithm id you created using
1194 * PK11_CreatePBEAlgorithmID or PK11_CreatePBEV2AlgorithmID.
1196 SECItem *
1197 PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations)
1199 CK_PBE_PARAMS *pbe_params = NULL;
1200 SECItem *paramRV = NULL;
1202 paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS));
1203 if (!paramRV ) {
1204 goto loser;
1206 /* init paramRV->data with zeros. SECITEM_AllocItem does not do it */
1207 PORT_Memset(paramRV->data, 0, sizeof(CK_PBE_PARAMS));
1209 pbe_params = (CK_PBE_PARAMS *)paramRV->data;
1210 pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len);
1211 if (!pbe_params->pPassword) {
1212 goto loser;
1214 PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len);
1215 pbe_params->ulPasswordLen = pwd->len;
1217 pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len);
1218 if (!pbe_params->pSalt) {
1219 goto loser;
1221 PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len);
1222 pbe_params->ulSaltLen = salt->len;
1224 pbe_params->ulIteration = (CK_ULONG)iterations;
1225 return paramRV;
1227 loser:
1228 if (pbe_params)
1229 pk11_destroy_ck_pbe_params(pbe_params);
1230 if (paramRV)
1231 PORT_ZFree(paramRV, sizeof(SECItem));
1232 return NULL;
1236 * public, deprecated.
1238 void
1239 PK11_DestroyPBEParams(SECItem *pItem)
1241 if (pItem) {
1242 CK_PBE_PARAMS * params = (CK_PBE_PARAMS *)(pItem->data);
1243 if (params)
1244 pk11_destroy_ck_pbe_params(params);
1245 PORT_ZFree(pItem, sizeof(SECItem));
1250 * public, Partially supports PKCS5 V2 (some parameters are not controllable
1251 * through this interface). Use PK11_CreatePBEV2AlgorithmID() if you need
1252 * finer control these.
1254 SECAlgorithmID *
1255 PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt)
1257 SECAlgorithmID *algid = NULL;
1258 algid = sec_pkcs5CreateAlgorithmID(algorithm,
1259 SEC_OID_UNKNOWN, SEC_OID_UNKNOWN, NULL, 0, salt, iteration);
1260 return algid;
1264 * public, fully support pkcs5v2.
1266 SECAlgorithmID *
1267 PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag,
1268 SECOidTag prfAlgTag, int keyLength, int iteration,
1269 SECItem *salt)
1271 SECAlgorithmID *algid = NULL;
1272 algid = sec_pkcs5CreateAlgorithmID(pbeAlgTag, cipherAlgTag, prfAlgTag,
1273 NULL, keyLength, salt, iteration);
1274 return algid;
1278 * private.
1280 PK11SymKey *
1281 pk11_RawPBEKeyGenWithKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
1282 SECItem *params, CK_KEY_TYPE keyType, int keyLen,
1283 SECItem *pwitem, void *wincx)
1285 CK_ULONG pwLen;
1286 /* do some sanity checks */
1287 if ((params == NULL) || (params->data == NULL)) {
1288 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1289 return NULL;
1292 if (type == CKM_INVALID_MECHANISM) {
1293 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1294 return NULL;
1297 /* set the password pointer in the parameters... */
1298 if (type == CKM_PKCS5_PBKD2) {
1299 CK_PKCS5_PBKD2_PARAMS *pbev2_params;
1300 if (params->len < sizeof(CK_PKCS5_PBKD2_PARAMS)) {
1301 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1302 return NULL;
1304 pbev2_params = (CK_PKCS5_PBKD2_PARAMS *)params->data;
1305 pbev2_params->pPassword = pwitem->data;
1306 pwLen = pwitem->len;
1307 pbev2_params->ulPasswordLen = &pwLen;
1308 } else {
1309 CK_PBE_PARAMS *pbe_params;
1310 if (params->len < sizeof(CK_PBE_PARAMS)) {
1311 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1312 return NULL;
1314 pbe_params = (CK_PBE_PARAMS *)params->data;
1315 pbe_params->pPassword = pwitem->data;
1316 pbe_params->ulPasswordLen = pwitem->len;
1319 /* generate the key (and sometimes the IV as a side effect...) */
1320 return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, params, keyType,
1321 keyLen, NULL, CKF_SIGN|CKF_ENCRYPT|CKF_DECRYPT|CKF_UNWRAP|CKF_WRAP,
1322 0, wincx);
1326 * public, deprecated. use PK11_PBEKeyGen instead.
1328 PK11SymKey *
1329 PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *mech,
1330 SECItem *pwitem, PRBool faulty3DES, void *wincx)
1332 if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
1333 type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
1335 return pk11_RawPBEKeyGenWithKeyType(slot, type, mech, -1, 0, pwitem, wincx);
1339 * pubic, supports pkcs5 v2.
1341 * Create symkey from a PBE key. The algid can be created with
1342 * PK11_CreatePBEV2AlgorithmID and PK11_CreatePBEAlgorithmID, or by
1343 * extraction of der data.
1345 PK11SymKey *
1346 PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem,
1347 PRBool faulty3DES, void *wincx)
1349 CK_MECHANISM_TYPE type;
1350 SECItem *param = NULL;
1351 PK11SymKey *symKey;
1352 SECOidTag pbeAlg;
1353 CK_KEY_TYPE keyType = -1;
1354 int keyLen = 0;
1356 pbeAlg = SECOID_GetAlgorithmTag(algid);
1357 /* if we're using PKCS5v2, extract the additional information we need
1358 * (key length, key type, and pbeAlg). */
1359 if (sec_pkcs5_is_algorithm_v2_pkcs5_algorithm(pbeAlg)) {
1360 CK_MECHANISM_TYPE cipherMech;
1361 sec_pkcs5V2Parameter *pbeV2_param;
1363 pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
1364 if (pbeV2_param == NULL) {
1365 return NULL;
1367 cipherMech = PK11_AlgtagToMechanism(
1368 SECOID_GetAlgorithmTag(&pbeV2_param->cipherAlgId));
1369 pbeAlg = SECOID_GetAlgorithmTag(&pbeV2_param->pbeAlgId);
1370 param = PK11_ParamFromAlgid(&pbeV2_param->pbeAlgId);
1371 sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
1372 keyLen = SEC_PKCS5GetKeyLength(algid);
1373 if (keyLen == -1) {
1374 keyLen = 0;
1376 keyType = PK11_GetKeyType(cipherMech, keyLen);
1377 } else {
1378 param = PK11_ParamFromAlgid(algid);
1380 if(param == NULL) {
1381 return NULL;
1384 type = PK11_AlgtagToMechanism(pbeAlg);
1385 if (type == CKM_INVALID_MECHANISM) {
1386 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1387 return NULL;
1389 if(faulty3DES && (type == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC)) {
1390 type = CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC;
1392 symKey = pk11_RawPBEKeyGenWithKeyType(slot, type, param, keyType, keyLen,
1393 pwitem, wincx);
1395 SECITEM_ZfreeItem(param, PR_TRUE);
1396 return symKey;
1400 * public, supports pkcs5v2
1402 SECItem *
1403 PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem)
1405 return SEC_PKCS5GetIV(algid, pwitem, PR_FALSE);
1408 CK_MECHANISM_TYPE
1409 pk11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param,
1410 SECItem *pbe_pwd, PRBool faulty3DES)
1412 int keyLen = 0;
1413 SECOidTag algTag = SEC_PKCS5GetCryptoAlgorithm(algid);
1414 CK_MECHANISM_TYPE mech = PK11_AlgtagToMechanism(algTag);
1415 CK_MECHANISM_TYPE returnedMechanism = CKM_INVALID_MECHANISM;
1416 SECItem *iv = NULL;
1418 if (mech == CKM_INVALID_MECHANISM) {
1419 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
1420 goto loser;
1422 if (PK11_GetIVLength(mech)) {
1423 iv = SEC_PKCS5GetIV(algid, pbe_pwd, faulty3DES);
1424 if (iv == NULL) {
1425 goto loser;
1429 keyLen = SEC_PKCS5GetKeyLength(algid);
1431 *param = pk11_ParamFromIVWithLen(mech, iv, keyLen);
1432 if (*param == NULL) {
1433 goto loser;
1435 returnedMechanism = mech;
1437 loser:
1438 if (iv) {
1439 SECITEM_FreeItem(iv,PR_TRUE);
1441 return returnedMechanism;
1445 * public, supports pkcs5 v2
1447 * get a the crypto mechanism directly from the pbe algorithmid.
1449 * it's important to go directly from the algorithm id so that we can
1450 * handle both the PKCS #5 v1, PKCS #12, and PKCS #5 v2 cases.
1452 * This function returns both the mechanism an the paramter for the mechanism.
1453 * The caller is responsible for freeing the parameter.
1455 CK_MECHANISM_TYPE
1456 PK11_GetPBECryptoMechanism(SECAlgorithmID *algid, SECItem **param,
1457 SECItem *pbe_pwd)
1459 return pk11_GetPBECryptoMechanism(algid, param, pbe_pwd, PR_FALSE);