PageRenderTime 59ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

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

http://github.com/zpao/v8monkey
C | 3581 lines | 2568 code | 500 blank | 513 comment | 611 complexity | 440184944dbc8980c185cb61abeecce8 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD

Large files files are truncated, but you can click here to view the full file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * 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 filter 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);

Large files files are truncated, but you can click here to view the full file