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

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

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

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

     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  */
    11 /* #define PKIX_BUILDDEBUG 1 */
    12 /* #define PKIX_FORWARDBUILDERSTATEDEBUG 1 */
    14 #include "pkix_build.h"
    16 extern PRLogModuleInfo *pkixLog;
    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 };
    33 /* --Private-ForwardBuilderState-Functions---------------------------------- */
    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;
    46         PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Destroy");
    47         PKIX_NULLCHECK_ONE(object);
    49         PKIX_CHECK(pkix_CheckType
    50                 (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext),
    51                 PKIX_OBJECTNOTFORWARDBUILDERSTATE);
    53         state = (PKIX_ForwardBuilderState *)object;
    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);
    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         }
   110 cleanup:
   112         PKIX_RETURN(FORWARDBUILDERSTATE);
   113 }
   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;
   169         PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_Create");
   170         PKIX_NULLCHECK_FOUR(prevCert, traversedSubjNames, pState, trustChain);
   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);
   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;
   199         PKIX_INCREF(validityDate);
   200         state->validityDate = validityDate;
   202         PKIX_INCREF(prevCert);
   203         state->prevCert = prevCert;
   205         state->candidateCert = NULL;
   207         PKIX_INCREF(traversedSubjNames);
   208         state->traversedSubjNames = traversedSubjNames;
   210         PKIX_INCREF(trustChain);
   211         state->trustChain = trustChain;
   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;
   222         PKIX_INCREF(parentState);
   223         state->parentState = parentState;
   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         }
   264         *pState = state;
   265         state = NULL;
   266 cleanup:
   268         PKIX_DECREF(state);
   270         PKIX_RETURN(FORWARDBUILDERSTATE);
   271 }
   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;
   301         PKIX_ENTER(BUILD, "pkix_Build_GetResourceLimits");
   302         PKIX_NULLCHECK_ONE(buildConstants);
   304         PKIX_CHECK(PKIX_ProcessingParams_GetResourceLimits
   305                 (buildConstants->procParams, &resourceLimits, plContext),
   306                 PKIX_PROCESSINGPARAMSGETRESOURCELIMITSFAILED);
   308         buildConstants->maxFanout = 0;
   309         buildConstants->maxDepth = 0;
   310         buildConstants->maxTime = 0;
   312         if (resourceLimits) {
   314                 PKIX_CHECK(PKIX_ResourceLimits_GetMaxFanout
   315                         (resourceLimits, &buildConstants->maxFanout, plContext),
   316                         PKIX_RESOURCELIMITSGETMAXFANOUTFAILED);
   318                 PKIX_CHECK(PKIX_ResourceLimits_GetMaxDepth
   319                         (resourceLimits, &buildConstants->maxDepth, plContext),
   320                         PKIX_RESOURCELIMITSGETMAXDEPTHFAILED);
   322                 PKIX_CHECK(PKIX_ResourceLimits_GetMaxTime
   323                         (resourceLimits, &buildConstants->maxTime, plContext),
   324                         PKIX_RESOURCELIMITSGETMAXTIMEFAILED);
   325         }
   327 cleanup:
   329         PKIX_DECREF(resourceLimits);
   331         PKIX_RETURN(BUILD);
   332 }
   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;
   382         PKIX_ENTER(FORWARDBUILDERSTATE, "pkix_ForwardBuilderState_ToString");
   383         PKIX_NULLCHECK_TWO(object, pString);
   385         PKIX_CHECK(pkix_CheckType
   386                 (object, PKIX_FORWARDBUILDERSTATE_TYPE, plContext),
   387                 PKIX_OBJECTNOTFORWARDBUILDERSTATE);
   389         state = (PKIX_ForwardBuilderState *)object;
   391         PKIX_CHECK(PKIX_PL_String_Create
   392                 (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
   393                 PKIX_STRINGCREATEFAILED);
   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         }
   432         PKIX_CHECK(PKIX_PL_String_Create
   433                 (PKIX_ESCASCII, asciiStatus, 0, &buildStatusString, plContext),
   434                 PKIX_STRINGCREATEFAILED);
   436         PKIX_TOSTRING
   437                (state->validityDate, &validityDateString, plContext,
   438                 PKIX_OBJECTTOSTRINGFAILED);
   440         PKIX_TOSTRING
   441                (state->prevCert, &prevCertString, plContext,
   442                 PKIX_OBJECTTOSTRINGFAILED);
   444         PKIX_TOSTRING
   445                 (state->candidateCert, &candidateCertString, plContext,
   446                 PKIX_OBJECTTOSTRINGFAILED);
   448         PKIX_TOSTRING
   449                 (state->traversedSubjNames,
   450                 &traversedSubjNamesString,
   451                 plContext,
   452                 PKIX_OBJECTTOSTRINGFAILED);
   454         PKIX_TOSTRING
   455                 (state->trustChain, &trustChainString, plContext,
   456                 PKIX_OBJECTTOSTRINGFAILED);
   458         PKIX_TOSTRING
   459                 (state->candidateCerts, &candidateCertsString, plContext,
   460                 PKIX_OBJECTTOSTRINGFAILED);
   462         PKIX_TOSTRING
   463                 (state->certSel, &certSelString, plContext,
   464                 PKIX_OBJECTTOSTRINGFAILED);
   466         PKIX_TOSTRING
   467                 (state->verifyNode, &verifyNodeString, plContext,
   468                 PKIX_OBJECTTOSTRINGFAILED);
   470         PKIX_TOSTRING
   471                 (state->parentState, &parentStateString, plContext,
   472                 PKIX_OBJECTTOSTRINGFAILED);
   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);
   502         *pString = resultString;
   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);
   517         PKIX_RETURN(FORWARDBUILDERSTATE);
   519 }
   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 {
   539         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
   540         pkix_ClassTable_Entry entry;
   542         PKIX_ENTER(FORWARDBUILDERSTATE,
   543                     "pkix_ForwardBuilderState_RegisterSelf");
   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;
   555         systemClasses[PKIX_FORWARDBUILDERSTATE_TYPE] = entry;
   557         PKIX_RETURN(FORWARDBUILDERSTATE);
   558 }
   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;
   583         PKIX_ENTER(FORWARDBUILDERSTATE,"pkix_ForwardBuilderState_DumpState");
   584         PKIX_NULLCHECK_ONE(state);
   586         PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   587                 ((PKIX_PL_Object *)state, plContext),
   588                 PKIX_OBJECTINVALIDATECACHEFAILED);
   590         PKIX_CHECK(PKIX_PL_Object_ToString
   591                 ((PKIX_PL_Object*)state, &stateString, plContext),
   592                 PKIX_OBJECTTOSTRINGFAILED);
   594         PKIX_CHECK(PKIX_PL_String_GetEncoded
   595                     (stateString,
   596                     PKIX_ESCASCII,
   597                     (void **)&stateAscii,
   598                     &length,
   599                     plContext),
   600                     PKIX_STRINGGETENCODEDFAILED);
   602         PKIX_DEBUG_ARG("In Phase 1: state = %s\n", stateAscii);
   604         PKIX_FREE(stateAscii);
   605         PKIX_DECREF(stateString);
   607 cleanup:
   608         PKIX_RETURN(FORWARDBUILDERSTATE);
   609 }
   610 #endif
   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);
   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         }
   653         PKIX_RETURN(FORWARDBUILDERSTATE);
   654 }
   656 /* --Private-BuildChain-Functions------------------------------------------- */
   658 /*
   659  * FUNCTION: pkix_Build_SortCertComparator
   660  * DESCRIPTION:
   661  *
   662  *  This Function takes two Certificates cast in "obj1" and "obj2",
   663  *  compares their validity NotAfter dates and returns the result at
   664  *  "pResult". The comparison key(s) can be expanded by using other
   665  *  data in the Certificate in the future.
   666  *
   667  * PARAMETERS:
   668  *  "obj1"
   669  *      Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert.
   670  *      Must be non-NULL.
   671  *  "obj2"
   672  *      Address of the PKIX_PL_Object that is a cast of PKIX_PL_Cert.
   673  *      Must be non-NULL.
   674  *  "pResult"
   675  *      Address where the comparison result is returned. Must be non-NULL.
   676  *  "plContext"
   677  *      Platform-specific context pointer.
   678  * THREAD SAFETY:
   679  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   680  * RETURNS:
   681  *  Returns NULL if the function succeeds.
   682  *  Returns a Build Error if the function fails in a non-fatal way
   683  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   684  */
   685 static PKIX_Error *
   686 pkix_Build_SortCertComparator(
   687         PKIX_PL_Object *obj1,
   688         PKIX_PL_Object *obj2,
   689         PKIX_Int32 *pResult,
   690         void *plContext)
   691 {
   692         PKIX_PL_Date *date1 = NULL;
   693         PKIX_PL_Date *date2 = NULL;
   694         PKIX_Boolean result = PKIX_FALSE;
   696         PKIX_ENTER(BUILD, "pkix_Build_SortCertComparator");
   697         PKIX_NULLCHECK_THREE(obj1, obj2, pResult);
   699         /*
   700          * For sorting candidate certificates, we use NotAfter date as the
   701          * sorted key for now (can be expanded if desired in the future).
   702          *
   703          * In PKIX_BuildChain, the List of CertStores was reordered so that
   704          * trusted CertStores are ahead of untrusted CertStores. That sort, or
   705          * this one, could be taken out if it is determined that it doesn't help
   706          * performance, or in some way hinders the solution of choosing desired
   707          * candidates.
   708          */
   710         PKIX_CHECK(pkix_CheckType(obj1, PKIX_CERT_TYPE, plContext),
   711                     PKIX_OBJECTNOTCERT);
   712         PKIX_CHECK(pkix_CheckType(obj2, PKIX_CERT_TYPE, plContext),
   713                     PKIX_OBJECTNOTCERT);
   715         PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
   716                 ((PKIX_PL_Cert *)obj1, &date1, plContext),
   717                 PKIX_CERTGETVALIDITYNOTAFTERFAILED);
   719         PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
   720                 ((PKIX_PL_Cert *)obj2, &date2, plContext),
   721                 PKIX_CERTGETVALIDITYNOTAFTERFAILED);
   723         PKIX_CHECK(PKIX_PL_Object_Compare
   724                 ((PKIX_PL_Object *)date1,
   725                 (PKIX_PL_Object *)date2,
   726                 &result,
   727                 plContext),
   728                 PKIX_OBJECTCOMPARATORFAILED);
   730         *pResult = !result;
   732 cleanup:
   734         PKIX_DECREF(date1);
   735         PKIX_DECREF(date2);
   737         PKIX_RETURN(BUILD);
   738 }
   740 /* This local error check macro */
   741 #define ERROR_CHECK(errCode) \
   742     if (pkixErrorResult) { \
   743         if (pkixLog) { \
   744             PR_LOG(pkixLog, PR_LOG_DEBUG, ("====> ERROR_CHECK code %s\n", #errCode)); \
   745         } \
   746         pkixTempErrorReceived = PKIX_TRUE; \
   747         pkixErrorClass = pkixErrorResult->errClass; \
   748         if (pkixErrorClass == PKIX_FATAL_ERROR) { \
   749             goto cleanup; \
   750         } \
   751         if (verifyNode) { \
   752             PKIX_DECREF(verifyNode->error); \
   753             PKIX_INCREF(pkixErrorResult); \
   754             verifyNode->error = pkixErrorResult; \
   755         } \
   756         pkixErrorCode = errCode; \
   757         goto cleanup; \
   758     }
   760 /*
   761  * FUNCTION: pkix_Build_VerifyCertificate
   762  * DESCRIPTION:
   763  *
   764  *  Checks whether the previous Cert stored in the ForwardBuilderState pointed
   765  *  to by "state" successfully chains, including signature verification, to the
   766  *  candidate Cert also stored in "state", using the Boolean value in "trusted"
   767  *  to determine whether "candidateCert" is trusted.
   768  *
   769  *  First it checks whether "candidateCert" has already been traversed by
   770  *  determining whether it is contained in the List of traversed Certs. It then
   771  *  checks the candidate Cert with user checkers, if any, in the List pointed to
   772  *  by "userCheckers". Finally, it runs the signature validation.
   773  *
   774  *  If this Certificate fails verification, and state->verifyNode is non-NULL,
   775  *  this function sets the Error code into the verifyNode.
   776  *
   777  * PARAMETERS:
   778  *  "state"
   779  *      Address of ForwardBuilderState to be used. Must be non-NULL.
   780  *  "userCheckers"
   781  *      Address of a List of CertChainCheckers to be used, if present, to
   782  *      validate the candidateCert.
   783  *  "trusted"
   784  *      Boolean value of trust for the candidate Cert
   785  *  "plContext"
   786  *      Platform-specific context pointer.
   787  * THREAD SAFETY:
   788  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   789  * RETURNS:
   790  *  Returns NULL if the function succeeds.
   791  *  Returns a Build Error if the function fails in a non-fatal way
   792  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   793  */
   794 static PKIX_Error *
   795 pkix_Build_VerifyCertificate(
   796         PKIX_ForwardBuilderState *state,
   797         PKIX_List *userCheckers,
   798         PKIX_Boolean *pTrusted,
   799         PKIX_VerifyNode *verifyNode,
   800         void *plContext)
   801 {
   802         PKIX_UInt32 numUserCheckers = 0;
   803         PKIX_UInt32 i = 0;
   804         PKIX_Boolean loopFound = PKIX_FALSE;
   805         PKIX_Boolean supportForwardChecking = PKIX_FALSE;
   806         PKIX_Boolean trusted = PKIX_FALSE;
   807         PKIX_PL_Cert *candidateCert = NULL;
   808         PKIX_PL_PublicKey *candidatePubKey = NULL;
   809         PKIX_CertChainChecker *userChecker = NULL;
   810         PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
   811         PKIX_PL_TrustAnchorMode trustAnchorMode =
   812                 PKIX_PL_TrustAnchorMode_Ignore;
   813         void *nbioContext = NULL;
   815         PKIX_ENTER(BUILD, "pkix_Build_VerifyCertificate");
   816         PKIX_NULLCHECK_TWO(state, pTrusted);
   817         PKIX_NULLCHECK_THREE
   818                 (state->candidateCerts, state->prevCert, state->trustChain);
   820         PKIX_INCREF(state->candidateCert);
   821         candidateCert = state->candidateCert;
   823         if (state->buildConstants.numAnchors) {
   824             if (state->buildConstants.trustOnlyUserAnchors) {
   825                 trustAnchorMode = PKIX_PL_TrustAnchorMode_Exclusive;
   826             } else {
   827                 trustAnchorMode = PKIX_PL_TrustAnchorMode_Additive;
   828             }
   829         } else {
   830             trustAnchorMode = PKIX_PL_TrustAnchorMode_Ignore;
   831         }
   833         PKIX_CHECK(
   834             PKIX_PL_Cert_IsCertTrusted(candidateCert, trustAnchorMode,
   835                                        &trusted, plContext),
   836             PKIX_CERTISCERTTRUSTEDFAILED);
   838         *pTrusted = trusted;
   840         /* check for loops */
   841         PKIX_CHECK(pkix_List_Contains
   842                 (state->trustChain,
   843                 (PKIX_PL_Object *)candidateCert,
   844                 &loopFound,
   845                 plContext),
   846                 PKIX_LISTCONTAINSFAILED);
   848         if (loopFound) {
   849                 if (verifyNode != NULL) {
   850                         PKIX_Error *verifyError = NULL;
   851                         PKIX_ERROR_CREATE
   852                                 (BUILD,
   853                                 PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED,
   854                                 verifyError);
   855                         PKIX_DECREF(verifyNode->error);
   856                         verifyNode->error = verifyError;
   857                 }
   858                 /* Even if error logged, still need to abort
   859                  * if cert is not trusted. */
   860                 if (!trusted) {
   861                         PKIX_ERROR(PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED);
   862                 }
   863                 state->certLoopingDetected = PKIX_TRUE;
   864         }
   866         if (userCheckers != NULL) {
   868                 PKIX_CHECK(PKIX_List_GetLength
   869                     (userCheckers, &numUserCheckers, plContext),
   870                     PKIX_LISTGETLENGTHFAILED);
   872                 for (i = 0; i < numUserCheckers; i++) {
   874                     PKIX_CHECK(PKIX_List_GetItem
   875                         (userCheckers,
   876                         i,
   877                         (PKIX_PL_Object **) &userChecker,
   878                         plContext),
   879                         PKIX_LISTGETITEMFAILED);
   881                     PKIX_CHECK
   882                         (PKIX_CertChainChecker_IsForwardCheckingSupported
   883                         (userChecker, &supportForwardChecking, plContext),
   884                         PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
   886                     if (supportForwardChecking == PKIX_TRUE) {
   888                         PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
   889                             (userChecker, &checkerCheck, plContext),
   890                             PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);
   892                         pkixErrorResult =
   893                             checkerCheck(userChecker, candidateCert, NULL,
   894                                          &nbioContext, plContext);
   896                         ERROR_CHECK(PKIX_USERCHECKERCHECKFAILED);
   897                     }
   899                     PKIX_DECREF(userChecker);
   900                 }
   901         }
   903         /* Check that public key of the trusted dsa cert has
   904          * dsa parameters */
   905         if (trusted) {
   906             PKIX_Boolean paramsNeeded = PKIX_FALSE;
   907             PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
   908                        (candidateCert, &candidatePubKey, plContext),
   909                        PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
   910             PKIX_CHECK(PKIX_PL_PublicKey_NeedsDSAParameters
   911                        (candidatePubKey, &paramsNeeded, plContext),
   912                        PKIX_PUBLICKEYNEEDSDSAPARAMETERSFAILED);
   913             if (paramsNeeded) {
   914                 PKIX_ERROR(PKIX_MISSINGDSAPARAMETERS);
   915             }
   916         }
   918 cleanup:
   919         PKIX_DECREF(candidateCert);
   920         PKIX_DECREF(candidatePubKey);
   921         PKIX_DECREF(userChecker);
   923         PKIX_RETURN(BUILD);
   924 }
   926 /*
   927  * FUNCTION: pkix_Build_ValidationCheckers
   928  * DESCRIPTION:
   929  *
   930  *  Creates a List of Objects to be used in determining whether the List of
   931  *  Certs pointed to by "certChain" successfully validates using the
   932  *  ForwardBuilderState pointed to by "state", and the TrustAnchor pointed to by
   933  *  "anchor". These objects are a reversed Cert Chain, consisting of the certs
   934  *  in "certChain" in reversed order, suitable for presenting to the
   935  *  CertChainCheckers; a List of critical extension OIDS that have already been
   936  *  processed in forward building; a List of CertChainCheckers to be called, and
   937  *  a List of RevocationCheckers to be called. These results are stored in
   938  *  fields of "state".
   939  *
   940  * PARAMETERS:
   941  *  "state"
   942  *      Address of ForwardBuilderState to be used. Must be non-NULL.
   943  *  "certChain"
   944  *      Address of List of Certs to be validated. Must be non-NULL.
   945  *  "anchor"
   946  *      Address of TrustAnchor to be used. Must be non-NULL.
   947  *  "addEkuChecker"
   948  *      Boolean flags that tells to add eku checker to the list
   949  *      of checkers. Only needs to be done for existing chain revalidation.
   950  *  "plContext"
   951  *      Platform-specific context pointer.
   952  * THREAD SAFETY:
   953  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   954  * RETURNS:
   955  *  Returns NULL if the function succeeds.
   956  *  Returns a Build Error if the function fails in a non-fatal way
   957  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   958  */
   959 static PKIX_Error *
   960 pkix_Build_ValidationCheckers(
   961         PKIX_ForwardBuilderState *state,
   962         PKIX_List *certChain,
   963         PKIX_TrustAnchor *anchor,
   964         PKIX_Boolean chainRevalidationStage,
   965         void *plContext)
   966 {
   967         PKIX_List *checkers = NULL;
   968         PKIX_List *initialPolicies = NULL;
   969         PKIX_List *reversedCertChain = NULL;
   970         PKIX_List *buildCheckedCritExtOIDsList = NULL;
   971         PKIX_ProcessingParams *procParams = NULL;
   972         PKIX_PL_Cert *trustedCert = NULL;
   973         PKIX_PL_PublicKey *trustedPubKey = NULL;
   974         PKIX_PL_CertNameConstraints *trustedNC = NULL;
   975         PKIX_CertChainChecker *sigChecker = NULL;
   976         PKIX_CertChainChecker *policyChecker = NULL;
   977         PKIX_CertChainChecker *userChecker = NULL;
   978         PKIX_CertChainChecker *nameConstraintsChecker = NULL;
   979         PKIX_CertChainChecker *checker = NULL;
   980         PKIX_CertSelector *certSelector = NULL;
   981         PKIX_List *userCheckerExtOIDs = NULL;
   982         PKIX_PL_OID *oid = NULL;
   983         PKIX_Boolean supportForwardChecking = PKIX_FALSE;
   984         PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
   985         PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
   986         PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
   987         PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
   988         PKIX_UInt32 numChainCerts;
   989         PKIX_UInt32 numCertCheckers;
   990         PKIX_UInt32 i;
   992         PKIX_ENTER(BUILD, "pkix_Build_ValidationCheckers");
   993         PKIX_NULLCHECK_THREE(state, certChain, anchor);
   995         PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
   996                 PKIX_LISTCREATEFAILED);
   998         PKIX_CHECK(PKIX_List_ReverseList
   999                 (certChain, &reversedCertChain, plContext),
  1000                 PKIX_LISTREVERSELISTFAILED);
  1002         PKIX_CHECK(PKIX_List_GetLength
  1003                 (reversedCertChain, &numChainCerts, plContext),
  1004                 PKIX_LISTGETLENGTHFAILED);
  1006         procParams = state->buildConstants.procParams;
  1008         /* Do need to add a number of checker to revalidate
  1009          * a built chain. KU, EKU, CertType and Validity Date
  1010          * get checked by certificate selector during chain
  1011          * construction, but needed to be checked for chain from
  1012          * the cache.*/
  1013         if (chainRevalidationStage) {
  1014             PKIX_CHECK(pkix_ExpirationChecker_Initialize
  1015                        (state->buildConstants.testDate, &checker, plContext),
  1016                        PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
  1017             PKIX_CHECK(PKIX_List_AppendItem
  1018                        (checkers, (PKIX_PL_Object *)checker, plContext),
  1019                        PKIX_LISTAPPENDITEMFAILED);
  1020             PKIX_DECREF(checker);
  1022             PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
  1023                        (procParams, &certSelector, plContext),
  1024                     PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
  1026             PKIX_CHECK(pkix_TargetCertChecker_Initialize
  1027                        (certSelector, numChainCerts, &checker, plContext),
  1028                        PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
  1029             PKIX_CHECK(PKIX_List_AppendItem
  1030                        (checkers, (PKIX_PL_Object *)checker, plContext),
  1031                        PKIX_LISTAPPENDITEMFAILED);
  1032             PKIX_DECREF(checker);
  1035         PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
  1036                 (procParams, &initialPolicies, plContext),
  1037                 PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);
  1039         PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
  1040                 (procParams, &policyQualifiersRejected, plContext),
  1041                 PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);
  1043         PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
  1044                 (procParams, &initialPolicyMappingInhibit, plContext),
  1045                 PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);
  1047         PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
  1048                 (procParams, &initialAnyPolicyInhibit, plContext),
  1049                 PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);
  1051         PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
  1052                 (procParams, &initialExplicitPolicy, plContext),
  1053                 PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);
  1055         PKIX_CHECK(pkix_PolicyChecker_Initialize
  1056                 (initialPolicies,
  1057                 policyQualifiersRejected,
  1058                 initialPolicyMappingInhibit,
  1059                 initialExplicitPolicy,
  1060                 initialAnyPolicyInhibit,
  1061                 numChainCerts,
  1062                 &policyChecker,
  1063                 plContext),
  1064                 PKIX_POLICYCHECKERINITIALIZEFAILED);
  1066         PKIX_CHECK(PKIX_List_AppendItem
  1067                 (checkers, (PKIX_PL_Object *)policyChecker, plContext),
  1068                 PKIX_LISTAPPENDITEMFAILED);
  1070         /*
  1071          * Create an OID list that contains critical extensions processed
  1072          * by BuildChain. These are specified in a static const array.
  1073          */
  1074         PKIX_CHECK(PKIX_List_Create(&buildCheckedCritExtOIDsList, plContext),
  1075                 PKIX_LISTCREATEFAILED);
  1077         for (i = 0; buildCheckedCritExtOIDs[i] != PKIX_UNKNOWN_OID; i++) {
  1078                 PKIX_CHECK(PKIX_PL_OID_Create
  1079                         (buildCheckedCritExtOIDs[i], &oid, plContext),
  1080                         PKIX_OIDCREATEFAILED);
  1082                 PKIX_CHECK(PKIX_List_AppendItem
  1083                         (buildCheckedCritExtOIDsList,
  1084                         (PKIX_PL_Object *) oid,
  1085                         plContext),
  1086                         PKIX_LISTAPPENDITEMFAILED);
  1088                 PKIX_DECREF(oid);
  1091         if (state->buildConstants.userCheckers != NULL) {
  1093                 PKIX_CHECK(PKIX_List_GetLength
  1094                         (state->buildConstants.userCheckers,
  1095                         &numCertCheckers,
  1096                         plContext),
  1097                         PKIX_LISTGETLENGTHFAILED);
  1099                 for (i = 0; i < numCertCheckers; i++) {
  1101                         PKIX_CHECK(PKIX_List_GetItem
  1102                             (state->buildConstants.userCheckers,
  1103                             i,
  1104                             (PKIX_PL_Object **) &userChecker,
  1105                             plContext),
  1106                             PKIX_LISTGETITEMFAILED);
  1108                         PKIX_CHECK
  1109                             (PKIX_CertChainChecker_IsForwardCheckingSupported
  1110                             (userChecker, &supportForwardChecking, plContext),
  1111                             PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
  1113                         /*
  1114                          * If this userChecker supports forwardChecking then it
  1115                          * should have been checked during build chain. Skip
  1116                          * checking but need to add checker's extension OIDs
  1117                          * to buildCheckedCritExtOIDsList.
  1118                          */
  1119                         if (supportForwardChecking == PKIX_TRUE) {
  1121                           PKIX_CHECK
  1122                             (PKIX_CertChainChecker_GetSupportedExtensions
  1123                             (userChecker, &userCheckerExtOIDs, plContext),
  1124                             PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
  1126                           if (userCheckerExtOIDs != NULL) {
  1127                             PKIX_CHECK(pkix_List_AppendList
  1128                                 (buildCheckedCritExtOIDsList,
  1129                                 userCheckerExtOIDs,
  1130                                 plContext),
  1131                                 PKIX_LISTAPPENDLISTFAILED);
  1134                         } else {
  1135                             PKIX_CHECK(PKIX_List_AppendItem
  1136                                 (checkers,
  1137                                 (PKIX_PL_Object *)userChecker,
  1138                                 plContext),
  1139                                 PKIX_LISTAPPENDITEMFAILED);
  1142                         PKIX_DECREF(userCheckerExtOIDs);
  1143                         PKIX_DECREF(userChecker);
  1147         /* Enabling post chain building signature check on the certs. */
  1148         PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
  1149                    (anchor, &trustedCert, plContext),
  1150                    PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  1152         PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
  1153                    (trustedCert, &trustedPubKey, plContext),
  1154                    PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
  1156         PKIX_CHECK(pkix_SignatureChecker_Initialize
  1157                    (trustedPubKey,
  1158                     numChainCerts,
  1159                     &sigChecker,
  1160                     plContext),
  1161                    PKIX_SIGNATURECHECKERINITIALIZEFAILED);
  1163         PKIX_CHECK(PKIX_List_AppendItem
  1164                    (checkers,
  1165                     (PKIX_PL_Object *)sigChecker,
  1166                     plContext),
  1167                    PKIX_LISTAPPENDITEMFAILED);
  1169         /* Enabling post chain building name constraints check on the certs. */
  1170         PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
  1171                   (anchor, &trustedNC, plContext),
  1172                   PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);
  1174         PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
  1175                   (trustedNC, numChainCerts, &nameConstraintsChecker,
  1176                    plContext),
  1177                   PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);
  1179         PKIX_CHECK(PKIX_List_AppendItem
  1180                   (checkers,
  1181                    (PKIX_PL_Object *)nameConstraintsChecker,
  1182                    plContext),
  1183                   PKIX_LISTAPPENDITEMFAILED);
  1186         PKIX_DECREF(state->reversedCertChain);
  1187         PKIX_INCREF(reversedCertChain);
  1188         state->reversedCertChain = reversedCertChain;
  1189         PKIX_DECREF(state->checkedCritExtOIDs);
  1190         PKIX_INCREF(buildCheckedCritExtOIDsList);
  1191         state->checkedCritExtOIDs = buildCheckedCritExtOIDsList;
  1192         PKIX_DECREF(state->checkerChain);
  1193         state->checkerChain = checkers;
  1194         checkers = NULL;
  1195         state->certCheckedIndex = 0;
  1196         state->checkerIndex = 0;
  1197         state->revChecking = PKIX_FALSE;
  1200 cleanup:
  1202         PKIX_DECREF(oid);
  1203         PKIX_DECREF(reversedCertChain);
  1204         PKIX_DECREF(buildCheckedCritExtOIDsList);
  1205         PKIX_DECREF(checker);
  1206         PKIX_DECREF(checkers);
  1207         PKIX_DECREF(initialPolicies);
  1208         PKIX_DECREF(trustedCert);
  1209         PKIX_DECREF(trustedPubKey);
  1210         PKIX_DECREF(certSelector);
  1211         PKIX_DECREF(sigChecker);
  1212         PKIX_DECREF(trustedNC);
  1213         PKIX_DECREF(nameConstraintsChecker);
  1214         PKIX_DECREF(policyChecker);
  1215         PKIX_DECREF(userChecker);
  1216         PKIX_DECREF(userCheckerExtOIDs);
  1218         PKIX_RETURN(BUILD);
  1221 /*
  1222  * FUNCTION: pkix_Build_ValidateEntireChain
  1223  * DESCRIPTION:
  1225  *  Checks whether the current List of Certs successfully validates using the 
  1226  *  TrustAnchor pointed to by "anchor" and other parameters contained, as was
  1227  *  the Cert List, in "state".
  1229  *  If a checker using non-blocking I/O returns with a non-NULL non-blocking I/O
  1230  *  context (NBIOContext), an indication that I/O is in progress and the
  1231  *  checking has not been completed, this function stores that context at
  1232  *  "pNBIOContext". Otherwise, it stores NULL at "pNBIOContext".
  1234  *  If not awaiting I/O and if successful, a ValidateResult is created
  1235  *  containing the Public Key of the target certificate (including DSA parameter
  1236  *  inheritance, if any) and the PolicyNode representing the policy tree output
  1237  *  by the validation algorithm.  If not successful, an Error pointer is
  1238  *  returned.
  1240  * PARAMETERS:
  1241  *  "state"
  1242  *      Address of ForwardBuilderState to be used. Must be non-NULL.
  1243  *  "anchor"
  1244  *      Address of TrustAnchor to be used. Must be non-NULL.
  1245  *  "pNBIOContext"
  1246  *      Address at which the NBIOContext is stored indicating whether the
  1247  *      validation is complete. Must be non-NULL.
  1248  *  "pValResult"
  1249  *      Address at which the ValidateResult is stored. Must be non-NULL.
  1250  *  "plContext"
  1251  *      Platform-specific context pointer.
  1252  * THREAD SAFETY:
  1253  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1254  * RETURNS:
  1255  *  Returns NULL if the function succeeds.
  1256  *  Returns a Build Error if the function fails in a non-fatal way
  1257  *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1258  */
  1259 static PKIX_Error *
  1260 pkix_Build_ValidateEntireChain(
  1261         PKIX_ForwardBuilderState *state,
  1262         PKIX_TrustAnchor *anchor,
  1263         void **pNBIOContext,
  1264         PKIX_ValidateResult **pValResult,
  1265         PKIX_VerifyNode *verifyNode,
  1266         void *plContext)
  1268         PKIX_UInt32 numChainCerts = 0;
  1269         PKIX_PL_PublicKey *subjPubKey = NULL;
  1270         PKIX_PolicyNode *policyTree = NULL;
  1271         PKIX_ValidateResult *valResult = NULL;
  1272         void *nbioContext = NULL;
  1274         PKIX_ENTER(BUILD, "pkix_Build_ValidateEntireChain");
  1275         PKIX_NULLCHECK_FOUR(state, anchor, pNBIOContext, pValResult);
  1277         *pNBIOContext = NULL; /* prepare for case of error exit */
  1279         PKIX_CHECK(PKIX_List_GetLength
  1280                 (state->reversedCertChain, &numChainCerts, plContext),
  1281                 PKIX_LISTGETLENGTHFAILED);
  1283         pkixErrorResult =
  1284             pkix_CheckChain(state->reversedCertChain, numChainCerts, anchor,
  1285                             state->checkerChain,
  1286                             state->buildConstants.revChecker,
  1287                             state->checkedCritExtOIDs,
  1288                             state->buildConstants.procParams,
  1289                             &state->certCheckedIndex, &state->checkerIndex,
  1290                             &state->revChecking, &state->reasonCode,
  1291                             &nbioContext, &subjPubKey, &policyTree, NULL,
  1292                             plContext);
  1294         if (nbioContext != NULL) {
  1295                 *pNBIOContext = nbioContext;
  1296                 goto cleanup;
  1299         ERROR_CHECK(PKIX_CHECKCHAINFAILED);
  1301         /* XXX Remove this assertion after 2014-12-31. See bug 946984. */
  1302         PORT_Assert(state->reasonCode == 0);
  1304         PKIX_CHECK(pkix_ValidateResult_Create
  1305                 (subjPubKey, anchor, policyTree, &valResult, plContext),
  1306                 PKIX_VALIDATERESULTCREATEFAILED);
  1308         *pValResult = valResult;
  1309         valResult = NULL;
  1311 cleanup:
  1312         PKIX_DECREF(subjPubKey);
  1313         PKIX_DECREF(policyTree);
  1314         PKIX_DECREF(valResult);
  1316         PKIX_RETURN(BUILD);
  1319 /*
  1320  * FUNCTION: pkix_Build_SortCandidateCerts
  1321  * DESCRIPTION:
  1323  *  This function sorts a List of candidate Certs pointed to by "candidates"
  1324  *  using an algorithm that places Certs most likely to produce a successful
  1325  *  chain at the front of the list, storing the resulting sorted List at
  1326  *  "pSortedCandidates".
  1328  *  At present the only sort criterion is that trusted Certs go ahead of
  1329  *  untrusted Certs.
  1331  * PARAMETERS:
  1332  *  "candidates"
  1333  *      Address of List of Candidate Certs to be sorted. Must be non-NULL.
  1334  *  "pSortedCandidates"
  1335  *      Address at which sorted List is stored. Must be non-NULL.
  1336  *  "plContext"
  1337  *      Platform-specific context pointer.
  1338  * THREAD SAFETY:
  1339  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1340  * RETURNS:
  1341  *  Returns NULL if the function succeeds.
  1342  *  Returns a Build Error if the function fails in a non-fatal way
  1343  *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1344  */
  1345 static PKIX_Error *
  1346 pkix_Build_SortCandidateCerts(
  1347         PKIX_List *candidates,
  1348         PKIX_List **pSortedCandidates,
  1349         void *plContext)
  1351         PKIX_List *sortedList = NULL;
  1353         PKIX_ENTER(BUILD, "pkix_Build_SortCandidateCerts");
  1354         PKIX_NULLCHECK_TWO(candidates, pSortedCandidates);
  1356         /*
  1357          * Both bubble and quick sort algorithms are available.
  1358          * For a list of fewer than around 100 items, the bubble sort is more
  1359          * efficient. (This number was determined by experimenting with both
  1360          * algorithms on a Java List.)
  1361          * If the candidate list is very small, using the sort can drag down
  1362          * the performance a little bit.
  1363          */
  1365         PKIX_CHECK(pkix_List_BubbleSort
  1366                 (candidates,
  1367                 pkix_Build_SortCertComparator,
  1368                 &sortedList,
  1369                 plContext),
  1370                 PKIX_LISTBUBBLESORTFAILED);
  1372         *pSortedCandidates = sortedList;
  1374 cleanup:
  1376         PKIX_RETURN(BUILD);
  1379 /*
  1380  * FUNCTION: pkix_Build_BuildSelectorAndParams
  1381  * DESCRIPTION:
  1383  *  This function creates a CertSelector, initialized with an appropriate
  1384  *  ComCertSelParams, using the variables provided in the ForwardBuilderState
  1385  *  pointed to by "state". The CertSelector created is stored in the certsel
  1386  *  element of "state".
  1388  * PARAMETERS:
  1389  *  "state"
  1390  *      Address of ForwardBuilderState to be used. Must be non-NULL.
  1391  *  "plContext"
  1392  *      Platform-specific context pointer.
  1393  * THREAD SAFETY:
  1394  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1395  * RETURNS:
  1396  *  Returns NULL if the function succeeds.
  1397  *  Returns a Build Error if the function fails in a non-fatal way
  1398  *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1399  */
  1400 static PKIX_Error *
  1401 pkix_Build_BuildSelectorAndParams(
  1402         PKIX_ForwardBuilderState *state,
  1403         void *plContext)
  1405         PKIX_ComCertSelParams *certSelParams = NULL;
  1406         PKIX_CertSelector *certSel = NULL;
  1407         PKIX_PL_X500Name *currentIssuer = NULL;
  1408         PKIX_PL_ByteArray *authKeyId = NULL;
  1409         PKIX_PL_Date *testDate = NULL;
  1410         PKIX_CertSelector *callerCertSelector = NULL;
  1411         PKIX_ComCertSelParams *callerComCertSelParams = NULL;
  1412         PKIX_UInt32 reqKu = 0;
  1413         PKIX_List   *reqEkuOids = NULL;
  1415         PKIX_ENTER(BUILD, "pkix_Build_BuildSelectorAndParams");
  1416         PKIX_NULLCHECK_THREE(state, state->prevCert, state->traversedSubjNames);
  1418         PKIX_CHECK(PKIX_PL_Cert_GetIssuer
  1419                 (state->prevCert, &currentIssuer, plContext),
  1420                 PKIX_CERTGETISSUERFAILED);
  1422         PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier
  1423                 (state->prevCert, &authKeyId, plContext),
  1424                 PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED);
  1426         PKIX_CHECK(PKIX_ComCertSelParams_Create(&certSelParams, plContext),
  1427                 PKIX_COMCERTSELPARAMSCREATEFAILED);
  1429         PKIX_CHECK(PKIX_ComCertSelParams_SetSubject
  1430                 (certSelParams, currentIssuer, plContext),
  1431                 PKIX_COMCERTSELPARAMSSETSUBJECTFAILED);
  1433         if (authKeyId != NULL) {
  1434             PKIX_CHECK(PKIX_ComCertSelParams_SetSubjKeyIdentifier
  1435                     (certSelParams, authKeyId, plContext),
  1436                     PKIX_COMCERTSELPARAMSSETSUBJKEYIDENTIFIERFAILED);
  1439         PKIX_INCREF(state->buildConstants.testDate);
  1440         testDate = state->buildConstants.testDate;
  1442         PKIX_CHECK(PKIX_ComCertSelParams_SetCertificateValid
  1443                 (certSelParams, testDate, plContext),
  1444                 PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED);
  1446         PKIX_CHECK(PKIX_ComCertSelParams_SetBasicConstraints
  1447                 (certSelParams, state->traversedCACerts, plContext),
  1448                 PKIX_COMCERTSELPARAMSSETBASICCONSTRAINTSFAILED);
  1450         PKIX_CHECK(PKIX_ComCertSelParams_SetPathToNames
  1451                 (certSelParams, state->traversedSubjNames, plContext),
  1452                 PKIX_COMCERTSELPARAMSSETPATHTONAMESFAILED);
  1454         PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
  1455                     (state->buildConstants.procParams,
  1456                      &callerCertSelector, plContext),
  1457                     PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
  1459         if (callerCertSelector != NULL) {
  1461             /* Get initial EKU OIDs from ComCertSelParams, if set */
  1462             PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
  1463                        (callerCertSelector, &callerComCertSelParams, plContext),
  1464                        PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
  1466             if (callerComCertSelParams != NULL) {
  1467                 PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage
  1468                            (callerComCertSelParams, &reqEkuOids, plContext),
  1469                            PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
  1471                 PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage
  1472                            (callerComCertSelParams, &reqKu, plContext),
  1473                            PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED);
  1477         PKIX_CHECK(
  1478             PKIX_ComCertSelParams_SetKeyUsage(certSelParams, reqKu,
  1479                                               plContext),
  1480             PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED);
  1482         PKIX_CHECK(
  1483             PKIX_ComCertSelParams_SetExtendedKeyUsage(certSelParams,
  1484                                                       reqEkuOids,
  1485                                                       plContext),
  1486             PKIX_COMCERTSELPARAMSSETEXTKEYUSAGEFAILED);
  1488         PKIX_CHECK(PKIX_CertSelector_Create
  1489                 (NULL, NULL, &state->certSel, plContext),
  1490                 PKIX_CERTSELECTORCREATEFAILED);
  1492         PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
  1493                 (state->certSel, certSelParams, plContext),
  1494                 PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
  1496         PKIX_CHECK(PKIX_List_Create(&state->candidateCerts, plContext),
  1497                 PKIX_LISTCREATEFAILED);
  1499         state->certStoreIndex = 0;
  1501 cleanup:
  1502         PKIX_DECREF(certSelParams);
  1503         PKIX_DECREF(certSel);
  1504         PKIX_DECREF(currentIssuer);
  1505         PKIX_DECREF(authKeyId);
  1506         PKIX_DECREF(testDate);
  1507         PKIX_DECREF(reqEkuOids);
  1508         PKIX_DECREF(callerComCertSelParams);
  1509         PKIX_DECREF(callerCertSelector);
  1511         PKIX_RETURN(BUILD);
  1514 /* Match trust anchor to select params in order to find next cert. */
  1515 static PKIX_Error*
  1516 pkix_Build_SelectCertsFromTrustAnchors(
  1517     PKIX_List *trustAnchorsList,
  1518     PKIX_ComCertSelParams *certSelParams,
  1519     PKIX_List **pMatchList,
  1520     void *plContext) 
  1522     int anchorIndex = 0;
  1523     PKIX_TrustAnchor *anchor = NULL;
  1524     PKIX_PL_Cert *trustedCert = NULL;
  1525     PKIX_List *matchList = NULL;
  1526     PKIX_CertSelector *certSel = NULL;
  1527     PKIX_CertSelector_MatchCallback selectorMatchCB = NULL;
  1529     PKIX_ENTER(BUILD, "pkix_Build_SelectCertsFromTrustAnchors");
  1531     PKIX_CHECK(PKIX_CertSelector_Create
  1532                (NULL, NULL, &certSel, plContext),
  1533                PKIX_CERTSELECTORCREATEFAILED);
  1534     PKIX_CHECK(PKIX_CertSelector_SetCommonCertSelectorParams
  1535                (certSel, certSelParams, plContext),
  1536                PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
  1537     PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
  1538                (certSel, &selectorMatchCB, plContext),
  1539                PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
  1541     for (anchorIndex = 0;anchorIndex < trustAnchorsList->length; anchorIndex++) {
  1542         PKIX_CHECK(
  1543             PKIX_List_GetItem(trustAnchorsList,
  1544                               anchorIndex,
  1545                               (PKIX_PL_Object **)&anchor,
  1546                               plContext),
  1547             PKIX_LISTGETITEMFAILED);
  1548         PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
  1549                    (anchor, &trustedCert, plContext),
  1550                    PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  1551         pkixErrorResult =
  1552             (*selectorMatchCB)(certSel, trustedCert, plContext);
  1553         if (!pkixErrorResult) {
  1554             if (!matchList) {
  1555                 PKIX_CHECK(PKIX_List_Create(&matchList,
  1556                                             plContext),
  1557                            PKIX_LISTCREATEFAILED);
  1559             PKIX_CHECK(
  1560                 PKIX_List_AppendItem(matchList,
  1561                     (PKIX_PL_Object*)trustedCert,
  1562                                      plContext),
  1563                 PKIX_LISTAPPENDITEMFAILED);
  1564         } else {
  1565             PKIX_DECREF(pkixErrorResult);
  1567         PKIX_DECREF(trustedCert);
  1568         PKIX_DECREF(anchor);
  1571     *pMatchList = matchList;
  1572     matchList = NULL;
  1574 cleanup:
  1575     PKIX_DECREF(matchList);
  1576     PKIX_DECREF(trustedCert);
  1577     PKIX_DECREF(anchor);
  1578     PKIX_DECREF(certSel);
  1580     PKIX_RETURN(BUILD);
  1584 static PKIX_Error*
  1585 pkix_Build_RemoveDupUntrustedCerts(
  1586     PKIX_List *trustedCertList,
  1587     PKIX_List *certsFound,
  1588     void *plContext)
  1590     PKIX_UInt32 trustIndex;
  1591     PKIX_PL_Cert *trustCert = NULL, *cert = NULL;
  1593     PKIX_ENTER(BUILD, "pkix_Build_RemoveDupUntrustedCerts");
  1594     if (trustedCertList == NULL || certsFound == NULL) {
  1595         goto cleanup;
  1597     for (trustIndex = 0;trustIndex < trustedCertList->length;
  1598         trustIndex++) {
  1599         PKIX_UInt32 certIndex = 0;
  1600         PKIX_CHECK(
  1601             PKIX_List_GetItem(trustedCertList,
  1602                               trustIndex,
  1603                               (PKIX_PL_Object **)&trustCert,
  1604                               plContext),
  1605             PKIX_LISTGETITEMFAILED);
  1607         while (certIndex < certsFound->length) {
  1608             PKIX_Boolean result = PKIX_FALSE;
  1609             PKIX_DECREF(cert);
  1610             PKIX_CHECK(
  1611                 PKIX_List_GetItem(certsFound, certIndex,
  1612                                   (PKIX_PL_Object **)&cert,
  1613                                   plContext),
  1614                 PKIX_LISTGETITEMFAILED);
  1615             PKIX_CHECK(
  1616                 PKIX_PL_Object_Equals((PKIX_PL_Object *)trustCert,
  1617                                       (PKIX_PL_Object *)cert,
  1618                                       &result,
  1619                                       plContext),
  1620                 PKIX_OBJECTEQUALSFAILED);
  1621             if (!result) {
  1622                 certIndex += 1;
  1623                 continue;
  1625             PKIX_CHECK(
  1626                 PKIX_List_DeleteItem(certsFound, certIndex,
  1627                                      plContext),
  1628                 PKIX_LISTDELETEITEMFAILED);
  1630         PKIX_DECREF(trustCert);
  1632 cleanup:
  1633     PKIX_DECREF(cert);
  1634     PKIX_DECREF(trustCert);
  1636     PKIX_RETURN(BUILD);
  1640 /*
  1641  * FUNCTION: pkix_Build_GatherCerts
  1642  * DESCRIPTION:
  1644  *  This function traverses the CertStores in the List of CertStores contained
  1645  *  in "state",  using the certSelector and other parameters contained in
  1646  *  "state", to obtain a List of all available Certs that satisfy the criteria.
  1647  *  If a CertStore has a cache, "certSelParams" is used both to query the cache
  1648  *  and, if an actual CertStore search occurred, to update the cache. (Behavior
  1649  *  is undefined if "certSelParams" is different from the parameters that were
  1650  *  used to initialize the certSelector in "state".)
  1652  *  If a CertStore using non-blocking I/O returns with an indication that I/O is
  1653  *  in progress and the checking has not been completed, this function stores
  1654  *  platform-dependent information at "pNBIOContext". Otherwise it stores NULL
  1655  *  at "pNBIOContext", and state is updated with the results of the search.
  1657  * PARAMETERS:
  1658  *  "state"
  1659  *      Address of ForwardBuilderState to be used. Must be non-NULL.
  1660  *  "certSelParams"
  1661  *      Address of ComCertSelParams which were used in creating the current
  1662  *      CertSelector, and to be used in querying and updating any caches that
  1663  *      may be associated with with the CertStores.
  1664  *  "pNBIOContext"
  1665  *      Address at which platform-dependent information is returned if request
  1666  *      is suspended for non-blocking I/O. Must be non-NULL.
  1667  *  "plContext"
  1668  *      Platform-specific context pointer.
  1669  * THREAD SAFETY:
  1670  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1671  * RETURNS:
  1672  *  Returns NULL if the function succeeds.
  1673  *  Returns a Build Error if the function fails in a non-fatal way
  1674  *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1675  */
  1676 /* return NULL if wouldblock, empty list if none found, else list of found */
  1677 static PKIX_Error *
  1678 pkix_Build_GatherCerts(
  1679         PKIX_ForwardBuilderState *state,
  1680         PKIX_ComCertSelParams *certSelParams,
  1681         void **pNBIOContext,
  1682         void *plContext)
  1684         PKIX_Boolean certStoreIsCached = PKIX_FALSE;
  1685         PKIX_Boolean certStoreIsLocal = PKIX_FALSE;
  1686         PKIX_Boolean foundInCache = PKIX_FALSE;
  1687         PKIX_CertStore *certStore = NULL;
  1688         PKIX_CertStore_CertCallback getCerts = NULL;
  1689         PKIX_List *certsFound = NULL;
  1690         PKIX_List *trustedCertList = NULL;
  1691         void *nbioContext = NULL;
  1693         PKIX_ENTER(BUILD, "pkix_Build_GatherCerts");
  1694         PKIX_NULLCHECK_THREE(state, certSelParams, pNBIOContext);
  1696         nbioContext = *pNBIOContext;
  1697         *pNBIOContext = NULL;
  1699         PKIX_DECREF(state->candidateCerts);
  1701         while (state->certStoreIndex < state->buildConstants.numCertStores) {
  1703                 /* Get the current CertStore */
  1704                 PKIX_CHECK(PKIX_List_GetItem
  1705                         (state->buildConstants.certStores,
  1706                         state->certStoreIndex,
  1707                         (PKIX_PL_Object **)&certStore,
  1708                         plContext),
  1709                         PKIX_LISTGETITEMFAILED);
  1711                 PKIX_CHECK(PKIX_CertStore_GetLocalFlag
  1712                            (certStore, &certStoreIsLocal, plContext),
  1713                            PKIX_CERTSTOREGETLOCALFLAGFAILED);
  1715                 if (state->useOnlyLocal == certStoreIsLocal) {
  1716                     /* If GATHERPENDING, we've already checked the cache */
  1717                     if (state->status == BUILD_GATHERPENDING) {
  1718                         certStoreIsCached = PKIX_FALSE;
  1719                         foundInCache = PKIX_FALSE;
  1720                     } else {
  1721                         PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
  1722                                 (certStore, &certStoreIsCached, plContext),
  1723                                 PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
  1725                         if (certStoreIsCached) {
  1726                         /*
  1727                          * Look for Certs in the cache, using the SubjectName as
  1728                          * the key. Then the ComCertSelParams are used to filter
  1729                          * for qualified certs. If none are found, then the
  1730                          * certStores are queried. When we eventually add items
  1731                          * to the cache, we will only add items that passed the
  1732                          * ComCertSelParams filter, rather than all Certs which
  1733                          * matched the SubjectName.
  1734                          */
  1736                                 PKIX_CHECK(pkix_CacheCert_Lookup
  1737                                         (certStore,
  1738                                         certSelParams,
  1739                                         state->buildConstants.testDate,
  1740                                         &foundInCache,
  1741                                         &certsFound,
  1742                                         plContext),
  1743                                         PKIX_CACHECERTCHAINLOOKUPFAILED);
  1748                     /*
  1749                      * XXX need to verify if Cert is trusted, hence may not
  1750                      * be worth it to have the Cert Cached or
  1751                      * If it is trusted, don't cache, but once there is cached
  1752                      * certs, we won't get certs from database any more.
  1753                      * can use flag to force not getting certs from cache
  1754                      */
  1755                     if (!foundInCache) {
  1757                         if (nbioContext == NULL) {
  1758                                 PKIX_CHECK(PKIX_CertStore_GetCertCallback
  1759                                         (certStore, &getCerts, plContext),
  1760                                         PKIX_CERTSTOREGETCERTCALLBACKFAILED);
  1762                                 PKIX_CHECK(getCerts
  1763                                         (certStore,
  1764                                         state->certSel,
  1765                                         state->verifyNode,
  1766                                         &nbioContext,
  1767                                         &certsFound,
  1768                                         plContext),
  1769                                         PKIX_GETCERTSFAILED);
  1770                         } else {
  1771                                 PKIX_CHECK(PKIX_CertStore_CertContinue
  1772                                         (certStore,
  1773                                         state->certSel,
  1774                                         state->verifyNode,
  1775                                         &nbioContext,
  1776                                         &certsFound,
  1777                                         plContext),
  1778                                         PKIX_CERTSTORECERTCONTINUEFAILED);
  1781                         if (certStoreIsCached && certsFound) {
  1783                                 PKIX_CHECK(pkix_CacheCert_Add
  1784                                         (certStore,
  1785                                         certSelParams,
  1786                                         certsFound,
  1787                                         plContext),
  1788                                         PKIX_CACHECERTADDFAILED);
  1792                     /*
  1793                      * getCerts returns an empty list for "NONE FOUND",
  1794                      * a NULL list for "would block"
  1795                      */
  1796                     if (certsFound == NULL) {
  1797                         state->status = BUILD_GATHERPENDING;
  1798                         *pNBIOContext = nbioContext;
  1799                         goto cleanup;
  1803                 /* Are there any more certStores to query? */
  1804                 PKIX_DECREF(certStore);
  1805                 ++(state->certStoreIndex);
  1808         if (certsFound && certsFound->length > 1) {
  1809             PKIX_List *sorted = NULL;
  1811             /* sort Certs to try to optimize search */
  1812             PKIX_CHECK(pkix_Build_SortCandidateCerts
  1813                        (certsFound, &sorted, plContext),
  1814                        PKIX_BUILDSORTCANDIDATECERTSFAILED);
  1815             PKIX_DECREF(certsFound);
  1816             certsFound = sorted;
  1819         PKIX_CHECK(
  1820             pkix_Build_SelectCertsFromTrustAnchors(
  1821                 state->buildConstants.anchors,
  1822                 certSelParams, &trustedCertList,
  1823                 plContext),
  1824             PKIX_FAILTOSELECTCERTSFROMANCHORS);
  1825         PKIX_CHECK(
  1826             pkix_Build_RemoveDupUntrustedCerts(trustedCertList,
  1827                                                certsFound,
  1828                                                plContext),
  1829             PKIX_REMOVEDUPUNTRUSTEDCERTSFAILED);
  1831         PKIX_CHECK(
  1832             pkix_List_MergeLists(trustedCertList,
  1833                                  certsFound,
  1834                                  &state->candidateCerts,
  1835                                  plContext),
  1836             PKIX_LISTMERGEFAILED);
  1838         /* No, return the list we have gathered */
  1839         PKIX_CHECK(PKIX_List_GetLength
  1840                 (state->candidateCerts, &state->numCerts, plContext),
  1841                 PKIX_LISTGETLENGTHFAILED);
  1843         state->certIndex = 0;
  1845 cleanup:
  1846         PKIX_DECREF(trustedCertList);
  1847         PKIX_DECREF(certStore);
  1848         PKIX_DECREF(certsFound);
  1850         PKIX_RETURN(BUILD);
  1853 /*
  1854  * FUNCTION: pkix_Build_UpdateDate
  1855  * DESCRIPTION:
  1857  *  This function updates the validityDate contained in "state", for the current
  1858  *  CertChain contained in "state", to include the validityDate of the
  1859  *  candidateCert contained in "state". The validityDate of a chain is the
  1860  *  earliest of all the notAfter dates contained in the respective Certificates.
  1862  * PARAMETERS:
  1863  *  "state"
  1864  *      Address of ForwardBuilderState to be used. Must be non-NULL.
  1865  *  "plContext"
  1866  *      Platform-specific context pointer.
  1867  * THREAD SAFETY:
  1868  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1869  * RETURNS:
  1870  *  Returns NULL if the function succeeds.
  1871  *  Returns a Build Error if the function fails in a non-fatal way
  1872  *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1873  */
  1874 static PKIX_Error *
  1875 pkix_Build_UpdateDate(
  1876         PKIX_ForwardBuilderState *state,
  1877         void *plContext)
  1879         PKIX_Boolean canBeCached = PKIX_FALSE;
  1880         PKIX_Int32 comparison = 0;
  1881         PKIX_PL_Date *notAfter = NULL;
  1883         PKIX_ENTER(BUILD, "pkix_Build_UpdateDate");
  1884         PKIX_NULLCHECK_ONE(state);
  1886         PKIX_CHECK(PKIX_PL_Cert_GetCacheFlag
  1887                 (state->candidateCert, &canBeCached, plContext),
  1888                 PKIX_CERTGETCACHEFLAGFAILED);
  1890         state->canBeCached = state->canBeCached && canBeCached;
  1891         if (state->canBeCached == PKIX_TRUE) {
  1893                 /*
  1894                  * So far, all certs can be cached. Update cert
  1895                  * chain validity time, which is the earliest of
  1896                  * all certs' notAfter times.
  1897                  */
  1898                 PKIX_CHECK(PKIX_PL_Cert_GetValidityNotAfter
  1899                         (state->candidateCert, &notAfter, plContext),
  1900                         PKIX_CERTGETVALIDITYNOTAFTERFAILED);
  1902                 if (state->validityDate == NULL) {
  1903                         state->validityDate = notAfter;
  1904                         notAfter = NULL;
  1905                 } else {
  1906                         PKIX_CHECK(PKIX_PL_Object_Compare
  1907                                 ((PKIX_PL_Object *)state->validityDate,
  1908                                 (PKIX_PL_Object *)notAfter,
  1909                                 &comparison,
  1910                                 plContext),
  1911                                 PKIX_OBJECTCOMPARATORFAILED);
  1912                         if (comparison > 0) {
  1913                                 PKIX_DECREF(state->validityDate);
  1914                                 state->validityDate = notAfter;
  1915                                 notAfter = NULL;
  1920 cleanup:
  1922         PKIX_DECREF(notAfter);
  1924         PKIX_RETURN(BUILD);
  1927 /* Prepare 'state' for the AIA round. */
  1928 static void
  1929 pkix_PrepareForwardBuilderStateForAIA(
  1930         PKIX_ForwardBuilderState *state)
  1932         PORT_Assert(state->useOnlyLocal == PKIX_TRUE);
  1933         state->useOnlyLocal = PKIX_FALSE;
  1934         state->certStoreIndex = 0;
  1935         state->numFanout = state->buildConstants.maxFanout;
  1936         state->status = BUILD_TRYAIA;
  1939 /*
  1940  * FUNCTION: pkix_BuildForwardDepthFirstSearch
  1941  * DESCRIPTION:
  1943  *  This function performs a depth first search in the "forward" direction (from
  1944  *  the target Cert to the trust anchor). A non-NULL targetCert must be stored
  1945  *  in the ForwardBuilderState before this function is called. It is not written
  1946  *  recursively since execution may be suspended in in any of several places
  1947  *  pending completion of non-blocking I/O. This iterative structure makes it
  1948  *  much easier to resume where it left off.
  1950  *  Since the nature of the search is recursive, the recursion is handled by
  1951  *  chaining states. That is, each new step involves creating a new
  1952  *  ForwardBuilderState linked to its predecessor. If a step turns out to be
  1953  *  fruitless, the state of the predecessor is restored and the next alternative
  1954  *  is tried. When a search is successful, values needed from the last state
  1955  *  (canBeCached and validityDate) are copied to the state provided by the
  1956  *  caller, so that the caller can retrieve those values.
  1958  *  There are three return arguments, the NBIOContext, the ValidateResult and
  1959  *  the ForwardBuilderState. If NBIOContext is non-NULL, it means the search is
  1960  *  suspended until the results of a non-blocking IO become available. The
  1961  *  caller may wait for the completion using platform-dependent methods and then
  1962  *  call this function again, allowing it to resume the search. If NBIOContext
  1963  *  is NULL and the ValidateResult is non-NULL, it means the search has
  1964  *  concluded successfully. If the NBIOContext is NULL but the ValidateResult is
  1965  *  NULL, it means the search was unsuccessful.
  1967  *  This function performs several steps at each node in the constructed chain:
  1969  *  1) It retrieves Certs from the registered CertStores that match the
  1970  *  criteria established by the ForwardBuilderState pointed to by "state", such
  1971  *  as a subject name matching the issuer name of the previous Cert. If there
  1972  *  are no matching Certs, the function returns to the previous, or "parent",
  1973  *  state and tries to continue the chain building with another of the Certs
  1974  *  obtained from the CertStores as possible issuers for that parent Cert.
  1976  *  2) For each candidate Cert returned by the CertStores, this function checks
  1977  *  whether the Cert is valid. If it is trusted, this function checks whether
  1978  *  this Cert might serve as a TrustAnchor for a complete chain.
  1980  *  3) It determines whether this Cert, in conjunction with any of the
  1981  *  TrustAnchors, might complete a chain. A complete chain, from this or the
  1982  *  preceding step, is checked to see whether it is valid as a complete
  1983  *  chain, including the checks that cannot be done in the forward direction.
  1985  *  4) If this Cert chains successfully, but is not a complete chain, that is,
  1986  *  we have not reached a trusted Cert, a new ForwardBuilderState is created
  1987  *  with this Cert as the immediate predecessor, and we continue in step (1),
  1988  *  attempting to get Certs from the CertStores with this Certs "issuer" as
  1989  *  their subject.
  1991  *  5) If an entire chain validates successfully, then we are done. A
  1992  *  ValidateResult is created containing the Public Key of the target
  1993  *  certificate (including DSA parameter inheritance, if any) and the
  1994  *  PolicyNode representing the policy tree output by the validation algorithm,
  1995  *  and stored at pValResult, and the function exits returning NULL.
  1997  *  5) If the entire chain does not validate successfully, the algorithm
  1998  *  discards the latest Cert and continues in step 2 with the next candidate
  1999  *  Cert, backing up to a parent state when no more possibilities exist at a
  2000  *  given level, and returning failure when we try to back up but discover we
  2001  *  are at the top level.
  2003  * PARAMETERS:
  2004  *  "pNBIOContext"
  2005  *      Address at which platform-dependent information is returned if building
  2006  *      is suspended for non-blocking I/O. Must be non-NULL.
  2007  *  "pState"
  2008  *      Address at which input ForwardBuilderState is found, and at which output
  2009  *      ForwardBuilderState is stored. Must be non-NULL.
  2010  *  "pValResult"
  2011  *      Address at which the ValidateResult is stored. Must be non-NULL.
  2012  *  "plContext"
  2013  *      Platform-specific context pointer.
  2014  * THREAD SAFETY:
  2015  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  2016  * RETURNS:
  2017  *  Returns NULL if the function succeeds.
  2018  *  Returns a Build Error if the function fails in a non-fatal way.
  2019  *  Returns a Fatal Error if the function fails in an unrecoverable way.
  2020  */
  2021 static PKIX_Error *
  2022 pkix_BuildForwardDepthFirstSearch(
  2023         void **pNBIOContext,
  2024         PKIX_ForwardBuilderState *state,
  2025         PKIX_ValidateResult **pValResult,
  2026         void *plContext)
  2028         PKIX_Boolean outOfOptions = PKIX_FALSE;
  2029         PKIX_Boolean trusted = PKIX_FALSE;
  2030         PKIX_Boolean isSelfIssued = PKIX_FALSE;
  2031         PKIX_Boolean canBeCached = PKIX_FALSE;
  2032         PKIX_Boolean ioPending = PKIX_FALSE;
  2033         PKIX_PL_Date *validityDate = NULL;
  2034         PKIX_PL_Date *currTime  = NULL;
  2035         PKIX_Int32 childTraversedCACerts = 0;
  2036         PKIX_UInt32 numSubjectNames = 0;
  2037         PKIX_UInt32 numChained = 0;
  2038         PKIX_Int32 cmpTimeResult = 0;
  2039         PKIX_UInt32 i = 0;
  2040         PKIX_UInt32 certsSoFar = 0;
  2041         PKIX_List *childTraversedSubjNames = NULL;
  2042         PKIX_List *subjectNames = NULL;
  2043         PKIX_List *unfilteredCerts = NULL;
  2044         PKIX_List *filteredCerts = NULL;
  2045         PKIX_PL_Object *subjectName = NULL;
  2046         PKIX_ValidateResult *valResult = NULL;
  2047         PKIX_ForwardBuilderState *childState = NULL;
  2048         PKIX_ForwardBuilderState *parentState = NULL;
  2049         PKIX_PL_Object *revCheckerState = NULL;
  2050         PKIX_ComCertSelParams *certSelParams = NULL;
  2051         PKIX_TrustAnchor *trustAnchor = NULL;
  2052         PKIX_PL_Cert *trustedCert = NULL;
  2053         PKIX_VerifyNode *verifyNode = NULL;
  2054         PKIX_Error *verifyError = NULL;
  2055         PKIX_Error *finalError = NULL;
  2056         void *nbio = NULL;
  2057         PKIX_UInt32 numIterations = 0;
  2059         PKIX_ENTER(BUILD, "pkix_BuildForwardDepthFirstSearch");
  2060         PKIX_NULLCHECK_THREE(pNBIOContext, state, pValResult);
  2062         nbio = *pNBIOContext;
  2063         *pNBIOContext = NULL;
  2064         PKIX_INCREF(state->validityDate);
  2065         validityDate = state->validityDate;
  2066         canBeCached = state->canBeCached;
  2067         PKIX_DECREF(*pValResult);
  2069         /*
  2070          * We return if successful; if we fall off the end
  2071          * of this "while" clause our search has failed.
  2072          */
  2073         while (outOfOptions == PKIX_FALSE) {
  2074             /*
  2075              * The maximum number of iterations works around a bug that
  2076              * causes this while loop to never exit when AIA and cross
  2077              * certificates are involved.  See bug xxxxx.
  2078              */
  2079             if (numIterations++ > 250)
  2080                     PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS);
  2082             if (state->buildConstants.maxTime != 0) {
  2083                     PKIX_DECREF(currTime);
  2084                     PKIX_CHECK(PKIX_PL_Date_Create_UTCTime
  2085                             (NULL, &currTime, plContext),
  2086                             PKIX_DATECREATEUTCTIMEFAILED);
  2088                     PKIX_CHECK(PKIX_PL_Object_Compare
  2089                              ((PKIX_PL_Object *)state->buildConstants.timeLimit,
  2090                              (PKIX_PL_Object *)currTime,
  2091                              &cmpTimeResult,
  2092                              plContext),
  2093                              PKIX_OBJECTCOMPARATORFAILED);
  2095                     if (cmpTimeResult < 0) {
  2096                         if (state->verifyNode != NULL) {
  2097                                 PKIX_ERROR_CREATE
  2098                                     (BUILD,
  2099                                     PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS,
  2100                                     verifyError);
  2101                                 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
  2102                                     (state->verifyNode,
  2103                                     verifyError,
  2104                                     plContext),
  2105                                     PKIX_VERIFYNODESETERRORFAILED);
  2106                                 PKIX_DECREF(finalError);
  2107                                 finalError = verifyError;
  2108                                 verifyError = NULL;
  2110                         /* Even if we logged error, we still have to abort */
  2111                         PKIX_ERROR(PKIX_TIMECONSUMEDEXCEEDSRESOURCELIMITS);
  2115             if (state->status == BUILD_INITIAL) {
  2117                 PKIX_CHECK(pkix_Build_BuildSelectorAndParams(state, plContext),
  2118                         PKIX_BUILDBUILDSELECTORANDPARAMSFAILED);
  2120                 /*
  2121                  * If the caller supplied a partial certChain (hintCerts) try
  2122                  * the next one from that List before we go to the certStores.
  2123                  */
  2124                 if (state->buildConstants.numHintCerts > 0) {
  2125                         /* How many Certs does our trust chain have already? */
  2126                         PKIX_CHECK(PKIX_List_GetLength
  2127                                 (state->trustChain, &certsSoFar, plContext),
  2128                                 PKIX_LISTGETLENGTHFAILED);
  2130                         /* That includes the target Cert. Don't count it. */
  2131                         certsSoFar--;
  2133                         /* Are we still within range of the partial chain? */
  2134                         if (certsSoFar >= state->buildConstants.numHintCerts) {
  2135                                 state->status = BUILD_TRYAIA;
  2136                         } else {
  2137                                 /*
  2138                                  * If we already have n certs, we want the n+1th
  2139                                  * (i.e., index = n) from the list of hints.
  2140                                  */
  2141                                 PKIX_DECREF(state->candidateCert);
  2142                                 PKIX_CHECK(PKIX_List_GetItem
  2143                                     (state->buildConstants.hintCerts,
  2144                                     certsSoFar,
  2145                                     (PKIX_PL_Object **)&state->candidateCert,
  2146                                     plContext),
  2147                                     PKIX_LISTGETITEMFAILED);
  2149                                 PKIX_CHECK(PKIX_List_AppendItem
  2150                                     (state->candidateCerts,
  2151                                     (PKIX_PL_Object *)state->candidateCert,
  2152                                     plContext),
  2153                                     PKIX_LISTAPPENDITEMFAILED);
  2155                                 state->numCerts = 1;
  2156                                 state->usingHintCerts = PKIX_TRUE;
  2157                                 state->status = BUILD_CERTVALIDATING;
  2159                 } else {
  2160                         state->status = BUILD_TRYAIA;
  2165             if (state->status == BUILD_TRYAIA) {
  2166                 if (state->useOnlyLocal == PKIX_TRUE) {
  2167                         state->status = BUILD_COLLECTINGCERTS;
  2168                 } else {
  2169                         state->status = BUILD_AIAPENDING;
  2173             if (state->status == BUILD_AIAPENDING &&
  2174                 state->buildConstants.aiaMgr) {
  2175                 pkixErrorResult = PKIX_PL_AIAMgr_GetAIACerts
  2176                         (state->buildConstants.aiaMgr,
  2177                         state->prevCert,
  2178                         &nbio,
  2179                         &unfilteredCerts,
  2180                          plContext);
  2182                 if (nbio != NULL) {
  2183                         /* IO still pending, resume later */
  2184                         *pNBIOContext = nbio;
  2185                         goto cleanup;
  2187                 state->numCerts = 0;
  2188                 if (pkixErrorResult) {
  2189                     pkixErrorClass = pkixErrorResult->errClass;
  2190                     if (pkixErrorClass == PKIX_FATAL_ERROR) {
  2191                         goto fatal;
  2193                     PKIX_DECREF(finalError);
  2194                     finalError = pkixErrorResult;
  2195                     pkixErrorResult = NULL;
  2196                     if (state->verifyNode != NULL) {
  2197                         /* state->verifyNode is the object that contains a list
  2198                          * of verifyNodes. verifyNodes contains cert chain
  2199                          * build failures that occurred on this level of chain
  2200                          * building.  Here, creating new verify node
  2201                          * to log the failure and adding it to the list. */
  2202                         PKIX_CHECK_FATAL(pkix_VerifyNode_Create
  2203                                          (state->prevCert,
  2204                                           0, NULL,
  2205                                           &verifyNode,
  2206                                           plContext),
  2207                                          PKIX_VERIFYNODECREATEFAILED);
  2208                         PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
  2209                                          (verifyNode, finalError, plContext),
  2210                                          PKIX_VERIFYNODESETERRORFAILED);
  2211                         PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  2212                                          (state->verifyNode,
  2213                                           verifyNode,
  2214                                           plContext),
  2215                                          PKIX_VERIFYNODEADDTOTREEFAILED);
  2216                         PKIX_DECREF(verifyNode);
  2219 #ifdef PKIX_BUILDDEBUG
  2220                 /* Turn this on to trace the List of Certs, before CertSelect */
  2222                                 PKIX_PL_String *unString;
  2223                                 char *unAscii;
  2224                                 PKIX_UInt32 length;
  2225                                 PKIX_TOSTRING
  2226                                         ((PKIX_PL_Object*)unfilteredCerts,
  2227                                         &unString,
  2228                                         plContext,
  2229                                         PKIX_OBJECTTOSTRINGFAILED);
  2231                                 PKIX_CHECK(PKIX_PL_String_GetEncoded
  2232                                         (unString,
  2233                                         PKIX_ESCASCII,
  2234                                         (void **)&unAscii,
  2235                                         &length,
  2236                                         plContext),
  2237                                         PKIX_STRINGGETENCODEDFAILED);
  2239                                 PKIX_DEBUG_ARG
  2240                                         ("unfilteredCerts = %s\n", unAscii);
  2241                                 PKIX_DECREF(unString);
  2242                                 PKIX_FREE(unAscii);
  2244 #endif
  2246                 /* Note: Certs winnowed here don't get into VerifyTree. */
  2247                 if (unfilteredCerts) {
  2248                         PKIX_CHECK(pkix_CertSelector_Select
  2249                                 (state->certSel,
  2250                                 unfilteredCerts,
  2251                                 &filteredCerts,
  2252                                 plContext),
  2253                                 PKIX_CERTSELECTORSELECTFAILED);
  2255                         PKIX_DECREF(unfilteredCerts);
  2257                         PKIX_CHECK(PKIX_List_GetLength
  2258                                 (filteredCerts, &(state->numCerts), plContext),
  2259                                 PKIX_LISTGETLENGTHFAILED);
  2261 #ifdef PKIX_BUILDDEBUG
  2262                 /* Turn this on to trace the List of Certs, after CertSelect */
  2264                         PKIX_PL_String *unString;
  2265                         char *unAscii;
  2266                         PKIX_UInt32 length;
  2267                         PKIX_TOSTRING
  2268                                 ((PKIX_PL_Object*)filteredCerts,
  2269                                 &unString,
  2270                                 plContext,
  2271                                 PKIX_OBJECTTOSTRINGFAILED);
  2273                         PKIX_CHECK(PKIX_PL_String_GetEncoded
  2274                                     (unString,
  2275                                     PKIX_ESCASCII,
  2276                                     (void **)&unAscii,
  2277                                     &length,
  2278                                     plContext),
  2279                                     PKIX_STRINGGETENCODEDFAILED);
  2281                         PKIX_DEBUG_ARG("filteredCerts = %s\n", unAscii);
  2282                         PKIX_DECREF(unString);
  2283                         PKIX_FREE(unAscii);
  2285 #endif
  2287                         PKIX_DECREF(state->candidateCerts);
  2288                         state->candidateCerts = filteredCerts;
  2289                         state->certIndex = 0;
  2290                         filteredCerts = NULL;
  2293                 /* Are there any Certs to try? */
  2294                 if (state->numCerts > 0) {
  2295                         state->status = BUILD_CERTVALIDATING;
  2296                 } else {
  2297                         state->status = BUILD_COLLECTINGCERTS;
  2301             PKIX_DECREF(certSelParams);
  2302             PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
  2303                 (state->certSel, &certSelParams, plContext),
  2304                 PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
  2306             /* **** Querying the CertStores ***** */
  2307             if ((state->status == BUILD_COLLECTINGCERTS) ||
  2308                 (state->status == BUILD_GATHERPENDING)) {
  2310 #if PKIX_FORWARDBUILDERSTATEDEBUG
  2311                 PKIX_CHECK(pkix_ForwardBuilderState_DumpState
  2312                         (state, plContext),
  2313                         PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED);
  2314 #endif
  2316                 PKIX_CHECK(pkix_Build_GatherCerts
  2317                         (state, certSelParams, &nbio, plContext),
  2318                         PKIX_BUILDGATHERCERTSFAILED);
  2320                 if (nbio != NULL) {
  2321                         /* IO still pending, resume later */
  2322                         *pNBIOContext = nbio;
  2323                         goto cleanup;
  2326                 /* Are there any Certs to try? */
  2327                 if (state->numCerts > 0) {
  2328                         state->status = BUILD_CERTVALIDATING;
  2329                 } else {
  2330                         state->status = BUILD_ABANDONNODE;
  2334             /* ****Phase 2 - Chain building***** */
  2336 #if PKIX_FORWARDBUILDERSTATEDEBUG
  2337             PKIX_CHECK(pkix_ForwardBuilderState_DumpState(state, plContext),
  2338                     PKIX_FORWARDBUILDERSTATEDUMPSTATEFAILED);
  2339 #endif
  2341             if (state->status == BUILD_CERTVALIDATING) {
  2342                     PKIX_DECREF(state->candidateCert);
  2343                     PKIX_CHECK(PKIX_List_GetItem
  2344                             (state->candidateCerts,
  2345                             state->certIndex,
  2346                             (PKIX_PL_Object **)&(state->candidateCert),
  2347                             plContext),
  2348                             PKIX_LISTGETITEMFAILED);
  2350                     if ((state->verifyNode) != NULL) {
  2351                             PKIX_CHECK_FATAL(pkix_VerifyNode_Create
  2352                                     (state->candidateCert,
  2353                                     0,
  2354                                     NULL,
  2355                                     &verifyNode,
  2356                                     plContext),
  2357                                     PKIX_VERIFYNODECREATEFAILED);
  2360                     /* If failure, this function sets Error in verifyNode */
  2361                     verifyError = pkix_Build_VerifyCertificate
  2362                             (state,
  2363                             state->buildConstants.userCheckers,
  2364                             &trusted,
  2365                             verifyNode,
  2366                             plContext);
  2368                     if (verifyError) {
  2369                             pkixTempErrorReceived = PKIX_TRUE;
  2370                             pkixErrorClass = verifyError->errClass;
  2371                             if (pkixErrorClass == PKIX_FATAL_ERROR) {
  2372                                 pkixErrorResult = verifyError;
  2373                                 verifyError = NULL;
  2374                                 goto fatal;
  2378                     if (PKIX_ERROR_RECEIVED) {
  2379                             if (state->verifyNode != NULL) {
  2380                                 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
  2381                                     (verifyNode, verifyError, plContext),
  2382                                     PKIX_VERIFYNODESETERRORFAILED);
  2383                                 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  2384                                         (state->verifyNode,
  2385                                         verifyNode,
  2386                                         plContext),
  2387                                         PKIX_VERIFYNODEADDTOTREEFAILED);
  2388                                 PKIX_DECREF(verifyNode);
  2390                             pkixTempErrorReceived = PKIX_FALSE;
  2391                             PKIX_DECREF(finalError);
  2392                             finalError = verifyError;
  2393                             verifyError = NULL;
  2394                             if (state->certLoopingDetected) {
  2395                                 PKIX_ERROR
  2396                                     (PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED);
  2398                             state->status = BUILD_GETNEXTCERT;
  2399                     } else {
  2400                             state->status = BUILD_DATEPREP;
  2404             if (state->status == BUILD_DATEPREP) {
  2405                     /* Keep track of whether this chain can be cached */
  2406                     PKIX_CHECK(pkix_Build_UpdateDate(state, plContext),
  2407                             PKIX_BUILDUPDATEDATEFAILED);
  2409                     canBeCached = state->canBeCached;
  2410                     PKIX_DECREF(validityDate);
  2411                     PKIX_INCREF(state->validityDate);
  2412                     validityDate = state->validityDate;
  2413                     if (trusted == PKIX_TRUE) {
  2414                             state->status = BUILD_CHECKTRUSTED;
  2415                     } else {
  2416                             state->status = BUILD_ADDTOCHAIN;
  2420             if (state->status == BUILD_CHECKTRUSTED) {
  2422                     /*
  2423                      * If this cert is trusted, try to validate the entire
  2424                      * chain using this certificate as trust anchor.
  2425                      */
  2426                     PKIX_CHECK(PKIX_TrustAnchor_CreateWithCert
  2427                       (state->candidateCert,
  2428                       &trustAnchor,
  2429                       plContext),
  2430                       PKIX_TRUSTANCHORCREATEWITHCERTFAILED);
  2432                     PKIX_CHECK(pkix_Build_ValidationCheckers
  2433                       (state,
  2434                       state->trustChain,
  2435                       trustAnchor,
  2436                       PKIX_FALSE, /* do not add eku checker
  2437                                    * since eku was already
  2438                                    * checked */
  2439                       plContext),
  2440                       PKIX_BUILDVALIDATIONCHECKERSFAILED);
  2442                     state->status = BUILD_CHECKTRUSTED2;
  2445             if (state->status == BUILD_CHECKTRUSTED2) {
  2446                     verifyError = 
  2447                         pkix_Build_ValidateEntireChain(state,
  2448                                                        trustAnchor,
  2449                                                        &nbio, &valResult,
  2450                                                        verifyNode,
  2451                                                        plContext);
  2452                     if (nbio != NULL) {
  2453                             /* IO still pending, resume later */
  2454                             goto cleanup;
  2455                     } else {
  2456                             /* checking the error for fatal status */
  2457                             if (verifyError) {
  2458                                 pkixTempErrorReceived = PKIX_TRUE;
  2459                                 pkixErrorClass = verifyError->errClass;
  2460                                 if (pkixErrorClass == PKIX_FATAL_ERROR) {
  2461                                     pkixErrorResult = verifyError;
  2462                                     verifyError = NULL;
  2463                                     goto fatal;
  2466                             if (state->verifyNode != NULL) {
  2467                                 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  2468                                         (state->verifyNode,
  2469                                         verifyNode,
  2470                                         plContext),
  2471                                         PKIX_VERIFYNODEADDTOTREEFAILED);
  2472                                 PKIX_DECREF(verifyNode);
  2474                             if (!PKIX_ERROR_RECEIVED) {
  2475                                 *pValResult = valResult;
  2476                                 valResult = NULL;
  2477                                 /* Change state so IsIOPending is FALSE */
  2478                                 state->status = BUILD_CHECKTRUSTED;
  2479                                 goto cleanup;
  2481                             PKIX_DECREF(finalError);
  2482                             finalError = verifyError;
  2483                             verifyError = NULL;
  2484                             /* Reset temp error that was set by 
  2485                              * PKIX_CHECK_ONLY_FATAL and continue */
  2486                             pkixTempErrorReceived = PKIX_FALSE;
  2487                             PKIX_DECREF(trustAnchor);
  2490                     /*
  2491                      * If chain doesn't validate with a trusted Cert,
  2492                      * adding more Certs to it can't help.
  2493                      */
  2494                     if (state->certLoopingDetected) {
  2495                             PKIX_DECREF(verifyError);
  2496                             PKIX_ERROR_CREATE(BUILD, 
  2497                                          PKIX_LOOPDISCOVEREDDUPCERTSNOTALLOWED,
  2498                                          verifyError);
  2499                             PKIX_CHECK_FATAL(
  2500                                 pkix_VerifyNode_SetError(state->verifyNode,
  2501                                                          verifyError,
  2502                                                          plContext),
  2503                                 PKIX_VERIFYNODESETERRORFAILED);
  2504                             PKIX_DECREF(verifyError);
  2506                     state->status = BUILD_GETNEXTCERT;
  2509             /*
  2510              * This Cert was not trusted. Add it to our chain, and
  2511              * continue building. If we don't reach a trust anchor,
  2512              * we'll take it off later and continue without it.
  2513              */
  2514             if (state->status == BUILD_ADDTOCHAIN) {
  2515                     PKIX_CHECK(PKIX_List_AppendItem
  2516                             (state->trustChain,
  2517                             (PKIX_PL_Object *)state->candidateCert,
  2518                             plContext),
  2519                             PKIX_LISTAPPENDITEMFAILED);
  2521                     state->status = BUILD_EXTENDCHAIN;
  2524             if (state->status == BUILD_EXTENDCHAIN) {
  2526                     /* Check whether we are allowed to extend the chain */
  2527                     if ((state->buildConstants.maxDepth != 0) &&
  2528                         (state->numDepth <= 1)) {
  2530                         if (state->verifyNode != NULL) {
  2531                                 PKIX_ERROR_CREATE
  2532                                     (BUILD,
  2533                                     PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS,
  2534                                     verifyError);
  2535                                 PKIX_CHECK_FATAL(pkix_VerifyNode_SetError
  2536                                     (verifyNode, verifyError, plContext),
  2537                                     PKIX_VERIFYNODESETERRORFAILED);
  2538                                 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  2539                                     (state->verifyNode, verifyNode, plContext),
  2540                                     PKIX_VERIFYNODEADDTOTREEFAILED);
  2541                                 PKIX_DECREF(verifyNode);
  2542                                 PKIX_DECREF(finalError);
  2543                                 finalError = verifyError;
  2544                                 verifyError = NULL;
  2546                         /* Even if error logged, still need to abort */
  2547                         PKIX_ERROR(PKIX_DEPTHWOULDEXCEEDRESOURCELIMITS);
  2550                     PKIX_CHECK(pkix_IsCertSelfIssued
  2551                             (state->candidateCert, &isSelfIssued, plContext),
  2552                             PKIX_ISCERTSELFISSUEDFAILED);
  2554                     PKIX_CHECK(PKIX_PL_Object_Duplicate
  2555                             ((PKIX_PL_Object *)state->traversedSubjNames,
  2556                             (PKIX_PL_Object **)&childTraversedSubjNames,
  2557                             plContext),
  2558                             PKIX_OBJECTDUPLICATEFAILED);
  2560                     if (isSelfIssued) {
  2561                             childTraversedCACerts = state->traversedCACerts;
  2562                     } else {
  2563                             childTraversedCACerts = state->traversedCACerts + 1;
  2565                             PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
  2566                                 (state->candidateCert,
  2567                                 &subjectNames,
  2568                                 plContext),
  2569                                 PKIX_CERTGETALLSUBJECTNAMESFAILED);
  2571                             if (subjectNames) {
  2572                                 PKIX_CHECK(PKIX_List_GetLength
  2573                                     (subjectNames,
  2574                                     &numSubjectNames,
  2575                                     plContext),
  2576                                     PKIX_LISTGETLENGTHFAILED);
  2578                             } else {
  2579                                 numSubjectNames = 0;
  2582                             for (i = 0; i < numSubjectNames; i++) {
  2583                                 PKIX_CHECK(PKIX_List_GetItem
  2584                                     (subjectNames,
  2585                                     i,
  2586                                     &subjectName,
  2587                                     plContext),
  2588                                     PKIX_LISTGETITEMFAILED);
  2589                                 PKIX_NULLCHECK_ONE
  2590                                     (state->traversedSubjNames);
  2591                                 PKIX_CHECK(PKIX_List_AppendItem
  2592                                     (state->traversedSubjNames,
  2593                                     subjectName,
  2594                                     plContext),
  2595                                     PKIX_LISTAPPENDITEMFAILED);
  2596                                 PKIX_DECREF(subjectName);
  2598                             PKIX_DECREF(subjectNames);
  2601                         PKIX_CHECK(pkix_ForwardBuilderState_Create
  2602                             (childTraversedCACerts,
  2603                             state->buildConstants.maxFanout,
  2604                             state->numDepth - 1,
  2605                             canBeCached,
  2606                             validityDate,
  2607                             state->candidateCert,
  2608                             childTraversedSubjNames,
  2609                             state->trustChain,
  2610                             state,
  2611                             &childState,
  2612                             plContext),
  2613                             PKIX_FORWARDBUILDSTATECREATEFAILED);
  2615                         PKIX_DECREF(childTraversedSubjNames);
  2616                         PKIX_DECREF(certSelParams);
  2617                         childState->verifyNode = verifyNode;
  2618                         verifyNode = NULL;
  2619                         PKIX_DECREF(state);
  2620                         state = childState; /* state->status == BUILD_INITIAL */
  2621                         childState = NULL;
  2622                         continue; /* with while (!outOfOptions) */
  2625             if (state->status == BUILD_GETNEXTCERT) {
  2626                     pkixTempErrorReceived = PKIX_FALSE;
  2627                     PKIX_DECREF(state->candidateCert);
  2629                     /*
  2630                      * If we were using a Cert from the callier-supplied partial
  2631                      * chain, delete it and go to the certStores.
  2632                      */
  2633                     if (state->usingHintCerts == PKIX_TRUE) {
  2634                             PKIX_DECREF(state->candidateCerts);
  2635                             PKIX_CHECK(PKIX_List_Create
  2636                                 (&state->candidateCerts, plContext),
  2637                                 PKIX_LISTCREATEFAILED);
  2639                             state->numCerts = 0;
  2640                             state->usingHintCerts = PKIX_FALSE;
  2641                             state->status = BUILD_TRYAIA;
  2642                             continue;
  2643                     } else if (++(state->certIndex) < (state->numCerts)) {
  2644                             if ((state->buildConstants.maxFanout != 0) &&
  2645                                 (--(state->numFanout) == 0)) {
  2647                                 if (state->verifyNode != NULL) {
  2648                                         PKIX_ERROR_CREATE
  2649                                             (BUILD,
  2650                                             PKIX_FANOUTEXCEEDSRESOURCELIMITS,
  2651                                             verifyError);
  2652                                         PKIX_CHECK_FATAL
  2653                                             (pkix_VerifyNode_SetError
  2654                                             (state->verifyNode,
  2655                                             verifyError,
  2656                                             plContext),
  2657                                             PKIX_VERIFYNODESETERRORFAILED);
  2658                                         PKIX_DECREF(finalError);
  2659                                         finalError = verifyError;
  2660                                         verifyError = NULL;
  2662                                 /* Even if error logged, still need to abort */
  2663                                 PKIX_ERROR
  2664                                         (PKIX_FANOUTEXCEEDSRESOURCELIMITS);
  2666                             state->status = BUILD_CERTVALIDATING;
  2667                             continue;
  2671             /*
  2672              * Adding the current cert to the chain didn't help. If our search
  2673              * has been restricted to local certStores, try opening up the
  2674              * search and see whether that helps. Otherwise, back up to the
  2675              * parent cert, and see if there are any more to try.
  2676              */
  2677             if (state->useOnlyLocal == PKIX_TRUE) {
  2678                 pkix_PrepareForwardBuilderStateForAIA(state);
  2679             } else do {
  2680                 if (state->parentState == NULL) {
  2681                         /* We are at the top level, and can't back up! */
  2682                         outOfOptions = PKIX_TRUE;
  2683                 } else {
  2684                         /*
  2685                          * Try the next cert, if any, for this parent.
  2686                          * Otherwise keep backing up until we reach a
  2687                          * parent with more certs to try.
  2688                          */
  2689                         PKIX_CHECK(PKIX_List_GetLength
  2690                                 (state->trustChain, &numChained, plContext),
  2691                                 PKIX_LISTGETLENGTHFAILED);
  2692                         PKIX_CHECK(PKIX_List_DeleteItem
  2693                                 (state->trustChain, numChained - 1, plContext),
  2694                                 PKIX_LISTDELETEITEMFAILED);
  2696                         /* local and aia fetching returned no good certs.
  2697                          * Creating a verify node in the parent that tells
  2698                          * us this. */
  2699                         if (!state->verifyNode) {
  2700                             PKIX_CHECK_FATAL(
  2701                                 pkix_VerifyNode_Create(state->prevCert,
  2702                                                        0, NULL, 
  2703                                                        &state->verifyNode,
  2704                                                        plContext),
  2705                                 PKIX_VERIFYNODECREATEFAILED);
  2707                         /* Updating the log with the error. */
  2708                         PKIX_DECREF(verifyError);
  2709                         PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER,
  2710                                           verifyError);
  2711                         PKIX_CHECK_FATAL(
  2712                             pkix_VerifyNode_SetError(state->verifyNode,
  2713                                                      verifyError,
  2714                                                      plContext),
  2715                             PKIX_VERIFYNODESETERRORFAILED);
  2716                         PKIX_DECREF(verifyError);
  2718                         PKIX_INCREF(state->parentState);
  2719                         parentState = state->parentState;
  2720                         PKIX_DECREF(verifyNode);
  2721                         verifyNode = state->verifyNode;
  2722                         state->verifyNode = NULL;
  2723                         PKIX_DECREF(state);
  2724                         state = parentState;
  2725                         parentState = NULL;
  2726                         if (state->verifyNode != NULL && verifyNode) {
  2727                                 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  2728                                         (state->verifyNode,
  2729                                         verifyNode,
  2730                                         plContext),
  2731                                         PKIX_VERIFYNODEADDTOTREEFAILED);
  2732                                 PKIX_DECREF(verifyNode);
  2734                         PKIX_DECREF(validityDate);
  2735                         PKIX_INCREF(state->validityDate);
  2736                         validityDate = state->validityDate;
  2737                         canBeCached = state->canBeCached;
  2739                         /* Are there any more Certs to try? */
  2740                         if (++(state->certIndex) < (state->numCerts)) {
  2741                                 state->status = BUILD_CERTVALIDATING;
  2742                                 PKIX_DECREF(state->candidateCert);
  2743                                 break;
  2745                         if (state->useOnlyLocal == PKIX_TRUE) {
  2746                             /* Clean up and go for AIA round. */
  2747                             pkix_PrepareForwardBuilderStateForAIA(state);
  2748                             break;
  2751                 PKIX_DECREF(state->candidateCert);
  2752             } while (outOfOptions == PKIX_FALSE);
  2754         } /* while (outOfOptions == PKIX_FALSE) */
  2756 cleanup:
  2758         if (pkixErrorClass == PKIX_FATAL_ERROR) {
  2759             goto fatal;
  2762         /* verifyNode should be equal to NULL at this point. Assert it.
  2763          * Temporarelly use verifyError to store an error ref to which we
  2764          * have in pkixErrorResult. This is done to prevent error cloberring
  2765          * while using macros below. */
  2766         PORT_Assert(verifyError == NULL);
  2767         verifyError = pkixErrorResult;
  2769         /*
  2770          * We were called with an initialState that had no parent. If we are
  2771          * returning with an error or with a result, we must destroy any state
  2772          * that we created (any state with a parent).
  2773          */
  2775         PKIX_CHECK_FATAL(pkix_ForwardBuilderState_IsIOPending
  2776                          (state, &ioPending, plContext),
  2777                 PKIX_FORWARDBUILDERSTATEISIOPENDINGFAILED);
  2779         if (ioPending == PKIX_FALSE) {
  2780                 while (state->parentState) {
  2781                         PKIX_INCREF(state->parentState);
  2782                         parentState = state->parentState;
  2783                         PKIX_DECREF(verifyNode);
  2784                         verifyNode = state->verifyNode;
  2785                         state->verifyNode = NULL;
  2786                         PKIX_DECREF(state);
  2787                         state = parentState;
  2788                         parentState = NULL;
  2789                         if (state->verifyNode != NULL && verifyNode) {
  2790                                 PKIX_CHECK_FATAL(pkix_VerifyNode_AddToTree
  2791                                         (state->verifyNode,
  2792                                         verifyNode,
  2793                                         plContext),
  2794                                         PKIX_VERIFYNODEADDTOTREEFAILED);
  2795                                 PKIX_DECREF(verifyNode);
  2798                 state->canBeCached = canBeCached;
  2799                 PKIX_DECREF(state->validityDate);
  2800                 state->validityDate = validityDate;
  2801                 validityDate = NULL;
  2803         if (!*pValResult && !verifyError) {
  2804             if (!finalError) {
  2805                 PKIX_CHECK_FATAL(
  2806                     pkix_VerifyNode_FindError(state->verifyNode,
  2807                                               &finalError,
  2808                                               plContext),
  2809                     PKIX_VERIFYNODEFINDERRORFAILED);
  2811             if (finalError) {
  2812                 pkixErrorResult = finalError;
  2813                 pkixErrorCode = PKIX_BUILDFORWARDDEPTHFIRSTSEARCHFAILED;
  2814                 finalError = NULL;
  2815                 goto fatal;
  2817             pkixErrorCode = PKIX_SECERRORUNKNOWNISSUER;
  2818             pkixErrorReceived = PKIX_TRUE;
  2819             PKIX_ERROR_CREATE(BUILD, PKIX_SECERRORUNKNOWNISSUER,
  2820                               verifyError);
  2821             PKIX_CHECK_FATAL(
  2822                 pkix_VerifyNode_SetError(state->verifyNode, verifyError,
  2823                                          plContext),
  2824                 PKIX_VERIFYNODESETERRORFAILED);
  2825         } else {
  2826             pkixErrorResult = verifyError;
  2827             verifyError = NULL;
  2830 fatal:
  2831         if (state->parentState) {
  2832             /* parentState in "state" object should be NULL at this point.
  2833              * If itn't, that means that we got fatal error(we have jumped to
  2834              * "fatal" label) and we should destroy all state except the top one. */
  2835             while (state->parentState) {
  2836                 PKIX_Error *error = NULL;
  2837                 PKIX_ForwardBuilderState *prntState = state->parentState;
  2838                 /* Dumb: need to increment parentState to avoid destruction
  2839                  * of "build constants"(they get destroyed when parentState is
  2840                  * set to NULL. */
  2841                 PKIX_INCREF(prntState);
  2842                 error = PKIX_PL_Object_DecRef((PKIX_PL_Object*)state, plContext);
  2843                 if (error) {
  2844                     PKIX_PL_Object_DecRef((PKIX_PL_Object*)error, plContext);
  2846                 /* No need to decref the parent state. It was already done by
  2847                  * pkix_ForwardBuilderState_Destroy function. */
  2848                 state = prntState;
  2851         PKIX_DECREF(parentState);
  2852         PKIX_DECREF(childState);
  2853         PKIX_DECREF(valResult);
  2854         PKIX_DECREF(verifyError);
  2855         PKIX_DECREF(finalError);
  2856         PKIX_DECREF(verifyNode);
  2857         PKIX_DECREF(childTraversedSubjNames);
  2858         PKIX_DECREF(certSelParams);
  2859         PKIX_DECREF(subjectNames);
  2860         PKIX_DECREF(subjectName);
  2861         PKIX_DECREF(trustAnchor);
  2862         PKIX_DECREF(validityDate);
  2863         PKIX_DECREF(revCheckerState);
  2864         PKIX_DECREF(currTime);
  2865         PKIX_DECREF(filteredCerts);
  2866         PKIX_DECREF(unfilteredCerts);
  2867         PKIX_DECREF(trustedCert);
  2869         PKIX_RETURN(BUILD);
  2872 /*
  2873  * FUNCTION: pkix_Build_CheckInCache
  2874  * DESCRIPTION:
  2876  * The function tries to locate a chain for a cert in the cert chain cache.
  2877  * If found, the chain goes through revocation chacking and returned back to
  2878  * caller. Chains that fail revocation check get removed from cache.
  2880  * PARAMETERS:
  2881  *  "state"
  2882  *      Address of ForwardBuilderState to be used. Must be non-NULL.
  2883  *  "pBuildResult"
  2884  *      Address at which the BuildResult is stored, after a successful build.
  2885  *      Must be non-NULL.
  2886  *  "pNBIOContext"
  2887  *      Address at which the NBIOContext is stored indicating whether the
  2888  *      validation is complete. Must be non-NULL.
  2889  *  "plContext"
  2890  *      Platform-specific context pointer.
  2891  * THREAD SAFETY:
  2892  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  2893  * RETURNS:
  2894  *  Returns NULL if the function succeeds.
  2895  *  Returns a Build Error if the function fails in a non-fatal way
  2896  *  Returns a Fatal Error if the function fails in an unrecoverable way.
  2897  */
  2898 static PKIX_Error*
  2899 pkix_Build_CheckInCache(
  2900         PKIX_ForwardBuilderState *state,
  2901         PKIX_BuildResult **pBuildResult,
  2902         void **pNBIOContext,
  2903         void *plContext)
  2905         PKIX_PL_Cert *targetCert = NULL;
  2906         PKIX_List *anchors = NULL;
  2907         PKIX_PL_Date *testDate = NULL;
  2908         PKIX_BuildResult *buildResult = NULL;
  2909         PKIX_ValidateResult *valResult = NULL;
  2910         PKIX_Error *buildError = NULL;
  2911         PKIX_TrustAnchor *matchingAnchor = NULL;
  2912         PKIX_PL_Cert *trustedCert = NULL;
  2913         PKIX_List *certList = NULL;
  2914         PKIX_Boolean cacheHit = PKIX_FALSE;
  2915         PKIX_Boolean trusted = PKIX_FALSE;
  2916         PKIX_Boolean stillValid = PKIX_FALSE;
  2917         void *nbioContext = NULL;
  2919         PKIX_ENTER(BUILD, "pkix_Build_CheckInCache");
  2921         nbioContext = *pNBIOContext;
  2922         *pNBIOContext = NULL;
  2924         targetCert = state->buildConstants.targetCert;
  2925         anchors = state->buildConstants.anchors;
  2926         testDate = state->buildConstants.testDate;
  2928         /* Check whether this cert verification has been cached. */
  2929         PKIX_CHECK(pkix_CacheCertChain_Lookup
  2930                    (targetCert,
  2931                     anchors,
  2932                     testDate,
  2933                     &cacheHit,
  2934                     &buildResult,
  2935                     plContext),
  2936                    PKIX_CACHECERTCHAINLOOKUPFAILED);
  2938         if (!cacheHit) {
  2939             goto cleanup;
  2942         /*
  2943          * We found something in cache. Verify that the anchor
  2944          * cert is still trusted,
  2945          */
  2946         PKIX_CHECK(PKIX_BuildResult_GetValidateResult
  2947                    (buildResult, &valResult, plContext),
  2948                    PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
  2950         PKIX_CHECK(PKIX_ValidateResult_GetTrustAnchor
  2951                        (valResult, &matchingAnchor, plContext),
  2952                    PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
  2954         PKIX_DECREF(valResult);
  2956         PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
  2957                    (matchingAnchor, &trustedCert, plContext),
  2958                    PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  2960         if (anchors && state->buildConstants.numAnchors) {
  2961             /* Check if it is one of the trust anchors */
  2962             PKIX_CHECK(
  2963                 pkix_List_Contains(anchors,
  2964                                    (PKIX_PL_Object *)matchingAnchor,
  2965                                    &trusted,
  2966                                    plContext),
  2967                 PKIX_LISTCONTAINSFAILED);
  2970         if ((!trusted && !state->buildConstants.trustOnlyUserAnchors) ||
  2971             !state->buildConstants.numAnchors) {
  2972             /* If it is not one of the trust anchors and the trust anchors
  2973              * are supplemental, or if there are no trust anchors, then check
  2974              * if the cert is trusted directly.
  2975              */
  2976             PKIX_CHECK(
  2977                 PKIX_PL_Cert_IsCertTrusted(trustedCert,
  2978                                            PKIX_PL_TrustAnchorMode_Ignore,
  2979                                            &trusted, plContext),
  2980                 PKIX_CERTISCERTTRUSTEDFAILED);
  2983         if (!trusted) {
  2984             goto cleanup;
  2986         /*
  2987          * Since the key usage may vary for different
  2988          * applications, we need to verify the chain again.
  2989          * Reverification will be improved with a fix for 397805.
  2990          */
  2991         PKIX_CHECK(PKIX_BuildResult_GetCertChain
  2992                    (buildResult, &certList, plContext),
  2993                    PKIX_BUILDRESULTGETCERTCHAINFAILED);
  2995         PKIX_CHECK(pkix_Build_ValidationCheckers
  2996                    (state,
  2997                     certList,
  2998                     matchingAnchor,
  2999                     PKIX_TRUE,  /* Chain revalidation stage. */
  3000                     plContext),
  3001                    PKIX_BUILDVALIDATIONCHECKERSFAILED);
  3003         PKIX_CHECK_ONLY_FATAL(
  3004             pkix_Build_ValidateEntireChain(state, matchingAnchor,
  3005                                            &nbioContext, &valResult,
  3006                                            state->verifyNode, plContext),
  3007             PKIX_BUILDVALIDATEENTIRECHAINFAILED);
  3009         if (nbioContext != NULL) {
  3010             /* IO still pending, resume later */
  3011             *pNBIOContext = nbioContext;
  3012             goto cleanup;
  3014         if (!PKIX_ERROR_RECEIVED) {
  3015             /* The result from cache is still valid. But we replace an old*/
  3016             *pBuildResult = buildResult;
  3017             buildResult = NULL;
  3018             stillValid = PKIX_TRUE;
  3021 cleanup:
  3023         if (!nbioContext && cacheHit && !(trusted && stillValid)) {
  3024             /* The anchor of this chain is no longer trusted or
  3025              * chain cert(s) has been revoked.
  3026              * Invalidate this result in the cache */
  3027             buildError = pkixErrorResult;
  3028             PKIX_CHECK_FATAL(pkix_CacheCertChain_Remove
  3029                        (targetCert,
  3030                         anchors,
  3031                         plContext),
  3032                        PKIX_CACHECERTCHAINREMOVEFAILED);
  3033             pkixErrorResult = buildError;
  3034             buildError = NULL;
  3037 fatal:
  3038        PKIX_DECREF(buildResult);
  3039        PKIX_DECREF(valResult);
  3040        PKIX_DECREF(buildError);
  3041        PKIX_DECREF(certList);
  3042        PKIX_DECREF(matchingAnchor);
  3043        PKIX_DECREF(trustedCert);
  3046        PKIX_RETURN(BUILD);
  3049 /*
  3050  * FUNCTION: pkix_Build_InitiateBuildChain
  3051  * DESCRIPTION:
  3053  *  This function initiates the search for a BuildChain, using the parameters
  3054  *  provided in "procParams" and, if continuing a search that was suspended
  3055  *  for I/O, using the ForwardBuilderState pointed to by "pState".
  3057  *  If a successful chain is built, this function stores the BuildResult at
  3058  *  "pBuildResult". Alternatively, if an operation using non-blocking I/O
  3059  *  is in progress and the operation has not been completed, this function
  3060  *  stores the platform-dependent non-blocking I/O context (nbioContext) at
  3061  *  "pNBIOContext", the FowardBuilderState at "pState", and NULL at
  3062  *  "pBuildResult". Finally, if chain building was unsuccessful, this function
  3063  *  stores NULL at both "pState" and at "pBuildResult".
  3065  *  Note: This function is re-entered only for the case of non-blocking I/O
  3066  *  in the "short-cut" attempt to build a chain using the target Certificate
  3067  *  directly with one of the trustAnchors. For all other cases, resumption
  3068  *  after non-blocking I/O is via pkix_Build_ResumeBuildChain.
  3070  * PARAMETERS:
  3071  *  "procParams"
  3072  *      Address of the ProcessingParams for the search. Must be non-NULL.
  3073  *  "pNBIOContext"
  3074  *      Address at which the NBIOContext is stored indicating whether the
  3075  *      validation is complete. Must be non-NULL.
  3076  *  "pState"
  3077  *      Address at which the ForwardBuilderState is stored, if the chain
  3078  *      building is suspended for waiting I/O; also, the address at which the
  3079  *      ForwardBuilderState is provided for resumption of the chain building
  3080  *      attempt. Must be non-NULL.
  3081  *  "pBuildResult"
  3082  *      Address at which the BuildResult is stored, after a successful build.
  3083  *      Must be non-NULL.
  3084  *  "pVerifyNode"
  3085  *      Address at which a VerifyNode chain is returned, if non-NULL.
  3086  *  "plContext"
  3087  *      Platform-specific context pointer.
  3088  * THREAD SAFETY:
  3089  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  3090  * RETURNS:
  3091  *  Returns NULL if the function succeeds.
  3092  *  Returns a Build Error if the function fails in a non-fatal way
  3093  *  Returns a Fatal Error if the function fails in an unrecoverable way.
  3094  */
  3095 static PKIX_Error *
  3096 pkix_Build_InitiateBuildChain(
  3097         PKIX_ProcessingParams *procParams,
  3098         void **pNBIOContext,
  3099         PKIX_ForwardBuilderState **pState,
  3100         PKIX_BuildResult **pBuildResult,
  3101         PKIX_VerifyNode **pVerifyNode,
  3102         void *plContext)
  3104         PKIX_UInt32 numAnchors = 0;
  3105         PKIX_UInt32 numCertStores = 0;
  3106         PKIX_UInt32 numHintCerts = 0;
  3107         PKIX_UInt32 i = 0;
  3108         PKIX_Boolean isDuplicate = PKIX_FALSE;
  3109         PKIX_PL_Cert *trustedCert = NULL;
  3110         PKIX_CertSelector *targetConstraints = NULL;
  3111         PKIX_ComCertSelParams *targetParams = NULL;
  3112         PKIX_List *anchors = NULL;
  3113         PKIX_List *targetSubjNames = NULL;
  3114         PKIX_PL_Cert *targetCert = NULL;
  3115         PKIX_PL_Object *firstHintCert = NULL;
  3116         PKIX_RevocationChecker *revChecker = NULL;
  3117         PKIX_List *certStores = NULL;
  3118         PKIX_CertStore *certStore = NULL;
  3119         PKIX_List *userCheckers = NULL;
  3120         PKIX_List *hintCerts = NULL;
  3121         PKIX_PL_Date *testDate = NULL;
  3122         PKIX_PL_PublicKey *targetPubKey = NULL;
  3123         void *nbioContext = NULL;
  3124         BuildConstants buildConstants;
  3126         PKIX_List *tentativeChain = NULL;
  3127         PKIX_ValidateResult *valResult = NULL;
  3128         PKIX_BuildResult *buildResult = NULL;
  3129         PKIX_List *certList = NULL;
  3130         PKIX_ForwardBuilderState *state = NULL;
  3131         PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
  3132         PKIX_CertSelector_MatchCallback selectorCallback = NULL;
  3133         PKIX_Boolean trusted = PKIX_FALSE;
  3134         PKIX_PL_AIAMgr *aiaMgr = NULL;
  3136         PKIX_ENTER(BUILD, "pkix_Build_InitiateBuildChain");
  3137         PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult);
  3139         nbioContext = *pNBIOContext;
  3140         *pNBIOContext = NULL;
  3142         state = *pState;
  3143         *pState = NULL; /* no net change in reference count */
  3145         if (state == NULL) {
  3146             PKIX_CHECK(PKIX_ProcessingParams_GetDate
  3147                     (procParams, &testDate, plContext),
  3148                     PKIX_PROCESSINGPARAMSGETDATEFAILED);
  3150             PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
  3151                     (procParams, &anchors, plContext),
  3152                     PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);
  3154             PKIX_CHECK(PKIX_List_GetLength(anchors, &numAnchors, plContext),
  3155                     PKIX_LISTGETLENGTHFAILED);
  3157             /* retrieve stuff from targetCertConstraints */
  3158             PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
  3159                        (procParams, &targetConstraints, plContext),
  3160                        PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
  3162             PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
  3163                     (targetConstraints, &targetParams, plContext),
  3164                     PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
  3166             PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate
  3167                     (targetParams, &targetCert, plContext),
  3168                     PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED);
  3170             PKIX_CHECK(
  3171                 PKIX_ComCertSelParams_SetLeafCertFlag(targetParams,
  3172                                                       PKIX_TRUE, plContext),
  3173                 PKIX_COMCERTSELPARAMSSETLEAFCERTFLAGFAILED);
  3175             PKIX_CHECK(PKIX_ProcessingParams_GetHintCerts
  3176                         (procParams, &hintCerts, plContext),
  3177                         PKIX_PROCESSINGPARAMSGETHINTCERTSFAILED);
  3179             if (hintCerts != NULL) {
  3180                     PKIX_CHECK(PKIX_List_GetLength
  3181                             (hintCerts, &numHintCerts, plContext),
  3182                             PKIX_LISTGETLENGTHFAILED);
  3185             /*
  3186              * Caller must provide either a target Cert
  3187              * (in ComCertSelParams->Certificate) or a partial Cert
  3188              * chain (in ProcParams->HintCerts).
  3189              */
  3191             if (targetCert == NULL) {
  3193                     /* Use first cert of hintCerts as the targetCert */
  3194                     if (numHintCerts == 0) {
  3195                             PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED);
  3198                     PKIX_CHECK(PKIX_List_GetItem
  3199                             (hintCerts,
  3200                             0,
  3201                             (PKIX_PL_Object **)&targetCert,
  3202                             plContext),
  3203                             PKIX_LISTGETITEMFAILED);
  3205                     PKIX_CHECK(PKIX_List_DeleteItem(hintCerts, 0, plContext),
  3206                             PKIX_LISTGETITEMFAILED);
  3207             } else {
  3209                     /*
  3210                      * If the first hintCert is the same as the targetCert,
  3211                      * delete it from hintCerts.
  3212                      */ 
  3213                     if (numHintCerts != 0) {
  3214                             PKIX_CHECK(PKIX_List_GetItem
  3215                                     (hintCerts, 0, &firstHintCert, plContext),
  3216                                     PKIX_LISTGETITEMFAILED);
  3218                             PKIX_CHECK(PKIX_PL_Object_Equals
  3219                                     ((PKIX_PL_Object *)targetCert,
  3220                                     firstHintCert,
  3221                                     &isDuplicate,
  3222                                     plContext),
  3223                                     PKIX_OBJECTEQUALSFAILED);
  3225                             if (isDuplicate) {
  3226                                     PKIX_CHECK(PKIX_List_DeleteItem
  3227                                     (hintCerts, 0, plContext),
  3228                                     PKIX_LISTGETITEMFAILED);
  3230                             PKIX_DECREF(firstHintCert);
  3235             if (targetCert == NULL) {
  3236                 PKIX_ERROR(PKIX_NOTARGETCERTSUPPLIED);
  3239             PKIX_CHECK(PKIX_PL_Cert_IsLeafCertTrusted
  3240                     (targetCert,
  3241                     &trusted, 
  3242                     plContext),
  3243                     PKIX_CERTISCERTTRUSTEDFAILED);
  3245             PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
  3246                     (targetCert,
  3247                     &targetSubjNames,
  3248                     plContext),
  3249                     PKIX_CERTGETALLSUBJECTNAMESFAILED);
  3251             PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
  3252                     (targetCert, &targetPubKey, plContext),
  3253                     PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
  3255             PKIX_CHECK(PKIX_List_Create(&tentativeChain, plContext),
  3256                     PKIX_LISTCREATEFAILED);
  3258             PKIX_CHECK(PKIX_List_AppendItem
  3259                     (tentativeChain, (PKIX_PL_Object *)targetCert, plContext),
  3260                     PKIX_LISTAPPENDITEMFAILED);
  3262             if (procParams->qualifyTargetCert) {
  3263                 /* EE cert validation */
  3264                 /* Sync up the time on the target selector parameter struct. */
  3265                 PKIX_CHECK(
  3266                     PKIX_ComCertSelParams_SetCertificateValid(targetParams,
  3267                                                               testDate,
  3268                                                               plContext),
  3269                     PKIX_COMCERTSELPARAMSSETCERTIFICATEVALIDFAILED);
  3271                 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
  3272                            (targetConstraints, &selectorCallback, plContext),
  3273                            PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
  3275                 pkixErrorResult =
  3276                     (*selectorCallback)(targetConstraints, targetCert,
  3277                                         plContext);
  3278                 if (pkixErrorResult) {
  3279                     pkixErrorClass = pkixErrorResult->errClass;
  3280                     if (pkixErrorClass == PKIX_FATAL_ERROR) {
  3281                         goto cleanup;
  3283                     if (pVerifyNode != NULL) {
  3284                             PKIX_Error *tempResult =
  3285                                 pkix_VerifyNode_Create(targetCert, 0,
  3286                                                        pkixErrorResult,
  3287                                                        pVerifyNode,
  3288                                                        plContext);
  3289                             if (tempResult) {
  3290                                 PKIX_DECREF(pkixErrorResult);
  3291                                 pkixErrorResult = tempResult;
  3292                                 pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
  3293                                 pkixErrorClass = PKIX_FATAL_ERROR;
  3294                                 goto cleanup;
  3297                     pkixErrorCode = PKIX_CERTCHECKVALIDITYFAILED;
  3298                     goto cleanup;
  3302             /* If the EE cert is trusted, force success. We only want to do
  3303              * this if we aren't validating against a policy (like EV). */
  3304             if (trusted && procParams->initialPolicies == NULL) {
  3305                 if (pVerifyNode != NULL) {
  3306                     PKIX_Error *tempResult =
  3307                         pkix_VerifyNode_Create(targetCert, 0, NULL,
  3308                                                pVerifyNode,
  3309                                                plContext);
  3310                     if (tempResult) {
  3311                         pkixErrorResult = tempResult;
  3312                         pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
  3313                         pkixErrorClass = PKIX_FATAL_ERROR;
  3314                         goto cleanup;
  3317                 PKIX_CHECK(pkix_ValidateResult_Create
  3318                         (targetPubKey, NULL /* anchor */,
  3319                          NULL /* policyTree */, &valResult, plContext),
  3320                         PKIX_VALIDATERESULTCREATEFAILED);
  3321                 PKIX_CHECK(
  3322                     pkix_BuildResult_Create(valResult, tentativeChain,
  3323                                             &buildResult, plContext),
  3324                     PKIX_BUILDRESULTCREATEFAILED);
  3325                 *pBuildResult = buildResult;
  3326                 /* Note that *pState is NULL.   The only side effect is that
  3327                  * the cert chain won't be cached in PKIX_BuildChain, which
  3328                  * is fine. */
  3329                 goto cleanup;
  3332             PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
  3333                     (procParams, &certStores, plContext),
  3334                     PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
  3336             PKIX_CHECK(PKIX_List_GetLength
  3337                     (certStores, &numCertStores, plContext),
  3338                     PKIX_LISTGETLENGTHFAILED);
  3340             /* Reorder CertStores so trusted are at front of the List */
  3341             if (numCertStores > 1) {
  3342                 for (i = numCertStores - 1; i > 0; i--) {
  3343                     PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem
  3344                         (certStores,
  3345                         i,
  3346                         (PKIX_PL_Object **)&certStore,
  3347                         plContext),
  3348                         PKIX_LISTGETITEMFAILED);
  3349                     PKIX_CHECK_ONLY_FATAL(PKIX_CertStore_GetTrustCallback
  3350                         (certStore, &trustCallback, plContext),
  3351                         PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
  3353                     if (trustCallback != NULL) {
  3354                         /* Is a trusted Cert, move CertStore to front */
  3355                         PKIX_CHECK(PKIX_List_DeleteItem
  3356                             (certStores, i, plContext),
  3357                             PKIX_LISTDELETEITEMFAILED);
  3358                         PKIX_CHECK(PKIX_List_InsertItem
  3359                             (certStores,
  3360                             0,
  3361                             (PKIX_PL_Object *)certStore,
  3362                             plContext),
  3363                         PKIX_LISTINSERTITEMFAILED);
  3367                     PKIX_DECREF(certStore);
  3371             PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
  3372                         (procParams, &userCheckers, plContext),
  3373                         PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
  3375             PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
  3376                         (procParams, &revChecker, plContext),
  3377                        PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
  3378             /* Do not initialize AIA manager if we are not going to fetch
  3379              * cert using aia url. */
  3380             if (procParams->useAIAForCertFetching) {
  3381                 PKIX_CHECK(PKIX_PL_AIAMgr_Create(&aiaMgr, plContext),
  3382                            PKIX_AIAMGRCREATEFAILED);
  3385             /*
  3386              * We initialize all the fields of buildConstants here, in one place,
  3387              * just to help keep track and ensure that we got everything.
  3388              */
  3390             buildConstants.numAnchors = numAnchors;
  3391             buildConstants.numCertStores = numCertStores;
  3392             buildConstants.numHintCerts = numHintCerts;
  3393             buildConstants.procParams = procParams;
  3394             buildConstants.testDate = testDate;
  3395             buildConstants.timeLimit = NULL;
  3396             buildConstants.targetCert = targetCert;
  3397             buildConstants.targetPubKey = targetPubKey;
  3398             buildConstants.certStores = certStores;
  3399             buildConstants.anchors = anchors;
  3400             buildConstants.userCheckers = userCheckers;
  3401             buildConstants.hintCerts = hintCerts;
  3402             buildConstants.revChecker = revChecker;
  3403             buildConstants.aiaMgr = aiaMgr;
  3404             buildConstants.trustOnlyUserAnchors =
  3405                     procParams->useOnlyTrustAnchors;
  3407             PKIX_CHECK(pkix_Build_GetResourceLimits(&buildConstants, plContext),
  3408                     PKIX_BUILDGETRESOURCELIMITSFAILED);
  3410             PKIX_CHECK(pkix_ForwardBuilderState_Create
  3411                     (0,              /* PKIX_UInt32 traversedCACerts */
  3412                     buildConstants.maxFanout,
  3413                     buildConstants.maxDepth,
  3414                     PKIX_TRUE,       /* PKIX_Boolean canBeCached */
  3415                     NULL,            /* PKIX_Date *validityDate */
  3416                     targetCert,      /* PKIX_PL_Cert *prevCert */
  3417                     targetSubjNames, /* PKIX_List *traversedSubjNames */
  3418                     tentativeChain,  /* PKIX_List *trustChain */
  3419                     NULL,            /* PKIX_ForwardBuilderState *parent */
  3420                     &state,          /* PKIX_ForwardBuilderState **pState */
  3421                     plContext),
  3422                     PKIX_BUILDSTATECREATEFAILED);
  3424             state->buildConstants.numAnchors = buildConstants.numAnchors;
  3425             state->buildConstants.numCertStores = buildConstants.numCertStores; 
  3426             state->buildConstants.numHintCerts = buildConstants.numHintCerts;
  3427             state->buildConstants.maxFanout = buildConstants.maxFanout;
  3428             state->buildConstants.maxDepth = buildConstants.maxDepth;
  3429             state->buildConstants.maxTime = buildConstants.maxTime;
  3430             state->buildConstants.procParams = buildConstants.procParams; 
  3431             PKIX_INCREF(buildConstants.testDate);
  3432             state->buildConstants.testDate = buildConstants.testDate;
  3433             state->buildConstants.timeLimit = buildConstants.timeLimit;
  3434             PKIX_INCREF(buildConstants.targetCert);
  3435             state->buildConstants.targetCert = buildConstants.targetCert;
  3436             PKIX_INCREF(buildConstants.targetPubKey);
  3437             state->buildConstants.targetPubKey =
  3438                     buildConstants.targetPubKey;
  3439             PKIX_INCREF(buildConstants.certStores);
  3440             state->buildConstants.certStores = buildConstants.certStores;
  3441             PKIX_INCREF(buildConstants.anchors);
  3442             state->buildConstants.anchors = buildConstants.anchors;
  3443             PKIX_INCREF(buildConstants.userCheckers);
  3444             state->buildConstants.userCheckers =
  3445                     buildConstants.userCheckers;
  3446             PKIX_INCREF(buildConstants.hintCerts);
  3447             state->buildConstants.hintCerts = buildConstants.hintCerts;
  3448             PKIX_INCREF(buildConstants.revChecker);
  3449             state->buildConstants.revChecker = buildConstants.revChecker;
  3450             state->buildConstants.aiaMgr = buildConstants.aiaMgr;
  3451             aiaMgr = NULL;
  3452             state->buildConstants.trustOnlyUserAnchors =
  3453                     buildConstants.trustOnlyUserAnchors;
  3455             if (buildConstants.maxTime != 0) {
  3456                     PKIX_CHECK(PKIX_PL_Date_Create_CurrentOffBySeconds
  3457                             (buildConstants.maxTime,
  3458                             &state->buildConstants.timeLimit,
  3459                             plContext),
  3460                             PKIX_DATECREATECURRENTOFFBYSECONDSFAILED);
  3463             if (pVerifyNode != NULL) {
  3464                 PKIX_Error *tempResult =
  3465                     pkix_VerifyNode_Create(targetCert, 0, NULL,
  3466                                            &(state->verifyNode),
  3467                                            plContext);
  3468                 if (tempResult) {
  3469                     pkixErrorResult = tempResult;
  3470                     pkixErrorCode = PKIX_VERIFYNODECREATEFAILED;
  3471                     pkixErrorClass = PKIX_FATAL_ERROR;
  3472                     goto cleanup;
  3476             PKIX_CHECK_ONLY_FATAL(
  3477                 pkix_Build_CheckInCache(state, &buildResult,
  3478                                         &nbioContext, plContext),
  3479                 PKIX_UNABLETOBUILDCHAIN);
  3480             if (nbioContext) {
  3481                 *pNBIOContext = nbioContext;
  3482                 *pState = state;
  3483                 state = NULL;
  3484                 goto cleanup;
  3486             if (buildResult) {
  3487                 *pBuildResult = buildResult;
  3488                 if (pVerifyNode != NULL) {
  3489                     *pVerifyNode = state->verifyNode;
  3490                     state->verifyNode = NULL;
  3492                 goto cleanup;
  3496         /* If we're resuming after non-blocking I/O we need to get SubjNames */
  3497         if (targetSubjNames == NULL) {
  3498             PKIX_CHECK(PKIX_PL_Cert_GetAllSubjectNames
  3499                     (state->buildConstants.targetCert,
  3500                     &targetSubjNames,
  3501                     plContext),
  3502                     PKIX_CERTGETALLSUBJECTNAMESFAILED);
  3505         state->status = BUILD_INITIAL;
  3507         pkixErrorResult =
  3508             pkix_BuildForwardDepthFirstSearch(&nbioContext, state,
  3509                                               &valResult, plContext);
  3511         /* non-null nbioContext means the build would block */
  3512         if (pkixErrorResult == NULL && nbioContext != NULL) {
  3514                 *pNBIOContext = nbioContext;
  3515                 *pBuildResult = NULL;
  3517         /* no valResult means the build has failed */
  3518         } else {
  3519                 if (pVerifyNode != NULL) {
  3520                         PKIX_INCREF(state->verifyNode);
  3521                         *pVerifyNode = state->verifyNode;
  3524                 if (valResult == NULL || pkixErrorResult)
  3525                         PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
  3526                 PKIX_CHECK(
  3527                     pkix_BuildResult_Create(valResult, state->trustChain,
  3528                                             &buildResult, plContext),
  3529                     PKIX_BUILDRESULTCREATEFAILED);
  3530                 *pBuildResult = buildResult;
  3533         *pState = state;
  3534         state = NULL;
  3536 cleanup:
  3538         PKIX_DECREF(targetConstraints);
  3539         PKIX_DECREF(targetParams);
  3540         PKIX_DECREF(anchors);
  3541         PKIX_DECREF(targetSubjNames);
  3542         PKIX_DECREF(targetCert);
  3543         PKIX_DECREF(revChecker);
  3544         PKIX_DECREF(certStores);
  3545         PKIX_DECREF(certStore);
  3546         PKIX_DECREF(userCheckers);
  3547         PKIX_DECREF(hintCerts);
  3548         PKIX_DECREF(firstHintCert);
  3549         PKIX_DECREF(testDate);
  3550         PKIX_DECREF(targetPubKey);
  3551         PKIX_DECREF(tentativeChain);
  3552         PKIX_DECREF(valResult);
  3553         PKIX_DECREF(certList);
  3554         PKIX_DECREF(trustedCert);
  3555         PKIX_DECREF(state);
  3556         PKIX_DECREF(aiaMgr);
  3558         PKIX_RETURN(BUILD);
  3561 /*
  3562  * FUNCTION: pkix_Build_ResumeBuildChain
  3563  * DESCRIPTION:
  3565  *  This function continues the search for a BuildChain, using the parameters
  3566  *  provided in "procParams" and the ForwardBuilderState pointed to by "state".
  3568  *  If a successful chain is built, this function stores the BuildResult at
  3569  *  "pBuildResult". Alternatively, if an operation using non-blocking I/O
  3570  *  is in progress and the operation has not been completed, this function
  3571  *  stores the FowardBuilderState at "pState" and NULL at "pBuildResult".
  3572  *  Finally, if chain building was unsuccessful, this function stores NULL
  3573  *  at both "pState" and at "pBuildResult".
  3575  * PARAMETERS:
  3576  *  "pNBIOContext"
  3577  *      Address at which the NBIOContext is stored indicating whether the
  3578  *      validation is complete. Must be non-NULL.
  3579  *  "pState"
  3580  *     Address at which the ForwardBuilderState is provided for resumption of
  3581  *     the chain building attempt; also, the address at which the
  3582  *     ForwardBuilderStateis stored, if the chain building is suspended for
  3583  *     waiting I/O. Must be non-NULL.
  3584  *  "pBuildResult"
  3585  *      Address at which the BuildResult is stored, after a successful build.
  3586  *      Must be non-NULL.
  3587  *  "plContext"
  3588  *      Platform-specific context pointer.
  3589  * THREAD SAFETY:
  3590  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  3591  * RETURNS:
  3592  *  Returns NULL if the function succeeds.
  3593  *  Returns a Build Error if the function fails in a non-fatal way
  3594  *  Returns a Fatal Error if the function fails in an unrecoverable way.
  3595  */
  3596 static PKIX_Error *
  3597 pkix_Build_ResumeBuildChain(
  3598         void **pNBIOContext,
  3599         PKIX_ForwardBuilderState *state,
  3600         PKIX_BuildResult **pBuildResult,
  3601         PKIX_VerifyNode **pVerifyNode,
  3602         void *plContext)
  3604         PKIX_ValidateResult *valResult = NULL;
  3605         PKIX_BuildResult *buildResult = NULL;
  3606         void *nbioContext = NULL;
  3608         PKIX_ENTER(BUILD, "pkix_Build_ResumeBuildChain");
  3609         PKIX_NULLCHECK_TWO(state, pBuildResult);
  3611         nbioContext = *pNBIOContext;
  3612         *pNBIOContext = NULL;
  3614         pkixErrorResult =
  3615             pkix_BuildForwardDepthFirstSearch(&nbioContext, state,
  3616                                               &valResult, plContext);
  3618         /* non-null nbioContext means the build would block */
  3619         if (pkixErrorResult == NULL && nbioContext != NULL) {
  3621                 *pNBIOContext = nbioContext;
  3622                 *pBuildResult = NULL;
  3624         /* no valResult means the build has failed */
  3625         } else {
  3626                 if (pVerifyNode != NULL) {
  3627                     PKIX_INCREF(state->verifyNode);
  3628                     *pVerifyNode = state->verifyNode;
  3631                 if (valResult == NULL || pkixErrorResult)
  3632                     PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
  3634                 PKIX_CHECK(
  3635                     pkix_BuildResult_Create(valResult, state->trustChain,
  3636                                             &buildResult, plContext),
  3637                     PKIX_BUILDRESULTCREATEFAILED);
  3638                 *pBuildResult = buildResult;
  3641 cleanup:
  3643         PKIX_DECREF(valResult);
  3645         PKIX_RETURN(BUILD);
  3648 /* --Public-Functions--------------------------------------------- */
  3650 /*
  3651  * FUNCTION: PKIX_BuildChain (see comments in pkix.h)
  3652  */
  3653 PKIX_Error *
  3654 PKIX_BuildChain(
  3655         PKIX_ProcessingParams *procParams,
  3656         void **pNBIOContext,
  3657         void **pState,
  3658         PKIX_BuildResult **pBuildResult,
  3659         PKIX_VerifyNode **pVerifyNode,
  3660         void *plContext)
  3662         PKIX_ForwardBuilderState *state = NULL;
  3663         PKIX_BuildResult *buildResult = NULL;
  3664         void *nbioContext = NULL;
  3666         PKIX_ENTER(BUILD, "PKIX_BuildChain");
  3667         PKIX_NULLCHECK_FOUR(procParams, pNBIOContext, pState, pBuildResult);
  3669         nbioContext = *pNBIOContext;
  3670         *pNBIOContext = NULL;
  3672         if (*pState == NULL) {
  3673                 PKIX_CHECK(pkix_Build_InitiateBuildChain
  3674                         (procParams,
  3675                         &nbioContext,
  3676                         &state,
  3677                         &buildResult,
  3678                         pVerifyNode,
  3679                         plContext),
  3680                         PKIX_BUILDINITIATEBUILDCHAINFAILED);
  3681         } else {
  3682                 state = (PKIX_ForwardBuilderState *)(*pState);
  3683                 *pState = NULL; /* no net change in reference count */
  3684                 if (state->status == BUILD_SHORTCUTPENDING) {
  3685                         PKIX_CHECK(pkix_Build_InitiateBuildChain
  3686                                 (procParams,
  3687                                 &nbioContext,
  3688                                 &state,
  3689                                 &buildResult,
  3690                                 pVerifyNode,
  3691                                 plContext),
  3692                                 PKIX_BUILDINITIATEBUILDCHAINFAILED);
  3693                 } else {
  3694                         PKIX_CHECK(pkix_Build_ResumeBuildChain
  3695                                 (&nbioContext,
  3696                                 state,
  3697                                 &buildResult,
  3698                                 pVerifyNode,
  3699                                 plContext),
  3700                                 PKIX_BUILDINITIATEBUILDCHAINFAILED);
  3704         /* non-null nbioContext means the build would block */
  3705         if (nbioContext != NULL) {
  3707                 *pNBIOContext = nbioContext;
  3708                 *pState = state;
  3709                 state = NULL;
  3710                 *pBuildResult = NULL;
  3712         /* no buildResult means the build has failed */
  3713         } else if (buildResult == NULL) {
  3714                 PKIX_ERROR(PKIX_UNABLETOBUILDCHAIN);
  3715         } else {
  3716                 /*
  3717                  * If we made a successful chain by combining the target Cert
  3718                  * with one of the Trust Anchors, we may have never created a
  3719                  * validityDate. We treat this situation as
  3720                  * canBeCached = PKIX_FALSE.
  3721                  */
  3722                 if ((state != NULL) &&
  3723                     ((state->validityDate) != NULL) &&
  3724                     (state->canBeCached)) {
  3725                         PKIX_CHECK(pkix_CacheCertChain_Add
  3726                                 (state->buildConstants.targetCert,
  3727                                 state->buildConstants.anchors,
  3728                                 state->validityDate,
  3729                                 buildResult,
  3730                                 plContext),
  3731                                 PKIX_CACHECERTCHAINADDFAILED);
  3734                 *pState = NULL;
  3735                 *pBuildResult = buildResult;
  3736                 buildResult = NULL;
  3739 cleanup:
  3740         PKIX_DECREF(buildResult);
  3741         PKIX_DECREF(state);
  3743         PKIX_RETURN(BUILD);

mercurial