secpkcs5.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:46k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #include "plarena.h"
  34. #include "seccomon.h"
  35. #include "secitem.h"
  36. #include "secport.h"
  37. #include "hasht.h"
  38. #include "pkcs11t.h"
  39. #include "blapi.h"
  40. #include "sechash.h"
  41. #include "secasn1.h"
  42. #include "secder.h"
  43. #include "secpkcs5.h"
  44. #include "secoid.h"
  45. #include "alghmac.h"
  46. #include "softoken.h"
  47. #include "secerr.h"
  48. #define DES_IV_LENGTH 8
  49. #define RC2_IV_LENGTH 8
  50. #define MD2_LENGTH 16
  51. #define MD5_LENGTH 16
  52. #define SHA1_LENGTH 20
  53. #define SEED_LENGTH  16
  54. #define SALT_LENGTH 8
  55. #define PBE_SALT_LENGTH 16
  56. /* template for PKCS 5 PBE Parameter.  This template has been expanded
  57.  * based upon the additions in PKCS 12.  This should eventually be moved
  58.  * if RSA updates PKCS 5.
  59.  */
  60. const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] =
  61. {
  62.     { SEC_ASN1_SEQUENCE, 
  63. 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
  64.     { SEC_ASN1_OCTET_STRING, 
  65. offsetof(SEC_PKCS5PBEParameter, salt) },
  66.     { SEC_ASN1_INTEGER,
  67. offsetof(SEC_PKCS5PBEParameter, iteration) },
  68.     { 0 }
  69. };
  70. const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] =
  71. {   
  72.     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) },
  73.     { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) },
  74.     { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) },
  75.     { 0 }
  76. };
  77. pbeBitGenParameters pbeHashAlgorithmParams[] = {
  78.     {   0,   0, SEC_OID_UNKNOWN },
  79.     { 128, 512, SEC_OID_MD2 },
  80.     { 128, 512, SEC_OID_MD5 },
  81.     { 160, 512, SEC_OID_SHA1 },
  82. };
  83. /* generate some random bytes.  this is used to generate the 
  84.  * salt if it is not specified.
  85.  */
  86. static SECStatus 
  87. sec_pkcs5_generate_random_bytes(PRArenaPool *poolp, 
  88. SECItem *dest, int len)
  89. {
  90.     SECStatus rv = SECFailure;
  91.     if(dest != NULL)
  92.     {
  93. void *mark = PORT_ArenaMark(poolp);
  94. dest->data = (unsigned char *)PORT_ArenaZAlloc(poolp, len);
  95. if(dest->data != NULL)
  96. {
  97.     dest->len = len;
  98.     RNG_GenerateGlobalRandomBytes(dest->data, dest->len);
  99.     PORT_ArenaUnmark(poolp, mark);
  100.     rv = SECSuccess;
  101. } else
  102.     PORT_ArenaRelease(poolp, mark);
  103.     }
  104.     return rv;
  105. }
  106. /* maps hash algorithm from PBE algorithm.
  107.  */
  108. static SECOidTag 
  109. sec_pkcs5_hash_algorithm(SECOidTag algorithm)
  110. {
  111.     switch(algorithm)
  112.     {
  113. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
  114. case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
  115. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  116. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  117. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
  118. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
  119. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
  120. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
  121. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
  122. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
  123. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  124. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  125.     return SEC_OID_SHA1;
  126. case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
  127.     return SEC_OID_MD5;
  128. case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
  129.     return SEC_OID_MD2;
  130. default:
  131.     break;
  132.     }
  133.     return SEC_OID_UNKNOWN;
  134. }
  135. /* get the iv length needed for the PBE algorithm 
  136.  */
  137. static int 
  138. sec_pkcs5_iv_length(SECOidTag algorithm)
  139. {
  140.     switch(algorithm)
  141.     {
  142. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
  143. case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
  144. case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
  145. case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
  146. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
  147. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
  148.     return DES_IV_LENGTH;
  149. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  150. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  151. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  152. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  153.     return RC2_IV_LENGTH;
  154. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
  155. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
  156. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
  157. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
  158.     return 0;
  159. default:
  160.     break;
  161.     }
  162.     return -1;
  163. }
  164. /* get the key length needed for the PBE algorithm
  165.  */
  166. static int 
  167. sec_pkcs5_key_length(SECOidTag algorithm)
  168. {
  169.     switch(algorithm)
  170.     {
  171. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
  172. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
  173. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
  174.     return 24;
  175. case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
  176. case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
  177. case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
  178.     return 8;
  179. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  180. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
  181. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
  182. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  183.     return 5;
  184. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  185. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
  186. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  187. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
  188.     return 16;
  189. default:
  190.     break;
  191.     }
  192.     return -1;
  193. }
  194. /* the V2 algorithms only encode the salt, there is no iteration
  195.  * count so we need a check for V2 algorithm parameters.
  196.  */
  197. static PRBool
  198. sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm)
  199. {
  200.     switch(algorithm) 
  201.     {
  202. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
  203. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
  204. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
  205. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
  206. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  207. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  208.     return PR_TRUE;
  209. default:
  210.     break;
  211.     }
  212.     return PR_FALSE;
  213. }
  214. /* creates a PBE parameter based on the PBE algorithm.  the only required
  215.  * parameters are algorithm and interation.  the return is a PBE parameter
  216.  * which conforms to PKCS 5 parameter unless an extended parameter is needed.
  217.  * this is primarily if keyLen and a variable key length algorithm are
  218.  * specified.
  219.  *   salt -  if null, a salt will be generated from random bytes.
  220.  *   iteration - number of iterations to perform hashing.
  221.  *   keyLen - only used in variable key length algorithms
  222.  *   iv - if null, the IV will be generated based on PKCS 5 when needed.
  223.  *   params - optional, currently unsupported additional parameters.
  224.  * once a parameter is allocated, it should be destroyed calling 
  225.  * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter.
  226.  */
  227. static SEC_PKCS5PBEParameter *
  228. sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, 
  229. SECItem *salt, 
  230. int iteration)
  231. {
  232.     PRArenaPool *poolp = NULL;
  233.     SEC_PKCS5PBEParameter *pbe_param = NULL;
  234.     SECStatus rv; 
  235.     void *dummy = NULL;
  236.     if(iteration < 0) {
  237. return NULL;
  238.     }
  239.     poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  240.     if(poolp == NULL)
  241. return NULL;
  242.     pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp,
  243. sizeof(SEC_PKCS5PBEParameter));
  244.     if(!pbe_param) {
  245. PORT_FreeArena(poolp, PR_TRUE);
  246. return NULL;
  247.     }
  248.     pbe_param->poolp = poolp;
  249.     pbe_param->algorithm = algorithm;
  250.     /* should we generate the salt? */
  251.     if(!salt || !salt->data) {
  252. rv = sec_pkcs5_generate_random_bytes(poolp, &pbe_param->salt, 
  253. SALT_LENGTH);
  254.     } else {
  255. rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt);
  256.     }
  257.     if(rv != SECSuccess) {
  258. PORT_FreeArena(poolp, PR_TRUE);
  259. return NULL;
  260.     }
  261.     /* encode the integer */
  262.     dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, 
  263. iteration);
  264.     rv = (dummy) ? SECSuccess : SECFailure;
  265.     if(rv != SECSuccess) {
  266. PORT_FreeArena(poolp, PR_FALSE);
  267. return NULL;
  268.     }
  269.     return pbe_param;
  270. }
  271. /* generate bits for key and iv using MD5 hashing 
  272.  */
  273. static SECItem *
  274. sec_pkcs5_compute_md5_hash(SECItem *salt, SECItem *pwd, int iter,
  275.    PRBool dummy)
  276. {
  277.     SECItem *hash = NULL, *pre_hash = NULL;
  278.     SECStatus rv = SECFailure;
  279.     if((salt == NULL) || (pwd == NULL) || (iter < 0)) {
  280. return NULL;
  281.     }
  282.     hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  283.     pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  284.     if((hash != NULL) && (pre_hash != NULL)) {
  285. unsigned int i, ph_len;
  286. ph_len = MD5_LENGTH;
  287. if(ph_len < (salt->len + pwd->len)) {
  288.     ph_len = salt->len + pwd->len;
  289. }
  290. rv = SECFailure;
  291. hash->data = (unsigned char *)PORT_ZAlloc(MD5_LENGTH);
  292. hash->len = MD5_LENGTH;
  293. pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len);
  294. pre_hash->len = salt->len + pwd->len;
  295. if((hash->data != NULL) && (pre_hash->data != NULL)) {
  296.     rv = SECSuccess;
  297.     /* handle 0 length password */
  298.     if(pwd->len > 0) {
  299. PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
  300.     }
  301.     if(salt->len > 0) {
  302.   PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len);
  303.     }
  304.     for(i = 0; ((i < (unsigned int)iter) && (rv == SECSuccess)); i++) {
  305. rv = MD5_HashBuf(hash->data, pre_hash->data, pre_hash->len);
  306. if(rv != SECFailure) {
  307.     PORT_Memcpy(pre_hash->data, hash->data, MD5_LENGTH);
  308.     pre_hash->len = MD5_LENGTH;
  309. }
  310.     }
  311. }
  312.     }
  313.     if(pre_hash != NULL)
  314. SECITEM_FreeItem(pre_hash, PR_TRUE);
  315.     if((rv == SECFailure) && (hash)) {
  316. SECITEM_FreeItem(hash, PR_TRUE);
  317. hash = NULL;
  318.     }
  319.     return hash;
  320. }
  321. /* generate bits for key and iv using MD2 hashing 
  322.  */
  323. static SECItem *
  324. sec_pkcs5_compute_md2_hash(SECItem *salt, SECItem *pwd, int iter,
  325.    PRBool dummy)
  326. {
  327.     SECItem *hash = NULL, *pre_hash = NULL;
  328.     SECStatus rv = SECFailure;
  329.     if((salt == NULL) || (pwd == NULL) || (iter < 0))
  330. return NULL;
  331.     hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  332.     pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  333.     if((hash != NULL) && (pre_hash != NULL))
  334.     {
  335. int i, ph_len;
  336. ph_len = MD2_LENGTH;
  337. if((salt->len + pwd->len) > MD2_LENGTH)
  338.     ph_len = salt->len+pwd->len;
  339. rv = SECFailure;
  340. hash->data = (unsigned char *)PORT_ZAlloc(MD2_LENGTH);
  341. hash->len = MD2_LENGTH;
  342. pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len);
  343. pre_hash->len = salt->len + pwd->len;
  344. if((hash->data != NULL) && (pre_hash->data != NULL))
  345. {
  346.     MD2Context *ctxt;
  347.     rv = SECSuccess;
  348.     if(pwd->len > 0) {
  349. PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
  350.     }
  351.     if(salt->len > 0) {
  352. PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len);
  353.     }
  354.     for(i = 0; ((i < iter) && (rv == SECSuccess)); i++)
  355.     {
  356. ctxt = MD2_NewContext();
  357. if(ctxt == NULL)
  358.     rv = SECFailure;
  359. else
  360. {
  361.     MD2_Update(ctxt, pre_hash->data, pre_hash->len);
  362.     MD2_End(ctxt, hash->data, &hash->len, hash->len);
  363.     PORT_Memcpy(pre_hash->data, hash->data, MD2_LENGTH);
  364.     pre_hash->len = MD2_LENGTH;
  365.     MD2_DestroyContext(ctxt, PR_TRUE);
  366. }
  367.     }
  368. }
  369.     }
  370.     if(pre_hash != NULL)
  371. SECITEM_FreeItem(pre_hash, PR_TRUE);
  372.     if(rv != SECSuccess)
  373. if(hash != NULL)
  374. {
  375.     SECITEM_FreeItem(hash, PR_TRUE);
  376.     hash = NULL;
  377. }
  378.     return hash;
  379. }
  380. /* generate bits using SHA1 hash 
  381.  */
  382. static SECItem *
  383. sec_pkcs5_compute_sha1_hash(SECItem *salt, SECItem *pwd, int iter, 
  384.     PRBool faulty3DES) 
  385. {
  386.     SECItem *hash = NULL, *pre_hash = NULL;
  387.     SECStatus rv = SECFailure;
  388.     if((salt == NULL) || (pwd == NULL) || (iter < 0)) {
  389. return NULL;
  390.     }
  391.     hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  392.     pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  393.     if((hash != NULL) && (pre_hash != NULL)) {
  394. int i, ph_len;
  395. ph_len = SHA1_LENGTH;
  396. if((salt->len + pwd->len) > SHA1_LENGTH) {
  397.     ph_len = salt->len + pwd->len;
  398. }
  399. rv = SECFailure;
  400. /* allocate buffers */
  401. hash->data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH);
  402. hash->len = SHA1_LENGTH;
  403. pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len);
  404. /* in pbeSHA1TripleDESCBC there was an allocation error that made
  405.  * it into the caller.  We do not want to propagate those errors
  406.  * further, so we are doing it correctly, but reading the old method.
  407.  */
  408. if(faulty3DES) {
  409.     pre_hash->len = ph_len;
  410. } else {
  411.     pre_hash->len = salt->len + pwd->len;
  412. }
  413. /* preform hash */
  414. if((hash->data != NULL) && (pre_hash->data != NULL)) {
  415.     rv = SECSuccess;
  416.     /* check for 0 length password */
  417.     if(pwd->len > 0) {
  418. PORT_Memcpy(pre_hash->data, pwd->data, pwd->len);
  419.     }
  420.     if(salt->len > 0) {
  421. PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len);
  422.     }
  423.     for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) {
  424. rv = SHA1_HashBuf(hash->data, pre_hash->data, pre_hash->len);
  425. if(rv != SECFailure) {
  426.     pre_hash->len = SHA1_LENGTH;
  427.     PORT_Memcpy(pre_hash->data, hash->data, SHA1_LENGTH);
  428. }
  429.     }
  430. }
  431.     }
  432.     if(pre_hash != NULL) {
  433. SECITEM_FreeItem(pre_hash, PR_TRUE);
  434.     }
  435.     if((rv != SECSuccess) && (hash != NULL)) {
  436. SECITEM_FreeItem(hash, PR_TRUE);
  437. hash = NULL;
  438.     }
  439.     return hash;
  440. }
  441. /* bit generation/key and iv generation routines. */
  442. typedef SECItem *(* sec_pkcs5_hash_func)(SECItem *s, SECItem *p, 
  443.  int iter, PRBool faulty3DES);
  444. /* generates bits needed for the key and iv based on PKCS 5,
  445.  * be concatenating the password and salt and using the appropriate
  446.  * hash algorithm.  This function serves as a front end to the 
  447.  * specific hash functions above.  a return of NULL indicates an
  448.  * error.
  449.  */
  450. static SECItem *
  451. sec_pkcs5_compute_hash(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem,
  452.        PRBool faulty3DES)
  453. {
  454.     sec_pkcs5_hash_func hash_func;
  455.     SECOidTag hash_alg;
  456.     SECItem *hash = NULL;
  457.     SECItem *salt = NULL;
  458.     hash_alg = sec_pkcs5_hash_algorithm(pbe_param->algorithm);
  459.     salt = &(pbe_param->salt);
  460.     switch(hash_alg)
  461.     {
  462. case SEC_OID_SHA1:
  463.     hash_func = sec_pkcs5_compute_sha1_hash;
  464.     break;
  465. case SEC_OID_MD2:
  466.     hash_func = sec_pkcs5_compute_md2_hash;
  467.     break;
  468. case SEC_OID_MD5:
  469.     hash_func = sec_pkcs5_compute_md5_hash;
  470.     break;
  471. default:
  472.     hash_func = NULL;
  473.     }
  474.     if(hash_func) {
  475. hash = (* hash_func)(salt, pwitem, pbe_param->iter, faulty3DES);
  476.     }
  477.     return hash;
  478. }
  479. /* determines the number of bits needed for key and iv generation
  480.  * based upon the algorithm identifier.  if a number of
  481.  * bits greater than the hash algorithm can produce are needed,
  482.  * the bits will be generated based upon the extended PKCS 5 
  483.  * described in PKCS 12.
  484.  *
  485.  * a return of -1 indicates an error.
  486.  */
  487. static int 
  488. sec_pkcs5_bits_needed(SEC_PKCS5PBEParameter *pbe_param)
  489. {
  490.     int iv_bits;
  491.     int key_bits;
  492.     
  493.     if(pbe_param == NULL) {
  494. return -1;
  495.     }
  496.     iv_bits = sec_pkcs5_iv_length(pbe_param->algorithm) * 8;
  497.     key_bits = sec_pkcs5_key_length(pbe_param->algorithm) * 8;
  498.     if(key_bits != 0) {
  499. return iv_bits + key_bits;
  500.     }
  501.     return -1;
  502. }
  503. /* determines the number of bits generated by each hash algorithm.
  504.  * in case of an error, -1 is returned. 
  505.  */
  506. static int
  507. sec_pkcs5_hash_bits_generated(SEC_PKCS5PBEParameter *pbe_param)
  508. {
  509.     if(pbe_param == NULL) {
  510. return -1;
  511.     }
  512.     switch(sec_pkcs5_hash_algorithm(pbe_param->algorithm)) {
  513. case SEC_OID_SHA1:
  514.     return SHA1_LENGTH * 8;
  515. case SEC_OID_MD2:
  516.     return MD2_LENGTH * 8;
  517. case SEC_OID_MD5:
  518.     return MD5_LENGTH * 8;
  519. default:
  520.     break;
  521.     }
  522.     return -1;
  523. }
  524. /* this bit generation routine is described in PKCS 12 and the proposed
  525.  * extensions to PKCS 5.  an initial hash is generated following the
  526.  * instructions laid out in PKCS 5.  If the number of bits generated is
  527.  * insufficient, then the method discussed in the proposed extensions to
  528.  * PKCS 5 in PKCS 12 are used.  This extension makes use of the HMAC
  529.  * function.  And the P_Hash function from the TLS standard.
  530.  */
  531. static SECItem *
  532. sec_pkcs5_bit_generator(SEC_PKCS5PBEParameter *pbe_param,
  533. SECItem *init_hash, 
  534. unsigned int bits_needed)
  535. {
  536.     SECItem *ret_bits = NULL;
  537.     int hash_size = 0;
  538.     unsigned int i;
  539.     unsigned int hash_iter;
  540.     unsigned int dig_len;
  541.     SECStatus rv = SECFailure;
  542.     unsigned char *state = NULL;
  543.     unsigned int state_len;
  544.     HMACContext *cx = NULL;
  545.     hash_size = sec_pkcs5_hash_bits_generated(pbe_param);
  546.     if(hash_size == -1)
  547. return NULL;
  548.     hash_iter = (bits_needed + (unsigned int)hash_size - 1) / hash_size;
  549.     hash_size /= 8;
  550.     /* allocate return buffer */
  551.     ret_bits = (SECItem  *)PORT_ZAlloc(sizeof(SECItem));
  552.     if(ret_bits == NULL)
  553. return NULL;
  554.     ret_bits->data = (unsigned char *)PORT_ZAlloc((hash_iter * hash_size) + 1);
  555.     ret_bits->len = (hash_iter * hash_size);
  556.     if(ret_bits->data == NULL) {
  557. PORT_Free(ret_bits);
  558. return NULL;
  559.     }
  560.     /* allocate intermediate hash buffer.  8 is for the 8 bytes of
  561.      * data which are added based on iteration number 
  562.      */
  563.     if ((unsigned int)hash_size > pbe_param->salt.len) {
  564. state_len = hash_size;
  565.     } else {
  566. state_len = pbe_param->salt.len;
  567.     }
  568.     state = (unsigned char *)PORT_ZAlloc(state_len);
  569.     if(state == NULL) {
  570. rv = SECFailure;
  571. goto loser;
  572.     }
  573.     if(pbe_param->salt.len > 0) {
  574. PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len);
  575.     }
  576.     cx = HMAC_Create(sec_pkcs5_hash_algorithm(pbe_param->algorithm),
  577.      init_hash->data, init_hash->len);
  578.     if (cx == NULL) {
  579. rv = SECFailure;
  580. goto loser;
  581.     }
  582.     for(i = 0; i < hash_iter; i++) { 
  583. /* generate output bits */
  584. HMAC_Begin(cx);
  585. HMAC_Update(cx, state, state_len);
  586. HMAC_Update(cx, pbe_param->salt.data, pbe_param->salt.len);
  587. rv = HMAC_Finish(cx, ret_bits->data + (i * hash_size),
  588.  &dig_len, hash_size);
  589. if (rv != SECSuccess)
  590.     goto loser;
  591. PORT_Assert((unsigned int)hash_size == dig_len);
  592. /* generate new state */
  593. HMAC_Begin(cx);
  594. HMAC_Update(cx, state, state_len);
  595. rv = HMAC_Finish(cx, state, &state_len, state_len);
  596. if (rv != SECSuccess)
  597.     goto loser;
  598. PORT_Assert(state_len == dig_len);
  599.     }
  600. loser:
  601.     if (state != NULL)
  602. PORT_ZFree(state, state_len);
  603.     HMAC_Destroy(cx);
  604.     if(rv != SECSuccess) {
  605. SECITEM_ZfreeItem(ret_bits, PR_TRUE);
  606. ret_bits = NULL;
  607.     }
  608.     return ret_bits;
  609. }
  610. /* generate bits for the key and iv determination.  if enough bits
  611.  * are not generated using PKCS 5, then we need to generate more bits
  612.  * based on the extension proposed in PKCS 12
  613.  */
  614. static SECItem *
  615. sec_pkcs5_generate_bits(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, 
  616. PRBool faulty3DES)
  617. {
  618.     SECItem * hash  = NULL;
  619.     SECItem * newHash  = NULL;
  620.     int       bits_needed;
  621.     int       bits_available;
  622.     
  623.     bits_needed = sec_pkcs5_bits_needed(pbe_param);
  624.     bits_available = sec_pkcs5_hash_bits_generated(pbe_param);
  625.     if((bits_needed == -1) || (bits_available == -1)) {
  626. return NULL;
  627.     }
  628.     hash = sec_pkcs5_compute_hash(pbe_param, pwitem, faulty3DES);
  629.     if(hash == NULL) {
  630. return NULL;
  631.     }
  632.     if(bits_needed <= bits_available) {
  633. return hash;
  634.     } 
  635.     newHash = sec_pkcs5_bit_generator(pbe_param, hash, bits_needed);
  636.     if (hash != newHash)
  637. SECITEM_FreeItem(hash, PR_TRUE);
  638.     return newHash;
  639. }
  640. /* compute the IV as per PKCS 5
  641.  */
  642. static SECItem *
  643. sec_pkcs5_compute_iv(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem,
  644.      PRBool faulty3DES)
  645. {
  646.     SECItem *hash = NULL, *iv = NULL;
  647.     if((pbe_param == NULL) || (pwitem == NULL)) {
  648. return NULL;
  649.     }
  650.     /* generate iv */
  651.     iv = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  652.     if(!iv) {
  653. return NULL;
  654.     }
  655.     iv->len = sec_pkcs5_iv_length(pbe_param->algorithm);
  656.     if(iv->len == -1) {
  657. PORT_Free(iv);
  658. return NULL;
  659.     }
  660.     iv->data = (unsigned char *)PORT_ZAlloc(iv->len);
  661.     if(iv->data == NULL) {
  662. PORT_Free(iv);
  663. return NULL;
  664.     }
  665.     if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(pbe_param->algorithm)) {
  666. SECOidTag hashAlg;
  667. PBEBitGenContext *ctxt;
  668. hashAlg = sec_pkcs5_hash_algorithm(pbe_param->algorithm);
  669. ctxt = PBE_CreateContext(hashAlg, pbeBitGenCipherIV,
  670.  pwitem, &pbe_param->salt,
  671.  iv->len * 8, pbe_param->iter);
  672. if(!ctxt) {
  673.     SECITEM_FreeItem(iv, PR_TRUE);
  674.     return NULL;
  675. }
  676. hash = PBE_GenerateBits(ctxt);
  677. PBE_DestroyContext(ctxt);
  678.     } else {
  679. hash = sec_pkcs5_generate_bits(pbe_param, pwitem, faulty3DES);
  680.     }
  681.     if(!hash) {
  682. SECITEM_FreeItem(iv, PR_TRUE);
  683. return NULL;
  684.     }
  685.     PORT_Memcpy(iv->data, (hash->data+(hash->len - iv->len)), iv->len);
  686.     SECITEM_FreeItem(hash, PR_TRUE);
  687.     return iv;
  688. }
  689. /* generate key as per PKCS 5
  690.  */
  691. static SECItem *
  692. sec_pkcs5_compute_key(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem,
  693.       PRBool faulty3DES)
  694. {
  695.     SECItem *hash = NULL, *key = NULL;
  696.     if((pbe_param == NULL) || (pwitem == NULL)) {
  697. return NULL;
  698.     }
  699.     key = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  700.     if(!key) {
  701. return NULL;
  702.     }
  703.     key->len = sec_pkcs5_key_length(pbe_param->algorithm);
  704.     if(key->len == -1) {
  705. PORT_Free(key);
  706. return NULL;
  707.     }
  708.     key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
  709.      key->len);
  710.     if(!key->data) {
  711. PORT_Free(key);
  712. return NULL;
  713.     }
  714.     if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(pbe_param->algorithm)) {
  715. SECOidTag hashAlg;
  716. PBEBitGenContext *ctxt;
  717. hashAlg = sec_pkcs5_hash_algorithm(pbe_param->algorithm);
  718. ctxt = PBE_CreateContext(hashAlg, pbeBitGenCipherKey,
  719.  pwitem, &pbe_param->salt,
  720.  key->len * 8, pbe_param->iter);
  721. if(!ctxt) {
  722.     SECITEM_FreeItem(key, PR_TRUE);
  723.     return NULL;
  724. }
  725. hash = PBE_GenerateBits(ctxt);
  726. PBE_DestroyContext(ctxt);
  727.     } else {
  728. hash = sec_pkcs5_generate_bits(pbe_param, pwitem, faulty3DES);
  729.     }
  730.    
  731.     if(!hash) {
  732. SECITEM_FreeItem(key, PR_TRUE);
  733. return NULL;
  734.     }
  735.     if(pbe_param->algorithm ==
  736.    SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC) {
  737. PORT_Memcpy(key->data, hash->data, (key->len * 2) / 3);
  738. PORT_Memcpy(&(key->data[(key->len  * 2) / 3]), key->data,
  739.     key->len / 3);
  740.     } else {
  741. PORT_Memcpy(key->data, hash->data, key->len);
  742.     }
  743.     SECITEM_FreeItem(hash, PR_TRUE);
  744.     return key;
  745. }
  746. /* decode the algid and generate a PKCS 5 parameter from it
  747.  */
  748. static SEC_PKCS5PBEParameter *
  749. sec_pkcs5_convert_algid(SECAlgorithmID *algid)
  750. {
  751.     PRArenaPool *poolp;
  752.     SEC_PKCS5PBEParameter *pbe_param = NULL;
  753.     SECOidTag algorithm;
  754.     SECStatus rv = SECFailure;
  755.     if(algid == NULL)
  756. return NULL;
  757.     algorithm = SECOID_GetAlgorithmTag(algid);
  758.    
  759.     if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN)
  760. return NULL;
  761.     poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  762.     if(poolp == NULL)
  763. return NULL;
  764.     /* allocate memory for the parameter */
  765.     pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp, 
  766. sizeof(SEC_PKCS5PBEParameter));
  767.     /* decode parameter */
  768.     if(pbe_param && !sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
  769. pbe_param->poolp = poolp;
  770. rv = SEC_ASN1DecodeItem(poolp, pbe_param, 
  771.     SEC_PKCS5PBEParameterTemplate, &algid->parameters);
  772. if(rv != SECSuccess) {
  773.     goto loser;
  774. }
  775. pbe_param->algorithm = algorithm;
  776. pbe_param->iter = DER_GetInteger(&pbe_param->iteration);
  777.     } else if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
  778. pbe_param->algorithm = algorithm;
  779. pbe_param->poolp = poolp;
  780. rv = SEC_ASN1DecodeItem(poolp, pbe_param, SEC_V2PKCS12PBEParameterTemplate,
  781. &algid->parameters);
  782. if(rv != SECSuccess) {
  783.     goto loser;
  784. }
  785. pbe_param->iter = DER_GetInteger(&pbe_param->iteration);
  786.     }
  787. loser:
  788.     if((pbe_param == NULL) || (rv != SECSuccess)) {
  789. PORT_FreeArena(poolp, PR_TRUE);
  790. pbe_param = NULL;
  791.     }
  792.     return pbe_param;
  793. }
  794. /* destroy a pbe parameter.  it assumes that the parameter was 
  795.  * generated using the appropriate create function and therefor
  796.  * contains an arena pool.
  797.  */
  798. static void 
  799. sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param)
  800. {
  801.     if(pbe_param != NULL)
  802. PORT_FreeArena(pbe_param->poolp, PR_TRUE);
  803. }
  804. /* crypto routines */
  805. /* function pointer template for crypto functions */
  806. typedef SECItem *(* pkcs5_crypto_func)(SECItem *key, SECItem *iv, 
  807.  SECItem *src, PRBool op1, PRBool op2);
  808. /* map PBE algorithm to crypto algorithm */
  809. static SECOidTag 
  810. sec_pkcs5_encryption_algorithm(SECOidTag algorithm)
  811. {
  812.     switch(algorithm)
  813.     {
  814. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
  815. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
  816. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
  817.     return SEC_OID_DES_EDE3_CBC;
  818. case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
  819. case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
  820. case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
  821.     return SEC_OID_DES_CBC;
  822. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  823. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  824. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  825. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  826.     return SEC_OID_RC2_CBC;
  827. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
  828. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
  829. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
  830. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
  831.     return SEC_OID_RC4;
  832. default:
  833.     break;
  834.     }
  835.     return SEC_OID_UNKNOWN;
  836. }
  837. /* perform DES encryption and decryption.  these routines are called
  838.  * by SEC_PKCS5CipherData.  In the case of an error, NULL is returned.
  839.  */
  840. static SECItem *
  841. sec_pkcs5_des(SECItem *key, 
  842.       SECItem *iv, 
  843.       SECItem *src,
  844.       PRBool triple_des, 
  845.       PRBool encrypt)
  846. {
  847.     SECItem *dest;
  848.     SECItem *dup_src;
  849.     SECStatus rv = SECFailure;
  850.     int pad;
  851.     if((src == NULL) || (key == NULL) || (iv == NULL))
  852. return NULL;
  853.     dup_src = SECITEM_DupItem(src);
  854.     if(dup_src == NULL) {
  855. return NULL;
  856.     }
  857.     if(encrypt != PR_FALSE) {
  858. void *dummy;
  859. dummy = DES_PadBuffer(NULL, dup_src->data, 
  860.     dup_src->len, &dup_src->len);
  861. if(dummy == NULL) {
  862.     SECITEM_FreeItem(dup_src, PR_TRUE);
  863.     return NULL;
  864. }
  865. dup_src->data = (unsigned char*)dummy;
  866.     }
  867.     dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  868.     if(dest != NULL) {
  869. /* allocate with over flow */
  870. dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
  871. if(dest->data != NULL) {
  872.     DESContext *ctxt;
  873.     ctxt = DES_CreateContext(key->data, iv->data, 
  874. (triple_des ? NSS_DES_EDE3_CBC : NSS_DES_CBC), 
  875. encrypt);
  876.     if(ctxt != NULL) {
  877. rv = ((encrypt != PR_TRUE) ? DES_Decrypt : DES_Encrypt)(
  878. ctxt, dest->data, &dest->len,
  879. dup_src->len + 64, dup_src->data, dup_src->len);
  880. /* remove padding -- assumes 64 bit blocks */
  881. if((encrypt == PR_FALSE) && (rv == SECSuccess)) {
  882.     pad = dest->data[dest->len-1];
  883.     if((pad > 0) && (pad <= 8)) {
  884. if(dest->data[dest->len-pad] != pad) {
  885.     rv = SECFailure;
  886.     PORT_SetError(SEC_ERROR_BAD_PASSWORD);
  887. } else {
  888.     dest->len -= pad;
  889. }
  890.     } else {
  891. rv = SECFailure;
  892. PORT_SetError(SEC_ERROR_BAD_PASSWORD);
  893.     }
  894. }
  895. DES_DestroyContext(ctxt, PR_TRUE);
  896.     }
  897. }
  898.     }
  899.     if(rv == SECFailure) {
  900. if(dest != NULL) {
  901.     SECITEM_FreeItem(dest, PR_TRUE);
  902. }
  903. dest = NULL;
  904.     }
  905.     if(dup_src != NULL) {
  906. SECITEM_FreeItem(dup_src, PR_TRUE);
  907.     }
  908.     return dest;
  909. }
  910. /* perform rc2 encryption/decryption if an error occurs, NULL is returned
  911.  */
  912. static SECItem *
  913. sec_pkcs5_rc2(SECItem *key, 
  914.       SECItem *iv, 
  915.       SECItem *src,
  916.       PRBool cbc_mode, 
  917.       PRBool encrypt)
  918. {
  919.     SECItem *dest;
  920.     SECItem *dup_src;
  921.     SECStatus rv = SECFailure;
  922.     int pad;
  923.     if((src == NULL) || (key == NULL) || (iv == NULL)) {
  924. return NULL;
  925.     }
  926.     dup_src = SECITEM_DupItem(src);
  927.     if(dup_src == NULL) {
  928. return NULL;
  929.     }
  930.     if(encrypt != PR_FALSE) {
  931. void *dummy;
  932. dummy = DES_PadBuffer(NULL, dup_src->data, 
  933.       dup_src->len, &dup_src->len);
  934. if(dummy == NULL) {
  935.     SECITEM_FreeItem(dup_src, PR_TRUE);
  936.     return NULL;
  937. }
  938. dup_src->data = (unsigned char*)dummy;
  939.     }
  940.     dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  941.     if(dest != NULL) {
  942. dest->data = (unsigned char *)PORT_ZAlloc(dup_src->len + 64);
  943. if(dest->data != NULL) {
  944.     RC2Context *ctxt;
  945.     ctxt = RC2_CreateContext(key->data, key->len, iv->data, 
  946. ((cbc_mode != PR_TRUE) ? NSS_RC2 : NSS_RC2_CBC), 
  947. key->len);
  948.     if(ctxt != NULL) {
  949. rv = ((encrypt != PR_TRUE) ? RC2_Decrypt : RC2_Encrypt)(
  950. ctxt, dest->data, &dest->len,
  951. dup_src->len + 64, dup_src->data, dup_src->len);
  952. /* assumes 8 byte blocks  -- remove padding */
  953. if((rv == SECSuccess) && (encrypt != PR_TRUE) && 
  954. (cbc_mode == PR_TRUE)) {
  955.     pad = dest->data[dest->len-1];
  956.     if((pad > 0) && (pad <= 8)) {
  957. if(dest->data[dest->len-pad] != pad) {
  958.     PORT_SetError(SEC_ERROR_BAD_PASSWORD);
  959.     rv = SECFailure;
  960. } else {
  961.     dest->len -= pad;
  962. }
  963.     } else {
  964. PORT_SetError(SEC_ERROR_BAD_PASSWORD);
  965. rv = SECFailure;
  966.     }
  967. }
  968.     }
  969. }
  970.     }
  971.     if((rv != SECSuccess) && (dest != NULL)) {
  972. SECITEM_FreeItem(dest, PR_TRUE);
  973. dest = NULL;
  974.     }
  975.     if(dup_src != NULL) {
  976. SECITEM_FreeItem(dup_src, PR_TRUE);
  977.     }
  978.     return dest;
  979. }
  980. /* perform rc4 encryption and decryption */
  981. static SECItem *
  982. sec_pkcs5_rc4(SECItem *key, 
  983.       SECItem *iv, 
  984.       SECItem *src, 
  985.       PRBool dummy_op,
  986.       PRBool encrypt)
  987. {
  988.     SECItem *dest;
  989.     SECStatus rv = SECFailure;
  990.     if((src == NULL) || (key == NULL) || (iv == NULL)) {
  991. return NULL;
  992.     }
  993.     dest = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  994.     if(dest != NULL) {
  995. dest->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) *
  996.     (src->len + 64));
  997. if(dest->data != NULL) {
  998.     RC4Context *ctxt;
  999.     ctxt = RC4_CreateContext(key->data, key->len);
  1000.     if(ctxt) { 
  1001. rv = ((encrypt != PR_FALSE) ? RC4_Decrypt : RC4_Encrypt)(
  1002. ctxt, dest->data, &dest->len,
  1003. src->len + 64, src->data, src->len);
  1004. RC4_DestroyContext(ctxt, PR_TRUE);
  1005.     }
  1006. }
  1007.     }
  1008.     if((rv != SECSuccess) && (dest)) {
  1009. SECITEM_FreeItem(dest, PR_TRUE);
  1010. dest = NULL;
  1011.     }
  1012.     return dest;
  1013. }
  1014. /* performs the cipher operation on the src and returns the result.
  1015.  * if an error occurs, NULL is returned. 
  1016.  *
  1017.  * a null length password is allowed.  this corresponds to encrypting
  1018.  * the data with ust the salt.
  1019.  */
  1020. /* change this to use PKCS 11? */
  1021. SECItem *
  1022. SEC_PKCS5CipherData(SECAlgorithmID *algid, 
  1023.     SECItem *pwitem,
  1024.     SECItem *src, 
  1025.     PRBool encrypt, PRBool *update)
  1026. {
  1027.     SEC_PKCS5PBEParameter *pbe_param;
  1028.     SECOidTag enc_alg;
  1029.     SECItem *key = NULL, *iv = NULL;
  1030.     SECItem *dest = NULL;
  1031.     int iv_len;
  1032.     if (update) { 
  1033.         *update = PR_FALSE;
  1034.     }
  1035.     if((algid == NULL) || (pwitem == NULL) || (src == NULL)) {
  1036. return NULL;
  1037.     }
  1038.     /* convert algid to pbe parameter */
  1039.     pbe_param = sec_pkcs5_convert_algid(algid);
  1040.     if(pbe_param == NULL) {
  1041. return NULL;
  1042.     }
  1043.     /* get algorithm, key, and iv */
  1044.     enc_alg = sec_pkcs5_encryption_algorithm(pbe_param->algorithm);
  1045.     key = sec_pkcs5_compute_key(pbe_param, pwitem, PR_FALSE);
  1046.     if(key != NULL) {
  1047. iv_len = sec_pkcs5_iv_length(pbe_param->algorithm);
  1048.      iv = sec_pkcs5_compute_iv(pbe_param, pwitem, PR_FALSE);
  1049. if((iv != NULL) || (iv_len == 0)) {
  1050.     /*perform encryption / decryption */
  1051.     PRBool op1 = PR_TRUE;
  1052.     pkcs5_crypto_func cryptof;
  1053.     switch(enc_alg) {
  1054. case SEC_OID_DES_EDE3_CBC:
  1055.     cryptof = sec_pkcs5_des;
  1056.     break;
  1057. case SEC_OID_DES_CBC:
  1058.     cryptof = sec_pkcs5_des;
  1059.     op1 = PR_FALSE;
  1060.     break;
  1061. case SEC_OID_RC2_CBC:
  1062.     cryptof = sec_pkcs5_rc2;
  1063.     break;
  1064. case SEC_OID_RC4:
  1065.     cryptof = sec_pkcs5_rc4;
  1066.     break;
  1067. default:
  1068.     cryptof = NULL;
  1069.     break;
  1070.     }
  1071.     if(cryptof) {
  1072. dest = (*cryptof)(key, iv, src, op1, encrypt);
  1073. /* 
  1074.  * it's possible for some keys and keydb's to claim to
  1075.  * be triple des when they're really des. In this case
  1076.  * we simply try des. If des works we set the update flag
  1077.  * so the key db knows it needs to update all it's entries.
  1078.  *  The case can only happen on decrypted of a 
  1079.  *  SEC_OID_DES_EDE3_CBD.
  1080.  */
  1081. if ((dest == NULL) && (encrypt == PR_FALSE) && 
  1082. (enc_alg == SEC_OID_DES_EDE3_CBC)) {
  1083.     dest = (*cryptof)(key, iv, src, PR_FALSE, encrypt);
  1084.     if (update && (dest != NULL)) *update = PR_TRUE;
  1085. }
  1086.     }
  1087. }
  1088.     }
  1089.     sec_pkcs5_destroy_pbe_param(pbe_param);
  1090.     if(key != NULL) {
  1091. SECITEM_ZfreeItem(key, PR_TRUE);
  1092.     }
  1093.     if(iv != NULL) {
  1094. SECITEM_ZfreeItem(iv, PR_TRUE);
  1095.     }
  1096.     return dest;
  1097. }
  1098. /* creates a algorithm ID containing the PBE algorithm and appropriate
  1099.  * parameters.  the required parameter is the algorithm.  if salt is
  1100.  * not specified, it is generated randomly.  if IV is specified, it overrides
  1101.  * the PKCS 5 generation of the IV.  
  1102.  *
  1103.  * the returned SECAlgorithmID should be destroyed using 
  1104.  * SECOID_DestroyAlgorithmID
  1105.  */
  1106. SECAlgorithmID *
  1107. SEC_PKCS5CreateAlgorithmID(SECOidTag algorithm, 
  1108.    SECItem *salt, 
  1109.    int iteration)
  1110. {
  1111.     PRArenaPool *poolp = NULL;
  1112.     SECAlgorithmID *algid, *ret_algid;
  1113.     SECItem der_param;
  1114.     SECStatus rv = SECFailure;
  1115.     SEC_PKCS5PBEParameter *pbe_param;
  1116.     if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN)
  1117. return NULL;
  1118.     if(iteration <= 0) {
  1119. return NULL;
  1120.     }
  1121.     der_param.data = NULL;
  1122.     der_param.len = 0;
  1123.     /* generate the parameter */
  1124.     pbe_param = sec_pkcs5_create_pbe_parameter(algorithm, salt, iteration);
  1125.     if(!pbe_param) {
  1126. return NULL;
  1127.     }
  1128.     poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  1129.     if(!poolp) {
  1130. sec_pkcs5_destroy_pbe_param(pbe_param);
  1131. return NULL;
  1132.     }
  1133.     /* generate the algorithm id */
  1134.     algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID));
  1135.     if(algid != NULL) {
  1136. void *dummy;
  1137. if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) {
  1138.     dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
  1139. SEC_PKCS5PBEParameterTemplate);
  1140. } else {
  1141.     dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param,
  1142.      SEC_V2PKCS12PBEParameterTemplate);
  1143. }
  1144. if(dummy) {
  1145.     rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param);
  1146. }
  1147.     }
  1148.     ret_algid = NULL;
  1149.     if(algid != NULL) {
  1150. ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID));
  1151. if(ret_algid != NULL) {
  1152.     rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid);
  1153.     if(rv != SECSuccess) {
  1154. SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE);
  1155. ret_algid = NULL;
  1156.     }
  1157. }
  1158.     }
  1159.     if(poolp != NULL) {
  1160. PORT_FreeArena(poolp, PR_TRUE);
  1161. algid = NULL;
  1162.     }
  1163.     sec_pkcs5_destroy_pbe_param(pbe_param);
  1164.     return ret_algid;
  1165. }
  1166. /* wrapper for converting the algid to a pbe parameter. 
  1167.  */
  1168. SEC_PKCS5PBEParameter *
  1169. SEC_PKCS5GetPBEParameter(SECAlgorithmID *algid)
  1170. {
  1171.     if(algid) {
  1172. return sec_pkcs5_convert_algid(algid);
  1173.     }
  1174.     return NULL;
  1175. }
  1176. /* destroy a pbe parameter */
  1177. void
  1178. SEC_PKCS5DestroyPBEParameter(SEC_PKCS5PBEParameter *pbe_param)
  1179. {
  1180.     sec_pkcs5_destroy_pbe_param(pbe_param);
  1181. }
  1182. /* return the initialization vector either the preset one if it 
  1183.  * exists or generated based on pkcs 5.
  1184.  *
  1185.  * a null length password is allowed...but not a null password
  1186.  * secitem.
  1187.  */
  1188. SECItem *
  1189. SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
  1190. {
  1191.     SECItem *iv;
  1192.     SEC_PKCS5PBEParameter *pbe_param;
  1193.     if((algid == NULL) || (pwitem == NULL)) {
  1194. return NULL;
  1195.     }
  1196.     pbe_param = sec_pkcs5_convert_algid(algid);
  1197.     if(!pbe_param) {
  1198. return NULL;
  1199.     }
  1200.     iv = sec_pkcs5_compute_iv(pbe_param, pwitem, faulty3DES);
  1201.     sec_pkcs5_destroy_pbe_param(pbe_param);
  1202.     return iv;
  1203. }
  1204. /* generate the key 
  1205.  * a 0 length password is allowed.  corresponds to a key generated
  1206.  * from just the salt.
  1207.  */
  1208. SECItem *
  1209. SEC_PKCS5GetKey(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES)
  1210. {
  1211.     SECItem *key;
  1212.     SEC_PKCS5PBEParameter *pbe_param;
  1213.     if((algid == NULL) || (pwitem == NULL)) {
  1214. return NULL;
  1215.     }
  1216.     pbe_param = sec_pkcs5_convert_algid(algid);
  1217.     if(pbe_param == NULL) {
  1218. return NULL;
  1219.     }
  1220.     key = sec_pkcs5_compute_key(pbe_param, pwitem, faulty3DES);
  1221.     sec_pkcs5_destroy_pbe_param(pbe_param);
  1222.     return key;
  1223. }
  1224. /* retrieve the salt */
  1225. SECItem *
  1226. SEC_PKCS5GetSalt(SECAlgorithmID *algid)
  1227. {
  1228.     SECItem *salt;
  1229.     SEC_PKCS5PBEParameter *pbe_param;
  1230.     if(algid == NULL)
  1231. return NULL;
  1232.     pbe_param = sec_pkcs5_convert_algid(algid);
  1233.     if(pbe_param == NULL)
  1234. return NULL;
  1235.     if(pbe_param->salt.data) {
  1236. salt = SECITEM_DupItem(&pbe_param->salt);
  1237.     } else {
  1238. salt = NULL;
  1239.     }
  1240.     sec_pkcs5_destroy_pbe_param(pbe_param);
  1241.     return salt;
  1242. }
  1243. /* check to see if an oid is a pbe algorithm
  1244.  */ 
  1245. PRBool 
  1246. SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid)
  1247. {
  1248.     SECOidTag algorithm;
  1249.     algorithm = SECOID_GetAlgorithmTag(algid);
  1250.     if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN) {
  1251. return PR_FALSE;
  1252.     }
  1253.     return PR_TRUE;
  1254. }
  1255. int 
  1256. SEC_PKCS5GetKeyLength(SECAlgorithmID *algid)
  1257. {
  1258.     SEC_PKCS5PBEParameter *pbe_param;
  1259.     int keyLen = -1;
  1260.     if(algid == NULL)
  1261. return -1;
  1262.     pbe_param = sec_pkcs5_convert_algid(algid);
  1263.     if(pbe_param == NULL)
  1264. return -1;
  1265.     keyLen = sec_pkcs5_key_length(pbe_param->algorithm);
  1266.     sec_pkcs5_destroy_pbe_param(pbe_param);
  1267.     return keyLen;
  1268. }
  1269. /* maps crypto algorithm from PBE algorithm.
  1270.  */
  1271. SECOidTag 
  1272. SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid)
  1273. {
  1274.     SEC_PKCS5PBEParameter *pbe_param;
  1275.     if(algid == NULL)
  1276. return SEC_OID_UNKNOWN;
  1277.     pbe_param = sec_pkcs5_convert_algid(algid);
  1278.     if(pbe_param == NULL)
  1279. return SEC_OID_UNKNOWN;
  1280.     switch(pbe_param->algorithm)
  1281.     {
  1282. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
  1283. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
  1284. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
  1285.     return SEC_OID_DES_EDE3_CBC;
  1286. case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
  1287. case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
  1288. case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
  1289.     return SEC_OID_DES_CBC;
  1290. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  1291. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  1292. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
  1293. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
  1294.     return SEC_OID_RC2_CBC;
  1295. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
  1296. case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
  1297. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
  1298. case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
  1299.     return SEC_OID_RC4;
  1300. default:
  1301.     break;
  1302.     }
  1303.     sec_pkcs5_destroy_pbe_param(pbe_param);
  1304.     return SEC_OID_UNKNOWN;
  1305. }
  1306. /* maps PBE algorithm from crypto algorithm, assumes SHA1 hashing.
  1307.  */
  1308. SECOidTag 
  1309. SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen)
  1310. {
  1311.     switch(algTag)
  1312.     {
  1313. case SEC_OID_DES_EDE3_CBC:
  1314.     switch(keyLen) {
  1315. case 168:
  1316. case 192:
  1317.     return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
  1318. case 128:
  1319. case 92:
  1320.     return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
  1321. default:
  1322.     break;
  1323.     }
  1324.     break;
  1325. case SEC_OID_DES_CBC:
  1326.     return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
  1327. case SEC_OID_RC2_CBC:
  1328.     switch(keyLen) {
  1329. case 40:
  1330.     return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
  1331. case 128:
  1332.     return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
  1333. default:
  1334.     break;
  1335.     }
  1336.     break;
  1337. case SEC_OID_RC4:
  1338.     switch(keyLen) {
  1339. case 40:
  1340.     return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
  1341. case 128:
  1342.     return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
  1343. default:
  1344.     break;
  1345.     }
  1346.     break;
  1347. default:
  1348.     break;
  1349.     }
  1350.     return SEC_OID_UNKNOWN;
  1351. }
  1352. /* zero length password and salts are allowed.  however, the items
  1353.  * containing the salt and password must be non-null.
  1354.  */
  1355. PBEBitGenContext *
  1356. PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
  1357.   SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
  1358.   unsigned int iterations)
  1359. {
  1360.     PRArenaPool *arena = NULL;
  1361.     PBEBitGenContext *pbeCtxt = NULL;
  1362.     HASH_HashType pbeHash;
  1363.     int vbytes, ubytes;
  1364.     
  1365.     unsigned int c;
  1366.     if(!pwitem || !salt) {
  1367. return NULL;
  1368.     }
  1369.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1370.     if(!arena) {
  1371. return NULL;
  1372.     }
  1373.     pbeCtxt = (PBEBitGenContext*)PORT_ArenaZAlloc(arena, sizeof(PBEBitGenContext));
  1374.     if(!pbeCtxt) {
  1375. goto loser;
  1376.     }
  1377.     switch(hashAlgorithm) {
  1378. case SEC_OID_MD2:
  1379.     pbeHash = HASH_AlgMD2;
  1380.     break;
  1381. case SEC_OID_MD5:
  1382.     pbeHash = HASH_AlgMD5;
  1383.     break;
  1384. case SEC_OID_SHA1:
  1385.     pbeHash = HASH_AlgSHA1;
  1386.     break;
  1387. default:
  1388.     goto loser;
  1389.     }
  1390.     pbeCtxt->hashObject = &SECRawHashObjects[pbeHash]; 
  1391.     PORT_Memcpy(&pbeCtxt->pbeParams, &pbeHashAlgorithmParams[pbeHash], 
  1392.      sizeof(pbeBitGenParameters));
  1393.     PORT_Assert(pbeCtxt->pbeParams.hashAlgorithm == hashAlgorithm);
  1394.     vbytes = pbeCtxt->pbeParams.v / 8;
  1395.     ubytes = pbeCtxt->pbeParams.u / 8;
  1396.     c = (bitsNeeded / pbeCtxt->pbeParams.u);
  1397.     c += ((bitsNeeded - (pbeCtxt->pbeParams.u * c)) > 0) ? 1 : 0;
  1398.     pbeCtxt->c = c;
  1399.     pbeCtxt->n = bitsNeeded;
  1400.     pbeCtxt->iterations = iterations;
  1401.     /* allocate buffers */
  1402.     pbeCtxt->D.len = vbytes;
  1403.     pbeCtxt->S.len = (((salt->len * 8) / pbeCtxt->pbeParams.v) + 
  1404.            ((((salt->len * 8) % pbeCtxt->pbeParams.v) > 0) ? 1 : 0)) *
  1405.            vbytes;
  1406.     pbeCtxt->P.len = (((pwitem->len * 8) / pbeCtxt->pbeParams.v) + 
  1407.            ((((pwitem->len * 8) % pbeCtxt->pbeParams.v) > 0) ? 1 : 0)) *
  1408.       vbytes;
  1409.     pbeCtxt->I.len = pbeCtxt->S.len + pbeCtxt->P.len;
  1410.     pbeCtxt->A.len = c * ubytes;
  1411.     pbeCtxt->B.len = pbeCtxt->D.len;
  1412.     pbeCtxt->D.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->D.len);
  1413.     if(pbeCtxt->S.len) {
  1414. pbeCtxt->S.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->S.len);
  1415.     }
  1416.     if(pbeCtxt->P.len) {
  1417. pbeCtxt->P.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->P.len);
  1418.     }
  1419.     if(pbeCtxt->I.len) {
  1420. pbeCtxt->I.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->I.len);
  1421.     }
  1422.     pbeCtxt->A.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->A.len);
  1423.     pbeCtxt->B.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->B.len);
  1424.     if(!pbeCtxt->D.data || !pbeCtxt->A.data || !pbeCtxt->B.data ||
  1425.        (!pbeCtxt->S.data && pbeCtxt->S.len) || 
  1426.        (!pbeCtxt->P.data && pbeCtxt->P.len) ||
  1427.        (!pbeCtxt->I.data && pbeCtxt->I.len)) {
  1428. goto loser;
  1429.     }
  1430.     PORT_Memset(pbeCtxt->D.data, (char)bitGenPurpose, pbeCtxt->D.len);
  1431.     if(pbeCtxt->P.len) {
  1432. unsigned int z = 0;
  1433. while(z < pbeCtxt->P.len) {
  1434.     PORT_Memcpy(&(pbeCtxt->P.data[z]), pwitem->data,  
  1435.      ((z + pwitem->len > pbeCtxt->P.len) ? (pbeCtxt->P.len - z) :
  1436.            (pwitem->len)));
  1437.     z += pwitem->len;
  1438. }
  1439.     } 
  1440.     if(pbeCtxt->S.len) {
  1441. unsigned int z = 0;
  1442. while(z < pbeCtxt->S.len) {
  1443.     PORT_Memcpy(&(pbeCtxt->S.data[z]), salt->data,  
  1444.      ((z + salt->len > pbeCtxt->S.len) ? (pbeCtxt->S.len - z) :
  1445.          (salt->len)));
  1446.     z += salt->len;
  1447. }
  1448.     } 
  1449.     if(pbeCtxt->I.len) {
  1450. if(pbeCtxt->S.len) {
  1451.     PORT_Memcpy(pbeCtxt->I.data, pbeCtxt->S.data, pbeCtxt->S.len);
  1452. }
  1453. if(pbeCtxt->P.len) {
  1454.     PORT_Memcpy(&(pbeCtxt->I.data[pbeCtxt->S.len]), pbeCtxt->P.data, 
  1455.      pbeCtxt->P.len);
  1456. }
  1457.     }
  1458.     pbeCtxt->arena = arena;
  1459.     return pbeCtxt;
  1460. loser:
  1461.     if(arena) {
  1462. PORT_FreeArena(arena, PR_TRUE);
  1463.     }
  1464.     return NULL;
  1465. }
  1466. SECItem *
  1467. PBE_GenerateBits(PBEBitGenContext *pbeCtxt)
  1468. {
  1469.     unsigned int i;
  1470.     SECItem *A, *D, *I, *B, *S, *P;
  1471.     unsigned int u, v, c, z, hashLen, n, iter;
  1472.     unsigned int vbyte, ubyte;
  1473.     unsigned char *iterBuf;
  1474.     void *hash = NULL;
  1475.     if(!pbeCtxt) {
  1476. return NULL;
  1477.     }
  1478.     A = &pbeCtxt->A;
  1479.     B = &pbeCtxt->B;
  1480.     I = &pbeCtxt->I;
  1481.     D = &pbeCtxt->D;
  1482.     S = &pbeCtxt->S;
  1483.     P = &pbeCtxt->P;
  1484.     u = pbeCtxt->pbeParams.u;
  1485.     v = pbeCtxt->pbeParams.v;
  1486.     vbyte = v / 8;
  1487.     ubyte = u / 8;
  1488.     c = pbeCtxt->c;
  1489.     n = pbeCtxt->n;
  1490.     z = 0;
  1491.     iterBuf = (unsigned char*)PORT_Alloc(ubyte);
  1492.     if(!iterBuf) {
  1493. goto loser;
  1494.     }
  1495.     for(i = 1; i <= c; i++) {
  1496. unsigned int Bidx;
  1497. unsigned int k, j;
  1498. for(iter = 1; iter <= pbeCtxt->iterations; iter++) {
  1499.     hash = pbeCtxt->hashObject->create();
  1500.     if(!hash) {
  1501. goto loser;
  1502.     }
  1503.     pbeCtxt->hashObject->begin(hash);
  1504.     if(iter == 1) {
  1505. pbeCtxt->hashObject->update(hash, D->data, D->len);
  1506. pbeCtxt->hashObject->update(hash, I->data, I->len); 
  1507.     } else {
  1508. pbeCtxt->hashObject->update(hash, iterBuf, hashLen);
  1509.     }
  1510.     pbeCtxt->hashObject->end(hash, iterBuf, &hashLen, (ubyte));
  1511.     pbeCtxt->hashObject->destroy(hash, PR_TRUE);
  1512.     if(hashLen != (ubyte)) {
  1513. goto loser;
  1514.     }
  1515. }
  1516. PORT_Memcpy(&(A->data[z]), iterBuf, (ubyte));
  1517. Bidx = 0;
  1518. while(Bidx < B->len) {
  1519.     PORT_Memcpy(&(B->data[Bidx]), &(A->data[z]), 
  1520. (((Bidx + (ubyte)) > B->len) ? (B->len - Bidx) : 
  1521.        (ubyte)));
  1522.     Bidx += (ubyte);
  1523. }
  1524. k = (S->len / (vbyte)) + (P->len / (vbyte));
  1525. for(j = 0; j < k; j++) {
  1526.     unsigned int byteIdx = (vbyte);
  1527.     unsigned int q, carryBit = 0;
  1528.     while(byteIdx > 0) {
  1529. q = (unsigned int)I->data[(j * (vbyte)) + byteIdx - 1];
  1530. q += (unsigned int)B->data[byteIdx - 1];
  1531. q += carryBit;
  1532. if(byteIdx == (vbyte)) {
  1533.     q += 1;
  1534. }
  1535. carryBit = ((q > 255) ? 1 : 0);
  1536. I->data[(j * (vbyte)) + byteIdx - 1] = (unsigned char)(q & 255);
  1537. byteIdx--;
  1538.     }
  1539. }
  1540. z += (ubyte);
  1541.     }
  1542.     A->len = (n / 8);
  1543.     
  1544.     return SECITEM_DupItem(A);
  1545. loser:
  1546.     return NULL;
  1547. void
  1548. PBE_DestroyContext(PBEBitGenContext *pbeCtxt) {
  1549.     if(pbeCtxt) {
  1550. PORT_FreeArena(pbeCtxt->arena, PR_TRUE);
  1551.     }
  1552. }
  1553. SECStatus
  1554. PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PRArenaPool *arena, 
  1555.      SECAlgorithmID *algId)
  1556. {
  1557.     CK_PBE_PARAMS *pbe_param;
  1558.     SECItem pbeSalt;
  1559.     SECAlgorithmID *pbeAlgID = NULL;
  1560.     SECStatus rv;
  1561.     if(!param || !algId) {
  1562. return SECFailure;
  1563.     }
  1564.     pbe_param = (CK_PBE_PARAMS *)param->data;
  1565.     pbeSalt.data = (unsigned char *)pbe_param->pSalt;
  1566.     pbeSalt.len = pbe_param->ulSaltLen;
  1567.     pbeAlgID = SEC_PKCS5CreateAlgorithmID(algTag, &pbeSalt, 
  1568.   (int)pbe_param->ulIteration);
  1569.     if(!pbeAlgID) {
  1570. return SECFailure;
  1571.     }
  1572.     rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID);
  1573.     SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE);
  1574.     return rv;
  1575. }