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

/security/nss/lib/libpkix/pkix/top/pkix_validate.c

http://github.com/zpao/v8monkey
C | 1404 lines | 827 code | 191 blank | 386 comment | 77 complexity | e122c38f113215b5fc747c313b5b015a 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
  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 PKIX-C library.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Sun Microsystems, Inc.
  18. * Portions created by the Initial Developer are
  19. * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Sun Microsystems, Inc.
  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. /*
  38. * pkix_validate.c
  39. *
  40. * Top level validateChain function
  41. *
  42. */
  43. #include "pkix_validate.h"
  44. /* --Private-Functions-------------------------------------------- */
  45. /*
  46. * FUNCTION: pkix_AddToVerifyLog
  47. * DESCRIPTION:
  48. *
  49. * This function returns immediately if the address for the VerifyNode tree
  50. * pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode
  51. * from the Cert pointed to by "cert" and the Error pointed to by "error",
  52. * and inserts it at the depth in the VerifyNode tree determined by "depth". A
  53. * depth of zero means that this function creates the root node of a new tree.
  54. *
  55. * Note: this function does not include the means of choosing among branches
  56. * of a tree. It is intended for non-branching trees, that is, where each
  57. * parent node has only a single child node.
  58. *
  59. * PARAMETERS:
  60. * "cert"
  61. * The address of the Cert to be included in the new VerifyNode. Must be
  62. * non-NULL.
  63. * "depth"
  64. * The UInt32 value of the depth.
  65. * "error"
  66. * The address of the Error to be included in the new VerifyNode.
  67. * "pVerifyTree"
  68. * The address of the VerifyNode tree into which the created VerifyNode
  69. * is to be inserted. The node is not created if VerifyTree is NULL.
  70. * "plContext"
  71. * Platform-specific context pointer.
  72. * THREAD SAFETY:
  73. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  74. * RETURNS:
  75. * Returns NULL if the function succeeds.
  76. * Returns a Validate Error if the function fails in a non-fatal way.
  77. * Returns a Fatal Error if the function fails in an unrecoverable way.
  78. */
  79. static PKIX_Error *
  80. pkix_AddToVerifyLog(
  81. PKIX_PL_Cert *cert,
  82. PKIX_UInt32 depth,
  83. PKIX_Error *error,
  84. PKIX_VerifyNode **pVerifyTree,
  85. void *plContext)
  86. {
  87. PKIX_VerifyNode *verifyNode = NULL;
  88. PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog");
  89. PKIX_NULLCHECK_ONE(cert);
  90. if (pVerifyTree) { /* nothing to do if no address given for log */
  91. PKIX_CHECK(pkix_VerifyNode_Create
  92. (cert, depth, error, &verifyNode, plContext),
  93. PKIX_VERIFYNODECREATEFAILED);
  94. if (depth == 0) {
  95. /* We just created the root node */
  96. *pVerifyTree = verifyNode;
  97. } else {
  98. PKIX_CHECK(pkix_VerifyNode_AddToChain
  99. (*pVerifyTree, verifyNode, plContext),
  100. PKIX_VERIFYNODEADDTOCHAINFAILED);
  101. }
  102. }
  103. cleanup:
  104. PKIX_RETURN(VALIDATE);
  105. }
  106. /*
  107. * FUNCTION: pkix_CheckCert
  108. * DESCRIPTION:
  109. *
  110. * Checks whether the Cert pointed to by "cert" successfully validates
  111. * using the List of CertChainCheckers pointed to by "checkers". If the
  112. * certificate does not validate, an Error pointer is returned.
  113. *
  114. * This function should be called initially with the UInt32 pointed to by
  115. * "pCheckerIndex" containing zero, and the pointer at "pNBIOContext"
  116. * containing NULL. If a checker does non-blocking I/O, this function will
  117. * return with the index of that checker stored at "pCheckerIndex" and a
  118. * platform-dependent non-blocking I/O context stored at "pNBIOContext".
  119. * A subsequent call to this function with those values intact will allow the
  120. * checking to resume where it left off. This should be repeated until the
  121. * function returns with NULL stored at "pNBIOContext".
  122. *
  123. * PARAMETERS:
  124. * "cert"
  125. * Address of Cert to validate. Must be non-NULL.
  126. * "checkers"
  127. * List of CertChainCheckers which must each validate the certificate.
  128. * Must be non-NULL.
  129. * "checkedExtOIDs"
  130. * List of PKIX_PL_OID that has been processed. If called from building
  131. * chain, it is the list of critical extension OIDs that has been
  132. * processed prior to validation. May be NULL.
  133. * "pCheckerIndex"
  134. * Address at which is stored the the index, within the List "checkers",
  135. * of a checker whose processing was interrupted by non-blocking I/O.
  136. * Must be non-NULL.
  137. * "pNBIOContext"
  138. * Address at which is stored platform-specific non-blocking I/O context.
  139. * Must be non-NULL.
  140. * "plContext"
  141. * Platform-specific context pointer.
  142. * THREAD SAFETY:
  143. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  144. * RETURNS:
  145. * Returns NULL if the function succeeds.
  146. * Returns a Validate Error if the function fails in a non-fatal way.
  147. * Returns a Fatal Error if the function fails in an unrecoverable way.
  148. */
  149. static PKIX_Error *
  150. pkix_CheckCert(
  151. PKIX_PL_Cert *cert,
  152. PKIX_List *checkers,
  153. PKIX_List *checkedExtOIDsList,
  154. PKIX_UInt32 *pCheckerIndex,
  155. void **pNBIOContext,
  156. void *plContext)
  157. {
  158. PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
  159. PKIX_CertChainChecker *checker = NULL;
  160. PKIX_List *unresCritExtOIDs = NULL;
  161. PKIX_UInt32 numCheckers;
  162. PKIX_UInt32 numUnresCritExtOIDs = 0;
  163. PKIX_UInt32 checkerIndex = 0;
  164. void *nbioContext = NULL;
  165. PKIX_ENTER(VALIDATE, "pkix_CheckCert");
  166. PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext);
  167. nbioContext = *pNBIOContext;
  168. *pNBIOContext = NULL; /* prepare for case of error exit */
  169. PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
  170. (cert, &unresCritExtOIDs, plContext),
  171. PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
  172. PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
  173. PKIX_LISTGETLENGTHFAILED);
  174. for (checkerIndex = *pCheckerIndex;
  175. checkerIndex < numCheckers;
  176. checkerIndex++) {
  177. PKIX_CHECK(PKIX_List_GetItem
  178. (checkers,
  179. checkerIndex,
  180. (PKIX_PL_Object **)&checker,
  181. plContext),
  182. PKIX_LISTGETITEMFAILED);
  183. PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
  184. (checker, &checkerCheck, plContext),
  185. PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);
  186. PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs,
  187. &nbioContext, plContext),
  188. PKIX_CERTCHAINCHECKERCHECKFAILED);
  189. if (nbioContext != NULL) {
  190. *pCheckerIndex = checkerIndex;
  191. *pNBIOContext = nbioContext;
  192. goto cleanup;
  193. }
  194. PKIX_DECREF(checker);
  195. }
  196. if (unresCritExtOIDs){
  197. #ifdef PKIX_VALIDATEDEBUG
  198. {
  199. PKIX_PL_String *oidString = NULL;
  200. PKIX_UInt32 length;
  201. char *oidAscii = NULL;
  202. PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext,
  203. PKIX_LISTTOSTRINGFAILED);
  204. PKIX_CHECK(PKIX_PL_String_GetEncoded
  205. (oidString,
  206. PKIX_ESCASCII,
  207. (void **) &oidAscii,
  208. &length,
  209. plContext),
  210. PKIX_STRINGGETENCODEDFAILED);
  211. PKIX_VALIDATE_DEBUG_ARG
  212. ("unrecognized critical extension OIDs:"
  213. " %s\n", oidAscii);
  214. PKIX_DECREF(oidString);
  215. PKIX_PL_Free(oidAscii, plContext);
  216. }
  217. #endif
  218. if (checkedExtOIDsList != NULL) {
  219. /* Take out OID's that had been processed, if any */
  220. PKIX_CHECK(pkix_List_RemoveItems
  221. (unresCritExtOIDs,
  222. checkedExtOIDsList,
  223. plContext),
  224. PKIX_LISTREMOVEITEMSFAILED);
  225. }
  226. PKIX_CHECK(PKIX_List_GetLength
  227. (unresCritExtOIDs, &numUnresCritExtOIDs, plContext),
  228. PKIX_LISTGETLENGTHFAILED);
  229. if (numUnresCritExtOIDs != 0){
  230. PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION);
  231. }
  232. }
  233. cleanup:
  234. PKIX_DECREF(checker);
  235. PKIX_DECREF(unresCritExtOIDs);
  236. PKIX_RETURN(VALIDATE);
  237. }
  238. /*
  239. * FUNCTION: pkix_InitializeCheckers
  240. * DESCRIPTION:
  241. *
  242. * Creates several checkers and initializes them with values derived from the
  243. * TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by
  244. * "procParams", and the number of Certs in the Chain, represented by
  245. * "numCerts". The List of checkers is stored at "pCheckers".
  246. *
  247. * PARAMETERS:
  248. * "anchor"
  249. * Address of TrustAnchor used to initialize the SignatureChecker and
  250. * NameChainingChecker. Must be non-NULL.
  251. * "procParams"
  252. * Address of ProcessingParams used to initialize the ExpirationChecker
  253. * and TargetCertChecker. Must be non-NULL.
  254. * "numCerts"
  255. * Number of certificates in the CertChain.
  256. * "pCheckers"
  257. * Address where object pointer will be stored. Must be non-NULL.
  258. * "plContext"
  259. * Platform-specific context pointer.
  260. * THREAD SAFETY:
  261. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  262. * RETURNS:
  263. * Returns NULL if the function succeeds.
  264. * Returns a Validate Error if the function fails in a non-fatal way.
  265. * Returns a Fatal Error if the function fails in an unrecoverable way.
  266. */
  267. static PKIX_Error *
  268. pkix_InitializeCheckers(
  269. PKIX_TrustAnchor *anchor,
  270. PKIX_ProcessingParams *procParams,
  271. PKIX_UInt32 numCerts,
  272. PKIX_List **pCheckers,
  273. void *plContext)
  274. {
  275. PKIX_CertChainChecker *targetCertChecker = NULL;
  276. PKIX_CertChainChecker *expirationChecker = NULL;
  277. PKIX_CertChainChecker *nameChainingChecker = NULL;
  278. PKIX_CertChainChecker *nameConstraintsChecker = NULL;
  279. PKIX_CertChainChecker *basicConstraintsChecker = NULL;
  280. PKIX_CertChainChecker *policyChecker = NULL;
  281. PKIX_CertChainChecker *sigChecker = NULL;
  282. PKIX_CertChainChecker *defaultCrlChecker = NULL;
  283. PKIX_CertChainChecker *userChecker = NULL;
  284. PKIX_PL_X500Name *trustedCAName = NULL;
  285. PKIX_PL_PublicKey *trustedPubKey = NULL;
  286. PKIX_List *checkers = NULL;
  287. PKIX_PL_Date *testDate = NULL;
  288. PKIX_CertSelector *certSelector = NULL;
  289. PKIX_PL_Cert *trustedCert = NULL;
  290. PKIX_PL_CertNameConstraints *trustedNC = NULL;
  291. PKIX_List *initialPolicies = NULL;
  292. PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
  293. PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
  294. PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
  295. PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
  296. PKIX_List *userCheckersList = NULL;
  297. PKIX_List *certStores = NULL;
  298. PKIX_UInt32 numCertCheckers = 0;
  299. PKIX_UInt32 i;
  300. PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers");
  301. PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers);
  302. PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
  303. PKIX_LISTCREATEFAILED);
  304. /*
  305. * The TrustAnchor may have been created using CreateWithCert
  306. * (in which case GetCAPublicKey and GetCAName will return NULL)
  307. * or may have been created using CreateWithNameKeyPair (in which
  308. * case GetTrustedCert will return NULL. So we call GetTrustedCert
  309. * and populate trustedPubKey and trustedCAName accordingly.
  310. */
  311. PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
  312. (anchor, &trustedCert, plContext),
  313. PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  314. if (trustedCert){
  315. PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
  316. (trustedCert, &trustedPubKey, plContext),
  317. PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
  318. PKIX_CHECK(PKIX_PL_Cert_GetSubject
  319. (trustedCert, &trustedCAName, plContext),
  320. PKIX_CERTGETSUBJECTFAILED);
  321. } else {
  322. PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey
  323. (anchor, &trustedPubKey, plContext),
  324. PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED);
  325. PKIX_CHECK(PKIX_TrustAnchor_GetCAName
  326. (anchor, &trustedCAName, plContext),
  327. PKIX_TRUSTANCHORGETCANAMEFAILED);
  328. }
  329. PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName);
  330. PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
  331. (anchor, &trustedNC, plContext),
  332. PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);
  333. PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
  334. (procParams, &certSelector, plContext),
  335. PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
  336. PKIX_CHECK(PKIX_ProcessingParams_GetDate
  337. (procParams, &testDate, plContext),
  338. PKIX_PROCESSINGPARAMSGETDATEFAILED);
  339. PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
  340. (procParams, &initialPolicies, plContext),
  341. PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);
  342. PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
  343. (procParams, &policyQualifiersRejected, plContext),
  344. PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);
  345. PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
  346. (procParams, &initialPolicyMappingInhibit, plContext),
  347. PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);
  348. PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
  349. (procParams, &initialAnyPolicyInhibit, plContext),
  350. PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);
  351. PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
  352. (procParams, &initialExplicitPolicy, plContext),
  353. PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);
  354. PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
  355. (procParams, &certStores, plContext),
  356. PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
  357. PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
  358. (procParams, &userCheckersList, plContext),
  359. PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
  360. /* now, initialize all the checkers */
  361. PKIX_CHECK(pkix_TargetCertChecker_Initialize
  362. (certSelector, numCerts, &targetCertChecker, plContext),
  363. PKIX_TARGETCERTCHECKERINITIALIZEFAILED);
  364. PKIX_CHECK(pkix_ExpirationChecker_Initialize
  365. (testDate, &expirationChecker, plContext),
  366. PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
  367. PKIX_CHECK(pkix_NameChainingChecker_Initialize
  368. (trustedCAName, &nameChainingChecker, plContext),
  369. PKIX_NAMECHAININGCHECKERINITIALIZEFAILED);
  370. PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
  371. (trustedNC, numCerts, &nameConstraintsChecker, plContext),
  372. PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);
  373. PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize
  374. (numCerts, &basicConstraintsChecker, plContext),
  375. PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED);
  376. PKIX_CHECK(pkix_PolicyChecker_Initialize
  377. (initialPolicies,
  378. policyQualifiersRejected,
  379. initialPolicyMappingInhibit,
  380. initialExplicitPolicy,
  381. initialAnyPolicyInhibit,
  382. numCerts,
  383. &policyChecker,
  384. plContext),
  385. PKIX_POLICYCHECKERINITIALIZEFAILED);
  386. PKIX_CHECK(pkix_SignatureChecker_Initialize
  387. (trustedPubKey, numCerts, &sigChecker, plContext),
  388. PKIX_SIGNATURECHECKERINITIALIZEFAILED);
  389. if (userCheckersList != NULL) {
  390. PKIX_CHECK(PKIX_List_GetLength
  391. (userCheckersList, &numCertCheckers, plContext),
  392. PKIX_LISTGETLENGTHFAILED);
  393. for (i = 0; i < numCertCheckers; i++) {
  394. PKIX_CHECK(PKIX_List_GetItem
  395. (userCheckersList,
  396. i,
  397. (PKIX_PL_Object **) &userChecker,
  398. plContext),
  399. PKIX_LISTGETITEMFAILED);
  400. PKIX_CHECK(PKIX_List_AppendItem
  401. (checkers,
  402. (PKIX_PL_Object *)userChecker,
  403. plContext),
  404. PKIX_LISTAPPENDITEMFAILED);
  405. PKIX_DECREF(userChecker);
  406. }
  407. }
  408. PKIX_CHECK(PKIX_List_AppendItem
  409. (checkers, (PKIX_PL_Object *)targetCertChecker, plContext),
  410. PKIX_LISTAPPENDITEMFAILED);
  411. PKIX_CHECK(PKIX_List_AppendItem
  412. (checkers, (PKIX_PL_Object *)expirationChecker, plContext),
  413. PKIX_LISTAPPENDITEMFAILED);
  414. PKIX_CHECK(PKIX_List_AppendItem
  415. (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext),
  416. PKIX_LISTAPPENDITEMFAILED);
  417. PKIX_CHECK(PKIX_List_AppendItem
  418. (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext),
  419. PKIX_LISTAPPENDITEMFAILED);
  420. PKIX_CHECK(PKIX_List_AppendItem
  421. (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext),
  422. PKIX_LISTAPPENDITEMFAILED);
  423. PKIX_CHECK(PKIX_List_AppendItem
  424. (checkers, (PKIX_PL_Object *)policyChecker, plContext),
  425. PKIX_LISTAPPENDITEMFAILED);
  426. PKIX_CHECK(PKIX_List_AppendItem
  427. (checkers, (PKIX_PL_Object *)sigChecker, plContext),
  428. PKIX_LISTAPPENDITEMFAILED);
  429. *pCheckers = checkers;
  430. cleanup:
  431. if (PKIX_ERROR_RECEIVED){
  432. PKIX_DECREF(checkers);
  433. }
  434. PKIX_DECREF(certSelector);
  435. PKIX_DECREF(testDate);
  436. PKIX_DECREF(initialPolicies);
  437. PKIX_DECREF(targetCertChecker);
  438. PKIX_DECREF(expirationChecker);
  439. PKIX_DECREF(nameChainingChecker);
  440. PKIX_DECREF(nameConstraintsChecker);
  441. PKIX_DECREF(basicConstraintsChecker);
  442. PKIX_DECREF(policyChecker);
  443. PKIX_DECREF(sigChecker);
  444. PKIX_DECREF(trustedCAName);
  445. PKIX_DECREF(trustedPubKey);
  446. PKIX_DECREF(trustedNC);
  447. PKIX_DECREF(trustedCert);
  448. PKIX_DECREF(defaultCrlChecker);
  449. PKIX_DECREF(userCheckersList);
  450. PKIX_DECREF(certStores);
  451. PKIX_DECREF(userChecker);
  452. PKIX_RETURN(VALIDATE);
  453. }
  454. /*
  455. * FUNCTION: pkix_RetrieveOutputs
  456. * DESCRIPTION:
  457. *
  458. * This function queries the respective states of the List of checkers in
  459. * "checkers" to to obtain the final public key from the SignatureChecker
  460. * and the policy tree from the PolicyChecker, storing those values at
  461. * "pFinalSubjPubKey" and "pPolicyTree", respectively.
  462. *
  463. * PARAMETERS:
  464. * "checkers"
  465. * Address of List of checkers to be queried. Must be non-NULL.
  466. * "pFinalSubjPubKey"
  467. * Address where final public key will be stored. Must be non-NULL.
  468. * "pPolicyTree"
  469. * Address where policy tree will be stored. Must be non-NULL.
  470. * "plContext"
  471. * Platform-specific context pointer.
  472. * THREAD SAFETY:
  473. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  474. * RETURNS:
  475. * Returns NULL if the function succeeds.
  476. * Returns a Validate Error if the function fails in a non-fatal way.
  477. * Returns a Fatal Error if the function fails in an unrecoverable way.
  478. */
  479. static PKIX_Error *
  480. pkix_RetrieveOutputs(
  481. PKIX_List *checkers,
  482. PKIX_PL_PublicKey **pFinalSubjPubKey,
  483. PKIX_PolicyNode **pPolicyTree,
  484. void *plContext)
  485. {
  486. PKIX_PL_PublicKey *finalSubjPubKey = NULL;
  487. PKIX_PolicyNode *validPolicyTree = NULL;
  488. PKIX_CertChainChecker *checker = NULL;
  489. PKIX_PL_Object *state = NULL;
  490. PKIX_UInt32 numCheckers = 0;
  491. PKIX_UInt32 type;
  492. PKIX_Int32 j;
  493. PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs");
  494. PKIX_NULLCHECK_TWO(checkers, pPolicyTree);
  495. /*
  496. * To optimize the search, we guess that the sigChecker is
  497. * last in the tree and is preceded by the policyChecker. We
  498. * search toward the front of the chain. Remember that List
  499. * items are indexed 0..(numItems - 1).
  500. */
  501. PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
  502. PKIX_LISTGETLENGTHFAILED);
  503. for (j = numCheckers - 1; j >= 0; j--){
  504. PKIX_CHECK(PKIX_List_GetItem
  505. (checkers, j, (PKIX_PL_Object **)&checker, plContext),
  506. PKIX_LISTGETITEMFAILED);
  507. PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
  508. (checker, &state, plContext),
  509. PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
  510. /* user defined checker may have no state */
  511. if (state != NULL) {
  512. PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext),
  513. PKIX_OBJECTGETTYPEFAILED);
  514. if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){
  515. /* final pubKey will include any inherited DSA params */
  516. finalSubjPubKey =
  517. ((pkix_SignatureCheckerState *)state)->
  518. prevPublicKey;
  519. PKIX_INCREF(finalSubjPubKey);
  520. *pFinalSubjPubKey = finalSubjPubKey;
  521. }
  522. if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) {
  523. validPolicyTree =
  524. ((PKIX_PolicyCheckerState *)state)->validPolicyTree;
  525. break;
  526. }
  527. }
  528. PKIX_DECREF(checker);
  529. PKIX_DECREF(state);
  530. }
  531. PKIX_INCREF(validPolicyTree);
  532. *pPolicyTree = validPolicyTree;
  533. cleanup:
  534. PKIX_DECREF(checker);
  535. PKIX_DECREF(state);
  536. PKIX_RETURN(VALIDATE);
  537. }
  538. /*
  539. * FUNCTION: pkix_CheckChain
  540. * DESCRIPTION:
  541. *
  542. * Checks whether the List of Certs pointed to by "certs", containing
  543. * "numCerts" entries, successfully validates using each CertChainChecker in
  544. * the List pointed to by "checkers" and has not been revoked, according to any
  545. * of the Revocation Checkers in the List pointed to by "revChecker". Checkers
  546. * are expected to remove from "removeCheckedExtOIDs" and extensions that they
  547. * process. Indices to the certChain and the checkerChain are obtained and
  548. * returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These
  549. * should be set to zero prior to the initial call, but may be changed (and
  550. * must be supplied on subsequent calls) if processing is suspended for non-
  551. * blocking I/O. Each time a Cert passes from being validated by one of the
  552. * CertChainCheckers to being checked by a Revocation Checker, the Boolean
  553. * stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is
  554. * rejected by a Revocation Checker, its reason code is returned at
  555. * "pReasonCode. If the List of Certs successfully validates, the public key i
  556. * the final certificate is obtained and stored at "pFinalSubjPubKey" and the
  557. * validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List
  558. * of Certs fails to validate, an Error pointer is returned.
  559. *
  560. * If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which
  561. * tracks the results of the validation. That is, either each node in the
  562. * chain has a NULL Error component, or the last node contains an Error
  563. * which indicates why the validation failed.
  564. *
  565. * The number of Certs in the List, represented by "numCerts", is used to
  566. * determine which Cert is the final Cert.
  567. *
  568. * PARAMETERS:
  569. * "certs"
  570. * Address of List of Certs to validate. Must be non-NULL.
  571. * "numCerts"
  572. * Number of certificates in the List of certificates.
  573. * "checkers"
  574. * List of CertChainCheckers which must each validate the List of
  575. * certificates. Must be non-NULL.
  576. * "revChecker"
  577. * List of RevocationCheckers which must each not reject the List of
  578. * certificates. May be empty, but must be non-NULL.
  579. * "removeCheckedExtOIDs"
  580. * List of PKIX_PL_OID that has been processed. If called from building
  581. * chain, it is the list of critical extension OIDs that has been
  582. * processed prior to validation. Extension OIDs that may be processed by
  583. * user defined checker processes are also in the list. May be NULL.
  584. * "procParams"
  585. * Address of ProcessingParams used to initialize various checkers. Must
  586. * be non-NULL.
  587. * "pCertCheckedIndex"
  588. * Address where Int32 index to the Cert chain is obtained and
  589. * returned. Must be non-NULL.
  590. * "pCheckerIndex"
  591. * Address where Int32 index to the CheckerChain is obtained and
  592. * returned. Must be non-NULL.
  593. * "pRevChecking"
  594. * Address where Boolean is obtained and returned, indicating, if FALSE,
  595. * that CertChainCheckers are being called; or, if TRUE, that RevChecker
  596. * are being called. Must be non-NULL.
  597. * "pReasonCode"
  598. * Address where UInt32 results of revocation checking are stored. Must be
  599. * non-NULL.
  600. * "pNBIOContext"
  601. * Address where platform-dependent context is stored if checking is
  602. * suspended for non-blocking I/O. Must be non-NULL.
  603. * "pFinalSubjPubKey"
  604. * Address where the final public key will be stored. Must be non-NULL.
  605. * "pPolicyTree"
  606. * Address where the final validPolicyTree is stored. Must be non-NULL.
  607. * "pVerifyTree"
  608. * Address where a VerifyTree is stored, if non-NULL.
  609. * "plContext"
  610. * Platform-specific context pointer.
  611. * THREAD SAFETY:
  612. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  613. * RETURNS:
  614. * Returns NULL if the function succeeds.
  615. * Returns a Validate Error if the function fails in a non-fatal way.
  616. * Returns a Fatal Error if the function fails in an unrecoverable way.
  617. */
  618. PKIX_Error *
  619. pkix_CheckChain(
  620. PKIX_List *certs,
  621. PKIX_UInt32 numCerts,
  622. PKIX_TrustAnchor *anchor,
  623. PKIX_List *checkers,
  624. PKIX_RevocationChecker *revChecker,
  625. PKIX_List *removeCheckedExtOIDs,
  626. PKIX_ProcessingParams *procParams,
  627. PKIX_UInt32 *pCertCheckedIndex,
  628. PKIX_UInt32 *pCheckerIndex,
  629. PKIX_Boolean *pRevChecking,
  630. PKIX_UInt32 *pReasonCode,
  631. void **pNBIOContext,
  632. PKIX_PL_PublicKey **pFinalSubjPubKey,
  633. PKIX_PolicyNode **pPolicyTree,
  634. PKIX_VerifyNode **pVerifyTree,
  635. void *plContext)
  636. {
  637. PKIX_UInt32 j = 0;
  638. PKIX_Boolean revChecking = PKIX_FALSE;
  639. PKIX_Error *checkCertError = NULL;
  640. void *nbioContext = NULL;
  641. PKIX_PL_Cert *cert = NULL;
  642. PKIX_PL_Cert *issuer = NULL;
  643. PKIX_ENTER(VALIDATE, "pkix_CheckChain");
  644. PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex);
  645. PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor);
  646. PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree);
  647. nbioContext = *pNBIOContext;
  648. *pNBIOContext = NULL;
  649. revChecking = *pRevChecking;
  650. PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
  651. (anchor, &cert, plContext),
  652. PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  653. for (j = *pCertCheckedIndex; j < numCerts; j++) {
  654. PORT_Assert(cert);
  655. PKIX_DECREF(issuer);
  656. issuer = cert;
  657. cert = NULL;
  658. PKIX_CHECK(PKIX_List_GetItem(
  659. certs, j, (PKIX_PL_Object **)&cert, plContext),
  660. PKIX_LISTGETITEMFAILED);
  661. /* check if cert pointer is valid */
  662. PORT_Assert(cert);
  663. if (cert == NULL) {
  664. continue;
  665. }
  666. if (revChecking == PKIX_FALSE) {
  667. PKIX_CHECK(pkix_CheckCert
  668. (cert,
  669. checkers,
  670. removeCheckedExtOIDs,
  671. pCheckerIndex,
  672. &nbioContext,
  673. plContext),
  674. PKIX_CHECKCERTFAILED);
  675. if (nbioContext != NULL) {
  676. *pCertCheckedIndex = j;
  677. *pRevChecking = revChecking;
  678. *pNBIOContext = nbioContext;
  679. goto cleanup;
  680. }
  681. revChecking = PKIX_TRUE;
  682. *pCheckerIndex = 0;
  683. }
  684. if (revChecking == PKIX_TRUE) {
  685. PKIX_RevocationStatus revStatus;
  686. pkixErrorResult =
  687. PKIX_RevocationChecker_Check(
  688. cert, issuer, revChecker,
  689. procParams, PKIX_TRUE,
  690. (j == numCerts - 1) ? PKIX_TRUE : PKIX_FALSE,
  691. &revStatus, pReasonCode,
  692. &nbioContext, plContext);
  693. if (nbioContext != NULL) {
  694. *pCertCheckedIndex = j;
  695. *pRevChecking = revChecking;
  696. *pNBIOContext = nbioContext;
  697. goto cleanup;
  698. }
  699. if (revStatus == PKIX_RevStatus_Revoked ||
  700. pkixErrorResult) {
  701. if (!pkixErrorResult) {
  702. /* if pkixErrorResult is returned then
  703. * use it as it has a detailed revocation
  704. * error code. Otherwise create a new error */
  705. PKIX_ERROR_CREATE(VALIDATE,
  706. PKIX_CERTIFICATEREVOKED,
  707. pkixErrorResult);
  708. }
  709. goto cleanup;
  710. }
  711. revChecking = PKIX_FALSE;
  712. *pCheckerIndex = 0;
  713. }
  714. PKIX_CHECK(pkix_AddToVerifyLog
  715. (cert, j, NULL, pVerifyTree, plContext),
  716. PKIX_ADDTOVERIFYLOGFAILED);
  717. }
  718. PKIX_CHECK(pkix_RetrieveOutputs
  719. (checkers, pFinalSubjPubKey, pPolicyTree, plContext),
  720. PKIX_RETRIEVEOUTPUTSFAILED);
  721. *pNBIOContext = NULL;
  722. cleanup:
  723. if (PKIX_ERROR_RECEIVED && cert) {
  724. checkCertError = pkixErrorResult;
  725. PKIX_CHECK_FATAL(
  726. pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree,
  727. plContext),
  728. PKIX_ADDTOVERIFYLOGFAILED);
  729. pkixErrorResult = checkCertError;
  730. pkixErrorCode = pkixErrorResult->errCode;
  731. checkCertError = NULL;
  732. }
  733. fatal:
  734. PKIX_DECREF(checkCertError);
  735. PKIX_DECREF(cert);
  736. PKIX_DECREF(issuer);
  737. PKIX_RETURN(VALIDATE);
  738. }
  739. /*
  740. * FUNCTION: pkix_ExtractParameters
  741. * DESCRIPTION:
  742. *
  743. * Extracts several parameters from the ValidateParams object pointed to by
  744. * "valParams" and stores the CertChain at "pChain", the List of Certs at
  745. * "pCerts", the number of Certs in the chain at "pNumCerts", the
  746. * ProcessingParams object at "pProcParams", the List of TrustAnchors at
  747. * "pAnchors", and the number of TrustAnchors at "pNumAnchors".
  748. *
  749. * PARAMETERS:
  750. * "valParams"
  751. * Address of ValidateParams from which the parameters are extracted.
  752. * Must be non-NULL.
  753. * "pCerts"
  754. * Address where object pointer for List of Certs will be stored.
  755. * Must be non-NULL.
  756. * "pNumCerts"
  757. * Address where number of Certs will be stored. Must be non-NULL.
  758. * "pProcParams"
  759. * Address where object pointer for ProcessingParams will be stored.
  760. * Must be non-NULL.
  761. * "pAnchors"
  762. * Address where object pointer for List of Anchors will be stored.
  763. * Must be non-NULL.
  764. * "pNumAnchors"
  765. * Address where number of Anchors will be stored. Must be non-NULL.
  766. * "plContext"
  767. * Platform-specific context pointer.
  768. * THREAD SAFETY:
  769. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  770. * RETURNS:
  771. * Returns NULL if the function succeeds.
  772. * Returns a Validate Error if the function fails in a non-fatal way.
  773. * Returns a Fatal Error if the function fails in an unrecoverable way.
  774. */
  775. static PKIX_Error *
  776. pkix_ExtractParameters(
  777. PKIX_ValidateParams *valParams,
  778. PKIX_List **pCerts,
  779. PKIX_UInt32 *pNumCerts,
  780. PKIX_ProcessingParams **pProcParams,
  781. PKIX_List **pAnchors,
  782. PKIX_UInt32 *pNumAnchors,
  783. void *plContext)
  784. {
  785. PKIX_ENTER(VALIDATE, "pkix_ExtractParameters");
  786. PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts);
  787. PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors);
  788. /* extract relevant parameters from chain */
  789. PKIX_CHECK(PKIX_ValidateParams_GetCertChain
  790. (valParams, pCerts, plContext),
  791. PKIX_VALIDATEPARAMSGETCERTCHAINFAILED);
  792. PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext),
  793. PKIX_LISTGETLENGTHFAILED);
  794. /* extract relevant parameters from procParams */
  795. PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams
  796. (valParams, pProcParams, plContext),
  797. PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED);
  798. PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
  799. (*pProcParams, pAnchors, plContext),
  800. PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);
  801. PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext),
  802. PKIX_LISTGETLENGTHFAILED);
  803. cleanup:
  804. PKIX_RETURN(VALIDATE);
  805. }
  806. /* --Public-Functions--------------------------------------------- */
  807. /*
  808. * FUNCTION: PKIX_ValidateChain (see comments in pkix.h)
  809. */
  810. PKIX_Error *
  811. PKIX_ValidateChain(
  812. PKIX_ValidateParams *valParams,
  813. PKIX_ValidateResult **pResult,
  814. PKIX_VerifyNode **pVerifyTree,
  815. void *plContext)
  816. {
  817. PKIX_Error *chainFailed = NULL;
  818. PKIX_ProcessingParams *procParams = NULL;
  819. PKIX_CertChainChecker *userChecker = NULL;
  820. PKIX_RevocationChecker *revChecker = NULL;
  821. PKIX_List *certs = NULL;
  822. PKIX_List *checkers = NULL;
  823. PKIX_List *anchors = NULL;
  824. PKIX_List *userCheckers = NULL;
  825. PKIX_List *userCheckerExtOIDs = NULL;
  826. PKIX_List *validateCheckedCritExtOIDsList = NULL;
  827. PKIX_TrustAnchor *anchor = NULL;
  828. PKIX_ValidateResult *valResult = NULL;
  829. PKIX_PL_PublicKey *finalPubKey = NULL;
  830. PKIX_PolicyNode *validPolicyTree = NULL;
  831. PKIX_Boolean supportForwarding = PKIX_FALSE;
  832. PKIX_Boolean revChecking = PKIX_FALSE;
  833. PKIX_UInt32 i, numCerts, numAnchors;
  834. PKIX_UInt32 numUserCheckers = 0;
  835. PKIX_UInt32 certCheckedIndex = 0;
  836. PKIX_UInt32 checkerIndex = 0;
  837. PKIX_UInt32 reasonCode = 0;
  838. void *nbioContext = NULL;
  839. PKIX_ENTER(VALIDATE, "PKIX_ValidateChain");
  840. PKIX_NULLCHECK_TWO(valParams, pResult);
  841. /* extract various parameters from valParams */
  842. PKIX_CHECK(pkix_ExtractParameters
  843. (valParams,
  844. &certs,
  845. &numCerts,
  846. &procParams,
  847. &anchors,
  848. &numAnchors,
  849. plContext),
  850. PKIX_EXTRACTPARAMETERSFAILED);
  851. /*
  852. * setup an extension OID list that user had defined for his checker
  853. * processing. User checker is not responsible for taking out OIDs
  854. * from unresolved critical extension list as the libpkix checker
  855. * is doing. Here we add those user checkers' OIDs to the removal
  856. * list to be taken out by CheckChain
  857. */
  858. PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
  859. (procParams, &userCheckers, plContext),
  860. PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
  861. if (userCheckers != NULL) {
  862. PKIX_CHECK(PKIX_List_Create
  863. (&validateCheckedCritExtOIDsList,
  864. plContext),
  865. PKIX_LISTCREATEFAILED);
  866. PKIX_CHECK(PKIX_List_GetLength
  867. (userCheckers, &numUserCheckers, plContext),
  868. PKIX_LISTGETLENGTHFAILED);
  869. for (i = 0; i < numUserCheckers; i++) {
  870. PKIX_CHECK(PKIX_List_GetItem
  871. (userCheckers,
  872. i,
  873. (PKIX_PL_Object **) &userChecker,
  874. plContext),
  875. PKIX_LISTGETITEMFAILED);
  876. PKIX_CHECK
  877. (PKIX_CertChainChecker_IsForwardCheckingSupported
  878. (userChecker, &supportForwarding, plContext),
  879. PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
  880. if (supportForwarding == PKIX_FALSE) {
  881. PKIX_CHECK
  882. (PKIX_CertChainChecker_GetSupportedExtensions
  883. (userChecker, &userCheckerExtOIDs, plContext),
  884. PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
  885. if (userCheckerExtOIDs != NULL) {
  886. PKIX_CHECK(pkix_List_AppendList
  887. (validateCheckedCritExtOIDsList,
  888. userCheckerExtOIDs,
  889. plContext),
  890. PKIX_LISTAPPENDLISTFAILED);
  891. }
  892. }
  893. PKIX_DECREF(userCheckerExtOIDs);
  894. PKIX_DECREF(userChecker);
  895. }
  896. }
  897. PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
  898. (procParams, &revChecker, plContext),
  899. PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
  900. /* try to validate the chain with each anchor */
  901. for (i = 0; i < numAnchors; i++){
  902. /* get trust anchor */
  903. PKIX_CHECK(PKIX_List_GetItem
  904. (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
  905. PKIX_LISTGETITEMFAILED);
  906. /* initialize checkers using information from trust anchor */
  907. PKIX_CHECK(pkix_InitializeCheckers
  908. (anchor, procParams, numCerts, &checkers, plContext),
  909. PKIX_INITIALIZECHECKERSFAILED);
  910. /*
  911. * Validate the chain using this trust anchor and these
  912. * checkers. (WARNING: checkers that use non-blocking I/O
  913. * are not currently supported.)
  914. */
  915. certCheckedIndex = 0;
  916. checkerIndex = 0;
  917. revChecking = PKIX_FALSE;
  918. chainFailed = pkix_CheckChain
  919. (certs,
  920. numCerts,
  921. anchor,
  922. checkers,
  923. revChecker,
  924. validateCheckedCritExtOIDsList,
  925. procParams,
  926. &certCheckedIndex,
  927. &checkerIndex,
  928. &revChecking,
  929. &reasonCode,
  930. &nbioContext,
  931. &finalPubKey,
  932. &validPolicyTree,
  933. pVerifyTree,
  934. plContext);
  935. if (chainFailed || (reasonCode != 0)) {
  936. /* cert chain failed to validate */
  937. PKIX_DECREF(chainFailed);
  938. PKIX_DECREF(anchor);
  939. PKIX_DECREF(checkers);
  940. PKIX_DECREF(validPolicyTree);
  941. /* if last anchor, we fail; else, we try next anchor */
  942. if (i == (numAnchors - 1)) { /* last anchor */
  943. PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
  944. }
  945. } else {
  946. /* cert chain successfully validated! */
  947. PKIX_CHECK(pkix_ValidateResult_Create
  948. (finalPubKey,
  949. anchor,
  950. validPolicyTree,
  951. &valResult,
  952. plContext),
  953. PKIX_VALIDATERESULTCREATEFAILED);
  954. *pResult = valResult;
  955. /* no need to try any more anchors in the loop */
  956. goto cleanup;
  957. }
  958. }
  959. cleanup:
  960. PKIX_DECREF(finalPubKey);
  961. PKIX_DECREF(certs);
  962. PKIX_DECREF(anchors);
  963. PKIX_DECREF(anchor);
  964. PKIX_DECREF(checkers);
  965. PKIX_DECREF(revChecker);
  966. PKIX_DECREF(validPolicyTree);
  967. PKIX_DECREF(chainFailed);
  968. PKIX_DECREF(procParams);
  969. PKIX_DECREF(userCheckers);
  970. PKIX_DECREF(validateCheckedCritExtOIDsList);
  971. PKIX_RETURN(VALIDATE);
  972. }
  973. /*
  974. * FUNCTION: pkix_Validate_BuildUserOIDs
  975. * DESCRIPTION:
  976. *
  977. * This function creates a List of the OIDs that are processed by the user
  978. * checkers in the List pointed to by "userCheckers", storing the resulting
  979. * List at "pUserCritOIDs". If the List of userCheckers is NULL, the output
  980. * List will be NULL. Otherwise the output List will be non-NULL, but may be
  981. * empty.
  982. *
  983. * PARAMETERS:
  984. * "userCheckers"
  985. * The address of the List of userCheckers.
  986. * "pUserCritOIDs"
  987. * The address at which the List is stored. Must be non-NULL.
  988. * "plContext"
  989. * Platform-specific context pointer.
  990. * THREAD SAFETY:
  991. * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  992. * RETURNS:
  993. * Returns NULL if the function succeeds.
  994. * Returns a VALIDATE Error if the function fails in a non-fatal way.
  995. * Returns a Fatal Error if the function fails in an unrecoverable way.
  996. */
  997. static PKIX_Error *
  998. pkix_Validate_BuildUserOIDs(
  999. PKIX_List *userCheckers,
  1000. PKIX_List **pUserCritOIDs,
  1001. void *plContext)
  1002. {
  1003. PKIX_UInt32 numUserCheckers = 0;
  1004. PKIX_UInt32 i = 0;
  1005. PKIX_List *userCritOIDs = NULL;
  1006. PKIX_List *userCheckerExtOIDs = NULL;
  1007. PKIX_Boolean supportForwarding = PKIX_FALSE;
  1008. PKIX_CertChainChecker *userChecker = NULL;
  1009. PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs");
  1010. PKIX_NULLCHECK_ONE(pUserCritOIDs);
  1011. if (userCheckers != NULL) {
  1012. PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext),
  1013. PKIX_LISTCREATEFAILED);
  1014. PKIX_CHECK(PKIX_List_GetLength
  1015. (userCheckers, &numUserCheckers, plContext),
  1016. PKIX_LISTGETLENGTHFAILED);
  1017. for (i = 0; i < numUserCheckers; i++) {
  1018. PKIX_CHECK(PKIX_List_GetItem
  1019. (userCheckers,
  1020. i,
  1021. (PKIX_PL_Object **) &userChecker,
  1022. plContext),
  1023. PKIX_LISTGETITEMFAILED);
  1024. PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported
  1025. (userChecker, &supportForwarding, plContext),
  1026. PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
  1027. if (supportForwarding == PKIX_FALSE) {
  1028. PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions
  1029. (userChecker, &userCheckerExtOIDs, plContext),
  1030. PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
  1031. if (userCheckerExtOIDs != NULL) {
  1032. PKIX_CHECK(pkix_List_AppendList
  1033. (userCritOIDs, userCheckerExtOIDs, plContext),
  1034. PKIX_LISTAPPENDLISTFAILED);
  1035. }
  1036. }
  1037. PKIX_DECREF(userCheckerExtOIDs);
  1038. PKIX_DECREF(userChecker);
  1039. }
  1040. }
  1041. *pUserCritOIDs = userCritOIDs;
  1042. cleanup:
  1043. if (PKIX_ERROR_RECEIVED){
  1044. PKIX_DECREF(userCritOIDs);
  1045. }
  1046. PKIX_DECREF(userCheckerExtOIDs);
  1047. PKIX_DECREF(userChecker);
  1048. PKIX_RETURN(VALIDATE);
  1049. }
  1050. /*
  1051. * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h)
  1052. */
  1053. PKIX_Error *
  1054. PKIX_ValidateChain_NB(
  1055. PKIX_ValidateParams *valParams,
  1056. PKIX_UInt32 *pCertIndex,
  1057. PKIX_UInt32 *pAnchorIndex,
  1058. PKIX_UInt32 *pCheckerIndex,
  1059. PKIX_Boolean *pRevChecking,
  1060. PKIX_List **pCheckers,
  1061. void **pNBIOContext,
  1062. PKIX_ValidateResult **pResult,
  1063. PKIX_VerifyNode **pVerifyTree,
  1064. void *plContext)
  1065. {
  1066. PKIX_UInt32 numCerts = 0;
  1067. PKIX_UInt32 numAnchors = 0;
  1068. PKIX_UInt32 i = 0;
  1069. PKIX_UInt32 certIndex = 0;
  1070. PKIX_UInt32 anchorIndex = 0;
  1071. PKIX_UInt32 checkerIndex = 0;
  1072. PKIX_UInt32 reasonCode = 0;
  1073. PKIX_Boolean revChecking = PKIX_FALSE;
  1074. PKIX_List *certs = NULL;
  1075. PKIX_List *anchors = NULL;
  1076. PKIX_List *checkers = NULL;
  1077. PKIX_List *userCheckers = NULL;
  1078. PKIX_List *validateCheckedCritExtOIDsList = NULL;
  1079. PKIX_TrustAnchor *anchor = NULL;
  1080. PKIX_ValidateResult *valResult = NULL;
  1081. PKIX_PL_PublicKey *finalPubKey = NULL;
  1082. PKIX_PolicyNode *validPolicyTree = NULL;
  1083. PKIX_ProcessingParams *procParams = NULL;
  1084. PKIX_RevocationChecker *revChecker = NULL;
  1085. PKIX_Error *chainFailed = NULL;
  1086. void *nbioContext = NULL;
  1087. PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB");
  1088. PKIX_NULLCHECK_FOUR
  1089. (valParams, pCertIndex, pAnchorIndex, pCheckerIndex);
  1090. PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult);
  1091. nbioContext = *pNBIOContext;
  1092. *pNBIOContext = NULL;
  1093. /* extract various parameters from valParams */
  1094. PKIX_CHECK(pkix_ExtractParameters
  1095. (valParams,
  1096. &certs,
  1097. &numCerts,
  1098. &procParams,
  1099. &anchors,
  1100. &numAnchors,
  1101. plContext),
  1102. PKIX_EXTRACTPARAMETERSFAILED);
  1103. /*
  1104. * Create a List of the OIDs that will be processed by the user
  1105. * checkers. User checkers are not responsible for removing OIDs from
  1106. * the List of unresolved critical extensions, as libpkix checkers are.
  1107. * So we add those user checkers' OIDs to the removal list to be taken
  1108. * out by CheckChain.
  1109. */
  1110. PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
  1111. (procParams, &userCheckers, plContext),
  1112. PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
  1113. PKIX_CHECK(pkix_Validate_BuildUserOIDs
  1114. (userCheckers, &validateCheckedCritExtOIDsList, plContext),
  1115. PKIX_VALIDATEBUILDUSEROIDSFAILED);
  1116. PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
  1117. (procParams, &revChecker, plContext),
  1118. PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
  1119. /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
  1120. if (nbioContext != NULL) {
  1121. /* Resuming */
  1122. certIndex = *pCertIndex;
  1123. anchorIndex = *pAnchorIndex;
  1124. checkerIndex = *pCheckerIndex;
  1125. revChecking = *pRevChecking;
  1126. checkers = *pCheckers;
  1127. *pCheckers = NULL;
  1128. }
  1129. /* try to validate the chain with each anchor */
  1130. for (i = anchorIndex; i < numAnchors; i++) {
  1131. /* get trust anchor */
  1132. PKIX_CHECK(PKIX_List_GetItem
  1133. (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
  1134. PKIX_LISTGETITEMFAILED);
  1135. /* initialize checkers using information from trust anchor */
  1136. if (nbioContext == NULL) {
  1137. PKIX_CHECK(pkix_InitializeCheckers
  1138. (anchor,
  1139. procParams,
  1140. numCerts,
  1141. &checkers,
  1142. plContext),
  1143. PKIX_INITIALIZECHECKERSFAILED);
  1144. }
  1145. /*
  1146. * Validate the chain using this trust anchor and these
  1147. * checkers.
  1148. */
  1149. chainFailed = pkix_CheckChain
  1150. (certs,
  1151. numCerts,
  1152. anchor,
  1153. checkers,
  1154. revChecker,
  1155. validateCheckedCritExtOIDsList,
  1156. procParams,
  1157. &certIndex,
  1158. &checkerIndex,
  1159. &revChecking,
  1160. &reasonCode,
  1161. &nbioContext,
  1162. &finalPubKey,
  1163. &validPolicyTree,
  1164. pVerifyTree,
  1165. plContext);
  1166. if (nbioContext != NULL) {
  1167. *pCertIndex = certIndex;
  1168. *pAnchorIndex = anchorIndex;
  1169. *pCheckerIndex = checkerIndex;
  1170. *pRevChecking = revChecking;
  1171. PKIX_INCREF(checkers);
  1172. *pCheckers = checkers;
  1173. *pNBIOContext = nbioContext;
  1174. goto cleanup;
  1175. }
  1176. if (chainFailed || (reasonCode != 0)) {
  1177. /* cert chain failed to validate */
  1178. PKIX_DECREF(chainFailed);
  1179. PKIX_DECREF(anchor);
  1180. PKIX_DECREF(checkers);
  1181. PKIX_DECREF(validPolicyTree);
  1182. /* if last anchor, we fail; else, we try next anchor */
  1183. if (i == (numAnchors - 1)) { /* last anchor */
  1184. PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
  1185. }
  1186. } else {
  1187. /* cert chain successfully validated! */
  1188. PKIX_CHECK(pkix_ValidateResult_Create
  1189. (finalPubKey,
  1190. anchor,
  1191. validPolicyTree,
  1192. &valResult,
  1193. plContext),
  1194. PKIX_VALIDATERESULTCREATEFAILED);
  1195. *pResult = valResult;
  1196. /* no need to try any more anchors in the loop */
  1197. goto cleanup;
  1198. }
  1199. }
  1200. cleanup:
  1201. PKIX_DECREF(finalPubKey);
  1202. PKIX_DECREF(certs);
  1203. PKIX_DECREF(anchors);
  1204. PKIX_DECREF(anchor);
  1205. PKIX_DECREF(checkers);
  1206. PKIX_DECREF(revChecker);
  1207. PKIX_DECREF(validPolicyTree);
  1208. PKIX_DECREF(chainFailed);
  1209. PKIX_DECREF(procParams);
  1210. PKIX_DECREF(userCheckers);
  1211. PKIX_DECREF(validateCheckedCritExtOIDsList);
  1212. PKIX_RETURN(VALIDATE);
  1213. }