/security/nss/lib/softoken/lowpbe.c

http://github.com/zpao/v8monkey · C · 1410 lines · 1073 code · 176 blank · 161 comment · 332 complexity · 082196e4487d2e02e6204c551ced476f MD5 · raw file

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