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

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 "p12t.h"
  34. #include "p12.h"
  35. #include "plarena.h"
  36. #include "secitem.h"
  37. #include "secoid.h"
  38. #include "seccomon.h"
  39. #include "secport.h"
  40. #include "cert.h"
  41. #include "secpkcs7.h"
  42. #include "secasn1.h"
  43. #include "secerr.h"
  44. #include "pk11func.h"
  45. #include "p12plcy.h"
  46. #include "p12local.h"
  47. #include "alghmac.h"
  48. #include "secder.h"
  49. #include "secport.h"
  50. #include "certdb.h"
  51. #include "prcpucfg.h"
  52. typedef struct sec_PKCS12SafeContentsContextStr sec_PKCS12SafeContentsContext;
  53. /* Opaque structure for decoding SafeContents.  These are used
  54.  * for each authenticated safe as well as any nested safe contents.
  55.  */
  56. struct sec_PKCS12SafeContentsContextStr {
  57.     /* the parent decoder context */
  58.     SEC_PKCS12DecoderContext *p12dcx;
  59.     /* memory arena to allocate space from */
  60.     PRArenaPool *arena;
  61.     /* decoder context and destination for decoding safe contents */
  62.     SEC_ASN1DecoderContext *safeContentsDcx;
  63.     sec_PKCS12SafeContents safeContents;
  64.     /* information for decoding safe bags within the safe contents.
  65.      * these variables are updated for each safe bag decoded.
  66.      */
  67.     SEC_ASN1DecoderContext *currentSafeBagDcx;
  68.     sec_PKCS12SafeBag *currentSafeBag;
  69.     PRBool skipCurrentSafeBag;
  70.     /* if the safe contents is nested, the parent is pointed to here. */
  71.     sec_PKCS12SafeContentsContext *nestedCtx;
  72. };
  73. /* opaque decoder context structure.  information for decoding a pkcs 12
  74.  * PDU are stored here as well as decoding pointers for intermediary 
  75.  * structures which are part of the PKCS 12 PDU.  Upon a successful
  76.  * decode, the safe bags containing certificates and keys encountered.
  77.  */  
  78. struct SEC_PKCS12DecoderContextStr {
  79.     PRArenaPool *arena;
  80.     PK11SlotInfo *slot;
  81.     void *wincx;
  82.     PRBool error;
  83.     int errorValue;
  84.     /* password */
  85.     SECItem *pwitem;
  86.     /* used for decoding the PFX structure */
  87.     SEC_ASN1DecoderContext *pfxDcx;
  88.     sec_PKCS12PFXItem pfx;
  89.     /* safe bags found during decoding */  
  90.     sec_PKCS12SafeBag **safeBags;
  91.     unsigned int safeBagCount;
  92.     /* state variables for decoding authenticated safes. */
  93.     SEC_PKCS7DecoderContext *currentASafeP7Dcx;
  94.     SEC_PKCS5KeyAndPassword *currentASafeKeyPwd;
  95.     SEC_ASN1DecoderContext *aSafeDcx;
  96.     SEC_PKCS7DecoderContext *aSafeP7Dcx;
  97.     sec_PKCS12AuthenticatedSafe authSafe;
  98.     SEC_PKCS7ContentInfo *aSafeCinfo;
  99.     sec_PKCS12SafeContents safeContents;
  100.     /* safe contents info */
  101.     unsigned int safeContentsCnt;
  102.     sec_PKCS12SafeContentsContext **safeContentsList;
  103.     /* HMAC info */
  104.     sec_PKCS12MacData macData;
  105.     SEC_ASN1DecoderContext *hmacDcx;
  106.     /* routines for reading back the data to be hmac'd */
  107.     digestOpenFn dOpen;
  108.     digestCloseFn dClose;
  109.     digestIOFn dRead, dWrite;
  110.     void *dArg;
  111.     /* helper functions */
  112.     SECKEYGetPasswordKey pwfn;
  113.     void *pwfnarg;
  114.     PRBool swapUnicodeBytes;
  115.     /* import information */
  116.     PRBool bagsVerified;
  117. };
  118. /* make sure that the PFX version being decoded is a version
  119.  * which we support.
  120.  */
  121. static PRBool
  122. sec_pkcs12_proper_version(sec_PKCS12PFXItem *pfx)
  123. {
  124.     /* if no version, assume it is not supported */
  125.     if(pfx->version.len == 0) {
  126. return PR_FALSE;
  127.     }
  128.     if(DER_GetInteger(&pfx->version) > SEC_PKCS12_VERSION) {
  129. return PR_FALSE;
  130.     }
  131.     return PR_TRUE;
  132. }
  133. /* retrieve the key for decrypting the safe contents */ 
  134. static PK11SymKey *
  135. sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
  136. {
  137.     SEC_PKCS5KeyAndPassword *keyPwd = 
  138.         (SEC_PKCS5KeyAndPassword *)arg;
  139.     if(!keyPwd) {
  140. return NULL;
  141.     }
  142.     /* if no slot specified, use the internal key slot */
  143.     if(!keyPwd->slot) {
  144. keyPwd->slot = PK11_GetInternalKeySlot();
  145.     }
  146.     /* retrieve the key */
  147.     if(!keyPwd->key) {
  148. keyPwd->key = PK11_PBEKeyGen(keyPwd->slot, algid, 
  149.      keyPwd->pwitem, PR_FALSE, keyPwd->wincx);
  150.     }
  151.     return (PK11SymKey *)keyPwd;
  152. }
  153. /* XXX this needs to be modified to handle enveloped data.  most
  154.  * likely, it should mirror the routines for SMIME in that regard.
  155.  */
  156. static PRBool
  157. sec_pkcs12_decoder_decryption_allowed(SECAlgorithmID *algid, 
  158.       PK11SymKey *bulkkey)
  159. {
  160.     PRBool decryptionAllowed = SEC_PKCS12DecryptionAllowed(algid);
  161.     if(!decryptionAllowed) {
  162. return PR_FALSE;
  163.     }
  164.     return PR_TRUE;
  165. }
  166. /* when we encounter a new safe bag during the decoding, we need
  167.  * to allocate space for the bag to be decoded to and set the 
  168.  * state variables appropriately.  all of the safe bags are allocated
  169.  * in a buffer in the outer SEC_PKCS12DecoderContext, however,
  170.  * a pointer to the safeBag is also used in the sec_PKCS12SafeContentsContext
  171.  * for the current bag.
  172.  */
  173. static SECStatus
  174. sec_pkcs12_decoder_init_new_safe_bag(sec_PKCS12SafeContentsContext 
  175. *safeContentsCtx)
  176. {
  177.     void *mark = NULL;
  178.     SEC_PKCS12DecoderContext *p12dcx;
  179.     /* make sure that the structures are defined, and there has
  180.      * not been an error in the decoding 
  181.      */
  182.     if(!safeContentsCtx || !safeContentsCtx->p12dcx 
  183. || safeContentsCtx->p12dcx->error) {
  184. return SECFailure;
  185.     }
  186.     p12dcx = safeContentsCtx->p12dcx;
  187.     mark = PORT_ArenaMark(p12dcx->arena);
  188.     /* allocate a new safe bag, if bags already exist, grow the 
  189.      * list of bags, otherwise allocate a new list.  the list is
  190.      * NULL terminated.
  191.      */
  192.     if(p12dcx->safeBagCount) {
  193. p12dcx->safeBags = 
  194.     (sec_PKCS12SafeBag**)PORT_ArenaGrow(p12dcx->arena,p12dcx->safeBags,
  195. (p12dcx->safeBagCount + 1) * sizeof(sec_PKCS12SafeBag *),
  196. (p12dcx->safeBagCount + 2) * sizeof(sec_PKCS12SafeBag *));
  197.     } else {
  198. p12dcx->safeBags = (sec_PKCS12SafeBag**)PORT_ArenaZAlloc(p12dcx->arena,
  199.     2 * sizeof(sec_PKCS12SafeBag *));
  200.     }
  201.     if(!p12dcx->safeBags) {
  202. p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  203. goto loser;
  204.     }
  205.     /* append the bag to the end of the list and update the reference
  206.      * in the safeContentsCtx.
  207.      */
  208.     p12dcx->safeBags[p12dcx->safeBagCount] = 
  209.         (sec_PKCS12SafeBag*)PORT_ArenaZAlloc(p12dcx->arena,
  210.      sizeof(sec_PKCS12SafeBag));
  211.     safeContentsCtx->currentSafeBag = p12dcx->safeBags[p12dcx->safeBagCount];
  212.     p12dcx->safeBags[++p12dcx->safeBagCount] = NULL;
  213.     if(!safeContentsCtx->currentSafeBag) {
  214. p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  215. goto loser;
  216.     }
  217.     safeContentsCtx->currentSafeBag->slot = safeContentsCtx->p12dcx->slot;
  218.     safeContentsCtx->currentSafeBag->pwitem = safeContentsCtx->p12dcx->pwitem;
  219.     safeContentsCtx->currentSafeBag->swapUnicodeBytes = 
  220. safeContentsCtx->p12dcx->swapUnicodeBytes;
  221.     safeContentsCtx->currentSafeBag->arena = safeContentsCtx->p12dcx->arena;
  222.     PORT_ArenaUnmark(p12dcx->arena, mark);
  223.     return SECSuccess;
  224. loser:
  225.     /* if an error occurred, release the memory and set the error flag
  226.      * the only possible errors triggered by this function are memory 
  227.      * related.
  228.      */
  229.     if(mark) {
  230. PORT_ArenaRelease(p12dcx->arena, mark);
  231.     }
  232.     p12dcx->error = PR_TRUE;
  233.     return SECFailure;
  234. }
  235. /* A wrapper for updating the ASN1 context in which a safeBag is
  236.  * being decoded.  This function is called as a callback from
  237.  * secasn1d when decoding SafeContents structures.
  238.  */
  239. static void
  240. sec_pkcs12_decoder_safe_bag_update(void *arg, const char *data, 
  241.    unsigned long len, int depth, 
  242.    SEC_ASN1EncodingPart data_kind)
  243. {
  244.     sec_PKCS12SafeContentsContext *safeContentsCtx = 
  245.         (sec_PKCS12SafeContentsContext *)arg;
  246.     SEC_PKCS12DecoderContext *p12dcx;
  247.     SECStatus rv;
  248.     /* make sure that we are not skipping the current safeBag,
  249.      * and that there are no errors.  If so, just return rather
  250.      * than continuing to process.
  251.      */
  252.     if(!safeContentsCtx || !safeContentsCtx->p12dcx 
  253. || safeContentsCtx->p12dcx->error 
  254. || safeContentsCtx->skipCurrentSafeBag) {
  255. return;
  256.     }
  257.     p12dcx = safeContentsCtx->p12dcx;
  258.     rv = SEC_ASN1DecoderUpdate(safeContentsCtx->currentSafeBagDcx, data, len);
  259.     if(rv != SECSuccess) {
  260. p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  261. goto loser;
  262.     }
  263.     return;
  264. loser:
  265.     /* set the error, and finish the decoder context.  because there 
  266.      * is not a way of returning an error message, it may be worth
  267.      * while to do a check higher up and finish any decoding contexts
  268.      * that are still open.
  269.      */
  270.     p12dcx->error = PR_TRUE;
  271.     SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagDcx);
  272.     safeContentsCtx->currentSafeBagDcx = NULL;
  273.     return;
  274. }
  275. /* forward declarations of functions that are used when decoding
  276.  * safeContents bags which are nested and when decoding the 
  277.  * authenticatedSafes.
  278.  */
  279. static SECStatus
  280. sec_pkcs12_decoder_begin_nested_safe_contents(sec_PKCS12SafeContentsContext 
  281. *safeContentsCtx);
  282. static SECStatus
  283. sec_pkcs12_decoder_finish_nested_safe_contents(sec_PKCS12SafeContentsContext
  284. *safeContentsCtx);
  285. static void
  286. sec_pkcs12_decoder_safe_bag_update(void *arg, const char *data, 
  287.    unsigned long len, int depth, 
  288.    SEC_ASN1EncodingPart data_kind);
  289. /* notify function for decoding safeBags.  This function is
  290.  * used to filter safeBag types which are not supported,
  291.  * initiate the decoding of nested safe contents, and decode
  292.  * safeBags in general.  this function is set when the decoder
  293.  * context for the safeBag is first created.
  294.  */
  295. static void
  296. sec_pkcs12_decoder_safe_bag_notify(void *arg, PRBool before,
  297.    void *dest, int real_depth)
  298. {
  299.     sec_PKCS12SafeContentsContext *safeContentsCtx = 
  300.         (sec_PKCS12SafeContentsContext *)arg;
  301.     SEC_PKCS12DecoderContext *p12dcx;
  302.     sec_PKCS12SafeBag *bag;
  303.     PRBool after;
  304.     /* if an error is encountered, return */
  305.     if(!safeContentsCtx || !safeContentsCtx->p12dcx || 
  306. safeContentsCtx->p12dcx->error) {
  307. return;
  308.     }
  309.     p12dcx = safeContentsCtx->p12dcx;
  310.     /* to make things more readable */
  311.     if(before)
  312. after = PR_FALSE;
  313.     else 
  314. after = PR_TRUE;
  315.     /* have we determined the safeBagType yet? */
  316.     bag = safeContentsCtx->currentSafeBag;
  317.     if(bag->bagTypeTag == NULL) {
  318. if(after && (dest == &(bag->safeBagType))) {
  319.     bag->bagTypeTag = SECOID_FindOID(&(bag->safeBagType));
  320.     if(bag->bagTypeTag == NULL) {
  321. p12dcx->error = PR_TRUE;
  322. p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
  323.     }
  324. }
  325. return;
  326.     }
  327.     /* process the safeBag depending on it's type.  those
  328.      * which we do not support, are ignored.  we start a decoding
  329.      * context for a nested safeContents.
  330.      */
  331.     switch(bag->bagTypeTag->offset) {
  332. case SEC_OID_PKCS12_V1_KEY_BAG_ID:
  333. case SEC_OID_PKCS12_V1_CERT_BAG_ID:
  334. case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
  335.     break;
  336. case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID:
  337.     /* if we are just starting to decode the safeContents, initialize
  338.      * a new safeContentsCtx to process it.
  339.      */
  340.     if(before && (dest == &(bag->safeBagContent))) {
  341. sec_pkcs12_decoder_begin_nested_safe_contents(safeContentsCtx);
  342.     } else if(after && (dest == &(bag->safeBagContent))) {
  343. /* clean up the nested decoding */
  344. sec_pkcs12_decoder_finish_nested_safe_contents(safeContentsCtx);
  345.     }
  346.     break;
  347. case SEC_OID_PKCS12_V1_CRL_BAG_ID:
  348. case SEC_OID_PKCS12_V1_SECRET_BAG_ID:
  349. default:
  350.     /* skip any safe bag types we don't understand or handle */
  351.     safeContentsCtx->skipCurrentSafeBag = PR_TRUE;
  352.     break;
  353.     }
  354.     return;
  355. }
  356. /* notify function for decoding safe contents.  each entry in the
  357.  * safe contents is a safeBag which needs to be allocated and
  358.  * the decoding context initialized at the beginning and then
  359.  * the context needs to be closed and finished at the end.
  360.  *
  361.  * this function is set when the safeContents decode context is
  362.  * initialized.
  363.  */
  364. static void
  365. sec_pkcs12_decoder_safe_contents_notify(void *arg, PRBool before,
  366. void *dest, int real_depth)
  367. {
  368.     sec_PKCS12SafeContentsContext *safeContentsCtx = 
  369.         (sec_PKCS12SafeContentsContext*)arg;
  370.     SEC_PKCS12DecoderContext *p12dcx;
  371.     SECStatus rv;
  372.     /* if there is an error we don't want to continue processing,
  373.      * just return and keep going.
  374.      */
  375.     if(!safeContentsCtx || !safeContentsCtx->p12dcx 
  376. || safeContentsCtx->p12dcx->error) {
  377. return;
  378.     }
  379.     p12dcx = safeContentsCtx->p12dcx;
  380.     /* if we are done with the current safeBag, then we need to
  381.      * finish the context and set the state variables appropriately.
  382.      */
  383.     if(!before) {
  384. SEC_ASN1DecoderClearFilterProc(safeContentsCtx->safeContentsDcx);
  385. SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagDcx);
  386. safeContentsCtx->currentSafeBagDcx = NULL;
  387. safeContentsCtx->skipCurrentSafeBag = PR_FALSE;
  388.     } else {
  389. /* we are starting a new safe bag.  we need to allocate space
  390.  * for the bag and initialize the decoding context.
  391.  */
  392. rv = sec_pkcs12_decoder_init_new_safe_bag(safeContentsCtx);
  393. if(rv != SECSuccess) {
  394.     goto loser;
  395. }
  396. /* set up the decoder context */
  397. safeContentsCtx->currentSafeBagDcx = SEC_ASN1DecoderStart(p12dcx->arena,
  398. safeContentsCtx->currentSafeBag,
  399. sec_PKCS12SafeBagTemplate);
  400. if(!safeContentsCtx->currentSafeBagDcx) {
  401.     p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  402.     goto loser;
  403. }
  404. /* set the notify and filter procs so that the safe bag
  405.  * data gets sent to the proper location when decoding.
  406.  */
  407. SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->currentSafeBagDcx, 
  408.  sec_pkcs12_decoder_safe_bag_notify, 
  409.  safeContentsCtx);
  410. SEC_ASN1DecoderSetFilterProc(safeContentsCtx->safeContentsDcx, 
  411.  sec_pkcs12_decoder_safe_bag_update, 
  412.  safeContentsCtx, PR_TRUE);
  413.     }
  414.     return;
  415. loser:
  416.     /* in the event of an error, we want to close the decoding
  417.      * context and clear the filter and notify procedures.
  418.      */
  419.     p12dcx->error = PR_TRUE;
  420.     if(safeContentsCtx->currentSafeBagDcx) {
  421. SEC_ASN1DecoderFinish(safeContentsCtx->currentSafeBagDcx);
  422. safeContentsCtx->currentSafeBagDcx = NULL;
  423.     }
  424.     SEC_ASN1DecoderClearNotifyProc(safeContentsCtx->safeContentsDcx);
  425.     SEC_ASN1DecoderClearFilterProc(safeContentsCtx->safeContentsDcx);
  426.     return;
  427. }
  428. /* initialize the safeContents for decoding.  this routine
  429.  * is used for authenticatedSafes as well as nested safeContents.
  430.  */
  431. static sec_PKCS12SafeContentsContext *
  432. sec_pkcs12_decoder_safe_contents_init_decode(SEC_PKCS12DecoderContext *p12dcx,
  433.      PRBool nestedSafe)
  434. {
  435.     sec_PKCS12SafeContentsContext *safeContentsCtx = NULL;
  436.     const SEC_ASN1Template *theTemplate;
  437.     if(!p12dcx || p12dcx->error) {
  438. return NULL;
  439.     }
  440.     /* allocate a new safeContents list or grow the existing list and
  441.      * append the new safeContents onto the end.
  442.      */
  443.     if(!p12dcx->safeContentsCnt) {
  444. p12dcx->safeContentsList = 
  445.     (sec_PKCS12SafeContentsContext**)PORT_ArenaZAlloc(p12dcx->arena, 
  446.          sizeof(sec_PKCS12SafeContentsContext *));
  447.     } else {
  448. p12dcx->safeContentsList = 
  449.    (sec_PKCS12SafeContentsContext **) PORT_ArenaGrow(p12dcx->arena,
  450. p12dcx->safeContentsList,
  451. (p12dcx->safeContentsCnt * 
  452. sizeof(sec_PKCS12SafeContentsContext *)),
  453. (1 + p12dcx->safeContentsCnt * 
  454. sizeof(sec_PKCS12SafeContentsContext *)));
  455.     }
  456.     if(!p12dcx->safeContentsList) {
  457. p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  458. goto loser;
  459.     }
  460.     p12dcx->safeContentsList[p12dcx->safeContentsCnt] = 
  461.         (sec_PKCS12SafeContentsContext*)PORT_ArenaZAlloc(
  462. p12dcx->arena,
  463. sizeof(sec_PKCS12SafeContentsContext));
  464.     p12dcx->safeContentsList[p12dcx->safeContentsCnt+1] = NULL;
  465.     if(!p12dcx->safeContentsList[p12dcx->safeContentsCnt]) {
  466. p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  467. goto loser;
  468.     }
  469.     /* set up the state variables */
  470.     safeContentsCtx = p12dcx->safeContentsList[p12dcx->safeContentsCnt];
  471.     p12dcx->safeContentsCnt++;
  472.     safeContentsCtx->p12dcx = p12dcx;
  473.     safeContentsCtx->arena = p12dcx->arena;
  474.     /* begin the decoding -- the template is based on whether we are
  475.      * decoding a nested safeContents or not.
  476.      */
  477.     if(nestedSafe == PR_TRUE) {
  478. theTemplate = sec_PKCS12NestedSafeContentsDecodeTemplate;
  479.     } else {
  480. theTemplate = sec_PKCS12SafeContentsDecodeTemplate;
  481.     }
  482.     /* start the decoder context */
  483.     safeContentsCtx->safeContentsDcx = SEC_ASN1DecoderStart(p12dcx->arena, 
  484. &safeContentsCtx->safeContents,
  485. theTemplate);
  486.     if(!safeContentsCtx->safeContentsDcx) {
  487. p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  488. goto loser;
  489.     }
  490.     /* set the safeContents notify procedure to look for
  491.      * and start the decode of safeBags.
  492.      */
  493.     SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->safeContentsDcx, 
  494. sec_pkcs12_decoder_safe_contents_notify,
  495. safeContentsCtx);
  496.     return safeContentsCtx;
  497. loser:
  498.     /* in the case of an error, we want to finish the decoder
  499.      * context and set the error flag.
  500.      */
  501.     if(safeContentsCtx && safeContentsCtx->safeContentsDcx) {
  502. SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsDcx);
  503. safeContentsCtx->safeContentsDcx = NULL;
  504.     }
  505.     p12dcx->error = PR_TRUE;
  506.     return NULL;
  507. }
  508. /* wrapper for updating safeContents.  this is set as the filter of
  509.  * safeBag when there is a nested safeContents.
  510.  */
  511. static void
  512. sec_pkcs12_decoder_nested_safe_contents_update(void *arg, const char *buf,
  513.   unsigned long len, int depth,
  514.   SEC_ASN1EncodingPart data_kind)
  515. {
  516.     sec_PKCS12SafeContentsContext *safeContentsCtx = 
  517.         (sec_PKCS12SafeContentsContext *)arg;
  518.     SEC_PKCS12DecoderContext *p12dcx;
  519.     SECStatus rv;
  520.     /* check for an error */
  521.     if(!safeContentsCtx || !safeContentsCtx->p12dcx 
  522. || safeContentsCtx->p12dcx->error) {
  523. return;
  524.     }
  525.     /* no need to update if no data sent in */
  526.     if(!len || !buf) {
  527. return;
  528.     }
  529.     /* update the decoding context */
  530.     p12dcx = safeContentsCtx->p12dcx;
  531.     rv = SEC_ASN1DecoderUpdate(safeContentsCtx->safeContentsDcx, buf, len);
  532.     if(rv != SECSuccess) {
  533. p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  534. goto loser;
  535.     }
  536.     return;
  537. loser:
  538.     /* handle any errors.  If a decoding context is open, close it. */
  539.     p12dcx->error = PR_TRUE;
  540.     if(safeContentsCtx->safeContentsDcx) {
  541. SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsDcx);
  542. safeContentsCtx->safeContentsDcx = NULL;
  543.     }
  544. }
  545. /* whenever a new safeContentsSafeBag is encountered, we need
  546.  * to init a safeContentsContext.  
  547.  */
  548. static SECStatus  
  549. sec_pkcs12_decoder_begin_nested_safe_contents(sec_PKCS12SafeContentsContext 
  550. *safeContentsCtx)
  551. {
  552.     /* check for an error */
  553.     if(!safeContentsCtx || !safeContentsCtx->p12dcx || 
  554. safeContentsCtx->p12dcx->error) {
  555. return SECFailure;
  556.     }
  557.     safeContentsCtx->nestedCtx = sec_pkcs12_decoder_safe_contents_init_decode(
  558. safeContentsCtx->p12dcx,
  559. PR_TRUE);
  560.     if(!safeContentsCtx->nestedCtx) {
  561. return SECFailure;
  562.     }
  563.     /* set up new filter proc */
  564.     SEC_ASN1DecoderSetNotifyProc(safeContentsCtx->nestedCtx->safeContentsDcx,
  565.  sec_pkcs12_decoder_safe_contents_notify,
  566.  safeContentsCtx->nestedCtx);
  567.     SEC_ASN1DecoderSetFilterProc(safeContentsCtx->currentSafeBagDcx,
  568.  sec_pkcs12_decoder_nested_safe_contents_update,
  569.  safeContentsCtx->nestedCtx, PR_TRUE);
  570.     return SECSuccess;
  571. }
  572. /* when the safeContents is done decoding, we need to reset the
  573.  * proper filter and notify procs and close the decoding context 
  574.  */
  575. static SECStatus
  576. sec_pkcs12_decoder_finish_nested_safe_contents(sec_PKCS12SafeContentsContext
  577. *safeContentsCtx)
  578. {
  579.     /* check for error */
  580.     if(!safeContentsCtx || !safeContentsCtx->p12dcx || 
  581. safeContentsCtx->p12dcx->error) {
  582. return SECFailure;
  583.     }
  584.     /* clean up */
  585.     SEC_ASN1DecoderClearFilterProc(safeContentsCtx->currentSafeBagDcx);
  586.     SEC_ASN1DecoderClearNotifyProc(safeContentsCtx->nestedCtx->safeContentsDcx);
  587.     SEC_ASN1DecoderFinish(safeContentsCtx->nestedCtx->safeContentsDcx);
  588.     safeContentsCtx->nestedCtx->safeContentsDcx = NULL;
  589.     safeContentsCtx->nestedCtx = NULL;
  590.     return SECSuccess;
  591. }
  592. /* wrapper for updating safeContents.  This is used when decoding
  593.  * the nested safeContents and any authenticatedSafes.
  594.  */
  595. static void
  596. sec_pkcs12_decoder_safe_contents_callback(void *arg, const char *buf,
  597.   unsigned long len)
  598. {
  599.     SECStatus rv;
  600.     sec_PKCS12SafeContentsContext *safeContentsCtx = 
  601.         (sec_PKCS12SafeContentsContext *)arg;
  602.     SEC_PKCS12DecoderContext *p12dcx;
  603.     /* check for error */  
  604.     if(!safeContentsCtx || !safeContentsCtx->p12dcx 
  605. || safeContentsCtx->p12dcx->error) {
  606. return;
  607.     }
  608.     p12dcx = safeContentsCtx->p12dcx;
  609.     /* update the decoder */
  610.     rv = SEC_ASN1DecoderUpdate(safeContentsCtx->safeContentsDcx, buf, len);
  611.     if(rv != SECSuccess) {
  612. p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
  613. goto loser;
  614.     }
  615.     return;
  616. loser:
  617.     /* set the error and finish the context */
  618.     p12dcx->error = PR_TRUE;
  619.     if(safeContentsCtx->safeContentsDcx) {
  620. SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsDcx);
  621. safeContentsCtx->safeContentsDcx = NULL;
  622.     }
  623.     return;
  624. }
  625. /* this is a wrapper for the ASN1 decoder to call SEC_PKCS7DecoderUpdate
  626.  */
  627. static void
  628. sec_pkcs12_decoder_wrap_p7_update(void *arg, const char *data,
  629.   unsigned long len, int depth,
  630.   SEC_ASN1EncodingPart data_kind)
  631. {
  632.     SEC_PKCS7DecoderContext *p7dcx = (SEC_PKCS7DecoderContext *)arg;
  633.     SEC_PKCS7DecoderUpdate(p7dcx, data, len);
  634. }
  635. /* notify function for decoding aSafes.  at the beginning,
  636.  * of an authenticatedSafe, we start a decode of a safeContents.
  637.  * at the end, we clean up the safeContents decoder context and
  638.  * reset state variables 
  639.  */
  640. static void
  641. sec_pkcs12_decoder_asafes_notify(void *arg, PRBool before, void *dest, 
  642.        int real_depth)
  643. {
  644.     SEC_PKCS12DecoderContext *p12dcx;
  645.     sec_PKCS12SafeContentsContext *safeContentsCtx;
  646.     /* make sure no error occurred. */
  647.     p12dcx = (SEC_PKCS12DecoderContext *)arg;
  648.     if(!p12dcx || p12dcx->error) {
  649. return;
  650.     }
  651.     if(before) {
  652. /* init a new safeContentsContext */
  653. safeContentsCtx = sec_pkcs12_decoder_safe_contents_init_decode(p12dcx, 
  654. PR_FALSE);
  655. if(!safeContentsCtx) {
  656.     goto loser;
  657. }
  658. /* set up password and encryption key information */
  659. p12dcx->currentASafeKeyPwd = 
  660.     (SEC_PKCS5KeyAndPassword*)PORT_ArenaZAlloc(p12dcx->arena, 
  661.       sizeof(SEC_PKCS5KeyAndPassword));
  662. if(!p12dcx->currentASafeKeyPwd) {
  663.     p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  664.     goto loser;
  665. }
  666. p12dcx->currentASafeKeyPwd->pwitem = p12dcx->pwitem;
  667. p12dcx->currentASafeKeyPwd->slot = p12dcx->slot;
  668. p12dcx->currentASafeKeyPwd->wincx = p12dcx->wincx;
  669. /* initiate the PKCS7ContentInfo decode */
  670. p12dcx->currentASafeP7Dcx = SEC_PKCS7DecoderStart(
  671. sec_pkcs12_decoder_safe_contents_callback,
  672. safeContentsCtx, 
  673. p12dcx->pwfn, p12dcx->pwfnarg,
  674. sec_pkcs12_decoder_get_decrypt_key, 
  675. p12dcx->currentASafeKeyPwd, 
  676. sec_pkcs12_decoder_decryption_allowed);
  677. if(!p12dcx->currentASafeP7Dcx) {
  678.     p12dcx->errorValue = PORT_GetError();
  679.     goto loser;
  680. }
  681. SEC_ASN1DecoderSetFilterProc(p12dcx->aSafeDcx, 
  682.      sec_pkcs12_decoder_wrap_p7_update,
  683.      p12dcx->currentASafeP7Dcx, PR_TRUE);
  684.     }
  685.     if(!before) {
  686. /* if one is being decoded, finish the decode */
  687. if(p12dcx->currentASafeP7Dcx != NULL) {
  688.     if(!SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx)) {
  689. p12dcx->currentASafeP7Dcx = NULL;
  690. p12dcx->errorValue = PORT_GetError();
  691. goto loser;
  692.     }
  693.     p12dcx->currentASafeP7Dcx = NULL;
  694. }
  695. p12dcx->currentASafeP7Dcx = NULL;
  696. if(p12dcx->currentASafeKeyPwd->key != NULL) {
  697.     p12dcx->currentASafeKeyPwd->key = NULL;
  698. }
  699.     }
  700.     return;
  701. loser:
  702.     /* set the error flag */
  703.     p12dcx->error = PR_TRUE;
  704.     return;
  705. }
  706. /* wrapper for updating asafes decoding context.  this function
  707.  * writes data being decoded to disk, so that a mac can be computed
  708.  * later.  
  709.  */
  710. static void
  711. sec_pkcs12_decoder_asafes_callback(void *arg, const char *buf, 
  712.   unsigned long len)
  713. {
  714.     SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg;
  715.     SECStatus rv;
  716.     if(!p12dcx || p12dcx->error) {
  717. return;
  718.     }
  719.     /* update the context */
  720.     rv = SEC_ASN1DecoderUpdate(p12dcx->aSafeDcx, buf, len);
  721.     if(rv != SECSuccess) {
  722. p12dcx->error = (PRBool)SEC_ERROR_NO_MEMORY;
  723. goto loser;
  724.     }
  725.     /* if we are writing to a file, write out the new information */
  726.     if(p12dcx->dWrite) {
  727. unsigned long writeLen = (*p12dcx->dWrite)(p12dcx->dArg, 
  728.    (unsigned char *)buf, len);
  729. if(writeLen != len) {
  730.     p12dcx->errorValue = PORT_GetError();
  731.     goto loser;
  732. }
  733.     }
  734.     return;
  735. loser:
  736.     /* set the error flag */
  737.     p12dcx->error = PR_TRUE;
  738.     SEC_ASN1DecoderFinish(p12dcx->aSafeDcx);
  739.     p12dcx->aSafeDcx = NULL;
  740.     return;
  741. }
  742.    
  743. /* start the decode of an authenticatedSafe contentInfo.
  744.  */ 
  745. static SECStatus
  746. sec_pkcs12_decode_start_asafes_cinfo(SEC_PKCS12DecoderContext *p12dcx)
  747. {
  748.     if(!p12dcx || p12dcx->error) {
  749. return SECFailure;
  750.     }
  751.     /* start the decode context */
  752.     p12dcx->aSafeDcx = SEC_ASN1DecoderStart(p12dcx->arena, 
  753.      &p12dcx->authSafe,
  754.      sec_PKCS12AuthenticatedSafeTemplate);
  755.     if(!p12dcx->aSafeDcx) {
  756. p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  757.     goto loser;
  758.     }
  759.     /* set the notify function */
  760.     SEC_ASN1DecoderSetNotifyProc(p12dcx->aSafeDcx,
  761.       sec_pkcs12_decoder_asafes_notify, p12dcx);
  762.     /* begin the authSafe decoder context */
  763.     p12dcx->aSafeP7Dcx = SEC_PKCS7DecoderStart(
  764.      sec_pkcs12_decoder_asafes_callback, p12dcx,
  765.      p12dcx->pwfn, p12dcx->pwfnarg, NULL, NULL, NULL);
  766.     if(!p12dcx->aSafeP7Dcx) {
  767. p12dcx->errorValue = SEC_ERROR_NO_MEMORY;
  768. goto loser;
  769.     }
  770.   
  771.     /* open the temp file for writing, if the filter functions were set */ 
  772.     if(p12dcx->dOpen && (*p12dcx->dOpen)(p12dcx->dArg, PR_FALSE) 
  773. != SECSuccess) {
  774. p12dcx->errorValue = PORT_GetError();
  775. goto loser;
  776.     }
  777.     return SECSuccess;
  778. loser:
  779.     p12dcx->error = PR_TRUE;
  780.     if(p12dcx->aSafeDcx) {
  781. SEC_ASN1DecoderFinish(p12dcx->aSafeDcx);
  782. p12dcx->aSafeDcx = NULL;
  783.     } 
  784.     if(p12dcx->aSafeP7Dcx) {
  785. SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);
  786. p12dcx->aSafeP7Dcx = NULL;
  787.     }
  788.     return SECFailure;
  789. }
  790. /* wrapper for updating the safeContents.  this function is used as
  791.  * a filter for the pfx when decoding the authenticated safes 
  792.  */
  793. static void 
  794. sec_pkcs12_decode_asafes_cinfo_update(void *arg, const char *buf,
  795.       unsigned long len, int depth,
  796.       SEC_ASN1EncodingPart data_kind)
  797. {
  798.     SEC_PKCS12DecoderContext *p12dcx;
  799.     SECStatus rv;
  800.     p12dcx = (SEC_PKCS12DecoderContext*)arg;
  801.     if(!p12dcx || p12dcx->error) {
  802. return;
  803.     }
  804.     /* update the safeContents decoder */
  805.     rv = SEC_PKCS7DecoderUpdate(p12dcx->aSafeP7Dcx, buf, len);
  806.     if(rv != SECSuccess) {
  807. p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
  808. goto loser;
  809.     }
  810.     return;
  811. loser:
  812.     /* did we find an error?  if so, close the context and set the 
  813.      * error flag.
  814.      */
  815.     SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);
  816.     p12dcx->aSafeP7Dcx = NULL;
  817.     p12dcx->error = PR_TRUE;
  818. }
  819. /* notify procedure used while decoding the pfx.  When we encounter
  820.  * the authSafes, we want to trigger the decoding of authSafes as well
  821.  * as when we encounter the macData, trigger the decoding of it.  we do
  822.  * this because we we are streaming the decoder and not decoding in place.
  823.  * the pfx which is the destination, only has the version decoded into it.
  824.  */
  825. static void 
  826. sec_pkcs12_decoder_pfx_notify_proc(void *arg, PRBool before, void *dest,
  827.    int real_depth)
  828. {
  829.     SECStatus rv;
  830.     SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext*)arg;
  831.     /* if an error occurrs, clear the notifyProc and the filterProc 
  832.      * and continue. 
  833.      */
  834.     if(p12dcx->error) {
  835. SEC_ASN1DecoderClearNotifyProc(p12dcx->pfxDcx);
  836. SEC_ASN1DecoderClearFilterProc(p12dcx->pfxDcx);
  837. return;
  838.     }
  839.     if(before && (dest == &p12dcx->pfx.encodedAuthSafe)) {
  840. /* we want to make sure this is a version we support */
  841. if(!sec_pkcs12_proper_version(&p12dcx->pfx)) {
  842.     p12dcx->errorValue = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION;
  843.     goto loser;
  844. }
  845. /* start the decode of the aSafes cinfo... */
  846. rv = sec_pkcs12_decode_start_asafes_cinfo(p12dcx);
  847. if(rv != SECSuccess) {
  848.     goto loser;
  849. }
  850. /* set the filter proc to update the authenticated safes. */
  851. SEC_ASN1DecoderSetFilterProc(p12dcx->pfxDcx,
  852.      sec_pkcs12_decode_asafes_cinfo_update,
  853.      p12dcx, PR_TRUE);
  854.     }
  855.     if(!before && (dest == &p12dcx->pfx.encodedAuthSafe)) {
  856. /* we are done decoding the authenticatedSafes, so we need to 
  857.  * finish the decoderContext and clear the filter proc
  858.  * and close the hmac callback, if present
  859.  */
  860. p12dcx->aSafeCinfo = SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);
  861. p12dcx->aSafeP7Dcx = NULL;
  862. if(!p12dcx->aSafeCinfo) {
  863.     p12dcx->errorValue = PORT_GetError();
  864.     goto loser;
  865. }
  866. SEC_ASN1DecoderClearFilterProc(p12dcx->pfxDcx);
  867. if(p12dcx->dClose && ((*p12dcx->dClose)(p12dcx->dArg, PR_FALSE) 
  868. != SECSuccess)) {
  869.     p12dcx->errorValue = PORT_GetError();
  870.     goto loser;
  871. }
  872.     }
  873.     return;
  874. loser:
  875.     p12dcx->error = PR_TRUE;
  876. }
  877. /* SEC_PKCS12DecoderStart
  878.  * Creates a decoder context for decoding a PKCS 12 PDU objct.
  879.  * This function sets up the initial decoding context for the
  880.  * PFX and sets the needed state variables.
  881.  *
  882.  * pwitem - the password for the hMac and any encoded safes.
  883.  *  this should be changed to take a callback which retrieves
  884.  *  the password.  it may be possible for different safes to
  885.  *  have different passwords.  also, the password is already
  886.  *  in unicode.  it should probably be converted down below via
  887.  *  a unicode conversion callback.
  888.  * slot - the slot to import the dataa into should multiple slots 
  889.  *  be supported based on key type and cert type?
  890.  * dOpen, dClose, dRead, dWrite - digest routines for writing data
  891.  *  to a file so it could be read back and the hmack recomputed
  892.  *  and verified.  doesn't seem to be away for both encoding
  893.  *  and decoding to be single pass, thus the need for these
  894.  *  routines.
  895.  * dArg - the argument for dOpen, etc.
  896.  *
  897.  * This function returns the decoder context, if it was successful.
  898.  * Otherwise, null is returned.
  899.  */
  900. SEC_PKCS12DecoderContext *
  901. SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx,
  902.        digestOpenFn dOpen, digestCloseFn dClose, 
  903.        digestIOFn dRead, digestIOFn dWrite, void *dArg)
  904. {
  905.     SEC_PKCS12DecoderContext *p12dcx;
  906.     PRArenaPool *arena;
  907.     arena = PORT_NewArena(2048); /* different size? */
  908.     if(!arena) {
  909. PORT_SetError(SEC_ERROR_NO_MEMORY);
  910. return NULL;
  911.     }
  912.     /* allocate the decoder context and set the state variables */
  913.     p12dcx = (SEC_PKCS12DecoderContext*)PORT_ArenaZAlloc(arena, sizeof(SEC_PKCS12DecoderContext));
  914.     if(!p12dcx) {
  915. PORT_SetError(SEC_ERROR_NO_MEMORY);
  916. goto loser;
  917.     }
  918.     p12dcx->arena = arena;
  919.     p12dcx->pwitem = pwitem;
  920.     p12dcx->slot = (slot ? slot : PK11_GetInternalKeySlot());
  921.     p12dcx->wincx = wincx;
  922. #ifdef IS_LITTLE_ENDIAN
  923.     p12dcx->swapUnicodeBytes = PR_TRUE;
  924. #else
  925.     p12dcx->swapUnicodeBytes = PR_FALSE;
  926. #endif
  927.     p12dcx->errorValue = 0;
  928.     p12dcx->error = PR_FALSE;
  929.     /* a slot is *required */
  930.     if(!slot) {
  931. PORT_SetError(SEC_ERROR_NO_MEMORY);
  932. goto loser;
  933.     }
  934.     /* start the decoding of the PFX and set the notify proc
  935.      * for the PFX item.
  936.      */
  937.     p12dcx->pfxDcx = SEC_ASN1DecoderStart(p12dcx->arena, &p12dcx->pfx,
  938.        sec_PKCS12PFXItemTemplate);
  939.     if(!p12dcx->pfxDcx) {
  940. PORT_SetError(SEC_ERROR_NO_MEMORY); 
  941. goto loser;
  942.     }
  943.     SEC_ASN1DecoderSetNotifyProc(p12dcx->pfxDcx, 
  944.  sec_pkcs12_decoder_pfx_notify_proc,
  945.       p12dcx); 
  946.     
  947.     /* set up digest functions */
  948.     p12dcx->dOpen = dOpen;
  949.     p12dcx->dWrite = dWrite;
  950.     p12dcx->dClose = dClose;
  951.     p12dcx->dRead = dRead;
  952.     p12dcx->dArg = dArg;
  953.     return p12dcx;
  954. loser:
  955.     PORT_FreeArena(arena, PR_TRUE);
  956.     return NULL;
  957. }
  958. /* SEC_PKCS12DecoderUpdate 
  959.  * Streaming update sending more data to the decoder.  If 
  960.  * an error occurs, SECFailure is returned.
  961.  *
  962.  * p12dcx - the decoder context 
  963.  * data, len - the data buffer and length of data to send to 
  964.  * the update functions.
  965.  */
  966. SECStatus
  967. SEC_PKCS12DecoderUpdate(SEC_PKCS12DecoderContext *p12dcx,
  968. unsigned char *data, unsigned long len)
  969. {
  970.     SECStatus rv;
  971.     if(!p12dcx || p12dcx->error) {
  972. return SECFailure;
  973.     }
  974.     /* update the PFX decoder context */
  975.     rv = SEC_ASN1DecoderUpdate(p12dcx->pfxDcx, (const char *)data, len);
  976.     if(rv != SECSuccess) {
  977. p12dcx->errorValue = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
  978. goto loser;
  979.     }
  980.     return SECSuccess;
  981. loser:
  982.     p12dcx->error = PR_TRUE;
  983.     return SECFailure;
  984. }
  985. /* IN_BUF_LEN should be larger than SHA1_LENGTH */
  986. #define IN_BUF_LEN 80
  987. /* verify the hmac by reading the data from the temporary file
  988.  * using the routines specified when the decodingContext was 
  989.  * created and return SECSuccess if the hmac matches.
  990.  */
  991. static SECStatus
  992. sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx)
  993. {
  994.     SECStatus rv = SECFailure;
  995.     PBEBitGenContext *pbeCtxt = NULL;
  996.     SECItem *hmacKey = NULL, hmacRes;
  997.     unsigned char buf[IN_BUF_LEN];
  998.     void *hmacCx;
  999.     unsigned int bufLen;
  1000.     int iteration;
  1001.     
  1002.     if(!p12dcx || p12dcx->error) {
  1003. return SECFailure;
  1004.     }
  1005.     /* generate hmac key */
  1006.     if(p12dcx->macData.iter.data) {
  1007. iteration = (int)DER_GetInteger(&p12dcx->macData.iter);
  1008.     } else {
  1009. iteration = 1;
  1010.     }
  1011.     pbeCtxt = PBE_CreateContext(SECOID_GetAlgorithmTag(
  1012. &p12dcx->macData.safeMac.digestAlgorithm),
  1013. pbeBitGenIntegrityKey, p12dcx->pwitem,
  1014. &p12dcx->macData.macSalt, 160, iteration);
  1015.     if(!pbeCtxt) {
  1016. return SECFailure;
  1017.     }
  1018.     hmacKey = PBE_GenerateBits(pbeCtxt);
  1019.     PBE_DestroyContext(pbeCtxt);
  1020.     pbeCtxt = NULL;
  1021.     if(!hmacKey) {
  1022. return SECFailure;
  1023.     }
  1024.     /* init hmac */
  1025.     hmacCx = HMAC_Create(SECOID_GetAlgorithmTag(
  1026. &p12dcx->macData.safeMac.digestAlgorithm),
  1027.  hmacKey->data, hmacKey->len);
  1028.     SECITEM_ZfreeItem(hmacKey, PR_TRUE);
  1029.     hmacKey = NULL;
  1030.     if(!hmacCx) {
  1031. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1032. return SECFailure;
  1033.     }
  1034.     HMAC_Begin((HMACContext*)hmacCx);
  1035.     /* try to open the data for readback */
  1036.     if(p12dcx->dOpen && ((*p12dcx->dOpen)(p12dcx->dArg, PR_TRUE) 
  1037. != SECSuccess)) {
  1038. goto loser;
  1039.     }
  1040.     /* read the data back IN_BUF_LEN bytes at a time and recompute
  1041.      * the hmac.  if fewer bytes are read than are requested, it is
  1042.      * assumed that the end of file has been reached. if bytesRead
  1043.      * is returned as -1, then an error occured reading from the 
  1044.      * file.
  1045.      */
  1046.     while(1) {
  1047. int bytesRead = (*p12dcx->dRead)(p12dcx->dArg, buf, IN_BUF_LEN);
  1048. if(bytesRead == -1) {
  1049.     goto loser;
  1050. }
  1051. HMAC_Update((HMACContext*)hmacCx, buf, bytesRead);
  1052. if(bytesRead < IN_BUF_LEN) {
  1053.     break;
  1054. }
  1055.     }
  1056.     /* finish the hmac context */
  1057.     HMAC_Finish((HMACContext*)hmacCx, buf, &bufLen, IN_BUF_LEN);
  1058.     HMAC_Destroy((HMACContext*)hmacCx);
  1059.     hmacCx = NULL;
  1060.     hmacRes.data = buf;
  1061.     hmacRes.len = bufLen;
  1062.     /* is the hmac computed the same as the hmac which was decoded? */
  1063.     rv = SECSuccess;
  1064.     if(SECITEM_CompareItem(&hmacRes, &p12dcx->macData.safeMac.digest) 
  1065. != SECEqual) {
  1066. PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);
  1067. rv = SECFailure;
  1068.     }
  1069. loser:
  1070.     /* close the file and remove it */
  1071.     if(p12dcx->dClose) {
  1072. (*p12dcx->dClose)(p12dcx->dArg, PR_TRUE);
  1073.     }
  1074.     if(hmacCx) {
  1075. HMAC_Destroy((HMACContext*)hmacCx);
  1076.     }
  1077.     if(hmacKey) {
  1078. SECITEM_ZfreeItem(hmacKey, PR_TRUE);
  1079.     }
  1080.     return rv;
  1081. }
  1082. /* SEC_PKCS12DecoderVerify
  1083.  *  Verify the macData or the signature of the decoded PKCS 12 PDU.
  1084.  * If the signature or the macData do not match, SECFailure is
  1085.  * returned.
  1086.  *
  1087.  *  p12dcx - the decoder context 
  1088.  */
  1089. SECStatus
  1090. SEC_PKCS12DecoderVerify(SEC_PKCS12DecoderContext *p12dcx)
  1091. {
  1092.     SECStatus rv = SECSuccess;
  1093.     /* make sure that no errors have occured... */
  1094.     if(!p12dcx || p12dcx->error) {
  1095. return SECFailure;
  1096.     }
  1097.     /* check the signature or the mac depending on the type of
  1098.      * integrity used.
  1099.      */
  1100.     if(p12dcx->pfx.encodedMacData.len) {
  1101. rv = SEC_ASN1DecodeItem(p12dcx->arena, &p12dcx->macData,
  1102. sec_PKCS12MacDataTemplate,
  1103. &p12dcx->pfx.encodedMacData);
  1104. if(rv == SECSuccess) {
  1105.     return sec_pkcs12_decoder_verify_mac(p12dcx);
  1106. } else {
  1107.     PORT_SetError(SEC_ERROR_NO_MEMORY);
  1108. }
  1109.     } else {
  1110. if(SEC_PKCS7VerifySignature(p12dcx->aSafeCinfo, certUsageEmailSigner,
  1111.     PR_FALSE)) {
  1112.     return SECSuccess;
  1113. } else {
  1114.     PORT_SetError(SEC_ERROR_PKCS12_INVALID_MAC);
  1115. }
  1116.     }
  1117.     return SECFailure;
  1118. }
  1119. /* SEC_PKCS12DecoderFinish
  1120.  * Free any open ASN1 or PKCS7 decoder contexts and then
  1121.  * free the arena pool which everything should be allocated
  1122.  * from.  This function should be called upon completion of
  1123.  * decoding and installing of a pfx pdu.  This should be
  1124.  * called even if an error occurs.
  1125.  *
  1126.  * p12dcx - the decoder context
  1127.  */
  1128. void
  1129. SEC_PKCS12DecoderFinish(SEC_PKCS12DecoderContext *p12dcx)
  1130. {
  1131.     void *freedCtxt = NULL;
  1132.     if(!p12dcx) {
  1133. return;
  1134.     }
  1135.     if(p12dcx->pfxDcx) {
  1136. SEC_ASN1DecoderFinish(p12dcx->pfxDcx);
  1137. p12dcx->pfxDcx = NULL;
  1138.     }
  1139.     if(p12dcx->aSafeDcx) {
  1140. SEC_ASN1DecoderFinish(p12dcx->aSafeDcx);
  1141. p12dcx->aSafeDcx = NULL;
  1142.     }
  1143.     if(p12dcx->currentASafeP7Dcx) {
  1144. SEC_PKCS7DecoderFinish(p12dcx->currentASafeP7Dcx);
  1145. p12dcx->currentASafeP7Dcx = NULL;
  1146.     }
  1147.     if(p12dcx->aSafeP7Dcx) {
  1148. SEC_PKCS7DecoderFinish(p12dcx->aSafeP7Dcx);
  1149.     }
  1150.     if(p12dcx->hmacDcx) {
  1151. SEC_ASN1DecoderFinish(p12dcx->hmacDcx);
  1152. p12dcx->hmacDcx = NULL;
  1153.     }
  1154.     if(p12dcx->arena) {
  1155. PORT_FreeArena(p12dcx->arena, PR_TRUE);
  1156.     }
  1157. }
  1158. static SECStatus
  1159. sec_pkcs12_decoder_set_attribute_value(sec_PKCS12SafeBag *bag,
  1160.        SECOidTag attributeType,
  1161.        SECItem *attrValue)
  1162. {
  1163.     int i = 0;
  1164.     SECOidData *oid;
  1165.     if(!bag || !attrValue) {
  1166. return SECFailure;
  1167.     }
  1168.     oid = SECOID_FindOIDByTag(attributeType);
  1169.     if(!oid) {
  1170. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1171. return SECFailure;
  1172.     }
  1173.     if(!bag->attribs) {
  1174. bag->attribs = (sec_PKCS12Attribute**)PORT_ArenaZAlloc(bag->arena, 
  1175. sizeof(sec_PKCS12Attribute *) * 2);
  1176.     } else {
  1177. while(bag->attribs[i]) i++;
  1178. bag->attribs = (sec_PKCS12Attribute **)PORT_ArenaGrow(bag->arena, 
  1179.       bag->attribs, 
  1180.       (i + 1) * sizeof(sec_PKCS12Attribute *),
  1181.       (i + 2) * sizeof(sec_PKCS12Attribute *));
  1182.     }
  1183.     if(!bag->attribs) {
  1184. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1185. return SECFailure;
  1186.     }
  1187.     bag->attribs[i] = (sec_PKCS12Attribute*)PORT_ArenaZAlloc(bag->arena, 
  1188.   sizeof(sec_PKCS12Attribute));
  1189.     if(!bag->attribs) {
  1190. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1191. return SECFailure;
  1192.     }
  1193.     bag->attribs[i]->attrValue = (SECItem**)PORT_ArenaZAlloc(bag->arena, 
  1194.   sizeof(SECItem *) * 2);
  1195.     if(!bag->attribs[i]->attrValue) {
  1196. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1197. return SECFailure;
  1198.     }
  1199.     bag->attribs[i+1] = NULL;
  1200.     bag->attribs[i]->attrValue[0] = attrValue;
  1201.     bag->attribs[i]->attrValue[1] = NULL;
  1202.     if(SECITEM_CopyItem(bag->arena, &bag->attribs[i]->attrType, &oid->oid)
  1203. != SECSuccess) {
  1204. PORT_SetError(SEC_ERROR_NO_MEMORY);
  1205. return SECFailure;
  1206.     }
  1207.     return SECSuccess;
  1208. }
  1209. static SECItem *
  1210. sec_pkcs12_get_attribute_value(sec_PKCS12SafeBag *bag,
  1211.        SECOidTag attributeType)
  1212. {
  1213.     int i = 0;
  1214.     if(!bag->attribs) {
  1215. return NULL;
  1216.     }
  1217.     while(bag->attribs[i] != NULL) {
  1218. if(SECOID_FindOIDTag(&bag->attribs[i]->attrType) 
  1219. == attributeType) {
  1220.     return bag->attribs[i]->attrValue[0];
  1221. }
  1222. i++;
  1223.     }
  1224.     return NULL;
  1225. }
  1226. /* For now, this function will merely remove any ":"
  1227.  * in the nickname which the PK11 functions may have
  1228.  * placed there.  This will keep dual certs from appearing
  1229.  * twice under "Your" certificates when imported onto smart
  1230.  * cards.  Once with the name "Slot:Cert" and another with
  1231.  * the nickname "Slot:Slot:Cert"
  1232.  */
  1233. static void
  1234. sec_pkcs12_sanitize_nickname(PK11SlotInfo *slot, SECItem *nick)
  1235. {
  1236.     char *nickname;
  1237.     char *delimit;
  1238.     int delimitlen;
  1239.  
  1240.     nickname = (char*)nick->data; /*Mac breaks without this type cast*/
  1241.     if ((delimit = PORT_Strchr(nickname, ':')) != NULL) {
  1242.         char *slotName;
  1243. int slotNameLen;
  1244. slotNameLen = delimit-nickname;
  1245. slotName = PORT_NewArray(char, (slotNameLen+1));
  1246. PORT_Assert(slotName);
  1247. if (slotName == NULL) {
  1248.   /* What else can we do?*/
  1249.   return;
  1250. }
  1251. PORT_Memcpy(slotName, nickname, slotNameLen);
  1252. slotName[slotNameLen] = '';
  1253. if (PORT_Strcmp(PK11_GetTokenName(slot), slotName) == 0) {
  1254.   delimitlen = PORT_Strlen(delimit+1);
  1255.   PORT_Memmove(nickname, delimit+1, delimitlen+1);
  1256.   nick->len = delimitlen;
  1257. }
  1258. PORT_Free(slotName);
  1259.     }
  1260.  
  1261. }
  1262. static SECItem *
  1263. sec_pkcs12_get_nickname(sec_PKCS12SafeBag *bag)
  1264. {
  1265.     SECItem *src, *dest;
  1266.     if(!bag) {
  1267. bag->problem = PR_TRUE;
  1268. bag->error = SEC_ERROR_NO_MEMORY;
  1269. return NULL;
  1270.     }
  1271.     src = sec_pkcs12_get_attribute_value(bag, SEC_OID_PKCS9_FRIENDLY_NAME);
  1272.     if(!src) {
  1273. return NULL;
  1274.     }
  1275.     dest = (SECItem*)PORT_ZAlloc(sizeof(SECItem));
  1276.     if(!dest) { 
  1277. goto loser;
  1278.     }
  1279.     if(!sec_pkcs12_convert_item_to_unicode(NULL, dest, src, PR_FALSE, 
  1280. PR_FALSE, PR_FALSE)) {
  1281. goto loser;
  1282.     }
  1283.     sec_pkcs12_sanitize_nickname(bag->slot, dest);
  1284.     return dest;
  1285. loser:
  1286.     if(dest) {
  1287. SECITEM_ZfreeItem(dest, PR_TRUE);
  1288.     }
  1289.     bag->problem = PR_TRUE;
  1290.     bag->error = PORT_GetError();
  1291.     return NULL;
  1292. }
  1293. static SECStatus
  1294. sec_pkcs12_set_nickname(sec_PKCS12SafeBag *bag, SECItem *name)
  1295. {
  1296.     int i = 0;
  1297.     sec_PKCS12Attribute *attr = NULL;
  1298.     SECOidData *oid = SECOID_FindOIDByTag(SEC_OID_PKCS9_FRIENDLY_NAME);
  1299.     if(!bag || !bag->arena || !name) {
  1300. return SECFailure;
  1301.     }
  1302.     if(!bag->attribs) {
  1303. if(!oid) {
  1304.     goto loser;
  1305. }
  1306. bag->attribs = (sec_PKCS12Attribute**)PORT_ArenaZAlloc(bag->arena, 
  1307.      sizeof(sec_PKCS12Attribute *)*2);
  1308. if(!bag->attribs) {
  1309.     goto loser;
  1310. }
  1311. bag->attribs[0] = (sec_PKCS12Attribute*)PORT_ArenaZAlloc(bag->arena, 
  1312.   sizeof(sec_PKCS12Attribute));
  1313. if(!bag->attribs[0]) {
  1314.     goto loser;
  1315. }
  1316. bag->attribs[1] = NULL;
  1317. attr = bag->attribs[0];
  1318. if(SECITEM_CopyItem(bag->arena, &attr->attrType, &oid->oid) 
  1319. != SECSuccess) {
  1320.     goto loser;
  1321. }
  1322.     } else {
  1323. while(bag->attribs[i]) {
  1324.     if(SECOID_FindOIDTag(&bag->attribs[i]->attrType)
  1325. == SEC_OID_PKCS9_FRIENDLY_NAME) {
  1326. attr = bag->attribs[i];
  1327. goto have_attrib;
  1328.     }
  1329.     i++;
  1330. }
  1331. if(!attr) {
  1332.     bag->attribs = (sec_PKCS12Attribute **)PORT_ArenaGrow(bag->arena, 
  1333.   bag->attribs,
  1334. (i+1) * sizeof(sec_PKCS12Attribute *),
  1335. (i+2) * sizeof(sec_PKCS12Attribute *));
  1336.     if(!bag->attribs) {
  1337. goto loser;
  1338.     }
  1339.     bag->attribs[i] = 
  1340.         (sec_PKCS12Attribute *)PORT_ArenaZAlloc(bag->arena, 
  1341.   sizeof(sec_PKCS12Attribute));
  1342.     if(!bag->attribs[i]) {
  1343. goto loser;
  1344.     }
  1345.     bag->attribs[i+1] = NULL;
  1346.     attr = bag->attribs[i];
  1347.     if(SECITEM_CopyItem(bag->arena, &attr->attrType, &oid->oid) 
  1348. != SECSuccess) {
  1349. goto loser;
  1350.     }
  1351. }
  1352.     }
  1353. have_attrib:
  1354.     PORT_Assert(attr);
  1355.     if(!attr->attrValue) {
  1356. attr->attrValue = (SECItem **)PORT_ArenaZAlloc(bag->arena, 
  1357.        sizeof(SECItem *) * 2);
  1358. if(!attr->attrValue) {
  1359.     goto loser;
  1360. }
  1361. attr->attrValue[0] = (SECItem*)PORT_ArenaZAlloc(bag->arena, 
  1362. sizeof(SECItem));
  1363. if(!attr->attrValue[0]) {
  1364.     goto loser;
  1365. }
  1366. attr->attrValue[1] = NULL;
  1367.     }
  1368.     name->len = PORT_Strlen((char *)name->data);
  1369.     if(!sec_pkcs12_convert_item_to_unicode(bag->arena, attr->attrValue[0],
  1370. name, PR_FALSE, PR_FALSE, PR_TRUE)) {
  1371. goto loser;
  1372.     }
  1373.     return SECSuccess;
  1374. loser:
  1375.     bag->problem = PR_TRUE;
  1376.     bag->error = SEC_ERROR_NO_MEMORY;
  1377.     return SECFailure;
  1378. }
  1379. static SECStatus
  1380. sec_pkcs12_get_key_info(sec_PKCS12SafeBag *key) 
  1381. {
  1382.     int i = 0;
  1383.     SECKEYPrivateKeyInfo *pki = NULL;
  1384.     if(!key) {
  1385. return SECFailure;
  1386.     }
  1387.     /* if the bag does *not* contain an unencrypted PrivateKeyInfo 
  1388.      * then we cannot convert the attributes.  We are propagating
  1389.      * attributes within the PrivateKeyInfo to the SafeBag level.
  1390.      */
  1391.     if(SECOID_FindOIDTag(&(key->safeBagType)) != 
  1392. SEC_OID_PKCS12_V1_KEY_BAG_ID) {
  1393. return SECSuccess;
  1394.     }
  1395.     pki = key->safeBagContent.pkcs8KeyBag;
  1396.     if(!pki || !pki->attributes) {
  1397. return SECSuccess;
  1398.     }
  1399.     while(pki->attributes[i]) {
  1400. SECItem *attrValue = NULL;
  1401. if(SECOID_FindOIDTag(&pki->attributes[i]->attrType) == 
  1402. SEC_OID_PKCS9_LOCAL_KEY_ID) {
  1403.     attrValue = sec_pkcs12_get_attribute_value(key, 
  1404.  SEC_OID_PKCS9_LOCAL_KEY_ID);
  1405.     if(!attrValue) {
  1406. if(sec_pkcs12_decoder_set_attribute_value(key, 
  1407. SEC_OID_PKCS9_LOCAL_KEY_ID,
  1408. pki->attributes[i]->attrValue[0])
  1409. != SECSuccess) {
  1410.     key->problem = PR_TRUE;
  1411.     key->error = SEC_ERROR_NO_MEMORY;
  1412.     return SECFailure;
  1413. }
  1414.     }
  1415. }
  1416. if(SECOID_FindOIDTag(&pki->attributes[i]->attrType) == 
  1417. SEC_OID_PKCS9_FRIENDLY_NAME) {
  1418.     attrValue = sec_pkcs12_get_attribute_value(key, 
  1419. SEC_OID_PKCS9_FRIENDLY_NAME);
  1420.     if(!attrValue) {
  1421. if(sec_pkcs12_decoder_set_attribute_value(key, 
  1422. SEC_OID_PKCS9_FRIENDLY_NAME,
  1423. pki->attributes[i]->attrValue[0])
  1424. != SECSuccess) {
  1425.     key->problem = PR_TRUE;
  1426.     key->error = SEC_ERROR_NO_MEMORY;
  1427.     return SECFailure;
  1428. }
  1429.     }
  1430. }
  1431. i++;
  1432.     }
  1433.     return SECSuccess;
  1434. }
  1435. /* retrieve the nickname for the certificate bag.  first look
  1436.  * in the cert bag, otherwise get it from the key.
  1437.  */
  1438. static SECItem *
  1439. sec_pkcs12_get_nickname_for_cert(sec_PKCS12SafeBag *cert,
  1440.  sec_PKCS12SafeBag *key, 
  1441.  void *wincx)
  1442. {
  1443.     SECItem *nickname;
  1444.     if(!cert) {
  1445. return NULL;
  1446.     }
  1447.     nickname = sec_pkcs12_get_nickname(cert);
  1448.     if(nickname) {
  1449. return nickname;
  1450.     }
  1451.     if(key) {
  1452. nickname = sec_pkcs12_get_nickname(key);
  1453.         if(nickname && sec_pkcs12_set_nickname(cert, nickname)
  1454. != SECSuccess) {
  1455.     cert->error = SEC_ERROR_NO_MEMORY;
  1456.     cert->problem = PR_TRUE;
  1457.     if(nickname) { 
  1458. SECITEM_ZfreeItem(nickname, PR_TRUE);
  1459.     }
  1460.     return NULL;
  1461. }
  1462.     }
  1463.     return nickname;
  1464. }
  1465. /* set the nickname for the certificate */
  1466. static SECStatus
  1467. sec_pkcs12_set_nickname_for_cert(sec_PKCS12SafeBag *cert, 
  1468.  sec_PKCS12SafeBag *key, 
  1469.  SECItem *nickname, 
  1470.  void *wincx)
  1471. {
  1472.     if(!nickname || !cert) {
  1473. return SECFailure;
  1474.     }
  1475.     if(sec_pkcs12_set_nickname(cert, nickname) != SECSuccess) {
  1476. cert->error = SEC_ERROR_NO_MEMORY;
  1477. cert->problem = PR_TRUE;
  1478. return SECFailure;
  1479.     }
  1480.     if(key) {
  1481. if(sec_pkcs12_set_nickname(key, nickname) != SECSuccess) {
  1482.     cert->error = SEC_ERROR_NO_MEMORY;
  1483.     cert->problem = PR_TRUE;
  1484.     return SECFailure;
  1485. }
  1486.     }
  1487.     return SECSuccess;
  1488. }
  1489. /* retrieve the DER cert from the cert bag */
  1490. static SECItem *
  1491. sec_pkcs12_get_der_cert(sec_PKCS12SafeBag *cert) 
  1492. {
  1493.     if(!cert) {
  1494. return NULL;
  1495.     }
  1496.     if(SECOID_FindOIDTag(&cert->safeBagType) != SEC_OID_PKCS12_V1_CERT_BAG_ID) {
  1497. return NULL;
  1498.     }
  1499.     /* only support X509 certs not SDSI */
  1500.     if(SECOID_FindOIDTag(&cert->safeBagContent.certBag->bagID) 
  1501. != SEC_OID_PKCS9_X509_CERT) {
  1502. return NULL;
  1503.     }
  1504.     return SECITEM_DupItem(&(cert->safeBagContent.certBag->value.x509Cert));
  1505. }
  1506. struct certNickInfo {
  1507.     PRArenaPool *arena;
  1508.     unsigned int nNicks;
  1509.     SECItem **nickList;
  1510.     unsigned int error;
  1511. };
  1512. /* callback for traversing certificates to gather the nicknames 
  1513.  * used in a particular traversal.  for instance, when using
  1514.  * CERT_TraversePermCertsForSubject, gather the nicknames and
  1515.  * store them in the certNickInfo for a particular DN.
  1516.  * 
  1517.  * this handles the case where multiple nicknames are allowed
  1518.  * for the same dn, which is not currently allowed, but may be
  1519.  * in the future.
  1520.  */ 
  1521. static SECStatus
  1522. gatherNicknames(CERTCertificate *cert, void *arg)
  1523. {
  1524.     struct certNickInfo *nickArg = (struct certNickInfo *)arg;
  1525.     SECItem tempNick;
  1526.     unsigned int i;
  1527.     if(!cert || !nickArg || nickArg->error) {
  1528. return SECFailure;
  1529.     }
  1530.     if(!cert->nickname) {
  1531. return SECSuccess;
  1532.     }
  1533.     tempNick.data = (unsigned char *)cert->nickname;
  1534.     tempNick.len = PORT_Strlen(cert->nickname) + 1;
  1535.     /* do we already have the nickname in the list? */
  1536.     if(nickArg->nNicks > 0) {
  1537. /* nicknames have been encountered, but there is no list -- bad */
  1538. if(!nickArg->nickList) {
  1539.     nickArg->error = SEC_ERROR_NO_MEMORY;
  1540.     return SECFailure;
  1541. }
  1542. for(i = 0; i < nickArg->nNicks; i++) {
  1543.     if(SECITEM_CompareItem(nickArg->nickList[i], &tempNick) 
  1544. == SECEqual) {
  1545. return SECSuccess;
  1546.     }
  1547. }
  1548.     }
  1549.     /* add the nickname to the list */
  1550.     if(nickArg->nNicks == 0) {
  1551. nickArg->nickList = (SECItem **)PORT_ArenaZAlloc(nickArg->arena, 
  1552.      2 * sizeof(SECItem *));
  1553.     } else {
  1554. nickArg->nickList = (SECItem **)PORT_ArenaGrow(nickArg->arena,
  1555. nickArg->nickList, 
  1556. (nickArg->nNicks + 1) * sizeof(SECItem *),
  1557. (nickArg->nNicks + 2) * sizeof(SECItem *));
  1558.     }
  1559.     if(!nickArg->nickList) {
  1560. nickArg->error = SEC_ERROR_NO_MEMORY;
  1561. return SECFailure;
  1562.     }
  1563.     nickArg->nickList[nickArg->nNicks] = 
  1564.         (SECItem *)PORT_ArenaZAlloc(nickArg->arena, sizeof(SECItem));
  1565.     if(!nickArg->nickList[nickArg->nNicks]) {
  1566. nickArg->error = SEC_ERROR_NO_MEMORY;
  1567. return SECFailure;
  1568.     }
  1569.     
  1570.     if(SECITEM_CopyItem(nickArg->arena, nickArg->nickList[nickArg->nNicks],
  1571. &tempNick) != SECSuccess) {
  1572. nickArg->error = SEC_ERROR_NO_MEMORY;
  1573. return SECFailure;
  1574.     }
  1575.     nickArg->nNicks++;
  1576.     return SECSuccess;
  1577. }
  1578. /* traverses the certs in the data base or in the token for the
  1579.  * DN to see if any certs currently have a nickname set.
  1580.  * If so, return it. 
  1581.  */
  1582. static SECItem *
  1583. sec_pkcs12_get_existing_nick_for_dn(sec_PKCS12SafeBag *cert, void *wincx)
  1584. {
  1585.     struct certNickInfo *nickArg = NULL;
  1586.     SECItem *derCert, *returnDn = NULL;
  1587.     PRArenaPool *arena = NULL;
  1588.     CERTCertificate *tempCert;
  1589.     if(!cert) {
  1590. return NULL;
  1591.     }
  1592.     derCert = sec_pkcs12_get_der_cert(cert);
  1593.     if(!derCert) {
  1594. return NULL;
  1595.     }
  1596.     tempCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL,
  1597.    PR_FALSE, PR_TRUE);
  1598.     if(!tempCert) {
  1599. returnDn = NULL;
  1600. goto loser;
  1601.     }
  1602.     arena = PORT_NewArena(1024);
  1603.     if(!arena) {
  1604. returnDn = NULL;
  1605. goto loser;
  1606.     }
  1607.     nickArg = (struct certNickInfo *)PORT_ArenaZAlloc(arena, 
  1608.  sizeof(struct certNickInfo));
  1609.     if(!nickArg) {
  1610. returnDn = NULL;
  1611. goto loser;
  1612.     }
  1613.     nickArg->error = 0;
  1614.     nickArg->nNicks = 0;
  1615.     nickArg->nickList = NULL;
  1616.     nickArg->arena = arena;
  1617.     /* if the token is local, first traverse the cert database 
  1618.      * then traverse the token.
  1619.      */
  1620.     if(PK11_IsInternal(cert->slot)) {
  1621. if(CERT_TraversePermCertsForSubject(CERT_GetDefaultCertDB(), 
  1622. &tempCert->derSubject, gatherNicknames,
  1623. nickArg) != SECSuccess) {
  1624.     returnDn = NULL;
  1625.     goto loser;
  1626. }
  1627.     }
  1628.     if(PK11_TraverseCertsForSubjectInSlot(tempCert, cert->slot, gatherNicknames,
  1629. (void *)nickArg) != SECSuccess) {
  1630. returnDn = NULL;
  1631. goto loser;
  1632.     }
  1633.     if(nickArg->error) {
  1634. /* XXX do we want to set the error? */
  1635. returnDn = NULL;
  1636. goto loser;
  1637.     }
  1638.     if(nickArg->nNicks == 0) {
  1639. returnDn = NULL;
  1640. goto loser;
  1641.     }
  1642.     /* set it to the first name, for now.  handle multiple names? */
  1643.     returnDn = SECITEM_DupItem(nickArg->nickList[0]);
  1644. loser:
  1645.     if(arena) {
  1646. PORT_FreeArena(arena, PR_TRUE);
  1647.     }
  1648.     if(tempCert) {
  1649. CERT_DestroyCertificate(tempCert);
  1650.     }
  1651.     if(derCert) {
  1652. SECITEM_FreeItem(derCert, PR_TRUE);
  1653.     }
  1654.     return (returnDn);
  1655. }
  1656. /* counts certificates found for a given traversal function */
  1657. static SECStatus
  1658. countCertificate(CERTCertificate *cert, void *arg)
  1659. {
  1660.     unsigned int *nCerts = (unsigned int *)arg;
  1661.     if(!cert || !arg) {
  1662. return SECFailure;
  1663.     }
  1664.     (*nCerts)++;
  1665.     return SECSuccess;
  1666. }
  1667. static PRBool
  1668. sec_pkcs12_certs_for_nickname_exist(SECItem *nickname, PK11SlotInfo *slot)
  1669. {
  1670.     unsigned int nCerts = 0;
  1671.     if(!nickname || !slot) {
  1672. return PR_TRUE;
  1673.     }
  1674.     /* we want to check the local database first if we are importing to it */
  1675.     if(PK11_IsInternal(slot)) {
  1676. CERT_TraversePermCertsForNickname(CERT_GetDefaultCertDB(), 
  1677.       (char *)nickname->data,
  1678.       countCertificate, (void *)&nCerts);
  1679.     }
  1680.     PK11_TraverseCertsForNicknameInSlot(nickname, slot, countCertificate, 
  1681. (void *)&nCerts);
  1682.     if(nCerts) return PR_TRUE;
  1683.     return PR_FALSE;
  1684. }
  1685. /* validate cert nickname such that there is a one-to-one relation
  1686.  * between nicknames and dn's.  we want to enforce the case that the
  1687.  * nickname is non-NULL and that there is only one nickname per DN.
  1688.  * 
  1689.  * if there is a problem with a nickname or the nickname is not present, 
  1690.  * the user will be prompted for it.
  1691.  */
  1692. static void
  1693. sec_pkcs12_validate_cert_nickname(sec_PKCS12SafeBag *cert,
  1694. sec_PKCS12SafeBag *key,
  1695. SEC_PKCS12NicknameCollisionCallback nicknameCb,
  1696. void *wincx)
  1697. {
  1698.     SECItem *certNickname, *existingDNNick;
  1699.     PRBool setNickname = PR_FALSE, cancel = PR_FALSE;
  1700.     SECItem *newNickname = NULL;
  1701.     if(!cert || !cert->hasKey) {
  1702. return;
  1703.     }
  1704.     if(!nicknameCb) {
  1705. cert->problem = PR_TRUE;
  1706. cert->error = SEC_ERROR_NO_MEMORY;
  1707. return;
  1708.     }
  1709.     if(cert->hasKey && !key) {
  1710. cert->problem = PR_TRUE;
  1711. cert->error = SEC_ERROR_NO_MEMORY;
  1712. return;
  1713.     }
  1714.     certNickname = sec_pkcs12_get_nickname_for_cert(cert, key, wincx);
  1715.     existingDNNick = sec_pkcs12_get_existing_nick_for_dn(cert, wincx);
  1716.     /* nickname is already used w/ this dn, so it is safe to return */
  1717.     if(certNickname && existingDNNick &&
  1718. SECITEM_CompareItem(certNickname, existingDNNick) == SECEqual) {
  1719. goto loser;
  1720.     }
  1721.     /* nickname not set in pkcs 12 bags, but a nick is already used for
  1722.      * this dn.  set the nicks in the p12 bags and finish.
  1723.      */
  1724.     if(existingDNNick) {
  1725. if(sec_pkcs12_set_nickname_for_cert(cert, key, existingDNNick, wincx)
  1726. != SECSuccess) {
  1727.     cert->problem = PR_TRUE;
  1728.     cert->error = SEC_ERROR_NO_MEMORY;
  1729. }
  1730. goto loser;
  1731.     }
  1732.     /* at this point, we have a certificate for which the DN is not located
  1733.      * on the token.  the nickname specified may or may not be NULL.  if it
  1734.      * is not null, we need to make sure that there are no other certificates
  1735.      * with this nickname in the token for it to be valid.  this imposes a 
  1736.      * one to one relationship between DN and nickname.  
  1737.      *
  1738.      * if the nickname is null, we need the user to enter a nickname for
  1739.      * the certificate.
  1740.      *
  1741.      * once we have a nickname, we make sure that the nickname is unique
  1742.      * for the DN.  if it is not, the user is reprompted to enter a new 
  1743.      * nickname.  
  1744.      *
  1745.      * in order to exit this loop, the nickname entered is either unique
  1746.      * or the user hits cancel and the certificate is not imported.
  1747.      */
  1748.     setNickname = PR_FALSE;
  1749.     while(1) {
  1750. if(certNickname && certNickname->data) {
  1751.     /* we will use the nickname so long as no other certs have the
  1752.      * same nickname.  and the nickname is not NULL.
  1753.      */
  1754.     if(!sec_pkcs12_certs_for_nickname_exist(certNickname, cert->slot)) {
  1755. if(setNickname) {
  1756.     if(sec_pkcs12_set_nickname_for_cert(cert, key, certNickname,
  1757. wincx) != SECSuccess) {
  1758. cert->problem = PR_TRUE;
  1759. cert->error = SEC_ERROR_NO_MEMORY;
  1760.     }
  1761. }
  1762. goto loser;
  1763.     }
  1764. }
  1765. setNickname = PR_FALSE;
  1766. newNickname = (*nicknameCb)(certNickname, &cancel, wincx);
  1767. if(cancel) {
  1768.     cert->problem = PR_TRUE;
  1769.     cert->error = SEC_ERROR_USER_CANCELLED;
  1770.     goto loser;
  1771. }
  1772. if(!newNickname) {
  1773.     cert->problem = PR_TRUE;
  1774.     cert->error = SEC_ERROR_NO_MEMORY;
  1775.     goto loser;
  1776. }
  1777. /* at this point we have a new nickname, if we have an existing
  1778.  * certNickname, we need to free it and assign the new nickname
  1779.  * to it to avoid a memory leak.  happy?
  1780.  */
  1781. if(certNickname) {
  1782.     SECITEM_ZfreeItem(certNickname, PR_TRUE);
  1783.     certNickname = NULL;
  1784. }
  1785. certNickname = newNickname;
  1786. setNickname = PR_TRUE;
  1787. /* go back and recheck the new nickname */
  1788.     }
  1789. loser:
  1790.     if(certNickname) {
  1791. SECITEM_ZfreeItem(certNickname, PR_TRUE);
  1792.     }
  1793.     if(existingDNNick) {
  1794. SECITEM_ZfreeItem(existingDNNick, PR_TRUE);
  1795.     }
  1796. }
  1797. static void 
  1798. sec_pkcs12_validate_cert(sec_PKCS12SafeBag *cert,
  1799.  sec_PKCS12SafeBag *key,
  1800.  SEC_PKCS12NicknameCollisionCallback nicknameCb,
  1801.  void *wincx)
  1802. {
  1803.     CERTCertificate *leafCert, *testCert;
  1804.     if(!cert) {
  1805. return;
  1806.     }
  1807.     
  1808.     cert->validated = PR_TRUE;
  1809.     if(!nicknameCb) {
  1810. cert->problem = PR_TRUE;
  1811. cert->error = SEC_ERROR_NO_MEMORY;
  1812. cert->noInstall = PR_TRUE;
  1813. return;
  1814.     }
  1815.     if(!cert->safeBagContent.certBag) {
  1816. cert->noInstall = PR_TRUE;
  1817. cert->problem = PR_TRUE;
  1818. cert->error = SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE;
  1819. return;
  1820.     }
  1821.     cert->noInstall = PR_FALSE;
  1822.     cert->removeExisting = PR_FALSE;
  1823.     cert->problem = PR_FALSE;
  1824.     cert->error = 0;
  1825.     leafCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
  1826. &cert->safeBagContent.certBag->value.x509Cert,
  1827. NULL, PR_FALSE, PR_TRUE);
  1828.     if(!leafCert) {
  1829. cert->noInstall = PR_TRUE;
  1830. cert->problem = PR_TRUE;
  1831. cert->error = SEC_ERROR_NO_MEMORY;
  1832. return;
  1833.     }
  1834.     testCert = PK11_FindCertFromDERCert(cert->slot, leafCert, wincx);
  1835.     CERT_DestroyCertificate(leafCert);
  1836.     /* if we can't find the certificate through the PKCS11 interface,
  1837.      * we should check the cert database directly, if we are
  1838.      * importing to an internal slot.
  1839.      */
  1840.     if(!testCert && PK11_IsInternal(cert->slot)) {
  1841. testCert = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(),
  1842.  &cert->safeBagContent.certBag->value.x509Cert);
  1843.     }
  1844.     if(testCert) {
  1845. if(!testCert->nickname) {
  1846.     cert->removeExisting = PR_TRUE;
  1847. } else {
  1848.     cert->noInstall = PR_TRUE;
  1849. }
  1850. CERT_DestroyCertificate(testCert);
  1851. if(cert->noInstall && !cert->removeExisting) {
  1852.     return;
  1853. }
  1854.     }
  1855.     sec_pkcs12_validate_cert_nickname(cert, key, nicknameCb, wincx);
  1856. }
  1857. static void
  1858. sec_pkcs12_validate_key_by_cert(sec_PKCS12SafeBag *cert, sec_PKCS12SafeBag *key,
  1859. void *wincx)
  1860. {
  1861.     CERTCertificate *leafCert;
  1862.     SECKEYPrivateKey *privk;
  1863.     if(!key) {
  1864. return;
  1865.     }
  1866.     key->validated = PR_TRUE;
  1867.     if(!cert) {
  1868. key->problem = PR_TRUE;
  1869. key->noInstall = PR_TRUE;
  1870. key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
  1871. return;
  1872.     }
  1873.     leafCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
  1874. &(cert->safeBagContent.certBag->value.x509Cert),
  1875. NULL, PR_FALSE, PR_TRUE);
  1876.     if(!leafCert) {
  1877. key->problem = PR_TRUE;
  1878. key->noInstall = PR_TRUE;
  1879. key->error = SEC_ERROR_NO_MEMORY;
  1880. return;
  1881.     }
  1882.     privk = PK11_FindPrivateKeyFromCert(key->slot, leafCert, wincx);
  1883.     if(!privk) {
  1884. privk = PK11_FindKeyByDERCert(key->slot, leafCert, wincx);
  1885.     }
  1886.  
  1887.     if(privk) {
  1888. SECKEY_DestroyPrivateKey(privk);
  1889. key->noInstall = PR_TRUE;
  1890.     } 
  1891.     CERT_DestroyCertificate(leafCert);
  1892. }
  1893. static SECStatus
  1894. sec_pkcs12_remove_existing_cert(sec_PKCS12SafeBag *cert, 
  1895. void *wincx)
  1896. {
  1897.     SECItem *derCert = NULL;
  1898.     CERTCertificate *tempCert = NULL;
  1899.     CK_OBJECT_HANDLE certObj;
  1900.     PK11SlotInfo *slot = NULL;
  1901.     PRBool removed = PR_FALSE;
  1902.     if(!cert) {
  1903. return SECFailure;
  1904.     }
  1905.     PORT_Assert(cert->removeExisting);
  1906.     cert->removeExisting = PR_FALSE;
  1907.     derCert = &cert->safeBagContent.certBag->value.x509Cert;
  1908.     tempCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert,
  1909.        NULL, PR_FALSE, PR_TRUE);
  1910.     if(!tempCert) {
  1911. return SECFailure;
  1912.     }
  1913.     certObj = PK11_FindCertInSlot(cert->slot, tempCert, wincx);
  1914.     CERT_DestroyCertificate(tempCert);
  1915.     tempCert = NULL;
  1916.     if(certObj != CK_INVALID_KEY) {
  1917. PK11_DestroyObject(cert->slot, certObj);
  1918. removed = PR_TRUE;
  1919.     } else if(PK11_IsInternal(cert->slot)) {
  1920. tempCert = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), derCert);
  1921. if(tempCert) {
  1922.     if(SEC_DeletePermCertificate(tempCert) == SECSuccess) {
  1923. removed = PR_TRUE;
  1924.     } 
  1925.     CERT_DestroyCertificate(tempCert);
  1926.     tempCert = NULL;
  1927. }
  1928.     }
  1929.     if(!removed) {
  1930. cert->problem = PR_TRUE;
  1931. cert->error = SEC_ERROR_NO_MEMORY;
  1932. cert->noInstall = PR_TRUE;
  1933.     }
  1934.     if(tempCert) {
  1935. CERT_DestroyCertificate(tempCert);
  1936.     }
  1937.     return ((removed) ? SECSuccess : SECFailure);
  1938. }
  1939. static SECStatus
  1940. sec_pkcs12_add_cert(sec_PKCS12SafeBag *cert, PRBool keyExists, void *wincx)
  1941. {
  1942.     SECItem *derCert, *nickName;
  1943.     char *nickData = NULL;
  1944.     SECStatus rv;
  1945.     if(!cert) {
  1946. return SECFailure;
  1947.     }
  1948.     if(cert->problem || cert->noInstall || cert->installed) {
  1949. return SECSuccess;
  1950.     }
  1951.     derCert = &cert->safeBagContent.certBag->value.x509Cert;
  1952.     if(cert->removeExisting) {
  1953. if(sec_pkcs12_remove_existing_cert(cert, wincx) 
  1954. != SECSuccess) {
  1955.     return SECFailure;
  1956. }
  1957. cert->removeExisting = PR_FALSE;
  1958.     }
  1959.     PORT_Assert(!cert->problem && !cert->removeExisting && !cert->noInstall);
  1960.     nickName = sec_pkcs12_get_nickname(cert);
  1961.     if(nickName) {
  1962. nickData = (char *)nickName->data;
  1963.     }
  1964.     if(keyExists) {
  1965. CERTCertificate *newCert;
  1966. newCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
  1967.   derCert, NULL, PR_FALSE, PR_TRUE);
  1968. if(!newCert) {
  1969.      if(nickName) SECITEM_ZfreeItem(nickName, PR_TRUE);
  1970.      cert->error = SEC_ERROR_NO_MEMORY;
  1971.      cert->problem = PR_TRUE;
  1972.      return SECFailure;
  1973. }
  1974. rv = PK11_ImportCertForKeyToSlot(cert->slot, newCert, nickData, 
  1975.  PR_TRUE, wincx);
  1976. CERT_DestroyCertificate(newCert);
  1977.     } else {
  1978. SECItem *certList[2];
  1979. certList[0] = derCert;
  1980. certList[1] = NULL;
  1981. rv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageUserCertImport,
  1982.       1, certList, NULL, PR_TRUE, PR_FALSE, nickData);
  1983.     }
  1984.     cert->installed = PR_TRUE;
  1985.     if(nickName) SECITEM_ZfreeItem(nickName, PR_TRUE);
  1986.     return rv;
  1987. }
  1988. static SECStatus
  1989. sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECItem *publicValue, 
  1990. KeyType keyType, unsigned int keyUsage, void *wincx)
  1991. {
  1992.     SECStatus rv;
  1993.     SECItem *nickName;
  1994.     if(!key) {
  1995. return SECFailure;
  1996.     }
  1997.     if(key->removeExisting) {
  1998. key->problem = PR_TRUE;
  1999. key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
  2000. return SECFailure;
  2001.     }
  2002.     if(key->problem || key->noInstall) {
  2003. return SECSuccess;
  2004.     }
  2005.     nickName = sec_pkcs12_get_nickname(key);
  2006.     switch(SECOID_FindOIDTag(&key->safeBagType))
  2007.     {
  2008. case SEC_OID_PKCS12_V1_KEY_BAG_ID:
  2009.     rv = PK11_ImportPrivateKeyInfo(key->slot, 
  2010.   key->safeBagContent.pkcs8KeyBag, 
  2011.   nickName, publicValue, PR_TRUE, PR_TRUE,
  2012.   keyUsage,  wincx);
  2013.     break;
  2014. case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
  2015.     rv = PK11_ImportEncryptedPrivateKeyInfo(key->slot,
  2016. key->safeBagContent.pkcs8ShroudedKeyBag,
  2017. key->pwitem, nickName, publicValue, 
  2018. PR_TRUE, PR_TRUE, keyType, keyUsage,
  2019. wincx);
  2020.     break;
  2021. default:
  2022.     key->error = SEC_ERROR_PKCS12_UNSUPPORTED_VERSION;
  2023.     key->problem = PR_TRUE;
  2024.     if(nickName) {
  2025. SECITEM_ZfreeItem(nickName, PR_TRUE);
  2026.     }
  2027.     return SECFailure;
  2028.     }
  2029.     key->installed = PR_TRUE;
  2030.     if(nickName) {
  2031. SECITEM_ZfreeItem(nickName, PR_TRUE);
  2032.     }
  2033.     if(rv != SECSuccess) {
  2034. key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
  2035. key->problem = PR_TRUE;
  2036.     } else {
  2037. key->installed = PR_TRUE;
  2038.     }
  2039.     return rv;
  2040. }
  2041. static SECStatus
  2042. sec_pkcs12_add_item_to_bag_list(sec_PKCS12SafeBag ***bagList, 
  2043. sec_PKCS12SafeBag *bag)
  2044. {
  2045.     int i = 0;
  2046.     if(!bagList || !bag) {
  2047. return SECFailure;
  2048.     }
  2049.     if(!(*bagList)) {
  2050. (*bagList) = (sec_PKCS12SafeBag **)PORT_ArenaZAlloc(bag->arena, 
  2051.       sizeof(sec_PKCS12SafeBag *) * 2);
  2052.     } else {
  2053. while((*bagList)[i]) i++;
  2054. (*bagList) = (sec_PKCS12SafeBag **)PORT_ArenaGrow(bag->arena, *bagList,
  2055. sizeof(sec_PKCS12SafeBag *) * (i + 1),
  2056. sizeof(sec_PKCS12SafeBag *) * (i + 2));
  2057.     }
  2058.     if(!(*bagList)) {
  2059. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2060. return SECFailure;
  2061.     }
  2062.     (*bagList)[i] = bag;
  2063.     (*bagList)[i+1] = NULL;
  2064.     return SECSuccess;
  2065. }
  2066. static sec_PKCS12SafeBag **
  2067. sec_pkcs12_find_certs_for_key(sec_PKCS12SafeBag **safeBags, sec_PKCS12SafeBag *key ) 
  2068. {
  2069.     sec_PKCS12SafeBag **certList = NULL;
  2070.     SECItem *keyId;
  2071.     int i;
  2072.     if(!safeBags || !safeBags[0]) {
  2073. return NULL;
  2074.     }
  2075.     keyId = sec_pkcs12_get_attribute_value(key, SEC_OID_PKCS9_LOCAL_KEY_ID);
  2076.     if(!keyId) {
  2077. return NULL;
  2078.     }
  2079.     i = 0;
  2080.     certList = NULL;
  2081.     while(safeBags[i]) {
  2082. if(SECOID_FindOIDTag(&(safeBags[i]->safeBagType)) 
  2083. == SEC_OID_PKCS12_V1_CERT_BAG_ID) {
  2084.     SECItem *certKeyId = sec_pkcs12_get_attribute_value(safeBags[i],
  2085. SEC_OID_PKCS9_LOCAL_KEY_ID);
  2086.     if(certKeyId && (SECITEM_CompareItem(certKeyId, keyId) 
  2087. == SECEqual)) {
  2088. if(sec_pkcs12_add_item_to_bag_list(&certList, safeBags[i])
  2089. != SECSuccess) {
  2090.     return NULL;
  2091. }
  2092.     }
  2093. }
  2094. i++;
  2095.     }
  2096.     return certList;
  2097. }
  2098. CERTCertList *
  2099. SEC_PKCS12DecoderGetCerts(SEC_PKCS12DecoderContext *p12dcx)
  2100. {
  2101.     CERTCertList *certList = NULL;
  2102.     sec_PKCS12SafeBag **safeBags = p12dcx->safeBags;
  2103.     int i;
  2104.     if (!p12dcx || !p12dcx->safeBags || !p12dcx->safeBags[0]) {
  2105. return NULL;
  2106.     }
  2107.     safeBags = p12dcx->safeBags;
  2108.     i = 0;
  2109.     certList = CERT_NewCertList();
  2110.     if (certList == NULL) {
  2111.  return NULL;
  2112.     }
  2113.     while(safeBags[i]) {
  2114. if (SECOID_FindOIDTag(&(safeBags[i]->safeBagType)) 
  2115. == SEC_OID_PKCS12_V1_CERT_BAG_ID) {
  2116. SECItem *derCert = sec_pkcs12_get_der_cert(safeBags[i]) ;
  2117. CERTCertificate *tempCert = NULL;
  2118. if (derCert == NULL) continue;
  2119.      tempCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 
  2120. derCert, NULL, PR_FALSE, PR_TRUE);
  2121. if (tempCert) {
  2122.     CERT_AddCertToListTail(certList,tempCert);
  2123. }
  2124. SECITEM_FreeItem(derCert,PR_TRUE);
  2125. }
  2126. i++;
  2127.     }
  2128.     return certList;
  2129. }
  2130. static sec_PKCS12SafeBag **
  2131. sec_pkcs12_get_key_bags(sec_PKCS12SafeBag **safeBags)
  2132. {
  2133.     int i;
  2134.     sec_PKCS12SafeBag **keyList = NULL;
  2135.     SECOidTag bagType;
  2136.     if(!safeBags || !safeBags[0]) {
  2137. return NULL;
  2138.     }
  2139.     i = 0;
  2140.     while(safeBags[i]) {
  2141. bagType = SECOID_FindOIDTag(&(safeBags[i]->safeBagType));
  2142. switch(bagType) {
  2143.     case SEC_OID_PKCS12_V1_KEY_BAG_ID:
  2144.     case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
  2145. if(sec_pkcs12_add_item_to_bag_list(&keyList, safeBags[i])
  2146. != SECSuccess) {
  2147.     return NULL;
  2148. }
  2149. break;
  2150.     default:
  2151. break;
  2152. }
  2153. i++;
  2154.     }
  2155.     return keyList;
  2156. }
  2157. static SECStatus 
  2158. sec_pkcs12_validate_bags(sec_PKCS12SafeBag **safeBags, 
  2159.  SEC_PKCS12NicknameCollisionCallback nicknameCb,
  2160.  void *wincx)
  2161. {
  2162.     sec_PKCS12SafeBag **keyList;
  2163.     int i;
  2164.     if(!safeBags || !nicknameCb) {
  2165. return SECFailure;
  2166.     }
  2167.     if(!safeBags[0]) {
  2168. return SECSuccess;
  2169.     }
  2170.     keyList = sec_pkcs12_get_key_bags(safeBags);
  2171.     if(keyList) {
  2172. i = 0;
  2173. while(keyList[i]) {
  2174.     sec_PKCS12SafeBag **certList = sec_pkcs12_find_certs_for_key(
  2175. safeBags, keyList[i]);
  2176.     if(certList) {
  2177. int j = 0;
  2178. if(SECOID_FindOIDTag(&(keyList[i]->safeBagType)) == 
  2179. SEC_OID_PKCS12_V1_KEY_BAG_ID) {
  2180.     /* if it is an unencrypted private key then make sure
  2181.      * the attributes are propageted to the appropriate 
  2182.      * level 
  2183.      */
  2184.     if(sec_pkcs12_get_key_info(keyList[i]) != SECSuccess) {
  2185. keyList[i]->problem = PR_TRUE;
  2186. keyList[i]->error = SEC_ERROR_NO_MEMORY;
  2187. return SECFailure;
  2188.      }
  2189. }
  2190. sec_pkcs12_validate_key_by_cert(certList[0], keyList[i], wincx);
  2191. while(certList[j]) {
  2192.     certList[j]->hasKey = PR_TRUE;
  2193.     if(keyList[i]->problem) {
  2194. certList[j]->problem = PR_TRUE;
  2195. certList[j]->error = keyList[i]->error;
  2196.     } else {
  2197. sec_pkcs12_validate_cert(certList[j], keyList[i],
  2198.  nicknameCb, wincx);
  2199. if(certList[j]->problem) {
  2200.     keyList[i]->problem = certList[j]->problem;
  2201.     keyList[i]->error = certList[j]->error;
  2202. }
  2203.     }
  2204.     j++;
  2205. }
  2206.     }
  2207.     i++;
  2208. }
  2209.     }
  2210.     i = 0;
  2211.     while(safeBags[i]) {
  2212. if(!safeBags[i]->validated) {
  2213.     SECOidTag bagType = SECOID_FindOIDTag(&safeBags[i]->safeBagType);
  2214.     switch(bagType) {
  2215. case SEC_OID_PKCS12_V1_CERT_BAG_ID:
  2216.     sec_pkcs12_validate_cert(safeBags[i], NULL, nicknameCb, 
  2217.      wincx);
  2218.     break;
  2219. case SEC_OID_PKCS12_V1_KEY_BAG_ID:
  2220. case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
  2221.     safeBags[i]->noInstall = PR_TRUE;
  2222.     safeBags[i]->problem = PR_TRUE;
  2223.     safeBags[i]->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
  2224.     break;
  2225. default:
  2226.     safeBags[i]->noInstall = PR_TRUE;
  2227.     }
  2228. }
  2229. i++;
  2230.     }
  2231.     return SECSuccess;
  2232. }
  2233. SECStatus
  2234. SEC_PKCS12DecoderValidateBags(SEC_PKCS12DecoderContext *p12dcx,
  2235.       SEC_PKCS12NicknameCollisionCallback nicknameCb)
  2236. {
  2237.     SECStatus rv;
  2238.     int i, noInstallCnt, probCnt, bagCnt, errorVal = 0;
  2239.     if(!p12dcx || p12dcx->error) {
  2240. return SECFailure;
  2241.     }
  2242.     rv = sec_pkcs12_validate_bags(p12dcx->safeBags, nicknameCb, p12dcx->wincx);
  2243.     if(rv == SECSuccess) {
  2244. p12dcx->bagsVerified = PR_TRUE;
  2245.     }
  2246.     noInstallCnt = probCnt = bagCnt = 0;
  2247.     i = 0;
  2248.     while(p12dcx->safeBags[i]) {
  2249. bagCnt++;
  2250. if(p12dcx->safeBags[i]->noInstall) noInstallCnt++;
  2251. if(p12dcx->safeBags[i]->problem) {
  2252.     probCnt++;
  2253.     errorVal = p12dcx->safeBags[i]->error;
  2254. }
  2255. i++;
  2256.     }
  2257.     if(bagCnt == noInstallCnt) {
  2258. PORT_SetError(SEC_ERROR_PKCS12_DUPLICATE_DATA);
  2259. return SECFailure;
  2260.     }
  2261.     if(probCnt) {
  2262. PORT_SetError(errorVal);
  2263. return SECFailure;
  2264.     }
  2265.     return rv;
  2266. }
  2267. static SECItem *
  2268. sec_pkcs12_get_public_value_and_type(sec_PKCS12SafeBag *certBag,
  2269. KeyType *type, unsigned int *usage)
  2270. {
  2271.     SECKEYPublicKey *pubKey = NULL;
  2272.     CERTCertificate *cert = NULL;
  2273.     SECItem *pubValue;
  2274.     *type = nullKey;
  2275.     *usage = 0;
  2276.     if(!certBag) {
  2277. return NULL;
  2278.     }
  2279.     cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 
  2280. &certBag->safeBagContent.certBag->value.x509Cert,
  2281. NULL, PR_FALSE, PR_FALSE);
  2282.     if(!cert) {
  2283. return NULL;
  2284.     }
  2285.     *usage = cert->keyUsage;
  2286.     pubKey = CERT_ExtractPublicKey(cert);
  2287.     CERT_DestroyCertificate(cert);
  2288.     if(!pubKey) {
  2289. return NULL;
  2290.     }
  2291.     *type = pubKey->keyType;
  2292.     switch(pubKey->keyType) {
  2293. case dsaKey:
  2294.     pubValue = SECITEM_DupItem(&pubKey->u.dsa.publicValue);
  2295.     break;
  2296. case dhKey:
  2297.     pubValue = SECITEM_DupItem(&pubKey->u.dh.publicValue);
  2298.     break;
  2299. case rsaKey:
  2300.     pubValue = SECITEM_DupItem(&pubKey->u.rsa.modulus);
  2301.     break;
  2302. default:
  2303.     pubValue = NULL;
  2304.     }
  2305.     SECKEY_DestroyPublicKey(pubKey);
  2306.     return pubValue;
  2307. }
  2308. static SECStatus 
  2309. sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, 
  2310. void *wincx)
  2311. {
  2312.     sec_PKCS12SafeBag **keyList, **certList;
  2313.     int i;
  2314.     if(!safeBags) {
  2315. return SECFailure;
  2316.     }
  2317.     if(!safeBags[0]) {
  2318. return SECSuccess;
  2319.     }
  2320.     keyList = sec_pkcs12_get_key_bags(safeBags);
  2321.     if(keyList) {
  2322. i = 0;
  2323. while(keyList[i]) {
  2324.     SECStatus rv;
  2325.     SECItem *publicValue = NULL;
  2326.     KeyType keyType;
  2327.     unsigned int keyUsage;
  2328.     if(keyList[i]->problem) {
  2329. goto next_key_bag;
  2330.     }
  2331.     certList = sec_pkcs12_find_certs_for_key(safeBags,
  2332.      keyList[i]);
  2333.     if(certList) {
  2334. publicValue = sec_pkcs12_get_public_value_and_type(certList[0],
  2335. &keyType, &keyUsage);
  2336.     }
  2337.     rv = sec_pkcs12_add_key(keyList[i], publicValue, keyType, keyUsage,
  2338. wincx);
  2339.     if(publicValue) {
  2340. SECITEM_FreeItem(publicValue, PR_TRUE);
  2341.     }
  2342.     if(rv != SECSuccess) {
  2343. PORT_SetError(keyList[i]->error);
  2344. return SECFailure;
  2345.     }
  2346.     if(certList) {
  2347. int j = 0;
  2348. while(certList[j]) {
  2349.     SECStatus certRv;
  2350.     if(rv != SECSuccess) {
  2351. certList[j]->problem = keyList[i]->problem;
  2352. certList[j]->error = keyList[i]->error;
  2353. certList[j]->noInstall = PR_TRUE;
  2354. goto next_cert_bag;
  2355.     }
  2356.     certRv = sec_pkcs12_add_cert(certList[j], 
  2357.  certList[j]->hasKey, wincx);
  2358.     if(certRv != SECSuccess) {
  2359. keyList[i]->problem = certList[j]->problem;
  2360. keyList[i]->error = certList[j]->error;
  2361. PORT_SetError(certList[j]->error);
  2362. return SECFailure;
  2363.     }
  2364. next_cert_bag:
  2365.     j++;
  2366. }
  2367.     }
  2368. next_key_bag:
  2369.     i++;
  2370. }
  2371.     }
  2372.     i = 0;
  2373.     while(safeBags[i]) {
  2374. if(!safeBags[i]->installed) {
  2375.     SECStatus rv;
  2376.     SECOidTag bagType = SECOID_FindOIDTag(&(safeBags[i]->safeBagType));
  2377.     switch(bagType) {
  2378. case SEC_OID_PKCS12_V1_CERT_BAG_ID:
  2379.     rv = sec_pkcs12_add_cert(safeBags[i], safeBags[i]->hasKey,
  2380.      wincx);
  2381.     if(rv != SECSuccess) {
  2382. PORT_SetError(safeBags[i]->error);
  2383. return SECFailure;
  2384.     }
  2385.     break;
  2386. case SEC_OID_PKCS12_V1_KEY_BAG_ID:
  2387. case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
  2388. default:
  2389.     break;
  2390.     }
  2391. }
  2392. i++;
  2393.     }
  2394.     return SECSuccess;
  2395. }
  2396. SECStatus
  2397. SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx)
  2398. {
  2399.     if(!p12dcx || p12dcx->error) {
  2400. return SECFailure;
  2401.     }
  2402.     if(!p12dcx->bagsVerified) {
  2403. return SECFailure;
  2404.     }
  2405.     return sec_pkcs12_install_bags(p12dcx->safeBags, p12dcx->wincx);
  2406. }
  2407. static SECStatus
  2408. sec_pkcs12_decoder_append_bag_to_context(SEC_PKCS12DecoderContext *p12dcx,
  2409.  sec_PKCS12SafeBag *bag)
  2410. {
  2411.     if(!p12dcx || p12dcx->error) {
  2412. return SECFailure;
  2413.     }
  2414.     if(!p12dcx->safeBagCount) {
  2415. p12dcx->safeBags = (sec_PKCS12SafeBag **)PORT_ArenaZAlloc(p12dcx->arena, 
  2416.     sizeof(sec_PKCS12SafeBag *) * 2);
  2417.     } else {
  2418. p12dcx->safeBags = 
  2419.   (sec_PKCS12SafeBag **)PORT_ArenaGrow(p12dcx->arena, p12dcx->safeBags,
  2420.      (p12dcx->safeBagCount + 1) * sizeof(sec_PKCS12SafeBag *),
  2421.      (p12dcx->safeBagCount + 2) * sizeof(sec_PKCS12SafeBag *));
  2422.     }
  2423.     if(!p12dcx->safeBags) {
  2424. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2425. return SECFailure;
  2426.     }
  2427.     p12dcx->safeBags[p12dcx->safeBagCount] = bag;
  2428.     p12dcx->safeBags[p12dcx->safeBagCount+1] = NULL;
  2429.     p12dcx->safeBagCount++;
  2430.     return SECSuccess;
  2431. }
  2432. static sec_PKCS12SafeBag *
  2433. sec_pkcs12_decoder_convert_old_key(SEC_PKCS12DecoderContext *p12dcx,
  2434.    void *key, PRBool isEspvk)
  2435. {
  2436.     sec_PKCS12SafeBag *keyBag;
  2437.     SECOidData *oid;
  2438.     SECOidTag keyTag;
  2439.     SECItem *keyID, *nickName, *newNickName;
  2440.     if(!p12dcx || p12dcx->error || !key) {
  2441. return NULL;
  2442.     }
  2443.     newNickName =(SECItem *)PORT_ArenaZAlloc(p12dcx->arena, sizeof(SECItem));
  2444.     keyBag = (sec_PKCS12SafeBag *)PORT_ArenaZAlloc(p12dcx->arena, 
  2445.    sizeof(sec_PKCS12SafeBag));
  2446.     if(!keyBag || !newNickName) {
  2447. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2448. return NULL;
  2449.     }
  2450.     keyBag->swapUnicodeBytes = p12dcx->swapUnicodeBytes;
  2451.     keyBag->slot = p12dcx->slot;
  2452.     keyBag->arena = p12dcx->arena;
  2453.     keyBag->pwitem = p12dcx->pwitem;
  2454.     keyBag->oldBagType = PR_TRUE;
  2455.     keyTag = (isEspvk) ? SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID :
  2456.  SEC_OID_PKCS12_V1_KEY_BAG_ID;
  2457.     oid = SECOID_FindOIDByTag(keyTag);
  2458.     if(!oid) {
  2459. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2460. return NULL;
  2461.     }
  2462.     if(SECITEM_CopyItem(p12dcx->arena, &keyBag->safeBagType, &oid->oid) 
  2463. != SECSuccess) {
  2464. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2465. return NULL;
  2466.     }
  2467.     if(isEspvk) {
  2468. SEC_PKCS12ESPVKItem *espvk = (SEC_PKCS12ESPVKItem *)key;
  2469. keyBag->safeBagContent.pkcs8ShroudedKeyBag  = 
  2470. espvk->espvkCipherText.pkcs8KeyShroud;
  2471. nickName = &(espvk->espvkData.uniNickName); 
  2472. if(!espvk->espvkData.assocCerts || !espvk->espvkData.assocCerts[0]) {
  2473.     PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
  2474.     return NULL;
  2475. }
  2476. keyID = &espvk->espvkData.assocCerts[0]->digest;
  2477.     } else {
  2478. SEC_PKCS12PrivateKey *pk = (SEC_PKCS12PrivateKey *)key;
  2479. keyBag->safeBagContent.pkcs8KeyBag = &pk->pkcs8data;
  2480. nickName= &(pk->pvkData.uniNickName);
  2481. if(!pk->pvkData.assocCerts || !pk->pvkData.assocCerts[0]) {
  2482.     PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
  2483.     return NULL;
  2484. }
  2485. keyID = &pk->pvkData.assocCerts[0]->digest;
  2486.     }
  2487.     if(nickName->len) {
  2488. if(nickName->len >= 2) {
  2489.     if(nickName->data[0] && nickName->data[1]) {
  2490. if(!sec_pkcs12_convert_item_to_unicode(p12dcx->arena, newNickName, 
  2491. nickName, PR_FALSE, PR_FALSE, PR_TRUE)) {
  2492.     PORT_SetError(SEC_ERROR_NO_MEMORY);
  2493.     return NULL;
  2494. }
  2495. nickName = newNickName;
  2496.     } else if(nickName->data[0] && !nickName->data[1]) {
  2497. unsigned int j = 0;
  2498. unsigned char t;
  2499. for(j = 0; j < nickName->len; j+=2) {
  2500.     t = nickName->data[j+1];
  2501.     nickName->data[j+1] = nickName->data[j];
  2502.     nickName->data[j] = t;
  2503. }
  2504.     }
  2505. } else {
  2506.     if(!sec_pkcs12_convert_item_to_unicode(p12dcx->arena, newNickName, 
  2507. nickName, PR_FALSE, PR_FALSE, PR_TRUE)) {
  2508. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2509. return NULL;
  2510.     }
  2511.     nickName = newNickName;
  2512. }
  2513.     }
  2514.     if(sec_pkcs12_decoder_set_attribute_value(keyBag,
  2515.       SEC_OID_PKCS9_FRIENDLY_NAME,
  2516.       nickName) != SECSuccess) {
  2517. return NULL;
  2518.     }
  2519.     if(sec_pkcs12_decoder_set_attribute_value(keyBag,SEC_OID_PKCS9_LOCAL_KEY_ID,
  2520. keyID) != SECSuccess) {
  2521. return NULL;
  2522.     }
  2523.     return keyBag;
  2524. }
  2525. static sec_PKCS12SafeBag *
  2526. sec_pkcs12_decoder_create_cert(SEC_PKCS12DecoderContext *p12dcx,
  2527.        SECItem *derCert)
  2528. {
  2529.     sec_PKCS12SafeBag *certBag;
  2530.     SECOidData *oid;
  2531.     SGNDigestInfo *digest;
  2532.     SECItem *keyId;
  2533.     SECStatus rv;
  2534.     if(!p12dcx || p12dcx->error || !derCert) {
  2535. return NULL;
  2536.     }
  2537.     keyId = (SECItem *)PORT_ArenaZAlloc(p12dcx->arena, sizeof(SECItem));
  2538.     if(!keyId) {
  2539. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2540. return NULL;
  2541.     }
  2542.     digest = sec_pkcs12_compute_thumbprint(derCert);
  2543.     if(!digest) {
  2544. return NULL;
  2545.     }
  2546.     rv = SECITEM_CopyItem(p12dcx->arena, keyId, &digest->digest);
  2547.     SGN_DestroyDigestInfo(digest);
  2548.     if(rv != SECSuccess) {
  2549. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2550. return NULL;
  2551.     }
  2552.     oid = SECOID_FindOIDByTag(SEC_OID_PKCS12_V1_CERT_BAG_ID);
  2553.     certBag = (sec_PKCS12SafeBag *)PORT_ArenaZAlloc(p12dcx->arena, 
  2554.     sizeof(sec_PKCS12SafeBag));
  2555.     if(!certBag || !oid || (SECITEM_CopyItem(p12dcx->arena, 
  2556. &certBag->safeBagType, &oid->oid) != SECSuccess)) {
  2557. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2558. return NULL;
  2559.     }
  2560.     certBag->slot = p12dcx->slot;
  2561.     certBag->pwitem = p12dcx->pwitem;
  2562.     certBag->swapUnicodeBytes = p12dcx->swapUnicodeBytes;
  2563.     certBag->arena = p12dcx->arena;
  2564.     oid = SECOID_FindOIDByTag(SEC_OID_PKCS9_X509_CERT);
  2565.     certBag->safeBagContent.certBag = 
  2566.         (sec_PKCS12CertBag *)PORT_ArenaZAlloc(p12dcx->arena, 
  2567.       sizeof(sec_PKCS12CertBag));
  2568.     if(!certBag->safeBagContent.certBag || !oid ||
  2569. (SECITEM_CopyItem(p12dcx->arena, 
  2570.  &certBag->safeBagContent.certBag->bagID,
  2571.  &oid->oid) != SECSuccess)) {
  2572. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2573. return NULL;
  2574.     }
  2575.       
  2576.     if(SECITEM_CopyItem(p12dcx->arena, 
  2577.  &(certBag->safeBagContent.certBag->value.x509Cert),
  2578.  derCert) != SECSuccess) {
  2579. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2580. return NULL;
  2581.     }
  2582.     if(sec_pkcs12_decoder_set_attribute_value(certBag, SEC_OID_PKCS9_LOCAL_KEY_ID,
  2583. keyId) != SECSuccess) {
  2584. return NULL;
  2585.     }
  2586.     return certBag;
  2587. }
  2588. static sec_PKCS12SafeBag **
  2589. sec_pkcs12_decoder_convert_old_cert(SEC_PKCS12DecoderContext *p12dcx,
  2590.     SEC_PKCS12CertAndCRL *oldCert)
  2591. {
  2592.     sec_PKCS12SafeBag **certList;
  2593.     SECItem **derCertList;
  2594.     int i, j;
  2595.     if(!p12dcx || p12dcx->error || !oldCert) {
  2596. return NULL;
  2597.     }
  2598.     derCertList = SEC_PKCS7GetCertificateList(&oldCert->value.x509->certOrCRL);
  2599.     if(!derCertList) {
  2600. return NULL;
  2601.     }
  2602.     i = 0;
  2603.     while(derCertList[i]) i++;
  2604.     certList = (sec_PKCS12SafeBag **)PORT_ArenaZAlloc(p12dcx->arena, 
  2605. (i + 1) * sizeof(sec_PKCS12SafeBag *));
  2606.     if(!certList) {
  2607. PORT_SetError(SEC_ERROR_NO_MEMORY);
  2608. return NULL;
  2609.     }
  2610.     for(j = 0; j < i; j++) {
  2611. certList[j] = sec_pkcs12_decoder_create_cert(p12dcx, derCertList[j]);
  2612. if(!certList[j]) {
  2613.     return NULL;
  2614. }
  2615.     }
  2616.     return certList;
  2617. }   
  2618. static SECStatus
  2619. sec_pkcs12_decoder_convert_old_key_and_certs(SEC_PKCS12DecoderContext *p12dcx,
  2620.      void *oldKey, PRBool isEspvk,
  2621.      SEC_PKCS12SafeContents *safe,
  2622.      SEC_PKCS12Baggage *baggage)
  2623. {
  2624.     sec_PKCS12SafeBag *key, **certList;
  2625.     SEC_PKCS12CertAndCRL *oldCert;
  2626.     SEC_PKCS12PVKSupportingData *pvkData;
  2627.     int i;
  2628.     SECItem *keyName;
  2629.     if(!p12dcx || !oldKey) {
  2630. return SECFailure;
  2631.     }
  2632.     if(isEspvk) {
  2633. pvkData = &((SEC_PKCS12ESPVKItem *)(oldKey))->espvkData;
  2634.     } else {
  2635. pvkData = &((SEC_PKCS12PrivateKey *)(oldKey))->pvkData;
  2636.     }
  2637.     if(!pvkData->assocCerts || !pvkData->assocCerts[0]) {
  2638. PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
  2639. return SECFailure;
  2640.     }
  2641.     oldCert = (SEC_PKCS12CertAndCRL *)sec_pkcs12_find_object(safe, baggage, 
  2642.      SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID, NULL,
  2643.      pvkData->assocCerts[0]);
  2644.     if(!oldCert) {
  2645. PORT_SetError(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE);
  2646. return SECFailure;
  2647.     }
  2648.     key = sec_pkcs12_decoder_convert_old_key(p12dcx,oldKey, isEspvk);
  2649.     certList = sec_pkcs12_decoder_convert_old_cert(p12dcx, oldCert);
  2650.     if(!key || !certList) {
  2651. return SECFailure;
  2652.     }
  2653.     if(sec_pkcs12_decoder_append_bag_to_context(p12dcx, key) != SECSuccess) {
  2654. return SECFailure;
  2655.     }
  2656.     keyName = sec_pkcs12_get_nickname(key);
  2657.     if(!keyName) {
  2658. return SECFailure;
  2659.     }
  2660.     i = 0;
  2661.     while(certList[i]) {
  2662. if(sec_pkcs12_decoder_append_bag_to_context(p12dcx, certList[i]) 
  2663. != SECSuccess) {
  2664.     return SECFailure;
  2665. }
  2666. i++;
  2667.     }
  2668.     certList = sec_pkcs12_find_certs_for_key(p12dcx->safeBags, key);
  2669.     if(!certList) {
  2670. return SECFailure;
  2671.     }
  2672.     i = 0;
  2673.     while(certList[i] != 0) {
  2674. if(sec_pkcs12_set_nickname(certList[i], keyName) != SECSuccess) {
  2675.     return SECFailure;
  2676. }
  2677. i++;
  2678.     }
  2679.     return SECSuccess;
  2680. }
  2681. static SECStatus
  2682. sec_pkcs12_decoder_convert_old_safe_to_bags(SEC_PKCS12DecoderContext *p12dcx,
  2683.     SEC_PKCS12SafeContents *safe,
  2684.     SEC_PKCS12Baggage *baggage)
  2685. {
  2686.     SECStatus rv;
  2687.     if(!p12dcx || p12dcx->error) {
  2688. return SECFailure;
  2689.     }
  2690.     if(safe && safe->contents) {
  2691. int i = 0;
  2692. while(safe->contents[i] != NULL) {
  2693.     if(SECOID_FindOIDTag(&safe->contents[i]->safeBagType) 
  2694. == SEC_OID_PKCS12_KEY_BAG_ID) {
  2695. int j = 0;
  2696. SEC_PKCS12PrivateKeyBag *privBag = 
  2697. safe->contents[i]->safeContent.keyBag;
  2698. while(privBag->privateKeys[j] != NULL) {
  2699.     SEC_PKCS12PrivateKey *pk = privBag->privateKeys[j];
  2700.     rv = sec_pkcs12_decoder_convert_old_key_and_certs(p12dcx,pk,
  2701. PR_FALSE, safe, baggage);
  2702.     if(rv != SECSuccess) {
  2703. goto loser;
  2704.     }
  2705.     j++;
  2706. }
  2707.     }
  2708.     i++;
  2709. }
  2710.     }
  2711.     if(baggage && baggage->bags) {
  2712. int i = 0;
  2713. while(baggage->bags[i] != NULL) {
  2714.     SEC_PKCS12BaggageItem *bag = baggage->bags[i];
  2715.     int j = 0;
  2716.     if(!bag->espvks) {
  2717. i++;
  2718. continue;
  2719.     }
  2720.     while(bag->espvks[j] != NULL) {
  2721. SEC_PKCS12ESPVKItem *espvk = bag->espvks[j];
  2722. rv = sec_pkcs12_decoder_convert_old_key_and_certs(p12dcx, espvk,
  2723. PR_TRUE, safe, baggage);
  2724. if(rv != SECSuccess) {
  2725.     goto loser;
  2726. }
  2727. j++;
  2728.     }
  2729.     i++;
  2730. }
  2731.     }
  2732.     return SECSuccess;
  2733. loser:
  2734.     return SECFailure;
  2735. }
  2736. SEC_PKCS12DecoderContext *
  2737. sec_PKCS12ConvertOldSafeToNew(PRArenaPool *arena, PK11SlotInfo *slot, 
  2738.       PRBool swapUnicode, SECItem *pwitem,
  2739.       void *wincx, SEC_PKCS12SafeContents *safe,
  2740.       SEC_PKCS12Baggage *baggage)
  2741. {
  2742.     SEC_PKCS12DecoderContext *p12dcx;
  2743.     if(!arena || !slot || !pwitem) {
  2744. return NULL;
  2745.     }
  2746.     if(!safe && !baggage) {
  2747. return NULL;
  2748.     }
  2749.     p12dcx = (SEC_PKCS12DecoderContext *)PORT_ArenaZAlloc(arena, 
  2750.     sizeof(SEC_PKCS12DecoderContext));
  2751.     if(!p12dcx) {
  2752. return NULL;
  2753.     }
  2754.     p12dcx->arena = arena;
  2755.     p12dcx->slot = slot;
  2756.     p12dcx->wincx = wincx;
  2757.     p12dcx->error = PR_FALSE;
  2758.     p12dcx->swapUnicodeBytes = swapUnicode; 
  2759.     p12dcx->pwitem = pwitem;
  2760.     
  2761.     if(sec_pkcs12_decoder_convert_old_safe_to_bags(p12dcx, safe, baggage) 
  2762. != SECSuccess) {
  2763. p12dcx->error = PR_TRUE;
  2764. return NULL;
  2765.     }
  2766.     return p12dcx;
  2767. }