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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/libpkix/pkix/top/pkix_build.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3744 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +/*
     1.8 + * pkix_build.c
     1.9 + *
    1.10 + * Top level buildChain function
    1.11 + *
    1.12 + */
    1.13 +
    1.14 +/* #define PKIX_BUILDDEBUG 1 */
    1.15 +/* #define PKIX_FORWARDBUILDERSTATEDEBUG 1 */
    1.16 +
    1.17 +#include "pkix_build.h"
    1.18 +
    1.19 +extern PRLogModuleInfo *pkixLog;
    1.20 +
    1.21 +/*
    1.22 + * List of critical extension OIDs associate with what build chain has
    1.23 + * checked. Those OIDs need to be removed from the unresolved critical
    1.24 + * extension OIDs list manually (instead of by checker automatically).
    1.25 + */
    1.26 +static SECOidTag buildCheckedCritExtOIDs[] = {
    1.27 +        PKIX_CERTKEYUSAGE_OID,
    1.28 +        PKIX_CERTSUBJALTNAME_OID,
    1.29 +        PKIX_BASICCONSTRAINTS_OID,
    1.30 +        PKIX_NAMECONSTRAINTS_OID,
    1.31 +        PKIX_EXTENDEDKEYUSAGE_OID,
    1.32 +        PKIX_NSCERTTYPE_OID,
    1.33 +        PKIX_UNKNOWN_OID
    1.34 +};
    1.35 +
    1.36 +/* --Private-ForwardBuilderState-Functions---------------------------------- */
    1.37 +
    1.38 +/*
    1.39 + * FUNCTION: pkix_ForwardBuilderState_Destroy
    1.40 + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
    1.41 + */
    1.42 +static PKIX_Error *
    1.43 +pkix_ForwardBuilderState_Destroy(
    1.44 +        PKIX_PL_Object *object,
    1.45 +        void *plContext)
    1.46 +{
    1.47 +        PKIX_ForwardBuilderState *state = NULL;
    1.48 +
    1.49 +        PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Destroy");
    1.50 +        PKIX_NULLCHECK_ONE(object);
    1.51 +
    1.52 +        PKIX_CHECK(pkix_CheckType
    1.53 +                (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext),
    1.54 +                PKIX_OBJECTNOTFORWARDBUILDERSTATE);
    1.55 +
    1.56 +        state = (PKIX_ForwardBuilderState *)object;
    1.57 +
    1.58 +        state->status = BUILD_INITIAL;
    1.59 +        state->traversedCACerts = 0;
    1.60 +        state->certStoreIndex = 0;
    1.61 +        state->numCerts = 0;
    1.62 +        state->numAias = 0;
    1.63 +        state->certIndex = 0;
    1.64 +        state->aiaIndex = 0;
    1.65 +        state->certCheckedIndex = 0;
    1.66 +        state->checkerIndex = 0;
    1.67 +        state->hintCertIndex = 0;
    1.68 +        state->numFanout = 0;
    1.69 +        state->numDepth = 0;
    1.70 +        state->reasonCode = 0;
    1.71 +        state->canBeCached = PKIX_FALSE;
    1.72 +        state->useOnlyLocal = PKIX_FALSE;
    1.73 +        state->revChecking = PKIX_FALSE;
    1.74 +        state->usingHintCerts = PKIX_FALSE;
    1.75 +        state->certLoopingDetected = PKIX_FALSE;
    1.76 +        PKIX_DECREF(state->validityDate);
    1.77 +        PKIX_DECREF(state->prevCert);
    1.78 +        PKIX_DECREF(state->candidateCert);
    1.79 +        PKIX_DECREF(state->traversedSubjNames);
    1.80 +        PKIX_DECREF(state->trustChain);
    1.81 +        PKIX_DECREF(state->aia);
    1.82 +        PKIX_DECREF(state->candidateCerts);
    1.83 +        PKIX_DECREF(state->reversedCertChain);
    1.84 +        PKIX_DECREF(state->checkedCritExtOIDs);
    1.85 +        PKIX_DECREF(state->checkerChain);
    1.86 +        PKIX_DECREF(state->certSel);
    1.87 +        PKIX_DECREF(state->verifyNode);
    1.88 +        PKIX_DECREF(state->client);
    1.89 +
    1.90 +        /*
    1.91 +         * If we ever add a child link we have to be careful not to have loops
    1.92 +         * in the Destroy process. But with one-way links we should be okay.
    1.93 +         */
    1.94 +        if (state->parentState == NULL) {
    1.95 +                state->buildConstants.numAnchors = 0;
    1.96 +                state->buildConstants.numCertStores = 0;
    1.97 +                state->buildConstants.numHintCerts = 0;
    1.98 +                state->buildConstants.procParams = 0;
    1.99 +                PKIX_DECREF(state->buildConstants.testDate);
   1.100 +                PKIX_DECREF(state->buildConstants.timeLimit);
   1.101 +                PKIX_DECREF(state->buildConstants.targetCert);
   1.102 +                PKIX_DECREF(state->buildConstants.targetPubKey);
   1.103 +                PKIX_DECREF(state->buildConstants.certStores);
   1.104 +                PKIX_DECREF(state->buildConstants.anchors);
   1.105 +                PKIX_DECREF(state->buildConstants.userCheckers);
   1.106 +                PKIX_DECREF(state->buildConstants.hintCerts);
   1.107 +                PKIX_DECREF(state->buildConstants.revChecker);
   1.108 +                PKIX_DECREF(state->buildConstants.aiaMgr);
   1.109 +        } else {
   1.110 +                PKIX_DECREF(state->parentState);
   1.111 +        }
   1.112 +
   1.113 +cleanup:
   1.114 +
   1.115 +        PKIX_RETURN(FORWARDBUILDERSTATE);
   1.116 +}
   1.117 +
   1.118 +/*
   1.119 + * FUNCTION: pkix_ForwardBuilderState_Create
   1.120 + *
   1.121 + * DESCRIPTION:
   1.122 + *  Allocate and initialize a ForwardBuilderState.
   1.123 + *
   1.124 + * PARAMETERS
   1.125 + *  "traversedCACerts"
   1.126 + *      Number of CA certificates traversed.
   1.127 + *  "numFanout"
   1.128 + *      Number of Certs that can be considered at this level (0 = no limit)
   1.129 + *  "numDepth"
   1.130 + *      Number of additional levels that can be searched (0 = no limit)
   1.131 + *  "canBeCached"
   1.132 + *      Boolean value indicating whether all certs on the chain can be cached.
   1.133 + *  "validityDate"
   1.134 + *      Address of Date at which build chain Certs' most restricted validity
   1.135 + *      time is kept. May be NULL.
   1.136 + *  "prevCert"
   1.137 + *      Address of Cert just traversed. Must be non-NULL.
   1.138 + *  "traversedSubjNames"
   1.139 + *      Address of List of GeneralNames that have been traversed.
   1.140 + *      Must be non-NULL.
   1.141 + *  "trustChain"
   1.142 + *      Address of List of certificates traversed. Must be non-NULL.
   1.143 + *  "parentState"
   1.144 + *      Address of previous ForwardBuilderState
   1.145 + *  "pState"
   1.146 + *      Address where ForwardBuilderState will be stored. Must be non-NULL.
   1.147 + *  "plContext"
   1.148 + *      Platform-specific context pointer.
   1.149 + * THREAD SAFETY:
   1.150 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.151 + * RETURNS:
   1.152 + *  Returns NULL if the function succeeds.
   1.153 + *  Returns a Build Error if the function fails in a non-fatal way.
   1.154 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.155 + */
   1.156 +static PKIX_Error *
   1.157 +pkix_ForwardBuilderState_Create(
   1.158 +        PKIX_Int32 traversedCACerts,
   1.159 +        PKIX_UInt32 numFanout,
   1.160 +        PKIX_UInt32 numDepth,
   1.161 +        PKIX_Boolean canBeCached,
   1.162 +        PKIX_PL_Date *validityDate,
   1.163 +        PKIX_PL_Cert *prevCert,
   1.164 +        PKIX_List *traversedSubjNames,
   1.165 +        PKIX_List *trustChain,
   1.166 +        PKIX_ForwardBuilderState *parentState,
   1.167 +        PKIX_ForwardBuilderState **pState,
   1.168 +        void *plContext)
   1.169 +{
   1.170 +        PKIX_ForwardBuilderState *state = NULL;
   1.171 +
   1.172 +        PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Create");
   1.173 +        PKIX_NULLCHECK_FOUR(prevCert, traversedSubjNames, pState, trustChain);
   1.174 +
   1.175 +        PKIX_CHECK(PKIX_PL_Object_Alloc
   1.176 +                (PKIX_FORWARDBUILDERSTATE_TYPE,
   1.177 +                sizeof (PKIX_ForwardBuilderState),
   1.178 +                (PKIX_PL_Object **)&state,
   1.179 +                plContext),
   1.180 +                PKIX_COULDNOTCREATEFORWARDBUILDERSTATEOBJECT);
   1.181 +
   1.182 +        state->status = BUILD_INITIAL;
   1.183 +        state->traversedCACerts = traversedCACerts;
   1.184 +        state->certStoreIndex = 0;
   1.185 +        state->numCerts = 0;
   1.186 +        state->numAias = 0;
   1.187 +        state->certIndex = 0;
   1.188 +        state->aiaIndex = 0;
   1.189 +        state->certCheckedIndex = 0;
   1.190 +        state->checkerIndex = 0;
   1.191 +        state->hintCertIndex = 0;
   1.192 +        state->numFanout = numFanout;
   1.193 +        state->numDepth = numDepth;
   1.194 +        state->reasonCode = 0;
   1.195 +        state->revChecking = numDepth;
   1.196 +        state->canBeCached = canBeCached;
   1.197 +        state->useOnlyLocal = PKIX_TRUE;
   1.198 +        state->revChecking = PKIX_FALSE;
   1.199 +        state->usingHintCerts = PKIX_FALSE;
   1.200 +        state->certLoopingDetected = PKIX_FALSE;
   1.201 +
   1.202 +        PKIX_INCREF(validityDate);
   1.203 +        state->validityDate = validityDate;
   1.204 +
   1.205 +        PKIX_INCREF(prevCert);
   1.206 +        state->prevCert = prevCert;
   1.207 +
   1.208 +        state->candidateCert = NULL;
   1.209 +
   1.210 +        PKIX_INCREF(traversedSubjNames);
   1.211 +        state->traversedSubjNames = traversedSubjNames;
   1.212 +
   1.213 +        PKIX_INCREF(trustChain);
   1.214 +        state->trustChain = trustChain;
   1.215 +
   1.216 +        state->aia = NULL;
   1.217 +        state->candidateCerts = NULL;
   1.218 +        state->reversedCertChain = NULL;
   1.219 +        state->checkedCritExtOIDs = NULL;
   1.220 +        state->checkerChain = NULL;
   1.221 +        state->certSel = NULL;
   1.222 +        state->verifyNode = NULL;
   1.223 +        state->client = NULL;
   1.224 +
   1.225 +        PKIX_INCREF(parentState);
   1.226 +        state->parentState = parentState;
   1.227 +
   1.228 +        if (parentState != NULL) {
   1.229 +                state->buildConstants.numAnchors =
   1.230 +                         parentState->buildConstants.numAnchors;
   1.231 +                state->buildConstants.numCertStores = 
   1.232 +                        parentState->buildConstants.numCertStores; 
   1.233 +                state->buildConstants.numHintCerts = 
   1.234 +                        parentState->buildConstants.numHintCerts; 
   1.235 +                state->buildConstants.maxFanout =
   1.236 +                        parentState->buildConstants.maxFanout;
   1.237 +                state->buildConstants.maxDepth =
   1.238 +                        parentState->buildConstants.maxDepth;
   1.239 +                state->buildConstants.maxTime =
   1.240 +                        parentState->buildConstants.maxTime;
   1.241 +                state->buildConstants.procParams = 
   1.242 +                        parentState->buildConstants.procParams; 
   1.243 +                state->buildConstants.testDate =
   1.244 +                        parentState->buildConstants.testDate;
   1.245 +                state->buildConstants.timeLimit =
   1.246 +                        parentState->buildConstants.timeLimit;
   1.247 +                state->buildConstants.targetCert =
   1.248 +                        parentState->buildConstants.targetCert;
   1.249 +                state->buildConstants.targetPubKey =
   1.250 +                        parentState->buildConstants.targetPubKey;
   1.251 +                state->buildConstants.certStores =
   1.252 +                        parentState->buildConstants.certStores;
   1.253 +                state->buildConstants.anchors =
   1.254 +                        parentState->buildConstants.anchors;
   1.255 +                state->buildConstants.userCheckers =
   1.256 +                        parentState->buildConstants.userCheckers;
   1.257 +                state->buildConstants.hintCerts =
   1.258 +                        parentState->buildConstants.hintCerts;
   1.259 +                state->buildConstants.revChecker =
   1.260 +                        parentState->buildConstants.revChecker;
   1.261 +                state->buildConstants.aiaMgr =
   1.262 +                        parentState->buildConstants.aiaMgr;
   1.263 +                state->buildConstants.trustOnlyUserAnchors =
   1.264 +                        parentState->buildConstants.trustOnlyUserAnchors;
   1.265 +        }
   1.266 +
   1.267 +        *pState = state;
   1.268 +        state = NULL;
   1.269 +cleanup:
   1.270 +        
   1.271 +        PKIX_DECREF(state);
   1.272 +
   1.273 +        PKIX_RETURN(FORWARDBUILDERSTATE);
   1.274 +}
   1.275 +
   1.276 +/*
   1.277 + * FUNCTION: pkix_Build_GetResourceLimits
   1.278 + *
   1.279 + * DESCRIPTION:
   1.280 + *  Retrieve Resource Limits from ProcessingParams and initialize them in
   1.281 + *  BuildConstants.
   1.282 + *
   1.283 + * PARAMETERS
   1.284 + *  "buildConstants"
   1.285 + *      Address of a BuildConstants structure containing objects and values
   1.286 + *      that remain constant throughout the building of a chain. Must be
   1.287 + *      non-NULL.
   1.288 + *  "plContext"
   1.289 + *      Platform-specific context pointer.
   1.290 + * THREAD SAFETY:
   1.291 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.292 + * RETURNS:
   1.293 + *  Returns NULL if the function succeeds.
   1.294 + *  Returns a Build Error if the function fails in a non-fatal way.
   1.295 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.296 + */
   1.297 +static PKIX_Error *
   1.298 +pkix_Build_GetResourceLimits(
   1.299 +        BuildConstants *buildConstants,
   1.300 +        void *plContext)
   1.301 +{
   1.302 +        PKIX_ResourceLimits *resourceLimits = NULL;
   1.303 +
   1.304 +        PKIX_ENTER(BUILD, "pkix_Build_GetResourceLimits");
   1.305 +        PKIX_NULLCHECK_ONE(buildConstants);
   1.306 +
   1.307 +        PKIX_CHECK(PKIX_ProcessingParams_GetResourceLimits
   1.308 +                (buildConstants->procParams, &resourceLimits, plContext),
   1.309 +                PKIX_PROCESSINGPARAMSGETRESOURCELIMITSFAILED);
   1.310 +
   1.311 +        buildConstants->maxFanout = 0;
   1.312 +        buildConstants->maxDepth = 0;
   1.313 +        buildConstants->maxTime = 0;
   1.314 +
   1.315 +        if (resourceLimits) {
   1.316 +
   1.317 +                PKIX_CHECK(PKIX_ResourceLimits_GetMaxFanout
   1.318 +                        (resourceLimits, &buildConstants->maxFanout, plContext),
   1.319 +                        PKIX_RESOURCELIMITSGETMAXFANOUTFAILED);
   1.320 +
   1.321 +                PKIX_CHECK(PKIX_ResourceLimits_GetMaxDepth
   1.322 +                        (resourceLimits, &buildConstants->maxDepth, plContext),
   1.323 +                        PKIX_RESOURCELIMITSGETMAXDEPTHFAILED);
   1.324 +
   1.325 +                PKIX_CHECK(PKIX_ResourceLimits_GetMaxTime
   1.326 +                        (resourceLimits, &buildConstants->maxTime, plContext),
   1.327 +                        PKIX_RESOURCELIMITSGETMAXTIMEFAILED);
   1.328 +        }
   1.329 +
   1.330 +cleanup:
   1.331 +
   1.332 +        PKIX_DECREF(resourceLimits);
   1.333 +
   1.334 +        PKIX_RETURN(BUILD);
   1.335 +}
   1.336 +
   1.337 +/*
   1.338 + * FUNCTION: pkix_ForwardBuilderState_ToString
   1.339 + * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
   1.340 + */
   1.341 +static PKIX_Error *
   1.342 +pkix_ForwardBuilderState_ToString
   1.343 +        (PKIX_PL_Object *object,
   1.344 +        PKIX_PL_String **pString,
   1.345 +        void *plContext)
   1.346 +{
   1.347 +        PKIX_ForwardBuilderState *state = NULL;
   1.348 +        PKIX_PL_String *formatString = NULL;
   1.349 +        PKIX_PL_String *resultString = NULL;
   1.350 +        PKIX_PL_String *buildStatusString = NULL;
   1.351 +        PKIX_PL_String *validityDateString = NULL;
   1.352 +        PKIX_PL_String *prevCertString = NULL;
   1.353 +        PKIX_PL_String *candidateCertString = NULL;
   1.354 +        PKIX_PL_String *traversedSubjNamesString = NULL;
   1.355 +        PKIX_PL_String *trustChainString = NULL;
   1.356 +        PKIX_PL_String *candidateCertsString = NULL;
   1.357 +        PKIX_PL_String *certSelString = NULL;
   1.358 +        PKIX_PL_String *verifyNodeString = NULL;
   1.359 +        PKIX_PL_String *parentStateString = NULL;
   1.360 +        char *asciiFormat = "\n"
   1.361 +                "\t{buildStatus: \t%s\n"
   1.362 +                "\ttraversedCACerts: \t%d\n"
   1.363 +                "\tcertStoreIndex: \t%d\n"
   1.364 +                "\tnumCerts: \t%d\n"
   1.365 +                "\tnumAias: \t%d\n"
   1.366 +                "\tcertIndex: \t%d\n"
   1.367 +                "\taiaIndex: \t%d\n"
   1.368 +                "\tnumFanout: \t%d\n"
   1.369 +                "\tnumDepth:  \t%d\n"
   1.370 +                "\treasonCode:  \t%d\n"
   1.371 +                "\tcanBeCached: \t%d\n"
   1.372 +                "\tuseOnlyLocal: \t%d\n"
   1.373 +                "\trevChecking: \t%d\n"
   1.374 +                "\tvalidityDate: \t%s\n"
   1.375 +                "\tprevCert: \t%s\n"
   1.376 +                "\tcandidateCert: \t%s\n"
   1.377 +                "\ttraversedSubjNames: \t%s\n"
   1.378 +                "\ttrustChain: \t%s\n"
   1.379 +                "\tcandidateCerts: \t%s\n"
   1.380 +                "\tcertSel: \t%s\n"
   1.381 +                "\tverifyNode: \t%s\n"
   1.382 +                "\tparentState: \t%s}\n";
   1.383 +        char *asciiStatus = NULL;
   1.384 +
   1.385 +        PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_ToString");
   1.386 +        PKIX_NULLCHECK_TWO(object, pString);
   1.387 +
   1.388 +        PKIX_CHECK(pkix_CheckType
   1.389 +                (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext),
   1.390 +                PKIX_OBJECTNOTFORWARDBUILDERSTATE);
   1.391 +
   1.392 +        state = (PKIX_ForwardBuilderState *)object;
   1.393 +
   1.394 +        PKIX_CHECK(PKIX_PL_String_Create
   1.395 +                (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
   1.396 +                PKIX_STRINGCREATEFAILED);
   1.397 +
   1.398 +        switch (state->status) {
   1.399 +            case BUILD_SHORTCUTPENDING: asciiStatus = "BUILD_SHORTCUTPENDING";
   1.400 +                                        break;
   1.401 +            case BUILD_INITIAL:         asciiStatus = "BUILD_INITIAL";
   1.402 +                                        break;
   1.403 +            case BUILD_TRYAIA:          asciiStatus = "BUILD_TRYAIA";
   1.404 +                                        break;
   1.405 +            case BUILD_AIAPENDING:      asciiStatus = "BUILD_AIAPENDING";
   1.406 +                                        break;
   1.407 +            case BUILD_COLLECTINGCERTS: asciiStatus = "BUILD_COLLECTINGCERTS";
   1.408 +                                        break;
   1.409 +            case BUILD_GATHERPENDING:   asciiStatus = "BUILD_GATHERPENDING";
   1.410 +                                        break;
   1.411 +            case BUILD_CERTVALIDATING:  asciiStatus = "BUILD_CERTVALIDATING";
   1.412 +                                        break;
   1.413 +            case BUILD_ABANDONNODE:     asciiStatus = "BUILD_ABANDONNODE";
   1.414 +                                        break;
   1.415 +            case BUILD_DATEPREP:        asciiStatus = "BUILD_DATEPREP";
   1.416 +                                        break;
   1.417 +            case BUILD_CHECKTRUSTED:    asciiStatus = "BUILD_CHECKTRUSTED";
   1.418 +                                        break;
   1.419 +            case BUILD_CHECKTRUSTED2:   asciiStatus = "BUILD_CHECKTRUSTED2";
   1.420 +                                        break;
   1.421 +            case BUILD_ADDTOCHAIN:      asciiStatus = "BUILD_ADDTOCHAIN";
   1.422 +                                        break;
   1.423 +            case BUILD_VALCHAIN:        asciiStatus = "BUILD_VALCHAIN";
   1.424 +                                        break;
   1.425 +            case BUILD_VALCHAIN2:       asciiStatus = "BUILD_VALCHAIN2";
   1.426 +                                        break;
   1.427 +            case BUILD_EXTENDCHAIN:     asciiStatus = "BUILD_EXTENDCHAIN";
   1.428 +                                        break;
   1.429 +            case BUILD_GETNEXTCERT:     asciiStatus = "BUILD_GETNEXTCERT";
   1.430 +                                        break;
   1.431 +            default:                    asciiStatus = "INVALID STATUS";
   1.432 +                                        break;
   1.433 +        }
   1.434 +
   1.435 +        PKIX_CHECK(PKIX_PL_String_Create
   1.436 +                (PKIX_ESCASCII, asciiStatus, 0, &buildStatusString, plContext),
   1.437 +                PKIX_STRINGCREATEFAILED);
   1.438 +
   1.439 +        PKIX_TOSTRING
   1.440 +               (state->validityDate, &validityDateString, plContext,
   1.441 +                PKIX_OBJECTTOSTRINGFAILED);
   1.442 +
   1.443 +        PKIX_TOSTRING
   1.444 +               (state->prevCert, &prevCertString, plContext,
   1.445 +                PKIX_OBJECTTOSTRINGFAILED);
   1.446 +
   1.447 +        PKIX_TOSTRING
   1.448 +                (state->candidateCert, &candidateCertString, plContext,
   1.449 +                PKIX_OBJECTTOSTRINGFAILED);
   1.450 +
   1.451 +        PKIX_TOSTRING
   1.452 +                (state->traversedSubjNames,
   1.453 +                &traversedSubjNamesString,
   1.454 +                plContext,
   1.455 +                PKIX_OBJECTTOSTRINGFAILED);
   1.456 +
   1.457 +        PKIX_TOSTRING
   1.458 +                (state->trustChain, &trustChainString, plContext,
   1.459 +                PKIX_OBJECTTOSTRINGFAILED);
   1.460 +
   1.461 +        PKIX_TOSTRING
   1.462 +                (state->candidateCerts, &candidateCertsString, plContext,
   1.463 +                PKIX_OBJECTTOSTRINGFAILED);
   1.464 +
   1.465 +        PKIX_TOSTRING
   1.466 +                (state->certSel, &certSelString, plContext,
   1.467 +                PKIX_OBJECTTOSTRINGFAILED);
   1.468 +
   1.469 +        PKIX_TOSTRING
   1.470 +                (state->verifyNode, &verifyNodeString, plContext,
   1.471 +                PKIX_OBJECTTOSTRINGFAILED);
   1.472 +
   1.473 +        PKIX_TOSTRING
   1.474 +                (state->parentState, &parentStateString, plContext,
   1.475 +                PKIX_OBJECTTOSTRINGFAILED);
   1.476 +
   1.477 +        PKIX_CHECK(PKIX_PL_Sprintf
   1.478 +                (&resultString,
   1.479 +                plContext,
   1.480 +                formatString,
   1.481 +                buildStatusString,
   1.482 +                (PKIX_Int32)state->traversedCACerts,
   1.483 +                (PKIX_UInt32)state->certStoreIndex,
   1.484 +                (PKIX_UInt32)state->numCerts,
   1.485 +                (PKIX_UInt32)state->numAias,
   1.486 +                (PKIX_UInt32)state->certIndex,
   1.487 +                (PKIX_UInt32)state->aiaIndex,
   1.488 +                (PKIX_UInt32)state->numFanout,
   1.489 +                (PKIX_UInt32)state->numDepth,
   1.490 +                (PKIX_UInt32)state->reasonCode,
   1.491 +                state->canBeCached,
   1.492 +                state->useOnlyLocal,
   1.493 +                state->revChecking,
   1.494 +                validityDateString,
   1.495 +                prevCertString,
   1.496 +                candidateCertString,
   1.497 +                traversedSubjNamesString,
   1.498 +                trustChainString,
   1.499 +                candidateCertsString,
   1.500 +                certSelString,
   1.501 +                verifyNodeString,
   1.502 +                parentStateString),
   1.503 +                PKIX_SPRINTFFAILED);
   1.504 +
   1.505 +        *pString = resultString;
   1.506 +
   1.507 +cleanup:
   1.508 +        PKIX_DECREF(formatString);
   1.509 +        PKIX_DECREF(buildStatusString);
   1.510 +        PKIX_DECREF(validityDateString);
   1.511 +        PKIX_DECREF(prevCertString);
   1.512 +        PKIX_DECREF(candidateCertString);
   1.513 +        PKIX_DECREF(traversedSubjNamesString);
   1.514 +        PKIX_DECREF(trustChainString);
   1.515 +        PKIX_DECREF(candidateCertsString);
   1.516 +        PKIX_DECREF(certSelString);
   1.517 +        PKIX_DECREF(verifyNodeString);
   1.518 +        PKIX_DECREF(parentStateString);
   1.519 +
   1.520 +        PKIX_RETURN(FORWARDBUILDERSTATE);
   1.521 +
   1.522 +}
   1.523 +
   1.524 +/*
   1.525 + * FUNCTION: pkix_ForwardBuilderState_RegisterSelf
   1.526 + *
   1.527 + * DESCRIPTION:
   1.528 + *  Registers PKIX_FORWARDBUILDERSTATE_TYPE and its related functions
   1.529 + *  with systemClasses[]
   1.530 + *
   1.531 + * THREAD SAFETY:
   1.532 + *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.533 + *
   1.534 + *  Since this function is only called by PKIX_PL_Initialize, which should
   1.535 + *  only be called once, it is acceptable that this function is not
   1.536 + *  thread-safe.
   1.537 + */
   1.538 +PKIX_Error *
   1.539 +pkix_ForwardBuilderState_RegisterSelf(void *plContext)
   1.540 +{
   1.541 +
   1.542 +        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
   1.543 +        pkix_ClassTable_Entry entry;
   1.544 +
   1.545 +        PKIX_ENTER(FORWARDBUILDERSTATE,
   1.546 +                    "pkix_ForwardBuilderState_RegisterSelf");
   1.547 +
   1.548 +        entry.description = "ForwardBuilderState";
   1.549 +        entry.objCounter = 0;
   1.550 +        entry.typeObjectSize = sizeof(PKIX_ForwardBuilderState);
   1.551 +        entry.destructor = pkix_ForwardBuilderState_Destroy;
   1.552 +        entry.equalsFunction = NULL;
   1.553 +        entry.hashcodeFunction = NULL;
   1.554 +        entry.toStringFunction = pkix_ForwardBuilderState_ToString;
   1.555 +        entry.comparator = NULL;
   1.556 +        entry.duplicateFunction = NULL;
   1.557 +
   1.558 +        systemClasses[PKIX_FORWARDBUILDERSTATE_TYPE] = entry;
   1.559 +
   1.560 +        PKIX_RETURN(FORWARDBUILDERSTATE);
   1.561 +}
   1.562 +
   1.563 +#if PKIX_FORWARDBUILDERSTATEDEBUG
   1.564 +/*
   1.565 + * FUNCTION: pkix_ForwardBuilderState_DumpState
   1.566 + *
   1.567 + * DESCRIPTION:
   1.568 + *  This function invokes the ToString function on the argument pointed to
   1.569 + *  by "state".
   1.570 + * PARAMETERS:
   1.571 + *  "state"
   1.572 + *      The address of the ForwardBuilderState object. Must be non-NULL.
   1.573 + *
   1.574 + * THREAD SAFETY:
   1.575 + *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.576 + */
   1.577 +PKIX_Error *
   1.578 +pkix_ForwardBuilderState_DumpState(
   1.579 +        PKIX_ForwardBuilderState *state,
   1.580 +        void *plContext)
   1.581 +{
   1.582 +        PKIX_PL_String *stateString = NULL;
   1.583 +        char *stateAscii = NULL;
   1.584 +        PKIX_UInt32 length;
   1.585 +
   1.586 +        PKIX_ENTER(FORWARDBUILDERSTATE,"pkix_ForwardBuilderState_DumpState");
   1.587 +        PKIX_NULLCHECK_ONE(state);
   1.588 +
   1.589 +        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1.590 +                ((PKIX_PL_Object *)state, plContext),
   1.591 +                PKIX_OBJECTINVALIDATECACHEFAILED);
   1.592 +
   1.593 +        PKIX_CHECK(PKIX_PL_Object_ToString
   1.594 +                ((PKIX_PL_Object*)state, &stateString, plContext),
   1.595 +                PKIX_OBJECTTOSTRINGFAILED);
   1.596 +
   1.597 +        PKIX_CHECK(PKIX_PL_String_GetEncoded
   1.598 +                    (stateString,
   1.599 +                    PKIX_ESCASCII,
   1.600 +                    (void **)&stateAscii,
   1.601 +                    &length,
   1.602 +                    plContext),
   1.603 +                    PKIX_STRINGGETENCODEDFAILED);
   1.604 +
   1.605 +        PKIX_DEBUG_ARG("In Phase 1: state = %s\n", stateAscii);
   1.606 +
   1.607 +        PKIX_FREE(stateAscii);
   1.608 +        PKIX_DECREF(stateString);
   1.609 +
   1.610 +cleanup:
   1.611 +        PKIX_RETURN(FORWARDBUILDERSTATE);
   1.612 +}
   1.613 +#endif
   1.614 +
   1.615 +/*
   1.616 + * FUNCTION: pkix_ForwardBuilderState_IsIOPending
   1.617 + * DESCRIPTION:
   1.618 + *
   1.619 + *  This function determines whether the state of the ForwardBuilderState
   1.620 + *  pointed to by "state" indicates I/O is in progress, and stores the Boolean
   1.621 + *  result at "pPending".
   1.622 + *
   1.623 + * PARAMETERS:
   1.624 + *  "state"
   1.625 + *      The address of the ForwardBuilderState object. Must be non-NULL.
   1.626 + *  "pPending"
   1.627 + *      The address at which the result is stored. Must be non-NULL.
   1.628 + *  "plContext"
   1.629 + *      Platform-specific context pointer.
   1.630 + * THREAD SAFETY:
   1.631 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.632 + * RETURNS:
   1.633 + *  Returns NULL if the function succeeds.
   1.634 + *  Returns a ForwardBuilderState Error if the function fails in a
   1.635 + *      non-fatal way.
   1.636 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.637 + */
   1.638 +static PKIX_Error*
   1.639 +pkix_ForwardBuilderState_IsIOPending(
   1.640 +        PKIX_ForwardBuilderState *state,
   1.641 +        PKIX_Boolean *pPending,
   1.642 +        void *plContext)
   1.643 +{
   1.644 +        PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_IsIOPending");
   1.645 +        PKIX_NULLCHECK_TWO(state, pPending);
   1.646 +
   1.647 +        if ((state->status == BUILD_GATHERPENDING) ||
   1.648 +            (state->status == BUILD_CHECKTRUSTED2) ||
   1.649 +            (state->status == BUILD_VALCHAIN2) ||
   1.650 +            (state->status == BUILD_AIAPENDING)) {
   1.651 +                *pPending = PKIX_TRUE;
   1.652 +        } else {
   1.653 +                *pPending = PKIX_FALSE;
   1.654 +        }
   1.655 +
   1.656 +        PKIX_RETURN(FORWARDBUILDERSTATE);
   1.657 +}
   1.658 +
   1.659 +/* --Private-BuildChain-Functions------------------------------------------- */
   1.660 +
   1.661 +/*
   1.662 + * FUNCTION: pkix_Build_SortCertComparator
   1.663 + * DESCRIPTION:
   1.664 + *
   1.665 + *  This Function takes two Certificates cast in "obj1" and "obj2",
   1.666 + *  compares their validity NotAfter dates and returns the result at
   1.667 + *  "pResult". The comparison key(s) can be expanded by using other
   1.668 + *  data in the Certificate in the future.
   1.669 + *
   1.670 + * PARAMETERS:
   1.671 + *  "obj1"
   1.672 + *      Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert.
   1.673 + *      Must be non-NULL.
   1.674 + *  "obj2"
   1.675 + *      Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert.
   1.676 + *      Must be non-NULL.
   1.677 + *  "pResult"
   1.678 + *      Address where the comparison result is returned. Must be non-NULL.
   1.679 + *  "plContext"
   1.680 + *      Platform-specific context pointer.
   1.681 + * THREAD SAFETY:
   1.682 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.683 + * RETURNS:
   1.684 + *  Returns NULL if the function succeeds.
   1.685 + *  Returns a Build Error if the function fails in a non-fatal way
   1.686 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.687 + */
   1.688 +static PKIX_Error *
   1.689 +pkix_Build_SortCertComparator(
   1.690 +        PKIX_PL_Object *obj1,
   1.691 +        PKIX_PL_Object *obj2,
   1.692 +        PKIX_Int32 *pResult,
   1.693 +        void *plContext)
   1.694 +{
   1.695 +        PKIX_PL_Date *date1 = NULL;
   1.696 +        PKIX_PL_Date *date2 = NULL;
   1.697 +        PKIX_Boolean result = PKIX_FALSE;
   1.698 +
   1.699 +        PKIX_ENTER(BUILD, "pkix_Build_SortCertComparator");
   1.700 +        PKIX_NULLCHECK_THREE(obj1, obj2, pResult);
   1.701 +
   1.702 +        /*
   1.703 +         * For sorting candidate certificates, we use NotAfter date as the
   1.704 +         * sorted key for now (can be expanded if desired in the future).
   1.705 +         *
   1.706 +         * In PKIX_BuildChain, the List of CertStores was reordered so that
   1.707 +         * trusted CertStores are ahead of untrusted CertStores. That sort, or
   1.708 +         * this one, could be taken out if it is determined that it doesn't help
   1.709 +         * performance, or in some way hinders the solution of choosing desired
   1.710 +         * candidates.
   1.711 +         */
   1.712 +
   1.713 +        PKIX_CHECK(pkix_CheckType(obj1, PKIX_CERT_TYPE, plContext),
   1.714 +                    PKIX_OBJECTNOTCERT);
   1.715 +        PKIX_CHECK(pkix_CheckType(obj2, PKIX_CERT_TYPE, plContext),
   1.716 +                    PKIX_OBJECTNOTCERT);
   1.717 +
   1.718 +        PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
   1.719 +                ((PKIX_PL_Cert *)obj1, &date1, plContext),
   1.720 +                PKIX_CERTGETVALIDITYNOTAFTERFAILED);
   1.721 +
   1.722 +        PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
   1.723 +                ((PKIX_PL_Cert *)obj2, &date2, plContext),
   1.724 +                PKIX_CERTGETVALIDITYNOTAFTERFAILED);
   1.725 +        
   1.726 +        PKIX_CHECK(PKIX_PL_Object_Compare
   1.727 +                ((PKIX_PL_Object *)date1,
   1.728 +                (PKIX_PL_Object *)date2,
   1.729 +                &result,
   1.730 +                plContext),
   1.731 +                PKIX_OBJECTCOMPARATORFAILED);
   1.732 +
   1.733 +        *pResult = !result;
   1.734 +
   1.735 +cleanup:
   1.736 +
   1.737 +        PKIX_DECREF(date1);
   1.738 +        PKIX_DECREF(date2);
   1.739 +
   1.740 +        PKIX_RETURN(BUILD);
   1.741 +}
   1.742 +
   1.743 +/* This local error check macro */
   1.744 +#define ERROR_CHECK(errCode) \
   1.745 +    if (pkixErrorResult) { \
   1.746 +        if (pkixLog) { \
   1.747 +            PR_LOG(pkixLog, PR_LOG_DEBUG, ("====> ERROR_CHECK code %s\n", #errCode)); \
   1.748 +        } \
   1.749 +        pkixTempErrorReceived = PKIX_TRUE; \
   1.750 +        pkixErrorClass = pkixErrorResult->errClass; \
   1.751 +        if (pkixErrorClass == PKIX_FATAL_ERROR) { \
   1.752 +            goto cleanup; \
   1.753 +        } \
   1.754 +        if (verifyNode) { \
   1.755 +            PKIX_DECREF(verifyNode->error); \
   1.756 +            PKIX_INCREF(pkixErrorResult); \
   1.757 +            verifyNode->error = pkixErrorResult; \
   1.758 +        } \
   1.759 +        pkixErrorCode = errCode; \
   1.760 +        goto cleanup; \
   1.761 +    }
   1.762 +
   1.763 +/*
   1.764 + * FUNCTION: pkix_Build_VerifyCertificate
   1.765 + * DESCRIPTION:
   1.766 + *
   1.767 + *  Checks whether the previous Cert stored in the ForwardBuilderState pointed
   1.768 + *  to by "state" successfully chains, including signature verification, to the
   1.769 + *  candidate Cert also stored in "state", using the Boolean value in "trusted"
   1.770 + *  to determine whether "candidateCert" is trusted.
   1.771 + *
   1.772 + *  First it checks whether "candidateCert" has already been traversed by
   1.773 + *  determining whether it is contained in the List of traversed Certs. It then
   1.774 + *  checks the candidate Cert with user checkers, if any, in the List pointed to
   1.775 + *  by "userCheckers". Finally, it runs the signature validation.
   1.776 + *
   1.777 + *  If this Certificate fails verification, and state->verifyNode is non-NULL,
   1.778 + *  this function sets the Error code into the verifyNode.
   1.779 + *
   1.780 + * PARAMETERS:
   1.781 + *  "state"
   1.782 + *      Address of ForwardBuilderState to be used. Must be non-NULL.
   1.783 + *  "userCheckers"
   1.784 + *      Address of a List of CertChainCheckers to be used, if present, to
   1.785 + *      validate the candidateCert.
   1.786 + *  "trusted"
   1.787 + *      Boolean value of trust for the candidate Cert
   1.788 + *  "plContext"
   1.789 + *      Platform-specific context pointer.
   1.790 + * THREAD SAFETY:
   1.791 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.792 + * RETURNS:
   1.793 + *  Returns NULL if the function succeeds.
   1.794 + *  Returns a Build Error if the function fails in a non-fatal way
   1.795 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.796 + */
   1.797 +static PKIX_Error *
   1.798 +pkix_Build_VerifyCertificate(
   1.799 +        PKIX_ForwardBuilderState *state,
   1.800 +        PKIX_List *userCheckers,
   1.801 +        PKIX_Boolean *pTrusted,
   1.802 +        PKIX_VerifyNode *verifyNode,
   1.803 +        void *plContext)
   1.804 +{
   1.805 +        PKIX_UInt32 numUserCheckers = 0;
   1.806 +        PKIX_UInt32 i = 0;
   1.807 +        PKIX_Boolean loopFound = PKIX_FALSE;
   1.808 +        PKIX_Boolean supportForwardChecking = PKIX_FALSE;
   1.809 +        PKIX_Boolean trusted = PKIX_FALSE;
   1.810 +        PKIX_PL_Cert *candidateCert = NULL;
   1.811 +        PKIX_PL_PublicKey *candidatePubKey = NULL;
   1.812 +        PKIX_CertChainChecker *userChecker = NULL;
   1.813 +        PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
   1.814 +        PKIX_PL_TrustAnchorMode trustAnchorMode =
   1.815 +                PKIX_PL_TrustAnchorMode_Ignore;
   1.816 +        void *nbioContext = NULL;
   1.817 +        
   1.818 +        PKIX_ENTER(BUILD, "pkix_Build_VerifyCertificate");
   1.819 +        PKIX_NULLCHECK_TWO(state, pTrusted);
   1.820 +        PKIX_NULLCHECK_THREE
   1.821 +                (state->candidateCerts, state->prevCert, state->trustChain);
   1.822 +
   1.823 +        PKIX_INCREF(state->candidateCert);
   1.824 +        candidateCert = state->candidateCert;
   1.825 +
   1.826 +        if (state->buildConstants.numAnchors) {
   1.827 +            if (state->buildConstants.trustOnlyUserAnchors) {
   1.828 +                trustAnchorMode = PKIX_PL_TrustAnchorMode_Exclusive;
   1.829 +            } else {
   1.830 +                trustAnchorMode = PKIX_PL_TrustAnchorMode_Additive;
   1.831 +            }
   1.832 +        } else {
   1.833 +            trustAnchorMode = PKIX_PL_TrustAnchorMode_Ignore;
   1.834 +        }
   1.835 +
   1.836 +        PKIX_CHECK(
   1.837 +            PKIX_PL_Cert_IsCertTrusted(candidateCert, trustAnchorMode,
   1.838 +                                       &trusted, plContext),
   1.839 +            PKIX_CERTISCERTTRUSTEDFAILED);
   1.840 +
   1.841 +        *pTrusted = trusted;
   1.842 +
   1.843 +        /* check for loops */
   1.844 +        PKIX_CHECK(pkix_List_Contains
   1.845 +                (state->trustChain,
   1.846 +                (PKIX_PL_Object *)candidateCert,
   1.847 +                &loopFound,
   1.848 +                plContext),
   1.849 +                PKIX_LISTCONTAINSFAILED);
   1.850 +
   1.851 +        if (loopFound) {
   1.852 +                if (verifyNode != NULL) {
   1.853 +                        PKIX_Error *verifyError = NULL;
   1.854 +                        PKIX_ERROR_CREATE
   1.855 +                                (BUILD,
   1.856 +                                PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED,
   1.857 +                                verifyError);
   1.858 +                        PKIX_DECREF(verifyNode->error);
   1.859 +                        verifyNode->error = verifyError;
   1.860 +                }
   1.861 +                /* Even if error logged, still need to abort
   1.862 +                 * if cert is not trusted. */
   1.863 +                if (!trusted) {
   1.864 +                        PKIX_ERROR(PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED);
   1.865 +                }
   1.866 +                state->certLoopingDetected = PKIX_TRUE;
   1.867 +        }
   1.868 +
   1.869 +        if (userCheckers != NULL) {
   1.870 +
   1.871 +                PKIX_CHECK(PKIX_List_GetLength
   1.872 +                    (userCheckers, &numUserCheckers, plContext),
   1.873 +                    PKIX_LISTGETLENGTHFAILED);
   1.874 +
   1.875 +                for (i = 0; i < numUserCheckers; i++) {
   1.876 +
   1.877 +                    PKIX_CHECK(PKIX_List_GetItem
   1.878 +                        (userCheckers,
   1.879 +                        i,
   1.880 +                        (PKIX_PL_Object **) &userChecker,
   1.881 +                        plContext),
   1.882 +                        PKIX_LISTGETITEMFAILED);
   1.883 +
   1.884 +                    PKIX_CHECK
   1.885 +                        (PKIX_CertChainChecker_IsForwardCheckingSupported
   1.886 +                        (userChecker, &supportForwardChecking, plContext),
   1.887 +                        PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
   1.888 +
   1.889 +                    if (supportForwardChecking == PKIX_TRUE) {
   1.890 +
   1.891 +                        PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
   1.892 +                            (userChecker, &checkerCheck, plContext),
   1.893 +                            PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);
   1.894 +
   1.895 +                        pkixErrorResult =
   1.896 +                            checkerCheck(userChecker, candidateCert, NULL,
   1.897 +                                         &nbioContext, plContext);
   1.898 +
   1.899 +                        ERROR_CHECK(PKIX_USERCHECKERCHECKFAILED);
   1.900 +                    }
   1.901 +
   1.902 +                    PKIX_DECREF(userChecker);
   1.903 +                }
   1.904 +        }
   1.905 +
   1.906 +        /* Check that public key of the trusted dsa cert has
   1.907 +         * dsa parameters */
   1.908 +        if (trusted) {
   1.909 +            PKIX_Boolean paramsNeeded = PKIX_FALSE;
   1.910 +            PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
   1.911 +                       (candidateCert, &candidatePubKey, plContext),
   1.912 +                       PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
   1.913 +            PKIX_CHECK(PKIX_PL_PublicKey_NeedsDSAParameters
   1.914 +                       (candidatePubKey, &paramsNeeded, plContext),
   1.915 +                       PKIX_PUBLICKEYNEEDSDSAPARAMETERSFAILED);
   1.916 +            if (paramsNeeded) {
   1.917 +                PKIX_ERROR(PKIX_MISSINGDSAPARAMETERS);
   1.918 +            }
   1.919 +        }
   1.920 +
   1.921 +cleanup:
   1.922 +        PKIX_DECREF(candidateCert);
   1.923 +        PKIX_DECREF(candidatePubKey);
   1.924 +        PKIX_DECREF(userChecker);
   1.925 +
   1.926 +        PKIX_RETURN(BUILD);
   1.927 +}
   1.928 +
   1.929 +/*
   1.930 + * FUNCTION: pkix_Build_ValidationCheckers
   1.931 + * DESCRIPTION:
   1.932 + *
   1.933 + *  Creates a List of Objects to be used in determining whether the List of
   1.934 + *  Certs pointed to by "certChain" successfully validates using the
   1.935 + *  ForwardBuilderState pointed to by "state", and the TrustAnchor pointed to by
   1.936 + *  "anchor". These objects are a reversed Cert Chain, consisting of the certs
   1.937 + *  in "certChain" in reversed order, suitable for presenting to the
   1.938 + *  CertChainCheckers; a List of critical extension OIDS that have already been
   1.939 + *  processed in forward building; a List of CertChainCheckers to be called, and
   1.940 + *  a List of RevocationCheckers to be called. These results are stored in
   1.941 + *  fields of "state".
   1.942 + *
   1.943 + * PARAMETERS:
   1.944 + *  "state"
   1.945 + *      Address of ForwardBuilderState to be used. Must be non-NULL.
   1.946 + *  "certChain"
   1.947 + *      Address of List of Certs to be validated. Must be non-NULL.
   1.948 + *  "anchor"
   1.949 + *      Address of TrustAnchor to be used. Must be non-NULL.
   1.950 + *  "addEkuChecker"
   1.951 + *      Boolean flags that tells to add eku checker to the list
   1.952 + *      of checkers. Only needs to be done for existing chain revalidation.
   1.953 + *  "plContext"
   1.954 + *      Platform-specific context pointer.
   1.955 + * THREAD SAFETY:
   1.956 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.957 + * RETURNS:
   1.958 + *  Returns NULL if the function succeeds.
   1.959 + *  Returns a Build Error if the function fails in a non-fatal way
   1.960 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.961 + */
   1.962 +static PKIX_Error *
   1.963 +pkix_Build_ValidationCheckers(
   1.964 +        PKIX_ForwardBuilderState *state,
   1.965 +        PKIX_List *certChain,
   1.966 +        PKIX_TrustAnchor *anchor,
   1.967 +        PKIX_Boolean chainRevalidationStage,
   1.968 +        void *plContext)
   1.969 +{
   1.970 +        PKIX_List *checkers = NULL;
   1.971 +        PKIX_List *initialPolicies = NULL;
   1.972 +        PKIX_List *reversedCertChain = NULL;
   1.973 +        PKIX_List *buildCheckedCritExtOIDsList = NULL;
   1.974 +        PKIX_ProcessingParams *procParams = NULL;
   1.975 +        PKIX_PL_Cert *trustedCert = NULL;
   1.976 +        PKIX_PL_PublicKey *trustedPubKey = NULL;
   1.977 +        PKIX_PL_CertNameConstraints *trustedNC = NULL;
   1.978 +        PKIX_CertChainChecker *sigChecker = NULL;
   1.979 +        PKIX_CertChainChecker *policyChecker = NULL;
   1.980 +        PKIX_CertChainChecker *userChecker = NULL;
   1.981 +        PKIX_CertChainChecker *nameConstraintsChecker = NULL;
   1.982 +        PKIX_CertChainChecker *checker = NULL;
   1.983 +        PKIX_CertSelector *certSelector = NULL;
   1.984 +        PKIX_List *userCheckerExtOIDs = NULL;
   1.985 +        PKIX_PL_OID *oid = NULL;
   1.986 +        PKIX_Boolean supportForwardChecking = PKIX_FALSE;
   1.987 +        PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
   1.988 +        PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
   1.989 +        PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
   1.990 +        PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
   1.991 +        PKIX_UInt32 numChainCerts;
   1.992 +        PKIX_UInt32 numCertCheckers;
   1.993 +        PKIX_UInt32 i;
   1.994 +
   1.995 +        PKIX_ENTER(BUILD, "pkix_Build_ValidationCheckers");
   1.996 +        PKIX_NULLCHECK_THREE(state, certChain, anchor);
   1.997 +
   1.998 +        PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
   1.999 +                PKIX_LISTCREATEFAILED);
  1.1000 +
  1.1001 +        PKIX_CHECK(PKIX_List_ReverseList
  1.1002 +                (certChain, &reversedCertChain, plContext),
  1.1003 +                PKIX_LISTREVERSELISTFAILED);
  1.1004 +
  1.1005 +        PKIX_CHECK(PKIX_List_GetLength
  1.1006 +                (reversedCertChain, &numChainCerts, plContext),
  1.1007 +                PKIX_LISTGETLENGTHFAILED);
  1.1008 +
  1.1009 +        procParams = state->buildConstants.procParams;
  1.1010 +
  1.1011 +        /* Do need to add a number of checker to revalidate
  1.1012 +         * a built chain. KU, EKU, CertType and Validity Date
  1.1013 +         * get checked by certificate selector during chain
  1.1014 +         * construction, but needed to be checked for chain from
  1.1015 +         * the cache.*/
  1.1016 +        if (chainRevalidationStage) {
  1.1017 +            PKIX_CHECK(pkix_ExpirationChecker_Initialize
  1.1018 +                       (state->buildConstants.testDate, &checker, plContext),
  1.1019 +                       PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
  1.1020 +            PKIX_CHECK(PKIX_List_AppendItem
  1.1021 +                       (checkers, (PKIX_PL_Object *)checker, plContext),
  1.1022 +                       PKIX_LISTAPPENDITEMFAILED);
  1.1023 +            PKIX_DECREF(checker);
  1.1024 +            
  1.1025 +            PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
  1.1026 +                       (procParams, &certSelector, plContext),
  1.1027 +                    PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
  1.1028 +
  1.1029 +            PKIX_CHECK(pkix_TargetCertChecker_Initialize
  1.1030 +                       (certSelector, numChainCerts, &checker, plContext),
  1.1031 +                       PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
  1.1032 +            PKIX_CHECK(PKIX_List_AppendItem
  1.1033 +                       (checkers, (PKIX_PL_Object *)checker, plContext),
  1.1034 +                       PKIX_LISTAPPENDITEMFAILED);
  1.1035 +            PKIX_DECREF(checker);
  1.1036 +        }
  1.1037 +
  1.1038 +        PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
  1.1039 +                (procParams, &initialPolicies, plContext),
  1.1040 +                PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);
  1.1041 +
  1.1042 +        PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
  1.1043 +                (procParams, &policyQualifiersRejected, plContext),
  1.1044 +                PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);
  1.1045 +
  1.1046 +        PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
  1.1047 +                (procParams, &initialPolicyMappingInhibit, plContext),
  1.1048 +                PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);
  1.1049 +
  1.1050 +        PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
  1.1051 +                (procParams, &initialAnyPolicyInhibit, plContext),
  1.1052 +                PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);
  1.1053 +
  1.1054 +        PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
  1.1055 +                (procParams, &initialExplicitPolicy, plContext),
  1.1056 +                PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);
  1.1057 +
  1.1058 +        PKIX_CHECK(pkix_PolicyChecker_Initialize
  1.1059 +                (initialPolicies,
  1.1060 +                policyQualifiersRejected,
  1.1061 +                initialPolicyMappingInhibit,
  1.1062 +                initialExplicitPolicy,
  1.1063 +                initialAnyPolicyInhibit,
  1.1064 +                numChainCerts,
  1.1065 +                &policyChecker,
  1.1066 +                plContext),
  1.1067 +                PKIX_POLICYCHECKERINITIALIZEFAILED);
  1.1068 +
  1.1069 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1070 +                (checkers, (PKIX_PL_Object *)policyChecker, plContext),
  1.1071 +                PKIX_LISTAPPENDITEMFAILED);
  1.1072 +
  1.1073 +        /*
  1.1074 +         * Create an OID list that contains critical extensions processed
  1.1075 +         * by BuildChain. These are specified in a static const array.
  1.1076 +         */
  1.1077 +        PKIX_CHECK(PKIX_List_Create(&buildCheckedCritExtOIDsList, plContext),
  1.1078 +                PKIX_LISTCREATEFAILED);
  1.1079 +
  1.1080 +        for (i = 0; buildCheckedCritExtOIDs[i] != PKIX_UNKNOWN_OID; i++) {
  1.1081 +                PKIX_CHECK(PKIX_PL_OID_Create
  1.1082 +                        (buildCheckedCritExtOIDs[i], &oid, plContext),
  1.1083 +                        PKIX_OIDCREATEFAILED);
  1.1084 +
  1.1085 +                PKIX_CHECK(PKIX_List_AppendItem
  1.1086 +                        (buildCheckedCritExtOIDsList,
  1.1087 +                        (PKIX_PL_Object *) oid,
  1.1088 +                        plContext),
  1.1089 +                        PKIX_LISTAPPENDITEMFAILED);
  1.1090 +
  1.1091 +                PKIX_DECREF(oid);
  1.1092 +        }
  1.1093 +
  1.1094 +        if (state->buildConstants.userCheckers != NULL) {
  1.1095 +
  1.1096 +                PKIX_CHECK(PKIX_List_GetLength
  1.1097 +                        (state->buildConstants.userCheckers,
  1.1098 +                        &numCertCheckers,
  1.1099 +                        plContext),
  1.1100 +                        PKIX_LISTGETLENGTHFAILED);
  1.1101 +
  1.1102 +                for (i = 0; i < numCertCheckers; i++) {
  1.1103 +
  1.1104 +                        PKIX_CHECK(PKIX_List_GetItem
  1.1105 +                            (state->buildConstants.userCheckers,
  1.1106 +                            i,
  1.1107 +                            (PKIX_PL_Object **) &userChecker,
  1.1108 +                            plContext),
  1.1109 +                            PKIX_LISTGETITEMFAILED);
  1.1110 +
  1.1111 +                        PKIX_CHECK
  1.1112 +                            (PKIX_CertChainChecker_IsForwardCheckingSupported
  1.1113 +                            (userChecker, &supportForwardChecking, plContext),
  1.1114 +                            PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
  1.1115 +
  1.1116 +                        /*
  1.1117 +                         * If this userChecker supports forwardChecking then it
  1.1118 +                         * should have been checked during build chain. Skip
  1.1119 +                         * checking but need to add checker's extension OIDs
  1.1120 +                         * to buildCheckedCritExtOIDsList.
  1.1121 +                         */
  1.1122 +                        if (supportForwardChecking == PKIX_TRUE) {
  1.1123 +
  1.1124 +                          PKIX_CHECK
  1.1125 +                            (PKIX_CertChainChecker_GetSupportedExtensions
  1.1126 +                            (userChecker, &userCheckerExtOIDs, plContext),
  1.1127 +                            PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
  1.1128 +
  1.1129 +                          if (userCheckerExtOIDs != NULL) {
  1.1130 +                            PKIX_CHECK(pkix_List_AppendList
  1.1131 +                                (buildCheckedCritExtOIDsList,
  1.1132 +                                userCheckerExtOIDs,
  1.1133 +                                plContext),
  1.1134 +                                PKIX_LISTAPPENDLISTFAILED);
  1.1135 +                          }
  1.1136 +
  1.1137 +                        } else {
  1.1138 +                            PKIX_CHECK(PKIX_List_AppendItem
  1.1139 +                                (checkers,
  1.1140 +                                (PKIX_PL_Object *)userChecker,
  1.1141 +                                plContext),
  1.1142 +                                PKIX_LISTAPPENDITEMFAILED);
  1.1143 +                        }
  1.1144 +
  1.1145 +                        PKIX_DECREF(userCheckerExtOIDs);
  1.1146 +                        PKIX_DECREF(userChecker);
  1.1147 +                }
  1.1148 +        }
  1.1149 +
  1.1150 +        /* Enabling post chain building signature check on the certs. */
  1.1151 +        PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
  1.1152 +                   (anchor, &trustedCert, plContext),
  1.1153 +                   PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  1.1154 +        
  1.1155 +        PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
  1.1156 +                   (trustedCert, &trustedPubKey, plContext),
  1.1157 +                   PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
  1.1158 +        
  1.1159 +        PKIX_CHECK(pkix_SignatureChecker_Initialize
  1.1160 +                   (trustedPubKey,
  1.1161 +                    numChainCerts,
  1.1162 +                    &sigChecker,
  1.1163 +                    plContext),
  1.1164 +                   PKIX_SIGNATURECHECKERINITIALIZEFAILED);
  1.1165 +        
  1.1166 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1167 +                   (checkers,
  1.1168 +                    (PKIX_PL_Object *)sigChecker,
  1.1169 +                    plContext),
  1.1170 +                   PKIX_LISTAPPENDITEMFAILED);
  1.1171 +
  1.1172 +        /* Enabling post chain building name constraints check on the certs. */
  1.1173 +        PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
  1.1174 +                  (anchor, &trustedNC, plContext),
  1.1175 +                  PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);
  1.1176 +
  1.1177 +        PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
  1.1178 +                  (trustedNC, numChainCerts, &nameConstraintsChecker,
  1.1179 +                   plContext),
  1.1180 +                  PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);
  1.1181 +
  1.1182 +        PKIX_CHECK(PKIX_List_AppendItem
  1.1183 +                  (checkers,
  1.1184 +                   (PKIX_PL_Object *)nameConstraintsChecker,
  1.1185 +                   plContext),
  1.1186 +                  PKIX_LISTAPPENDITEMFAILED);
  1.1187 +
  1.1188 +
  1.1189 +        PKIX_DECREF(state->reversedCertChain);
  1.1190 +        PKIX_INCREF(reversedCertChain);
  1.1191 +        state->reversedCertChain = reversedCertChain;
  1.1192 +        PKIX_DECREF(state->checkedCritExtOIDs);
  1.1193 +        PKIX_INCREF(buildCheckedCritExtOIDsList);
  1.1194 +        state->checkedCritExtOIDs = buildCheckedCritExtOIDsList;
  1.1195 +        PKIX_DECREF(state->checkerChain);
  1.1196 +        state->checkerChain = checkers;
  1.1197 +        checkers = NULL;
  1.1198 +        state->certCheckedIndex = 0;
  1.1199 +        state->checkerIndex = 0;
  1.1200 +        state->revChecking = PKIX_FALSE;
  1.1201 +
  1.1202 +
  1.1203 +cleanup:
  1.1204 +
  1.1205 +        PKIX_DECREF(oid);
  1.1206 +        PKIX_DECREF(reversedCertChain);
  1.1207 +        PKIX_DECREF(buildCheckedCritExtOIDsList);
  1.1208 +        PKIX_DECREF(checker);
  1.1209 +        PKIX_DECREF(checkers);
  1.1210 +        PKIX_DECREF(initialPolicies);
  1.1211 +        PKIX_DECREF(trustedCert);
  1.1212 +        PKIX_DECREF(trustedPubKey);
  1.1213 +        PKIX_DECREF(certSelector);
  1.1214 +        PKIX_DECREF(sigChecker);
  1.1215 +        PKIX_DECREF(trustedNC);
  1.1216 +        PKIX_DECREF(nameConstraintsChecker);
  1.1217 +        PKIX_DECREF(policyChecker);
  1.1218 +        PKIX_DECREF(userChecker);
  1.1219 +        PKIX_DECREF(userCheckerExtOIDs);
  1.1220 +
  1.1221 +        PKIX_RETURN(BUILD);
  1.1222 +}
  1.1223 +
  1.1224 +/*
  1.1225 + * FUNCTION: pkix_Build_ValidateEntireChain
  1.1226 + * DESCRIPTION:
  1.1227 + *
  1.1228 + *  Checks whether the current List of Certs successfully validates using the 
  1.1229 + *  TrustAnchor pointed to by "anchor" and other parameters contained, as was
  1.1230 + *  the Cert List, in "state".
  1.1231 + *
  1.1232 + *  If a checker using non-blocking I/O returns with a non-NULL non-blocking I/O
  1.1233 + *  context (NBIOContext), an indication that I/O is in progress and the
  1.1234 + *  checking has not been completed, this function stores that context at
  1.1235 + *  "pNBIOContext". Otherwise, it stores NULL at "pNBIOContext".
  1.1236 + *
  1.1237 + *  If not awaiting I/O and if successful, a ValidateResult is created
  1.1238 + *  containing the Public Key of the target certificate (including DSA parameter
  1.1239 + *  inheritance, if any) and the PolicyNode representing the policy tree output
  1.1240 + *  by the validation algorithm.  If not successful, an Error pointer is
  1.1241 + *  returned.
  1.1242 + *
  1.1243 + * PARAMETERS:
  1.1244 + *  "state"
  1.1245 + *      Address of ForwardBuilderState to be used. Must be non-NULL.
  1.1246 + *  "anchor"
  1.1247 + *      Address of TrustAnchor to be used. Must be non-NULL.
  1.1248 + *  "pNBIOContext"
  1.1249 + *      Address at which the NBIOContext is stored indicating whether the
  1.1250 + *      validation is complete. Must be non-NULL.
  1.1251 + *  "pValResult"
  1.1252 + *      Address at which the ValidateResult is stored. Must be non-NULL.
  1.1253 + *  "plContext"
  1.1254 + *      Platform-specific context pointer.
  1.1255 + * THREAD SAFETY:
  1.1256 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1257 + * RETURNS:
  1.1258 + *  Returns NULL if the function succeeds.
  1.1259 + *  Returns a Build Error if the function fails in a non-fatal way
  1.1260 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.1261 + */
  1.1262 +static PKIX_Error *
  1.1263 +pkix_Build_ValidateEntireChain(
  1.1264 +        PKIX_ForwardBuilderState *state,
  1.1265 +        PKIX_TrustAnchor *anchor,
  1.1266 +        void **pNBIOContext,
  1.1267 +        PKIX_ValidateResult **pValResult,
  1.1268 +        PKIX_VerifyNode *verifyNode,
  1.1269 +        void *plContext)
  1.1270 +{
  1.1271 +        PKIX_UInt32 numChainCerts = 0;
  1.1272 +        PKIX_PL_PublicKey *subjPubKey = NULL;
  1.1273 +        PKIX_PolicyNode *policyTree = NULL;
  1.1274 +        PKIX_ValidateResult *valResult = NULL;
  1.1275 +        void *nbioContext = NULL;
  1.1276 +
  1.1277 +        PKIX_ENTER(BUILD, "pkix_Build_ValidateEntireChain");
  1.1278 +        PKIX_NULLCHECK_FOUR(state, anchor, pNBIOContext, pValResult);
  1.1279 +
  1.1280 +        *pNBIOContext = NULL; /* prepare for case of error exit */
  1.1281 +
  1.1282 +        PKIX_CHECK(PKIX_List_GetLength
  1.1283 +                (state->reversedCertChain, &numChainCerts, plContext),
  1.1284 +                PKIX_LISTGETLENGTHFAILED);
  1.1285 +
  1.1286 +        pkixErrorResult =
  1.1287 +            pkix_CheckChain(state->reversedCertChain, numChainCerts, anchor,
  1.1288 +                            state->checkerChain,
  1.1289 +                            state->buildConstants.revChecker,
  1.1290 +                            state->checkedCritExtOIDs,
  1.1291 +                            state->buildConstants.procParams,
  1.1292 +                            &state->certCheckedIndex, &state->checkerIndex,
  1.1293 +                            &state->revChecking, &state->reasonCode,
  1.1294 +                            &nbioContext, &subjPubKey, &policyTree, NULL,
  1.1295 +                            plContext);
  1.1296 +
  1.1297 +        if (nbioContext != NULL) {
  1.1298 +                *pNBIOContext = nbioContext;
  1.1299 +                goto cleanup;
  1.1300 +        }
  1.1301 +
  1.1302 +        ERROR_CHECK(PKIX_CHECKCHAINFAILED);
  1.1303 +
  1.1304 +        /* XXX Remove this assertion after 2014-12-31. See bug 946984. */
  1.1305 +        PORT_Assert(state->reasonCode == 0);
  1.1306 +
  1.1307 +        PKIX_CHECK(pkix_ValidateResult_Create
  1.1308 +                (subjPubKey, anchor, policyTree, &valResult, plContext),
  1.1309 +                PKIX_VALIDATERESULTCREATEFAILED);
  1.1310 +
  1.1311 +        *pValResult = valResult;
  1.1312 +        valResult = NULL;
  1.1313 +
  1.1314 +cleanup:
  1.1315 +        PKIX_DECREF(subjPubKey);
  1.1316 +        PKIX_DECREF(policyTree);
  1.1317 +        PKIX_DECREF(valResult);
  1.1318 +
  1.1319 +        PKIX_RETURN(BUILD);
  1.1320 +}
  1.1321 +
  1.1322 +/*
  1.1323 + * FUNCTION: pkix_Build_SortCandidateCerts
  1.1324 + * DESCRIPTION:
  1.1325 + *
  1.1326 + *  This function sorts a List of candidate Certs pointed to by "candidates"
  1.1327 + *  using an algorithm that places Certs most likely to produce a successful
  1.1328 + *  chain at the front of the list, storing the resulting sorted List at
  1.1329 + *  "pSortedCandidates".
  1.1330 + *
  1.1331 + *  At present the only sort criterion is that trusted Certs go ahead of
  1.1332 + *  untrusted Certs.
  1.1333 + *
  1.1334 + * PARAMETERS:
  1.1335 + *  "candidates"
  1.1336 + *      Address of List of Candidate Certs to be sorted. Must be non-NULL.
  1.1337 + *  "pSortedCandidates"
  1.1338 + *      Address at which sorted List is stored. Must be non-NULL.
  1.1339 + *  "plContext"
  1.1340 + *      Platform-specific context pointer.
  1.1341 + * THREAD SAFETY:
  1.1342 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1343 + * RETURNS:
  1.1344 + *  Returns NULL if the function succeeds.
  1.1345 + *  Returns a Build Error if the function fails in a non-fatal way
  1.1346 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.1347 + */
  1.1348 +static PKIX_Error *
  1.1349 +pkix_Build_SortCandidateCerts(
  1.1350 +        PKIX_List *candidates,
  1.1351 +        PKIX_List **pSortedCandidates,
  1.1352 +        void *plContext)
  1.1353 +{
  1.1354 +        PKIX_List *sortedList = NULL;
  1.1355 +
  1.1356 +        PKIX_ENTER(BUILD, "pkix_Build_SortCandidateCerts");
  1.1357 +        PKIX_NULLCHECK_TWO(candidates, pSortedCandidates);
  1.1358 +
  1.1359 +        /*
  1.1360 +         * Both bubble and quick sort algorithms are available.
  1.1361 +         * For a list of fewer than around 100 items, the bubble sort is more
  1.1362 +         * efficient. (This number was determined by experimenting with both
  1.1363 +         * algorithms on a Java List.)
  1.1364 +         * If the candidate list is very small, using the sort can drag down
  1.1365 +         * the performance a little bit.
  1.1366 +         */
  1.1367 +
  1.1368 +        PKIX_CHECK(pkix_List_BubbleSort
  1.1369 +                (candidates,
  1.1370 +                pkix_Build_SortCertComparator,
  1.1371 +                &sortedList,
  1.1372 +                plContext),
  1.1373 +                PKIX_LISTBUBBLESORTFAILED);
  1.1374 +
  1.1375 +        *pSortedCandidates = sortedList;
  1.1376 +
  1.1377 +cleanup:
  1.1378 +
  1.1379 +        PKIX_RETURN(BUILD);
  1.1380 +}
  1.1381 +
  1.1382 +/*
  1.1383 + * FUNCTION: pkix_Build_BuildSelectorAndParams
  1.1384 + * DESCRIPTION:
  1.1385 + *
  1.1386 + *  This function creates a CertSelector, initialized with an appropriate
  1.1387 + *  ComCertSelParams, using the variables provided in the ForwardBuilderState
  1.1388 + *  pointed to by "state". The CertSelector created is stored in the certsel
  1.1389 + *  element of "state".
  1.1390 + *
  1.1391 + * PARAMETERS:
  1.1392 + *  "state"
  1.1393 + *      Address of ForwardBuilderState to be used. Must be non-NULL.
  1.1394 + *  "plContext"
  1.1395 + *      Platform-specific context pointer.
  1.1396 + * THREAD SAFETY:
  1.1397 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1398 + * RETURNS:
  1.1399 + *  Returns NULL if the function succeeds.
  1.1400 + *  Returns a Build Error if the function fails in a non-fatal way
  1.1401 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.1402 + */
  1.1403 +static PKIX_Error *
  1.1404 +pkix_Build_BuildSelectorAndParams(
  1.1405 +        PKIX_ForwardBuilderState *state,
  1.1406 +        void *plContext)
  1.1407 +{
  1.1408 +        PKIX_ComCertSelParams *certSelParams = NULL;
  1.1409 +        PKIX_CertSelector *certSel = NULL;
  1.1410 +        PKIX_PL_X500Name *currentIssuer = NULL;
  1.1411 +        PKIX_PL_ByteArray *authKeyId = NULL;
  1.1412 +        PKIX_PL_Date *testDate = NULL;
  1.1413 +        PKIX_CertSelector *callerCertSelector = NULL;
  1.1414 +        PKIX_ComCertSelParams *callerComCertSelParams = NULL;
  1.1415 +        PKIX_UInt32 reqKu = 0;
  1.1416 +        PKIX_List   *reqEkuOids = NULL;
  1.1417 +
  1.1418 +        PKIX_ENTER(BUILD, "pkix_Build_BuildSelectorAndParams");
  1.1419 +        PKIX_NULLCHECK_THREE(state, state->prevCert, state->traversedSubjNames);
  1.1420 +
  1.1421 +        PKIX_CHECK(PKIX_PL_Cert_GetIssuer
  1.1422 +                (state->prevCert, &currentIssuer, plContext),
  1.1423 +                PKIX_CERTGETISSUERFAILED);
  1.1424 +
  1.1425 +        PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
  1.1426 +                (state->prevCert, &authKeyId, plContext),
  1.1427 +                PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
  1.1428 +
  1.1429 +        PKIX_CHECK(PKIX_ComCertSelParams_Create(&certSelParams, plContext),
  1.1430 +                PKIX_COMCERTSELPARAMSCREATEFAILED);
  1.1431 +
  1.1432 +        PKIX_CHECK(PKIX_ComCertSelParams_SetSubject
  1.1433 +                (certSelParams, currentIssuer, plContext),
  1.1434 +                PKIX_COMCERTSELPARAMSSETSUBJECTFAILED);
  1.1435 +
  1.1436 +        if (authKeyId != NULL) {
  1.1437 +            PKIX_CHECK(PKIX_ComCertSelParams_SetSubjKeyIdentifier
  1.1438 +                    (certSelParams, authKeyId, plContext),
  1.1439 +                    PKIX_COMCERTSELPARAMSSETSUBJKEYIDENTIFIERFAILED);
  1.1440 +        }
  1.1441 +
  1.1442 +        PKIX_INCREF(state->buildConstants.testDate);
  1.1443 +        testDate = state->buildConstants.testDate;
  1.1444 +
  1.1445 +        PKIX_CHECK(PKIX_ComCertSelParams_SetCertificateValid
  1.1446 +                (certSelParams, testDate, plContext),
  1.1447 +                PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED);
  1.1448 +
  1.1449 +        PKIX_CHECK(PKIX_ComCertSelParams_SetBasicConstraints
  1.1450 +                (certSelParams, state->traversedCACerts, plContext),
  1.1451 +                PKIX_COMCERTSELPARAMSSETBASICCONSTRAINTSFAILED);
  1.1452 +
  1.1453 +        PKIX_CHECK(PKIX_ComCertSelParams_SetPathToNames
  1.1454 +                (certSelParams, state->traversedSubjNames, plContext),
  1.1455 +                PKIX_COMCERTSELPARAMSSETPATHTONAMESFAILED);
  1.1456 +
  1.1457 +        PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
  1.1458 +                    (state->buildConstants.procParams,
  1.1459 +                     &callerCertSelector, plContext),
  1.1460 +                    PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
  1.1461 +
  1.1462 +        if (callerCertSelector != NULL) {
  1.1463 +
  1.1464 +            /* Get initial EKU OIDs from ComCertSelParams, if set */
  1.1465 +            PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
  1.1466 +                       (callerCertSelector, &callerComCertSelParams, plContext),
  1.1467 +                       PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
  1.1468 +
  1.1469 +            if (callerComCertSelParams != NULL) {
  1.1470 +                PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
  1.1471 +                           (callerComCertSelParams, &reqEkuOids, plContext),
  1.1472 +                           PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
  1.1473 +
  1.1474 +                PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage
  1.1475 +                           (callerComCertSelParams, &reqKu, plContext),
  1.1476 +                           PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
  1.1477 +            }
  1.1478 +        }
  1.1479 +
  1.1480 +        PKIX_CHECK(
  1.1481 +            PKIX_ComCertSelParams_SetKeyUsage(certSelParams, reqKu,
  1.1482 +                                              plContext),
  1.1483 +            PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED);
  1.1484 +        
  1.1485 +        PKIX_CHECK(
  1.1486 +            PKIX_ComCertSelParams_SetExtendedKeyUsage(certSelParams,
  1.1487 +                                                      reqEkuOids,
  1.1488 +                                                      plContext),
  1.1489 +            PKIX_COMCERTSELPARAMSSETEXTKEYUSAGEFAILED);
  1.1490 +
  1.1491 +        PKIX_CHECK(PKIX_CertSelector_Create
  1.1492 +                (NULL, NULL, &state->certSel, plContext),
  1.1493 +                PKIX_CERTSELECTORCREATEFAILED);
  1.1494 +
  1.1495 +        PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
  1.1496 +                (state->certSel, certSelParams, plContext),
  1.1497 +                PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
  1.1498 +
  1.1499 +        PKIX_CHECK(PKIX_List_Create(&state->candidateCerts, plContext),
  1.1500 +                PKIX_LISTCREATEFAILED);
  1.1501 +
  1.1502 +        state->certStoreIndex = 0;
  1.1503 +
  1.1504 +cleanup:
  1.1505 +        PKIX_DECREF(certSelParams);
  1.1506 +        PKIX_DECREF(certSel);
  1.1507 +        PKIX_DECREF(currentIssuer);
  1.1508 +        PKIX_DECREF(authKeyId);
  1.1509 +        PKIX_DECREF(testDate);
  1.1510 +        PKIX_DECREF(reqEkuOids);
  1.1511 +        PKIX_DECREF(callerComCertSelParams);
  1.1512 +        PKIX_DECREF(callerCertSelector);
  1.1513 +
  1.1514 +        PKIX_RETURN(BUILD);
  1.1515 +}
  1.1516 +
  1.1517 +/* Match trust anchor to select params in order to find next cert. */
  1.1518 +static PKIX_Error*
  1.1519 +pkix_Build_SelectCertsFromTrustAnchors(
  1.1520 +    PKIX_List *trustAnchorsList,
  1.1521 +    PKIX_ComCertSelParams *certSelParams,
  1.1522 +    PKIX_List **pMatchList,
  1.1523 +    void *plContext) 
  1.1524 +{
  1.1525 +    int anchorIndex = 0;
  1.1526 +    PKIX_TrustAnchor *anchor = NULL;
  1.1527 +    PKIX_PL_Cert *trustedCert = NULL;
  1.1528 +    PKIX_List *matchList = NULL;
  1.1529 +    PKIX_CertSelector *certSel = NULL;
  1.1530 +    PKIX_CertSelector_MatchCallback selectorMatchCB = NULL;
  1.1531 +
  1.1532 +    PKIX_ENTER(BUILD, "pkix_Build_SelectCertsFromTrustAnchors");
  1.1533 +    
  1.1534 +    PKIX_CHECK(PKIX_CertSelector_Create
  1.1535 +               (NULL, NULL, &certSel, plContext),
  1.1536 +               PKIX_CERTSELECTORCREATEFAILED);
  1.1537 +    PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
  1.1538 +               (certSel, certSelParams, plContext),
  1.1539 +               PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
  1.1540 +    PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
  1.1541 +               (certSel, &selectorMatchCB, plContext),
  1.1542 +               PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
  1.1543 +
  1.1544 +    for (anchorIndex = 0;anchorIndex < trustAnchorsList->length; anchorIndex++) {
  1.1545 +        PKIX_CHECK(
  1.1546 +            PKIX_List_GetItem(trustAnchorsList,
  1.1547 +                              anchorIndex,
  1.1548 +                              (PKIX_PL_Object **)&anchor,
  1.1549 +                              plContext),
  1.1550 +            PKIX_LISTGETITEMFAILED);
  1.1551 +        PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
  1.1552 +                   (anchor, &trustedCert, plContext),
  1.1553 +                   PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  1.1554 +        pkixErrorResult =
  1.1555 +            (*selectorMatchCB)(certSel, trustedCert, plContext);
  1.1556 +        if (!pkixErrorResult) {
  1.1557 +            if (!matchList) {
  1.1558 +                PKIX_CHECK(PKIX_List_Create(&matchList,
  1.1559 +                                            plContext),
  1.1560 +                           PKIX_LISTCREATEFAILED);
  1.1561 +            }
  1.1562 +            PKIX_CHECK(
  1.1563 +                PKIX_List_AppendItem(matchList,
  1.1564 +                    (PKIX_PL_Object*)trustedCert,
  1.1565 +                                     plContext),
  1.1566 +                PKIX_LISTAPPENDITEMFAILED);
  1.1567 +        } else {
  1.1568 +            PKIX_DECREF(pkixErrorResult);
  1.1569 +        }
  1.1570 +        PKIX_DECREF(trustedCert);
  1.1571 +        PKIX_DECREF(anchor);
  1.1572 +     }
  1.1573 +    
  1.1574 +    *pMatchList = matchList;
  1.1575 +    matchList = NULL;
  1.1576 +
  1.1577 +cleanup:
  1.1578 +    PKIX_DECREF(matchList);
  1.1579 +    PKIX_DECREF(trustedCert);
  1.1580 +    PKIX_DECREF(anchor);
  1.1581 +    PKIX_DECREF(certSel);
  1.1582 +    
  1.1583 +    PKIX_RETURN(BUILD);
  1.1584 +}
  1.1585 +
  1.1586 +
  1.1587 +static PKIX_Error*
  1.1588 +pkix_Build_RemoveDupUntrustedCerts(
  1.1589 +    PKIX_List *trustedCertList,
  1.1590 +    PKIX_List *certsFound,
  1.1591 +    void *plContext)
  1.1592 +{
  1.1593 +    PKIX_UInt32 trustIndex;
  1.1594 +    PKIX_PL_Cert *trustCert = NULL, *cert = NULL;
  1.1595 +
  1.1596 +    PKIX_ENTER(BUILD, "pkix_Build_RemoveDupUntrustedCerts");
  1.1597 +    if (trustedCertList == NULL || certsFound == NULL) {
  1.1598 +        goto cleanup;
  1.1599 +    }
  1.1600 +    for (trustIndex = 0;trustIndex < trustedCertList->length;
  1.1601 +        trustIndex++) {
  1.1602 +        PKIX_UInt32 certIndex = 0;
  1.1603 +        PKIX_CHECK(
  1.1604 +            PKIX_List_GetItem(trustedCertList,
  1.1605 +                              trustIndex,
  1.1606 +                              (PKIX_PL_Object **)&trustCert,
  1.1607 +                              plContext),
  1.1608 +            PKIX_LISTGETITEMFAILED);
  1.1609 +        
  1.1610 +        while (certIndex < certsFound->length) {
  1.1611 +            PKIX_Boolean result = PKIX_FALSE;
  1.1612 +            PKIX_DECREF(cert);
  1.1613 +            PKIX_CHECK(
  1.1614 +                PKIX_List_GetItem(certsFound, certIndex,
  1.1615 +                                  (PKIX_PL_Object **)&cert,
  1.1616 +                                  plContext),
  1.1617 +                PKIX_LISTGETITEMFAILED);
  1.1618 +            PKIX_CHECK(
  1.1619 +                PKIX_PL_Object_Equals((PKIX_PL_Object *)trustCert,
  1.1620 +                                      (PKIX_PL_Object *)cert,
  1.1621 +                                      &result,
  1.1622 +                                      plContext),
  1.1623 +                PKIX_OBJECTEQUALSFAILED);
  1.1624 +            if (!result) {
  1.1625 +                certIndex += 1;
  1.1626 +                continue;
  1.1627 +            }
  1.1628 +            PKIX_CHECK(
  1.1629 +                PKIX_List_DeleteItem(certsFound, certIndex,
  1.1630 +                                     plContext),
  1.1631 +                PKIX_LISTDELETEITEMFAILED);
  1.1632 +        }
  1.1633 +        PKIX_DECREF(trustCert);
  1.1634 +    }
  1.1635 +cleanup:
  1.1636 +    PKIX_DECREF(cert);
  1.1637 +    PKIX_DECREF(trustCert);
  1.1638 +
  1.1639 +    PKIX_RETURN(BUILD);
  1.1640 +}
  1.1641 +
  1.1642 +
  1.1643 +/*
  1.1644 + * FUNCTION: pkix_Build_GatherCerts
  1.1645 + * DESCRIPTION:
  1.1646 + *
  1.1647 + *  This function traverses the CertStores in the List of CertStores contained
  1.1648 + *  in "state",  using the certSelector and other parameters contained in
  1.1649 + *  "state", to obtain a List of all available Certs that satisfy the criteria.
  1.1650 + *  If a CertStore has a cache, "certSelParams" is used both to query the cache
  1.1651 + *  and, if an actual CertStore search occurred, to update the cache. (Behavior
  1.1652 + *  is undefined if "certSelParams" is different from the parameters that were
  1.1653 + *  used to initialize the certSelector in "state".)
  1.1654 + * 
  1.1655 + *  If a CertStore using non-blocking I/O returns with an indication that I/O is
  1.1656 + *  in progress and the checking has not been completed, this function stores
  1.1657 + *  platform-dependent information at "pNBIOContext". Otherwise it stores NULL
  1.1658 + *  at "pNBIOContext", and state is updated with the results of the search.
  1.1659 + *
  1.1660 + * PARAMETERS:
  1.1661 + *  "state"
  1.1662 + *      Address of ForwardBuilderState to be used. Must be non-NULL.
  1.1663 + *  "certSelParams"
  1.1664 + *      Address of ComCertSelParams which were used in creating the current
  1.1665 + *      CertSelector, and to be used in querying and updating any caches that
  1.1666 + *      may be associated with with the CertStores.
  1.1667 + *  "pNBIOContext"
  1.1668 + *      Address at which platform-dependent information is returned if request
  1.1669 + *      is suspended for non-blocking I/O. Must be non-NULL.
  1.1670 + *  "plContext"
  1.1671 + *      Platform-specific context pointer.
  1.1672 + * THREAD SAFETY:
  1.1673 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1674 + * RETURNS:
  1.1675 + *  Returns NULL if the function succeeds.
  1.1676 + *  Returns a Build Error if the function fails in a non-fatal way
  1.1677 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.1678 + */
  1.1679 +/* return NULL if wouldblock, empty list if none found, else list of found */
  1.1680 +static PKIX_Error *
  1.1681 +pkix_Build_GatherCerts(
  1.1682 +        PKIX_ForwardBuilderState *state,
  1.1683 +        PKIX_ComCertSelParams *certSelParams,
  1.1684 +        void **pNBIOContext,
  1.1685 +        void *plContext)
  1.1686 +{
  1.1687 +        PKIX_Boolean certStoreIsCached = PKIX_FALSE;
  1.1688 +        PKIX_Boolean certStoreIsLocal = PKIX_FALSE;
  1.1689 +        PKIX_Boolean foundInCache = PKIX_FALSE;
  1.1690 +        PKIX_CertStore *certStore = NULL;
  1.1691 +        PKIX_CertStore_CertCallback getCerts = NULL;
  1.1692 +        PKIX_List *certsFound = NULL;
  1.1693 +        PKIX_List *trustedCertList = NULL;
  1.1694 +        void *nbioContext = NULL;
  1.1695 +
  1.1696 +        PKIX_ENTER(BUILD, "pkix_Build_GatherCerts");
  1.1697 +        PKIX_NULLCHECK_THREE(state, certSelParams, pNBIOContext);
  1.1698 +
  1.1699 +        nbioContext = *pNBIOContext;
  1.1700 +        *pNBIOContext = NULL;
  1.1701 +
  1.1702 +        PKIX_DECREF(state->candidateCerts);
  1.1703 +
  1.1704 +        while (state->certStoreIndex < state->buildConstants.numCertStores) {
  1.1705 +
  1.1706 +                /* Get the current CertStore */
  1.1707 +                PKIX_CHECK(PKIX_List_GetItem
  1.1708 +                        (state->buildConstants.certStores,
  1.1709 +                        state->certStoreIndex,
  1.1710 +                        (PKIX_PL_Object **)&certStore,
  1.1711 +                        plContext),
  1.1712 +                        PKIX_LISTGETITEMFAILED);
  1.1713 +
  1.1714 +                PKIX_CHECK(PKIX_CertStore_GetLocalFlag
  1.1715 +                           (certStore, &certStoreIsLocal, plContext),
  1.1716 +                           PKIX_CERTSTOREGETLOCALFLAGFAILED);
  1.1717 +
  1.1718 +                if (state->useOnlyLocal == certStoreIsLocal) {
  1.1719 +                    /* If GATHERPENDING, we've already checked the cache */
  1.1720 +                    if (state->status == BUILD_GATHERPENDING) {
  1.1721 +                        certStoreIsCached = PKIX_FALSE;
  1.1722 +                        foundInCache = PKIX_FALSE;
  1.1723 +                    } else {
  1.1724 +                        PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
  1.1725 +                                (certStore, &certStoreIsCached, plContext),
  1.1726 +                                PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
  1.1727 +
  1.1728 +                        if (certStoreIsCached) {
  1.1729 +                        /*
  1.1730 +                         * Look for Certs in the cache, using the SubjectName as
  1.1731 +                         * the key. Then the ComCertSelParams are used to filter
  1.1732 +                         * for qualified certs. If none are found, then the
  1.1733 +                         * certStores are queried. When we eventually add items
  1.1734 +                         * to the cache, we will only add items that passed the
  1.1735 +                         * ComCertSelParams filter, rather than all Certs which
  1.1736 +                         * matched the SubjectName.
  1.1737 +                         */
  1.1738 +
  1.1739 +                                PKIX_CHECK(pkix_CacheCert_Lookup
  1.1740 +                                        (certStore,
  1.1741 +                                        certSelParams,
  1.1742 +                                        state->buildConstants.testDate,
  1.1743 +                                        &foundInCache,
  1.1744 +                                        &certsFound,
  1.1745 +                                        plContext),
  1.1746 +                                        PKIX_CACHECERTCHAINLOOKUPFAILED);
  1.1747 +
  1.1748 +                        }
  1.1749 +                    }
  1.1750 +
  1.1751 +                    /*
  1.1752 +                     * XXX need to verify if Cert is trusted, hence may not
  1.1753 +                     * be worth it to have the Cert Cached or
  1.1754 +                     * If it is trusted, don't cache, but once there is cached
  1.1755 +                     * certs, we won't get certs from database any more.
  1.1756 +                     * can use flag to force not getting certs from cache
  1.1757 +                     */
  1.1758 +                    if (!foundInCache) {
  1.1759 +
  1.1760 +                        if (nbioContext == NULL) {
  1.1761 +                                PKIX_CHECK(PKIX_CertStore_GetCertCallback
  1.1762 +                                        (certStore, &getCerts, plContext),
  1.1763 +                                        PKIX_CERTSTOREGETCERTCALLBACKFAILED);
  1.1764 +
  1.1765 +                                PKIX_CHECK(getCerts
  1.1766 +                                        (certStore,
  1.1767 +                                        state->certSel,
  1.1768 +                                        state->verifyNode,
  1.1769 +                                        &nbioContext,
  1.1770 +                                        &certsFound,
  1.1771 +                                        plContext),
  1.1772 +                                        PKIX_GETCERTSFAILED);
  1.1773 +                        } else {
  1.1774 +                                PKIX_CHECK(PKIX_CertStore_CertContinue
  1.1775 +                                        (certStore,
  1.1776 +                                        state->certSel,
  1.1777 +                                        state->verifyNode,
  1.1778 +                                        &nbioContext,
  1.1779 +                                        &certsFound,
  1.1780 +                                        plContext),
  1.1781 +                                        PKIX_CERTSTORECERTCONTINUEFAILED);
  1.1782 +                        }
  1.1783 +
  1.1784 +                        if (certStoreIsCached && certsFound) {
  1.1785 +
  1.1786 +                                PKIX_CHECK(pkix_CacheCert_Add
  1.1787 +                                        (certStore,
  1.1788 +                                        certSelParams,
  1.1789 +                                        certsFound,
  1.1790 +                                        plContext),
  1.1791 +                                        PKIX_CACHECERTADDFAILED);
  1.1792 +                        }
  1.1793 +                    }
  1.1794 +
  1.1795 +                    /*
  1.1796 +                     * getCerts returns an empty list for "NONE FOUND",
  1.1797 +                     * a NULL list for "would block"
  1.1798 +                     */
  1.1799 +                    if (certsFound == NULL) {
  1.1800 +                        state->status = BUILD_GATHERPENDING;
  1.1801 +                        *pNBIOContext = nbioContext;
  1.1802 +                        goto cleanup;
  1.1803 +                    }
  1.1804 +                }
  1.1805 +
  1.1806 +                /* Are there any more certStores to query? */
  1.1807 +                PKIX_DECREF(certStore);
  1.1808 +                ++(state->certStoreIndex);
  1.1809 +        }
  1.1810 +
  1.1811 +        if (certsFound && certsFound->length > 1) {
  1.1812 +            PKIX_List *sorted = NULL;
  1.1813 +            
  1.1814 +            /* sort Certs to try to optimize search */
  1.1815 +            PKIX_CHECK(pkix_Build_SortCandidateCerts
  1.1816 +                       (certsFound, &sorted, plContext),
  1.1817 +                       PKIX_BUILDSORTCANDIDATECERTSFAILED);
  1.1818 +            PKIX_DECREF(certsFound);
  1.1819 +            certsFound = sorted;
  1.1820 +        }
  1.1821 +
  1.1822 +        PKIX_CHECK(
  1.1823 +            pkix_Build_SelectCertsFromTrustAnchors(
  1.1824 +                state->buildConstants.anchors,
  1.1825 +                certSelParams, &trustedCertList,
  1.1826 +                plContext),
  1.1827 +            PKIX_FAILTOSELECTCERTSFROMANCHORS);
  1.1828 +        PKIX_CHECK(
  1.1829 +            pkix_Build_RemoveDupUntrustedCerts(trustedCertList,
  1.1830 +                                               certsFound,
  1.1831 +                                               plContext),
  1.1832 +            PKIX_REMOVEDUPUNTRUSTEDCERTSFAILED);
  1.1833 +
  1.1834 +        PKIX_CHECK(
  1.1835 +            pkix_List_MergeLists(trustedCertList,
  1.1836 +                                 certsFound,
  1.1837 +                                 &state->candidateCerts,
  1.1838 +                                 plContext),
  1.1839 +            PKIX_LISTMERGEFAILED);
  1.1840 +
  1.1841 +        /* No, return the list we have gathered */
  1.1842 +        PKIX_CHECK(PKIX_List_GetLength
  1.1843 +                (state->candidateCerts, &state->numCerts, plContext),
  1.1844 +                PKIX_LISTGETLENGTHFAILED);
  1.1845 +
  1.1846 +        state->certIndex = 0;
  1.1847 +
  1.1848 +cleanup:
  1.1849 +        PKIX_DECREF(trustedCertList);
  1.1850 +        PKIX_DECREF(certStore);
  1.1851 +        PKIX_DECREF(certsFound);
  1.1852 +
  1.1853 +        PKIX_RETURN(BUILD);
  1.1854 +}
  1.1855 +
  1.1856 +/*
  1.1857 + * FUNCTION: pkix_Build_UpdateDate
  1.1858 + * DESCRIPTION:
  1.1859 + *
  1.1860 + *  This function updates the validityDate contained in "state", for the current
  1.1861 + *  CertChain contained in "state", to include the validityDate of the
  1.1862 + *  candidateCert contained in "state". The validityDate of a chain is the
  1.1863 + *  earliest of all the notAfter dates contained in the respective Certificates.
  1.1864 + *
  1.1865 + * PARAMETERS:
  1.1866 + *  "state"
  1.1867 + *      Address of ForwardBuilderState to be used. Must be non-NULL.
  1.1868 + *  "plContext"
  1.1869 + *      Platform-specific context pointer.
  1.1870 + * THREAD SAFETY:
  1.1871 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1872 + * RETURNS:
  1.1873 + *  Returns NULL if the function succeeds.
  1.1874 + *  Returns a Build Error if the function fails in a non-fatal way
  1.1875 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.1876 + */
  1.1877 +static PKIX_Error *
  1.1878 +pkix_Build_UpdateDate(
  1.1879 +        PKIX_ForwardBuilderState *state,
  1.1880 +        void *plContext)
  1.1881 +{
  1.1882 +        PKIX_Boolean canBeCached = PKIX_FALSE;
  1.1883 +        PKIX_Int32 comparison = 0;
  1.1884 +        PKIX_PL_Date *notAfter = NULL;
  1.1885 +
  1.1886 +        PKIX_ENTER(BUILD, "pkix_Build_UpdateDate");
  1.1887 +        PKIX_NULLCHECK_ONE(state);
  1.1888 +
  1.1889 +        PKIX_CHECK(PKIX_PL_Cert_GetCacheFlag
  1.1890 +                (state->candidateCert, &canBeCached, plContext),
  1.1891 +                PKIX_CERTGETCACHEFLAGFAILED);
  1.1892 +
  1.1893 +        state->canBeCached = state->canBeCached && canBeCached;
  1.1894 +        if (state->canBeCached == PKIX_TRUE) {
  1.1895 +
  1.1896 +                /*
  1.1897 +                 * So far, all certs can be cached. Update cert
  1.1898 +                 * chain validity time, which is the earliest of
  1.1899 +                 * all certs' notAfter times.
  1.1900 +                 */
  1.1901 +                PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
  1.1902 +                        (state->candidateCert, &notAfter, plContext),
  1.1903 +                        PKIX_CERTGETVALIDITYNOTAFTERFAILED);
  1.1904 +
  1.1905 +                if (state->validityDate == NULL) {
  1.1906 +                        state->validityDate = notAfter;
  1.1907 +                        notAfter = NULL;
  1.1908 +                } else {
  1.1909 +                        PKIX_CHECK(PKIX_PL_Object_Compare
  1.1910 +                                ((PKIX_PL_Object *)state->validityDate,
  1.1911 +                                (PKIX_PL_Object *)notAfter,
  1.1912 +                                &comparison,
  1.1913 +                                plContext),
  1.1914 +                                PKIX_OBJECTCOMPARATORFAILED);
  1.1915 +                        if (comparison > 0) {
  1.1916 +                                PKIX_DECREF(state->validityDate);
  1.1917 +                                state->validityDate = notAfter;
  1.1918 +                                notAfter = NULL;
  1.1919 +                        }
  1.1920 +                }
  1.1921 +        }
  1.1922 +
  1.1923 +cleanup:
  1.1924 +
  1.1925 +        PKIX_DECREF(notAfter);
  1.1926 +
  1.1927 +        PKIX_RETURN(BUILD);
  1.1928 +}
  1.1929 +
  1.1930 +/* Prepare 'state' for the AIA round. */
  1.1931 +static void
  1.1932 +pkix_PrepareForwardBuilderStateForAIA(
  1.1933 +        PKIX_ForwardBuilderState *state)
  1.1934 +{
  1.1935 +        PORT_Assert(state->useOnlyLocal == PKIX_TRUE);
  1.1936 +        state->useOnlyLocal = PKIX_FALSE;
  1.1937 +        state->certStoreIndex = 0;
  1.1938 +        state->numFanout = state->buildConstants.maxFanout;
  1.1939 +        state->status = BUILD_TRYAIA;
  1.1940 +}
  1.1941 +
  1.1942 +/*
  1.1943 + * FUNCTION: pkix_BuildForwardDepthFirstSearch
  1.1944 + * DESCRIPTION:
  1.1945 + *
  1.1946 + *  This function performs a depth first search in the "forward" direction (from
  1.1947 + *  the target Cert to the trust anchor). A non-NULL targetCert must be stored
  1.1948 + *  in the ForwardBuilderState before this function is called. It is not written
  1.1949 + *  recursively since execution may be suspended in in any of several places
  1.1950 + *  pending completion of non-blocking I/O. This iterative structure makes it
  1.1951 + *  much easier to resume where it left off.
  1.1952 + *
  1.1953 + *  Since the nature of the search is recursive, the recursion is handled by
  1.1954 + *  chaining states. That is, each new step involves creating a new
  1.1955 + *  ForwardBuilderState linked to its predecessor. If a step turns out to be
  1.1956 + *  fruitless, the state of the predecessor is restored and the next alternative
  1.1957 + *  is tried. When a search is successful, values needed from the last state
  1.1958 + *  (canBeCached and validityDate) are copied to the state provided by the
  1.1959 + *  caller, so that the caller can retrieve those values.
  1.1960 + *
  1.1961 + *  There are three return arguments, the NBIOContext, the ValidateResult and
  1.1962 + *  the ForwardBuilderState. If NBIOContext is non-NULL, it means the search is
  1.1963 + *  suspended until the results of a non-blocking IO become available. The
  1.1964 + *  caller may wait for the completion using platform-dependent methods and then
  1.1965 + *  call this function again, allowing it to resume the search. If NBIOContext
  1.1966 + *  is NULL and the ValidateResult is non-NULL, it means the search has
  1.1967 + *  concluded successfully. If the NBIOContext is NULL but the ValidateResult is
  1.1968 + *  NULL, it means the search was unsuccessful.
  1.1969 + *
  1.1970 + *  This function performs several steps at each node in the constructed chain:
  1.1971 + *
  1.1972 + *  1) It retrieves Certs from the registered CertStores that match the
  1.1973 + *  criteria established by the ForwardBuilderState pointed to by "state", such
  1.1974 + *  as a subject name matching the issuer name of the previous Cert. If there
  1.1975 + *  are no matching Certs, the function returns to the previous, or "parent",
  1.1976 + *  state and tries to continue the chain building with another of the Certs
  1.1977 + *  obtained from the CertStores as possible issuers for that parent Cert.
  1.1978 + *
  1.1979 + *  2) For each candidate Cert returned by the CertStores, this function checks
  1.1980 + *  whether the Cert is valid. If it is trusted, this function checks whether
  1.1981 + *  this Cert might serve as a TrustAnchor for a complete chain.
  1.1982 + *
  1.1983 + *  3) It determines whether this Cert, in conjunction with any of the
  1.1984 + *  TrustAnchors, might complete a chain. A complete chain, from this or the
  1.1985 + *  preceding step, is checked to see whether it is valid as a complete
  1.1986 + *  chain, including the checks that cannot be done in the forward direction.
  1.1987 + *
  1.1988 + *  4) If this Cert chains successfully, but is not a complete chain, that is,
  1.1989 + *  we have not reached a trusted Cert, a new ForwardBuilderState is created
  1.1990 + *  with this Cert as the immediate predecessor, and we continue in step (1),
  1.1991 + *  attempting to get Certs from the CertStores with this Certs "issuer" as
  1.1992 + *  their subject.
  1.1993 + *
  1.1994 + *  5) If an entire chain validates successfully, then we are done. A
  1.1995 + *  ValidateResult is created containing the Public Key of the target
  1.1996 + *  certificate (including DSA parameter inheritance, if any) and the
  1.1997 + *  PolicyNode representing the policy tree output by the validation algorithm,
  1.1998 + *  and stored at pValResult, and the function exits returning NULL.
  1.1999 + *
  1.2000 + *  5) If the entire chain does not validate successfully, the algorithm
  1.2001 + *  discards the latest Cert and continues in step 2 with the next candidate
  1.2002 + *  Cert, backing up to a parent state when no more possibilities exist at a
  1.2003 + *  given level, and returning failure when we try to back up but discover we
  1.2004 + *  are at the top level.
  1.2005 + *
  1.2006 + * PARAMETERS:
  1.2007 + *  "pNBIOContext"
  1.2008 + *      Address at which platform-dependent information is returned if building
  1.2009 + *      is suspended for non-blocking I/O. Must be non-NULL.
  1.2010 + *  "pState"
  1.2011 + *      Address at which input ForwardBuilderState is found, and at which output
  1.2012 + *      ForwardBuilderState is stored. Must be non-NULL.
  1.2013 + *  "pValResult"
  1.2014 + *      Address at which the ValidateResult is stored. Must be non-NULL.
  1.2015 + *  "plContext"
  1.2016 + *      Platform-specific context pointer.
  1.2017 + * THREAD SAFETY:
  1.2018 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.2019 + * RETURNS:
  1.2020 + *  Returns NULL if the function succeeds.
  1.2021 + *  Returns a Build Error if the function fails in a non-fatal way.
  1.2022 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.2023 + */
  1.2024 +static PKIX_Error *
  1.2025 +pkix_BuildForwardDepthFirstSearch(
  1.2026 +        void **pNBIOContext,
  1.2027 +        PKIX_ForwardBuilderState *state,
  1.2028 +        PKIX_ValidateResult **pValResult,
  1.2029 +        void *plContext)
  1.2030 +{
  1.2031 +        PKIX_Boolean outOfOptions = PKIX_FALSE;
  1.2032 +        PKIX_Boolean trusted = PKIX_FALSE;
  1.2033 +        PKIX_Boolean isSelfIssued = PKIX_FALSE;
  1.2034 +        PKIX_Boolean canBeCached = PKIX_FALSE;
  1.2035 +        PKIX_Boolean ioPending = PKIX_FALSE;
  1.2036 +        PKIX_PL_Date *validityDate = NULL;
  1.2037 +        PKIX_PL_Date *currTime  = NULL;
  1.2038 +        PKIX_Int32 childTraversedCACerts = 0;
  1.2039 +        PKIX_UInt32 numSubjectNames = 0;
  1.2040 +        PKIX_UInt32 numChained = 0;
  1.2041 +        PKIX_Int32 cmpTimeResult = 0;
  1.2042 +        PKIX_UInt32 i = 0;
  1.2043 +        PKIX_UInt32 certsSoFar = 0;
  1.2044 +        PKIX_List *childTraversedSubjNames = NULL;
  1.2045 +        PKIX_List *subjectNames = NULL;
  1.2046 +        PKIX_List *unfilteredCerts = NULL;
  1.2047 +        PKIX_List *filteredCerts = NULL;
  1.2048 +        PKIX_PL_Object *subjectName = NULL;
  1.2049 +        PKIX_ValidateResult *valResult = NULL;
  1.2050 +        PKIX_ForwardBuilderState *childState = NULL;
  1.2051 +        PKIX_ForwardBuilderState *parentState = NULL;
  1.2052 +        PKIX_PL_Object *revCheckerState = NULL;
  1.2053 +        PKIX_ComCertSelParams *certSelParams = NULL;
  1.2054 +        PKIX_TrustAnchor *trustAnchor = NULL;
  1.2055 +        PKIX_PL_Cert *trustedCert = NULL;
  1.2056 +        PKIX_VerifyNode *verifyNode = NULL;
  1.2057 +        PKIX_Error *verifyError = NULL;
  1.2058 +        PKIX_Error *finalError = NULL;
  1.2059 +        void *nbio = NULL;
  1.2060 +        PKIX_UInt32 numIterations = 0;
  1.2061 +
  1.2062 +        PKIX_ENTER(BUILD, "pkix_BuildForwardDepthFirstSearch");
  1.2063 +        PKIX_NULLCHECK_THREE(pNBIOContext, state, pValResult);
  1.2064 +
  1.2065 +        nbio = *pNBIOContext;
  1.2066 +        *pNBIOContext = NULL;
  1.2067 +        PKIX_INCREF(state->validityDate);
  1.2068 +        validityDate = state->validityDate;
  1.2069 +        canBeCached = state->canBeCached;
  1.2070 +        PKIX_DECREF(*pValResult);
  1.2071 +
  1.2072 +        /*
  1.2073 +         * We return if successful; if we fall off the end
  1.2074 +         * of this "while" clause our search has failed.
  1.2075 +         */
  1.2076 +        while (outOfOptions == PKIX_FALSE) {
  1.2077 +            /*
  1.2078 +             * The maximum number of iterations works around a bug that
  1.2079 +             * causes this while loop to never exit when AIA and cross
  1.2080 +             * certificates are involved.  See bug xxxxx.
  1.2081 +             */
  1.2082 +            if (numIterations++ > 250)
  1.2083 +                    PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS);
  1.2084 +
  1.2085 +            if (state->buildConstants.maxTime != 0) {
  1.2086 +                    PKIX_DECREF(currTime);
  1.2087 +                    PKIX_CHECK(PKIX_PL_Date_Create_UTCTime
  1.2088 +                            (NULL, &currTime, plContext),
  1.2089 +                            PKIX_DATECREATEUTCTIMEFAILED);
  1.2090 +
  1.2091 +                    PKIX_CHECK(PKIX_PL_Object_Compare
  1.2092 +                             ((PKIX_PL_Object *)state->buildConstants.timeLimit,
  1.2093 +                             (PKIX_PL_Object *)currTime,
  1.2094 +                             &cmpTimeResult,
  1.2095 +                             plContext),
  1.2096 +                             PKIX_OBJECTCOMPARATORFAILED);
  1.2097 +
  1.2098 +                    if (cmpTimeResult < 0) {
  1.2099 +                        if (state->verifyNode != NULL) {
  1.2100 +                                PKIX_ERROR_CREATE
  1.2101 +                                    (BUILD,
  1.2102 +                                    PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS,
  1.2103 +                                    verifyError);
  1.2104 +                                PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
  1.2105 +                                    (state->verifyNode,
  1.2106 +                                    verifyError,
  1.2107 +                                    plContext),
  1.2108 +                                    PKIX_VERIFYNODESETERRORFAILED);
  1.2109 +                                PKIX_DECREF(finalError);
  1.2110 +                                finalError = verifyError;
  1.2111 +                                verifyError = NULL;
  1.2112 +                        }
  1.2113 +                        /* Even if we logged error, we still have to abort */
  1.2114 +                        PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS);
  1.2115 +                    }
  1.2116 +            }
  1.2117 +
  1.2118 +            if (state->status == BUILD_INITIAL) {
  1.2119 +
  1.2120 +                PKIX_CHECK(pkix_Build_BuildSelectorAndParams(state, plContext),
  1.2121 +                        PKIX_BUILDBUILDSELECTORANDPARAMSFAILED);
  1.2122 +
  1.2123 +                /*
  1.2124 +                 * If the caller supplied a partial certChain (hintCerts) try
  1.2125 +                 * the next one from that List before we go to the certStores.
  1.2126 +                 */
  1.2127 +                if (state->buildConstants.numHintCerts > 0) {
  1.2128 +                        /* How many Certs does our trust chain have already? */
  1.2129 +                        PKIX_CHECK(PKIX_List_GetLength
  1.2130 +                                (state->trustChain, &certsSoFar, plContext),
  1.2131 +                                PKIX_LISTGETLENGTHFAILED);
  1.2132 +
  1.2133 +                        /* That includes the target Cert. Don't count it. */
  1.2134 +                        certsSoFar--;
  1.2135 +
  1.2136 +                        /* Are we still within range of the partial chain? */
  1.2137 +                        if (certsSoFar >= state->buildConstants.numHintCerts) {
  1.2138 +                                state->status = BUILD_TRYAIA;
  1.2139 +                        } else {
  1.2140 +                                /*
  1.2141 +                                 * If we already have n certs, we want the n+1th
  1.2142 +                                 * (i.e., index = n) from the list of hints.
  1.2143 +                                 */
  1.2144 +                                PKIX_DECREF(state->candidateCert);
  1.2145 +                                PKIX_CHECK(PKIX_List_GetItem
  1.2146 +                                    (state->buildConstants.hintCerts,
  1.2147 +                                    certsSoFar,
  1.2148 +                                    (PKIX_PL_Object **)&state->candidateCert,
  1.2149 +                                    plContext),
  1.2150 +                                    PKIX_LISTGETITEMFAILED);
  1.2151 +
  1.2152 +                                PKIX_CHECK(PKIX_List_AppendItem
  1.2153 +                                    (state->candidateCerts,
  1.2154 +                                    (PKIX_PL_Object *)state->candidateCert,
  1.2155 +                                    plContext),
  1.2156 +                                    PKIX_LISTAPPENDITEMFAILED);
  1.2157 +
  1.2158 +                                state->numCerts = 1;
  1.2159 +                                state->usingHintCerts = PKIX_TRUE;
  1.2160 +                                state->status = BUILD_CERTVALIDATING;
  1.2161 +                        }
  1.2162 +                } else {
  1.2163 +                        state->status = BUILD_TRYAIA;
  1.2164 +                }
  1.2165 +
  1.2166 +            }
  1.2167 +
  1.2168 +            if (state->status == BUILD_TRYAIA) {
  1.2169 +                if (state->useOnlyLocal == PKIX_TRUE) {
  1.2170 +                        state->status = BUILD_COLLECTINGCERTS;
  1.2171 +                } else {
  1.2172 +                        state->status = BUILD_AIAPENDING;
  1.2173 +                }
  1.2174 +            }
  1.2175 +
  1.2176 +            if (state->status == BUILD_AIAPENDING &&
  1.2177 +                state->buildConstants.aiaMgr) {
  1.2178 +                pkixErrorResult = PKIX_PL_AIAMgr_GetAIACerts
  1.2179 +                        (state->buildConstants.aiaMgr,
  1.2180 +                        state->prevCert,
  1.2181 +                        &nbio,
  1.2182 +                        &unfilteredCerts,
  1.2183 +                         plContext);
  1.2184 +
  1.2185 +                if (nbio != NULL) {
  1.2186 +                        /* IO still pending, resume later */
  1.2187 +                        *pNBIOContext = nbio;
  1.2188 +                        goto cleanup;
  1.2189 +                }
  1.2190 +                state->numCerts = 0;
  1.2191 +                if (pkixErrorResult) {
  1.2192 +                    pkixErrorClass = pkixErrorResult->errClass;
  1.2193 +                    if (pkixErrorClass == PKIX_FATAL_ERROR) {
  1.2194 +                        goto fatal;
  1.2195 +                    }
  1.2196 +                    PKIX_DECREF(finalError);
  1.2197 +                    finalError = pkixErrorResult;
  1.2198 +                    pkixErrorResult = NULL;
  1.2199 +                    if (state->verifyNode != NULL) {
  1.2200 +                        /* state->verifyNode is the object that contains a list
  1.2201 +                         * of verifyNodes. verifyNodes contains cert chain
  1.2202 +                         * build failures that occurred on this level of chain
  1.2203 +                         * building.  Here, creating new verify node
  1.2204 +                         * to log the failure and adding it to the list. */
  1.2205 +                        PKIX_CHECK_FATAL(pkix_VerifyNode_Create
  1.2206 +                                         (state->prevCert,
  1.2207 +                                          0, NULL,
  1.2208 +                                          &verifyNode,
  1.2209 +                                          plContext),
  1.2210 +                                         PKIX_VERIFYNODECREATEFAILED);
  1.2211 +                        PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
  1.2212 +                                         (verifyNode, finalError, plContext),
  1.2213 +                                         PKIX_VERIFYNODESETERRORFAILED);
  1.2214 +                        PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  1.2215 +                                         (state->verifyNode,
  1.2216 +                                          verifyNode,
  1.2217 +                                          plContext),
  1.2218 +                                         PKIX_VERIFYNODEADDTOTREEFAILED);
  1.2219 +                        PKIX_DECREF(verifyNode);
  1.2220 +                    }
  1.2221 +                }
  1.2222 +#ifdef PKIX_BUILDDEBUG
  1.2223 +                /* Turn this on to trace the List of Certs, before CertSelect */
  1.2224 +                {
  1.2225 +                                PKIX_PL_String *unString;
  1.2226 +                                char *unAscii;
  1.2227 +                                PKIX_UInt32 length;
  1.2228 +                                PKIX_TOSTRING
  1.2229 +                                        ((PKIX_PL_Object*)unfilteredCerts,
  1.2230 +                                        &unString,
  1.2231 +                                        plContext,
  1.2232 +                                        PKIX_OBJECTTOSTRINGFAILED);
  1.2233 +
  1.2234 +                                PKIX_CHECK(PKIX_PL_String_GetEncoded
  1.2235 +                                        (unString,
  1.2236 +                                        PKIX_ESCASCII,
  1.2237 +                                        (void **)&unAscii,
  1.2238 +                                        &length,
  1.2239 +                                        plContext),
  1.2240 +                                        PKIX_STRINGGETENCODEDFAILED);
  1.2241 +
  1.2242 +                                PKIX_DEBUG_ARG
  1.2243 +                                        ("unfilteredCerts = %s\n", unAscii);
  1.2244 +                                PKIX_DECREF(unString);
  1.2245 +                                PKIX_FREE(unAscii);
  1.2246 +                }
  1.2247 +#endif
  1.2248 +
  1.2249 +                /* Note: Certs winnowed here don't get into VerifyTree. */
  1.2250 +                if (unfilteredCerts) {
  1.2251 +                        PKIX_CHECK(pkix_CertSelector_Select
  1.2252 +                                (state->certSel,
  1.2253 +                                unfilteredCerts,
  1.2254 +                                &filteredCerts,
  1.2255 +                                plContext),
  1.2256 +                                PKIX_CERTSELECTORSELECTFAILED);
  1.2257 +
  1.2258 +                        PKIX_DECREF(unfilteredCerts);
  1.2259 +
  1.2260 +                        PKIX_CHECK(PKIX_List_GetLength
  1.2261 +                                (filteredCerts, &(state->numCerts), plContext),
  1.2262 +                                PKIX_LISTGETLENGTHFAILED);
  1.2263 +
  1.2264 +#ifdef PKIX_BUILDDEBUG
  1.2265 +                /* Turn this on to trace the List of Certs, after CertSelect */
  1.2266 +                {
  1.2267 +                        PKIX_PL_String *unString;
  1.2268 +                        char *unAscii;
  1.2269 +                        PKIX_UInt32 length;
  1.2270 +                        PKIX_TOSTRING
  1.2271 +                                ((PKIX_PL_Object*)filteredCerts,
  1.2272 +                                &unString,
  1.2273 +                                plContext,
  1.2274 +                                PKIX_OBJECTTOSTRINGFAILED);
  1.2275 +
  1.2276 +                        PKIX_CHECK(PKIX_PL_String_GetEncoded
  1.2277 +                                    (unString,
  1.2278 +                                    PKIX_ESCASCII,
  1.2279 +                                    (void **)&unAscii,
  1.2280 +                                    &length,
  1.2281 +                                    plContext),
  1.2282 +                                    PKIX_STRINGGETENCODEDFAILED);
  1.2283 +
  1.2284 +                        PKIX_DEBUG_ARG("filteredCerts = %s\n", unAscii);
  1.2285 +                        PKIX_DECREF(unString);
  1.2286 +                        PKIX_FREE(unAscii);
  1.2287 +                }
  1.2288 +#endif
  1.2289 +
  1.2290 +                        PKIX_DECREF(state->candidateCerts);
  1.2291 +                        state->candidateCerts = filteredCerts;
  1.2292 +                        state->certIndex = 0;
  1.2293 +                        filteredCerts = NULL;
  1.2294 +                }
  1.2295 +
  1.2296 +                /* Are there any Certs to try? */
  1.2297 +                if (state->numCerts > 0) {
  1.2298 +                        state->status = BUILD_CERTVALIDATING;
  1.2299 +                } else {
  1.2300 +                        state->status = BUILD_COLLECTINGCERTS;
  1.2301 +                }
  1.2302 +            }
  1.2303 +
  1.2304 +            PKIX_DECREF(certSelParams);
  1.2305 +            PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
  1.2306 +                (state->certSel, &certSelParams, plContext),
  1.2307 +                PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
  1.2308 +
  1.2309 +            /* **** Querying the CertStores ***** */
  1.2310 +            if ((state->status == BUILD_COLLECTINGCERTS) ||
  1.2311 +                (state->status == BUILD_GATHERPENDING)) {
  1.2312 +
  1.2313 +#if PKIX_FORWARDBUILDERSTATEDEBUG
  1.2314 +                PKIX_CHECK(pkix_ForwardBuilderState_DumpState
  1.2315 +                        (state, plContext),
  1.2316 +                        PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED);
  1.2317 +#endif
  1.2318 +
  1.2319 +                PKIX_CHECK(pkix_Build_GatherCerts
  1.2320 +                        (state, certSelParams, &nbio, plContext),
  1.2321 +                        PKIX_BUILDGATHERCERTSFAILED);
  1.2322 +
  1.2323 +                if (nbio != NULL) {
  1.2324 +                        /* IO still pending, resume later */
  1.2325 +                        *pNBIOContext = nbio;
  1.2326 +                        goto cleanup;
  1.2327 +                }
  1.2328 +
  1.2329 +                /* Are there any Certs to try? */
  1.2330 +                if (state->numCerts > 0) {
  1.2331 +                        state->status = BUILD_CERTVALIDATING;
  1.2332 +                } else {
  1.2333 +                        state->status = BUILD_ABANDONNODE;
  1.2334 +                }
  1.2335 +            }
  1.2336 +
  1.2337 +            /* ****Phase 2 - Chain building***** */
  1.2338 +
  1.2339 +#if PKIX_FORWARDBUILDERSTATEDEBUG
  1.2340 +            PKIX_CHECK(pkix_ForwardBuilderState_DumpState(state, plContext),
  1.2341 +                    PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED);
  1.2342 +#endif
  1.2343 +
  1.2344 +            if (state->status == BUILD_CERTVALIDATING) {
  1.2345 +                    PKIX_DECREF(state->candidateCert);
  1.2346 +                    PKIX_CHECK(PKIX_List_GetItem
  1.2347 +                            (state->candidateCerts,
  1.2348 +                            state->certIndex,
  1.2349 +                            (PKIX_PL_Object **)&(state->candidateCert),
  1.2350 +                            plContext),
  1.2351 +                            PKIX_LISTGETITEMFAILED);
  1.2352 +
  1.2353 +                    if ((state->verifyNode) != NULL) {
  1.2354 +                            PKIX_CHECK_FATAL(pkix_VerifyNode_Create
  1.2355 +                                    (state->candidateCert,
  1.2356 +                                    0,
  1.2357 +                                    NULL,
  1.2358 +                                    &verifyNode,
  1.2359 +                                    plContext),
  1.2360 +                                    PKIX_VERIFYNODECREATEFAILED);
  1.2361 +                    }
  1.2362 +
  1.2363 +                    /* If failure, this function sets Error in verifyNode */
  1.2364 +                    verifyError = pkix_Build_VerifyCertificate
  1.2365 +                            (state,
  1.2366 +                            state->buildConstants.userCheckers,
  1.2367 +                            &trusted,
  1.2368 +                            verifyNode,
  1.2369 +                            plContext);
  1.2370 +
  1.2371 +                    if (verifyError) {
  1.2372 +                            pkixTempErrorReceived = PKIX_TRUE;
  1.2373 +                            pkixErrorClass = verifyError->errClass;
  1.2374 +                            if (pkixErrorClass == PKIX_FATAL_ERROR) {
  1.2375 +                                pkixErrorResult = verifyError;
  1.2376 +                                verifyError = NULL;
  1.2377 +                                goto fatal;
  1.2378 +                            }
  1.2379 +                    }
  1.2380 +
  1.2381 +                    if (PKIX_ERROR_RECEIVED) {
  1.2382 +                            if (state->verifyNode != NULL) {
  1.2383 +                                PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
  1.2384 +                                    (verifyNode, verifyError, plContext),
  1.2385 +                                    PKIX_VERIFYNODESETERRORFAILED);
  1.2386 +                                PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  1.2387 +                                        (state->verifyNode,
  1.2388 +                                        verifyNode,
  1.2389 +                                        plContext),
  1.2390 +                                        PKIX_VERIFYNODEADDTOTREEFAILED);
  1.2391 +                                PKIX_DECREF(verifyNode);
  1.2392 +                            }
  1.2393 +                            pkixTempErrorReceived = PKIX_FALSE;
  1.2394 +                            PKIX_DECREF(finalError);
  1.2395 +                            finalError = verifyError;
  1.2396 +                            verifyError = NULL;
  1.2397 +                            if (state->certLoopingDetected) {
  1.2398 +                                PKIX_ERROR
  1.2399 +                                    (PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED);
  1.2400 +                            }
  1.2401 +                            state->status = BUILD_GETNEXTCERT;
  1.2402 +                    } else {
  1.2403 +                            state->status = BUILD_DATEPREP;
  1.2404 +                    }
  1.2405 +            }
  1.2406 +
  1.2407 +            if (state->status == BUILD_DATEPREP) {
  1.2408 +                    /* Keep track of whether this chain can be cached */
  1.2409 +                    PKIX_CHECK(pkix_Build_UpdateDate(state, plContext),
  1.2410 +                            PKIX_BUILDUPDATEDATEFAILED);
  1.2411 +    
  1.2412 +                    canBeCached = state->canBeCached;
  1.2413 +                    PKIX_DECREF(validityDate);
  1.2414 +                    PKIX_INCREF(state->validityDate);
  1.2415 +                    validityDate = state->validityDate;
  1.2416 +                    if (trusted == PKIX_TRUE) {
  1.2417 +                            state->status = BUILD_CHECKTRUSTED;
  1.2418 +                    } else {
  1.2419 +                            state->status = BUILD_ADDTOCHAIN;
  1.2420 +                    }
  1.2421 +            }
  1.2422 +
  1.2423 +            if (state->status == BUILD_CHECKTRUSTED) {
  1.2424 +
  1.2425 +                    /*
  1.2426 +                     * If this cert is trusted, try to validate the entire
  1.2427 +                     * chain using this certificate as trust anchor.
  1.2428 +                     */
  1.2429 +                    PKIX_CHECK(PKIX_TrustAnchor_CreateWithCert
  1.2430 +                      (state->candidateCert,
  1.2431 +                      &trustAnchor,
  1.2432 +                      plContext),
  1.2433 +                      PKIX_TRUSTANCHORCREATEWITHCERTFAILED);
  1.2434 +
  1.2435 +                    PKIX_CHECK(pkix_Build_ValidationCheckers
  1.2436 +                      (state,
  1.2437 +                      state->trustChain,
  1.2438 +                      trustAnchor,
  1.2439 +                      PKIX_FALSE, /* do not add eku checker
  1.2440 +                                   * since eku was already
  1.2441 +                                   * checked */
  1.2442 +                      plContext),
  1.2443 +                      PKIX_BUILDVALIDATIONCHECKERSFAILED);
  1.2444 +
  1.2445 +                    state->status = BUILD_CHECKTRUSTED2;
  1.2446 +            }
  1.2447 +
  1.2448 +            if (state->status == BUILD_CHECKTRUSTED2) {
  1.2449 +                    verifyError = 
  1.2450 +                        pkix_Build_ValidateEntireChain(state,
  1.2451 +                                                       trustAnchor,
  1.2452 +                                                       &nbio, &valResult,
  1.2453 +                                                       verifyNode,
  1.2454 +                                                       plContext);
  1.2455 +                    if (nbio != NULL) {
  1.2456 +                            /* IO still pending, resume later */
  1.2457 +                            goto cleanup;
  1.2458 +                    } else {
  1.2459 +                            /* checking the error for fatal status */
  1.2460 +                            if (verifyError) {
  1.2461 +                                pkixTempErrorReceived = PKIX_TRUE;
  1.2462 +                                pkixErrorClass = verifyError->errClass;
  1.2463 +                                if (pkixErrorClass == PKIX_FATAL_ERROR) {
  1.2464 +                                    pkixErrorResult = verifyError;
  1.2465 +                                    verifyError = NULL;
  1.2466 +                                    goto fatal;
  1.2467 +                                }
  1.2468 +                            }
  1.2469 +                            if (state->verifyNode != NULL) {
  1.2470 +                                PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  1.2471 +                                        (state->verifyNode,
  1.2472 +                                        verifyNode,
  1.2473 +                                        plContext),
  1.2474 +                                        PKIX_VERIFYNODEADDTOTREEFAILED);
  1.2475 +                                PKIX_DECREF(verifyNode);
  1.2476 +                            }
  1.2477 +                            if (!PKIX_ERROR_RECEIVED) {
  1.2478 +                                *pValResult = valResult;
  1.2479 +                                valResult = NULL;
  1.2480 +                                /* Change state so IsIOPending is FALSE */
  1.2481 +                                state->status = BUILD_CHECKTRUSTED;
  1.2482 +                                goto cleanup;
  1.2483 +                            }
  1.2484 +                            PKIX_DECREF(finalError);
  1.2485 +                            finalError = verifyError;
  1.2486 +                            verifyError = NULL;
  1.2487 +                            /* Reset temp error that was set by 
  1.2488 +                             * PKIX_CHECK_ONLY_FATAL and continue */
  1.2489 +                            pkixTempErrorReceived = PKIX_FALSE;
  1.2490 +                            PKIX_DECREF(trustAnchor);
  1.2491 +                    }
  1.2492 +
  1.2493 +                    /*
  1.2494 +                     * If chain doesn't validate with a trusted Cert,
  1.2495 +                     * adding more Certs to it can't help.
  1.2496 +                     */
  1.2497 +                    if (state->certLoopingDetected) {
  1.2498 +                            PKIX_DECREF(verifyError);
  1.2499 +                            PKIX_ERROR_CREATE(BUILD, 
  1.2500 +                                         PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED,
  1.2501 +                                         verifyError);
  1.2502 +                            PKIX_CHECK_FATAL(
  1.2503 +                                pkix_VerifyNode_SetError(state->verifyNode,
  1.2504 +                                                         verifyError,
  1.2505 +                                                         plContext),
  1.2506 +                                PKIX_VERIFYNODESETERRORFAILED);
  1.2507 +                            PKIX_DECREF(verifyError);
  1.2508 +                    }
  1.2509 +                    state->status = BUILD_GETNEXTCERT;
  1.2510 +            }
  1.2511 +
  1.2512 +            /*
  1.2513 +             * This Cert was not trusted. Add it to our chain, and
  1.2514 +             * continue building. If we don't reach a trust anchor,
  1.2515 +             * we'll take it off later and continue without it.
  1.2516 +             */
  1.2517 +            if (state->status == BUILD_ADDTOCHAIN) {
  1.2518 +                    PKIX_CHECK(PKIX_List_AppendItem
  1.2519 +                            (state->trustChain,
  1.2520 +                            (PKIX_PL_Object *)state->candidateCert,
  1.2521 +                            plContext),
  1.2522 +                            PKIX_LISTAPPENDITEMFAILED);
  1.2523 +
  1.2524 +                    state->status = BUILD_EXTENDCHAIN;
  1.2525 +            }
  1.2526 +
  1.2527 +            if (state->status == BUILD_EXTENDCHAIN) {
  1.2528 +
  1.2529 +                    /* Check whether we are allowed to extend the chain */
  1.2530 +                    if ((state->buildConstants.maxDepth != 0) &&
  1.2531 +                        (state->numDepth <= 1)) {
  1.2532 +
  1.2533 +                        if (state->verifyNode != NULL) {
  1.2534 +                                PKIX_ERROR_CREATE
  1.2535 +                                    (BUILD,
  1.2536 +                                    PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS,
  1.2537 +                                    verifyError);
  1.2538 +                                PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
  1.2539 +                                    (verifyNode, verifyError, plContext),
  1.2540 +                                    PKIX_VERIFYNODESETERRORFAILED);
  1.2541 +                                PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  1.2542 +                                    (state->verifyNode, verifyNode, plContext),
  1.2543 +                                    PKIX_VERIFYNODEADDTOTREEFAILED);
  1.2544 +                                PKIX_DECREF(verifyNode);
  1.2545 +                                PKIX_DECREF(finalError);
  1.2546 +                                finalError = verifyError;
  1.2547 +                                verifyError = NULL;
  1.2548 +                        }
  1.2549 +                        /* Even if error logged, still need to abort */
  1.2550 +                        PKIX_ERROR(PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS);
  1.2551 +                    }
  1.2552 +
  1.2553 +                    PKIX_CHECK(pkix_IsCertSelfIssued
  1.2554 +                            (state->candidateCert, &isSelfIssued, plContext),
  1.2555 +                            PKIX_ISCERTSELFISSUEDFAILED);
  1.2556 +                 
  1.2557 +                    PKIX_CHECK(PKIX_PL_Object_Duplicate
  1.2558 +                            ((PKIX_PL_Object *)state->traversedSubjNames,
  1.2559 +                            (PKIX_PL_Object **)&childTraversedSubjNames,
  1.2560 +                            plContext),
  1.2561 +                            PKIX_OBJECTDUPLICATEFAILED);
  1.2562 +         
  1.2563 +                    if (isSelfIssued) {
  1.2564 +                            childTraversedCACerts = state->traversedCACerts;
  1.2565 +                    } else {
  1.2566 +                            childTraversedCACerts = state->traversedCACerts + 1;
  1.2567 +                 
  1.2568 +                            PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
  1.2569 +                                (state->candidateCert,
  1.2570 +                                &subjectNames,
  1.2571 +                                plContext),
  1.2572 +                                PKIX_CERTGETALLSUBJECTNAMESFAILED);
  1.2573 +                 
  1.2574 +                            if (subjectNames) {
  1.2575 +                                PKIX_CHECK(PKIX_List_GetLength
  1.2576 +                                    (subjectNames,
  1.2577 +                                    &numSubjectNames,
  1.2578 +                                    plContext),
  1.2579 +                                    PKIX_LISTGETLENGTHFAILED);
  1.2580 +         
  1.2581 +                            } else {
  1.2582 +                                numSubjectNames = 0;
  1.2583 +                            }
  1.2584 +
  1.2585 +                            for (i = 0; i < numSubjectNames; i++) {
  1.2586 +                                PKIX_CHECK(PKIX_List_GetItem
  1.2587 +                                    (subjectNames,
  1.2588 +                                    i,
  1.2589 +                                    &subjectName,
  1.2590 +                                    plContext),
  1.2591 +                                    PKIX_LISTGETITEMFAILED);
  1.2592 +                                PKIX_NULLCHECK_ONE
  1.2593 +                                    (state->traversedSubjNames);
  1.2594 +                                PKIX_CHECK(PKIX_List_AppendItem
  1.2595 +                                    (state->traversedSubjNames,
  1.2596 +                                    subjectName,
  1.2597 +                                    plContext),
  1.2598 +                                    PKIX_LISTAPPENDITEMFAILED);
  1.2599 +                                PKIX_DECREF(subjectName);
  1.2600 +                            }
  1.2601 +                            PKIX_DECREF(subjectNames);
  1.2602 +                        }
  1.2603 +            
  1.2604 +                        PKIX_CHECK(pkix_ForwardBuilderState_Create
  1.2605 +                            (childTraversedCACerts,
  1.2606 +                            state->buildConstants.maxFanout,
  1.2607 +                            state->numDepth - 1,
  1.2608 +                            canBeCached,
  1.2609 +                            validityDate,
  1.2610 +                            state->candidateCert,
  1.2611 +                            childTraversedSubjNames,
  1.2612 +                            state->trustChain,
  1.2613 +                            state,
  1.2614 +                            &childState,
  1.2615 +                            plContext),
  1.2616 +                            PKIX_FORWARDBUILDSTATECREATEFAILED);
  1.2617 +
  1.2618 +                        PKIX_DECREF(childTraversedSubjNames);
  1.2619 +                        PKIX_DECREF(certSelParams);
  1.2620 +                        childState->verifyNode = verifyNode;
  1.2621 +                        verifyNode = NULL;
  1.2622 +                        PKIX_DECREF(state);
  1.2623 +                        state = childState; /* state->status == BUILD_INITIAL */
  1.2624 +                        childState = NULL;
  1.2625 +                        continue; /* with while (!outOfOptions) */
  1.2626 +            }
  1.2627 +
  1.2628 +            if (state->status == BUILD_GETNEXTCERT) {
  1.2629 +                    pkixTempErrorReceived = PKIX_FALSE;
  1.2630 +                    PKIX_DECREF(state->candidateCert);
  1.2631 +
  1.2632 +                    /*
  1.2633 +                     * If we were using a Cert from the callier-supplied partial
  1.2634 +                     * chain, delete it and go to the certStores.
  1.2635 +                     */
  1.2636 +                    if (state->usingHintCerts == PKIX_TRUE) {
  1.2637 +                            PKIX_DECREF(state->candidateCerts);
  1.2638 +                            PKIX_CHECK(PKIX_List_Create
  1.2639 +                                (&state->candidateCerts, plContext),
  1.2640 +                                PKIX_LISTCREATEFAILED);
  1.2641 +
  1.2642 +                            state->numCerts = 0;
  1.2643 +                            state->usingHintCerts = PKIX_FALSE;
  1.2644 +                            state->status = BUILD_TRYAIA;
  1.2645 +                            continue;
  1.2646 +                    } else if (++(state->certIndex) < (state->numCerts)) {
  1.2647 +                            if ((state->buildConstants.maxFanout != 0) &&
  1.2648 +                                (--(state->numFanout) == 0)) {
  1.2649 +
  1.2650 +                                if (state->verifyNode != NULL) {
  1.2651 +                                        PKIX_ERROR_CREATE
  1.2652 +                                            (BUILD,
  1.2653 +                                            PKIX_FANOUTEXCEEDSRESOURCELIMITS,
  1.2654 +                                            verifyError);
  1.2655 +                                        PKIX_CHECK_FATAL
  1.2656 +                                            (pkix_VerifyNode_SetError
  1.2657 +                                            (state->verifyNode,
  1.2658 +                                            verifyError,
  1.2659 +                                            plContext),
  1.2660 +                                            PKIX_VERIFYNODESETERRORFAILED);
  1.2661 +                                        PKIX_DECREF(finalError);
  1.2662 +                                        finalError = verifyError;
  1.2663 +                                        verifyError = NULL;
  1.2664 +                                }
  1.2665 +                                /* Even if error logged, still need to abort */
  1.2666 +                                PKIX_ERROR
  1.2667 +                                        (PKIX_FANOUTEXCEEDSRESOURCELIMITS);
  1.2668 +                            }
  1.2669 +                            state->status = BUILD_CERTVALIDATING;
  1.2670 +                            continue;
  1.2671 +                    }
  1.2672 +            }
  1.2673 +
  1.2674 +            /*
  1.2675 +             * Adding the current cert to the chain didn't help. If our search
  1.2676 +             * has been restricted to local certStores, try opening up the
  1.2677 +             * search and see whether that helps. Otherwise, back up to the
  1.2678 +             * parent cert, and see if there are any more to try.
  1.2679 +             */
  1.2680 +            if (state->useOnlyLocal == PKIX_TRUE) {
  1.2681 +                pkix_PrepareForwardBuilderStateForAIA(state);
  1.2682 +            } else do {
  1.2683 +                if (state->parentState == NULL) {
  1.2684 +                        /* We are at the top level, and can't back up! */
  1.2685 +                        outOfOptions = PKIX_TRUE;
  1.2686 +                } else {
  1.2687 +                        /*
  1.2688 +                         * Try the next cert, if any, for this parent.
  1.2689 +                         * Otherwise keep backing up until we reach a
  1.2690 +                         * parent with more certs to try.
  1.2691 +                         */
  1.2692 +                        PKIX_CHECK(PKIX_List_GetLength
  1.2693 +                                (state->trustChain, &numChained, plContext),
  1.2694 +                                PKIX_LISTGETLENGTHFAILED);
  1.2695 +                        PKIX_CHECK(PKIX_List_DeleteItem
  1.2696 +                                (state->trustChain, numChained - 1, plContext),
  1.2697 +                                PKIX_LISTDELETEITEMFAILED);
  1.2698 +                        
  1.2699 +                        /* local and aia fetching returned no good certs.
  1.2700 +                         * Creating a verify node in the parent that tells
  1.2701 +                         * us this. */
  1.2702 +                        if (!state->verifyNode) {
  1.2703 +                            PKIX_CHECK_FATAL(
  1.2704 +                                pkix_VerifyNode_Create(state->prevCert,
  1.2705 +                                                       0, NULL, 
  1.2706 +                                                       &state->verifyNode,
  1.2707 +                                                       plContext),
  1.2708 +                                PKIX_VERIFYNODECREATEFAILED);
  1.2709 +                        }
  1.2710 +                        /* Updating the log with the error. */
  1.2711 +                        PKIX_DECREF(verifyError);
  1.2712 +                        PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER,
  1.2713 +                                          verifyError);
  1.2714 +                        PKIX_CHECK_FATAL(
  1.2715 +                            pkix_VerifyNode_SetError(state->verifyNode,
  1.2716 +                                                     verifyError,
  1.2717 +                                                     plContext),
  1.2718 +                            PKIX_VERIFYNODESETERRORFAILED);
  1.2719 +                        PKIX_DECREF(verifyError);
  1.2720 +
  1.2721 +                        PKIX_INCREF(state->parentState);
  1.2722 +                        parentState = state->parentState;
  1.2723 +                        PKIX_DECREF(verifyNode);
  1.2724 +                        verifyNode = state->verifyNode;
  1.2725 +                        state->verifyNode = NULL;
  1.2726 +                        PKIX_DECREF(state);
  1.2727 +                        state = parentState;
  1.2728 +                        parentState = NULL;
  1.2729 +                        if (state->verifyNode != NULL && verifyNode) {
  1.2730 +                                PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  1.2731 +                                        (state->verifyNode,
  1.2732 +                                        verifyNode,
  1.2733 +                                        plContext),
  1.2734 +                                        PKIX_VERIFYNODEADDTOTREEFAILED);
  1.2735 +                                PKIX_DECREF(verifyNode);
  1.2736 +                        }
  1.2737 +                        PKIX_DECREF(validityDate);
  1.2738 +                        PKIX_INCREF(state->validityDate);
  1.2739 +                        validityDate = state->validityDate;
  1.2740 +                        canBeCached = state->canBeCached;
  1.2741 +
  1.2742 +                        /* Are there any more Certs to try? */
  1.2743 +                        if (++(state->certIndex) < (state->numCerts)) {
  1.2744 +                                state->status = BUILD_CERTVALIDATING;
  1.2745 +                                PKIX_DECREF(state->candidateCert);
  1.2746 +                                break;
  1.2747 +                        }
  1.2748 +                        if (state->useOnlyLocal == PKIX_TRUE) {
  1.2749 +                            /* Clean up and go for AIA round. */
  1.2750 +                            pkix_PrepareForwardBuilderStateForAIA(state);
  1.2751 +                            break;
  1.2752 +                        }
  1.2753 +                }
  1.2754 +                PKIX_DECREF(state->candidateCert);
  1.2755 +            } while (outOfOptions == PKIX_FALSE);
  1.2756 +
  1.2757 +        } /* while (outOfOptions == PKIX_FALSE) */
  1.2758 +
  1.2759 +cleanup:
  1.2760 +
  1.2761 +        if (pkixErrorClass == PKIX_FATAL_ERROR) {
  1.2762 +            goto fatal;
  1.2763 +        }
  1.2764 +
  1.2765 +        /* verifyNode should be equal to NULL at this point. Assert it.
  1.2766 +         * Temporarelly use verifyError to store an error ref to which we
  1.2767 +         * have in pkixErrorResult. This is done to prevent error cloberring
  1.2768 +         * while using macros below. */
  1.2769 +        PORT_Assert(verifyError == NULL);
  1.2770 +        verifyError = pkixErrorResult;
  1.2771 +
  1.2772 +        /*
  1.2773 +         * We were called with an initialState that had no parent. If we are
  1.2774 +         * returning with an error or with a result, we must destroy any state
  1.2775 +         * that we created (any state with a parent).
  1.2776 +         */
  1.2777 +
  1.2778 +        PKIX_CHECK_FATAL(pkix_ForwardBuilderState_IsIOPending
  1.2779 +                         (state, &ioPending, plContext),
  1.2780 +                PKIX_FORWARDBUILDERSTATEISIOPENDINGFAILED);
  1.2781 +
  1.2782 +        if (ioPending == PKIX_FALSE) {
  1.2783 +                while (state->parentState) {
  1.2784 +                        PKIX_INCREF(state->parentState);
  1.2785 +                        parentState = state->parentState;
  1.2786 +                        PKIX_DECREF(verifyNode);
  1.2787 +                        verifyNode = state->verifyNode;
  1.2788 +                        state->verifyNode = NULL;
  1.2789 +                        PKIX_DECREF(state);
  1.2790 +                        state = parentState;
  1.2791 +                        parentState = NULL;
  1.2792 +                        if (state->verifyNode != NULL && verifyNode) {
  1.2793 +                                PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  1.2794 +                                        (state->verifyNode,
  1.2795 +                                        verifyNode,
  1.2796 +                                        plContext),
  1.2797 +                                        PKIX_VERIFYNODEADDTOTREEFAILED);
  1.2798 +                                PKIX_DECREF(verifyNode);
  1.2799 +                        }
  1.2800 +                }
  1.2801 +                state->canBeCached = canBeCached;
  1.2802 +                PKIX_DECREF(state->validityDate);
  1.2803 +                state->validityDate = validityDate;
  1.2804 +                validityDate = NULL;
  1.2805 +        }
  1.2806 +        if (!*pValResult && !verifyError) {
  1.2807 +            if (!finalError) {
  1.2808 +                PKIX_CHECK_FATAL(
  1.2809 +                    pkix_VerifyNode_FindError(state->verifyNode,
  1.2810 +                                              &finalError,
  1.2811 +                                              plContext),
  1.2812 +                    PKIX_VERIFYNODEFINDERRORFAILED);
  1.2813 +            }
  1.2814 +            if (finalError) {
  1.2815 +                pkixErrorResult = finalError;
  1.2816 +                pkixErrorCode = PKIX_BUILDFORWARDDEPTHFIRSTSEARCHFAILED;
  1.2817 +                finalError = NULL;
  1.2818 +                goto fatal;
  1.2819 +            }
  1.2820 +            pkixErrorCode = PKIX_SECERRORUNKNOWNISSUER;
  1.2821 +            pkixErrorReceived = PKIX_TRUE;
  1.2822 +            PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER,
  1.2823 +                              verifyError);
  1.2824 +            PKIX_CHECK_FATAL(
  1.2825 +                pkix_VerifyNode_SetError(state->verifyNode, verifyError,
  1.2826 +                                         plContext),
  1.2827 +                PKIX_VERIFYNODESETERRORFAILED);
  1.2828 +        } else {
  1.2829 +            pkixErrorResult = verifyError;
  1.2830 +            verifyError = NULL;
  1.2831 +        }
  1.2832 +
  1.2833 +fatal:
  1.2834 +        if (state->parentState) {
  1.2835 +            /* parentState in "state" object should be NULL at this point.
  1.2836 +             * If itn't, that means that we got fatal error(we have jumped to
  1.2837 +             * "fatal" label) and we should destroy all state except the top one. */
  1.2838 +            while (state->parentState) {
  1.2839 +                PKIX_Error *error = NULL;
  1.2840 +                PKIX_ForwardBuilderState *prntState = state->parentState;
  1.2841 +                /* Dumb: need to increment parentState to avoid destruction
  1.2842 +                 * of "build constants"(they get destroyed when parentState is
  1.2843 +                 * set to NULL. */
  1.2844 +                PKIX_INCREF(prntState);
  1.2845 +                error = PKIX_PL_Object_DecRef((PKIX_PL_Object*)state, plContext);
  1.2846 +                if (error) {
  1.2847 +                    PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext);
  1.2848 +                }
  1.2849 +                /* No need to decref the parent state. It was already done by
  1.2850 +                 * pkix_ForwardBuilderState_Destroy function. */
  1.2851 +                state = prntState;
  1.2852 +            }
  1.2853 +        }
  1.2854 +        PKIX_DECREF(parentState);
  1.2855 +        PKIX_DECREF(childState);
  1.2856 +        PKIX_DECREF(valResult);
  1.2857 +        PKIX_DECREF(verifyError);
  1.2858 +        PKIX_DECREF(finalError);
  1.2859 +        PKIX_DECREF(verifyNode);
  1.2860 +        PKIX_DECREF(childTraversedSubjNames);
  1.2861 +        PKIX_DECREF(certSelParams);
  1.2862 +        PKIX_DECREF(subjectNames);
  1.2863 +        PKIX_DECREF(subjectName);
  1.2864 +        PKIX_DECREF(trustAnchor);
  1.2865 +        PKIX_DECREF(validityDate);
  1.2866 +        PKIX_DECREF(revCheckerState);
  1.2867 +        PKIX_DECREF(currTime);
  1.2868 +        PKIX_DECREF(filteredCerts);
  1.2869 +        PKIX_DECREF(unfilteredCerts);
  1.2870 +        PKIX_DECREF(trustedCert);
  1.2871 +
  1.2872 +        PKIX_RETURN(BUILD);
  1.2873 +}
  1.2874 +
  1.2875 +/*
  1.2876 + * FUNCTION: pkix_Build_CheckInCache
  1.2877 + * DESCRIPTION:
  1.2878 + *
  1.2879 + * The function tries to locate a chain for a cert in the cert chain cache.
  1.2880 + * If found, the chain goes through revocation chacking and returned back to
  1.2881 + * caller. Chains that fail revocation check get removed from cache.
  1.2882 + * 
  1.2883 + * PARAMETERS:
  1.2884 + *  "state"
  1.2885 + *      Address of ForwardBuilderState to be used. Must be non-NULL.
  1.2886 + *  "pBuildResult"
  1.2887 + *      Address at which the BuildResult is stored, after a successful build.
  1.2888 + *      Must be non-NULL.
  1.2889 + *  "pNBIOContext"
  1.2890 + *      Address at which the NBIOContext is stored indicating whether the
  1.2891 + *      validation is complete. Must be non-NULL.
  1.2892 + *  "plContext"
  1.2893 + *      Platform-specific context pointer.
  1.2894 + * THREAD SAFETY:
  1.2895 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.2896 + * RETURNS:
  1.2897 + *  Returns NULL if the function succeeds.
  1.2898 + *  Returns a Build Error if the function fails in a non-fatal way
  1.2899 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.2900 + */
  1.2901 +static PKIX_Error*
  1.2902 +pkix_Build_CheckInCache(
  1.2903 +        PKIX_ForwardBuilderState *state,
  1.2904 +        PKIX_BuildResult **pBuildResult,
  1.2905 +        void **pNBIOContext,
  1.2906 +        void *plContext)
  1.2907 +{
  1.2908 +        PKIX_PL_Cert *targetCert = NULL;
  1.2909 +        PKIX_List *anchors = NULL;
  1.2910 +        PKIX_PL_Date *testDate = NULL;
  1.2911 +        PKIX_BuildResult *buildResult = NULL;
  1.2912 +        PKIX_ValidateResult *valResult = NULL;
  1.2913 +        PKIX_Error *buildError = NULL;
  1.2914 +        PKIX_TrustAnchor *matchingAnchor = NULL;
  1.2915 +        PKIX_PL_Cert *trustedCert = NULL;
  1.2916 +        PKIX_List *certList = NULL;
  1.2917 +        PKIX_Boolean cacheHit = PKIX_FALSE;
  1.2918 +        PKIX_Boolean trusted = PKIX_FALSE;
  1.2919 +        PKIX_Boolean stillValid = PKIX_FALSE;
  1.2920 +        void *nbioContext = NULL;
  1.2921 +
  1.2922 +        PKIX_ENTER(BUILD, "pkix_Build_CheckInCache");
  1.2923 +
  1.2924 +        nbioContext = *pNBIOContext;
  1.2925 +        *pNBIOContext = NULL;
  1.2926 +
  1.2927 +        targetCert = state->buildConstants.targetCert;
  1.2928 +        anchors = state->buildConstants.anchors;
  1.2929 +        testDate = state->buildConstants.testDate;
  1.2930 +
  1.2931 +        /* Check whether this cert verification has been cached. */
  1.2932 +        PKIX_CHECK(pkix_CacheCertChain_Lookup
  1.2933 +                   (targetCert,
  1.2934 +                    anchors,
  1.2935 +                    testDate,
  1.2936 +                    &cacheHit,
  1.2937 +                    &buildResult,
  1.2938 +                    plContext),
  1.2939 +                   PKIX_CACHECERTCHAINLOOKUPFAILED);
  1.2940 +        
  1.2941 +        if (!cacheHit) {
  1.2942 +            goto cleanup;
  1.2943 +        }
  1.2944 +        
  1.2945 +        /*
  1.2946 +         * We found something in cache. Verify that the anchor
  1.2947 +         * cert is still trusted,
  1.2948 +         */
  1.2949 +        PKIX_CHECK(PKIX_BuildResult_GetValidateResult
  1.2950 +                   (buildResult, &valResult, plContext),
  1.2951 +                   PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
  1.2952 +        
  1.2953 +        PKIX_CHECK(PKIX_ValidateResult_GetTrustAnchor
  1.2954 +                       (valResult, &matchingAnchor, plContext),
  1.2955 +                   PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
  1.2956 +        
  1.2957 +        PKIX_DECREF(valResult);
  1.2958 +        
  1.2959 +        PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
  1.2960 +                   (matchingAnchor, &trustedCert, plContext),
  1.2961 +                   PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  1.2962 +        
  1.2963 +        if (anchors && state->buildConstants.numAnchors) {
  1.2964 +            /* Check if it is one of the trust anchors */
  1.2965 +            PKIX_CHECK(
  1.2966 +                pkix_List_Contains(anchors,
  1.2967 +                                   (PKIX_PL_Object *)matchingAnchor,
  1.2968 +                                   &trusted,
  1.2969 +                                   plContext),
  1.2970 +                PKIX_LISTCONTAINSFAILED);
  1.2971 +        }
  1.2972 +
  1.2973 +        if ((!trusted && !state->buildConstants.trustOnlyUserAnchors) ||
  1.2974 +            !state->buildConstants.numAnchors) {
  1.2975 +            /* If it is not one of the trust anchors and the trust anchors
  1.2976 +             * are supplemental, or if there are no trust anchors, then check
  1.2977 +             * if the cert is trusted directly.
  1.2978 +             */
  1.2979 +            PKIX_CHECK(
  1.2980 +                PKIX_PL_Cert_IsCertTrusted(trustedCert,
  1.2981 +                                           PKIX_PL_TrustAnchorMode_Ignore,
  1.2982 +                                           &trusted, plContext),
  1.2983 +                PKIX_CERTISCERTTRUSTEDFAILED);
  1.2984 +        }
  1.2985 +
  1.2986 +        if (!trusted) {
  1.2987 +            goto cleanup;
  1.2988 +        }
  1.2989 +        /*
  1.2990 +         * Since the key usage may vary for different
  1.2991 +         * applications, we need to verify the chain again.
  1.2992 +         * Reverification will be improved with a fix for 397805.
  1.2993 +         */
  1.2994 +        PKIX_CHECK(PKIX_BuildResult_GetCertChain
  1.2995 +                   (buildResult, &certList, plContext),
  1.2996 +                   PKIX_BUILDRESULTGETCERTCHAINFAILED);
  1.2997 +        
  1.2998 +        PKIX_CHECK(pkix_Build_ValidationCheckers
  1.2999 +                   (state,
  1.3000 +                    certList,
  1.3001 +                    matchingAnchor,
  1.3002 +                    PKIX_TRUE,  /* Chain revalidation stage. */
  1.3003 +                    plContext),
  1.3004 +                   PKIX_BUILDVALIDATIONCHECKERSFAILED);
  1.3005 +
  1.3006 +        PKIX_CHECK_ONLY_FATAL(
  1.3007 +            pkix_Build_ValidateEntireChain(state, matchingAnchor,
  1.3008 +                                           &nbioContext, &valResult,
  1.3009 +                                           state->verifyNode, plContext),
  1.3010 +            PKIX_BUILDVALIDATEENTIRECHAINFAILED);
  1.3011 +
  1.3012 +        if (nbioContext != NULL) {
  1.3013 +            /* IO still pending, resume later */
  1.3014 +            *pNBIOContext = nbioContext;
  1.3015 +            goto cleanup;
  1.3016 +        }
  1.3017 +        if (!PKIX_ERROR_RECEIVED) {
  1.3018 +            /* The result from cache is still valid. But we replace an old*/
  1.3019 +            *pBuildResult = buildResult;
  1.3020 +            buildResult = NULL;
  1.3021 +            stillValid = PKIX_TRUE;
  1.3022 +        }
  1.3023 +
  1.3024 +cleanup:
  1.3025 +
  1.3026 +        if (!nbioContext && cacheHit && !(trusted && stillValid)) {
  1.3027 +            /* The anchor of this chain is no longer trusted or
  1.3028 +             * chain cert(s) has been revoked.
  1.3029 +             * Invalidate this result in the cache */
  1.3030 +            buildError = pkixErrorResult;
  1.3031 +            PKIX_CHECK_FATAL(pkix_CacheCertChain_Remove
  1.3032 +                       (targetCert,
  1.3033 +                        anchors,
  1.3034 +                        plContext),
  1.3035 +                       PKIX_CACHECERTCHAINREMOVEFAILED);
  1.3036 +            pkixErrorResult = buildError;
  1.3037 +            buildError = NULL;
  1.3038 +        }
  1.3039 +
  1.3040 +fatal:
  1.3041 +       PKIX_DECREF(buildResult);
  1.3042 +       PKIX_DECREF(valResult);
  1.3043 +       PKIX_DECREF(buildError);
  1.3044 +       PKIX_DECREF(certList);
  1.3045 +       PKIX_DECREF(matchingAnchor);
  1.3046 +       PKIX_DECREF(trustedCert);
  1.3047 +
  1.3048 +       
  1.3049 +       PKIX_RETURN(BUILD);
  1.3050 +}
  1.3051 +
  1.3052 +/*
  1.3053 + * FUNCTION: pkix_Build_InitiateBuildChain
  1.3054 + * DESCRIPTION:
  1.3055 + *
  1.3056 + *  This function initiates the search for a BuildChain, using the parameters
  1.3057 + *  provided in "procParams" and, if continuing a search that was suspended
  1.3058 + *  for I/O, using the ForwardBuilderState pointed to by "pState".
  1.3059 + *
  1.3060 + *  If a successful chain is built, this function stores the BuildResult at
  1.3061 + *  "pBuildResult". Alternatively, if an operation using non-blocking I/O
  1.3062 + *  is in progress and the operation has not been completed, this function
  1.3063 + *  stores the platform-dependent non-blocking I/O context (nbioContext) at
  1.3064 + *  "pNBIOContext", the FowardBuilderState at "pState", and NULL at
  1.3065 + *  "pBuildResult". Finally, if chain building was unsuccessful, this function
  1.3066 + *  stores NULL at both "pState" and at "pBuildResult".
  1.3067 + *
  1.3068 + *  Note: This function is re-entered only for the case of non-blocking I/O
  1.3069 + *  in the "short-cut" attempt to build a chain using the target Certificate
  1.3070 + *  directly with one of the trustAnchors. For all other cases, resumption
  1.3071 + *  after non-blocking I/O is via pkix_Build_ResumeBuildChain.
  1.3072 + *
  1.3073 + * PARAMETERS:
  1.3074 + *  "procParams"
  1.3075 + *      Address of the ProcessingParams for the search. Must be non-NULL.
  1.3076 + *  "pNBIOContext"
  1.3077 + *      Address at which the NBIOContext is stored indicating whether the
  1.3078 + *      validation is complete. Must be non-NULL.
  1.3079 + *  "pState"
  1.3080 + *      Address at which the ForwardBuilderState is stored, if the chain
  1.3081 + *      building is suspended for waiting I/O; also, the address at which the
  1.3082 + *      ForwardBuilderState is provided for resumption of the chain building
  1.3083 + *      attempt. Must be non-NULL.
  1.3084 + *  "pBuildResult"
  1.3085 + *      Address at which the BuildResult is stored, after a successful build.
  1.3086 + *      Must be non-NULL.
  1.3087 + *  "pVerifyNode"
  1.3088 + *      Address at which a VerifyNode chain is returned, if non-NULL.
  1.3089 + *  "plContext"
  1.3090 + *      Platform-specific context pointer.
  1.3091 + * THREAD SAFETY:
  1.3092 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.3093 + * RETURNS:
  1.3094 + *  Returns NULL if the function succeeds.
  1.3095 + *  Returns a Build Error if the function fails in a non-fatal way
  1.3096 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.3097 + */
  1.3098 +static PKIX_Error *
  1.3099 +pkix_Build_InitiateBuildChain(
  1.3100 +        PKIX_ProcessingParams *procParams,
  1.3101 +        void **pNBIOContext,
  1.3102 +        PKIX_ForwardBuilderState **pState,
  1.3103 +        PKIX_BuildResult **pBuildResult,
  1.3104 +        PKIX_VerifyNode **pVerifyNode,
  1.3105 +        void *plContext)
  1.3106 +{
  1.3107 +        PKIX_UInt32 numAnchors = 0;
  1.3108 +        PKIX_UInt32 numCertStores = 0;
  1.3109 +        PKIX_UInt32 numHintCerts = 0;
  1.3110 +        PKIX_UInt32 i = 0;
  1.3111 +        PKIX_Boolean isDuplicate = PKIX_FALSE;
  1.3112 +        PKIX_PL_Cert *trustedCert = NULL;
  1.3113 +        PKIX_CertSelector *targetConstraints = NULL;
  1.3114 +        PKIX_ComCertSelParams *targetParams = NULL;
  1.3115 +        PKIX_List *anchors = NULL;
  1.3116 +        PKIX_List *targetSubjNames = NULL;
  1.3117 +        PKIX_PL_Cert *targetCert = NULL;
  1.3118 +        PKIX_PL_Object *firstHintCert = NULL;
  1.3119 +        PKIX_RevocationChecker *revChecker = NULL;
  1.3120 +        PKIX_List *certStores = NULL;
  1.3121 +        PKIX_CertStore *certStore = NULL;
  1.3122 +        PKIX_List *userCheckers = NULL;
  1.3123 +        PKIX_List *hintCerts = NULL;
  1.3124 +        PKIX_PL_Date *testDate = NULL;
  1.3125 +        PKIX_PL_PublicKey *targetPubKey = NULL;
  1.3126 +        void *nbioContext = NULL;
  1.3127 +        BuildConstants buildConstants;
  1.3128 +
  1.3129 +        PKIX_List *tentativeChain = NULL;
  1.3130 +        PKIX_ValidateResult *valResult = NULL;
  1.3131 +        PKIX_BuildResult *buildResult = NULL;
  1.3132 +        PKIX_List *certList = NULL;
  1.3133 +        PKIX_ForwardBuilderState *state = NULL;
  1.3134 +        PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
  1.3135 +        PKIX_CertSelector_MatchCallback selectorCallback = NULL;
  1.3136 +        PKIX_Boolean trusted = PKIX_FALSE;
  1.3137 +        PKIX_PL_AIAMgr *aiaMgr = NULL;
  1.3138 +
  1.3139 +        PKIX_ENTER(BUILD, "pkix_Build_InitiateBuildChain");
  1.3140 +        PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult);
  1.3141 +
  1.3142 +        nbioContext = *pNBIOContext;
  1.3143 +        *pNBIOContext = NULL;
  1.3144 +
  1.3145 +        state = *pState;
  1.3146 +        *pState = NULL; /* no net change in reference count */
  1.3147 +
  1.3148 +        if (state == NULL) {
  1.3149 +            PKIX_CHECK(PKIX_ProcessingParams_GetDate
  1.3150 +                    (procParams, &testDate, plContext),
  1.3151 +                    PKIX_PROCESSINGPARAMSGETDATEFAILED);
  1.3152 +    
  1.3153 +            PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
  1.3154 +                    (procParams, &anchors, plContext),
  1.3155 +                    PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);
  1.3156 +    
  1.3157 +            PKIX_CHECK(PKIX_List_GetLength(anchors, &numAnchors, plContext),
  1.3158 +                    PKIX_LISTGETLENGTHFAILED);
  1.3159 +    
  1.3160 +            /* retrieve stuff from targetCertConstraints */
  1.3161 +            PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
  1.3162 +                       (procParams, &targetConstraints, plContext),
  1.3163 +                       PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
  1.3164 +    
  1.3165 +            PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
  1.3166 +                    (targetConstraints, &targetParams, plContext),
  1.3167 +                    PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
  1.3168 +    
  1.3169 +            PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate
  1.3170 +                    (targetParams, &targetCert, plContext),
  1.3171 +                    PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED);
  1.3172 +    
  1.3173 +            PKIX_CHECK(
  1.3174 +                PKIX_ComCertSelParams_SetLeafCertFlag(targetParams,
  1.3175 +                                                      PKIX_TRUE, plContext),
  1.3176 +                PKIX_COMCERTSELPARAMSSETLEAFCERTFLAGFAILED);
  1.3177 +
  1.3178 +            PKIX_CHECK(PKIX_ProcessingParams_GetHintCerts
  1.3179 +                        (procParams, &hintCerts, plContext),
  1.3180 +                        PKIX_PROCESSINGPARAMSGETHINTCERTSFAILED);
  1.3181 +    
  1.3182 +            if (hintCerts != NULL) {
  1.3183 +                    PKIX_CHECK(PKIX_List_GetLength
  1.3184 +                            (hintCerts, &numHintCerts, plContext),
  1.3185 +                            PKIX_LISTGETLENGTHFAILED);
  1.3186 +            }
  1.3187 +
  1.3188 +            /*
  1.3189 +             * Caller must provide either a target Cert
  1.3190 +             * (in ComCertSelParams->Certificate) or a partial Cert
  1.3191 +             * chain (in ProcParams->HintCerts).
  1.3192 +             */
  1.3193 +
  1.3194 +            if (targetCert == NULL) {
  1.3195 +
  1.3196 +                    /* Use first cert of hintCerts as the targetCert */
  1.3197 +                    if (numHintCerts == 0) {
  1.3198 +                            PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED);
  1.3199 +                    }
  1.3200 +
  1.3201 +                    PKIX_CHECK(PKIX_List_GetItem
  1.3202 +                            (hintCerts,
  1.3203 +                            0,
  1.3204 +                            (PKIX_PL_Object **)&targetCert,
  1.3205 +                            plContext),
  1.3206 +                            PKIX_LISTGETITEMFAILED);
  1.3207 +
  1.3208 +                    PKIX_CHECK(PKIX_List_DeleteItem(hintCerts, 0, plContext),
  1.3209 +                            PKIX_LISTGETITEMFAILED);
  1.3210 +            } else {
  1.3211 +
  1.3212 +                    /*
  1.3213 +                     * If the first hintCert is the same as the targetCert,
  1.3214 +                     * delete it from hintCerts.
  1.3215 +                     */ 
  1.3216 +                    if (numHintCerts != 0) {
  1.3217 +                            PKIX_CHECK(PKIX_List_GetItem
  1.3218 +                                    (hintCerts, 0, &firstHintCert, plContext),
  1.3219 +                                    PKIX_LISTGETITEMFAILED);
  1.3220 +
  1.3221 +                            PKIX_CHECK(PKIX_PL_Object_Equals
  1.3222 +                                    ((PKIX_PL_Object *)targetCert,
  1.3223 +                                    firstHintCert,
  1.3224 +                                    &isDuplicate,
  1.3225 +                                    plContext),
  1.3226 +                                    PKIX_OBJECTEQUALSFAILED);
  1.3227 +
  1.3228 +                            if (isDuplicate) {
  1.3229 +                                    PKIX_CHECK(PKIX_List_DeleteItem
  1.3230 +                                    (hintCerts, 0, plContext),
  1.3231 +                                    PKIX_LISTGETITEMFAILED);
  1.3232 +                            }
  1.3233 +                            PKIX_DECREF(firstHintCert);
  1.3234 +                    }
  1.3235 +
  1.3236 +            }
  1.3237 +
  1.3238 +            if (targetCert == NULL) {
  1.3239 +                PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED);
  1.3240 +            }
  1.3241 +
  1.3242 +            PKIX_CHECK(PKIX_PL_Cert_IsLeafCertTrusted
  1.3243 +                    (targetCert,
  1.3244 +                    &trusted, 
  1.3245 +                    plContext),
  1.3246 +                    PKIX_CERTISCERTTRUSTEDFAILED);
  1.3247 +
  1.3248 +            PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
  1.3249 +                    (targetCert,
  1.3250 +                    &targetSubjNames,
  1.3251 +                    plContext),
  1.3252 +                    PKIX_CERTGETALLSUBJECTNAMESFAILED);
  1.3253 +    
  1.3254 +            PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
  1.3255 +                    (targetCert, &targetPubKey, plContext),
  1.3256 +                    PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
  1.3257 +    
  1.3258 +            PKIX_CHECK(PKIX_List_Create(&tentativeChain, plContext),
  1.3259 +                    PKIX_LISTCREATEFAILED);
  1.3260 +    
  1.3261 +            PKIX_CHECK(PKIX_List_AppendItem
  1.3262 +                    (tentativeChain, (PKIX_PL_Object *)targetCert, plContext),
  1.3263 +                    PKIX_LISTAPPENDITEMFAILED);
  1.3264 +    
  1.3265 +            if (procParams->qualifyTargetCert) {
  1.3266 +                /* EE cert validation */
  1.3267 +                /* Sync up the time on the target selector parameter struct. */
  1.3268 +                PKIX_CHECK(
  1.3269 +                    PKIX_ComCertSelParams_SetCertificateValid(targetParams,
  1.3270 +                                                              testDate,
  1.3271 +                                                              plContext),
  1.3272 +                    PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED);
  1.3273 +                
  1.3274 +                PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
  1.3275 +                           (targetConstraints, &selectorCallback, plContext),
  1.3276 +                           PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
  1.3277 +                
  1.3278 +                pkixErrorResult =
  1.3279 +                    (*selectorCallback)(targetConstraints, targetCert,
  1.3280 +                                        plContext);
  1.3281 +                if (pkixErrorResult) {
  1.3282 +                    pkixErrorClass = pkixErrorResult->errClass;
  1.3283 +                    if (pkixErrorClass == PKIX_FATAL_ERROR) {
  1.3284 +                        goto cleanup;
  1.3285 +                    }
  1.3286 +                    if (pVerifyNode != NULL) {
  1.3287 +                            PKIX_Error *tempResult =
  1.3288 +                                pkix_VerifyNode_Create(targetCert, 0,
  1.3289 +                                                       pkixErrorResult,
  1.3290 +                                                       pVerifyNode,
  1.3291 +                                                       plContext);
  1.3292 +                            if (tempResult) {
  1.3293 +                                PKIX_DECREF(pkixErrorResult);
  1.3294 +                                pkixErrorResult = tempResult;
  1.3295 +                                pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
  1.3296 +                                pkixErrorClass = PKIX_FATAL_ERROR;
  1.3297 +                                goto cleanup;
  1.3298 +                            }
  1.3299 +                    }
  1.3300 +                    pkixErrorCode = PKIX_CERTCHECKVALIDITYFAILED;
  1.3301 +                    goto cleanup;
  1.3302 +                }
  1.3303 +            }
  1.3304 +
  1.3305 +            /* If the EE cert is trusted, force success. We only want to do
  1.3306 +             * this if we aren't validating against a policy (like EV). */
  1.3307 +            if (trusted && procParams->initialPolicies == NULL) {
  1.3308 +                if (pVerifyNode != NULL) {
  1.3309 +                    PKIX_Error *tempResult =
  1.3310 +                        pkix_VerifyNode_Create(targetCert, 0, NULL,
  1.3311 +                                               pVerifyNode,
  1.3312 +                                               plContext);
  1.3313 +                    if (tempResult) {
  1.3314 +                        pkixErrorResult = tempResult;
  1.3315 +                        pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
  1.3316 +                        pkixErrorClass = PKIX_FATAL_ERROR;
  1.3317 +                        goto cleanup;
  1.3318 +                    }
  1.3319 +                }
  1.3320 +                PKIX_CHECK(pkix_ValidateResult_Create
  1.3321 +                        (targetPubKey, NULL /* anchor */,
  1.3322 +                         NULL /* policyTree */, &valResult, plContext),
  1.3323 +                        PKIX_VALIDATERESULTCREATEFAILED);
  1.3324 +                PKIX_CHECK(
  1.3325 +                    pkix_BuildResult_Create(valResult, tentativeChain,
  1.3326 +                                            &buildResult, plContext),
  1.3327 +                    PKIX_BUILDRESULTCREATEFAILED);
  1.3328 +                *pBuildResult = buildResult;
  1.3329 +                /* Note that *pState is NULL.   The only side effect is that
  1.3330 +                 * the cert chain won't be cached in PKIX_BuildChain, which
  1.3331 +                 * is fine. */
  1.3332 +                goto cleanup;
  1.3333 +            }
  1.3334 +    
  1.3335 +            PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
  1.3336 +                    (procParams, &certStores, plContext),
  1.3337 +                    PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
  1.3338 +    
  1.3339 +            PKIX_CHECK(PKIX_List_GetLength
  1.3340 +                    (certStores, &numCertStores, plContext),
  1.3341 +                    PKIX_LISTGETLENGTHFAILED);
  1.3342 +    
  1.3343 +            /* Reorder CertStores so trusted are at front of the List */
  1.3344 +            if (numCertStores > 1) {
  1.3345 +                for (i = numCertStores - 1; i > 0; i--) {
  1.3346 +                    PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem
  1.3347 +                        (certStores,
  1.3348 +                        i,
  1.3349 +                        (PKIX_PL_Object **)&certStore,
  1.3350 +                        plContext),
  1.3351 +                        PKIX_LISTGETITEMFAILED);
  1.3352 +                    PKIX_CHECK_ONLY_FATAL(PKIX_CertStore_GetTrustCallback
  1.3353 +                        (certStore, &trustCallback, plContext),
  1.3354 +                        PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
  1.3355 +    
  1.3356 +                    if (trustCallback != NULL) {
  1.3357 +                        /* Is a trusted Cert, move CertStore to front */
  1.3358 +                        PKIX_CHECK(PKIX_List_DeleteItem
  1.3359 +                            (certStores, i, plContext),
  1.3360 +                            PKIX_LISTDELETEITEMFAILED);
  1.3361 +                        PKIX_CHECK(PKIX_List_InsertItem
  1.3362 +                            (certStores,
  1.3363 +                            0,
  1.3364 +                            (PKIX_PL_Object *)certStore,
  1.3365 +                            plContext),
  1.3366 +                        PKIX_LISTINSERTITEMFAILED);
  1.3367 +    
  1.3368 +                    }
  1.3369 +    
  1.3370 +                    PKIX_DECREF(certStore);
  1.3371 +                }
  1.3372 +            }
  1.3373 +    
  1.3374 +            PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
  1.3375 +                        (procParams, &userCheckers, plContext),
  1.3376 +                        PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
  1.3377 +    
  1.3378 +            PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
  1.3379 +                        (procParams, &revChecker, plContext),
  1.3380 +                       PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
  1.3381 +            /* Do not initialize AIA manager if we are not going to fetch
  1.3382 +             * cert using aia url. */
  1.3383 +            if (procParams->useAIAForCertFetching) {
  1.3384 +                PKIX_CHECK(PKIX_PL_AIAMgr_Create(&aiaMgr, plContext),
  1.3385 +                           PKIX_AIAMGRCREATEFAILED);
  1.3386 +            }
  1.3387 +
  1.3388 +            /*
  1.3389 +             * We initialize all the fields of buildConstants here, in one place,
  1.3390 +             * just to help keep track and ensure that we got everything.
  1.3391 +             */
  1.3392 +    
  1.3393 +            buildConstants.numAnchors = numAnchors;
  1.3394 +            buildConstants.numCertStores = numCertStores;
  1.3395 +            buildConstants.numHintCerts = numHintCerts;
  1.3396 +            buildConstants.procParams = procParams;
  1.3397 +            buildConstants.testDate = testDate;
  1.3398 +            buildConstants.timeLimit = NULL;
  1.3399 +            buildConstants.targetCert = targetCert;
  1.3400 +            buildConstants.targetPubKey = targetPubKey;
  1.3401 +            buildConstants.certStores = certStores;
  1.3402 +            buildConstants.anchors = anchors;
  1.3403 +            buildConstants.userCheckers = userCheckers;
  1.3404 +            buildConstants.hintCerts = hintCerts;
  1.3405 +            buildConstants.revChecker = revChecker;
  1.3406 +            buildConstants.aiaMgr = aiaMgr;
  1.3407 +            buildConstants.trustOnlyUserAnchors =
  1.3408 +                    procParams->useOnlyTrustAnchors;
  1.3409 +
  1.3410 +            PKIX_CHECK(pkix_Build_GetResourceLimits(&buildConstants, plContext),
  1.3411 +                    PKIX_BUILDGETRESOURCELIMITSFAILED);
  1.3412 +    
  1.3413 +            PKIX_CHECK(pkix_ForwardBuilderState_Create
  1.3414 +                    (0,              /* PKIX_UInt32 traversedCACerts */
  1.3415 +                    buildConstants.maxFanout,
  1.3416 +                    buildConstants.maxDepth,
  1.3417 +                    PKIX_TRUE,       /* PKIX_Boolean canBeCached */
  1.3418 +                    NULL,            /* PKIX_Date *validityDate */
  1.3419 +                    targetCert,      /* PKIX_PL_Cert *prevCert */
  1.3420 +                    targetSubjNames, /* PKIX_List *traversedSubjNames */
  1.3421 +                    tentativeChain,  /* PKIX_List *trustChain */
  1.3422 +                    NULL,            /* PKIX_ForwardBuilderState *parent */
  1.3423 +                    &state,          /* PKIX_ForwardBuilderState **pState */
  1.3424 +                    plContext),
  1.3425 +                    PKIX_BUILDSTATECREATEFAILED);
  1.3426 +    
  1.3427 +            state->buildConstants.numAnchors = buildConstants.numAnchors;
  1.3428 +            state->buildConstants.numCertStores = buildConstants.numCertStores; 
  1.3429 +            state->buildConstants.numHintCerts = buildConstants.numHintCerts;
  1.3430 +            state->buildConstants.maxFanout = buildConstants.maxFanout;
  1.3431 +            state->buildConstants.maxDepth = buildConstants.maxDepth;
  1.3432 +            state->buildConstants.maxTime = buildConstants.maxTime;
  1.3433 +            state->buildConstants.procParams = buildConstants.procParams; 
  1.3434 +            PKIX_INCREF(buildConstants.testDate);
  1.3435 +            state->buildConstants.testDate = buildConstants.testDate;
  1.3436 +            state->buildConstants.timeLimit = buildConstants.timeLimit;
  1.3437 +            PKIX_INCREF(buildConstants.targetCert);
  1.3438 +            state->buildConstants.targetCert = buildConstants.targetCert;
  1.3439 +            PKIX_INCREF(buildConstants.targetPubKey);
  1.3440 +            state->buildConstants.targetPubKey =
  1.3441 +                    buildConstants.targetPubKey;
  1.3442 +            PKIX_INCREF(buildConstants.certStores);
  1.3443 +            state->buildConstants.certStores = buildConstants.certStores;
  1.3444 +            PKIX_INCREF(buildConstants.anchors);
  1.3445 +            state->buildConstants.anchors = buildConstants.anchors;
  1.3446 +            PKIX_INCREF(buildConstants.userCheckers);
  1.3447 +            state->buildConstants.userCheckers =
  1.3448 +                    buildConstants.userCheckers;
  1.3449 +            PKIX_INCREF(buildConstants.hintCerts);
  1.3450 +            state->buildConstants.hintCerts = buildConstants.hintCerts;
  1.3451 +            PKIX_INCREF(buildConstants.revChecker);
  1.3452 +            state->buildConstants.revChecker = buildConstants.revChecker;
  1.3453 +            state->buildConstants.aiaMgr = buildConstants.aiaMgr;
  1.3454 +            aiaMgr = NULL;
  1.3455 +            state->buildConstants.trustOnlyUserAnchors =
  1.3456 +                    buildConstants.trustOnlyUserAnchors;
  1.3457 +
  1.3458 +            if (buildConstants.maxTime != 0) {
  1.3459 +                    PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
  1.3460 +                            (buildConstants.maxTime,
  1.3461 +                            &state->buildConstants.timeLimit,
  1.3462 +                            plContext),
  1.3463 +                            PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
  1.3464 +            }
  1.3465 +
  1.3466 +            if (pVerifyNode != NULL) {
  1.3467 +                PKIX_Error *tempResult =
  1.3468 +                    pkix_VerifyNode_Create(targetCert, 0, NULL,
  1.3469 +                                           &(state->verifyNode),
  1.3470 +                                           plContext);
  1.3471 +                if (tempResult) {
  1.3472 +                    pkixErrorResult = tempResult;
  1.3473 +                    pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
  1.3474 +                    pkixErrorClass = PKIX_FATAL_ERROR;
  1.3475 +                    goto cleanup;
  1.3476 +                }
  1.3477 +            }
  1.3478 +
  1.3479 +            PKIX_CHECK_ONLY_FATAL(
  1.3480 +                pkix_Build_CheckInCache(state, &buildResult,
  1.3481 +                                        &nbioContext, plContext),
  1.3482 +                PKIX_UNABLETOBUILDCHAIN);
  1.3483 +            if (nbioContext) {
  1.3484 +                *pNBIOContext = nbioContext;
  1.3485 +                *pState = state;
  1.3486 +                state = NULL;
  1.3487 +                goto cleanup;
  1.3488 +            }
  1.3489 +            if (buildResult) {
  1.3490 +                *pBuildResult = buildResult;
  1.3491 +                if (pVerifyNode != NULL) {
  1.3492 +                    *pVerifyNode = state->verifyNode;
  1.3493 +                    state->verifyNode = NULL;
  1.3494 +                }
  1.3495 +                goto cleanup;
  1.3496 +            }
  1.3497 +        }
  1.3498 +
  1.3499 +        /* If we're resuming after non-blocking I/O we need to get SubjNames */
  1.3500 +        if (targetSubjNames == NULL) {
  1.3501 +            PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
  1.3502 +                    (state->buildConstants.targetCert,
  1.3503 +                    &targetSubjNames,
  1.3504 +                    plContext),
  1.3505 +                    PKIX_CERTGETALLSUBJECTNAMESFAILED);
  1.3506 +        }
  1.3507 +
  1.3508 +        state->status = BUILD_INITIAL;
  1.3509 +
  1.3510 +        pkixErrorResult =
  1.3511 +            pkix_BuildForwardDepthFirstSearch(&nbioContext, state,
  1.3512 +                                              &valResult, plContext);
  1.3513 +
  1.3514 +        /* non-null nbioContext means the build would block */
  1.3515 +        if (pkixErrorResult == NULL && nbioContext != NULL) {
  1.3516 +
  1.3517 +                *pNBIOContext = nbioContext;
  1.3518 +                *pBuildResult = NULL;
  1.3519 +
  1.3520 +        /* no valResult means the build has failed */
  1.3521 +        } else {
  1.3522 +                if (pVerifyNode != NULL) {
  1.3523 +                        PKIX_INCREF(state->verifyNode);
  1.3524 +                        *pVerifyNode = state->verifyNode;
  1.3525 +                }
  1.3526 +
  1.3527 +                if (valResult == NULL || pkixErrorResult)
  1.3528 +                        PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
  1.3529 +                PKIX_CHECK(
  1.3530 +                    pkix_BuildResult_Create(valResult, state->trustChain,
  1.3531 +                                            &buildResult, plContext),
  1.3532 +                    PKIX_BUILDRESULTCREATEFAILED);
  1.3533 +                *pBuildResult = buildResult;
  1.3534 +        }
  1.3535 +
  1.3536 +        *pState = state;
  1.3537 +        state = NULL;
  1.3538 +
  1.3539 +cleanup:
  1.3540 +
  1.3541 +        PKIX_DECREF(targetConstraints);
  1.3542 +        PKIX_DECREF(targetParams);
  1.3543 +        PKIX_DECREF(anchors);
  1.3544 +        PKIX_DECREF(targetSubjNames);
  1.3545 +        PKIX_DECREF(targetCert);
  1.3546 +        PKIX_DECREF(revChecker);
  1.3547 +        PKIX_DECREF(certStores);
  1.3548 +        PKIX_DECREF(certStore);
  1.3549 +        PKIX_DECREF(userCheckers);
  1.3550 +        PKIX_DECREF(hintCerts);
  1.3551 +        PKIX_DECREF(firstHintCert);
  1.3552 +        PKIX_DECREF(testDate);
  1.3553 +        PKIX_DECREF(targetPubKey);
  1.3554 +        PKIX_DECREF(tentativeChain);
  1.3555 +        PKIX_DECREF(valResult);
  1.3556 +        PKIX_DECREF(certList);
  1.3557 +        PKIX_DECREF(trustedCert);
  1.3558 +        PKIX_DECREF(state);
  1.3559 +        PKIX_DECREF(aiaMgr);
  1.3560 +
  1.3561 +        PKIX_RETURN(BUILD);
  1.3562 +}
  1.3563 +
  1.3564 +/*
  1.3565 + * FUNCTION: pkix_Build_ResumeBuildChain
  1.3566 + * DESCRIPTION:
  1.3567 + *
  1.3568 + *  This function continues the search for a BuildChain, using the parameters
  1.3569 + *  provided in "procParams" and the ForwardBuilderState pointed to by "state".
  1.3570 + *
  1.3571 + *  If a successful chain is built, this function stores the BuildResult at
  1.3572 + *  "pBuildResult". Alternatively, if an operation using non-blocking I/O
  1.3573 + *  is in progress and the operation has not been completed, this function
  1.3574 + *  stores the FowardBuilderState at "pState" and NULL at "pBuildResult".
  1.3575 + *  Finally, if chain building was unsuccessful, this function stores NULL
  1.3576 + *  at both "pState" and at "pBuildResult".
  1.3577 + *
  1.3578 + * PARAMETERS:
  1.3579 + *  "pNBIOContext"
  1.3580 + *      Address at which the NBIOContext is stored indicating whether the
  1.3581 + *      validation is complete. Must be non-NULL.
  1.3582 + *  "pState"
  1.3583 + *     Address at which the ForwardBuilderState is provided for resumption of
  1.3584 + *     the chain building attempt; also, the address at which the
  1.3585 + *     ForwardBuilderStateis stored, if the chain building is suspended for
  1.3586 + *     waiting I/O. Must be non-NULL.
  1.3587 + *  "pBuildResult"
  1.3588 + *      Address at which the BuildResult is stored, after a successful build.
  1.3589 + *      Must be non-NULL.
  1.3590 + *  "plContext"
  1.3591 + *      Platform-specific context pointer.
  1.3592 + * THREAD SAFETY:
  1.3593 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.3594 + * RETURNS:
  1.3595 + *  Returns NULL if the function succeeds.
  1.3596 + *  Returns a Build Error if the function fails in a non-fatal way
  1.3597 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.3598 + */
  1.3599 +static PKIX_Error *
  1.3600 +pkix_Build_ResumeBuildChain(
  1.3601 +        void **pNBIOContext,
  1.3602 +        PKIX_ForwardBuilderState *state,
  1.3603 +        PKIX_BuildResult **pBuildResult,
  1.3604 +        PKIX_VerifyNode **pVerifyNode,
  1.3605 +        void *plContext)
  1.3606 +{
  1.3607 +        PKIX_ValidateResult *valResult = NULL;
  1.3608 +        PKIX_BuildResult *buildResult = NULL;
  1.3609 +        void *nbioContext = NULL;
  1.3610 +
  1.3611 +        PKIX_ENTER(BUILD, "pkix_Build_ResumeBuildChain");
  1.3612 +        PKIX_NULLCHECK_TWO(state, pBuildResult);
  1.3613 +
  1.3614 +        nbioContext = *pNBIOContext;
  1.3615 +        *pNBIOContext = NULL;
  1.3616 +
  1.3617 +        pkixErrorResult =
  1.3618 +            pkix_BuildForwardDepthFirstSearch(&nbioContext, state,
  1.3619 +                                              &valResult, plContext);
  1.3620 +
  1.3621 +        /* non-null nbioContext means the build would block */
  1.3622 +        if (pkixErrorResult == NULL && nbioContext != NULL) {
  1.3623 +
  1.3624 +                *pNBIOContext = nbioContext;
  1.3625 +                *pBuildResult = NULL;
  1.3626 +
  1.3627 +        /* no valResult means the build has failed */
  1.3628 +        } else {
  1.3629 +                if (pVerifyNode != NULL) {
  1.3630 +                    PKIX_INCREF(state->verifyNode);
  1.3631 +                    *pVerifyNode = state->verifyNode;
  1.3632 +                }
  1.3633 +
  1.3634 +                if (valResult == NULL || pkixErrorResult)
  1.3635 +                    PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
  1.3636 +
  1.3637 +                PKIX_CHECK(
  1.3638 +                    pkix_BuildResult_Create(valResult, state->trustChain,
  1.3639 +                                            &buildResult, plContext),
  1.3640 +                    PKIX_BUILDRESULTCREATEFAILED);
  1.3641 +                *pBuildResult = buildResult;
  1.3642 +        }
  1.3643 +
  1.3644 +cleanup:
  1.3645 +
  1.3646 +        PKIX_DECREF(valResult);
  1.3647 +
  1.3648 +        PKIX_RETURN(BUILD);
  1.3649 +}
  1.3650 +
  1.3651 +/* --Public-Functions--------------------------------------------- */
  1.3652 +
  1.3653 +/*
  1.3654 + * FUNCTION: PKIX_BuildChain (see comments in pkix.h)
  1.3655 + */
  1.3656 +PKIX_Error *
  1.3657 +PKIX_BuildChain(
  1.3658 +        PKIX_ProcessingParams *procParams,
  1.3659 +        void **pNBIOContext,
  1.3660 +        void **pState,
  1.3661 +        PKIX_BuildResult **pBuildResult,
  1.3662 +        PKIX_VerifyNode **pVerifyNode,
  1.3663 +        void *plContext)
  1.3664 +{
  1.3665 +        PKIX_ForwardBuilderState *state = NULL;
  1.3666 +        PKIX_BuildResult *buildResult = NULL;
  1.3667 +        void *nbioContext = NULL;
  1.3668 +
  1.3669 +        PKIX_ENTER(BUILD, "PKIX_BuildChain");
  1.3670 +        PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult);
  1.3671 +
  1.3672 +        nbioContext = *pNBIOContext;
  1.3673 +        *pNBIOContext = NULL;
  1.3674 +
  1.3675 +        if (*pState == NULL) {
  1.3676 +                PKIX_CHECK(pkix_Build_InitiateBuildChain
  1.3677 +                        (procParams,
  1.3678 +                        &nbioContext,
  1.3679 +                        &state,
  1.3680 +                        &buildResult,
  1.3681 +                        pVerifyNode,
  1.3682 +                        plContext),
  1.3683 +                        PKIX_BUILDINITIATEBUILDCHAINFAILED);
  1.3684 +        } else {
  1.3685 +                state = (PKIX_ForwardBuilderState *)(*pState);
  1.3686 +                *pState = NULL; /* no net change in reference count */
  1.3687 +                if (state->status == BUILD_SHORTCUTPENDING) {
  1.3688 +                        PKIX_CHECK(pkix_Build_InitiateBuildChain
  1.3689 +                                (procParams,
  1.3690 +                                &nbioContext,
  1.3691 +                                &state,
  1.3692 +                                &buildResult,
  1.3693 +                                pVerifyNode,
  1.3694 +                                plContext),
  1.3695 +                                PKIX_BUILDINITIATEBUILDCHAINFAILED);
  1.3696 +                } else {
  1.3697 +                        PKIX_CHECK(pkix_Build_ResumeBuildChain
  1.3698 +                                (&nbioContext,
  1.3699 +                                state,
  1.3700 +                                &buildResult,
  1.3701 +                                pVerifyNode,
  1.3702 +                                plContext),
  1.3703 +                                PKIX_BUILDINITIATEBUILDCHAINFAILED);
  1.3704 +                }
  1.3705 +        }
  1.3706 +
  1.3707 +        /* non-null nbioContext means the build would block */
  1.3708 +        if (nbioContext != NULL) {
  1.3709 +
  1.3710 +                *pNBIOContext = nbioContext;
  1.3711 +                *pState = state;
  1.3712 +                state = NULL;
  1.3713 +                *pBuildResult = NULL;
  1.3714 +
  1.3715 +        /* no buildResult means the build has failed */
  1.3716 +        } else if (buildResult == NULL) {
  1.3717 +                PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
  1.3718 +        } else {
  1.3719 +                /*
  1.3720 +                 * If we made a successful chain by combining the target Cert
  1.3721 +                 * with one of the Trust Anchors, we may have never created a
  1.3722 +                 * validityDate. We treat this situation as
  1.3723 +                 * canBeCached = PKIX_FALSE.
  1.3724 +                 */
  1.3725 +                if ((state != NULL) &&
  1.3726 +                    ((state->validityDate) != NULL) &&
  1.3727 +                    (state->canBeCached)) {
  1.3728 +                        PKIX_CHECK(pkix_CacheCertChain_Add
  1.3729 +                                (state->buildConstants.targetCert,
  1.3730 +                                state->buildConstants.anchors,
  1.3731 +                                state->validityDate,
  1.3732 +                                buildResult,
  1.3733 +                                plContext),
  1.3734 +                                PKIX_CACHECERTCHAINADDFAILED);
  1.3735 +                }
  1.3736 +
  1.3737 +                *pState = NULL;
  1.3738 +                *pBuildResult = buildResult;
  1.3739 +                buildResult = NULL;
  1.3740 +        }
  1.3741 +
  1.3742 +cleanup:
  1.3743 +        PKIX_DECREF(buildResult);
  1.3744 +        PKIX_DECREF(state);
  1.3745 +
  1.3746 +        PKIX_RETURN(BUILD);
  1.3747 +}

mercurial