PageRenderTime 76ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/pkcs12/p12d.c

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