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