| OLD | NEW |
| (Empty) |
| 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_build.c | |
| 6 * | |
| 7 * Top level buildChain function | |
| 8 * | |
| 9 */ | |
| 10 | |
| 11 /* #define PKIX_BUILDDEBUG 1 */ | |
| 12 /* #define PKIX_FORWARDBUILDERSTATEDEBUG 1 */ | |
| 13 | |
| 14 #include "pkix_build.h" | |
| 15 | |
| 16 extern PRLogModuleInfo *pkixLog; | |
| 17 | |
| 18 /* | |
| 19 * List of critical extension OIDs associate with what build chain has | |
| 20 * checked. Those OIDs need to be removed from the unresolved critical | |
| 21 * extension OIDs list manually (instead of by checker automatically). | |
| 22 */ | |
| 23 static SECOidTag buildCheckedCritExtOIDs[] = { | |
| 24 PKIX_CERTKEYUSAGE_OID, | |
| 25 PKIX_CERTSUBJALTNAME_OID, | |
| 26 PKIX_BASICCONSTRAINTS_OID, | |
| 27 PKIX_NAMECONSTRAINTS_OID, | |
| 28 PKIX_EXTENDEDKEYUSAGE_OID, | |
| 29 PKIX_NSCERTTYPE_OID, | |
| 30 PKIX_UNKNOWN_OID | |
| 31 }; | |
| 32 | |
| 33 /* --Private-ForwardBuilderState-Functions---------------------------------- */ | |
| 34 | |
| 35 /* | |
| 36 * FUNCTION: pkix_ForwardBuilderState_Destroy | |
| 37 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
| 38 */ | |
| 39 static PKIX_Error * | |
| 40 pkix_ForwardBuilderState_Destroy( | |
| 41 PKIX_PL_Object *object, | |
| 42 void *plContext) | |
| 43 { | |
| 44 PKIX_ForwardBuilderState *state = NULL; | |
| 45 | |
| 46 PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Destroy"); | |
| 47 PKIX_NULLCHECK_ONE(object); | |
| 48 | |
| 49 PKIX_CHECK(pkix_CheckType | |
| 50 (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext), | |
| 51 PKIX_OBJECTNOTFORWARDBUILDERSTATE); | |
| 52 | |
| 53 state = (PKIX_ForwardBuilderState *)object; | |
| 54 | |
| 55 state->status = BUILD_INITIAL; | |
| 56 state->traversedCACerts = 0; | |
| 57 state->certStoreIndex = 0; | |
| 58 state->numCerts = 0; | |
| 59 state->numAias = 0; | |
| 60 state->certIndex = 0; | |
| 61 state->aiaIndex = 0; | |
| 62 state->certCheckedIndex = 0; | |
| 63 state->checkerIndex = 0; | |
| 64 state->hintCertIndex = 0; | |
| 65 state->numFanout = 0; | |
| 66 state->numDepth = 0; | |
| 67 state->reasonCode = 0; | |
| 68 state->revCheckDelayed = PKIX_FALSE; | |
| 69 state->canBeCached = PKIX_FALSE; | |
| 70 state->useOnlyLocal = PKIX_FALSE; | |
| 71 state->revChecking = PKIX_FALSE; | |
| 72 state->usingHintCerts = PKIX_FALSE; | |
| 73 state->certLoopingDetected = PKIX_FALSE; | |
| 74 PKIX_DECREF(state->validityDate); | |
| 75 PKIX_DECREF(state->prevCert); | |
| 76 PKIX_DECREF(state->candidateCert); | |
| 77 PKIX_DECREF(state->traversedSubjNames); | |
| 78 PKIX_DECREF(state->trustChain); | |
| 79 PKIX_DECREF(state->aia); | |
| 80 PKIX_DECREF(state->candidateCerts); | |
| 81 PKIX_DECREF(state->reversedCertChain); | |
| 82 PKIX_DECREF(state->checkedCritExtOIDs); | |
| 83 PKIX_DECREF(state->checkerChain); | |
| 84 PKIX_DECREF(state->certSel); | |
| 85 PKIX_DECREF(state->verifyNode); | |
| 86 PKIX_DECREF(state->client); | |
| 87 | |
| 88 /* | |
| 89 * If we ever add a child link we have to be careful not to have loops | |
| 90 * in the Destroy process. But with one-way links we should be okay. | |
| 91 */ | |
| 92 if (state->parentState == NULL) { | |
| 93 state->buildConstants.numAnchors = 0; | |
| 94 state->buildConstants.numCertStores = 0; | |
| 95 state->buildConstants.numHintCerts = 0; | |
| 96 state->buildConstants.procParams = 0; | |
| 97 PKIX_DECREF(state->buildConstants.testDate); | |
| 98 PKIX_DECREF(state->buildConstants.timeLimit); | |
| 99 PKIX_DECREF(state->buildConstants.targetCert); | |
| 100 PKIX_DECREF(state->buildConstants.targetPubKey); | |
| 101 PKIX_DECREF(state->buildConstants.certStores); | |
| 102 PKIX_DECREF(state->buildConstants.anchors); | |
| 103 PKIX_DECREF(state->buildConstants.userCheckers); | |
| 104 PKIX_DECREF(state->buildConstants.hintCerts); | |
| 105 PKIX_DECREF(state->buildConstants.revChecker); | |
| 106 PKIX_DECREF(state->buildConstants.aiaMgr); | |
| 107 } else { | |
| 108 PKIX_DECREF(state->parentState); | |
| 109 } | |
| 110 | |
| 111 cleanup: | |
| 112 | |
| 113 PKIX_RETURN(FORWARDBUILDERSTATE); | |
| 114 } | |
| 115 | |
| 116 /* | |
| 117 * FUNCTION: pkix_ForwardBuilderState_Create | |
| 118 * | |
| 119 * DESCRIPTION: | |
| 120 * Allocate and initialize a ForwardBuilderState. | |
| 121 * | |
| 122 * PARAMETERS | |
| 123 * "traversedCACerts" | |
| 124 * Number of CA certificates traversed. | |
| 125 * "numFanout" | |
| 126 * Number of Certs that can be considered at this level (0 = no limit) | |
| 127 * "numDepth" | |
| 128 * Number of additional levels that can be searched (0 = no limit) | |
| 129 * "revCheckDelayed" | |
| 130 * Boolean value indicating whether rev check is delayed until after | |
| 131 * entire chain is built. | |
| 132 * "canBeCached" | |
| 133 * Boolean value indicating whether all certs on the chain can be cached. | |
| 134 * "validityDate" | |
| 135 * Address of Date at which build chain Certs' most restricted validity | |
| 136 * time is kept. May be NULL. | |
| 137 * "prevCert" | |
| 138 * Address of Cert just traversed. Must be non-NULL. | |
| 139 * "traversedSubjNames" | |
| 140 * Address of List of GeneralNames that have been traversed. | |
| 141 * Must be non-NULL. | |
| 142 * "trustChain" | |
| 143 * Address of List of certificates traversed. Must be non-NULL. | |
| 144 * "parentState" | |
| 145 * Address of previous ForwardBuilderState | |
| 146 * "pState" | |
| 147 * Address where ForwardBuilderState will be stored. Must be non-NULL. | |
| 148 * "plContext" | |
| 149 * Platform-specific context pointer. | |
| 150 * THREAD SAFETY: | |
| 151 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 152 * RETURNS: | |
| 153 * Returns NULL if the function succeeds. | |
| 154 * Returns a Build Error if the function fails in a non-fatal way. | |
| 155 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 156 */ | |
| 157 static PKIX_Error * | |
| 158 pkix_ForwardBuilderState_Create( | |
| 159 PKIX_Int32 traversedCACerts, | |
| 160 PKIX_UInt32 numFanout, | |
| 161 PKIX_UInt32 numDepth, | |
| 162 PKIX_Boolean revCheckDelayed, | |
| 163 PKIX_Boolean canBeCached, | |
| 164 PKIX_PL_Date *validityDate, | |
| 165 PKIX_PL_Cert *prevCert, | |
| 166 PKIX_List *traversedSubjNames, | |
| 167 PKIX_List *trustChain, | |
| 168 PKIX_ForwardBuilderState *parentState, | |
| 169 PKIX_ForwardBuilderState **pState, | |
| 170 void *plContext) | |
| 171 { | |
| 172 PKIX_ForwardBuilderState *state = NULL; | |
| 173 | |
| 174 PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Create"); | |
| 175 PKIX_NULLCHECK_FOUR(prevCert, traversedSubjNames, pState, trustChain); | |
| 176 | |
| 177 PKIX_CHECK(PKIX_PL_Object_Alloc | |
| 178 (PKIX_FORWARDBUILDERSTATE_TYPE, | |
| 179 sizeof (PKIX_ForwardBuilderState), | |
| 180 (PKIX_PL_Object **)&state, | |
| 181 plContext), | |
| 182 PKIX_COULDNOTCREATEFORWARDBUILDERSTATEOBJECT); | |
| 183 | |
| 184 state->status = BUILD_INITIAL; | |
| 185 state->traversedCACerts = traversedCACerts; | |
| 186 state->certStoreIndex = 0; | |
| 187 state->numCerts = 0; | |
| 188 state->numAias = 0; | |
| 189 state->certIndex = 0; | |
| 190 state->aiaIndex = 0; | |
| 191 state->certCheckedIndex = 0; | |
| 192 state->checkerIndex = 0; | |
| 193 state->hintCertIndex = 0; | |
| 194 state->numFanout = numFanout; | |
| 195 state->numDepth = numDepth; | |
| 196 state->reasonCode = 0; | |
| 197 state->revChecking = numDepth; | |
| 198 state->revCheckDelayed = revCheckDelayed; | |
| 199 state->canBeCached = canBeCached; | |
| 200 state->useOnlyLocal = PKIX_TRUE; | |
| 201 state->revChecking = PKIX_FALSE; | |
| 202 state->usingHintCerts = PKIX_FALSE; | |
| 203 state->certLoopingDetected = PKIX_FALSE; | |
| 204 | |
| 205 PKIX_INCREF(validityDate); | |
| 206 state->validityDate = validityDate; | |
| 207 | |
| 208 PKIX_INCREF(prevCert); | |
| 209 state->prevCert = prevCert; | |
| 210 | |
| 211 state->candidateCert = NULL; | |
| 212 | |
| 213 PKIX_INCREF(traversedSubjNames); | |
| 214 state->traversedSubjNames = traversedSubjNames; | |
| 215 | |
| 216 PKIX_INCREF(trustChain); | |
| 217 state->trustChain = trustChain; | |
| 218 | |
| 219 state->aia = NULL; | |
| 220 state->candidateCerts = NULL; | |
| 221 state->reversedCertChain = NULL; | |
| 222 state->checkedCritExtOIDs = NULL; | |
| 223 state->checkerChain = NULL; | |
| 224 state->certSel = NULL; | |
| 225 state->verifyNode = NULL; | |
| 226 state->client = NULL; | |
| 227 | |
| 228 PKIX_INCREF(parentState); | |
| 229 state->parentState = parentState; | |
| 230 | |
| 231 if (parentState != NULL) { | |
| 232 state->buildConstants.numAnchors = | |
| 233 parentState->buildConstants.numAnchors; | |
| 234 state->buildConstants.numCertStores = | |
| 235 parentState->buildConstants.numCertStores; | |
| 236 state->buildConstants.numHintCerts = | |
| 237 parentState->buildConstants.numHintCerts; | |
| 238 state->buildConstants.maxFanout = | |
| 239 parentState->buildConstants.maxFanout; | |
| 240 state->buildConstants.maxDepth = | |
| 241 parentState->buildConstants.maxDepth; | |
| 242 state->buildConstants.maxTime = | |
| 243 parentState->buildConstants.maxTime; | |
| 244 state->buildConstants.procParams = | |
| 245 parentState->buildConstants.procParams; | |
| 246 state->buildConstants.testDate = | |
| 247 parentState->buildConstants.testDate; | |
| 248 state->buildConstants.timeLimit = | |
| 249 parentState->buildConstants.timeLimit; | |
| 250 state->buildConstants.targetCert = | |
| 251 parentState->buildConstants.targetCert; | |
| 252 state->buildConstants.targetPubKey = | |
| 253 parentState->buildConstants.targetPubKey; | |
| 254 state->buildConstants.certStores = | |
| 255 parentState->buildConstants.certStores; | |
| 256 state->buildConstants.anchors = | |
| 257 parentState->buildConstants.anchors; | |
| 258 state->buildConstants.userCheckers = | |
| 259 parentState->buildConstants.userCheckers; | |
| 260 state->buildConstants.hintCerts = | |
| 261 parentState->buildConstants.hintCerts; | |
| 262 state->buildConstants.revChecker = | |
| 263 parentState->buildConstants.revChecker; | |
| 264 state->buildConstants.aiaMgr = | |
| 265 parentState->buildConstants.aiaMgr; | |
| 266 state->buildConstants.trustOnlyUserAnchors = | |
| 267 parentState->buildConstants.trustOnlyUserAnchors; | |
| 268 } | |
| 269 | |
| 270 *pState = state; | |
| 271 state = NULL; | |
| 272 cleanup: | |
| 273 | |
| 274 PKIX_DECREF(state); | |
| 275 | |
| 276 PKIX_RETURN(FORWARDBUILDERSTATE); | |
| 277 } | |
| 278 | |
| 279 /* | |
| 280 * FUNCTION: pkix_Build_GetResourceLimits | |
| 281 * | |
| 282 * DESCRIPTION: | |
| 283 * Retrieve Resource Limits from ProcessingParams and initialize them in | |
| 284 * BuildConstants. | |
| 285 * | |
| 286 * PARAMETERS | |
| 287 * "buildConstants" | |
| 288 * Address of a BuildConstants structure containing objects and values | |
| 289 * that remain constant throughout the building of a chain. Must be | |
| 290 * non-NULL. | |
| 291 * "plContext" | |
| 292 * Platform-specific context pointer. | |
| 293 * THREAD SAFETY: | |
| 294 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 295 * RETURNS: | |
| 296 * Returns NULL if the function succeeds. | |
| 297 * Returns a Build Error if the function fails in a non-fatal way. | |
| 298 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 299 */ | |
| 300 static PKIX_Error * | |
| 301 pkix_Build_GetResourceLimits( | |
| 302 BuildConstants *buildConstants, | |
| 303 void *plContext) | |
| 304 { | |
| 305 PKIX_ResourceLimits *resourceLimits = NULL; | |
| 306 | |
| 307 PKIX_ENTER(BUILD, "pkix_Build_GetResourceLimits"); | |
| 308 PKIX_NULLCHECK_ONE(buildConstants); | |
| 309 | |
| 310 PKIX_CHECK(PKIX_ProcessingParams_GetResourceLimits | |
| 311 (buildConstants->procParams, &resourceLimits, plContext), | |
| 312 PKIX_PROCESSINGPARAMSGETRESOURCELIMITSFAILED); | |
| 313 | |
| 314 buildConstants->maxFanout = 0; | |
| 315 buildConstants->maxDepth = 0; | |
| 316 buildConstants->maxTime = 0; | |
| 317 | |
| 318 if (resourceLimits) { | |
| 319 | |
| 320 PKIX_CHECK(PKIX_ResourceLimits_GetMaxFanout | |
| 321 (resourceLimits, &buildConstants->maxFanout, plContext), | |
| 322 PKIX_RESOURCELIMITSGETMAXFANOUTFAILED); | |
| 323 | |
| 324 PKIX_CHECK(PKIX_ResourceLimits_GetMaxDepth | |
| 325 (resourceLimits, &buildConstants->maxDepth, plContext), | |
| 326 PKIX_RESOURCELIMITSGETMAXDEPTHFAILED); | |
| 327 | |
| 328 PKIX_CHECK(PKIX_ResourceLimits_GetMaxTime | |
| 329 (resourceLimits, &buildConstants->maxTime, plContext), | |
| 330 PKIX_RESOURCELIMITSGETMAXTIMEFAILED); | |
| 331 } | |
| 332 | |
| 333 cleanup: | |
| 334 | |
| 335 PKIX_DECREF(resourceLimits); | |
| 336 | |
| 337 PKIX_RETURN(BUILD); | |
| 338 } | |
| 339 | |
| 340 /* | |
| 341 * FUNCTION: pkix_ForwardBuilderState_ToString | |
| 342 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) | |
| 343 */ | |
| 344 static PKIX_Error * | |
| 345 pkix_ForwardBuilderState_ToString | |
| 346 (PKIX_PL_Object *object, | |
| 347 PKIX_PL_String **pString, | |
| 348 void *plContext) | |
| 349 { | |
| 350 PKIX_ForwardBuilderState *state = NULL; | |
| 351 PKIX_PL_String *formatString = NULL; | |
| 352 PKIX_PL_String *resultString = NULL; | |
| 353 PKIX_PL_String *buildStatusString = NULL; | |
| 354 PKIX_PL_String *validityDateString = NULL; | |
| 355 PKIX_PL_String *prevCertString = NULL; | |
| 356 PKIX_PL_String *candidateCertString = NULL; | |
| 357 PKIX_PL_String *traversedSubjNamesString = NULL; | |
| 358 PKIX_PL_String *trustChainString = NULL; | |
| 359 PKIX_PL_String *candidateCertsString = NULL; | |
| 360 PKIX_PL_String *certSelString = NULL; | |
| 361 PKIX_PL_String *verifyNodeString = NULL; | |
| 362 PKIX_PL_String *parentStateString = NULL; | |
| 363 char *asciiFormat = "\n" | |
| 364 "\t{buildStatus: \t%s\n" | |
| 365 "\ttraversedCACerts: \t%d\n" | |
| 366 "\tcertStoreIndex: \t%d\n" | |
| 367 "\tnumCerts: \t%d\n" | |
| 368 "\tnumAias: \t%d\n" | |
| 369 "\tcertIndex: \t%d\n" | |
| 370 "\taiaIndex: \t%d\n" | |
| 371 "\tnumFanout: \t%d\n" | |
| 372 "\tnumDepth: \t%d\n" | |
| 373 "\treasonCode: \t%d\n" | |
| 374 "\trevCheckDelayed: \t%d\n" | |
| 375 "\tcanBeCached: \t%d\n" | |
| 376 "\tuseOnlyLocal: \t%d\n" | |
| 377 "\trevChecking: \t%d\n" | |
| 378 "\tvalidityDate: \t%s\n" | |
| 379 "\tprevCert: \t%s\n" | |
| 380 "\tcandidateCert: \t%s\n" | |
| 381 "\ttraversedSubjNames: \t%s\n" | |
| 382 "\ttrustChain: \t%s\n" | |
| 383 "\tcandidateCerts: \t%s\n" | |
| 384 "\tcertSel: \t%s\n" | |
| 385 "\tverifyNode: \t%s\n" | |
| 386 "\tparentState: \t%s}\n"; | |
| 387 char *asciiStatus = NULL; | |
| 388 | |
| 389 PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_ToString"); | |
| 390 PKIX_NULLCHECK_TWO(object, pString); | |
| 391 | |
| 392 PKIX_CHECK(pkix_CheckType | |
| 393 (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext), | |
| 394 PKIX_OBJECTNOTFORWARDBUILDERSTATE); | |
| 395 | |
| 396 state = (PKIX_ForwardBuilderState *)object; | |
| 397 | |
| 398 PKIX_CHECK(PKIX_PL_String_Create | |
| 399 (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), | |
| 400 PKIX_STRINGCREATEFAILED); | |
| 401 | |
| 402 switch (state->status) { | |
| 403 case BUILD_SHORTCUTPENDING: asciiStatus = "BUILD_SHORTCUTPENDING"; | |
| 404 break; | |
| 405 case BUILD_INITIAL: asciiStatus = "BUILD_INITIAL"; | |
| 406 break; | |
| 407 case BUILD_TRYAIA: asciiStatus = "BUILD_TRYAIA"; | |
| 408 break; | |
| 409 case BUILD_AIAPENDING: asciiStatus = "BUILD_AIAPENDING"; | |
| 410 break; | |
| 411 case BUILD_COLLECTINGCERTS: asciiStatus = "BUILD_COLLECTINGCERTS"; | |
| 412 break; | |
| 413 case BUILD_GATHERPENDING: asciiStatus = "BUILD_GATHERPENDING"; | |
| 414 break; | |
| 415 case BUILD_CERTVALIDATING: asciiStatus = "BUILD_CERTVALIDATING"; | |
| 416 break; | |
| 417 case BUILD_ABANDONNODE: asciiStatus = "BUILD_ABANDONNODE"; | |
| 418 break; | |
| 419 case BUILD_CRLPREP: asciiStatus = "BUILD_CRLPREP"; | |
| 420 break; | |
| 421 case BUILD_CRL1: asciiStatus = "BUILD_CRL1"; | |
| 422 break; | |
| 423 case BUILD_DATEPREP: asciiStatus = "BUILD_DATEPREP"; | |
| 424 break; | |
| 425 case BUILD_CHECKTRUSTED: asciiStatus = "BUILD_CHECKTRUSTED"; | |
| 426 break; | |
| 427 case BUILD_CHECKTRUSTED2: asciiStatus = "BUILD_CHECKTRUSTED2"; | |
| 428 break; | |
| 429 case BUILD_ADDTOCHAIN: asciiStatus = "BUILD_ADDTOCHAIN"; | |
| 430 break; | |
| 431 case BUILD_CRL2: asciiStatus = "BUILD_CRL2"; | |
| 432 break; | |
| 433 case BUILD_VALCHAIN: asciiStatus = "BUILD_VALCHAIN"; | |
| 434 break; | |
| 435 case BUILD_VALCHAIN2: asciiStatus = "BUILD_VALCHAIN2"; | |
| 436 break; | |
| 437 case BUILD_EXTENDCHAIN: asciiStatus = "BUILD_EXTENDCHAIN"; | |
| 438 break; | |
| 439 case BUILD_GETNEXTCERT: asciiStatus = "BUILD_GETNEXTCERT"; | |
| 440 break; | |
| 441 default: asciiStatus = "INVALID STATUS"; | |
| 442 break; | |
| 443 } | |
| 444 | |
| 445 PKIX_CHECK(PKIX_PL_String_Create | |
| 446 (PKIX_ESCASCII, asciiStatus, 0, &buildStatusString, plContext), | |
| 447 PKIX_STRINGCREATEFAILED); | |
| 448 | |
| 449 PKIX_TOSTRING | |
| 450 (state->validityDate, &validityDateString, plContext, | |
| 451 PKIX_OBJECTTOSTRINGFAILED); | |
| 452 | |
| 453 PKIX_TOSTRING | |
| 454 (state->prevCert, &prevCertString, plContext, | |
| 455 PKIX_OBJECTTOSTRINGFAILED); | |
| 456 | |
| 457 PKIX_TOSTRING | |
| 458 (state->candidateCert, &candidateCertString, plContext, | |
| 459 PKIX_OBJECTTOSTRINGFAILED); | |
| 460 | |
| 461 PKIX_TOSTRING | |
| 462 (state->traversedSubjNames, | |
| 463 &traversedSubjNamesString, | |
| 464 plContext, | |
| 465 PKIX_OBJECTTOSTRINGFAILED); | |
| 466 | |
| 467 PKIX_TOSTRING | |
| 468 (state->trustChain, &trustChainString, plContext, | |
| 469 PKIX_OBJECTTOSTRINGFAILED); | |
| 470 | |
| 471 PKIX_TOSTRING | |
| 472 (state->candidateCerts, &candidateCertsString, plContext, | |
| 473 PKIX_OBJECTTOSTRINGFAILED); | |
| 474 | |
| 475 PKIX_TOSTRING | |
| 476 (state->certSel, &certSelString, plContext, | |
| 477 PKIX_OBJECTTOSTRINGFAILED); | |
| 478 | |
| 479 PKIX_TOSTRING | |
| 480 (state->verifyNode, &verifyNodeString, plContext, | |
| 481 PKIX_OBJECTTOSTRINGFAILED); | |
| 482 | |
| 483 PKIX_TOSTRING | |
| 484 (state->parentState, &parentStateString, plContext, | |
| 485 PKIX_OBJECTTOSTRINGFAILED); | |
| 486 | |
| 487 PKIX_CHECK(PKIX_PL_Sprintf | |
| 488 (&resultString, | |
| 489 plContext, | |
| 490 formatString, | |
| 491 buildStatusString, | |
| 492 (PKIX_Int32)state->traversedCACerts, | |
| 493 (PKIX_UInt32)state->certStoreIndex, | |
| 494 (PKIX_UInt32)state->numCerts, | |
| 495 (PKIX_UInt32)state->numAias, | |
| 496 (PKIX_UInt32)state->certIndex, | |
| 497 (PKIX_UInt32)state->aiaIndex, | |
| 498 (PKIX_UInt32)state->numFanout, | |
| 499 (PKIX_UInt32)state->numDepth, | |
| 500 (PKIX_UInt32)state->reasonCode, | |
| 501 state->revCheckDelayed, | |
| 502 state->canBeCached, | |
| 503 state->useOnlyLocal, | |
| 504 state->revChecking, | |
| 505 validityDateString, | |
| 506 prevCertString, | |
| 507 candidateCertString, | |
| 508 traversedSubjNamesString, | |
| 509 trustChainString, | |
| 510 candidateCertsString, | |
| 511 certSelString, | |
| 512 verifyNodeString, | |
| 513 parentStateString), | |
| 514 PKIX_SPRINTFFAILED); | |
| 515 | |
| 516 *pString = resultString; | |
| 517 | |
| 518 cleanup: | |
| 519 PKIX_DECREF(formatString); | |
| 520 PKIX_DECREF(buildStatusString); | |
| 521 PKIX_DECREF(validityDateString); | |
| 522 PKIX_DECREF(prevCertString); | |
| 523 PKIX_DECREF(candidateCertString); | |
| 524 PKIX_DECREF(traversedSubjNamesString); | |
| 525 PKIX_DECREF(trustChainString); | |
| 526 PKIX_DECREF(candidateCertsString); | |
| 527 PKIX_DECREF(certSelString); | |
| 528 PKIX_DECREF(verifyNodeString); | |
| 529 PKIX_DECREF(parentStateString); | |
| 530 | |
| 531 PKIX_RETURN(FORWARDBUILDERSTATE); | |
| 532 | |
| 533 } | |
| 534 | |
| 535 /* | |
| 536 * FUNCTION: pkix_ForwardBuilderState_RegisterSelf | |
| 537 * | |
| 538 * DESCRIPTION: | |
| 539 * Registers PKIX_FORWARDBUILDERSTATE_TYPE and its related functions | |
| 540 * with systemClasses[] | |
| 541 * | |
| 542 * THREAD SAFETY: | |
| 543 * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 544 * | |
| 545 * Since this function is only called by PKIX_PL_Initialize, which should | |
| 546 * only be called once, it is acceptable that this function is not | |
| 547 * thread-safe. | |
| 548 */ | |
| 549 PKIX_Error * | |
| 550 pkix_ForwardBuilderState_RegisterSelf(void *plContext) | |
| 551 { | |
| 552 | |
| 553 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
| 554 pkix_ClassTable_Entry entry; | |
| 555 | |
| 556 PKIX_ENTER(FORWARDBUILDERSTATE, | |
| 557 "pkix_ForwardBuilderState_RegisterSelf"); | |
| 558 | |
| 559 entry.description = "ForwardBuilderState"; | |
| 560 entry.objCounter = 0; | |
| 561 entry.typeObjectSize = sizeof(PKIX_ForwardBuilderState); | |
| 562 entry.destructor = pkix_ForwardBuilderState_Destroy; | |
| 563 entry.equalsFunction = NULL; | |
| 564 entry.hashcodeFunction = NULL; | |
| 565 entry.toStringFunction = pkix_ForwardBuilderState_ToString; | |
| 566 entry.comparator = NULL; | |
| 567 entry.duplicateFunction = NULL; | |
| 568 | |
| 569 systemClasses[PKIX_FORWARDBUILDERSTATE_TYPE] = entry; | |
| 570 | |
| 571 PKIX_RETURN(FORWARDBUILDERSTATE); | |
| 572 } | |
| 573 | |
| 574 #if PKIX_FORWARDBUILDERSTATEDEBUG | |
| 575 /* | |
| 576 * FUNCTION: pkix_ForwardBuilderState_DumpState | |
| 577 * | |
| 578 * DESCRIPTION: | |
| 579 * This function invokes the ToString function on the argument pointed to | |
| 580 * by "state". | |
| 581 * PARAMETERS: | |
| 582 * "state" | |
| 583 * The address of the ForwardBuilderState object. Must be non-NULL. | |
| 584 * | |
| 585 * THREAD SAFETY: | |
| 586 * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 587 */ | |
| 588 PKIX_Error * | |
| 589 pkix_ForwardBuilderState_DumpState( | |
| 590 PKIX_ForwardBuilderState *state, | |
| 591 void *plContext) | |
| 592 { | |
| 593 PKIX_PL_String *stateString = NULL; | |
| 594 char *stateAscii = NULL; | |
| 595 PKIX_UInt32 length; | |
| 596 | |
| 597 PKIX_ENTER(FORWARDBUILDERSTATE,"pkix_ForwardBuilderState_DumpState"); | |
| 598 PKIX_NULLCHECK_ONE(state); | |
| 599 | |
| 600 PKIX_CHECK(PKIX_PL_Object_InvalidateCache | |
| 601 ((PKIX_PL_Object *)state, plContext), | |
| 602 PKIX_OBJECTINVALIDATECACHEFAILED); | |
| 603 | |
| 604 PKIX_CHECK(PKIX_PL_Object_ToString | |
| 605 ((PKIX_PL_Object*)state, &stateString, plContext), | |
| 606 PKIX_OBJECTTOSTRINGFAILED); | |
| 607 | |
| 608 PKIX_CHECK(PKIX_PL_String_GetEncoded | |
| 609 (stateString, | |
| 610 PKIX_ESCASCII, | |
| 611 (void **)&stateAscii, | |
| 612 &length, | |
| 613 plContext), | |
| 614 PKIX_STRINGGETENCODEDFAILED); | |
| 615 | |
| 616 PKIX_DEBUG_ARG("In Phase 1: state = %s\n", stateAscii); | |
| 617 | |
| 618 PKIX_FREE(stateAscii); | |
| 619 PKIX_DECREF(stateString); | |
| 620 | |
| 621 cleanup: | |
| 622 PKIX_RETURN(FORWARDBUILDERSTATE); | |
| 623 } | |
| 624 #endif | |
| 625 | |
| 626 /* | |
| 627 * FUNCTION: pkix_ForwardBuilderState_IsIOPending | |
| 628 * DESCRIPTION: | |
| 629 * | |
| 630 * This function determines whether the state of the ForwardBuilderState | |
| 631 * pointed to by "state" indicates I/O is in progress, and stores the Boolean | |
| 632 * result at "pPending". | |
| 633 * | |
| 634 * PARAMETERS: | |
| 635 * "state" | |
| 636 * The address of the ForwardBuilderState object. Must be non-NULL. | |
| 637 * "pPending" | |
| 638 * The address at which the result is stored. Must be non-NULL. | |
| 639 * "plContext" | |
| 640 * Platform-specific context pointer. | |
| 641 * THREAD SAFETY: | |
| 642 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 643 * RETURNS: | |
| 644 * Returns NULL if the function succeeds. | |
| 645 * Returns a ForwardBuilderState Error if the function fails in a | |
| 646 * non-fatal way. | |
| 647 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 648 */ | |
| 649 static PKIX_Error* | |
| 650 pkix_ForwardBuilderState_IsIOPending( | |
| 651 PKIX_ForwardBuilderState *state, | |
| 652 PKIX_Boolean *pPending, | |
| 653 void *plContext) | |
| 654 { | |
| 655 PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_IsIOPending"); | |
| 656 PKIX_NULLCHECK_TWO(state, pPending); | |
| 657 | |
| 658 if ((state->status == BUILD_GATHERPENDING) || | |
| 659 (state->status == BUILD_CRL1) || | |
| 660 (state->status == BUILD_CRL2) || | |
| 661 (state->status == BUILD_CHECKTRUSTED2) || | |
| 662 (state->status == BUILD_VALCHAIN2) || | |
| 663 (state->status == BUILD_AIAPENDING)) { | |
| 664 *pPending = PKIX_TRUE; | |
| 665 } else { | |
| 666 *pPending = PKIX_FALSE; | |
| 667 } | |
| 668 | |
| 669 PKIX_RETURN(FORWARDBUILDERSTATE); | |
| 670 } | |
| 671 | |
| 672 /* --Private-BuildChain-Functions------------------------------------------- */ | |
| 673 | |
| 674 /* | |
| 675 * FUNCTION: pkix_Build_SortCertComparator | |
| 676 * DESCRIPTION: | |
| 677 * | |
| 678 * This Function takes two Certificates cast in "obj1" and "obj2", | |
| 679 * compares their validity NotAfter dates and returns the result at | |
| 680 * "pResult". The comparison key(s) can be expanded by using other | |
| 681 * data in the Certificate in the future. | |
| 682 * | |
| 683 * PARAMETERS: | |
| 684 * "obj1" | |
| 685 * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert. | |
| 686 * Must be non-NULL. | |
| 687 * "obj2" | |
| 688 * Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert. | |
| 689 * Must be non-NULL. | |
| 690 * "pResult" | |
| 691 * Address where the comparison result is returned. Must be non-NULL. | |
| 692 * "plContext" | |
| 693 * Platform-specific context pointer. | |
| 694 * THREAD SAFETY: | |
| 695 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 696 * RETURNS: | |
| 697 * Returns NULL if the function succeeds. | |
| 698 * Returns a Build Error if the function fails in a non-fatal way | |
| 699 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 700 */ | |
| 701 static PKIX_Error * | |
| 702 pkix_Build_SortCertComparator( | |
| 703 PKIX_PL_Object *obj1, | |
| 704 PKIX_PL_Object *obj2, | |
| 705 PKIX_Int32 *pResult, | |
| 706 void *plContext) | |
| 707 { | |
| 708 PKIX_PL_Date *date1 = NULL; | |
| 709 PKIX_PL_Date *date2 = NULL; | |
| 710 PKIX_Boolean result = PKIX_FALSE; | |
| 711 | |
| 712 PKIX_ENTER(BUILD, "pkix_Build_SortCertComparator"); | |
| 713 PKIX_NULLCHECK_THREE(obj1, obj2, pResult); | |
| 714 | |
| 715 /* | |
| 716 * For sorting candidate certificates, we use NotAfter date as the | |
| 717 * sorted key for now (can be expanded if desired in the future). | |
| 718 * | |
| 719 * In PKIX_BuildChain, the List of CertStores was reordered so that | |
| 720 * trusted CertStores are ahead of untrusted CertStores. That sort, or | |
| 721 * this one, could be taken out if it is determined that it doesn't help | |
| 722 * performance, or in some way hinders the solution of choosing desired | |
| 723 * candidates. | |
| 724 */ | |
| 725 | |
| 726 PKIX_CHECK(pkix_CheckType(obj1, PKIX_CERT_TYPE, plContext), | |
| 727 PKIX_OBJECTNOTCERT); | |
| 728 PKIX_CHECK(pkix_CheckType(obj2, PKIX_CERT_TYPE, plContext), | |
| 729 PKIX_OBJECTNOTCERT); | |
| 730 | |
| 731 PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter | |
| 732 ((PKIX_PL_Cert *)obj1, &date1, plContext), | |
| 733 PKIX_CERTGETVALIDITYNOTAFTERFAILED); | |
| 734 | |
| 735 PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter | |
| 736 ((PKIX_PL_Cert *)obj2, &date2, plContext), | |
| 737 PKIX_CERTGETVALIDITYNOTAFTERFAILED); | |
| 738 | |
| 739 PKIX_CHECK(PKIX_PL_Object_Compare | |
| 740 ((PKIX_PL_Object *)date1, | |
| 741 (PKIX_PL_Object *)date2, | |
| 742 &result, | |
| 743 plContext), | |
| 744 PKIX_OBJECTCOMPARATORFAILED); | |
| 745 | |
| 746 *pResult = !result; | |
| 747 | |
| 748 cleanup: | |
| 749 | |
| 750 PKIX_DECREF(date1); | |
| 751 PKIX_DECREF(date2); | |
| 752 | |
| 753 PKIX_RETURN(BUILD); | |
| 754 } | |
| 755 | |
| 756 /* This local error check macro */ | |
| 757 #define ERROR_CHECK(errCode) \ | |
| 758 if (pkixErrorResult) { \ | |
| 759 if (pkixLog) { \ | |
| 760 PR_LOG(pkixLog, PR_LOG_DEBUG, ("====> ERROR_CHECK code %s\n", #errCo
de)); \ | |
| 761 } \ | |
| 762 pkixTempErrorReceived = PKIX_TRUE; \ | |
| 763 pkixErrorClass = pkixErrorResult->errClass; \ | |
| 764 if (pkixErrorClass == PKIX_FATAL_ERROR) { \ | |
| 765 goto cleanup; \ | |
| 766 } \ | |
| 767 if (verifyNode) { \ | |
| 768 PKIX_DECREF(verifyNode->error); \ | |
| 769 PKIX_INCREF(pkixErrorResult); \ | |
| 770 verifyNode->error = pkixErrorResult; \ | |
| 771 } \ | |
| 772 pkixErrorCode = errCode; \ | |
| 773 goto cleanup; \ | |
| 774 } | |
| 775 | |
| 776 /* | |
| 777 * FUNCTION: pkix_Build_VerifyCertificate | |
| 778 * DESCRIPTION: | |
| 779 * | |
| 780 * Checks whether the previous Cert stored in the ForwardBuilderState pointed | |
| 781 * to by "state" successfully chains, including signature verification, to the | |
| 782 * candidate Cert also stored in "state", using the Boolean value in "trusted" | |
| 783 * to determine whether "candidateCert" is trusted. Using the Boolean value in | |
| 784 * "revocationChecking" for the existence of revocation checking, it sets | |
| 785 * "pNeedsCRLChecking" to PKIX_TRUE if the candidate Cert needs to be checked | |
| 786 * against Certificate Revocation Lists. | |
| 787 * | |
| 788 * First it checks whether "candidateCert" has already been traversed by | |
| 789 * determining whether it is contained in the List of traversed Certs. It | |
| 790 * checks the candidate Cert with user checkers, if any, in the List pointed to | |
| 791 * by "userCheckers". It then runs the signature validation. Finally, it | |
| 792 * determines the appropriate value for "pNeedsCRLChecking". | |
| 793 * | |
| 794 * If this Certificate fails verification, and state->verifyNode is non-NULL, | |
| 795 * this function sets the Error code into the verifyNode. | |
| 796 * | |
| 797 * PARAMETERS: | |
| 798 * "state" | |
| 799 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
| 800 * "userCheckers" | |
| 801 * Address of a List of CertChainCheckers to be used, if present, to | |
| 802 * validate the candidateCert. | |
| 803 * "revocationChecking" | |
| 804 * Boolean indication of whether revocation checking is available, either | |
| 805 * as a CertChainChecker or a List of RevocationCheckers. | |
| 806 * "trusted" | |
| 807 * Boolean value of trust for the candidate Cert | |
| 808 * "pNeedsCRLChecking" | |
| 809 * Address where Boolean CRL-checking-needed value is stored. | |
| 810 * Must be non-NULL. | |
| 811 * "plContext" | |
| 812 * Platform-specific context pointer. | |
| 813 * THREAD SAFETY: | |
| 814 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 815 * RETURNS: | |
| 816 * Returns NULL if the function succeeds. | |
| 817 * Returns a Build Error if the function fails in a non-fatal way | |
| 818 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 819 */ | |
| 820 static PKIX_Error * | |
| 821 pkix_Build_VerifyCertificate( | |
| 822 PKIX_ForwardBuilderState *state, | |
| 823 PKIX_List *userCheckers, | |
| 824 PKIX_Boolean revocationChecking, | |
| 825 PKIX_Boolean *pTrusted, | |
| 826 PKIX_Boolean *pNeedsCRLChecking, | |
| 827 PKIX_VerifyNode *verifyNode, | |
| 828 void *plContext) | |
| 829 { | |
| 830 PKIX_UInt32 numUserCheckers = 0; | |
| 831 PKIX_UInt32 i = 0; | |
| 832 PKIX_Boolean loopFound = PKIX_FALSE; | |
| 833 PKIX_Boolean supportForwardChecking = PKIX_FALSE; | |
| 834 PKIX_Boolean trusted = PKIX_FALSE; | |
| 835 PKIX_PL_Cert *candidateCert = NULL; | |
| 836 PKIX_PL_PublicKey *candidatePubKey = NULL; | |
| 837 PKIX_CertChainChecker *userChecker = NULL; | |
| 838 PKIX_CertChainChecker_CheckCallback checkerCheck = NULL; | |
| 839 PKIX_Boolean trustOnlyUserAnchors = PKIX_FALSE; | |
| 840 void *nbioContext = NULL; | |
| 841 | |
| 842 PKIX_ENTER(BUILD, "pkix_Build_VerifyCertificate"); | |
| 843 PKIX_NULLCHECK_THREE(state, pTrusted, pNeedsCRLChecking); | |
| 844 PKIX_NULLCHECK_THREE | |
| 845 (state->candidateCerts, state->prevCert, state->trustChain); | |
| 846 | |
| 847 *pNeedsCRLChecking = PKIX_FALSE; | |
| 848 | |
| 849 PKIX_INCREF(state->candidateCert); | |
| 850 candidateCert = state->candidateCert; | |
| 851 | |
| 852 if (state->buildConstants.numAnchors) { | |
| 853 trustOnlyUserAnchors = state->buildConstants.trustOnlyUserAnchors; | |
| 854 } | |
| 855 | |
| 856 PKIX_CHECK( | |
| 857 PKIX_PL_Cert_IsCertTrusted(candidateCert, | |
| 858 trustOnlyUserAnchors, | |
| 859 &trusted, plContext), | |
| 860 PKIX_CERTISCERTTRUSTEDFAILED); | |
| 861 | |
| 862 *pTrusted = trusted; | |
| 863 | |
| 864 /* check for loops */ | |
| 865 PKIX_CHECK(pkix_List_Contains | |
| 866 (state->trustChain, | |
| 867 (PKIX_PL_Object *)candidateCert, | |
| 868 &loopFound, | |
| 869 plContext), | |
| 870 PKIX_LISTCONTAINSFAILED); | |
| 871 | |
| 872 if (loopFound) { | |
| 873 if (verifyNode != NULL) { | |
| 874 PKIX_Error *verifyError = NULL; | |
| 875 PKIX_ERROR_CREATE | |
| 876 (BUILD, | |
| 877 PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED, | |
| 878 verifyError); | |
| 879 PKIX_DECREF(verifyNode->error); | |
| 880 verifyNode->error = verifyError; | |
| 881 } | |
| 882 /* Even if error logged, still need to abort | |
| 883 * if cert is not trusted. */ | |
| 884 if (!trusted) { | |
| 885 PKIX_ERROR(PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED); | |
| 886 } | |
| 887 state->certLoopingDetected = PKIX_TRUE; | |
| 888 } | |
| 889 | |
| 890 if (userCheckers != NULL) { | |
| 891 | |
| 892 PKIX_CHECK(PKIX_List_GetLength | |
| 893 (userCheckers, &numUserCheckers, plContext), | |
| 894 PKIX_LISTGETLENGTHFAILED); | |
| 895 | |
| 896 for (i = 0; i < numUserCheckers; i++) { | |
| 897 | |
| 898 PKIX_CHECK(PKIX_List_GetItem | |
| 899 (userCheckers, | |
| 900 i, | |
| 901 (PKIX_PL_Object **) &userChecker, | |
| 902 plContext), | |
| 903 PKIX_LISTGETITEMFAILED); | |
| 904 | |
| 905 PKIX_CHECK | |
| 906 (PKIX_CertChainChecker_IsForwardCheckingSupported | |
| 907 (userChecker, &supportForwardChecking, plContext), | |
| 908 PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED); | |
| 909 | |
| 910 if (supportForwardChecking == PKIX_TRUE) { | |
| 911 | |
| 912 PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback | |
| 913 (userChecker, &checkerCheck, plContext), | |
| 914 PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED); | |
| 915 | |
| 916 pkixErrorResult = | |
| 917 checkerCheck(userChecker, candidateCert, NULL, | |
| 918 &nbioContext, plContext); | |
| 919 | |
| 920 ERROR_CHECK(PKIX_USERCHECKERCHECKFAILED); | |
| 921 } | |
| 922 | |
| 923 PKIX_DECREF(userChecker); | |
| 924 } | |
| 925 } | |
| 926 | |
| 927 /* Check that public key of the trusted dsa cert has | |
| 928 * dsa parameters */ | |
| 929 if (trusted) { | |
| 930 PKIX_Boolean paramsNeeded = PKIX_FALSE; | |
| 931 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey | |
| 932 (candidateCert, &candidatePubKey, plContext), | |
| 933 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); | |
| 934 PKIX_CHECK(PKIX_PL_PublicKey_NeedsDSAParameters | |
| 935 (candidatePubKey, ¶msNeeded, plContext), | |
| 936 PKIX_PUBLICKEYNEEDSDSAPARAMETERSFAILED); | |
| 937 if (paramsNeeded) { | |
| 938 PKIX_ERROR(PKIX_MISSINGDSAPARAMETERS); | |
| 939 } | |
| 940 } | |
| 941 | |
| 942 | |
| 943 if (revocationChecking) { | |
| 944 if (!trusted) { | |
| 945 if (state->revCheckDelayed) { | |
| 946 goto cleanup; | |
| 947 } else { | |
| 948 PKIX_Boolean isSelfIssued = PKIX_FALSE; | |
| 949 PKIX_CHECK( | |
| 950 pkix_IsCertSelfIssued(candidateCert, &isSelfIssued, | |
| 951 plContext), | |
| 952 PKIX_ISCERTSELFISSUEDFAILED); | |
| 953 if (isSelfIssued) { | |
| 954 state->revCheckDelayed = PKIX_TRUE; | |
| 955 goto cleanup; | |
| 956 } | |
| 957 } | |
| 958 } | |
| 959 *pNeedsCRLChecking = PKIX_TRUE; | |
| 960 } | |
| 961 | |
| 962 cleanup: | |
| 963 PKIX_DECREF(candidateCert); | |
| 964 PKIX_DECREF(candidatePubKey); | |
| 965 PKIX_DECREF(userChecker); | |
| 966 | |
| 967 PKIX_RETURN(BUILD); | |
| 968 } | |
| 969 | |
| 970 /* | |
| 971 * FUNCTION: pkix_Build_ValidationCheckers | |
| 972 * DESCRIPTION: | |
| 973 * | |
| 974 * Creates a List of Objects to be used in determining whether the List of | |
| 975 * Certs pointed to by "certChain" successfully validates using the | |
| 976 * ForwardBuilderState pointed to by "state", and the TrustAnchor pointed to by | |
| 977 * "anchor". These objects are a reversed Cert Chain, consisting of the certs | |
| 978 * in "certChain" in reversed order, suitable for presenting to the | |
| 979 * CertChainCheckers; a List of critical extension OIDS that have already been | |
| 980 * processed in forward building; a List of CertChainCheckers to be called, and | |
| 981 * a List of RevocationCheckers to be called. These results are stored in | |
| 982 * fields of "state". | |
| 983 * | |
| 984 * PARAMETERS: | |
| 985 * "state" | |
| 986 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
| 987 * "certChain" | |
| 988 * Address of List of Certs to be validated. Must be non-NULL. | |
| 989 * "anchor" | |
| 990 * Address of TrustAnchor to be used. Must be non-NULL. | |
| 991 * "addEkuChecker" | |
| 992 * Boolean flags that tells to add eku checker to the list | |
| 993 * of checkers. Only needs to be done for existing chain revalidation. | |
| 994 * "plContext" | |
| 995 * Platform-specific context pointer. | |
| 996 * THREAD SAFETY: | |
| 997 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 998 * RETURNS: | |
| 999 * Returns NULL if the function succeeds. | |
| 1000 * Returns a Build Error if the function fails in a non-fatal way | |
| 1001 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 1002 */ | |
| 1003 static PKIX_Error * | |
| 1004 pkix_Build_ValidationCheckers( | |
| 1005 PKIX_ForwardBuilderState *state, | |
| 1006 PKIX_List *certChain, | |
| 1007 PKIX_TrustAnchor *anchor, | |
| 1008 PKIX_Boolean chainRevalidationStage, | |
| 1009 void *plContext) | |
| 1010 { | |
| 1011 PKIX_List *checkers = NULL; | |
| 1012 PKIX_List *initialPolicies = NULL; | |
| 1013 PKIX_List *reversedCertChain = NULL; | |
| 1014 PKIX_List *buildCheckedCritExtOIDsList = NULL; | |
| 1015 PKIX_ProcessingParams *procParams = NULL; | |
| 1016 PKIX_PL_Cert *trustedCert = NULL; | |
| 1017 PKIX_PL_PublicKey *trustedPubKey = NULL; | |
| 1018 PKIX_CertChainChecker *sigChecker = NULL; | |
| 1019 PKIX_CertChainChecker *policyChecker = NULL; | |
| 1020 PKIX_CertChainChecker *userChecker = NULL; | |
| 1021 PKIX_CertChainChecker *checker = NULL; | |
| 1022 PKIX_CertSelector *certSelector = NULL; | |
| 1023 PKIX_List *userCheckerExtOIDs = NULL; | |
| 1024 PKIX_PL_OID *oid = NULL; | |
| 1025 PKIX_Boolean supportForwardChecking = PKIX_FALSE; | |
| 1026 PKIX_Boolean policyQualifiersRejected = PKIX_FALSE; | |
| 1027 PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE; | |
| 1028 PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE; | |
| 1029 PKIX_Boolean initialExplicitPolicy = PKIX_FALSE; | |
| 1030 PKIX_UInt32 numChainCerts; | |
| 1031 PKIX_UInt32 numCertCheckers; | |
| 1032 PKIX_UInt32 i; | |
| 1033 | |
| 1034 PKIX_ENTER(BUILD, "pkix_Build_ValidationCheckers"); | |
| 1035 PKIX_NULLCHECK_THREE(state, certChain, anchor); | |
| 1036 | |
| 1037 PKIX_CHECK(PKIX_List_Create(&checkers, plContext), | |
| 1038 PKIX_LISTCREATEFAILED); | |
| 1039 | |
| 1040 PKIX_CHECK(PKIX_List_ReverseList | |
| 1041 (certChain, &reversedCertChain, plContext), | |
| 1042 PKIX_LISTREVERSELISTFAILED); | |
| 1043 | |
| 1044 PKIX_CHECK(PKIX_List_GetLength | |
| 1045 (reversedCertChain, &numChainCerts, plContext), | |
| 1046 PKIX_LISTGETLENGTHFAILED); | |
| 1047 | |
| 1048 procParams = state->buildConstants.procParams; | |
| 1049 | |
| 1050 /* Do need to add a number of checker to revalidate | |
| 1051 * a built chain. KU, EKU, CertType and Validity Date | |
| 1052 * get checked by certificate selector during chain | |
| 1053 * construction, but needed to be checked for chain from | |
| 1054 * the cache.*/ | |
| 1055 if (chainRevalidationStage) { | |
| 1056 PKIX_CHECK(pkix_ExpirationChecker_Initialize | |
| 1057 (state->buildConstants.testDate, &checker, plContext), | |
| 1058 PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); | |
| 1059 PKIX_CHECK(PKIX_List_AppendItem | |
| 1060 (checkers, (PKIX_PL_Object *)checker, plContext), | |
| 1061 PKIX_LISTAPPENDITEMFAILED); | |
| 1062 PKIX_DECREF(checker); | |
| 1063 | |
| 1064 PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints | |
| 1065 (procParams, &certSelector, plContext), | |
| 1066 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); | |
| 1067 | |
| 1068 PKIX_CHECK(pkix_TargetCertChecker_Initialize | |
| 1069 (certSelector, numChainCerts, &checker, plContext), | |
| 1070 PKIX_EXPIRATIONCHECKERINITIALIZEFAILED); | |
| 1071 PKIX_CHECK(PKIX_List_AppendItem | |
| 1072 (checkers, (PKIX_PL_Object *)checker, plContext), | |
| 1073 PKIX_LISTAPPENDITEMFAILED); | |
| 1074 PKIX_DECREF(checker); | |
| 1075 } | |
| 1076 | |
| 1077 PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies | |
| 1078 (procParams, &initialPolicies, plContext), | |
| 1079 PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED); | |
| 1080 | |
| 1081 PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected | |
| 1082 (procParams, &policyQualifiersRejected, plContext), | |
| 1083 PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED); | |
| 1084 | |
| 1085 PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited | |
| 1086 (procParams, &initialPolicyMappingInhibit, plContext), | |
| 1087 PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED); | |
| 1088 | |
| 1089 PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited | |
| 1090 (procParams, &initialAnyPolicyInhibit, plContext), | |
| 1091 PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED); | |
| 1092 | |
| 1093 PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired | |
| 1094 (procParams, &initialExplicitPolicy, plContext), | |
| 1095 PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED); | |
| 1096 | |
| 1097 PKIX_CHECK(pkix_PolicyChecker_Initialize | |
| 1098 (initialPolicies, | |
| 1099 policyQualifiersRejected, | |
| 1100 initialPolicyMappingInhibit, | |
| 1101 initialExplicitPolicy, | |
| 1102 initialAnyPolicyInhibit, | |
| 1103 numChainCerts, | |
| 1104 &policyChecker, | |
| 1105 plContext), | |
| 1106 PKIX_POLICYCHECKERINITIALIZEFAILED); | |
| 1107 | |
| 1108 PKIX_CHECK(PKIX_List_AppendItem | |
| 1109 (checkers, (PKIX_PL_Object *)policyChecker, plContext), | |
| 1110 PKIX_LISTAPPENDITEMFAILED); | |
| 1111 | |
| 1112 /* | |
| 1113 * Create an OID list that contains critical extensions processed | |
| 1114 * by BuildChain. These are specified in a static const array. | |
| 1115 */ | |
| 1116 PKIX_CHECK(PKIX_List_Create(&buildCheckedCritExtOIDsList, plContext), | |
| 1117 PKIX_LISTCREATEFAILED); | |
| 1118 | |
| 1119 for (i = 0; buildCheckedCritExtOIDs[i] != PKIX_UNKNOWN_OID; i++) { | |
| 1120 PKIX_CHECK(PKIX_PL_OID_Create | |
| 1121 (buildCheckedCritExtOIDs[i], &oid, plContext), | |
| 1122 PKIX_OIDCREATEFAILED); | |
| 1123 | |
| 1124 PKIX_CHECK(PKIX_List_AppendItem | |
| 1125 (buildCheckedCritExtOIDsList, | |
| 1126 (PKIX_PL_Object *) oid, | |
| 1127 plContext), | |
| 1128 PKIX_LISTAPPENDITEMFAILED); | |
| 1129 | |
| 1130 PKIX_DECREF(oid); | |
| 1131 } | |
| 1132 | |
| 1133 if (state->buildConstants.userCheckers != NULL) { | |
| 1134 | |
| 1135 PKIX_CHECK(PKIX_List_GetLength | |
| 1136 (state->buildConstants.userCheckers, | |
| 1137 &numCertCheckers, | |
| 1138 plContext), | |
| 1139 PKIX_LISTGETLENGTHFAILED); | |
| 1140 | |
| 1141 for (i = 0; i < numCertCheckers; i++) { | |
| 1142 | |
| 1143 PKIX_CHECK(PKIX_List_GetItem | |
| 1144 (state->buildConstants.userCheckers, | |
| 1145 i, | |
| 1146 (PKIX_PL_Object **) &userChecker, | |
| 1147 plContext), | |
| 1148 PKIX_LISTGETITEMFAILED); | |
| 1149 | |
| 1150 PKIX_CHECK | |
| 1151 (PKIX_CertChainChecker_IsForwardCheckingSupported | |
| 1152 (userChecker, &supportForwardChecking, plContext), | |
| 1153 PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); | |
| 1154 | |
| 1155 /* | |
| 1156 * If this userChecker supports forwardChecking then it | |
| 1157 * should have been checked during build chain. Skip | |
| 1158 * checking but need to add checker's extension OIDs | |
| 1159 * to buildCheckedCritExtOIDsList. | |
| 1160 */ | |
| 1161 if (supportForwardChecking == PKIX_TRUE) { | |
| 1162 | |
| 1163 PKIX_CHECK | |
| 1164 (PKIX_CertChainChecker_GetSupportedExtensions | |
| 1165 (userChecker, &userCheckerExtOIDs, plContext), | |
| 1166 PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED); | |
| 1167 | |
| 1168 if (userCheckerExtOIDs != NULL) { | |
| 1169 PKIX_CHECK(pkix_List_AppendList | |
| 1170 (buildCheckedCritExtOIDsList, | |
| 1171 userCheckerExtOIDs, | |
| 1172 plContext), | |
| 1173 PKIX_LISTAPPENDLISTFAILED); | |
| 1174 } | |
| 1175 | |
| 1176 } else { | |
| 1177 PKIX_CHECK(PKIX_List_AppendItem | |
| 1178 (checkers, | |
| 1179 (PKIX_PL_Object *)userChecker, | |
| 1180 plContext), | |
| 1181 PKIX_LISTAPPENDITEMFAILED); | |
| 1182 } | |
| 1183 | |
| 1184 PKIX_DECREF(userCheckerExtOIDs); | |
| 1185 PKIX_DECREF(userChecker); | |
| 1186 } | |
| 1187 } | |
| 1188 | |
| 1189 /* Inabling post chain building signature check on the certs. */ | |
| 1190 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert | |
| 1191 (anchor, &trustedCert, plContext), | |
| 1192 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); | |
| 1193 | |
| 1194 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey | |
| 1195 (trustedCert, &trustedPubKey, plContext), | |
| 1196 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); | |
| 1197 | |
| 1198 PKIX_CHECK(pkix_SignatureChecker_Initialize | |
| 1199 (trustedPubKey, | |
| 1200 numChainCerts, | |
| 1201 &sigChecker, | |
| 1202 plContext), | |
| 1203 PKIX_SIGNATURECHECKERINITIALIZEFAILED); | |
| 1204 | |
| 1205 PKIX_CHECK(PKIX_List_AppendItem | |
| 1206 (checkers, | |
| 1207 (PKIX_PL_Object *)sigChecker, | |
| 1208 plContext), | |
| 1209 PKIX_LISTAPPENDITEMFAILED); | |
| 1210 | |
| 1211 PKIX_DECREF(state->reversedCertChain); | |
| 1212 PKIX_INCREF(reversedCertChain); | |
| 1213 state->reversedCertChain = reversedCertChain; | |
| 1214 PKIX_DECREF(state->checkedCritExtOIDs); | |
| 1215 PKIX_INCREF(buildCheckedCritExtOIDsList); | |
| 1216 state->checkedCritExtOIDs = buildCheckedCritExtOIDsList; | |
| 1217 PKIX_DECREF(state->checkerChain); | |
| 1218 state->checkerChain = checkers; | |
| 1219 checkers = NULL; | |
| 1220 state->certCheckedIndex = 0; | |
| 1221 state->checkerIndex = 0; | |
| 1222 state->revChecking = PKIX_FALSE; | |
| 1223 | |
| 1224 | |
| 1225 cleanup: | |
| 1226 | |
| 1227 PKIX_DECREF(oid); | |
| 1228 PKIX_DECREF(reversedCertChain); | |
| 1229 PKIX_DECREF(buildCheckedCritExtOIDsList); | |
| 1230 PKIX_DECREF(checker); | |
| 1231 PKIX_DECREF(checkers); | |
| 1232 PKIX_DECREF(initialPolicies); | |
| 1233 PKIX_DECREF(trustedCert); | |
| 1234 PKIX_DECREF(trustedPubKey); | |
| 1235 PKIX_DECREF(certSelector); | |
| 1236 PKIX_DECREF(sigChecker); | |
| 1237 PKIX_DECREF(policyChecker); | |
| 1238 PKIX_DECREF(userChecker); | |
| 1239 PKIX_DECREF(userCheckerExtOIDs); | |
| 1240 | |
| 1241 PKIX_RETURN(BUILD); | |
| 1242 } | |
| 1243 | |
| 1244 /* | |
| 1245 * FUNCTION: pkix_Build_ValidateEntireChain | |
| 1246 * DESCRIPTION: | |
| 1247 * | |
| 1248 * Checks whether the current List of Certs successfully validates using the | |
| 1249 * TrustAnchor pointed to by "anchor" and other parameters contained, as was | |
| 1250 * the Cert List, in "state". | |
| 1251 * | |
| 1252 * If a checker using non-blocking I/O returns with a non-NULL non-blocking I/O | |
| 1253 * context (NBIOContext), an indication that I/O is in progress and the | |
| 1254 * checking has not been completed, this function stores that context at | |
| 1255 * "pNBIOContext". Otherwise, it stores NULL at "pNBIOContext". | |
| 1256 * | |
| 1257 * If not awaiting I/O and if successful, a ValidateResult is created | |
| 1258 * containing the Public Key of the target certificate (including DSA parameter | |
| 1259 * inheritance, if any) and the PolicyNode representing the policy tree output | |
| 1260 * by the validation algorithm. If not successful, an Error pointer is | |
| 1261 * returned. | |
| 1262 * | |
| 1263 * PARAMETERS: | |
| 1264 * "state" | |
| 1265 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
| 1266 * "anchor" | |
| 1267 * Address of TrustAnchor to be used. Must be non-NULL. | |
| 1268 * "pNBIOContext" | |
| 1269 * Address at which the NBIOContext is stored indicating whether the | |
| 1270 * validation is complete. Must be non-NULL. | |
| 1271 * "pValResult" | |
| 1272 * Address at which the ValidateResult is stored. Must be non-NULL. | |
| 1273 * "plContext" | |
| 1274 * Platform-specific context pointer. | |
| 1275 * THREAD SAFETY: | |
| 1276 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 1277 * RETURNS: | |
| 1278 * Returns NULL if the function succeeds. | |
| 1279 * Returns a Build Error if the function fails in a non-fatal way | |
| 1280 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 1281 */ | |
| 1282 static PKIX_Error * | |
| 1283 pkix_Build_ValidateEntireChain( | |
| 1284 PKIX_ForwardBuilderState *state, | |
| 1285 PKIX_TrustAnchor *anchor, | |
| 1286 void **pNBIOContext, | |
| 1287 PKIX_ValidateResult **pValResult, | |
| 1288 PKIX_VerifyNode *verifyNode, | |
| 1289 void *plContext) | |
| 1290 { | |
| 1291 PKIX_UInt32 numChainCerts = 0; | |
| 1292 PKIX_PL_PublicKey *subjPubKey = NULL; | |
| 1293 PKIX_PolicyNode *policyTree = NULL; | |
| 1294 PKIX_ValidateResult *valResult = NULL; | |
| 1295 void *nbioContext = NULL; | |
| 1296 | |
| 1297 PKIX_ENTER(BUILD, "pkix_Build_ValidateEntireChain"); | |
| 1298 PKIX_NULLCHECK_FOUR(state, anchor, pNBIOContext, pValResult); | |
| 1299 | |
| 1300 *pNBIOContext = NULL; /* prepare for case of error exit */ | |
| 1301 | |
| 1302 PKIX_CHECK(PKIX_List_GetLength | |
| 1303 (state->reversedCertChain, &numChainCerts, plContext), | |
| 1304 PKIX_LISTGETLENGTHFAILED); | |
| 1305 | |
| 1306 pkixErrorResult = | |
| 1307 pkix_CheckChain(state->reversedCertChain, numChainCerts, anchor, | |
| 1308 state->checkerChain, | |
| 1309 state->buildConstants.revChecker, | |
| 1310 state->checkedCritExtOIDs, | |
| 1311 state->buildConstants.procParams, | |
| 1312 &state->certCheckedIndex, &state->checkerIndex, | |
| 1313 &state->revChecking, &state->reasonCode, | |
| 1314 &nbioContext, &subjPubKey, &policyTree, NULL, | |
| 1315 plContext); | |
| 1316 | |
| 1317 if (nbioContext != NULL) { | |
| 1318 *pNBIOContext = nbioContext; | |
| 1319 goto cleanup; | |
| 1320 } | |
| 1321 | |
| 1322 ERROR_CHECK(PKIX_CHECKCHAINFAILED); | |
| 1323 | |
| 1324 if (state->reasonCode != 0) { | |
| 1325 PKIX_ERROR(PKIX_CHAINREJECTEDBYREVOCATIONCHECKER); | |
| 1326 } | |
| 1327 | |
| 1328 PKIX_CHECK(pkix_ValidateResult_Create | |
| 1329 (subjPubKey, anchor, policyTree, &valResult, plContext), | |
| 1330 PKIX_VALIDATERESULTCREATEFAILED); | |
| 1331 | |
| 1332 *pValResult = valResult; | |
| 1333 valResult = NULL; | |
| 1334 | |
| 1335 cleanup: | |
| 1336 PKIX_DECREF(subjPubKey); | |
| 1337 PKIX_DECREF(policyTree); | |
| 1338 PKIX_DECREF(valResult); | |
| 1339 | |
| 1340 PKIX_RETURN(BUILD); | |
| 1341 } | |
| 1342 | |
| 1343 /* | |
| 1344 * FUNCTION: pkix_Build_SortCandidateCerts | |
| 1345 * DESCRIPTION: | |
| 1346 * | |
| 1347 * This function sorts a List of candidate Certs pointed to by "candidates" | |
| 1348 * using an algorithm that places Certs most likely to produce a successful | |
| 1349 * chain at the front of the list, storing the resulting sorted List at | |
| 1350 * "pSortedCandidates". | |
| 1351 * | |
| 1352 * At present the only sort criterion is that trusted Certs go ahead of | |
| 1353 * untrusted Certs. | |
| 1354 * | |
| 1355 * PARAMETERS: | |
| 1356 * "candidates" | |
| 1357 * Address of List of Candidate Certs to be sorted. Must be non-NULL. | |
| 1358 * "pSortedCandidates" | |
| 1359 * Address at which sorted List is stored. Must be non-NULL. | |
| 1360 * "plContext" | |
| 1361 * Platform-specific context pointer. | |
| 1362 * THREAD SAFETY: | |
| 1363 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 1364 * RETURNS: | |
| 1365 * Returns NULL if the function succeeds. | |
| 1366 * Returns a Build Error if the function fails in a non-fatal way | |
| 1367 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 1368 */ | |
| 1369 static PKIX_Error * | |
| 1370 pkix_Build_SortCandidateCerts( | |
| 1371 PKIX_List *candidates, | |
| 1372 PKIX_List **pSortedCandidates, | |
| 1373 void *plContext) | |
| 1374 { | |
| 1375 PKIX_List *sortedList = NULL; | |
| 1376 | |
| 1377 PKIX_ENTER(BUILD, "pkix_Build_SortCandidateCerts"); | |
| 1378 PKIX_NULLCHECK_TWO(candidates, pSortedCandidates); | |
| 1379 | |
| 1380 /* | |
| 1381 * Both bubble and quick sort algorithms are available. | |
| 1382 * For a list of fewer than around 100 items, the bubble sort is more | |
| 1383 * efficient. (This number was determined by experimenting with both | |
| 1384 * algorithms on a Java List.) | |
| 1385 * If the candidate list is very small, using the sort can drag down | |
| 1386 * the performance a little bit. | |
| 1387 */ | |
| 1388 | |
| 1389 PKIX_CHECK(pkix_List_BubbleSort | |
| 1390 (candidates, | |
| 1391 pkix_Build_SortCertComparator, | |
| 1392 &sortedList, | |
| 1393 plContext), | |
| 1394 PKIX_LISTBUBBLESORTFAILED); | |
| 1395 | |
| 1396 *pSortedCandidates = sortedList; | |
| 1397 | |
| 1398 cleanup: | |
| 1399 | |
| 1400 PKIX_RETURN(BUILD); | |
| 1401 } | |
| 1402 | |
| 1403 /* | |
| 1404 * FUNCTION: pkix_Build_BuildSelectorAndParams | |
| 1405 * DESCRIPTION: | |
| 1406 * | |
| 1407 * This function creates a CertSelector, initialized with an appropriate | |
| 1408 * ComCertSelParams, using the variables provided in the ForwardBuilderState | |
| 1409 * pointed to by "state". The CertSelector created is stored in the certsel | |
| 1410 * element of "state". | |
| 1411 * | |
| 1412 * PARAMETERS: | |
| 1413 * "state" | |
| 1414 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
| 1415 * "plContext" | |
| 1416 * Platform-specific context pointer. | |
| 1417 * THREAD SAFETY: | |
| 1418 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 1419 * RETURNS: | |
| 1420 * Returns NULL if the function succeeds. | |
| 1421 * Returns a Build Error if the function fails in a non-fatal way | |
| 1422 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 1423 */ | |
| 1424 static PKIX_Error * | |
| 1425 pkix_Build_BuildSelectorAndParams( | |
| 1426 PKIX_ForwardBuilderState *state, | |
| 1427 void *plContext) | |
| 1428 { | |
| 1429 PKIX_ComCertSelParams *certSelParams = NULL; | |
| 1430 PKIX_CertSelector *certSel = NULL; | |
| 1431 PKIX_PL_X500Name *currentIssuer = NULL; | |
| 1432 PKIX_PL_ByteArray *authKeyId = NULL; | |
| 1433 PKIX_PL_Date *testDate = NULL; | |
| 1434 PKIX_CertSelector *callerCertSelector = NULL; | |
| 1435 PKIX_ComCertSelParams *callerComCertSelParams = NULL; | |
| 1436 PKIX_UInt32 reqKu = 0; | |
| 1437 PKIX_List *reqEkuOids = NULL; | |
| 1438 | |
| 1439 PKIX_ENTER(BUILD, "pkix_Build_BuildSelectorAndParams"); | |
| 1440 PKIX_NULLCHECK_THREE(state, state->prevCert, state->traversedSubjNames); | |
| 1441 | |
| 1442 PKIX_CHECK(PKIX_PL_Cert_GetIssuer | |
| 1443 (state->prevCert, ¤tIssuer, plContext), | |
| 1444 PKIX_CERTGETISSUERFAILED); | |
| 1445 | |
| 1446 PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier | |
| 1447 (state->prevCert, &authKeyId, plContext), | |
| 1448 PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); | |
| 1449 | |
| 1450 PKIX_CHECK(PKIX_ComCertSelParams_Create(&certSelParams, plContext), | |
| 1451 PKIX_COMCERTSELPARAMSCREATEFAILED); | |
| 1452 | |
| 1453 PKIX_CHECK(PKIX_ComCertSelParams_SetSubject | |
| 1454 (certSelParams, currentIssuer, plContext), | |
| 1455 PKIX_COMCERTSELPARAMSSETSUBJECTFAILED); | |
| 1456 | |
| 1457 if (authKeyId != NULL) { | |
| 1458 PKIX_CHECK(PKIX_ComCertSelParams_SetSubjKeyIdentifier | |
| 1459 (certSelParams, authKeyId, plContext), | |
| 1460 PKIX_COMCERTSELPARAMSSETSUBJKEYIDENTIFIERFAILED); | |
| 1461 } | |
| 1462 | |
| 1463 PKIX_INCREF(state->buildConstants.testDate); | |
| 1464 testDate = state->buildConstants.testDate; | |
| 1465 | |
| 1466 PKIX_CHECK(PKIX_ComCertSelParams_SetCertificateValid | |
| 1467 (certSelParams, testDate, plContext), | |
| 1468 PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED); | |
| 1469 | |
| 1470 PKIX_CHECK(PKIX_ComCertSelParams_SetBasicConstraints | |
| 1471 (certSelParams, state->traversedCACerts, plContext), | |
| 1472 PKIX_COMCERTSELPARAMSSETBASICCONSTRAINTSFAILED); | |
| 1473 | |
| 1474 PKIX_CHECK(PKIX_ComCertSelParams_SetPathToNames | |
| 1475 (certSelParams, state->traversedSubjNames, plContext), | |
| 1476 PKIX_COMCERTSELPARAMSSETPATHTONAMESFAILED); | |
| 1477 | |
| 1478 PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints | |
| 1479 (state->buildConstants.procParams, | |
| 1480 &callerCertSelector, plContext), | |
| 1481 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); | |
| 1482 | |
| 1483 if (callerCertSelector != NULL) { | |
| 1484 | |
| 1485 /* Get initial EKU OIDs from ComCertSelParams, if set */ | |
| 1486 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams | |
| 1487 (callerCertSelector, &callerComCertSelParams, plContext), | |
| 1488 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); | |
| 1489 | |
| 1490 if (callerComCertSelParams != NULL) { | |
| 1491 PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage | |
| 1492 (callerComCertSelParams, &reqEkuOids, plContext), | |
| 1493 PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); | |
| 1494 | |
| 1495 PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage | |
| 1496 (callerComCertSelParams, &reqKu, plContext), | |
| 1497 PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); | |
| 1498 } | |
| 1499 } | |
| 1500 | |
| 1501 PKIX_CHECK( | |
| 1502 PKIX_ComCertSelParams_SetKeyUsage(certSelParams, reqKu, | |
| 1503 plContext), | |
| 1504 PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED); | |
| 1505 | |
| 1506 PKIX_CHECK( | |
| 1507 PKIX_ComCertSelParams_SetExtendedKeyUsage(certSelParams, | |
| 1508 reqEkuOids, | |
| 1509 plContext), | |
| 1510 PKIX_COMCERTSELPARAMSSETEXTKEYUSAGEFAILED); | |
| 1511 | |
| 1512 PKIX_CHECK(PKIX_CertSelector_Create | |
| 1513 (NULL, NULL, &state->certSel, plContext), | |
| 1514 PKIX_CERTSELECTORCREATEFAILED); | |
| 1515 | |
| 1516 PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams | |
| 1517 (state->certSel, certSelParams, plContext), | |
| 1518 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); | |
| 1519 | |
| 1520 PKIX_CHECK(PKIX_List_Create(&state->candidateCerts, plContext), | |
| 1521 PKIX_LISTCREATEFAILED); | |
| 1522 | |
| 1523 state->certStoreIndex = 0; | |
| 1524 | |
| 1525 cleanup: | |
| 1526 PKIX_DECREF(certSelParams); | |
| 1527 PKIX_DECREF(certSel); | |
| 1528 PKIX_DECREF(currentIssuer); | |
| 1529 PKIX_DECREF(authKeyId); | |
| 1530 PKIX_DECREF(testDate); | |
| 1531 PKIX_DECREF(reqEkuOids); | |
| 1532 PKIX_DECREF(callerComCertSelParams); | |
| 1533 PKIX_DECREF(callerCertSelector); | |
| 1534 | |
| 1535 PKIX_RETURN(BUILD); | |
| 1536 } | |
| 1537 | |
| 1538 /* Match trust anchor to select params in order to find next cert. */ | |
| 1539 static PKIX_Error* | |
| 1540 pkix_Build_SelectCertsFromTrustAnchors( | |
| 1541 PKIX_List *trustAnchorsList, | |
| 1542 PKIX_ComCertSelParams *certSelParams, | |
| 1543 PKIX_List **pMatchList, | |
| 1544 void *plContext) | |
| 1545 { | |
| 1546 int anchorIndex = 0; | |
| 1547 PKIX_TrustAnchor *anchor = NULL; | |
| 1548 PKIX_PL_Cert *trustedCert = NULL; | |
| 1549 PKIX_List *matchList = NULL; | |
| 1550 PKIX_CertSelector *certSel = NULL; | |
| 1551 PKIX_CertSelector_MatchCallback selectorMatchCB = NULL; | |
| 1552 | |
| 1553 PKIX_ENTER(BUILD, "pkix_Build_SelectCertsFromTrustAnchors"); | |
| 1554 | |
| 1555 PKIX_CHECK(PKIX_CertSelector_Create | |
| 1556 (NULL, NULL, &certSel, plContext), | |
| 1557 PKIX_CERTSELECTORCREATEFAILED); | |
| 1558 PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams | |
| 1559 (certSel, certSelParams, plContext), | |
| 1560 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED); | |
| 1561 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback | |
| 1562 (certSel, &selectorMatchCB, plContext), | |
| 1563 PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); | |
| 1564 | |
| 1565 for (anchorIndex = 0;anchorIndex < trustAnchorsList->length; anchorIndex++)
{ | |
| 1566 PKIX_CHECK( | |
| 1567 PKIX_List_GetItem(trustAnchorsList, | |
| 1568 anchorIndex, | |
| 1569 (PKIX_PL_Object **)&anchor, | |
| 1570 plContext), | |
| 1571 PKIX_LISTGETITEMFAILED); | |
| 1572 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert | |
| 1573 (anchor, &trustedCert, plContext), | |
| 1574 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); | |
| 1575 pkixErrorResult = | |
| 1576 (*selectorMatchCB)(certSel, trustedCert, plContext); | |
| 1577 if (!pkixErrorResult) { | |
| 1578 if (!matchList) { | |
| 1579 PKIX_CHECK(PKIX_List_Create(&matchList, | |
| 1580 plContext), | |
| 1581 PKIX_LISTCREATEFAILED); | |
| 1582 } | |
| 1583 PKIX_CHECK( | |
| 1584 PKIX_List_AppendItem(matchList, | |
| 1585 (PKIX_PL_Object*)trustedCert, | |
| 1586 plContext), | |
| 1587 PKIX_LISTAPPENDITEMFAILED); | |
| 1588 } else { | |
| 1589 PKIX_DECREF(pkixErrorResult); | |
| 1590 } | |
| 1591 PKIX_DECREF(trustedCert); | |
| 1592 PKIX_DECREF(anchor); | |
| 1593 } | |
| 1594 | |
| 1595 *pMatchList = matchList; | |
| 1596 matchList = NULL; | |
| 1597 | |
| 1598 cleanup: | |
| 1599 PKIX_DECREF(matchList); | |
| 1600 PKIX_DECREF(trustedCert); | |
| 1601 PKIX_DECREF(anchor); | |
| 1602 PKIX_DECREF(certSel); | |
| 1603 | |
| 1604 PKIX_RETURN(BUILD); | |
| 1605 } | |
| 1606 | |
| 1607 | |
| 1608 static PKIX_Error* | |
| 1609 pkix_Build_RemoveDupUntrustedCerts( | |
| 1610 PKIX_List *trustedCertList, | |
| 1611 PKIX_List *certsFound, | |
| 1612 void *plContext) | |
| 1613 { | |
| 1614 PKIX_UInt32 trustIndex; | |
| 1615 PKIX_PL_Cert *trustCert = NULL, *cert = NULL; | |
| 1616 | |
| 1617 PKIX_ENTER(BUILD, "pkix_Build_RemoveDupUntrustedCerts"); | |
| 1618 if (trustedCertList == NULL || certsFound == NULL) { | |
| 1619 goto cleanup; | |
| 1620 } | |
| 1621 for (trustIndex = 0;trustIndex < trustedCertList->length; | |
| 1622 trustIndex++) { | |
| 1623 PKIX_UInt32 certIndex = 0; | |
| 1624 PKIX_CHECK( | |
| 1625 PKIX_List_GetItem(trustedCertList, | |
| 1626 trustIndex, | |
| 1627 (PKIX_PL_Object **)&trustCert, | |
| 1628 plContext), | |
| 1629 PKIX_LISTGETITEMFAILED); | |
| 1630 | |
| 1631 while (certIndex < certsFound->length) { | |
| 1632 PKIX_Boolean result = PKIX_FALSE; | |
| 1633 PKIX_DECREF(cert); | |
| 1634 PKIX_CHECK( | |
| 1635 PKIX_List_GetItem(certsFound, certIndex, | |
| 1636 (PKIX_PL_Object **)&cert, | |
| 1637 plContext), | |
| 1638 PKIX_LISTGETITEMFAILED); | |
| 1639 PKIX_CHECK( | |
| 1640 PKIX_PL_Object_Equals((PKIX_PL_Object *)trustCert, | |
| 1641 (PKIX_PL_Object *)cert, | |
| 1642 &result, | |
| 1643 plContext), | |
| 1644 PKIX_OBJECTEQUALSFAILED); | |
| 1645 if (!result) { | |
| 1646 certIndex += 1; | |
| 1647 continue; | |
| 1648 } | |
| 1649 PKIX_CHECK( | |
| 1650 PKIX_List_DeleteItem(certsFound, certIndex, | |
| 1651 plContext), | |
| 1652 PKIX_LISTDELETEITEMFAILED); | |
| 1653 } | |
| 1654 PKIX_DECREF(trustCert); | |
| 1655 } | |
| 1656 cleanup: | |
| 1657 PKIX_DECREF(cert); | |
| 1658 PKIX_DECREF(trustCert); | |
| 1659 | |
| 1660 PKIX_RETURN(BUILD); | |
| 1661 } | |
| 1662 | |
| 1663 | |
| 1664 /* | |
| 1665 * FUNCTION: pkix_Build_GatherCerts | |
| 1666 * DESCRIPTION: | |
| 1667 * | |
| 1668 * This function traverses the CertStores in the List of CertStores contained | |
| 1669 * in "state", using the certSelector and other parameters contained in | |
| 1670 * "state", to obtain a List of all available Certs that satisfy the criteria. | |
| 1671 * If a CertStore has a cache, "certSelParams" is used both to query the cache | |
| 1672 * and, if an actual CertStore search occurred, to update the cache. (Behavior | |
| 1673 * is undefined if "certSelParams" is different from the parameters that were | |
| 1674 * used to initialize the certSelector in "state".) | |
| 1675 * | |
| 1676 * If a CertStore using non-blocking I/O returns with an indication that I/O is | |
| 1677 * in progress and the checking has not been completed, this function stores | |
| 1678 * platform-dependent information at "pNBIOContext". Otherwise it stores NULL | |
| 1679 * at "pNBIOContext", and state is updated with the results of the search. | |
| 1680 * | |
| 1681 * PARAMETERS: | |
| 1682 * "state" | |
| 1683 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
| 1684 * "certSelParams" | |
| 1685 * Address of ComCertSelParams which were used in creating the current | |
| 1686 * CertSelector, and to be used in querying and updating any caches that | |
| 1687 * may be associated with with the CertStores. | |
| 1688 * "pNBIOContext" | |
| 1689 * Address at which platform-dependent information is returned if request | |
| 1690 * is suspended for non-blocking I/O. Must be non-NULL. | |
| 1691 * "plContext" | |
| 1692 * Platform-specific context pointer. | |
| 1693 * THREAD SAFETY: | |
| 1694 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 1695 * RETURNS: | |
| 1696 * Returns NULL if the function succeeds. | |
| 1697 * Returns a Build Error if the function fails in a non-fatal way | |
| 1698 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 1699 */ | |
| 1700 /* return NULL if wouldblock, empty list if none found, else list of found */ | |
| 1701 static PKIX_Error * | |
| 1702 pkix_Build_GatherCerts( | |
| 1703 PKIX_ForwardBuilderState *state, | |
| 1704 PKIX_ComCertSelParams *certSelParams, | |
| 1705 void **pNBIOContext, | |
| 1706 void *plContext) | |
| 1707 { | |
| 1708 PKIX_Boolean certStoreIsCached = PKIX_FALSE; | |
| 1709 PKIX_Boolean certStoreIsLocal = PKIX_FALSE; | |
| 1710 PKIX_Boolean foundInCache = PKIX_FALSE; | |
| 1711 PKIX_CertStore *certStore = NULL; | |
| 1712 PKIX_CertStore_CertCallback getCerts = NULL; | |
| 1713 PKIX_List *certsFound = NULL; | |
| 1714 PKIX_List *trustedCertList = NULL; | |
| 1715 void *nbioContext = NULL; | |
| 1716 | |
| 1717 PKIX_ENTER(BUILD, "pkix_Build_GatherCerts"); | |
| 1718 PKIX_NULLCHECK_THREE(state, certSelParams, pNBIOContext); | |
| 1719 | |
| 1720 nbioContext = *pNBIOContext; | |
| 1721 *pNBIOContext = NULL; | |
| 1722 | |
| 1723 PKIX_DECREF(state->candidateCerts); | |
| 1724 | |
| 1725 while (state->certStoreIndex < state->buildConstants.numCertStores) { | |
| 1726 | |
| 1727 /* Get the current CertStore */ | |
| 1728 PKIX_CHECK(PKIX_List_GetItem | |
| 1729 (state->buildConstants.certStores, | |
| 1730 state->certStoreIndex, | |
| 1731 (PKIX_PL_Object **)&certStore, | |
| 1732 plContext), | |
| 1733 PKIX_LISTGETITEMFAILED); | |
| 1734 | |
| 1735 PKIX_CHECK(PKIX_CertStore_GetLocalFlag | |
| 1736 (certStore, &certStoreIsLocal, plContext), | |
| 1737 PKIX_CERTSTOREGETLOCALFLAGFAILED); | |
| 1738 | |
| 1739 if (state->useOnlyLocal == certStoreIsLocal) { | |
| 1740 /* If GATHERPENDING, we've already checked the cache */ | |
| 1741 if (state->status == BUILD_GATHERPENDING) { | |
| 1742 certStoreIsCached = PKIX_FALSE; | |
| 1743 foundInCache = PKIX_FALSE; | |
| 1744 } else { | |
| 1745 PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag | |
| 1746 (certStore, &certStoreIsCached, plContext), | |
| 1747 PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED); | |
| 1748 | |
| 1749 if (certStoreIsCached) { | |
| 1750 /* | |
| 1751 * Look for Certs in the cache, using the SubjectName as | |
| 1752 * the key. Then the ComCertSelParams are used to filter | |
| 1753 * for qualified certs. If none are found, then the | |
| 1754 * certStores are queried. When we eventually add items | |
| 1755 * to the cache, we will only add items that passed the | |
| 1756 * ComCertSelParams filter, rather than all Certs which | |
| 1757 * matched the SubjectName. | |
| 1758 */ | |
| 1759 | |
| 1760 PKIX_CHECK(pkix_CacheCert_Lookup | |
| 1761 (certStore, | |
| 1762 certSelParams, | |
| 1763 state->buildConstants.testDate, | |
| 1764 &foundInCache, | |
| 1765 &certsFound, | |
| 1766 plContext), | |
| 1767 PKIX_CACHECERTCHAINLOOKUPFAILED); | |
| 1768 | |
| 1769 } | |
| 1770 } | |
| 1771 | |
| 1772 /* | |
| 1773 * XXX need to verify if Cert is trusted, hence may not | |
| 1774 * be worth it to have the Cert Cached or | |
| 1775 * If it is trusted, don't cache, but once there is cached | |
| 1776 * certs, we won't get certs from database any more. | |
| 1777 * can use flag to force not getting certs from cache | |
| 1778 */ | |
| 1779 if (!foundInCache) { | |
| 1780 | |
| 1781 if (nbioContext == NULL) { | |
| 1782 PKIX_CHECK(PKIX_CertStore_GetCertCallback | |
| 1783 (certStore, &getCerts, plContext), | |
| 1784 PKIX_CERTSTOREGETCERTCALLBACKFAILED); | |
| 1785 | |
| 1786 PKIX_CHECK(getCerts | |
| 1787 (certStore, | |
| 1788 state->certSel, | |
| 1789 state->verifyNode, | |
| 1790 &nbioContext, | |
| 1791 &certsFound, | |
| 1792 plContext), | |
| 1793 PKIX_GETCERTSFAILED); | |
| 1794 } else { | |
| 1795 PKIX_CHECK(PKIX_CertStore_CertContinue | |
| 1796 (certStore, | |
| 1797 state->certSel, | |
| 1798 state->verifyNode, | |
| 1799 &nbioContext, | |
| 1800 &certsFound, | |
| 1801 plContext), | |
| 1802 PKIX_CERTSTORECERTCONTINUEFAILED); | |
| 1803 } | |
| 1804 | |
| 1805 if (certStoreIsCached && certsFound) { | |
| 1806 | |
| 1807 PKIX_CHECK(pkix_CacheCert_Add | |
| 1808 (certStore, | |
| 1809 certSelParams, | |
| 1810 certsFound, | |
| 1811 plContext), | |
| 1812 PKIX_CACHECERTADDFAILED); | |
| 1813 } | |
| 1814 } | |
| 1815 | |
| 1816 /* | |
| 1817 * getCerts returns an empty list for "NONE FOUND", | |
| 1818 * a NULL list for "would block" | |
| 1819 */ | |
| 1820 if (certsFound == NULL) { | |
| 1821 state->status = BUILD_GATHERPENDING; | |
| 1822 *pNBIOContext = nbioContext; | |
| 1823 goto cleanup; | |
| 1824 } | |
| 1825 } | |
| 1826 | |
| 1827 /* Are there any more certStores to query? */ | |
| 1828 PKIX_DECREF(certStore); | |
| 1829 ++(state->certStoreIndex); | |
| 1830 } | |
| 1831 | |
| 1832 if (certsFound && certsFound->length > 1) { | |
| 1833 PKIX_List *sorted = NULL; | |
| 1834 | |
| 1835 /* sort Certs to try to optimize search */ | |
| 1836 PKIX_CHECK(pkix_Build_SortCandidateCerts | |
| 1837 (certsFound, &sorted, plContext), | |
| 1838 PKIX_BUILDSORTCANDIDATECERTSFAILED); | |
| 1839 PKIX_DECREF(certsFound); | |
| 1840 certsFound = sorted; | |
| 1841 } | |
| 1842 | |
| 1843 PKIX_CHECK( | |
| 1844 pkix_Build_SelectCertsFromTrustAnchors( | |
| 1845 state->buildConstants.anchors, | |
| 1846 certSelParams, &trustedCertList, | |
| 1847 plContext), | |
| 1848 PKIX_FAILTOSELECTCERTSFROMANCHORS); | |
| 1849 PKIX_CHECK( | |
| 1850 pkix_Build_RemoveDupUntrustedCerts(trustedCertList, | |
| 1851 certsFound, | |
| 1852 plContext), | |
| 1853 PKIX_REMOVEDUPUNTRUSTEDCERTSFAILED); | |
| 1854 | |
| 1855 PKIX_CHECK( | |
| 1856 pkix_List_MergeLists(trustedCertList, | |
| 1857 certsFound, | |
| 1858 &state->candidateCerts, | |
| 1859 plContext), | |
| 1860 PKIX_LISTMERGEFAILED); | |
| 1861 | |
| 1862 /* No, return the list we have gathered */ | |
| 1863 PKIX_CHECK(PKIX_List_GetLength | |
| 1864 (state->candidateCerts, &state->numCerts, plContext), | |
| 1865 PKIX_LISTGETLENGTHFAILED); | |
| 1866 | |
| 1867 state->certIndex = 0; | |
| 1868 | |
| 1869 cleanup: | |
| 1870 PKIX_DECREF(trustedCertList); | |
| 1871 PKIX_DECREF(certStore); | |
| 1872 PKIX_DECREF(certsFound); | |
| 1873 | |
| 1874 PKIX_RETURN(BUILD); | |
| 1875 } | |
| 1876 | |
| 1877 /* | |
| 1878 * FUNCTION: pkix_Build_UpdateDate | |
| 1879 * DESCRIPTION: | |
| 1880 * | |
| 1881 * This function updates the validityDate contained in "state", for the current | |
| 1882 * CertChain contained in "state", to include the validityDate of the | |
| 1883 * candidateCert contained in "state". The validityDate of a chain is the | |
| 1884 * earliest of all the notAfter dates contained in the respective Certificates. | |
| 1885 * | |
| 1886 * PARAMETERS: | |
| 1887 * "state" | |
| 1888 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
| 1889 * "plContext" | |
| 1890 * Platform-specific context pointer. | |
| 1891 * THREAD SAFETY: | |
| 1892 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 1893 * RETURNS: | |
| 1894 * Returns NULL if the function succeeds. | |
| 1895 * Returns a Build Error if the function fails in a non-fatal way | |
| 1896 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 1897 */ | |
| 1898 static PKIX_Error * | |
| 1899 pkix_Build_UpdateDate( | |
| 1900 PKIX_ForwardBuilderState *state, | |
| 1901 void *plContext) | |
| 1902 { | |
| 1903 PKIX_Boolean canBeCached = PKIX_FALSE; | |
| 1904 PKIX_Int32 comparison = 0; | |
| 1905 PKIX_PL_Date *notAfter = NULL; | |
| 1906 | |
| 1907 PKIX_ENTER(BUILD, "pkix_Build_UpdateDate"); | |
| 1908 PKIX_NULLCHECK_ONE(state); | |
| 1909 | |
| 1910 PKIX_CHECK(PKIX_PL_Cert_GetCacheFlag | |
| 1911 (state->candidateCert, &canBeCached, plContext), | |
| 1912 PKIX_CERTGETCACHEFLAGFAILED); | |
| 1913 | |
| 1914 state->canBeCached = state->canBeCached && canBeCached; | |
| 1915 if (state->canBeCached == PKIX_TRUE) { | |
| 1916 | |
| 1917 /* | |
| 1918 * So far, all certs can be cached. Update cert | |
| 1919 * chain validity time, which is the earliest of | |
| 1920 * all certs' notAfter times. | |
| 1921 */ | |
| 1922 PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter | |
| 1923 (state->candidateCert, ¬After, plContext), | |
| 1924 PKIX_CERTGETVALIDITYNOTAFTERFAILED); | |
| 1925 | |
| 1926 if (state->validityDate == NULL) { | |
| 1927 state->validityDate = notAfter; | |
| 1928 notAfter = NULL; | |
| 1929 } else { | |
| 1930 PKIX_CHECK(PKIX_PL_Object_Compare | |
| 1931 ((PKIX_PL_Object *)state->validityDate, | |
| 1932 (PKIX_PL_Object *)notAfter, | |
| 1933 &comparison, | |
| 1934 plContext), | |
| 1935 PKIX_OBJECTCOMPARATORFAILED); | |
| 1936 if (comparison > 0) { | |
| 1937 PKIX_DECREF(state->validityDate); | |
| 1938 state->validityDate = notAfter; | |
| 1939 notAfter = NULL; | |
| 1940 } | |
| 1941 } | |
| 1942 } | |
| 1943 | |
| 1944 cleanup: | |
| 1945 | |
| 1946 PKIX_DECREF(notAfter); | |
| 1947 | |
| 1948 PKIX_RETURN(BUILD); | |
| 1949 } | |
| 1950 | |
| 1951 /* Prepare 'state' for the AIA round. */ | |
| 1952 static void | |
| 1953 pkix_PrepareForwardBuilderStateForAIA( | |
| 1954 PKIX_ForwardBuilderState *state) | |
| 1955 { | |
| 1956 PORT_Assert(state->useOnlyLocal == PKIX_TRUE); | |
| 1957 state->useOnlyLocal = PKIX_FALSE; | |
| 1958 state->certStoreIndex = 0; | |
| 1959 state->numFanout = state->buildConstants.maxFanout; | |
| 1960 state->status = BUILD_TRYAIA; | |
| 1961 } | |
| 1962 | |
| 1963 /* | |
| 1964 * FUNCTION: pkix_BuildForwardDepthFirstSearch | |
| 1965 * DESCRIPTION: | |
| 1966 * | |
| 1967 * This function performs a depth first search in the "forward" direction (from | |
| 1968 * the target Cert to the trust anchor). A non-NULL targetCert must be stored | |
| 1969 * in the ForwardBuilderState before this function is called. It is not written | |
| 1970 * recursively since execution may be suspended in in any of several places | |
| 1971 * pending completion of non-blocking I/O. This iterative structure makes it | |
| 1972 * much easier to resume where it left off. | |
| 1973 * | |
| 1974 * Since the nature of the search is recursive, the recursion is handled by | |
| 1975 * chaining states. That is, each new step involves creating a new | |
| 1976 * ForwardBuilderState linked to its predecessor. If a step turns out to be | |
| 1977 * fruitless, the state of the predecessor is restored and the next alternative | |
| 1978 * is tried. When a search is successful, values needed from the last state | |
| 1979 * (canBeCached and validityDate) are copied to the state provided by the | |
| 1980 * caller, so that the caller can retrieve those values. | |
| 1981 * | |
| 1982 * There are three return arguments, the NBIOContext, the ValidateResult and | |
| 1983 * the ForwardBuilderState. If NBIOContext is non-NULL, it means the search is | |
| 1984 * suspended until the results of a non-blocking IO become available. The | |
| 1985 * caller may wait for the completion using platform-dependent methods and then | |
| 1986 * call this function again, allowing it to resume the search. If NBIOContext | |
| 1987 * is NULL and the ValidateResult is non-NULL, it means the search has | |
| 1988 * concluded successfully. If the NBIOContext is NULL but the ValidateResult is | |
| 1989 * NULL, it means the search was unsuccessful. | |
| 1990 * | |
| 1991 * This function performs several steps at each node in the constructed chain: | |
| 1992 * | |
| 1993 * 1) It retrieves Certs from the registered CertStores that match the | |
| 1994 * criteria established by the ForwardBuilderState pointed to by "state", such | |
| 1995 * as a subject name matching the issuer name of the previous Cert. If there | |
| 1996 * are no matching Certs, the function returns to the previous, or "parent", | |
| 1997 * state and tries to continue the chain building with another of the Certs | |
| 1998 * obtained from the CertStores as possible issuers for that parent Cert. | |
| 1999 * | |
| 2000 * 2) For each candidate Cert returned by the CertStores, this function checks | |
| 2001 * whether the Cert is valid. If it is trusted, this function checks whether | |
| 2002 * this Cert might serve as a TrustAnchor for a complete chain. | |
| 2003 * | |
| 2004 * 3) It determines whether this Cert, in conjunction with any of the | |
| 2005 * TrustAnchors, might complete a chain. A complete chain, from this or the | |
| 2006 * preceding step, is checked to see whether it is valid as a complete | |
| 2007 * chain, including the checks that cannot be done in the forward direction. | |
| 2008 * | |
| 2009 * 4) If this Cert chains successfully, but is not a complete chain, that is, | |
| 2010 * we have not reached a trusted Cert, a new ForwardBuilderState is created | |
| 2011 * with this Cert as the immediate predecessor, and we continue in step (1), | |
| 2012 * attempting to get Certs from the CertStores with this Certs "issuer" as | |
| 2013 * their subject. | |
| 2014 * | |
| 2015 * 5) If an entire chain validates successfully, then we are done. A | |
| 2016 * ValidateResult is created containing the Public Key of the target | |
| 2017 * certificate (including DSA parameter inheritance, if any) and the | |
| 2018 * PolicyNode representing the policy tree output by the validation algorithm, | |
| 2019 * and stored at pValResult, and the function exits returning NULL. | |
| 2020 * | |
| 2021 * 5) If the entire chain does not validate successfully, the algorithm | |
| 2022 * discards the latest Cert and continues in step 2 with the next candidate | |
| 2023 * Cert, backing up to a parent state when no more possibilities exist at a | |
| 2024 * given level, and returning failure when we try to back up but discover we | |
| 2025 * are at the top level. | |
| 2026 * | |
| 2027 * PARAMETERS: | |
| 2028 * "pNBIOContext" | |
| 2029 * Address at which platform-dependent information is returned if building | |
| 2030 * is suspended for non-blocking I/O. Must be non-NULL. | |
| 2031 * "pState" | |
| 2032 * Address at which input ForwardBuilderState is found, and at which output | |
| 2033 * ForwardBuilderState is stored. Must be non-NULL. | |
| 2034 * "pValResult" | |
| 2035 * Address at which the ValidateResult is stored. Must be non-NULL. | |
| 2036 * "plContext" | |
| 2037 * Platform-specific context pointer. | |
| 2038 * THREAD SAFETY: | |
| 2039 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 2040 * RETURNS: | |
| 2041 * Returns NULL if the function succeeds. | |
| 2042 * Returns a Build Error if the function fails in a non-fatal way. | |
| 2043 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 2044 */ | |
| 2045 static PKIX_Error * | |
| 2046 pkix_BuildForwardDepthFirstSearch( | |
| 2047 void **pNBIOContext, | |
| 2048 PKIX_ForwardBuilderState *state, | |
| 2049 PKIX_ValidateResult **pValResult, | |
| 2050 void *plContext) | |
| 2051 { | |
| 2052 PKIX_Boolean outOfOptions = PKIX_FALSE; | |
| 2053 PKIX_Boolean trusted = PKIX_FALSE; | |
| 2054 PKIX_Boolean isSelfIssued = PKIX_FALSE; | |
| 2055 PKIX_Boolean canBeCached = PKIX_FALSE; | |
| 2056 PKIX_Boolean revocationCheckingExists = PKIX_FALSE; | |
| 2057 PKIX_Boolean needsCRLChecking = PKIX_FALSE; | |
| 2058 PKIX_Boolean ioPending = PKIX_FALSE; | |
| 2059 PKIX_PL_Date *validityDate = NULL; | |
| 2060 PKIX_PL_Date *currTime = NULL; | |
| 2061 PKIX_Int32 childTraversedCACerts = 0; | |
| 2062 PKIX_UInt32 numSubjectNames = 0; | |
| 2063 PKIX_UInt32 numChained = 0; | |
| 2064 PKIX_Int32 cmpTimeResult = 0; | |
| 2065 PKIX_UInt32 i = 0; | |
| 2066 PKIX_UInt32 certsSoFar = 0; | |
| 2067 PKIX_List *childTraversedSubjNames = NULL; | |
| 2068 PKIX_List *subjectNames = NULL; | |
| 2069 PKIX_List *unfilteredCerts = NULL; | |
| 2070 PKIX_List *filteredCerts = NULL; | |
| 2071 PKIX_PL_Object *subjectName = NULL; | |
| 2072 PKIX_ValidateResult *valResult = NULL; | |
| 2073 PKIX_ForwardBuilderState *childState = NULL; | |
| 2074 PKIX_ForwardBuilderState *parentState = NULL; | |
| 2075 PKIX_PL_Object *revCheckerState = NULL; | |
| 2076 PKIX_ComCertSelParams *certSelParams = NULL; | |
| 2077 PKIX_TrustAnchor *trustAnchor = NULL; | |
| 2078 PKIX_PL_Cert *trustedCert = NULL; | |
| 2079 PKIX_VerifyNode *verifyNode = NULL; | |
| 2080 PKIX_Error *verifyError = NULL; | |
| 2081 PKIX_Error *finalError = NULL; | |
| 2082 void *nbio = NULL; | |
| 2083 PKIX_UInt32 numIterations = 0; | |
| 2084 | |
| 2085 PKIX_ENTER(BUILD, "pkix_BuildForwardDepthFirstSearch"); | |
| 2086 PKIX_NULLCHECK_THREE(pNBIOContext, state, pValResult); | |
| 2087 | |
| 2088 nbio = *pNBIOContext; | |
| 2089 *pNBIOContext = NULL; | |
| 2090 PKIX_INCREF(state->validityDate); | |
| 2091 validityDate = state->validityDate; | |
| 2092 canBeCached = state->canBeCached; | |
| 2093 PKIX_DECREF(*pValResult); | |
| 2094 | |
| 2095 /* | |
| 2096 * We return if successful; if we fall off the end | |
| 2097 * of this "while" clause our search has failed. | |
| 2098 */ | |
| 2099 while (outOfOptions == PKIX_FALSE) { | |
| 2100 /* | |
| 2101 * The maximum number of iterations works around a bug that | |
| 2102 * causes this while loop to never exit when AIA and cross | |
| 2103 * certificates are involved. See bug xxxxx. | |
| 2104 */ | |
| 2105 if (numIterations++ > 250) | |
| 2106 PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS); | |
| 2107 | |
| 2108 if (state->buildConstants.maxTime != 0) { | |
| 2109 PKIX_DECREF(currTime); | |
| 2110 PKIX_CHECK(PKIX_PL_Date_Create_UTCTime | |
| 2111 (NULL, &currTime, plContext), | |
| 2112 PKIX_DATECREATEUTCTIMEFAILED); | |
| 2113 | |
| 2114 PKIX_CHECK(PKIX_PL_Object_Compare | |
| 2115 ((PKIX_PL_Object *)state->buildConstants.timeLimit, | |
| 2116 (PKIX_PL_Object *)currTime, | |
| 2117 &cmpTimeResult, | |
| 2118 plContext), | |
| 2119 PKIX_OBJECTCOMPARATORFAILED); | |
| 2120 | |
| 2121 if (cmpTimeResult < 0) { | |
| 2122 if (state->verifyNode != NULL) { | |
| 2123 PKIX_ERROR_CREATE | |
| 2124 (BUILD, | |
| 2125 PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS, | |
| 2126 verifyError); | |
| 2127 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
| 2128 (state->verifyNode, | |
| 2129 verifyError, | |
| 2130 plContext), | |
| 2131 PKIX_VERIFYNODESETERRORFAILED); | |
| 2132 PKIX_DECREF(finalError); | |
| 2133 finalError = verifyError; | |
| 2134 verifyError = NULL; | |
| 2135 } | |
| 2136 /* Even if we logged error, we still have to abort */ | |
| 2137 PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS); | |
| 2138 } | |
| 2139 } | |
| 2140 | |
| 2141 if (state->status == BUILD_INITIAL) { | |
| 2142 | |
| 2143 PKIX_CHECK(pkix_Build_BuildSelectorAndParams(state, plContext), | |
| 2144 PKIX_BUILDBUILDSELECTORANDPARAMSFAILED); | |
| 2145 | |
| 2146 /* | |
| 2147 * If the caller supplied a partial certChain (hintCerts) try | |
| 2148 * the next one from that List before we go to the certStores. | |
| 2149 */ | |
| 2150 if (state->buildConstants.numHintCerts > 0) { | |
| 2151 /* How many Certs does our trust chain have already? */ | |
| 2152 PKIX_CHECK(PKIX_List_GetLength | |
| 2153 (state->trustChain, &certsSoFar, plContext), | |
| 2154 PKIX_LISTGETLENGTHFAILED); | |
| 2155 | |
| 2156 /* That includes the target Cert. Don't count it. */ | |
| 2157 certsSoFar--; | |
| 2158 | |
| 2159 /* Are we still within range of the partial chain? */ | |
| 2160 if (certsSoFar >= state->buildConstants.numHintCerts) { | |
| 2161 state->status = BUILD_TRYAIA; | |
| 2162 } else { | |
| 2163 /* | |
| 2164 * If we already have n certs, we want the n+1th | |
| 2165 * (i.e., index = n) from the list of hints. | |
| 2166 */ | |
| 2167 PKIX_DECREF(state->candidateCert); | |
| 2168 PKIX_CHECK(PKIX_List_GetItem | |
| 2169 (state->buildConstants.hintCerts, | |
| 2170 certsSoFar, | |
| 2171 (PKIX_PL_Object **)&state->candidateCert, | |
| 2172 plContext), | |
| 2173 PKIX_LISTGETITEMFAILED); | |
| 2174 | |
| 2175 PKIX_CHECK(PKIX_List_AppendItem | |
| 2176 (state->candidateCerts, | |
| 2177 (PKIX_PL_Object *)state->candidateCert, | |
| 2178 plContext), | |
| 2179 PKIX_LISTAPPENDITEMFAILED); | |
| 2180 | |
| 2181 state->numCerts = 1; | |
| 2182 state->usingHintCerts = PKIX_TRUE; | |
| 2183 state->status = BUILD_CERTVALIDATING; | |
| 2184 } | |
| 2185 } else { | |
| 2186 state->status = BUILD_TRYAIA; | |
| 2187 } | |
| 2188 | |
| 2189 } | |
| 2190 | |
| 2191 if (state->status == BUILD_TRYAIA) { | |
| 2192 if (state->useOnlyLocal == PKIX_TRUE) { | |
| 2193 state->status = BUILD_COLLECTINGCERTS; | |
| 2194 } else { | |
| 2195 state->status = BUILD_AIAPENDING; | |
| 2196 } | |
| 2197 } | |
| 2198 | |
| 2199 if (state->status == BUILD_AIAPENDING && | |
| 2200 state->buildConstants.aiaMgr) { | |
| 2201 pkixErrorResult = PKIX_PL_AIAMgr_GetAIACerts | |
| 2202 (state->buildConstants.aiaMgr, | |
| 2203 state->prevCert, | |
| 2204 &nbio, | |
| 2205 &unfilteredCerts, | |
| 2206 plContext); | |
| 2207 | |
| 2208 if (nbio != NULL) { | |
| 2209 /* IO still pending, resume later */ | |
| 2210 *pNBIOContext = nbio; | |
| 2211 goto cleanup; | |
| 2212 } | |
| 2213 state->numCerts = 0; | |
| 2214 if (pkixErrorResult) { | |
| 2215 pkixErrorClass = pkixErrorResult->errClass; | |
| 2216 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
| 2217 goto fatal; | |
| 2218 } | |
| 2219 PKIX_DECREF(finalError); | |
| 2220 finalError = pkixErrorResult; | |
| 2221 pkixErrorResult = NULL; | |
| 2222 if (state->verifyNode != NULL) { | |
| 2223 /* state->verifyNode is the object that contains a list | |
| 2224 * of verifyNodes. verifyNodes contains cert chain | |
| 2225 * build failures that occurred on this level of chain | |
| 2226 * building. Here, creating new verify node | |
| 2227 * to log the failure and adding it to the list. */ | |
| 2228 PKIX_CHECK_FATAL(pkix_VerifyNode_Create | |
| 2229 (state->prevCert, | |
| 2230 0, NULL, | |
| 2231 &verifyNode, | |
| 2232 plContext), | |
| 2233 PKIX_VERIFYNODECREATEFAILED); | |
| 2234 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
| 2235 (verifyNode, finalError, plContext), | |
| 2236 PKIX_VERIFYNODESETERRORFAILED); | |
| 2237 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
| 2238 (state->verifyNode, | |
| 2239 verifyNode, | |
| 2240 plContext), | |
| 2241 PKIX_VERIFYNODEADDTOTREEFAILED); | |
| 2242 PKIX_DECREF(verifyNode); | |
| 2243 } | |
| 2244 } | |
| 2245 #ifdef PKIX_BUILDDEBUG | |
| 2246 /* Turn this on to trace the List of Certs, before CertSelect */ | |
| 2247 { | |
| 2248 PKIX_PL_String *unString; | |
| 2249 char *unAscii; | |
| 2250 PKIX_UInt32 length; | |
| 2251 PKIX_TOSTRING | |
| 2252 ((PKIX_PL_Object*)unfilteredCerts, | |
| 2253 &unString, | |
| 2254 plContext, | |
| 2255 PKIX_OBJECTTOSTRINGFAILED); | |
| 2256 | |
| 2257 PKIX_CHECK(PKIX_PL_String_GetEncoded | |
| 2258 (unString, | |
| 2259 PKIX_ESCASCII, | |
| 2260 (void **)&unAscii, | |
| 2261 &length, | |
| 2262 plContext), | |
| 2263 PKIX_STRINGGETENCODEDFAILED); | |
| 2264 | |
| 2265 PKIX_DEBUG_ARG | |
| 2266 ("unfilteredCerts = %s\n", unAscii); | |
| 2267 PKIX_DECREF(unString); | |
| 2268 PKIX_FREE(unAscii); | |
| 2269 } | |
| 2270 #endif | |
| 2271 | |
| 2272 /* Note: Certs winnowed here don't get into VerifyTree. */ | |
| 2273 if (unfilteredCerts) { | |
| 2274 PKIX_CHECK(pkix_CertSelector_Select | |
| 2275 (state->certSel, | |
| 2276 unfilteredCerts, | |
| 2277 &filteredCerts, | |
| 2278 plContext), | |
| 2279 PKIX_CERTSELECTORSELECTFAILED); | |
| 2280 | |
| 2281 PKIX_DECREF(unfilteredCerts); | |
| 2282 | |
| 2283 PKIX_CHECK(PKIX_List_GetLength | |
| 2284 (filteredCerts, &(state->numCerts), plContext), | |
| 2285 PKIX_LISTGETLENGTHFAILED); | |
| 2286 | |
| 2287 #ifdef PKIX_BUILDDEBUG | |
| 2288 /* Turn this on to trace the List of Certs, after CertSelect */ | |
| 2289 { | |
| 2290 PKIX_PL_String *unString; | |
| 2291 char *unAscii; | |
| 2292 PKIX_UInt32 length; | |
| 2293 PKIX_TOSTRING | |
| 2294 ((PKIX_PL_Object*)filteredCerts, | |
| 2295 &unString, | |
| 2296 plContext, | |
| 2297 PKIX_OBJECTTOSTRINGFAILED); | |
| 2298 | |
| 2299 PKIX_CHECK(PKIX_PL_String_GetEncoded | |
| 2300 (unString, | |
| 2301 PKIX_ESCASCII, | |
| 2302 (void **)&unAscii, | |
| 2303 &length, | |
| 2304 plContext), | |
| 2305 PKIX_STRINGGETENCODEDFAILED); | |
| 2306 | |
| 2307 PKIX_DEBUG_ARG("filteredCerts = %s\n", unAscii); | |
| 2308 PKIX_DECREF(unString); | |
| 2309 PKIX_FREE(unAscii); | |
| 2310 } | |
| 2311 #endif | |
| 2312 | |
| 2313 PKIX_DECREF(state->candidateCerts); | |
| 2314 state->candidateCerts = filteredCerts; | |
| 2315 state->certIndex = 0; | |
| 2316 filteredCerts = NULL; | |
| 2317 } | |
| 2318 | |
| 2319 /* Are there any Certs to try? */ | |
| 2320 if (state->numCerts > 0) { | |
| 2321 state->status = BUILD_CERTVALIDATING; | |
| 2322 } else { | |
| 2323 state->status = BUILD_COLLECTINGCERTS; | |
| 2324 } | |
| 2325 } | |
| 2326 | |
| 2327 PKIX_DECREF(certSelParams); | |
| 2328 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams | |
| 2329 (state->certSel, &certSelParams, plContext), | |
| 2330 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); | |
| 2331 | |
| 2332 /* **** Querying the CertStores ***** */ | |
| 2333 if ((state->status == BUILD_COLLECTINGCERTS) || | |
| 2334 (state->status == BUILD_GATHERPENDING)) { | |
| 2335 | |
| 2336 #if PKIX_FORWARDBUILDERSTATEDEBUG | |
| 2337 PKIX_CHECK(pkix_ForwardBuilderState_DumpState | |
| 2338 (state, plContext), | |
| 2339 PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED); | |
| 2340 #endif | |
| 2341 | |
| 2342 PKIX_CHECK(pkix_Build_GatherCerts | |
| 2343 (state, certSelParams, &nbio, plContext), | |
| 2344 PKIX_BUILDGATHERCERTSFAILED); | |
| 2345 | |
| 2346 if (nbio != NULL) { | |
| 2347 /* IO still pending, resume later */ | |
| 2348 *pNBIOContext = nbio; | |
| 2349 goto cleanup; | |
| 2350 } | |
| 2351 | |
| 2352 /* Are there any Certs to try? */ | |
| 2353 if (state->numCerts > 0) { | |
| 2354 state->status = BUILD_CERTVALIDATING; | |
| 2355 } else { | |
| 2356 state->status = BUILD_ABANDONNODE; | |
| 2357 } | |
| 2358 } | |
| 2359 | |
| 2360 /* ****Phase 2 - Chain building***** */ | |
| 2361 | |
| 2362 #if PKIX_FORWARDBUILDERSTATEDEBUG | |
| 2363 PKIX_CHECK(pkix_ForwardBuilderState_DumpState(state, plContext), | |
| 2364 PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED); | |
| 2365 #endif | |
| 2366 | |
| 2367 if (state->status == BUILD_CERTVALIDATING) { | |
| 2368 revocationCheckingExists = | |
| 2369 (state->buildConstants.revChecker != NULL); | |
| 2370 | |
| 2371 PKIX_DECREF(state->candidateCert); | |
| 2372 PKIX_CHECK(PKIX_List_GetItem | |
| 2373 (state->candidateCerts, | |
| 2374 state->certIndex, | |
| 2375 (PKIX_PL_Object **)&(state->candidateCert), | |
| 2376 plContext), | |
| 2377 PKIX_LISTGETITEMFAILED); | |
| 2378 | |
| 2379 if ((state->verifyNode) != NULL) { | |
| 2380 PKIX_CHECK_FATAL(pkix_VerifyNode_Create | |
| 2381 (state->candidateCert, | |
| 2382 0, | |
| 2383 NULL, | |
| 2384 &verifyNode, | |
| 2385 plContext), | |
| 2386 PKIX_VERIFYNODECREATEFAILED); | |
| 2387 } | |
| 2388 | |
| 2389 /* If failure, this function sets Error in verifyNode */ | |
| 2390 verifyError = pkix_Build_VerifyCertificate | |
| 2391 (state, | |
| 2392 state->buildConstants.userCheckers, | |
| 2393 revocationCheckingExists, | |
| 2394 &trusted, | |
| 2395 &needsCRLChecking, | |
| 2396 verifyNode, | |
| 2397 plContext); | |
| 2398 | |
| 2399 if (verifyError) { | |
| 2400 pkixTempErrorReceived = PKIX_TRUE; | |
| 2401 pkixErrorClass = verifyError->errClass; | |
| 2402 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
| 2403 pkixErrorResult = verifyError; | |
| 2404 verifyError = NULL; | |
| 2405 goto fatal; | |
| 2406 } | |
| 2407 } | |
| 2408 | |
| 2409 if (PKIX_ERROR_RECEIVED) { | |
| 2410 if (state->verifyNode != NULL) { | |
| 2411 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
| 2412 (verifyNode, verifyError, plContext), | |
| 2413 PKIX_VERIFYNODESETERRORFAILED); | |
| 2414 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
| 2415 (state->verifyNode, | |
| 2416 verifyNode, | |
| 2417 plContext), | |
| 2418 PKIX_VERIFYNODEADDTOTREEFAILED); | |
| 2419 PKIX_DECREF(verifyNode); | |
| 2420 } | |
| 2421 pkixTempErrorReceived = PKIX_FALSE; | |
| 2422 PKIX_DECREF(finalError); | |
| 2423 finalError = verifyError; | |
| 2424 verifyError = NULL; | |
| 2425 if (state->certLoopingDetected) { | |
| 2426 PKIX_ERROR | |
| 2427 (PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED); | |
| 2428 } | |
| 2429 state->status = BUILD_GETNEXTCERT; | |
| 2430 } else if (needsCRLChecking) { | |
| 2431 state->status = BUILD_CRLPREP; | |
| 2432 } else { | |
| 2433 state->status = BUILD_DATEPREP; | |
| 2434 } | |
| 2435 } | |
| 2436 | |
| 2437 if (state->status == BUILD_CRLPREP) { | |
| 2438 PKIX_RevocationStatus revStatus; | |
| 2439 PKIX_UInt32 reasonCode; | |
| 2440 | |
| 2441 verifyError = | |
| 2442 PKIX_RevocationChecker_Check( | |
| 2443 state->prevCert, state->candidateCert, | |
| 2444 state->buildConstants.revChecker, | |
| 2445 state->buildConstants.procParams, | |
| 2446 PKIX_FALSE, | |
| 2447 (state->parentState == NULL) ? | |
| 2448 PKIX_TRUE : PKIX_FALSE, | |
| 2449 &revStatus, &reasonCode, | |
| 2450 &nbio, plContext); | |
| 2451 if (nbio != NULL) { | |
| 2452 *pNBIOContext = nbio; | |
| 2453 goto cleanup; | |
| 2454 } | |
| 2455 if (revStatus == PKIX_RevStatus_Revoked || verifyError) { | |
| 2456 if (!verifyError) { | |
| 2457 /* if verifyError is returned then use it as | |
| 2458 * it has a detailed revocation error code. | |
| 2459 * Otherwise create a new error */ | |
| 2460 PKIX_ERROR_CREATE(VALIDATE, PKIX_CERTIFICATEREVOKED, | |
| 2461 verifyError); | |
| 2462 } | |
| 2463 if (state->verifyNode != NULL) { | |
| 2464 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
| 2465 (verifyNode, verifyError, plContext), | |
| 2466 PKIX_VERIFYNODESETERRORFAILED); | |
| 2467 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
| 2468 (state->verifyNode, | |
| 2469 verifyNode, | |
| 2470 plContext), | |
| 2471 PKIX_VERIFYNODEADDTOTREEFAILED); | |
| 2472 PKIX_DECREF(verifyNode); | |
| 2473 } | |
| 2474 PKIX_DECREF(finalError); | |
| 2475 finalError = verifyError; | |
| 2476 verifyError = NULL; | |
| 2477 if (state->certLoopingDetected) { | |
| 2478 PKIX_ERROR | |
| 2479 (PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED); | |
| 2480 } | |
| 2481 state->status = BUILD_GETNEXTCERT; | |
| 2482 } else { | |
| 2483 state->status = BUILD_DATEPREP; | |
| 2484 } | |
| 2485 } | |
| 2486 | |
| 2487 if (state->status == BUILD_DATEPREP) { | |
| 2488 /* Keep track of whether this chain can be cached */ | |
| 2489 PKIX_CHECK(pkix_Build_UpdateDate(state, plContext), | |
| 2490 PKIX_BUILDUPDATEDATEFAILED); | |
| 2491 | |
| 2492 canBeCached = state->canBeCached; | |
| 2493 PKIX_DECREF(validityDate); | |
| 2494 PKIX_INCREF(state->validityDate); | |
| 2495 validityDate = state->validityDate; | |
| 2496 if (trusted == PKIX_TRUE) { | |
| 2497 state->status = BUILD_CHECKTRUSTED; | |
| 2498 } else { | |
| 2499 state->status = BUILD_ADDTOCHAIN; | |
| 2500 } | |
| 2501 } | |
| 2502 | |
| 2503 if (state->status == BUILD_CHECKTRUSTED) { | |
| 2504 | |
| 2505 /* | |
| 2506 * If this cert is trusted, try to validate the entire | |
| 2507 * chain using this certificate as trust anchor. | |
| 2508 */ | |
| 2509 PKIX_CHECK(PKIX_TrustAnchor_CreateWithCert | |
| 2510 (state->candidateCert, | |
| 2511 &trustAnchor, | |
| 2512 plContext), | |
| 2513 PKIX_TRUSTANCHORCREATEWITHCERTFAILED); | |
| 2514 | |
| 2515 PKIX_CHECK(pkix_Build_ValidationCheckers | |
| 2516 (state, | |
| 2517 state->trustChain, | |
| 2518 trustAnchor, | |
| 2519 PKIX_FALSE, /* do not add eku checker | |
| 2520 * since eku was already | |
| 2521 * checked */ | |
| 2522 plContext), | |
| 2523 PKIX_BUILDVALIDATIONCHECKERSFAILED); | |
| 2524 | |
| 2525 state->status = BUILD_CHECKTRUSTED2; | |
| 2526 } | |
| 2527 | |
| 2528 if (state->status == BUILD_CHECKTRUSTED2) { | |
| 2529 verifyError = | |
| 2530 pkix_Build_ValidateEntireChain(state, | |
| 2531 trustAnchor, | |
| 2532 &nbio, &valResult, | |
| 2533 verifyNode, | |
| 2534 plContext); | |
| 2535 if (nbio != NULL) { | |
| 2536 /* IO still pending, resume later */ | |
| 2537 goto cleanup; | |
| 2538 } else { | |
| 2539 /* checking the error for fatal status */ | |
| 2540 if (verifyError) { | |
| 2541 pkixTempErrorReceived = PKIX_TRUE; | |
| 2542 pkixErrorClass = verifyError->errClass; | |
| 2543 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
| 2544 pkixErrorResult = verifyError; | |
| 2545 verifyError = NULL; | |
| 2546 goto fatal; | |
| 2547 } | |
| 2548 } | |
| 2549 if (state->verifyNode != NULL) { | |
| 2550 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
| 2551 (state->verifyNode, | |
| 2552 verifyNode, | |
| 2553 plContext), | |
| 2554 PKIX_VERIFYNODEADDTOTREEFAILED); | |
| 2555 PKIX_DECREF(verifyNode); | |
| 2556 } | |
| 2557 if (!PKIX_ERROR_RECEIVED) { | |
| 2558 *pValResult = valResult; | |
| 2559 valResult = NULL; | |
| 2560 /* Change state so IsIOPending is FALSE */ | |
| 2561 state->status = BUILD_CHECKTRUSTED; | |
| 2562 goto cleanup; | |
| 2563 } | |
| 2564 PKIX_DECREF(finalError); | |
| 2565 finalError = verifyError; | |
| 2566 verifyError = NULL; | |
| 2567 /* Reset temp error that was set by | |
| 2568 * PKIX_CHECK_ONLY_FATAL and continue */ | |
| 2569 pkixTempErrorReceived = PKIX_FALSE; | |
| 2570 PKIX_DECREF(trustAnchor); | |
| 2571 } | |
| 2572 | |
| 2573 /* | |
| 2574 * If chain doesn't validate with a trusted Cert, | |
| 2575 * adding more Certs to it can't help. | |
| 2576 */ | |
| 2577 if (state->certLoopingDetected) { | |
| 2578 PKIX_DECREF(verifyError); | |
| 2579 PKIX_ERROR_CREATE(BUILD, | |
| 2580 PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED, | |
| 2581 verifyError); | |
| 2582 PKIX_CHECK_FATAL( | |
| 2583 pkix_VerifyNode_SetError(state->verifyNode, | |
| 2584 verifyError, | |
| 2585 plContext), | |
| 2586 PKIX_VERIFYNODESETERRORFAILED); | |
| 2587 PKIX_DECREF(verifyError); | |
| 2588 } | |
| 2589 state->status = BUILD_GETNEXTCERT; | |
| 2590 } | |
| 2591 | |
| 2592 /* | |
| 2593 * This Cert was not trusted. Add it to our chain, and | |
| 2594 * continue building. If we don't reach a trust anchor, | |
| 2595 * we'll take it off later and continue without it. | |
| 2596 */ | |
| 2597 if (state->status == BUILD_ADDTOCHAIN) { | |
| 2598 PKIX_CHECK(PKIX_List_AppendItem | |
| 2599 (state->trustChain, | |
| 2600 (PKIX_PL_Object *)state->candidateCert, | |
| 2601 plContext), | |
| 2602 PKIX_LISTAPPENDITEMFAILED); | |
| 2603 | |
| 2604 state->status = BUILD_EXTENDCHAIN; | |
| 2605 } | |
| 2606 | |
| 2607 if (state->status == BUILD_EXTENDCHAIN) { | |
| 2608 | |
| 2609 /* Check whether we are allowed to extend the chain */ | |
| 2610 if ((state->buildConstants.maxDepth != 0) && | |
| 2611 (state->numDepth <= 1)) { | |
| 2612 | |
| 2613 if (state->verifyNode != NULL) { | |
| 2614 PKIX_ERROR_CREATE | |
| 2615 (BUILD, | |
| 2616 PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS, | |
| 2617 verifyError); | |
| 2618 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError | |
| 2619 (verifyNode, verifyError, plContext), | |
| 2620 PKIX_VERIFYNODESETERRORFAILED); | |
| 2621 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
| 2622 (state->verifyNode, verifyNode, plContext), | |
| 2623 PKIX_VERIFYNODEADDTOTREEFAILED); | |
| 2624 PKIX_DECREF(verifyNode); | |
| 2625 PKIX_DECREF(finalError); | |
| 2626 finalError = verifyError; | |
| 2627 verifyError = NULL; | |
| 2628 } | |
| 2629 /* Even if error logged, still need to abort */ | |
| 2630 PKIX_ERROR(PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS); | |
| 2631 } | |
| 2632 | |
| 2633 PKIX_CHECK(pkix_IsCertSelfIssued | |
| 2634 (state->candidateCert, &isSelfIssued, plContext), | |
| 2635 PKIX_ISCERTSELFISSUEDFAILED); | |
| 2636 | |
| 2637 PKIX_CHECK(PKIX_PL_Object_Duplicate | |
| 2638 ((PKIX_PL_Object *)state->traversedSubjNames, | |
| 2639 (PKIX_PL_Object **)&childTraversedSubjNames, | |
| 2640 plContext), | |
| 2641 PKIX_OBJECTDUPLICATEFAILED); | |
| 2642 | |
| 2643 if (isSelfIssued) { | |
| 2644 childTraversedCACerts = state->traversedCACerts; | |
| 2645 } else { | |
| 2646 childTraversedCACerts = state->traversedCACerts + 1; | |
| 2647 | |
| 2648 PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames | |
| 2649 (state->candidateCert, | |
| 2650 &subjectNames, | |
| 2651 plContext), | |
| 2652 PKIX_CERTGETALLSUBJECTNAMESFAILED); | |
| 2653 | |
| 2654 if (subjectNames) { | |
| 2655 PKIX_CHECK(PKIX_List_GetLength | |
| 2656 (subjectNames, | |
| 2657 &numSubjectNames, | |
| 2658 plContext), | |
| 2659 PKIX_LISTGETLENGTHFAILED); | |
| 2660 | |
| 2661 } else { | |
| 2662 numSubjectNames = 0; | |
| 2663 } | |
| 2664 | |
| 2665 for (i = 0; i < numSubjectNames; i++) { | |
| 2666 PKIX_CHECK(PKIX_List_GetItem | |
| 2667 (subjectNames, | |
| 2668 i, | |
| 2669 &subjectName, | |
| 2670 plContext), | |
| 2671 PKIX_LISTGETITEMFAILED); | |
| 2672 PKIX_NULLCHECK_ONE | |
| 2673 (state->traversedSubjNames); | |
| 2674 PKIX_CHECK(PKIX_List_AppendItem | |
| 2675 (state->traversedSubjNames, | |
| 2676 subjectName, | |
| 2677 plContext), | |
| 2678 PKIX_LISTAPPENDITEMFAILED); | |
| 2679 PKIX_DECREF(subjectName); | |
| 2680 } | |
| 2681 PKIX_DECREF(subjectNames); | |
| 2682 } | |
| 2683 | |
| 2684 PKIX_CHECK(pkix_ForwardBuilderState_Create | |
| 2685 (childTraversedCACerts, | |
| 2686 state->buildConstants.maxFanout, | |
| 2687 state->numDepth - 1, | |
| 2688 state->revCheckDelayed, | |
| 2689 canBeCached, | |
| 2690 validityDate, | |
| 2691 state->candidateCert, | |
| 2692 childTraversedSubjNames, | |
| 2693 state->trustChain, | |
| 2694 state, | |
| 2695 &childState, | |
| 2696 plContext), | |
| 2697 PKIX_FORWARDBUILDSTATECREATEFAILED); | |
| 2698 | |
| 2699 PKIX_DECREF(childTraversedSubjNames); | |
| 2700 PKIX_DECREF(certSelParams); | |
| 2701 childState->verifyNode = verifyNode; | |
| 2702 verifyNode = NULL; | |
| 2703 PKIX_DECREF(state); | |
| 2704 state = childState; /* state->status == BUILD_INITIAL */ | |
| 2705 childState = NULL; | |
| 2706 continue; /* with while (!outOfOptions) */ | |
| 2707 } | |
| 2708 | |
| 2709 if (state->status == BUILD_GETNEXTCERT) { | |
| 2710 pkixTempErrorReceived = PKIX_FALSE; | |
| 2711 PKIX_DECREF(state->candidateCert); | |
| 2712 | |
| 2713 /* | |
| 2714 * If we were using a Cert from the callier-supplied partial | |
| 2715 * chain, delete it and go to the certStores. | |
| 2716 */ | |
| 2717 if (state->usingHintCerts == PKIX_TRUE) { | |
| 2718 PKIX_DECREF(state->candidateCerts); | |
| 2719 PKIX_CHECK(PKIX_List_Create | |
| 2720 (&state->candidateCerts, plContext), | |
| 2721 PKIX_LISTCREATEFAILED); | |
| 2722 | |
| 2723 state->numCerts = 0; | |
| 2724 state->usingHintCerts = PKIX_FALSE; | |
| 2725 state->status = BUILD_TRYAIA; | |
| 2726 continue; | |
| 2727 } else if (++(state->certIndex) < (state->numCerts)) { | |
| 2728 if ((state->buildConstants.maxFanout != 0) && | |
| 2729 (--(state->numFanout) == 0)) { | |
| 2730 | |
| 2731 if (state->verifyNode != NULL) { | |
| 2732 PKIX_ERROR_CREATE | |
| 2733 (BUILD, | |
| 2734 PKIX_FANOUTEXCEEDSRESOURCELIMITS, | |
| 2735 verifyError); | |
| 2736 PKIX_CHECK_FATAL | |
| 2737 (pkix_VerifyNode_SetError | |
| 2738 (state->verifyNode, | |
| 2739 verifyError, | |
| 2740 plContext), | |
| 2741 PKIX_VERIFYNODESETERRORFAILED); | |
| 2742 PKIX_DECREF(finalError); | |
| 2743 finalError = verifyError; | |
| 2744 verifyError = NULL; | |
| 2745 } | |
| 2746 /* Even if error logged, still need to abort */ | |
| 2747 PKIX_ERROR | |
| 2748 (PKIX_FANOUTEXCEEDSRESOURCELIMITS); | |
| 2749 } | |
| 2750 state->status = BUILD_CERTVALIDATING; | |
| 2751 continue; | |
| 2752 } | |
| 2753 } | |
| 2754 | |
| 2755 /* | |
| 2756 * Adding the current cert to the chain didn't help. If our search | |
| 2757 * has been restricted to local certStores, try opening up the | |
| 2758 * search and see whether that helps. Otherwise, back up to the | |
| 2759 * parent cert, and see if there are any more to try. | |
| 2760 */ | |
| 2761 if (state->useOnlyLocal == PKIX_TRUE) { | |
| 2762 pkix_PrepareForwardBuilderStateForAIA(state); | |
| 2763 } else do { | |
| 2764 if (state->parentState == NULL) { | |
| 2765 /* We are at the top level, and can't back up! */ | |
| 2766 outOfOptions = PKIX_TRUE; | |
| 2767 } else { | |
| 2768 /* | |
| 2769 * Try the next cert, if any, for this parent. | |
| 2770 * Otherwise keep backing up until we reach a | |
| 2771 * parent with more certs to try. | |
| 2772 */ | |
| 2773 PKIX_CHECK(PKIX_List_GetLength | |
| 2774 (state->trustChain, &numChained, plContext), | |
| 2775 PKIX_LISTGETLENGTHFAILED); | |
| 2776 PKIX_CHECK(PKIX_List_DeleteItem | |
| 2777 (state->trustChain, numChained - 1, plContext), | |
| 2778 PKIX_LISTDELETEITEMFAILED); | |
| 2779 | |
| 2780 /* local and aia fetching returned no good certs. | |
| 2781 * Creating a verify node in the parent that tells | |
| 2782 * us this. */ | |
| 2783 if (!state->verifyNode) { | |
| 2784 PKIX_CHECK_FATAL( | |
| 2785 pkix_VerifyNode_Create(state->prevCert, | |
| 2786 0, NULL, | |
| 2787 &state->verifyNode, | |
| 2788 plContext), | |
| 2789 PKIX_VERIFYNODECREATEFAILED); | |
| 2790 } | |
| 2791 /* Updating the log with the error. */ | |
| 2792 PKIX_DECREF(verifyError); | |
| 2793 PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER, | |
| 2794 verifyError); | |
| 2795 PKIX_CHECK_FATAL( | |
| 2796 pkix_VerifyNode_SetError(state->verifyNode, | |
| 2797 verifyError, | |
| 2798 plContext), | |
| 2799 PKIX_VERIFYNODESETERRORFAILED); | |
| 2800 PKIX_DECREF(verifyError); | |
| 2801 | |
| 2802 PKIX_INCREF(state->parentState); | |
| 2803 parentState = state->parentState; | |
| 2804 PKIX_DECREF(verifyNode); | |
| 2805 verifyNode = state->verifyNode; | |
| 2806 state->verifyNode = NULL; | |
| 2807 PKIX_DECREF(state); | |
| 2808 state = parentState; | |
| 2809 parentState = NULL; | |
| 2810 if (state->verifyNode != NULL && verifyNode) { | |
| 2811 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
| 2812 (state->verifyNode, | |
| 2813 verifyNode, | |
| 2814 plContext), | |
| 2815 PKIX_VERIFYNODEADDTOTREEFAILED); | |
| 2816 PKIX_DECREF(verifyNode); | |
| 2817 } | |
| 2818 PKIX_DECREF(validityDate); | |
| 2819 PKIX_INCREF(state->validityDate); | |
| 2820 validityDate = state->validityDate; | |
| 2821 canBeCached = state->canBeCached; | |
| 2822 | |
| 2823 /* Are there any more Certs to try? */ | |
| 2824 if (++(state->certIndex) < (state->numCerts)) { | |
| 2825 state->status = BUILD_CERTVALIDATING; | |
| 2826 PKIX_DECREF(state->candidateCert); | |
| 2827 break; | |
| 2828 } | |
| 2829 if (state->useOnlyLocal == PKIX_TRUE) { | |
| 2830 /* Clean up and go for AIA round. */ | |
| 2831 pkix_PrepareForwardBuilderStateForAIA(state); | |
| 2832 break; | |
| 2833 } | |
| 2834 } | |
| 2835 PKIX_DECREF(state->candidateCert); | |
| 2836 } while (outOfOptions == PKIX_FALSE); | |
| 2837 | |
| 2838 } /* while (outOfOptions == PKIX_FALSE) */ | |
| 2839 | |
| 2840 cleanup: | |
| 2841 | |
| 2842 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
| 2843 goto fatal; | |
| 2844 } | |
| 2845 | |
| 2846 /* verifyNode should be equal to NULL at this point. Assert it. | |
| 2847 * Temporarelly use verifyError to store an error ref to which we | |
| 2848 * have in pkixErrorResult. This is done to prevent error cloberring | |
| 2849 * while using macros below. */ | |
| 2850 PORT_Assert(verifyError == NULL); | |
| 2851 verifyError = pkixErrorResult; | |
| 2852 | |
| 2853 /* | |
| 2854 * We were called with an initialState that had no parent. If we are | |
| 2855 * returning with an error or with a result, we must destroy any state | |
| 2856 * that we created (any state with a parent). | |
| 2857 */ | |
| 2858 | |
| 2859 PKIX_CHECK_FATAL(pkix_ForwardBuilderState_IsIOPending | |
| 2860 (state, &ioPending, plContext), | |
| 2861 PKIX_FORWARDBUILDERSTATEISIOPENDINGFAILED); | |
| 2862 | |
| 2863 if (ioPending == PKIX_FALSE) { | |
| 2864 while (state->parentState) { | |
| 2865 PKIX_INCREF(state->parentState); | |
| 2866 parentState = state->parentState; | |
| 2867 PKIX_DECREF(verifyNode); | |
| 2868 verifyNode = state->verifyNode; | |
| 2869 state->verifyNode = NULL; | |
| 2870 PKIX_DECREF(state); | |
| 2871 state = parentState; | |
| 2872 parentState = NULL; | |
| 2873 if (state->verifyNode != NULL && verifyNode) { | |
| 2874 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree | |
| 2875 (state->verifyNode, | |
| 2876 verifyNode, | |
| 2877 plContext), | |
| 2878 PKIX_VERIFYNODEADDTOTREEFAILED); | |
| 2879 PKIX_DECREF(verifyNode); | |
| 2880 } | |
| 2881 } | |
| 2882 state->canBeCached = canBeCached; | |
| 2883 PKIX_DECREF(state->validityDate); | |
| 2884 state->validityDate = validityDate; | |
| 2885 validityDate = NULL; | |
| 2886 } | |
| 2887 if (!*pValResult && !verifyError) { | |
| 2888 if (!finalError) { | |
| 2889 PKIX_CHECK_FATAL( | |
| 2890 pkix_VerifyNode_FindError(state->verifyNode, | |
| 2891 &finalError, | |
| 2892 plContext), | |
| 2893 PKIX_VERIFYNODEFINDERRORFAILED); | |
| 2894 } | |
| 2895 if (finalError) { | |
| 2896 pkixErrorResult = finalError; | |
| 2897 pkixErrorCode = PKIX_BUILDFORWARDDEPTHFIRSTSEARCHFAILED; | |
| 2898 finalError = NULL; | |
| 2899 goto fatal; | |
| 2900 } | |
| 2901 pkixErrorCode = PKIX_SECERRORUNKNOWNISSUER; | |
| 2902 pkixErrorReceived = PKIX_TRUE; | |
| 2903 PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER, | |
| 2904 verifyError); | |
| 2905 PKIX_CHECK_FATAL( | |
| 2906 pkix_VerifyNode_SetError(state->verifyNode, verifyError, | |
| 2907 plContext), | |
| 2908 PKIX_VERIFYNODESETERRORFAILED); | |
| 2909 } else { | |
| 2910 pkixErrorResult = verifyError; | |
| 2911 verifyError = NULL; | |
| 2912 } | |
| 2913 | |
| 2914 fatal: | |
| 2915 if (state->parentState) { | |
| 2916 /* parentState in "state" object should be NULL at this point. | |
| 2917 * If itn't, that means that we got fatal error(we have jumped to | |
| 2918 * "fatal" label) and we should destroy all state except the top one
. */ | |
| 2919 while (state->parentState) { | |
| 2920 PKIX_Error *error = NULL; | |
| 2921 PKIX_ForwardBuilderState *prntState = state->parentState; | |
| 2922 /* Dumb: need to increment parentState to avoid destruction | |
| 2923 * of "build constants"(they get destroyed when parentState is | |
| 2924 * set to NULL. */ | |
| 2925 PKIX_INCREF(prntState); | |
| 2926 error = PKIX_PL_Object_DecRef((PKIX_PL_Object*)state, plContext)
; | |
| 2927 if (error) { | |
| 2928 PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext); | |
| 2929 } | |
| 2930 /* No need to decref the parent state. It was already done by | |
| 2931 * pkix_ForwardBuilderState_Destroy function. */ | |
| 2932 state = prntState; | |
| 2933 } | |
| 2934 } | |
| 2935 PKIX_DECREF(parentState); | |
| 2936 PKIX_DECREF(childState); | |
| 2937 PKIX_DECREF(valResult); | |
| 2938 PKIX_DECREF(verifyError); | |
| 2939 PKIX_DECREF(finalError); | |
| 2940 PKIX_DECREF(verifyNode); | |
| 2941 PKIX_DECREF(childTraversedSubjNames); | |
| 2942 PKIX_DECREF(certSelParams); | |
| 2943 PKIX_DECREF(subjectNames); | |
| 2944 PKIX_DECREF(subjectName); | |
| 2945 PKIX_DECREF(trustAnchor); | |
| 2946 PKIX_DECREF(validityDate); | |
| 2947 PKIX_DECREF(revCheckerState); | |
| 2948 PKIX_DECREF(currTime); | |
| 2949 PKIX_DECREF(filteredCerts); | |
| 2950 PKIX_DECREF(unfilteredCerts); | |
| 2951 PKIX_DECREF(trustedCert); | |
| 2952 | |
| 2953 PKIX_RETURN(BUILD); | |
| 2954 } | |
| 2955 | |
| 2956 /* | |
| 2957 * FUNCTION: pkix_Build_CheckInCache | |
| 2958 * DESCRIPTION: | |
| 2959 * | |
| 2960 * The function tries to locate a chain for a cert in the cert chain cache. | |
| 2961 * If found, the chain goes through revocation chacking and returned back to | |
| 2962 * caller. Chains that fail revocation check get removed from cache. | |
| 2963 * | |
| 2964 * PARAMETERS: | |
| 2965 * "state" | |
| 2966 * Address of ForwardBuilderState to be used. Must be non-NULL. | |
| 2967 * "pBuildResult" | |
| 2968 * Address at which the BuildResult is stored, after a successful build. | |
| 2969 * Must be non-NULL. | |
| 2970 * "pNBIOContext" | |
| 2971 * Address at which the NBIOContext is stored indicating whether the | |
| 2972 * validation is complete. Must be non-NULL. | |
| 2973 * "plContext" | |
| 2974 * Platform-specific context pointer. | |
| 2975 * THREAD SAFETY: | |
| 2976 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 2977 * RETURNS: | |
| 2978 * Returns NULL if the function succeeds. | |
| 2979 * Returns a Build Error if the function fails in a non-fatal way | |
| 2980 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 2981 */ | |
| 2982 static PKIX_Error* | |
| 2983 pkix_Build_CheckInCache( | |
| 2984 PKIX_ForwardBuilderState *state, | |
| 2985 PKIX_BuildResult **pBuildResult, | |
| 2986 void **pNBIOContext, | |
| 2987 void *plContext) | |
| 2988 { | |
| 2989 PKIX_PL_Cert *targetCert = NULL; | |
| 2990 PKIX_List *anchors = NULL; | |
| 2991 PKIX_PL_Date *testDate = NULL; | |
| 2992 PKIX_BuildResult *buildResult = NULL; | |
| 2993 PKIX_ValidateResult *valResult = NULL; | |
| 2994 PKIX_Error *buildError = NULL; | |
| 2995 PKIX_TrustAnchor *matchingAnchor = NULL; | |
| 2996 PKIX_PL_Cert *trustedCert = NULL; | |
| 2997 PKIX_List *certList = NULL; | |
| 2998 PKIX_Boolean cacheHit = PKIX_FALSE; | |
| 2999 PKIX_Boolean trusted = PKIX_FALSE; | |
| 3000 PKIX_Boolean stillValid = PKIX_FALSE; | |
| 3001 void *nbioContext = NULL; | |
| 3002 | |
| 3003 PKIX_ENTER(BUILD, "pkix_Build_CheckInCache"); | |
| 3004 | |
| 3005 nbioContext = *pNBIOContext; | |
| 3006 *pNBIOContext = NULL; | |
| 3007 | |
| 3008 targetCert = state->buildConstants.targetCert; | |
| 3009 anchors = state->buildConstants.anchors; | |
| 3010 testDate = state->buildConstants.testDate; | |
| 3011 | |
| 3012 /* Check whether this cert verification has been cached. */ | |
| 3013 PKIX_CHECK(pkix_CacheCertChain_Lookup | |
| 3014 (targetCert, | |
| 3015 anchors, | |
| 3016 testDate, | |
| 3017 &cacheHit, | |
| 3018 &buildResult, | |
| 3019 plContext), | |
| 3020 PKIX_CACHECERTCHAINLOOKUPFAILED); | |
| 3021 | |
| 3022 if (!cacheHit) { | |
| 3023 goto cleanup; | |
| 3024 } | |
| 3025 | |
| 3026 /* | |
| 3027 * We found something in cache. Verify that the anchor | |
| 3028 * cert is still trusted, | |
| 3029 */ | |
| 3030 PKIX_CHECK(PKIX_BuildResult_GetValidateResult | |
| 3031 (buildResult, &valResult, plContext), | |
| 3032 PKIX_BUILDRESULTGETVALIDATERESULTFAILED); | |
| 3033 | |
| 3034 PKIX_CHECK(PKIX_ValidateResult_GetTrustAnchor | |
| 3035 (valResult, &matchingAnchor, plContext), | |
| 3036 PKIX_VALIDATERESULTGETTRUSTANCHORFAILED); | |
| 3037 | |
| 3038 PKIX_DECREF(valResult); | |
| 3039 | |
| 3040 PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert | |
| 3041 (matchingAnchor, &trustedCert, plContext), | |
| 3042 PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED); | |
| 3043 | |
| 3044 if (state->buildConstants.anchors && | |
| 3045 state->buildConstants.anchors->length) { | |
| 3046 /* Check if it is one of the trust anchors */ | |
| 3047 PKIX_CHECK( | |
| 3048 pkix_List_Contains(state->buildConstants.anchors, | |
| 3049 (PKIX_PL_Object *)matchingAnchor, | |
| 3050 &trusted, | |
| 3051 plContext), | |
| 3052 PKIX_LISTCONTAINSFAILED); | |
| 3053 } else { | |
| 3054 PKIX_CHECK(PKIX_PL_Cert_IsCertTrusted | |
| 3055 (trustedCert, PKIX_FALSE, &trusted, plContext), | |
| 3056 PKIX_CERTISCERTTRUSTEDFAILED); | |
| 3057 } | |
| 3058 | |
| 3059 if (!trusted) { | |
| 3060 goto cleanup; | |
| 3061 } | |
| 3062 /* | |
| 3063 * Since the key usage may vary for different | |
| 3064 * applications, we need to verify the chain again. | |
| 3065 * Reverification will be improved with a fix for 397805. | |
| 3066 */ | |
| 3067 PKIX_CHECK(PKIX_BuildResult_GetCertChain | |
| 3068 (buildResult, &certList, plContext), | |
| 3069 PKIX_BUILDRESULTGETCERTCHAINFAILED); | |
| 3070 | |
| 3071 PKIX_CHECK(pkix_Build_ValidationCheckers | |
| 3072 (state, | |
| 3073 certList, | |
| 3074 matchingAnchor, | |
| 3075 PKIX_TRUE, /* Chain revalidation stage. */ | |
| 3076 plContext), | |
| 3077 PKIX_BUILDVALIDATIONCHECKERSFAILED); | |
| 3078 | |
| 3079 PKIX_CHECK_ONLY_FATAL( | |
| 3080 pkix_Build_ValidateEntireChain(state, matchingAnchor, | |
| 3081 &nbioContext, &valResult, | |
| 3082 state->verifyNode, plContext), | |
| 3083 PKIX_BUILDVALIDATEENTIRECHAINFAILED); | |
| 3084 | |
| 3085 if (nbioContext != NULL) { | |
| 3086 /* IO still pending, resume later */ | |
| 3087 *pNBIOContext = nbioContext; | |
| 3088 goto cleanup; | |
| 3089 } | |
| 3090 if (!PKIX_ERROR_RECEIVED) { | |
| 3091 /* The result from cache is still valid. But we replace an old*/ | |
| 3092 *pBuildResult = buildResult; | |
| 3093 buildResult = NULL; | |
| 3094 stillValid = PKIX_TRUE; | |
| 3095 } | |
| 3096 | |
| 3097 cleanup: | |
| 3098 | |
| 3099 if (!nbioContext && cacheHit && !(trusted && stillValid)) { | |
| 3100 /* The anchor of this chain is no longer trusted or | |
| 3101 * chain cert(s) has been revoked. | |
| 3102 * Invalidate this result in the cache */ | |
| 3103 buildError = pkixErrorResult; | |
| 3104 PKIX_CHECK_FATAL(pkix_CacheCertChain_Remove | |
| 3105 (targetCert, | |
| 3106 anchors, | |
| 3107 plContext), | |
| 3108 PKIX_CACHECERTCHAINREMOVEFAILED); | |
| 3109 pkixErrorResult = buildError; | |
| 3110 buildError = NULL; | |
| 3111 } | |
| 3112 | |
| 3113 fatal: | |
| 3114 PKIX_DECREF(buildResult); | |
| 3115 PKIX_DECREF(valResult); | |
| 3116 PKIX_DECREF(buildError); | |
| 3117 PKIX_DECREF(certList); | |
| 3118 PKIX_DECREF(matchingAnchor); | |
| 3119 PKIX_DECREF(trustedCert); | |
| 3120 | |
| 3121 | |
| 3122 PKIX_RETURN(BUILD); | |
| 3123 } | |
| 3124 | |
| 3125 /* | |
| 3126 * FUNCTION: pkix_Build_InitiateBuildChain | |
| 3127 * DESCRIPTION: | |
| 3128 * | |
| 3129 * This function initiates the search for a BuildChain, using the parameters | |
| 3130 * provided in "procParams" and, if continuing a search that was suspended | |
| 3131 * for I/O, using the ForwardBuilderState pointed to by "pState". | |
| 3132 * | |
| 3133 * If a successful chain is built, this function stores the BuildResult at | |
| 3134 * "pBuildResult". Alternatively, if an operation using non-blocking I/O | |
| 3135 * is in progress and the operation has not been completed, this function | |
| 3136 * stores the platform-dependent non-blocking I/O context (nbioContext) at | |
| 3137 * "pNBIOContext", the FowardBuilderState at "pState", and NULL at | |
| 3138 * "pBuildResult". Finally, if chain building was unsuccessful, this function | |
| 3139 * stores NULL at both "pState" and at "pBuildResult". | |
| 3140 * | |
| 3141 * Note: This function is re-entered only for the case of non-blocking I/O | |
| 3142 * in the "short-cut" attempt to build a chain using the target Certificate | |
| 3143 * directly with one of the trustAnchors. For all other cases, resumption | |
| 3144 * after non-blocking I/O is via pkix_Build_ResumeBuildChain. | |
| 3145 * | |
| 3146 * PARAMETERS: | |
| 3147 * "procParams" | |
| 3148 * Address of the ProcessingParams for the search. Must be non-NULL. | |
| 3149 * "pNBIOContext" | |
| 3150 * Address at which the NBIOContext is stored indicating whether the | |
| 3151 * validation is complete. Must be non-NULL. | |
| 3152 * "pState" | |
| 3153 * Address at which the ForwardBuilderState is stored, if the chain | |
| 3154 * building is suspended for waiting I/O; also, the address at which the | |
| 3155 * ForwardBuilderState is provided for resumption of the chain building | |
| 3156 * attempt. Must be non-NULL. | |
| 3157 * "pBuildResult" | |
| 3158 * Address at which the BuildResult is stored, after a successful build. | |
| 3159 * Must be non-NULL. | |
| 3160 * "pVerifyNode" | |
| 3161 * Address at which a VerifyNode chain is returned, if non-NULL. | |
| 3162 * "plContext" | |
| 3163 * Platform-specific context pointer. | |
| 3164 * THREAD SAFETY: | |
| 3165 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 3166 * RETURNS: | |
| 3167 * Returns NULL if the function succeeds. | |
| 3168 * Returns a Build Error if the function fails in a non-fatal way | |
| 3169 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 3170 */ | |
| 3171 static PKIX_Error * | |
| 3172 pkix_Build_InitiateBuildChain( | |
| 3173 PKIX_ProcessingParams *procParams, | |
| 3174 void **pNBIOContext, | |
| 3175 PKIX_ForwardBuilderState **pState, | |
| 3176 PKIX_BuildResult **pBuildResult, | |
| 3177 PKIX_VerifyNode **pVerifyNode, | |
| 3178 void *plContext) | |
| 3179 { | |
| 3180 PKIX_UInt32 numAnchors = 0; | |
| 3181 PKIX_UInt32 numCertStores = 0; | |
| 3182 PKIX_UInt32 numHintCerts = 0; | |
| 3183 PKIX_UInt32 i = 0; | |
| 3184 PKIX_Boolean isDuplicate = PKIX_FALSE; | |
| 3185 PKIX_PL_Cert *trustedCert = NULL; | |
| 3186 PKIX_CertSelector *targetConstraints = NULL; | |
| 3187 PKIX_ComCertSelParams *targetParams = NULL; | |
| 3188 PKIX_List *anchors = NULL; | |
| 3189 PKIX_List *targetSubjNames = NULL; | |
| 3190 PKIX_PL_Cert *targetCert = NULL; | |
| 3191 PKIX_PL_Object *firstHintCert = NULL; | |
| 3192 PKIX_RevocationChecker *revChecker = NULL; | |
| 3193 PKIX_List *certStores = NULL; | |
| 3194 PKIX_CertStore *certStore = NULL; | |
| 3195 PKIX_List *userCheckers = NULL; | |
| 3196 PKIX_List *hintCerts = NULL; | |
| 3197 PKIX_PL_Date *testDate = NULL; | |
| 3198 PKIX_PL_PublicKey *targetPubKey = NULL; | |
| 3199 void *nbioContext = NULL; | |
| 3200 BuildConstants buildConstants; | |
| 3201 | |
| 3202 PKIX_List *tentativeChain = NULL; | |
| 3203 PKIX_ValidateResult *valResult = NULL; | |
| 3204 PKIX_BuildResult *buildResult = NULL; | |
| 3205 PKIX_List *certList = NULL; | |
| 3206 PKIX_ForwardBuilderState *state = NULL; | |
| 3207 PKIX_CertStore_CheckTrustCallback trustCallback = NULL; | |
| 3208 PKIX_CertSelector_MatchCallback selectorCallback = NULL; | |
| 3209 PKIX_Boolean trusted = PKIX_FALSE; | |
| 3210 PKIX_PL_AIAMgr *aiaMgr = NULL; | |
| 3211 | |
| 3212 PKIX_ENTER(BUILD, "pkix_Build_InitiateBuildChain"); | |
| 3213 PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult); | |
| 3214 | |
| 3215 nbioContext = *pNBIOContext; | |
| 3216 *pNBIOContext = NULL; | |
| 3217 | |
| 3218 state = *pState; | |
| 3219 *pState = NULL; /* no net change in reference count */ | |
| 3220 | |
| 3221 if (state == NULL) { | |
| 3222 PKIX_CHECK(PKIX_ProcessingParams_GetDate | |
| 3223 (procParams, &testDate, plContext), | |
| 3224 PKIX_PROCESSINGPARAMSGETDATEFAILED); | |
| 3225 | |
| 3226 PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors | |
| 3227 (procParams, &anchors, plContext), | |
| 3228 PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED); | |
| 3229 | |
| 3230 PKIX_CHECK(PKIX_List_GetLength(anchors, &numAnchors, plContext), | |
| 3231 PKIX_LISTGETLENGTHFAILED); | |
| 3232 | |
| 3233 /* retrieve stuff from targetCertConstraints */ | |
| 3234 PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints | |
| 3235 (procParams, &targetConstraints, plContext), | |
| 3236 PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED); | |
| 3237 | |
| 3238 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams | |
| 3239 (targetConstraints, &targetParams, plContext), | |
| 3240 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED); | |
| 3241 | |
| 3242 PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate | |
| 3243 (targetParams, &targetCert, plContext), | |
| 3244 PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED); | |
| 3245 | |
| 3246 PKIX_CHECK( | |
| 3247 PKIX_ComCertSelParams_SetLeafCertFlag(targetParams, | |
| 3248 PKIX_TRUE, plContext), | |
| 3249 PKIX_COMCERTSELPARAMSSETLEAFCERTFLAGFAILED); | |
| 3250 | |
| 3251 PKIX_CHECK(PKIX_ProcessingParams_GetHintCerts | |
| 3252 (procParams, &hintCerts, plContext), | |
| 3253 PKIX_PROCESSINGPARAMSGETHINTCERTSFAILED); | |
| 3254 | |
| 3255 if (hintCerts != NULL) { | |
| 3256 PKIX_CHECK(PKIX_List_GetLength | |
| 3257 (hintCerts, &numHintCerts, plContext), | |
| 3258 PKIX_LISTGETLENGTHFAILED); | |
| 3259 } | |
| 3260 | |
| 3261 /* | |
| 3262 * Caller must provide either a target Cert | |
| 3263 * (in ComCertSelParams->Certificate) or a partial Cert | |
| 3264 * chain (in ProcParams->HintCerts). | |
| 3265 */ | |
| 3266 | |
| 3267 if (targetCert == NULL) { | |
| 3268 | |
| 3269 /* Use first cert of hintCerts as the targetCert */ | |
| 3270 if (numHintCerts == 0) { | |
| 3271 PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED); | |
| 3272 } | |
| 3273 | |
| 3274 PKIX_CHECK(PKIX_List_GetItem | |
| 3275 (hintCerts, | |
| 3276 0, | |
| 3277 (PKIX_PL_Object **)&targetCert, | |
| 3278 plContext), | |
| 3279 PKIX_LISTGETITEMFAILED); | |
| 3280 | |
| 3281 PKIX_CHECK(PKIX_List_DeleteItem(hintCerts, 0, plContext), | |
| 3282 PKIX_LISTGETITEMFAILED); | |
| 3283 } else { | |
| 3284 | |
| 3285 /* | |
| 3286 * If the first hintCert is the same as the targetCert, | |
| 3287 * delete it from hintCerts. | |
| 3288 */ | |
| 3289 if (numHintCerts != 0) { | |
| 3290 PKIX_CHECK(PKIX_List_GetItem | |
| 3291 (hintCerts, 0, &firstHintCert, plContext), | |
| 3292 PKIX_LISTGETITEMFAILED); | |
| 3293 | |
| 3294 PKIX_CHECK(PKIX_PL_Object_Equals | |
| 3295 ((PKIX_PL_Object *)targetCert, | |
| 3296 firstHintCert, | |
| 3297 &isDuplicate, | |
| 3298 plContext), | |
| 3299 PKIX_OBJECTEQUALSFAILED); | |
| 3300 | |
| 3301 if (isDuplicate) { | |
| 3302 PKIX_CHECK(PKIX_List_DeleteItem | |
| 3303 (hintCerts, 0, plContext), | |
| 3304 PKIX_LISTGETITEMFAILED); | |
| 3305 } | |
| 3306 PKIX_DECREF(firstHintCert); | |
| 3307 } | |
| 3308 | |
| 3309 } | |
| 3310 | |
| 3311 if (targetCert == NULL) { | |
| 3312 PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED); | |
| 3313 } | |
| 3314 | |
| 3315 PKIX_CHECK(PKIX_PL_Cert_IsLeafCertTrusted | |
| 3316 (targetCert, | |
| 3317 &trusted, | |
| 3318 plContext), | |
| 3319 PKIX_CERTISCERTTRUSTEDFAILED); | |
| 3320 | |
| 3321 PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames | |
| 3322 (targetCert, | |
| 3323 &targetSubjNames, | |
| 3324 plContext), | |
| 3325 PKIX_CERTGETALLSUBJECTNAMESFAILED); | |
| 3326 | |
| 3327 PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey | |
| 3328 (targetCert, &targetPubKey, plContext), | |
| 3329 PKIX_CERTGETSUBJECTPUBLICKEYFAILED); | |
| 3330 | |
| 3331 PKIX_CHECK(PKIX_List_Create(&tentativeChain, plContext), | |
| 3332 PKIX_LISTCREATEFAILED); | |
| 3333 | |
| 3334 PKIX_CHECK(PKIX_List_AppendItem | |
| 3335 (tentativeChain, (PKIX_PL_Object *)targetCert, plContext), | |
| 3336 PKIX_LISTAPPENDITEMFAILED); | |
| 3337 | |
| 3338 if (procParams->qualifyTargetCert) { | |
| 3339 /* EE cert validation */ | |
| 3340 /* Sync up the time on the target selector parameter struct. */ | |
| 3341 PKIX_CHECK( | |
| 3342 PKIX_ComCertSelParams_SetCertificateValid(targetParams, | |
| 3343 testDate, | |
| 3344 plContext), | |
| 3345 PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED); | |
| 3346 | |
| 3347 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback | |
| 3348 (targetConstraints, &selectorCallback, plContext), | |
| 3349 PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); | |
| 3350 | |
| 3351 pkixErrorResult = | |
| 3352 (*selectorCallback)(targetConstraints, targetCert, | |
| 3353 plContext); | |
| 3354 if (pkixErrorResult) { | |
| 3355 pkixErrorClass = pkixErrorResult->errClass; | |
| 3356 if (pkixErrorClass == PKIX_FATAL_ERROR) { | |
| 3357 goto cleanup; | |
| 3358 } | |
| 3359 if (pVerifyNode != NULL) { | |
| 3360 PKIX_Error *tempResult = | |
| 3361 pkix_VerifyNode_Create(targetCert, 0, | |
| 3362 pkixErrorResult, | |
| 3363 pVerifyNode, | |
| 3364 plContext); | |
| 3365 if (tempResult) { | |
| 3366 PKIX_DECREF(pkixErrorResult); | |
| 3367 pkixErrorResult = tempResult; | |
| 3368 pkixErrorCode = PKIX_VERIFYNODECREATEFAILED; | |
| 3369 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 3370 goto cleanup; | |
| 3371 } | |
| 3372 } | |
| 3373 pkixErrorCode = PKIX_CERTCHECKVALIDITYFAILED; | |
| 3374 goto cleanup; | |
| 3375 } | |
| 3376 } | |
| 3377 | |
| 3378 /* If the EE cert is trusted, force success. We only want to do | |
| 3379 * this if we aren't validating against a policy (like EV). */ | |
| 3380 if (trusted && procParams->initialPolicies == NULL) { | |
| 3381 if (pVerifyNode != NULL) { | |
| 3382 PKIX_Error *tempResult = | |
| 3383 pkix_VerifyNode_Create(targetCert, 0, NULL, | |
| 3384 pVerifyNode, | |
| 3385 plContext); | |
| 3386 if (tempResult) { | |
| 3387 pkixErrorResult = tempResult; | |
| 3388 pkixErrorCode = PKIX_VERIFYNODECREATEFAILED; | |
| 3389 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 3390 goto cleanup; | |
| 3391 } | |
| 3392 } | |
| 3393 PKIX_CHECK(pkix_ValidateResult_Create | |
| 3394 (targetPubKey, NULL /* anchor */, | |
| 3395 NULL /* policyTree */, &valResult, plContext), | |
| 3396 PKIX_VALIDATERESULTCREATEFAILED); | |
| 3397 PKIX_CHECK( | |
| 3398 pkix_BuildResult_Create(valResult, tentativeChain, | |
| 3399 &buildResult, plContext), | |
| 3400 PKIX_BUILDRESULTCREATEFAILED); | |
| 3401 *pBuildResult = buildResult; | |
| 3402 /* Note that *pState is NULL. The only side effect is that | |
| 3403 * the cert chain won't be cached in PKIX_BuildChain, which | |
| 3404 * is fine. */ | |
| 3405 goto cleanup; | |
| 3406 } | |
| 3407 | |
| 3408 PKIX_CHECK(PKIX_ProcessingParams_GetCertStores | |
| 3409 (procParams, &certStores, plContext), | |
| 3410 PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED); | |
| 3411 | |
| 3412 PKIX_CHECK(PKIX_List_GetLength | |
| 3413 (certStores, &numCertStores, plContext), | |
| 3414 PKIX_LISTGETLENGTHFAILED); | |
| 3415 | |
| 3416 /* Reorder CertStores so trusted are at front of the List */ | |
| 3417 if (numCertStores > 1) { | |
| 3418 for (i = numCertStores - 1; i > 0; i--) { | |
| 3419 PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem | |
| 3420 (certStores, | |
| 3421 i, | |
| 3422 (PKIX_PL_Object **)&certStore, | |
| 3423 plContext), | |
| 3424 PKIX_LISTGETITEMFAILED); | |
| 3425 PKIX_CHECK_ONLY_FATAL(PKIX_CertStore_GetTrustCallback | |
| 3426 (certStore, &trustCallback, plContext), | |
| 3427 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); | |
| 3428 | |
| 3429 if (trustCallback != NULL) { | |
| 3430 /* Is a trusted Cert, move CertStore to front */ | |
| 3431 PKIX_CHECK(PKIX_List_DeleteItem | |
| 3432 (certStores, i, plContext), | |
| 3433 PKIX_LISTDELETEITEMFAILED); | |
| 3434 PKIX_CHECK(PKIX_List_InsertItem | |
| 3435 (certStores, | |
| 3436 0, | |
| 3437 (PKIX_PL_Object *)certStore, | |
| 3438 plContext), | |
| 3439 PKIX_LISTINSERTITEMFAILED); | |
| 3440 | |
| 3441 } | |
| 3442 | |
| 3443 PKIX_DECREF(certStore); | |
| 3444 } | |
| 3445 } | |
| 3446 | |
| 3447 PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers | |
| 3448 (procParams, &userCheckers, plContext), | |
| 3449 PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED); | |
| 3450 | |
| 3451 PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker | |
| 3452 (procParams, &revChecker, plContext), | |
| 3453 PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED); | |
| 3454 /* Do not initialize AIA manager if we are not going to fetch | |
| 3455 * cert using aia url. */ | |
| 3456 if (procParams->useAIAForCertFetching) { | |
| 3457 PKIX_CHECK(PKIX_PL_AIAMgr_Create(&aiaMgr, plContext), | |
| 3458 PKIX_AIAMGRCREATEFAILED); | |
| 3459 } | |
| 3460 | |
| 3461 /* | |
| 3462 * We initialize all the fields of buildConstants here, in one place
, | |
| 3463 * just to help keep track and ensure that we got everything. | |
| 3464 */ | |
| 3465 | |
| 3466 buildConstants.numAnchors = numAnchors; | |
| 3467 buildConstants.numCertStores = numCertStores; | |
| 3468 buildConstants.numHintCerts = numHintCerts; | |
| 3469 buildConstants.procParams = procParams; | |
| 3470 buildConstants.testDate = testDate; | |
| 3471 buildConstants.timeLimit = NULL; | |
| 3472 buildConstants.targetCert = targetCert; | |
| 3473 buildConstants.targetPubKey = targetPubKey; | |
| 3474 buildConstants.certStores = certStores; | |
| 3475 buildConstants.anchors = anchors; | |
| 3476 buildConstants.userCheckers = userCheckers; | |
| 3477 buildConstants.hintCerts = hintCerts; | |
| 3478 buildConstants.revChecker = revChecker; | |
| 3479 buildConstants.aiaMgr = aiaMgr; | |
| 3480 buildConstants.trustOnlyUserAnchors = | |
| 3481 procParams->useOnlyTrustAnchors; | |
| 3482 | |
| 3483 PKIX_CHECK(pkix_Build_GetResourceLimits(&buildConstants, plContext), | |
| 3484 PKIX_BUILDGETRESOURCELIMITSFAILED); | |
| 3485 | |
| 3486 PKIX_CHECK(pkix_ForwardBuilderState_Create | |
| 3487 (0, /* PKIX_UInt32 traversedCACerts */ | |
| 3488 buildConstants.maxFanout, | |
| 3489 buildConstants.maxDepth, | |
| 3490 PKIX_FALSE, /* PKIX_Boolean revCheckDelayed */ | |
| 3491 PKIX_TRUE, /* PKIX_Boolean canBeCached */ | |
| 3492 NULL, /* PKIX_Date *validityDate */ | |
| 3493 targetCert, /* PKIX_PL_Cert *prevCert */ | |
| 3494 targetSubjNames, /* PKIX_List *traversedSubjNames */ | |
| 3495 tentativeChain, /* PKIX_List *trustChain */ | |
| 3496 NULL, /* PKIX_ForwardBuilderState *parent */ | |
| 3497 &state, /* PKIX_ForwardBuilderState **pState */ | |
| 3498 plContext), | |
| 3499 PKIX_BUILDSTATECREATEFAILED); | |
| 3500 | |
| 3501 state->buildConstants.numAnchors = buildConstants.numAnchors; | |
| 3502 state->buildConstants.numCertStores = buildConstants.numCertStores; | |
| 3503 state->buildConstants.numHintCerts = buildConstants.numHintCerts; | |
| 3504 state->buildConstants.maxFanout = buildConstants.maxFanout; | |
| 3505 state->buildConstants.maxDepth = buildConstants.maxDepth; | |
| 3506 state->buildConstants.maxTime = buildConstants.maxTime; | |
| 3507 state->buildConstants.procParams = buildConstants.procParams; | |
| 3508 PKIX_INCREF(buildConstants.testDate); | |
| 3509 state->buildConstants.testDate = buildConstants.testDate; | |
| 3510 state->buildConstants.timeLimit = buildConstants.timeLimit; | |
| 3511 PKIX_INCREF(buildConstants.targetCert); | |
| 3512 state->buildConstants.targetCert = buildConstants.targetCert; | |
| 3513 PKIX_INCREF(buildConstants.targetPubKey); | |
| 3514 state->buildConstants.targetPubKey = | |
| 3515 buildConstants.targetPubKey; | |
| 3516 PKIX_INCREF(buildConstants.certStores); | |
| 3517 state->buildConstants.certStores = buildConstants.certStores; | |
| 3518 PKIX_INCREF(buildConstants.anchors); | |
| 3519 state->buildConstants.anchors = buildConstants.anchors; | |
| 3520 PKIX_INCREF(buildConstants.userCheckers); | |
| 3521 state->buildConstants.userCheckers = | |
| 3522 buildConstants.userCheckers; | |
| 3523 PKIX_INCREF(buildConstants.hintCerts); | |
| 3524 state->buildConstants.hintCerts = buildConstants.hintCerts; | |
| 3525 PKIX_INCREF(buildConstants.revChecker); | |
| 3526 state->buildConstants.revChecker = buildConstants.revChecker; | |
| 3527 state->buildConstants.aiaMgr = buildConstants.aiaMgr; | |
| 3528 aiaMgr = NULL; | |
| 3529 state->buildConstants.trustOnlyUserAnchors = | |
| 3530 buildConstants.trustOnlyUserAnchors; | |
| 3531 | |
| 3532 if (buildConstants.maxTime != 0) { | |
| 3533 PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds | |
| 3534 (buildConstants.maxTime, | |
| 3535 &state->buildConstants.timeLimit, | |
| 3536 plContext), | |
| 3537 PKIX_DATECREATECURRENTOFFBYSECONDSFAILED); | |
| 3538 } | |
| 3539 | |
| 3540 if (pVerifyNode != NULL) { | |
| 3541 PKIX_Error *tempResult = | |
| 3542 pkix_VerifyNode_Create(targetCert, 0, NULL, | |
| 3543 &(state->verifyNode), | |
| 3544 plContext); | |
| 3545 if (tempResult) { | |
| 3546 pkixErrorResult = tempResult; | |
| 3547 pkixErrorCode = PKIX_VERIFYNODECREATEFAILED; | |
| 3548 pkixErrorClass = PKIX_FATAL_ERROR; | |
| 3549 goto cleanup; | |
| 3550 } | |
| 3551 } | |
| 3552 | |
| 3553 PKIX_CHECK_ONLY_FATAL( | |
| 3554 pkix_Build_CheckInCache(state, &buildResult, | |
| 3555 &nbioContext, plContext), | |
| 3556 PKIX_UNABLETOBUILDCHAIN); | |
| 3557 if (nbioContext) { | |
| 3558 *pNBIOContext = nbioContext; | |
| 3559 *pState = state; | |
| 3560 state = NULL; | |
| 3561 goto cleanup; | |
| 3562 } | |
| 3563 if (buildResult) { | |
| 3564 *pBuildResult = buildResult; | |
| 3565 if (pVerifyNode != NULL) { | |
| 3566 *pVerifyNode = state->verifyNode; | |
| 3567 state->verifyNode = NULL; | |
| 3568 } | |
| 3569 goto cleanup; | |
| 3570 } | |
| 3571 } | |
| 3572 | |
| 3573 /* If we're resuming after non-blocking I/O we need to get SubjNames */ | |
| 3574 if (targetSubjNames == NULL) { | |
| 3575 PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames | |
| 3576 (state->buildConstants.targetCert, | |
| 3577 &targetSubjNames, | |
| 3578 plContext), | |
| 3579 PKIX_CERTGETALLSUBJECTNAMESFAILED); | |
| 3580 } | |
| 3581 | |
| 3582 state->status = BUILD_INITIAL; | |
| 3583 | |
| 3584 pkixErrorResult = | |
| 3585 pkix_BuildForwardDepthFirstSearch(&nbioContext, state, | |
| 3586 &valResult, plContext); | |
| 3587 | |
| 3588 /* non-null nbioContext means the build would block */ | |
| 3589 if (pkixErrorResult == NULL && nbioContext != NULL) { | |
| 3590 | |
| 3591 *pNBIOContext = nbioContext; | |
| 3592 *pBuildResult = NULL; | |
| 3593 | |
| 3594 /* no valResult means the build has failed */ | |
| 3595 } else { | |
| 3596 if (pVerifyNode != NULL) { | |
| 3597 PKIX_INCREF(state->verifyNode); | |
| 3598 *pVerifyNode = state->verifyNode; | |
| 3599 } | |
| 3600 | |
| 3601 if (valResult == NULL || pkixErrorResult) | |
| 3602 PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN); | |
| 3603 PKIX_CHECK( | |
| 3604 pkix_BuildResult_Create(valResult, state->trustChain, | |
| 3605 &buildResult, plContext), | |
| 3606 PKIX_BUILDRESULTCREATEFAILED); | |
| 3607 *pBuildResult = buildResult; | |
| 3608 } | |
| 3609 | |
| 3610 *pState = state; | |
| 3611 state = NULL; | |
| 3612 | |
| 3613 cleanup: | |
| 3614 | |
| 3615 PKIX_DECREF(targetConstraints); | |
| 3616 PKIX_DECREF(targetParams); | |
| 3617 PKIX_DECREF(anchors); | |
| 3618 PKIX_DECREF(targetSubjNames); | |
| 3619 PKIX_DECREF(targetCert); | |
| 3620 PKIX_DECREF(revChecker); | |
| 3621 PKIX_DECREF(certStores); | |
| 3622 PKIX_DECREF(certStore); | |
| 3623 PKIX_DECREF(userCheckers); | |
| 3624 PKIX_DECREF(hintCerts); | |
| 3625 PKIX_DECREF(firstHintCert); | |
| 3626 PKIX_DECREF(testDate); | |
| 3627 PKIX_DECREF(targetPubKey); | |
| 3628 PKIX_DECREF(tentativeChain); | |
| 3629 PKIX_DECREF(valResult); | |
| 3630 PKIX_DECREF(certList); | |
| 3631 PKIX_DECREF(trustedCert); | |
| 3632 PKIX_DECREF(state); | |
| 3633 PKIX_DECREF(aiaMgr); | |
| 3634 | |
| 3635 PKIX_RETURN(BUILD); | |
| 3636 } | |
| 3637 | |
| 3638 /* | |
| 3639 * FUNCTION: pkix_Build_ResumeBuildChain | |
| 3640 * DESCRIPTION: | |
| 3641 * | |
| 3642 * This function continues the search for a BuildChain, using the parameters | |
| 3643 * provided in "procParams" and the ForwardBuilderState pointed to by "state". | |
| 3644 * | |
| 3645 * If a successful chain is built, this function stores the BuildResult at | |
| 3646 * "pBuildResult". Alternatively, if an operation using non-blocking I/O | |
| 3647 * is in progress and the operation has not been completed, this function | |
| 3648 * stores the FowardBuilderState at "pState" and NULL at "pBuildResult". | |
| 3649 * Finally, if chain building was unsuccessful, this function stores NULL | |
| 3650 * at both "pState" and at "pBuildResult". | |
| 3651 * | |
| 3652 * PARAMETERS: | |
| 3653 * "pNBIOContext" | |
| 3654 * Address at which the NBIOContext is stored indicating whether the | |
| 3655 * validation is complete. Must be non-NULL. | |
| 3656 * "pState" | |
| 3657 * Address at which the ForwardBuilderState is provided for resumption of | |
| 3658 * the chain building attempt; also, the address at which the | |
| 3659 * ForwardBuilderStateis stored, if the chain building is suspended for | |
| 3660 * waiting I/O. Must be non-NULL. | |
| 3661 * "pBuildResult" | |
| 3662 * Address at which the BuildResult is stored, after a successful build. | |
| 3663 * Must be non-NULL. | |
| 3664 * "plContext" | |
| 3665 * Platform-specific context pointer. | |
| 3666 * THREAD SAFETY: | |
| 3667 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
| 3668 * RETURNS: | |
| 3669 * Returns NULL if the function succeeds. | |
| 3670 * Returns a Build Error if the function fails in a non-fatal way | |
| 3671 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
| 3672 */ | |
| 3673 static PKIX_Error * | |
| 3674 pkix_Build_ResumeBuildChain( | |
| 3675 void **pNBIOContext, | |
| 3676 PKIX_ForwardBuilderState *state, | |
| 3677 PKIX_BuildResult **pBuildResult, | |
| 3678 PKIX_VerifyNode **pVerifyNode, | |
| 3679 void *plContext) | |
| 3680 { | |
| 3681 PKIX_ValidateResult *valResult = NULL; | |
| 3682 PKIX_BuildResult *buildResult = NULL; | |
| 3683 void *nbioContext = NULL; | |
| 3684 | |
| 3685 PKIX_ENTER(BUILD, "pkix_Build_ResumeBuildChain"); | |
| 3686 PKIX_NULLCHECK_TWO(state, pBuildResult); | |
| 3687 | |
| 3688 nbioContext = *pNBIOContext; | |
| 3689 *pNBIOContext = NULL; | |
| 3690 | |
| 3691 pkixErrorResult = | |
| 3692 pkix_BuildForwardDepthFirstSearch(&nbioContext, state, | |
| 3693 &valResult, plContext); | |
| 3694 | |
| 3695 /* non-null nbioContext means the build would block */ | |
| 3696 if (pkixErrorResult == NULL && nbioContext != NULL) { | |
| 3697 | |
| 3698 *pNBIOContext = nbioContext; | |
| 3699 *pBuildResult = NULL; | |
| 3700 | |
| 3701 /* no valResult means the build has failed */ | |
| 3702 } else { | |
| 3703 if (pVerifyNode != NULL) { | |
| 3704 PKIX_INCREF(state->verifyNode); | |
| 3705 *pVerifyNode = state->verifyNode; | |
| 3706 } | |
| 3707 | |
| 3708 if (valResult == NULL || pkixErrorResult) | |
| 3709 PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN); | |
| 3710 | |
| 3711 PKIX_CHECK( | |
| 3712 pkix_BuildResult_Create(valResult, state->trustChain, | |
| 3713 &buildResult, plContext), | |
| 3714 PKIX_BUILDRESULTCREATEFAILED); | |
| 3715 *pBuildResult = buildResult; | |
| 3716 } | |
| 3717 | |
| 3718 cleanup: | |
| 3719 | |
| 3720 PKIX_DECREF(valResult); | |
| 3721 | |
| 3722 PKIX_RETURN(BUILD); | |
| 3723 } | |
| 3724 | |
| 3725 /* --Public-Functions--------------------------------------------- */ | |
| 3726 | |
| 3727 /* | |
| 3728 * FUNCTION: PKIX_BuildChain (see comments in pkix.h) | |
| 3729 */ | |
| 3730 PKIX_Error * | |
| 3731 PKIX_BuildChain( | |
| 3732 PKIX_ProcessingParams *procParams, | |
| 3733 void **pNBIOContext, | |
| 3734 void **pState, | |
| 3735 PKIX_BuildResult **pBuildResult, | |
| 3736 PKIX_VerifyNode **pVerifyNode, | |
| 3737 void *plContext) | |
| 3738 { | |
| 3739 PKIX_ForwardBuilderState *state = NULL; | |
| 3740 PKIX_BuildResult *buildResult = NULL; | |
| 3741 void *nbioContext = NULL; | |
| 3742 | |
| 3743 PKIX_ENTER(BUILD, "PKIX_BuildChain"); | |
| 3744 PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult); | |
| 3745 | |
| 3746 nbioContext = *pNBIOContext; | |
| 3747 *pNBIOContext = NULL; | |
| 3748 | |
| 3749 if (*pState == NULL) { | |
| 3750 PKIX_CHECK(pkix_Build_InitiateBuildChain | |
| 3751 (procParams, | |
| 3752 &nbioContext, | |
| 3753 &state, | |
| 3754 &buildResult, | |
| 3755 pVerifyNode, | |
| 3756 plContext), | |
| 3757 PKIX_BUILDINITIATEBUILDCHAINFAILED); | |
| 3758 } else { | |
| 3759 state = (PKIX_ForwardBuilderState *)(*pState); | |
| 3760 *pState = NULL; /* no net change in reference count */ | |
| 3761 if (state->status == BUILD_SHORTCUTPENDING) { | |
| 3762 PKIX_CHECK(pkix_Build_InitiateBuildChain | |
| 3763 (procParams, | |
| 3764 &nbioContext, | |
| 3765 &state, | |
| 3766 &buildResult, | |
| 3767 pVerifyNode, | |
| 3768 plContext), | |
| 3769 PKIX_BUILDINITIATEBUILDCHAINFAILED); | |
| 3770 } else { | |
| 3771 PKIX_CHECK(pkix_Build_ResumeBuildChain | |
| 3772 (&nbioContext, | |
| 3773 state, | |
| 3774 &buildResult, | |
| 3775 pVerifyNode, | |
| 3776 plContext), | |
| 3777 PKIX_BUILDINITIATEBUILDCHAINFAILED); | |
| 3778 } | |
| 3779 } | |
| 3780 | |
| 3781 /* non-null nbioContext means the build would block */ | |
| 3782 if (nbioContext != NULL) { | |
| 3783 | |
| 3784 *pNBIOContext = nbioContext; | |
| 3785 *pState = state; | |
| 3786 state = NULL; | |
| 3787 *pBuildResult = NULL; | |
| 3788 | |
| 3789 /* no buildResult means the build has failed */ | |
| 3790 } else if (buildResult == NULL) { | |
| 3791 PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN); | |
| 3792 } else { | |
| 3793 /* | |
| 3794 * If we made a successful chain by combining the target Cert | |
| 3795 * with one of the Trust Anchors, we may have never created a | |
| 3796 * validityDate. We treat this situation as | |
| 3797 * canBeCached = PKIX_FALSE. | |
| 3798 */ | |
| 3799 if ((state != NULL) && | |
| 3800 ((state->validityDate) != NULL) && | |
| 3801 (state->canBeCached)) { | |
| 3802 PKIX_CHECK(pkix_CacheCertChain_Add | |
| 3803 (state->buildConstants.targetCert, | |
| 3804 state->buildConstants.anchors, | |
| 3805 state->validityDate, | |
| 3806 buildResult, | |
| 3807 plContext), | |
| 3808 PKIX_CACHECERTCHAINADDFAILED); | |
| 3809 } | |
| 3810 | |
| 3811 *pState = NULL; | |
| 3812 *pBuildResult = buildResult; | |
| 3813 buildResult = NULL; | |
| 3814 } | |
| 3815 | |
| 3816 cleanup: | |
| 3817 PKIX_DECREF(buildResult); | |
| 3818 PKIX_DECREF(state); | |
| 3819 | |
| 3820 PKIX_RETURN(BUILD); | |
| 3821 } | |
| OLD | NEW |