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