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