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

Side by Side Diff: nss/lib/softoken/lowpbe.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/softoken/lowpbe.h ('k') | nss/lib/softoken/padbuf.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "plarena.h"
6
7 #include "seccomon.h"
8 #include "secitem.h"
9 #include "secport.h"
10 #include "hasht.h"
11 #include "pkcs11t.h"
12 #include "blapi.h"
13 #include "hasht.h"
14 #include "secasn1.h"
15 #include "secder.h"
16 #include "lowpbe.h"
17 #include "secoid.h"
18 #include "alghmac.h"
19 #include "softoken.h"
20 #include "secerr.h"
21
22 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
23
24 /* template for PKCS 5 PBE Parameter. This template has been expanded
25 * based upon the additions in PKCS 12. This should eventually be moved
26 * if RSA updates PKCS 5.
27 */
28 static const SEC_ASN1Template NSSPKCS5PBEParameterTemplate[] =
29 {
30 { SEC_ASN1_SEQUENCE,
31 0, NULL, sizeof(NSSPKCS5PBEParameter) },
32 { SEC_ASN1_OCTET_STRING,
33 offsetof(NSSPKCS5PBEParameter, salt) },
34 { SEC_ASN1_INTEGER,
35 offsetof(NSSPKCS5PBEParameter, iteration) },
36 { 0 }
37 };
38
39 static const SEC_ASN1Template NSSPKCS5PKCS12V2PBEParameterTemplate[] =
40 {
41 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) },
42 { SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) },
43 { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) },
44 { 0 }
45 };
46
47
48 /* PKCS5 v2 */
49
50 struct nsspkcs5V2PBEParameterStr {
51 SECAlgorithmID keyParams; /* parameters of the key generation */
52 SECAlgorithmID algParams; /* parameters for the encryption or mac op */
53 };
54
55 typedef struct nsspkcs5V2PBEParameterStr nsspkcs5V2PBEParameter;
56
57 static const SEC_ASN1Template NSSPKCS5V2PBES2ParameterTemplate[] =
58 {
59 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(nsspkcs5V2PBEParameter) },
60 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
61 offsetof(nsspkcs5V2PBEParameter, keyParams),
62 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
63 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
64 offsetof(nsspkcs5V2PBEParameter, algParams),
65 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
66 { 0 }
67 };
68
69 static const SEC_ASN1Template NSSPKCS5V2PBEParameterTemplate[] =
70 {
71 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) },
72 /* this is really a choice, but since we don't understand any other
73 *choice, just inline it. */
74 { SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) },
75 { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) },
76 { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, keyLength) },
77 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
78 offsetof(NSSPKCS5PBEParameter, prfAlg),
79 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
80 { 0 }
81 };
82
83 SECStatus
84 nsspkcs5_HashBuf(const SECHashObject *hashObj, unsigned char *dest,
85 unsigned char *src, int len)
86 {
87 void *ctx;
88 unsigned int retLen;
89
90 ctx = hashObj->create();
91 if(ctx == NULL) {
92 return SECFailure;
93 }
94 hashObj->begin(ctx);
95 hashObj->update(ctx, src, len);
96 hashObj->end(ctx, dest, &retLen, hashObj->length);
97 hashObj->destroy(ctx, PR_TRUE);
98 return SECSuccess;
99 }
100
101 /* generate bits using any hash
102 */
103 static SECItem *
104 nsspkcs5_PBKDF1(const SECHashObject *hashObj, SECItem *salt, SECItem *pwd,
105 int iter, PRBool faulty3DES)
106 {
107 SECItem *hash = NULL, *pre_hash = NULL;
108 SECStatus rv = SECFailure;
109
110 if((salt == NULL) || (pwd == NULL) || (iter < 0)) {
111 return NULL;
112 }
113
114 hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
115 pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
116
117 if((hash != NULL) && (pre_hash != NULL)) {
118 int i, ph_len;
119
120 ph_len = hashObj->length;
121 if((salt->len + pwd->len) > hashObj->length) {
122 ph_len = salt->len + pwd->len;
123 }
124
125 rv = SECFailure;
126
127 /* allocate buffers */
128 hash->len = hashObj->length;
129 hash->data = (unsigned char *)PORT_ZAlloc(hash->len);
130 pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len);
131
132 /* in pbeSHA1TripleDESCBC there was an allocation error that made
133 * it into the caller. We do not want to propagate those errors
134 * further, so we are doing it correctly, but reading the old method.
135 */
136 if (faulty3DES) {
137 pre_hash->len = ph_len;
138 } else {
139 pre_hash->len = salt->len + pwd->len;
140 }
141
142 /* preform hash */
143 if ((hash->data != NULL) && (pre_hash->data != NULL)) {
144 rv = SECSuccess;
145 /* check for 0 length password */
146 if(pwd->len > 0) {
147 PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
148 }
149 if(salt->len > 0) {
150 PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len);
151 }
152 for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) {
153 rv = nsspkcs5_HashBuf(hashObj, hash->data,
154 pre_hash->data, pre_hash->len);
155 if(rv != SECFailure) {
156 pre_hash->len = hashObj->length;
157 PORT_Memcpy(pre_hash->data, hash->data, hashObj->length);
158 }
159 }
160 }
161 }
162
163 if(pre_hash != NULL) {
164 SECITEM_FreeItem(pre_hash, PR_TRUE);
165 }
166
167 if((rv != SECSuccess) && (hash != NULL)) {
168 SECITEM_FreeItem(hash, PR_TRUE);
169 hash = NULL;
170 }
171
172 return hash;
173 }
174
175 /* this bit generation routine is described in PKCS 12 and the proposed
176 * extensions to PKCS 5. an initial hash is generated following the
177 * instructions laid out in PKCS 5. If the number of bits generated is
178 * insufficient, then the method discussed in the proposed extensions to
179 * PKCS 5 in PKCS 12 are used. This extension makes use of the HMAC
180 * function. And the P_Hash function from the TLS standard.
181 */
182 static SECItem *
183 nsspkcs5_PFXPBE(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param,
184 SECItem *init_hash, unsigned int bytes_needed)
185 {
186 SECItem *ret_bits = NULL;
187 int hash_size = 0;
188 unsigned int i;
189 unsigned int hash_iter;
190 unsigned int dig_len;
191 SECStatus rv = SECFailure;
192 unsigned char *state = NULL;
193 unsigned int state_len;
194 HMACContext *cx = NULL;
195
196 hash_size = hashObj->length;
197 hash_iter = (bytes_needed + (unsigned int)hash_size - 1) / hash_size;
198
199 /* allocate return buffer */
200 ret_bits = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
201 if(ret_bits == NULL)
202 return NULL;
203 ret_bits->data = (unsigned char *)PORT_ZAlloc((hash_iter * hash_size) + 1);
204 ret_bits->len = (hash_iter * hash_size);
205 if(ret_bits->data == NULL) {
206 PORT_Free(ret_bits);
207 return NULL;
208 }
209
210 /* allocate intermediate hash buffer. 8 is for the 8 bytes of
211 * data which are added based on iteration number
212 */
213
214 if ((unsigned int)hash_size > pbe_param->salt.len) {
215 state_len = hash_size;
216 } else {
217 state_len = pbe_param->salt.len;
218 }
219 state = (unsigned char *)PORT_ZAlloc(state_len);
220 if(state == NULL) {
221 rv = SECFailure;
222 goto loser;
223 }
224 if(pbe_param->salt.len > 0) {
225 PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len);
226 }
227
228 cx = HMAC_Create(hashObj, init_hash->data, init_hash->len, PR_TRUE);
229 if (cx == NULL) {
230 rv = SECFailure;
231 goto loser;
232 }
233
234 for(i = 0; i < hash_iter; i++) {
235
236 /* generate output bits */
237 HMAC_Begin(cx);
238 HMAC_Update(cx, state, state_len);
239 HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len);
240 rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size),
241 &dig_len, hash_size);
242 if (rv != SECSuccess)
243 goto loser;
244 PORT_Assert((unsigned int)hash_size == dig_len);
245
246 /* generate new state */
247 HMAC_Begin(cx);
248 HMAC_Update(cx, state, state_len);
249 rv = HMAC_Finish(cx, state, &state_len, state_len);
250 if (rv != SECSuccess)
251 goto loser;
252 PORT_Assert(state_len == dig_len);
253 }
254
255 loser:
256 if (state != NULL)
257 PORT_ZFree(state, state_len);
258 HMAC_Destroy(cx, PR_TRUE);
259
260 if(rv != SECSuccess) {
261 SECITEM_ZfreeItem(ret_bits, PR_TRUE);
262 ret_bits = NULL;
263 }
264
265 return ret_bits;
266 }
267
268 /* generate bits for the key and iv determination. if enough bits
269 * are not generated using PKCS 5, then we need to generate more bits
270 * based on the extension proposed in PKCS 12
271 */
272 static SECItem *
273 nsspkcs5_PBKDF1Extended(const SECHashObject *hashObj,
274 NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, PRBool faulty3DES)
275 {
276 SECItem * hash = NULL;
277 SECItem * newHash = NULL;
278 int bytes_needed;
279 int bytes_available;
280
281 bytes_needed = pbe_param->ivLen + pbe_param->keyLen;
282 bytes_available = hashObj->length;
283
284 hash = nsspkcs5_PBKDF1(hashObj, &pbe_param->salt, pwitem,
285 pbe_param->iter, faulty3DES);
286
287 if(hash == NULL) {
288 return NULL;
289 }
290
291 if(bytes_needed <= bytes_available) {
292 return hash;
293 }
294
295 newHash = nsspkcs5_PFXPBE(hashObj, pbe_param, hash, bytes_needed);
296 if (hash != newHash)
297 SECITEM_FreeItem(hash, PR_TRUE);
298 return newHash;
299 }
300
301 /*
302 * PBDKDF2 is PKCS #5 v2.0 it's currently not used by NSS
303 */
304 static void
305 do_xor(unsigned char *dest, unsigned char *src, int len)
306 {
307 /* use byt xor, not all platforms are happy about inaligned
308 * integer fetches */
309 while (len--) {
310 *dest = *dest ^ *src;
311 dest++;
312 src++;
313 }
314 }
315
316 static SECStatus
317 nsspkcs5_PBKDF2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt,
318 int iterations, unsigned int i, unsigned char *T)
319 {
320 int j;
321 HMACContext *cx = NULL;
322 unsigned int hLen = hashobj->length;
323 SECStatus rv = SECFailure;
324 unsigned char *last = NULL;
325 unsigned int lastLength = salt->len + 4;
326 unsigned int lastBufLength;
327
328 cx=HMAC_Create(hashobj,pwitem->data,pwitem->len,PR_FALSE);
329 if (cx == NULL) {
330 goto loser;
331 }
332 PORT_Memset(T,0,hLen);
333 lastBufLength = PR_MAX(lastLength, hLen);
334 last = PORT_Alloc(lastBufLength);
335 if (last == NULL) {
336 goto loser;
337 }
338 PORT_Memcpy(last,salt->data,salt->len);
339 last[salt->len ] = (i >> 24) & 0xff;
340 last[salt->len+1] = (i >> 16) & 0xff;
341 last[salt->len+2] = (i >> 8) & 0xff;
342 last[salt->len+3] = i & 0xff;
343
344 /* NOTE: we need at least one iteration to return success! */
345 for (j=0; j < iterations; j++) {
346 HMAC_Begin(cx);
347 HMAC_Update(cx,last,lastLength);
348 rv =HMAC_Finish(cx,last,&lastLength,hLen);
349 if (rv !=SECSuccess) {
350 break;
351 }
352 do_xor(T,last,hLen);
353 }
354 loser:
355 if (cx) {
356 HMAC_Destroy(cx, PR_TRUE);
357 }
358 if (last) {
359 PORT_ZFree(last,lastBufLength);
360 }
361 return rv;
362 }
363
364 static SECItem *
365 nsspkcs5_PBKDF2(const SECHashObject *hashobj, NSSPKCS5PBEParameter *pbe_param,
366 SECItem *pwitem)
367 {
368 int iterations = pbe_param->iter;
369 int bytesNeeded = pbe_param->keyLen;
370 unsigned int dkLen = bytesNeeded;
371 unsigned int hLen = hashobj->length;
372 unsigned int nblocks = (dkLen+hLen-1) / hLen;
373 unsigned int i;
374 unsigned char *rp;
375 unsigned char *T = NULL;
376 SECItem *result = NULL;
377 SECItem *salt = &pbe_param->salt;
378 SECStatus rv = SECFailure;
379
380 result = SECITEM_AllocItem(NULL,NULL,nblocks*hLen);
381 if (result == NULL) {
382 return NULL;
383 }
384
385 T = PORT_Alloc(hLen);
386 if (T == NULL) {
387 goto loser;
388 }
389
390 for (i=1,rp=result->data; i <= nblocks ; i++, rp +=hLen) {
391 rv = nsspkcs5_PBKDF2_F(hashobj, pwitem, salt, iterations, i, T);
392 if (rv != SECSuccess) {
393 break;
394 }
395 PORT_Memcpy(rp,T,hLen);
396 }
397
398 loser:
399 if (T) {
400 PORT_ZFree(T,hLen);
401 }
402 if (rv != SECSuccess) {
403 SECITEM_FreeItem(result,PR_TRUE);
404 result = NULL;
405 } else {
406 result->len = dkLen;
407 }
408
409 return result;
410 }
411
412 #define HMAC_BUFFER 64
413 #define NSSPBE_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
414 #define NSSPBE_MIN(x,y) ((x) < (y) ? (x) : (y))
415 /*
416 * This is the extended PBE function defined by the final PKCS #12 spec.
417 */
418 static SECItem *
419 nsspkcs5_PKCS12PBE(const SECHashObject *hashObject,
420 NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
421 PBEBitGenID bitGenPurpose, unsigned int bytesNeeded)
422 {
423 PLArenaPool *arena = NULL;
424 unsigned int SLen,PLen;
425 unsigned int hashLength = hashObject->length;
426 unsigned char *S, *P;
427 SECItem *A = NULL, B, D, I;
428 SECItem *salt = &pbe_param->salt;
429 unsigned int c,i = 0;
430 unsigned int hashLen;
431 int iter;
432 unsigned char *iterBuf;
433 void *hash = NULL;
434
435 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
436 if(!arena) {
437 return NULL;
438 }
439
440 /* how many hash object lengths are needed */
441 c = (bytesNeeded + (hashLength-1))/hashLength;
442
443 /* initialize our buffers */
444 D.len = HMAC_BUFFER;
445 /* B and D are the same length, use one alloc go get both */
446 D.data = (unsigned char*)PORT_ArenaZAlloc(arena, D.len*2);
447 B.len = D.len;
448 B.data = D.data + D.len;
449
450 /* if all goes well, A will be returned, so don't use our temp arena */
451 A = SECITEM_AllocItem(NULL,NULL,c*hashLength);
452 if (A == NULL) {
453 goto loser;
454 }
455
456 SLen = NSSPBE_ROUNDUP(salt->len,HMAC_BUFFER);
457 PLen = NSSPBE_ROUNDUP(pwitem->len,HMAC_BUFFER);
458 I.len = SLen+PLen;
459 I.data = (unsigned char*)PORT_ArenaZAlloc(arena, I.len);
460 if (I.data == NULL) {
461 goto loser;
462 }
463
464 /* S & P are only used to initialize I */
465 S = I.data;
466 P = S + SLen;
467
468 PORT_Memset(D.data, (char)bitGenPurpose, D.len);
469 if (SLen) {
470 for (i=0; i < SLen; i += salt->len) {
471 PORT_Memcpy(S+i, salt->data, NSSPBE_MIN(SLen-i,salt->len));
472 }
473 }
474 if (PLen) {
475 for (i=0; i < PLen; i += pwitem->len) {
476 PORT_Memcpy(P+i, pwitem->data, NSSPBE_MIN(PLen-i,pwitem->len));
477 }
478 }
479
480 iterBuf = (unsigned char*)PORT_ArenaZAlloc(arena,hashLength);
481 if (iterBuf == NULL) {
482 goto loser;
483 }
484
485 hash = hashObject->create();
486 if(!hash) {
487 goto loser;
488 }
489 /* calculate the PBE now */
490 for(i = 0; i < c; i++) {
491 int Bidx; /* must be signed or the for loop won't terminate */
492 unsigned int k, j;
493 unsigned char *Ai = A->data+i*hashLength;
494
495
496 for(iter = 0; iter < pbe_param->iter; iter++) {
497 hashObject->begin(hash);
498
499 if (iter) {
500 hashObject->update(hash, iterBuf, hashLen);
501 } else {
502 hashObject->update(hash, D.data, D.len);
503 hashObject->update(hash, I.data, I.len);
504 }
505
506 hashObject->end(hash, iterBuf, &hashLen, hashObject->length);
507 if(hashLen != hashObject->length) {
508 break;
509 }
510 }
511
512 PORT_Memcpy(Ai, iterBuf, hashLength);
513 for (Bidx = 0; Bidx < (int)B.len; Bidx += hashLength) {
514 PORT_Memcpy(B.data+Bidx,iterBuf,NSSPBE_MIN(B.len-Bidx,hashLength));
515 }
516
517 k = I.len/B.len;
518 for(j = 0; j < k; j++) {
519 unsigned int q, carryBit;
520 unsigned char *Ij = I.data + j*B.len;
521
522 /* (Ij = Ij+B+1) */
523 for (Bidx = (B.len-1), q=1, carryBit=0; Bidx >= 0; Bidx--,q=0) {
524 q += (unsigned int)Ij[Bidx];
525 q += (unsigned int)B.data[Bidx];
526 q += carryBit;
527
528 carryBit = (q > 0xff);
529 Ij[Bidx] = (unsigned char)(q & 0xff);
530 }
531 }
532 }
533 loser:
534 if (hash) {
535 hashObject->destroy(hash, PR_TRUE);
536 }
537 if(arena) {
538 PORT_FreeArena(arena, PR_TRUE);
539 }
540
541 if (A) {
542 /* if i != c, then we didn't complete the loop above and must of failed
543 * somwhere along the way */
544 if (i != c) {
545 SECITEM_ZfreeItem(A,PR_TRUE);
546 A = NULL;
547 } else {
548 A->len = bytesNeeded;
549 }
550 }
551
552 return A;
553 }
554
555 /*
556 * generate key as per PKCS 5
557 */
558 SECItem *
559 nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
560 SECItem *iv, PRBool faulty3DES)
561 {
562 SECItem *hash = NULL, *key = NULL;
563 const SECHashObject *hashObj;
564 PRBool getIV = PR_FALSE;
565
566 if((pbe_param == NULL) || (pwitem == NULL)) {
567 return NULL;
568 }
569
570 key = SECITEM_AllocItem(NULL,NULL,pbe_param->keyLen);
571 if (key == NULL) {
572 return NULL;
573 }
574
575 if (iv && (pbe_param->ivLen) && (iv->data == NULL)) {
576 getIV = PR_TRUE;
577 iv->data = (unsigned char *)PORT_Alloc(pbe_param->ivLen);
578 if (iv->data == NULL) {
579 goto loser;
580 }
581 iv->len = pbe_param->ivLen;
582 }
583
584 hashObj = HASH_GetRawHashObject(pbe_param->hashType);
585 switch (pbe_param->pbeType) {
586 case NSSPKCS5_PBKDF1:
587 hash = nsspkcs5_PBKDF1Extended(hashObj,pbe_param,pwitem,faulty3DES);
588 if (hash == NULL) {
589 goto loser;
590 }
591 PORT_Assert(hash->len >= key->len+(getIV ? iv->len : 0));
592 if (getIV) {
593 PORT_Memcpy(iv->data, hash->data+(hash->len - iv->len),iv->len);
594 }
595
596 break;
597 case NSSPKCS5_PBKDF2:
598 hash = nsspkcs5_PBKDF2(hashObj,pbe_param,pwitem);
599 if (getIV) {
600 PORT_Memcpy(iv->data, pbe_param->ivData, iv->len);
601 }
602 break;
603 case NSSPKCS5_PKCS12_V2:
604 if (getIV) {
605 hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem,
606 pbeBitGenCipherIV,iv->len);
607 if (hash == NULL) {
608 goto loser;
609 }
610 PORT_Memcpy(iv->data,hash->data,iv->len);
611 SECITEM_ZfreeItem(hash,PR_TRUE);
612 hash = NULL;
613 }
614 hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem,
615 pbe_param->keyID,key->len);
616 default:
617 break;
618 }
619
620 if (hash == NULL) {
621 goto loser;
622 }
623
624 if (pbe_param->is2KeyDES) {
625 PORT_Memcpy(key->data, hash->data, (key->len * 2) / 3);
626 PORT_Memcpy(&(key->data[(key->len * 2) / 3]), key->data,
627 key->len / 3);
628 } else {
629 PORT_Memcpy(key->data, hash->data, key->len);
630 }
631
632 SECITEM_ZfreeItem(hash, PR_TRUE);
633 return key;
634
635 loser:
636 if (getIV && iv->data) {
637 PORT_ZFree(iv->data,iv->len);
638 iv->data = NULL;
639 }
640
641 SECITEM_ZfreeItem(key, PR_TRUE);
642 return NULL;
643 }
644
645 static SECStatus
646 nsspkcs5_FillInParam(SECOidTag algorithm, HASH_HashType hashType,
647 NSSPKCS5PBEParameter *pbe_param)
648 {
649 PRBool skipType = PR_FALSE;
650
651 pbe_param->keyLen = 5;
652 pbe_param->ivLen = 8;
653 pbe_param->hashType = hashType;
654 pbe_param->pbeType = NSSPKCS5_PBKDF1;
655 pbe_param->encAlg = SEC_OID_RC2_CBC;
656 pbe_param->is2KeyDES = PR_FALSE;
657 switch(algorithm) {
658 /* DES3 Algorithms */
659 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
660 pbe_param->is2KeyDES = PR_TRUE;
661 /* fall through */
662 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
663 pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
664 /* fall through */
665 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
666 pbe_param->keyLen = 24;
667 pbe_param->encAlg = SEC_OID_DES_EDE3_CBC;
668 break;
669
670 /* DES Algorithms */
671 case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
672 pbe_param->hashType = HASH_AlgMD2;
673 goto finish_des;
674 case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
675 pbe_param->hashType = HASH_AlgMD5;
676 /* fall through */
677 case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
678 finish_des:
679 pbe_param->keyLen = 8;
680 pbe_param->encAlg = SEC_OID_DES_CBC;
681 break;
682
683 /* RC2 Algorithms */
684 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
685 pbe_param->keyLen = 16;
686 /* fall through */
687 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
688 pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
689 break;
690 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
691 pbe_param->keyLen = 16;
692 /* fall through */
693 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
694 break;
695
696 /* RC4 algorithms */
697 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
698 skipType = PR_TRUE;
699 /* fall through */
700 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
701 pbe_param->keyLen = 16;
702 /* fall through */
703 case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
704 if (!skipType) {
705 pbe_param->pbeType = NSSPKCS5_PKCS12_V2;
706 }
707 /* fall through */
708 case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
709 pbe_param->ivLen = 0;
710 pbe_param->encAlg = SEC_OID_RC4;
711 break;
712
713 case SEC_OID_PKCS5_PBKDF2:
714 case SEC_OID_PKCS5_PBES2:
715 case SEC_OID_PKCS5_PBMAC1:
716 /* everything else will be filled in by the template */
717 pbe_param->ivLen = 0;
718 pbe_param->pbeType = NSSPKCS5_PBKDF2;
719 pbe_param->encAlg = SEC_OID_PKCS5_PBKDF2;
720 pbe_param->keyLen = 0; /* needs to be set by caller after return */
721 break;
722
723 default:
724 return SECFailure;
725 }
726
727 return SECSuccess;
728 }
729
730 /* decode the algid and generate a PKCS 5 parameter from it
731 */
732 NSSPKCS5PBEParameter *
733 nsspkcs5_NewParam(SECOidTag alg, HASH_HashType hashType, SECItem *salt,
734 int iterationCount)
735 {
736 PLArenaPool *arena = NULL;
737 NSSPKCS5PBEParameter *pbe_param = NULL;
738 SECStatus rv = SECFailure;
739
740 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
741 if (arena == NULL)
742 return NULL;
743
744 /* allocate memory for the parameter */
745 pbe_param = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena,
746 sizeof(NSSPKCS5PBEParameter));
747
748 if (pbe_param == NULL) {
749 goto loser;
750 }
751
752 pbe_param->poolp = arena;
753
754 rv = nsspkcs5_FillInParam(alg, hashType, pbe_param);
755 if (rv != SECSuccess) {
756 goto loser;
757 }
758
759 pbe_param->iter = iterationCount;
760 if (salt) {
761 rv = SECITEM_CopyItem(arena,&pbe_param->salt,salt);
762 }
763
764 /* default key gen */
765 pbe_param->keyID = pbeBitGenCipherKey;
766
767 loser:
768 if (rv != SECSuccess) {
769 PORT_FreeArena(arena, PR_TRUE);
770 pbe_param = NULL;
771 }
772
773 return pbe_param;
774 }
775
776 /*
777 * find the hash type needed to implement a specific HMAC.
778 * OID definitions are from pkcs 5 v2.0 and 2.1
779 */
780 HASH_HashType
781 HASH_FromHMACOid(SECOidTag hmac)
782 {
783 switch (hmac) {
784 case SEC_OID_HMAC_SHA1:
785 return HASH_AlgSHA1;
786 case SEC_OID_HMAC_SHA256:
787 return HASH_AlgSHA256;
788 case SEC_OID_HMAC_SHA384:
789 return HASH_AlgSHA384;
790 case SEC_OID_HMAC_SHA512:
791 return HASH_AlgSHA512;
792 case SEC_OID_HMAC_SHA224:
793 default:
794 break;
795 }
796 return HASH_AlgNULL;
797 }
798
799 /* decode the algid and generate a PKCS 5 parameter from it
800 */
801 NSSPKCS5PBEParameter *
802 nsspkcs5_AlgidToParam(SECAlgorithmID *algid)
803 {
804 NSSPKCS5PBEParameter *pbe_param = NULL;
805 nsspkcs5V2PBEParameter pbev2_param;
806 SECOidTag algorithm;
807 SECStatus rv = SECFailure;
808
809 if (algid == NULL) {
810 return NULL;
811 }
812
813 algorithm = SECOID_GetAlgorithmTag(algid);
814 if (algorithm == SEC_OID_UNKNOWN) {
815 goto loser;
816 }
817
818 pbe_param = nsspkcs5_NewParam(algorithm, HASH_AlgSHA1, NULL, 1);
819 if (pbe_param == NULL) {
820 goto loser;
821 }
822
823 /* decode parameter */
824 rv = SECFailure;
825 switch (pbe_param->pbeType) {
826 case NSSPKCS5_PBKDF1:
827 rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
828 NSSPKCS5PBEParameterTemplate, &algid->parameters);
829 break;
830 case NSSPKCS5_PKCS12_V2:
831 rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
832 NSSPKCS5PKCS12V2PBEParameterTemplate, &algid->parameters);
833 break;
834 case NSSPKCS5_PBKDF2:
835 PORT_Memset(&pbev2_param,0, sizeof(pbev2_param));
836 /* just the PBE */
837 if (algorithm == SEC_OID_PKCS5_PBKDF2) {
838 rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
839 NSSPKCS5V2PBEParameterTemplate, &algid->parameters);
840 } else {
841 /* PBE data an others */
842 rv = SEC_ASN1DecodeItem(pbe_param->poolp, &pbev2_param,
843 NSSPKCS5V2PBES2ParameterTemplate, &algid->parameters);
844 if (rv != SECSuccess) {
845 break;
846 }
847 pbe_param->encAlg = SECOID_GetAlgorithmTag(&pbev2_param.algParams);
848 rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param,
849 NSSPKCS5V2PBEParameterTemplate,
850 &pbev2_param.keyParams.parameters);
851 if (rv != SECSuccess) {
852 break;
853 }
854 pbe_param->keyLen = DER_GetInteger(&pbe_param->keyLength);
855 }
856 /* we we are encrypting, save any iv's */
857 if (algorithm == SEC_OID_PKCS5_PBES2) {
858 pbe_param->ivLen = pbev2_param.algParams.parameters.len;
859 pbe_param->ivData = pbev2_param.algParams.parameters.data;
860 }
861 pbe_param->hashType =
862 HASH_FromHMACOid(SECOID_GetAlgorithmTag(&pbe_param->prfAlg));
863 if (pbe_param->hashType == HASH_AlgNULL) {
864 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
865 rv = SECFailure;
866 }
867 break;
868 }
869
870 loser:
871 if (rv == SECSuccess) {
872 pbe_param->iter = DER_GetInteger(&pbe_param->iteration);
873 } else {
874 nsspkcs5_DestroyPBEParameter(pbe_param);
875 pbe_param = NULL;
876 }
877
878 return pbe_param;
879 }
880
881 /* destroy a pbe parameter. it assumes that the parameter was
882 * generated using the appropriate create function and therefor
883 * contains an arena pool.
884 */
885 void
886 nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param)
887 {
888 if (pbe_param != NULL) {
889 PORT_FreeArena(pbe_param->poolp, PR_FALSE);
890 }
891 }
892
893
894 /* crypto routines */
895 /* perform DES encryption and decryption. these routines are called
896 * by nsspkcs5_CipherData. In the case of an error, NULL is returned.
897 */
898 static SECItem *
899 sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
900 PRBool encrypt)
901 {
902 SECItem *dest;
903 SECItem *dup_src;
904 SECStatus rv = SECFailure;
905 int pad;
906
907 if((src == NULL) || (key == NULL) || (iv == NULL))
908 return NULL;
909
910 dup_src = SECITEM_DupItem(src);
911 if(dup_src == NULL) {
912 return NULL;
913 }
914
915 if(encrypt != PR_FALSE) {
916 void *dummy;
917
918 dummy = CBC_PadBuffer(NULL, dup_src->data,
919 dup_src->len, &dup_src->len, 8 /* DES_BLOCK_SIZE */);
920 if(dummy == NULL) {
921 SECITEM_FreeItem(dup_src, PR_TRUE);
922 return NULL;
923 }
924 dup_src->data = (unsigned char*)dummy;
925 }
926
927 dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
928 if(dest != NULL) {
929 /* allocate with over flow */
930 dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
931 if(dest->data != NULL) {
932 DESContext *ctxt;
933 ctxt = DES_CreateContext(key->data, iv->data,
934 (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC),
935 encrypt);
936
937 if(ctxt != NULL) {
938 rv = (encrypt ? DES_Encrypt : DES_Decrypt)(
939 ctxt, dest->data, &dest->len,
940 dup_src->len + 64, dup_src->data, dup_src->len);
941
942 /* remove padding -- assumes 64 bit blocks */
943 if((encrypt == PR_FALSE) && (rv == SECSuccess)) {
944 pad = dest->data[dest->len-1];
945 if((pad > 0) && (pad <= 8)) {
946 if(dest->data[dest->len-pad] != pad) {
947 rv = SECFailure;
948 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
949 } else {
950 dest->len -= pad;
951 }
952 } else {
953 rv = SECFailure;
954 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
955 }
956 }
957 DES_DestroyContext(ctxt, PR_TRUE);
958 }
959 }
960 }
961
962 if(rv == SECFailure) {
963 if(dest != NULL) {
964 SECITEM_FreeItem(dest, PR_TRUE);
965 }
966 dest = NULL;
967 }
968
969 if(dup_src != NULL) {
970 SECITEM_FreeItem(dup_src, PR_TRUE);
971 }
972
973 return dest;
974 }
975
976 /* perform aes encryption/decryption if an error occurs, NULL is returned
977 */
978 static SECItem *
979 sec_pkcs5_aes(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des,
980 PRBool encrypt)
981 {
982 SECItem *dest;
983 SECItem *dup_src;
984 SECStatus rv = SECFailure;
985 int pad;
986
987 if((src == NULL) || (key == NULL) || (iv == NULL))
988 return NULL;
989
990 dup_src = SECITEM_DupItem(src);
991 if(dup_src == NULL) {
992 return NULL;
993 }
994
995 if(encrypt != PR_FALSE) {
996 void *dummy;
997
998 dummy = CBC_PadBuffer(NULL, dup_src->data,
999 dup_src->len, &dup_src->len,AES_BLOCK_SIZE);
1000 if(dummy == NULL) {
1001 SECITEM_FreeItem(dup_src, PR_TRUE);
1002 return NULL;
1003 }
1004 dup_src->data = (unsigned char*)dummy;
1005 }
1006
1007 dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
1008 if(dest != NULL) {
1009 /* allocate with over flow */
1010 dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
1011 if(dest->data != NULL) {
1012 AESContext *ctxt;
1013 ctxt = AES_CreateContext(key->data, iv->data,
1014 NSS_AES_CBC, encrypt, key->len, 16);
1015
1016 if(ctxt != NULL) {
1017 rv = (encrypt ? AES_Encrypt : AES_Decrypt)(
1018 ctxt, dest->data, &dest->len,
1019 dup_src->len + 64, dup_src->data, dup_src->len);
1020
1021 /* remove padding -- assumes 64 bit blocks */
1022 if((encrypt == PR_FALSE) && (rv == SECSuccess)) {
1023 pad = dest->data[dest->len-1];
1024 if((pad > 0) && (pad <= 16)) {
1025 if(dest->data[dest->len-pad] != pad) {
1026 rv = SECFailure;
1027 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
1028 } else {
1029 dest->len -= pad;
1030 }
1031 } else {
1032 rv = SECFailure;
1033 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
1034 }
1035 }
1036 AES_DestroyContext(ctxt, PR_TRUE);
1037 }
1038 }
1039 }
1040
1041 if(rv == SECFailure) {
1042 if(dest != NULL) {
1043 SECITEM_FreeItem(dest, PR_TRUE);
1044 }
1045 dest = NULL;
1046 }
1047
1048 if(dup_src != NULL) {
1049 SECITEM_FreeItem(dup_src, PR_TRUE);
1050 }
1051
1052 return dest;
1053 }
1054
1055 /* perform rc2 encryption/decryption if an error occurs, NULL is returned
1056 */
1057 static SECItem *
1058 sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy,
1059 PRBool encrypt)
1060 {
1061 SECItem *dest;
1062 SECItem *dup_src;
1063 SECStatus rv = SECFailure;
1064 int pad;
1065
1066 if((src == NULL) || (key == NULL) || (iv == NULL)) {
1067 return NULL;
1068 }
1069
1070 dup_src = SECITEM_DupItem(src);
1071 if(dup_src == NULL) {
1072 return NULL;
1073 }
1074
1075 if(encrypt != PR_FALSE) {
1076 void *dummy;
1077
1078 dummy = CBC_PadBuffer(NULL, dup_src->data,
1079 dup_src->len, &dup_src->len, 8 /* RC2_BLOCK_SIZE */);
1080 if(dummy == NULL) {
1081 SECITEM_FreeItem(dup_src, PR_TRUE);
1082 return NULL;
1083 }
1084 dup_src->data = (unsigned char*)dummy;
1085 }
1086
1087 dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
1088 if(dest != NULL) {
1089 dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
1090 if(dest->data != NULL) {
1091 RC2Context *ctxt;
1092
1093 ctxt = RC2_CreateContext(key->data, key->len, iv->data,
1094 NSS_RC2_CBC, key->len);
1095
1096 if(ctxt != NULL) {
1097 rv = (encrypt ? RC2_Encrypt: RC2_Decrypt)(
1098 ctxt, dest->data, &dest->len,
1099 dup_src->len + 64, dup_src->data, dup_src->len);
1100
1101 /* assumes 8 byte blocks -- remove padding */
1102 if((rv == SECSuccess) && (encrypt != PR_TRUE)) {
1103 pad = dest->data[dest->len-1];
1104 if((pad > 0) && (pad <= 8)) {
1105 if(dest->data[dest->len-pad] != pad) {
1106 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
1107 rv = SECFailure;
1108 } else {
1109 dest->len -= pad;
1110 }
1111 } else {
1112 PORT_SetError(SEC_ERROR_BAD_PASSWORD);
1113 rv = SECFailure;
1114 }
1115 }
1116
1117 }
1118 }
1119 }
1120
1121 if((rv != SECSuccess) && (dest != NULL)) {
1122 SECITEM_FreeItem(dest, PR_TRUE);
1123 dest = NULL;
1124 }
1125
1126 if(dup_src != NULL) {
1127 SECITEM_FreeItem(dup_src, PR_TRUE);
1128 }
1129
1130 return dest;
1131 }
1132
1133 /* perform rc4 encryption and decryption */
1134 static SECItem *
1135 sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op,
1136 PRBool encrypt)
1137 {
1138 SECItem *dest;
1139 SECStatus rv = SECFailure;
1140
1141 if((src == NULL) || (key == NULL) || (iv == NULL)) {
1142 return NULL;
1143 }
1144
1145 dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
1146 if(dest != NULL) {
1147 dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
1148 (src->len + 64));
1149 if(dest->data != NULL) {
1150 RC4Context *ctxt;
1151
1152 ctxt = RC4_CreateContext(key->data, key->len);
1153 if(ctxt) {
1154 rv = (encrypt ? RC4_Encrypt : RC4_Decrypt)(
1155 ctxt, dest->data, &dest->len,
1156 src->len + 64, src->data, src->len);
1157 RC4_DestroyContext(ctxt, PR_TRUE);
1158 }
1159 }
1160 }
1161
1162 if((rv != SECSuccess) && (dest)) {
1163 SECITEM_FreeItem(dest, PR_TRUE);
1164 dest = NULL;
1165 }
1166
1167 return dest;
1168 }
1169 /* function pointer template for crypto functions */
1170 typedef SECItem *(* pkcs5_crypto_func)(SECItem *key, SECItem *iv,
1171 SECItem *src, PRBool op1, PRBool op2);
1172
1173 /* performs the cipher operation on the src and returns the result.
1174 * if an error occurs, NULL is returned.
1175 *
1176 * a null length password is allowed. this corresponds to encrypting
1177 * the data with ust the salt.
1178 */
1179 /* change this to use PKCS 11? */
1180 SECItem *
1181 nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem,
1182 SECItem *src, PRBool encrypt, PRBool *update)
1183 {
1184 SECItem *key = NULL, iv;
1185 SECItem *dest = NULL;
1186 PRBool tripleDES = PR_TRUE;
1187 pkcs5_crypto_func cryptof;
1188
1189 iv.data = NULL;
1190
1191 if (update) {
1192 *update = PR_FALSE;
1193 }
1194
1195 if ((pwitem == NULL) || (src == NULL)) {
1196 return NULL;
1197 }
1198
1199 /* get key, and iv */
1200 key = nsspkcs5_ComputeKeyAndIV(pbe_param, pwitem, &iv, PR_FALSE);
1201 if(key == NULL) {
1202 return NULL;
1203 }
1204
1205 switch(pbe_param->encAlg) {
1206 /* PKCS 5 v2 only */
1207 case SEC_OID_AES_128_CBC:
1208 case SEC_OID_AES_192_CBC:
1209 case SEC_OID_AES_256_CBC:
1210 cryptof = sec_pkcs5_aes;
1211 break;
1212 case SEC_OID_DES_EDE3_CBC:
1213 cryptof = sec_pkcs5_des;
1214 tripleDES = PR_TRUE;
1215 break;
1216 case SEC_OID_DES_CBC:
1217 cryptof = sec_pkcs5_des;
1218 tripleDES = PR_FALSE;
1219 break;
1220 case SEC_OID_RC2_CBC:
1221 cryptof = sec_pkcs5_rc2;
1222 break;
1223 case SEC_OID_RC4:
1224 cryptof = sec_pkcs5_rc4;
1225 break;
1226 default:
1227 cryptof = NULL;
1228 break;
1229 }
1230
1231 if (cryptof == NULL) {
1232 goto loser;
1233 }
1234
1235 dest = (*cryptof)(key, &iv, src, tripleDES, encrypt);
1236 /*
1237 * it's possible for some keys and keydb's to claim to
1238 * be triple des when they're really des. In this case
1239 * we simply try des. If des works we set the update flag
1240 * so the key db knows it needs to update all it's entries.
1241 * The case can only happen on decrypted of a
1242 * SEC_OID_DES_EDE3_CBD.
1243 */
1244 if ((dest == NULL) && (encrypt == PR_FALSE) &&
1245 (pbe_param->encAlg == SEC_OID_DES_EDE3_CBC)) {
1246 dest = (*cryptof)(key, &iv, src, PR_FALSE, encrypt);
1247 if (update && (dest != NULL)) *update = PR_TRUE;
1248 }
1249
1250 loser:
1251 if (key != NULL) {
1252 SECITEM_ZfreeItem(key, PR_TRUE);
1253 }
1254 if (iv.data != NULL) {
1255 SECITEM_ZfreeItem(&iv, PR_FALSE);
1256 }
1257
1258 return dest;
1259 }
1260
1261 /* creates a algorithm ID containing the PBE algorithm and appropriate
1262 * parameters. the required parameter is the algorithm. if salt is
1263 * not specified, it is generated randomly. if IV is specified, it overrides
1264 * the PKCS 5 generation of the IV.
1265 *
1266 * the returned SECAlgorithmID should be destroyed using
1267 * SECOID_DestroyAlgorithmID
1268 */
1269 SECAlgorithmID *
1270 nsspkcs5_CreateAlgorithmID(PLArenaPool *arena, SECOidTag algorithm,
1271 NSSPKCS5PBEParameter *pbe_param)
1272 {
1273 SECAlgorithmID *algid, *ret_algid = NULL;
1274 SECItem der_param;
1275 nsspkcs5V2PBEParameter pkcs5v2_param;
1276
1277 SECStatus rv = SECFailure;
1278 void *dummy = NULL;
1279
1280 if (arena == NULL) {
1281 return NULL;
1282 }
1283
1284 der_param.data = NULL;
1285 der_param.len = 0;
1286
1287 /* generate the algorithm id */
1288 algid = (SECAlgorithmID *)PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID));
1289 if (algid == NULL) {
1290 goto loser;
1291 }
1292
1293 if (pbe_param->iteration.data == NULL) {
1294 dummy = SEC_ASN1EncodeInteger(pbe_param->poolp,&pbe_param->iteration,
1295 pbe_param->iter) ;
1296 if (dummy == NULL) {
1297 goto loser;
1298 }
1299 }
1300 switch (pbe_param->pbeType) {
1301 case NSSPKCS5_PBKDF1:
1302 dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
1303 NSSPKCS5PBEParameterTemplate);
1304 break;
1305 case NSSPKCS5_PKCS12_V2:
1306 dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
1307 NSSPKCS5PKCS12V2PBEParameterTemplate);
1308 break;
1309 case NSSPKCS5_PBKDF2:
1310 if (pbe_param->keyLength.data == NULL) {
1311 dummy = SEC_ASN1EncodeInteger(pbe_param->poolp,
1312 &pbe_param->keyLength, pbe_param->keyLen);
1313 if (dummy == NULL) {
1314 goto loser;
1315 }
1316 }
1317 PORT_Memset(&pkcs5v2_param, 0, sizeof(pkcs5v2_param));
1318 dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param,
1319 NSSPKCS5V2PBEParameterTemplate);
1320 if (dummy == NULL) {
1321 break;
1322 }
1323 dummy = NULL;
1324 rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.keyParams,
1325 SEC_OID_PKCS5_PBKDF2, &der_param);
1326 if (rv != SECSuccess) {
1327 break;
1328 }
1329 der_param.data = pbe_param->ivData;
1330 der_param.len = pbe_param->ivLen;
1331 rv = SECOID_SetAlgorithmID(arena, &pkcs5v2_param.algParams,
1332 pbe_param->encAlg, pbe_param->ivLen ? &der_param : NULL);
1333 if (rv != SECSuccess) {
1334 break;
1335 }
1336 dummy = SEC_ASN1EncodeItem(arena, &der_param, &pkcs5v2_param,
1337 NSSPKCS5V2PBES2ParameterTemplate);
1338 break;
1339 default:
1340 break;
1341 }
1342
1343 if (dummy == NULL) {
1344 goto loser;
1345 }
1346
1347 rv = SECOID_SetAlgorithmID(arena, algid, algorithm, &der_param);
1348 if (rv != SECSuccess) {
1349 goto loser;
1350 }
1351
1352 ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
1353 if (ret_algid == NULL) {
1354 goto loser;
1355 }
1356
1357 rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
1358 if (rv != SECSuccess) {
1359 SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
1360 ret_algid = NULL;
1361 }
1362
1363 loser:
1364
1365 return ret_algid;
1366 }
OLDNEW
« no previous file with comments | « nss/lib/softoken/lowpbe.h ('k') | nss/lib/softoken/padbuf.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698