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