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