tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_build.c (153455B)


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