PageRenderTime 80ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

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

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