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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rwxr-xr-x

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial