pkix_validate.c (55533B)
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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 * 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 }