tor-browser

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

pkix_validate.c (55533B)


      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_validate.c
      6 *
      7 * Top level validateChain function
      8 *
      9 */
     10 
     11 #include "pkix_validate.h"
     12 #include "pkix_pl_common.h"
     13 
     14 /* --Private-Functions-------------------------------------------- */
     15 
     16 /*
     17 * FUNCTION: pkix_AddToVerifyLog
     18 * DESCRIPTION:
     19 *
     20 *  This function returns immediately if the address for the VerifyNode tree
     21 *  pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode
     22 *  from the Cert pointed to by "cert" and the Error pointed to by "error",
     23 *  and inserts it at the depth in the VerifyNode tree determined by "depth". A
     24 *  depth of zero means that this function creates the root node of a new tree.
     25 *
     26 *  Note: this function does not include the means of choosing among branches
     27 *  of a tree. It is intended for non-branching trees, that is, where each
     28 *  parent node has only a single child node.
     29 *
     30 * PARAMETERS:
     31 *  "cert"
     32 *      The address of the Cert to be included in the new VerifyNode. Must be
     33 *      non-NULL.
     34 *  "depth"
     35 *      The UInt32 value of the depth.
     36 *  "error"
     37 *      The address of the Error to be included in the new VerifyNode.
     38 *  "pVerifyTree"
     39 *      The address of the VerifyNode tree into which the created VerifyNode
     40 *      is to be inserted. The node is not created if VerifyTree is NULL.
     41 *  "plContext"
     42 *      Platform-specific context pointer.
     43 * THREAD SAFETY:
     44 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     45 * RETURNS:
     46 *  Returns NULL if the function succeeds.
     47 *  Returns a Validate Error if the function fails in a non-fatal way.
     48 *  Returns a Fatal Error if the function fails in an unrecoverable way.
     49 */
     50 static PKIX_Error *
     51 pkix_AddToVerifyLog(
     52        PKIX_PL_Cert *cert,
     53        PKIX_UInt32 depth,
     54        PKIX_Error *error,
     55        PKIX_VerifyNode **pVerifyTree,
     56        void *plContext)
     57 {
     58 
     59        PKIX_VerifyNode *verifyNode = NULL;
     60 
     61        PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog");
     62        PKIX_NULLCHECK_ONE(cert);
     63 
     64        if (pVerifyTree) { /* nothing to do if no address given for log */
     65 
     66                PKIX_CHECK(pkix_VerifyNode_Create
     67                        (cert, depth, error, &verifyNode, plContext),
     68                        PKIX_VERIFYNODECREATEFAILED);
     69 
     70                if (depth == 0) {
     71                        /* We just created the root node */
     72                        *pVerifyTree = verifyNode;
     73                } else {
     74                        PKIX_CHECK(pkix_VerifyNode_AddToChain
     75                                (*pVerifyTree, verifyNode, plContext),
     76                                PKIX_VERIFYNODEADDTOCHAINFAILED);
     77                }
     78        }
     79 
     80 cleanup:
     81 
     82        PKIX_RETURN(VALIDATE);
     83 
     84 }
     85 
     86 /*
     87 * FUNCTION: pkix_CheckCert
     88 * DESCRIPTION:
     89 *
     90 *  Checks whether the Cert pointed to by "cert" successfully validates
     91 *  using the List of CertChainCheckers pointed to by "checkers". If the
     92 *  certificate does not validate, an Error pointer is returned.
     93 *
     94 *  This function should be called initially with the UInt32 pointed to by
     95 *  "pCheckerIndex" containing zero, and the pointer at "pNBIOContext"
     96 *  containing NULL. If a checker does non-blocking I/O, this function will
     97 *  return with the index of that checker stored at "pCheckerIndex" and a
     98 *  platform-dependent non-blocking I/O context stored at "pNBIOContext".
     99 *  A subsequent call to this function with those values intact will allow the
    100 *  checking to resume where it left off. This should be repeated until the
    101 *  function returns with NULL stored at "pNBIOContext".
    102 *
    103 * PARAMETERS:
    104 *  "cert"
    105 *      Address of Cert to validate. Must be non-NULL.
    106 *  "checkers"
    107 *      List of CertChainCheckers which must each validate the certificate.
    108 *      Must be non-NULL.
    109 *  "checkedExtOIDs"
    110 *      List of PKIX_PL_OID that has been processed. If called from building
    111 *      chain, it is the list of critical extension OIDs that has been
    112 *      processed prior to validation. May be NULL.
    113 *  "pCheckerIndex"
    114 *      Address at which is stored the the index, within the List "checkers",
    115 *      of a checker whose processing was interrupted by non-blocking I/O.
    116 *      Must be non-NULL.
    117 *  "pNBIOContext"
    118 *      Address at which is stored platform-specific non-blocking I/O context.
    119 *      Must be non-NULL.
    120 *  "plContext"
    121 *      Platform-specific context pointer.
    122 * THREAD SAFETY:
    123 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    124 * RETURNS:
    125 *  Returns NULL if the function succeeds.
    126 *  Returns a Validate Error if the function fails in a non-fatal way.
    127 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    128 */
    129 static PKIX_Error *
    130 pkix_CheckCert(
    131        PKIX_PL_Cert *cert,
    132        PKIX_List *checkers,
    133        PKIX_List *checkedExtOIDsList,
    134        PKIX_UInt32 *pCheckerIndex,
    135        void **pNBIOContext,
    136        void *plContext)
    137 {
    138        PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
    139        PKIX_CertChainChecker *checker = NULL;
    140        PKIX_List *unresCritExtOIDs = NULL;
    141        PKIX_UInt32 numCheckers;
    142        PKIX_UInt32 numUnresCritExtOIDs = 0;
    143        PKIX_UInt32 checkerIndex = 0;
    144        void *nbioContext = NULL;
    145 
    146        PKIX_ENTER(VALIDATE, "pkix_CheckCert");
    147        PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext);
    148 
    149        nbioContext = *pNBIOContext;
    150        *pNBIOContext = NULL; /* prepare for case of error exit */
    151 
    152        PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
    153                    (cert, &unresCritExtOIDs, plContext),
    154                    PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
    155 
    156        PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
    157                    PKIX_LISTGETLENGTHFAILED);
    158 
    159        for (checkerIndex = *pCheckerIndex;
    160                checkerIndex < numCheckers;
    161                checkerIndex++) {
    162 
    163                PKIX_CHECK(PKIX_List_GetItem
    164                        (checkers,
    165                        checkerIndex,
    166                        (PKIX_PL_Object **)&checker,
    167                        plContext),
    168                        PKIX_LISTGETITEMFAILED);
    169 
    170                PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
    171                        (checker, &checkerCheck, plContext),
    172                        PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);
    173 
    174                PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs,
    175                                        &nbioContext,  plContext),
    176                           PKIX_CERTCHAINCHECKERCHECKFAILED);
    177 
    178                if (nbioContext != NULL) {
    179                        *pCheckerIndex = checkerIndex;
    180                        *pNBIOContext = nbioContext;
    181                        goto cleanup;
    182                }
    183 
    184                PKIX_DECREF(checker);
    185        }
    186 
    187        if (unresCritExtOIDs){
    188 
    189 #ifdef PKIX_VALIDATEDEBUG
    190                {
    191                        PKIX_PL_String *oidString = NULL;
    192                        PKIX_UInt32 length;
    193                        char *oidAscii = NULL;
    194                        PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext,
    195                                PKIX_LISTTOSTRINGFAILED);
    196                        PKIX_CHECK(PKIX_PL_String_GetEncoded
    197                                (oidString,
    198                                PKIX_ESCASCII,
    199                                (void **) &oidAscii,
    200                                &length,
    201                                plContext),
    202                                PKIX_STRINGGETENCODEDFAILED);
    203                        PKIX_VALIDATE_DEBUG_ARG
    204                                ("unrecognized critical extension OIDs:"
    205                                " %s\n", oidAscii);
    206                        PKIX_DECREF(oidString);
    207                        PKIX_PL_Free(oidAscii, plContext);
    208                }
    209 #endif
    210 
    211                if (checkedExtOIDsList != NULL) {
    212                 /* Take out OID's that had been processed, if any */
    213                        PKIX_CHECK(pkix_List_RemoveItems
    214                                (unresCritExtOIDs,
    215                                checkedExtOIDsList,
    216                                plContext),
    217                                PKIX_LISTREMOVEITEMSFAILED);
    218                }
    219 
    220                PKIX_CHECK(PKIX_List_GetLength
    221                        (unresCritExtOIDs, &numUnresCritExtOIDs, plContext),
    222                        PKIX_LISTGETLENGTHFAILED);
    223 
    224                if (numUnresCritExtOIDs != 0){
    225                        PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION);
    226                }
    227 
    228        }
    229 
    230 cleanup:
    231 
    232        PKIX_DECREF(checker);
    233        PKIX_DECREF(unresCritExtOIDs);
    234 
    235        PKIX_RETURN(VALIDATE);
    236 
    237 }
    238 
    239 /*
    240 * FUNCTION: pkix_InitializeCheckers
    241 * DESCRIPTION:
    242 *
    243 *  Creates several checkers and initializes them with values derived from the
    244 *  TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by
    245 *  "procParams", and the number of Certs in the Chain, represented by
    246 *  "numCerts". The List of checkers is stored at "pCheckers".
    247 *
    248 * PARAMETERS:
    249 *  "anchor"
    250 *      Address of TrustAnchor used to initialize the SignatureChecker and
    251 *      NameChainingChecker. Must be non-NULL.
    252 *  "procParams"
    253 *      Address of ProcessingParams used to initialize the ExpirationChecker
    254 *      and TargetCertChecker. Must be non-NULL.
    255 *  "numCerts"
    256 *      Number of certificates in the CertChain.
    257 *  "pCheckers"
    258 *      Address where object pointer will be stored. Must be non-NULL.
    259 *  "plContext"
    260 *      Platform-specific context pointer.
    261 * THREAD SAFETY:
    262 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    263 * RETURNS:
    264 *  Returns NULL if the function succeeds.
    265 *  Returns a Validate Error if the function fails in a non-fatal way.
    266 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    267 */
    268 static PKIX_Error *
    269 pkix_InitializeCheckers(
    270        PKIX_TrustAnchor *anchor,
    271        PKIX_ProcessingParams *procParams,
    272        PKIX_UInt32 numCerts,
    273        PKIX_List **pCheckers,
    274        void *plContext)
    275 {
    276        PKIX_CertChainChecker *targetCertChecker = NULL;
    277        PKIX_CertChainChecker *expirationChecker = NULL;
    278        PKIX_CertChainChecker *nameChainingChecker = NULL;
    279        PKIX_CertChainChecker *nameConstraintsChecker = NULL;
    280        PKIX_CertChainChecker *basicConstraintsChecker = NULL;
    281        PKIX_CertChainChecker *policyChecker = NULL;
    282        PKIX_CertChainChecker *sigChecker = NULL;
    283        PKIX_CertChainChecker *defaultCrlChecker = NULL;
    284        PKIX_CertChainChecker *userChecker = NULL;
    285        PKIX_PL_X500Name *trustedCAName = NULL;
    286        PKIX_PL_PublicKey *trustedPubKey = NULL;
    287        PKIX_List *checkers = NULL;
    288        PKIX_PL_Date *testDate = NULL;
    289        PKIX_CertSelector *certSelector = NULL;
    290        PKIX_PL_Cert *trustedCert = NULL;
    291        PKIX_PL_CertNameConstraints *trustedNC = NULL;
    292        PKIX_List *initialPolicies = NULL;
    293        PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
    294        PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
    295        PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
    296        PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
    297        PKIX_List *userCheckersList = NULL;
    298        PKIX_List *certStores = NULL;
    299        PKIX_UInt32 numCertCheckers = 0;
    300        PKIX_UInt32 i;
    301 
    302        PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers");
    303        PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers);
    304        PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
    305                    PKIX_LISTCREATEFAILED);
    306 
    307        /*
    308         * The TrustAnchor may have been created using CreateWithCert
    309         * (in which case GetCAPublicKey and GetCAName will return NULL)
    310         * or may have been created using CreateWithNameKeyPair (in which
    311         * case GetTrustedCert will return NULL. So we call GetTrustedCert
    312         * and populate trustedPubKey and trustedCAName accordingly.
    313         */
    314 
    315        PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
    316                (anchor, &trustedCert, plContext),
    317                    PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
    318 
    319        if (trustedCert){
    320                PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
    321                            (trustedCert, &trustedPubKey, plContext),
    322                            PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
    323 
    324                PKIX_CHECK(PKIX_PL_Cert_GetSubject
    325                            (trustedCert, &trustedCAName, plContext),
    326                            PKIX_CERTGETSUBJECTFAILED);
    327        } else {
    328                PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey
    329                            (anchor, &trustedPubKey, plContext),
    330                            PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED);
    331 
    332                PKIX_CHECK(PKIX_TrustAnchor_GetCAName
    333                            (anchor, &trustedCAName, plContext),
    334                            PKIX_TRUSTANCHORGETCANAMEFAILED);
    335        }
    336 
    337        PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName);
    338 
    339        PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
    340                (anchor, &trustedNC, plContext),
    341                PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);
    342 
    343        PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
    344                (procParams, &certSelector, plContext),
    345                PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
    346 
    347        PKIX_CHECK(PKIX_ProcessingParams_GetDate
    348                (procParams, &testDate, plContext),
    349                PKIX_PROCESSINGPARAMSGETDATEFAILED);
    350 
    351        PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
    352                (procParams, &initialPolicies, plContext),
    353                PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);
    354 
    355        PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
    356                (procParams, &policyQualifiersRejected, plContext),
    357                PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);
    358 
    359        PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
    360                (procParams, &initialPolicyMappingInhibit, plContext),
    361                PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);
    362 
    363        PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
    364                (procParams, &initialAnyPolicyInhibit, plContext),
    365                PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);
    366 
    367        PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
    368                (procParams, &initialExplicitPolicy, plContext),
    369                PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);
    370 
    371        PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
    372                (procParams, &certStores, plContext),
    373                PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
    374 
    375        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
    376                (procParams, &userCheckersList, plContext),
    377                PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
    378 
    379        /* now, initialize all the checkers */
    380        PKIX_CHECK(pkix_TargetCertChecker_Initialize
    381                (certSelector, numCerts, &targetCertChecker, plContext),
    382                PKIX_TARGETCERTCHECKERINITIALIZEFAILED);
    383 
    384        PKIX_CHECK(pkix_ExpirationChecker_Initialize
    385                (testDate, &expirationChecker, plContext),
    386                PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
    387 
    388        PKIX_CHECK(pkix_NameChainingChecker_Initialize
    389                (trustedCAName, &nameChainingChecker, plContext),
    390                PKIX_NAMECHAININGCHECKERINITIALIZEFAILED);
    391 
    392        PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
    393                (trustedNC, numCerts, &nameConstraintsChecker, plContext),
    394                PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);
    395 
    396        PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize
    397                (numCerts, &basicConstraintsChecker, plContext),
    398                PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED);
    399 
    400        PKIX_CHECK(pkix_PolicyChecker_Initialize
    401                (initialPolicies,
    402                policyQualifiersRejected,
    403                initialPolicyMappingInhibit,
    404                initialExplicitPolicy,
    405                initialAnyPolicyInhibit,
    406                numCerts,
    407                &policyChecker,
    408                plContext),
    409                PKIX_POLICYCHECKERINITIALIZEFAILED);
    410 
    411        PKIX_CHECK(pkix_SignatureChecker_Initialize
    412                    (trustedPubKey, numCerts, &sigChecker, plContext),
    413                    PKIX_SIGNATURECHECKERINITIALIZEFAILED);
    414 
    415        if (userCheckersList != NULL) {
    416 
    417                PKIX_CHECK(PKIX_List_GetLength
    418                    (userCheckersList, &numCertCheckers, plContext),
    419                    PKIX_LISTGETLENGTHFAILED);
    420 
    421                for (i = 0; i < numCertCheckers; i++) {
    422 
    423                        PKIX_CHECK(PKIX_List_GetItem
    424                            (userCheckersList,
    425                            i,
    426                            (PKIX_PL_Object **) &userChecker,
    427                            plContext),
    428                            PKIX_LISTGETITEMFAILED);
    429 
    430                        PKIX_CHECK(PKIX_List_AppendItem
    431                            (checkers,
    432                            (PKIX_PL_Object *)userChecker,
    433                            plContext),
    434                            PKIX_LISTAPPENDITEMFAILED);
    435 
    436                        PKIX_DECREF(userChecker);
    437                }
    438        }
    439 
    440        PKIX_CHECK(PKIX_List_AppendItem
    441            (checkers, (PKIX_PL_Object *)targetCertChecker, plContext),
    442            PKIX_LISTAPPENDITEMFAILED);
    443 
    444        PKIX_CHECK(PKIX_List_AppendItem
    445            (checkers, (PKIX_PL_Object *)expirationChecker, plContext),
    446            PKIX_LISTAPPENDITEMFAILED);
    447 
    448        PKIX_CHECK(PKIX_List_AppendItem
    449            (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext),
    450            PKIX_LISTAPPENDITEMFAILED);
    451 
    452        PKIX_CHECK(PKIX_List_AppendItem
    453            (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext),
    454            PKIX_LISTAPPENDITEMFAILED);
    455 
    456        PKIX_CHECK(PKIX_List_AppendItem
    457            (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext),
    458            PKIX_LISTAPPENDITEMFAILED);
    459 
    460        PKIX_CHECK(PKIX_List_AppendItem
    461            (checkers, (PKIX_PL_Object *)policyChecker, plContext),
    462            PKIX_LISTAPPENDITEMFAILED);
    463 
    464        PKIX_CHECK(PKIX_List_AppendItem
    465            (checkers, (PKIX_PL_Object *)sigChecker, plContext),
    466            PKIX_LISTAPPENDITEMFAILED);
    467 
    468        *pCheckers = checkers;
    469 
    470 cleanup:
    471 
    472        if (PKIX_ERROR_RECEIVED){
    473                PKIX_DECREF(checkers);
    474        }
    475 
    476        PKIX_DECREF(certSelector);
    477        PKIX_DECREF(testDate);
    478        PKIX_DECREF(initialPolicies);
    479        PKIX_DECREF(targetCertChecker);
    480        PKIX_DECREF(expirationChecker);
    481        PKIX_DECREF(nameChainingChecker);
    482        PKIX_DECREF(nameConstraintsChecker);
    483        PKIX_DECREF(basicConstraintsChecker);
    484        PKIX_DECREF(policyChecker);
    485        PKIX_DECREF(sigChecker);
    486        PKIX_DECREF(trustedCAName);
    487        PKIX_DECREF(trustedPubKey);
    488        PKIX_DECREF(trustedNC);
    489        PKIX_DECREF(trustedCert);
    490        PKIX_DECREF(defaultCrlChecker);
    491        PKIX_DECREF(userCheckersList);
    492        PKIX_DECREF(certStores);
    493        PKIX_DECREF(userChecker);
    494 
    495        PKIX_RETURN(VALIDATE);
    496 }
    497 
    498 /*
    499 * FUNCTION: pkix_RetrieveOutputs
    500 * DESCRIPTION:
    501 *
    502 *  This function queries the respective states of the List of checkers in
    503 *  "checkers" to to obtain the final public key from the SignatureChecker
    504 *  and the policy tree from the PolicyChecker, storing those values at
    505 *  "pFinalSubjPubKey" and "pPolicyTree", respectively.
    506 *
    507 * PARAMETERS:
    508 *  "checkers"
    509 *      Address of List of checkers to be queried. Must be non-NULL.
    510 *  "pFinalSubjPubKey"
    511 *      Address where final public key will be stored. Must be non-NULL.
    512 *  "pPolicyTree"
    513 *      Address where policy tree will be stored. Must be non-NULL.
    514 *  "plContext"
    515 *      Platform-specific context pointer.
    516 * THREAD SAFETY:
    517 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    518 * RETURNS:
    519 *  Returns NULL if the function succeeds.
    520 *  Returns a Validate Error if the function fails in a non-fatal way.
    521 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    522 */
    523 static PKIX_Error *
    524 pkix_RetrieveOutputs(
    525        PKIX_List *checkers,
    526        PKIX_PL_PublicKey **pFinalSubjPubKey,
    527        PKIX_PolicyNode **pPolicyTree,
    528        void *plContext)
    529 {
    530        PKIX_PL_PublicKey *finalSubjPubKey = NULL;
    531        PKIX_PolicyNode *validPolicyTree = NULL;
    532        PKIX_CertChainChecker *checker = NULL;
    533        PKIX_PL_Object *state = NULL;
    534        PKIX_UInt32 numCheckers = 0;
    535        PKIX_UInt32 type;
    536        PKIX_Int32 j;
    537 
    538        PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs");
    539 
    540        PKIX_NULLCHECK_TWO(checkers, pPolicyTree);
    541 
    542        /*
    543         * To optimize the search, we guess that the sigChecker is
    544         * last in the tree and is preceded by the policyChecker. We
    545         * search toward the front of the chain. Remember that List
    546         * items are indexed 0..(numItems - 1).
    547         */
    548 
    549        PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
    550                PKIX_LISTGETLENGTHFAILED);
    551 
    552        for (j = numCheckers - 1; j >= 0; j--){
    553                PKIX_CHECK(PKIX_List_GetItem
    554                        (checkers, j, (PKIX_PL_Object **)&checker, plContext),
    555                        PKIX_LISTGETITEMFAILED);
    556 
    557                PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
    558                        (checker, &state, plContext),
    559                        PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
    560 
    561                /* user defined checker may have no state */
    562                if (state != NULL) {
    563 
    564                    PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext),
    565                            PKIX_OBJECTGETTYPEFAILED);
    566 
    567                    if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){
    568                        /* final pubKey will include any inherited DSA params */
    569                        finalSubjPubKey =
    570                            ((pkix_SignatureCheckerState *)state)->
    571                                prevPublicKey;
    572                        PKIX_INCREF(finalSubjPubKey);
    573                        *pFinalSubjPubKey = finalSubjPubKey;
    574                    }
    575 
    576                    if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) {
    577                        validPolicyTree =
    578                            ((PKIX_PolicyCheckerState *)state)->validPolicyTree;
    579                        break;
    580                    }
    581                }
    582 
    583                PKIX_DECREF(checker);
    584                PKIX_DECREF(state);
    585        }
    586 
    587        PKIX_INCREF(validPolicyTree);
    588        *pPolicyTree = validPolicyTree;
    589 
    590 cleanup:
    591 
    592        PKIX_DECREF(checker);
    593        PKIX_DECREF(state);
    594 
    595        PKIX_RETURN(VALIDATE);
    596 
    597 }
    598 
    599 /*
    600 * FUNCTION: pkix_CheckChain
    601 * DESCRIPTION:
    602 *
    603 *  Checks whether the List of Certs pointed to by "certs", containing
    604 *  "numCerts" entries, successfully validates using each CertChainChecker in
    605 *  the List pointed to by "checkers" and has not been revoked, according to any
    606 *  of the Revocation Checkers in the List pointed to by "revChecker". Checkers
    607 *  are expected to remove from "removeCheckedExtOIDs" and extensions that they
    608 *  process. Indices to the certChain and the checkerChain are obtained and
    609 *  returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These
    610 *  should be set to zero prior to the initial call, but may be changed (and
    611 *  must be supplied on subsequent calls) if processing is suspended for non-
    612 *  blocking I/O. Each time a Cert passes from being validated by one of the
    613 *  CertChainCheckers to being checked by a Revocation Checker, the Boolean
    614 *  stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is
    615 *  rejected by a Revocation Checker, its reason code is returned at
    616 *  "pReasonCode. If the List of Certs successfully validates, the public key i
    617 *  the final certificate is obtained and stored at "pFinalSubjPubKey" and the
    618 *  validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List
    619 *  of Certs fails to validate, an Error pointer is returned.
    620 *
    621 *  If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which
    622 *  tracks the results of the validation. That is, either each node in the
    623 *  chain has a NULL Error component, or the last node contains an Error
    624 *  which indicates why the validation failed.
    625 *
    626 *  The number of Certs in the List, represented by "numCerts", is used to
    627 *  determine which Cert is the final Cert.
    628 *
    629 * PARAMETERS:
    630 *  "certs"
    631 *      Address of List of Certs to validate. Must be non-NULL.
    632 *  "numCerts"
    633 *      Number of certificates in the List of certificates.
    634 *  "checkers"
    635 *      List of CertChainCheckers which must each validate the List of
    636 *      certificates. Must be non-NULL.
    637 *  "revChecker"
    638 *      List of RevocationCheckers which must each not reject the List of
    639 *      certificates. May be empty, but must be non-NULL.
    640 *  "removeCheckedExtOIDs"
    641 *      List of PKIX_PL_OID that has been processed. If called from building
    642 *      chain, it is the list of critical extension OIDs that has been
    643 *      processed prior to validation. Extension OIDs that may be processed by
    644 *      user defined checker processes are also in the list. May be NULL.
    645 *  "procParams"
    646 *      Address of ProcessingParams used to initialize various checkers. Must
    647 *      be non-NULL.
    648 *  "pCertCheckedIndex"
    649 *      Address where Int32 index to the Cert chain is obtained and
    650 *      returned. Must be non-NULL.
    651 *  "pCheckerIndex"
    652 *      Address where Int32 index to the CheckerChain is obtained and
    653 *      returned. Must be non-NULL.
    654 *  "pRevChecking"
    655 *      Address where Boolean is obtained and returned, indicating, if FALSE,
    656 *      that CertChainCheckers are being called; or, if TRUE, that RevChecker
    657 *      are being called. Must be non-NULL.
    658 *  "pReasonCode"
    659 *      Address where UInt32 results of revocation checking are stored. Must be
    660 *      non-NULL.
    661 *  "pNBIOContext"
    662 *      Address where platform-dependent context is stored if checking is
    663 *      suspended for non-blocking I/O. Must be non-NULL.
    664 *  "pFinalSubjPubKey"
    665 *      Address where the final public key will be stored. Must be non-NULL.
    666 *  "pPolicyTree"
    667 *      Address where the final validPolicyTree is stored. Must be non-NULL.
    668 *  "pVerifyTree"
    669 *      Address where a VerifyTree is stored, if non-NULL.
    670 *  "plContext"
    671 *      Platform-specific context pointer.
    672 * THREAD SAFETY:
    673 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    674 * RETURNS:
    675 *  Returns NULL if the function succeeds.
    676 *  Returns a Validate Error if the function fails in a non-fatal way.
    677 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    678 */
    679 PKIX_Error *
    680 pkix_CheckChain(
    681        PKIX_List *certs,
    682        PKIX_UInt32 numCerts,
    683        PKIX_TrustAnchor *anchor,
    684        PKIX_List *checkers,
    685        PKIX_RevocationChecker *revChecker,
    686        PKIX_List *removeCheckedExtOIDs,
    687        PKIX_ProcessingParams *procParams,
    688        PKIX_UInt32 *pCertCheckedIndex,
    689        PKIX_UInt32 *pCheckerIndex,
    690        PKIX_Boolean *pRevChecking,
    691        PKIX_UInt32 *pReasonCode,
    692        void **pNBIOContext,
    693        PKIX_PL_PublicKey **pFinalSubjPubKey,
    694        PKIX_PolicyNode **pPolicyTree,
    695        PKIX_VerifyNode **pVerifyTree,
    696        void *plContext)
    697 {
    698        PKIX_UInt32 j = 0;
    699        PKIX_Boolean revChecking = PKIX_FALSE;
    700        PKIX_Error *checkCertError = NULL;
    701        void *nbioContext = NULL;
    702        PKIX_PL_Cert *cert = NULL;
    703        PKIX_PL_Cert *issuer = NULL;
    704        PKIX_PL_NssContext *nssContext = NULL;
    705        CERTCertList *certList = NULL;
    706        const CERTChainVerifyCallback *chainVerifyCallback = NULL;
    707        CERTCertificate *nssCert = NULL;
    708 
    709        PKIX_ENTER(VALIDATE, "pkix_CheckChain");
    710        PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex);
    711        PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor);
    712        PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree);
    713 
    714        nbioContext = *pNBIOContext;
    715        *pNBIOContext = NULL;
    716        revChecking = *pRevChecking;
    717        nssContext = (PKIX_PL_NssContext *)plContext;
    718        chainVerifyCallback = &nssContext->chainVerifyCallback;
    719 
    720        if (chainVerifyCallback->isChainValid != NULL) {
    721                PRBool chainOK = PR_FALSE; /*assume failure*/
    722                SECStatus rv;
    723 
    724                certList = CERT_NewCertList();
    725                if (certList == NULL) {
    726                        PKIX_ERROR_ALLOC_ERROR();
    727                }
    728 
    729                /* Add the trust anchor to the list */
    730                PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
    731                        (anchor, &cert, plContext),
    732                        PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
    733 
    734                PKIX_CHECK(
    735                        PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
    736                        PKIX_CERTGETCERTCERTIFICATEFAILED);
    737 
    738                rv = CERT_AddCertToListHead(certList, nssCert);
    739                if (rv != SECSuccess) {
    740                        PKIX_ERROR_ALLOC_ERROR();
    741                }
    742                /* the certList takes ownership of nssCert on success */
    743                nssCert = NULL;
    744                PKIX_DECREF(cert);
    745 
    746                /* Add the rest of the chain to the list */
    747                for (j = *pCertCheckedIndex; j < numCerts; j++) {
    748                        PKIX_CHECK(PKIX_List_GetItem(
    749                                certs, j, (PKIX_PL_Object **)&cert, plContext),
    750                                PKIX_LISTGETITEMFAILED);
    751 
    752                        PKIX_CHECK(
    753                                PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
    754                                PKIX_CERTGETCERTCERTIFICATEFAILED);
    755 
    756                        rv = CERT_AddCertToListHead(certList, nssCert);
    757                        if (rv != SECSuccess) {
    758                                PKIX_ERROR_ALLOC_ERROR();
    759                        }
    760                        /* the certList takes ownership of nssCert on success */
    761                        nssCert = NULL;
    762                        PKIX_DECREF(cert);
    763                }
    764 
    765                rv = (*chainVerifyCallback->isChainValid)
    766                     (chainVerifyCallback->isChainValidArg, certList, &chainOK);
    767                if (rv != SECSuccess) {
    768                       PKIX_ERROR_FATAL(PKIX_CHAINVERIFYCALLBACKFAILED);
    769                }
    770 
    771                if (!chainOK) {
    772                        PKIX_ERROR(PKIX_CHAINVERIFYCALLBACKFAILED);
    773                }
    774 
    775        }
    776 
    777        PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
    778                (anchor, &cert, plContext),
    779                   PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
    780 
    781        for (j = *pCertCheckedIndex; j < numCerts; j++) {
    782 
    783                PORT_Assert(cert);
    784                PKIX_DECREF(issuer);
    785                issuer = cert;
    786                cert = NULL;
    787 
    788                PKIX_CHECK(PKIX_List_GetItem(
    789                               certs, j, (PKIX_PL_Object **)&cert, plContext),
    790                           PKIX_LISTGETITEMFAILED);
    791                
    792                /* check if cert pointer is valid */
    793                PORT_Assert(cert);
    794                if (cert == NULL) {
    795                    continue;
    796                }
    797 
    798                if (revChecking == PKIX_FALSE) {
    799 
    800                        PKIX_CHECK(pkix_CheckCert
    801                                (cert,
    802                                checkers,
    803                                removeCheckedExtOIDs,
    804                                pCheckerIndex,
    805                                &nbioContext,
    806                                plContext),
    807                                PKIX_CHECKCERTFAILED);
    808 
    809                        if (nbioContext != NULL) {
    810                                *pCertCheckedIndex = j;
    811                                *pRevChecking = revChecking;
    812                                *pNBIOContext = nbioContext;
    813                                goto cleanup;
    814                        }
    815 
    816                        revChecking = PKIX_TRUE;
    817                        *pCheckerIndex = 0;
    818                }
    819 
    820                if (revChecking == PKIX_TRUE) {
    821                        PKIX_RevocationStatus revStatus;
    822                        pkixErrorResult =
    823                            PKIX_RevocationChecker_Check(
    824                                      cert, issuer, revChecker,
    825                                      procParams, PKIX_TRUE,
    826                                      (j == numCerts - 1) ? PKIX_TRUE : PKIX_FALSE,
    827                                      &revStatus, pReasonCode,
    828                                      &nbioContext, plContext);
    829                        if (nbioContext != NULL) {
    830                                *pCertCheckedIndex = j;
    831                                *pRevChecking = revChecking;
    832                                *pNBIOContext = nbioContext;
    833                                goto cleanup;
    834                        }
    835                        if (revStatus == PKIX_RevStatus_Revoked ||
    836                            pkixErrorResult) {
    837                            if (!pkixErrorResult) {
    838                                /* if pkixErrorResult is returned then
    839                                 * use it as it has a detailed revocation
    840                                 * error code. Otherwise create a new error */
    841                                PKIX_ERROR_CREATE(VALIDATE,
    842                                                  PKIX_CERTIFICATEREVOKED,
    843                                                  pkixErrorResult);
    844                            }
    845                            goto cleanup;
    846                        }
    847                        revChecking = PKIX_FALSE;
    848                        *pCheckerIndex = 0;
    849                }
    850 
    851                PKIX_CHECK(pkix_AddToVerifyLog
    852                        (cert, j, NULL, pVerifyTree, plContext),
    853                        PKIX_ADDTOVERIFYLOGFAILED);
    854        }
    855 
    856        PKIX_CHECK(pkix_RetrieveOutputs
    857                    (checkers, pFinalSubjPubKey, pPolicyTree, plContext),
    858                    PKIX_RETRIEVEOUTPUTSFAILED);
    859 
    860        *pNBIOContext = NULL;
    861 
    862 cleanup:
    863        if (PKIX_ERROR_RECEIVED && cert) {
    864            checkCertError = pkixErrorResult;
    865            
    866            PKIX_CHECK_FATAL(
    867                pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree,
    868                                    plContext),
    869                PKIX_ADDTOVERIFYLOGFAILED);
    870            pkixErrorResult = checkCertError;
    871            pkixErrorCode = pkixErrorResult->errCode;
    872            checkCertError = NULL;
    873        }
    874 
    875 fatal:
    876        if (nssCert) {
    877                CERT_DestroyCertificate(nssCert);
    878        }
    879 
    880        if (certList) {
    881                CERT_DestroyCertList(certList);
    882        }
    883 
    884        PKIX_DECREF(checkCertError);
    885        PKIX_DECREF(cert);
    886        PKIX_DECREF(issuer);
    887 
    888        PKIX_RETURN(VALIDATE);
    889 }
    890 
    891 /*
    892 * FUNCTION: pkix_ExtractParameters
    893 * DESCRIPTION:
    894 *
    895 *  Extracts several parameters from the ValidateParams object pointed to by
    896 *  "valParams" and stores the CertChain at "pChain", the List of Certs at
    897 *  "pCerts", the number of Certs in the chain at "pNumCerts", the
    898 *  ProcessingParams object at "pProcParams", the List of TrustAnchors at
    899 *  "pAnchors", and the number of TrustAnchors at "pNumAnchors".
    900 *
    901 * PARAMETERS:
    902 *  "valParams"
    903 *      Address of ValidateParams from which the parameters are extracted.
    904 *      Must be non-NULL.
    905 *  "pCerts"
    906 *      Address where object pointer for List of Certs will be stored.
    907 *      Must be non-NULL.
    908 *  "pNumCerts"
    909 *      Address where number of Certs will be stored. Must be non-NULL.
    910 *  "pProcParams"
    911 *      Address where object pointer for ProcessingParams will be stored.
    912 *      Must be non-NULL.
    913 *  "pAnchors"
    914 *      Address where object pointer for List of Anchors will be stored.
    915 *      Must be non-NULL.
    916 *  "pNumAnchors"
    917 *      Address where number of Anchors will be stored. Must be non-NULL.
    918 *  "plContext"
    919 *      Platform-specific context pointer.
    920 * THREAD SAFETY:
    921 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    922 * RETURNS:
    923 *  Returns NULL if the function succeeds.
    924 *  Returns a Validate Error if the function fails in a non-fatal way.
    925 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    926 */
    927 static PKIX_Error *
    928 pkix_ExtractParameters(
    929        PKIX_ValidateParams *valParams,
    930        PKIX_List **pCerts,
    931        PKIX_UInt32 *pNumCerts,
    932        PKIX_ProcessingParams **pProcParams,
    933        PKIX_List **pAnchors,
    934        PKIX_UInt32 *pNumAnchors,
    935        void *plContext)
    936 {
    937        PKIX_ENTER(VALIDATE, "pkix_ExtractParameters");
    938        PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts);
    939        PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors);
    940 
    941        /* extract relevant parameters from chain */
    942        PKIX_CHECK(PKIX_ValidateParams_GetCertChain
    943                (valParams, pCerts, plContext),
    944                PKIX_VALIDATEPARAMSGETCERTCHAINFAILED);
    945 
    946        PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext),
    947                PKIX_LISTGETLENGTHFAILED);
    948 
    949        /* extract relevant parameters from procParams */
    950        PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams
    951                (valParams, pProcParams, plContext),
    952                PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED);
    953 
    954        PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
    955                (*pProcParams, pAnchors, plContext),
    956                PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);
    957 
    958        PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext),
    959                PKIX_LISTGETLENGTHFAILED);
    960 
    961 cleanup:
    962 
    963        PKIX_RETURN(VALIDATE);
    964 }
    965 
    966 /* --Public-Functions--------------------------------------------- */
    967 
    968 /*
    969 * FUNCTION: PKIX_ValidateChain (see comments in pkix.h)
    970 */
    971 PKIX_Error *
    972 PKIX_ValidateChain(
    973        PKIX_ValidateParams *valParams,
    974        PKIX_ValidateResult **pResult,
    975        PKIX_VerifyNode **pVerifyTree,
    976        void *plContext)
    977 {
    978        PKIX_Error *chainFailed = NULL;
    979 
    980        PKIX_ProcessingParams *procParams = NULL;
    981        PKIX_CertChainChecker *userChecker = NULL;
    982        PKIX_RevocationChecker *revChecker = NULL;
    983        PKIX_List *certs = NULL;
    984        PKIX_List *checkers = NULL;
    985        PKIX_List *anchors = NULL;
    986        PKIX_List *userCheckers = NULL;
    987        PKIX_List *userCheckerExtOIDs = NULL;
    988        PKIX_List *validateCheckedCritExtOIDsList = NULL;
    989        PKIX_TrustAnchor *anchor = NULL;
    990        PKIX_ValidateResult *valResult = NULL;
    991        PKIX_PL_PublicKey *finalPubKey = NULL;
    992        PKIX_PolicyNode *validPolicyTree = NULL;
    993        PKIX_Boolean supportForwarding = PKIX_FALSE;
    994        PKIX_Boolean revChecking = PKIX_FALSE;
    995        PKIX_UInt32 i, numCerts, numAnchors;
    996        PKIX_UInt32 numUserCheckers = 0;
    997        PKIX_UInt32 certCheckedIndex = 0;
    998        PKIX_UInt32 checkerIndex = 0;
    999        PKIX_UInt32 reasonCode = 0;
   1000        void *nbioContext = NULL;
   1001 
   1002        PKIX_ENTER(VALIDATE, "PKIX_ValidateChain");
   1003        PKIX_NULLCHECK_TWO(valParams, pResult);
   1004 
   1005        /* extract various parameters from valParams */
   1006        PKIX_CHECK(pkix_ExtractParameters
   1007                    (valParams,
   1008                    &certs,
   1009                    &numCerts,
   1010                    &procParams,
   1011                    &anchors,
   1012                    &numAnchors,
   1013                    plContext),
   1014                    PKIX_EXTRACTPARAMETERSFAILED);
   1015 
   1016        /*
   1017         * setup an extension OID list that user had defined for his checker
   1018         * processing. User checker is not responsible for taking out OIDs
   1019         * from unresolved critical extension list as the libpkix checker
   1020         * is doing. Here we add those user checkers' OIDs to the removal
   1021         * list to be taken out by CheckChain
   1022         */
   1023        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
   1024                    (procParams, &userCheckers, plContext),
   1025                    PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
   1026 
   1027        if (userCheckers != NULL) {
   1028 
   1029                PKIX_CHECK(PKIX_List_Create
   1030                    (&validateCheckedCritExtOIDsList,
   1031                    plContext),
   1032                    PKIX_LISTCREATEFAILED);
   1033 
   1034                PKIX_CHECK(PKIX_List_GetLength
   1035                    (userCheckers, &numUserCheckers, plContext),
   1036                    PKIX_LISTGETLENGTHFAILED);
   1037 
   1038                for (i = 0; i < numUserCheckers; i++) {
   1039 
   1040                    PKIX_CHECK(PKIX_List_GetItem
   1041                        (userCheckers,
   1042                        i,
   1043                        (PKIX_PL_Object **) &userChecker,
   1044                        plContext),
   1045                        PKIX_LISTGETITEMFAILED);
   1046 
   1047                    PKIX_CHECK
   1048                        (PKIX_CertChainChecker_IsForwardCheckingSupported
   1049                        (userChecker, &supportForwarding, plContext),
   1050                        PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
   1051 
   1052                    if (supportForwarding == PKIX_FALSE) {
   1053 
   1054                        PKIX_CHECK
   1055                            (PKIX_CertChainChecker_GetSupportedExtensions
   1056                            (userChecker, &userCheckerExtOIDs, plContext),
   1057                            PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
   1058 
   1059                        if (userCheckerExtOIDs != NULL) {
   1060                            PKIX_CHECK(pkix_List_AppendList
   1061                                (validateCheckedCritExtOIDsList,
   1062                                userCheckerExtOIDs,
   1063                                plContext),
   1064                                PKIX_LISTAPPENDLISTFAILED);
   1065                        }
   1066                    }
   1067 
   1068                    PKIX_DECREF(userCheckerExtOIDs);
   1069                    PKIX_DECREF(userChecker);
   1070                }
   1071        }
   1072 
   1073        PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
   1074                (procParams, &revChecker, plContext),
   1075                PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
   1076 
   1077        /* try to validate the chain with each anchor */
   1078        for (i = 0; i < numAnchors; i++){
   1079 
   1080                /* get trust anchor */
   1081                PKIX_CHECK(PKIX_List_GetItem
   1082                        (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
   1083                        PKIX_LISTGETITEMFAILED);
   1084 
   1085                /* initialize checkers using information from trust anchor */
   1086                PKIX_CHECK(pkix_InitializeCheckers
   1087                        (anchor, procParams, numCerts, &checkers, plContext),
   1088                        PKIX_INITIALIZECHECKERSFAILED);
   1089 
   1090                /*
   1091                 * Validate the chain using this trust anchor and these
   1092                 * checkers. (WARNING: checkers that use non-blocking I/O
   1093                 * are not currently supported.)
   1094                 */
   1095                certCheckedIndex = 0;
   1096                checkerIndex = 0;
   1097                revChecking = PKIX_FALSE;
   1098                chainFailed = pkix_CheckChain
   1099                        (certs,
   1100                        numCerts,
   1101                        anchor,
   1102                        checkers,
   1103                        revChecker,
   1104                        validateCheckedCritExtOIDsList,
   1105                        procParams,
   1106                        &certCheckedIndex,
   1107                        &checkerIndex,
   1108                        &revChecking,
   1109                        &reasonCode,
   1110                        &nbioContext,
   1111                        &finalPubKey,
   1112                        &validPolicyTree,
   1113                        pVerifyTree,
   1114                        plContext);
   1115 
   1116                if (chainFailed) {
   1117 
   1118                        /* cert chain failed to validate */
   1119 
   1120                        PKIX_DECREF(chainFailed);
   1121                        PKIX_DECREF(anchor);
   1122                        PKIX_DECREF(checkers);
   1123                        PKIX_DECREF(validPolicyTree);
   1124 
   1125                        /* if last anchor, we fail; else, we try next anchor */
   1126                        if (i == (numAnchors - 1)) { /* last anchor */
   1127                                PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
   1128                        }
   1129 
   1130                } else {
   1131 
   1132                        /* XXX Remove this assertion after 2014-12-31.
   1133                         * See bug 946984. */
   1134                        PORT_Assert(reasonCode == 0);
   1135 
   1136                        /* cert chain successfully validated! */
   1137                        PKIX_CHECK(pkix_ValidateResult_Create
   1138                                (finalPubKey,
   1139                                anchor,
   1140                                validPolicyTree,
   1141                                &valResult,
   1142                                plContext),
   1143                                PKIX_VALIDATERESULTCREATEFAILED);
   1144 
   1145                        *pResult = valResult;
   1146 
   1147                        /* no need to try any more anchors in the loop */
   1148                        goto cleanup;
   1149                }
   1150        }
   1151 
   1152 cleanup:
   1153 
   1154        PKIX_DECREF(finalPubKey);
   1155        PKIX_DECREF(certs);
   1156        PKIX_DECREF(anchors);
   1157        PKIX_DECREF(anchor);
   1158        PKIX_DECREF(checkers);
   1159        PKIX_DECREF(revChecker);
   1160        PKIX_DECREF(validPolicyTree);
   1161        PKIX_DECREF(chainFailed);
   1162        PKIX_DECREF(procParams);
   1163        PKIX_DECREF(userCheckers);
   1164        PKIX_DECREF(validateCheckedCritExtOIDsList);
   1165 
   1166        PKIX_RETURN(VALIDATE);
   1167 }
   1168 
   1169 /*
   1170 * FUNCTION: pkix_Validate_BuildUserOIDs
   1171 * DESCRIPTION:
   1172 *
   1173 *  This function creates a List of the OIDs that are processed by the user
   1174 *  checkers in the List pointed to by "userCheckers", storing the resulting
   1175 *  List at "pUserCritOIDs". If the List of userCheckers is NULL, the output
   1176 *  List will be NULL. Otherwise the output List will be non-NULL, but may be
   1177 *  empty.
   1178 *
   1179 * PARAMETERS:
   1180 *  "userCheckers"
   1181 *      The address of the List of userCheckers.
   1182 *  "pUserCritOIDs"
   1183 *      The address at which the List is stored. Must be non-NULL.
   1184 *  "plContext"
   1185 *      Platform-specific context pointer.
   1186 * THREAD SAFETY:
   1187 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1188 * RETURNS:
   1189 *  Returns NULL if the function succeeds.
   1190 *  Returns a VALIDATE Error if the function fails in a non-fatal way.
   1191 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1192 */
   1193 static PKIX_Error *
   1194 pkix_Validate_BuildUserOIDs(
   1195        PKIX_List *userCheckers,
   1196        PKIX_List **pUserCritOIDs,
   1197        void *plContext)
   1198 {
   1199        PKIX_UInt32 numUserCheckers = 0;
   1200        PKIX_UInt32 i = 0;
   1201        PKIX_List *userCritOIDs = NULL;
   1202        PKIX_List *userCheckerExtOIDs = NULL;
   1203        PKIX_Boolean supportForwarding = PKIX_FALSE;
   1204        PKIX_CertChainChecker *userChecker = NULL;
   1205 
   1206        PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs");
   1207        PKIX_NULLCHECK_ONE(pUserCritOIDs);
   1208 
   1209        if (userCheckers != NULL) {
   1210            PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext),
   1211                PKIX_LISTCREATEFAILED);
   1212 
   1213            PKIX_CHECK(PKIX_List_GetLength
   1214                (userCheckers, &numUserCheckers, plContext),
   1215                PKIX_LISTGETLENGTHFAILED);
   1216 
   1217            for (i = 0; i < numUserCheckers; i++) {
   1218                PKIX_CHECK(PKIX_List_GetItem
   1219                    (userCheckers,
   1220                    i,
   1221                    (PKIX_PL_Object **) &userChecker,
   1222                    plContext),
   1223                    PKIX_LISTGETITEMFAILED);
   1224 
   1225                PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported
   1226                    (userChecker, &supportForwarding, plContext),
   1227                    PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
   1228 
   1229                if (supportForwarding == PKIX_FALSE) {
   1230 
   1231                    PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions
   1232                        (userChecker, &userCheckerExtOIDs, plContext),
   1233                        PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
   1234 
   1235                    if (userCheckerExtOIDs != NULL) {
   1236                        PKIX_CHECK(pkix_List_AppendList
   1237                            (userCritOIDs, userCheckerExtOIDs, plContext),
   1238                            PKIX_LISTAPPENDLISTFAILED);
   1239                    }
   1240                }
   1241 
   1242                PKIX_DECREF(userCheckerExtOIDs);
   1243                PKIX_DECREF(userChecker);
   1244            }
   1245        }
   1246 
   1247        *pUserCritOIDs = userCritOIDs;
   1248 
   1249 cleanup:
   1250 
   1251        if (PKIX_ERROR_RECEIVED){
   1252                PKIX_DECREF(userCritOIDs);
   1253        }
   1254 
   1255        PKIX_DECREF(userCheckerExtOIDs);
   1256        PKIX_DECREF(userChecker);
   1257 
   1258        PKIX_RETURN(VALIDATE);
   1259 }
   1260 
   1261 /*
   1262 * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h)
   1263 */
   1264 PKIX_Error *
   1265 PKIX_ValidateChain_NB(
   1266        PKIX_ValidateParams *valParams,
   1267        PKIX_UInt32 *pCertIndex,
   1268        PKIX_UInt32 *pAnchorIndex,
   1269        PKIX_UInt32 *pCheckerIndex,
   1270        PKIX_Boolean *pRevChecking,
   1271        PKIX_List **pCheckers,
   1272        void **pNBIOContext,
   1273        PKIX_ValidateResult **pResult,
   1274        PKIX_VerifyNode **pVerifyTree,
   1275        void *plContext)
   1276 {
   1277        PKIX_UInt32 numCerts = 0;
   1278        PKIX_UInt32 numAnchors = 0;
   1279        PKIX_UInt32 i = 0;
   1280        PKIX_UInt32 certIndex = 0;
   1281        PKIX_UInt32 anchorIndex = 0;
   1282        PKIX_UInt32 checkerIndex = 0;
   1283        PKIX_UInt32 reasonCode = 0;
   1284        PKIX_Boolean revChecking = PKIX_FALSE;
   1285        PKIX_List *certs = NULL;
   1286        PKIX_List *anchors = NULL;
   1287        PKIX_List *checkers = NULL;
   1288        PKIX_List *userCheckers = NULL;
   1289        PKIX_List *validateCheckedCritExtOIDsList = NULL;
   1290        PKIX_TrustAnchor *anchor = NULL;
   1291        PKIX_ValidateResult *valResult = NULL;
   1292        PKIX_PL_PublicKey *finalPubKey = NULL;
   1293        PKIX_PolicyNode *validPolicyTree = NULL;
   1294        PKIX_ProcessingParams *procParams = NULL;
   1295        PKIX_RevocationChecker *revChecker = NULL;
   1296        PKIX_Error *chainFailed = NULL;
   1297        void *nbioContext = NULL;
   1298 
   1299        PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB");
   1300        PKIX_NULLCHECK_FOUR
   1301                (valParams, pCertIndex, pAnchorIndex, pCheckerIndex);
   1302        PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult);
   1303 
   1304        nbioContext = *pNBIOContext;
   1305        *pNBIOContext = NULL;
   1306 
   1307        /* extract various parameters from valParams */
   1308        PKIX_CHECK(pkix_ExtractParameters
   1309                    (valParams,
   1310                    &certs,
   1311                    &numCerts,
   1312                    &procParams,
   1313                    &anchors,
   1314                    &numAnchors,
   1315                    plContext),
   1316                    PKIX_EXTRACTPARAMETERSFAILED);
   1317 
   1318        /*
   1319         * Create a List of the OIDs that will be processed by the user
   1320         * checkers. User checkers are not responsible for removing OIDs from
   1321         * the List of unresolved critical extensions, as libpkix checkers are.
   1322         * So we add those user checkers' OIDs to the removal list to be taken
   1323         * out by CheckChain.
   1324         */
   1325        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
   1326                (procParams, &userCheckers, plContext),
   1327                PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
   1328 
   1329        PKIX_CHECK(pkix_Validate_BuildUserOIDs
   1330                (userCheckers, &validateCheckedCritExtOIDsList, plContext),
   1331                PKIX_VALIDATEBUILDUSEROIDSFAILED);
   1332 
   1333        PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
   1334                (procParams, &revChecker, plContext),
   1335                PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
   1336 
   1337        /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
   1338        if (nbioContext != NULL) {
   1339                /* Resuming */
   1340                certIndex = *pCertIndex;
   1341                anchorIndex = *pAnchorIndex;
   1342                checkerIndex = *pCheckerIndex;
   1343                revChecking = *pRevChecking;
   1344                checkers = *pCheckers;
   1345                *pCheckers = NULL;
   1346        }
   1347 
   1348        /* try to validate the chain with each anchor */
   1349        for (i = anchorIndex; i < numAnchors; i++) {
   1350 
   1351                /* get trust anchor */
   1352                PKIX_CHECK(PKIX_List_GetItem
   1353                        (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
   1354                        PKIX_LISTGETITEMFAILED);
   1355 
   1356                /* initialize checkers using information from trust anchor */
   1357                if (nbioContext == NULL) {
   1358                        PKIX_CHECK(pkix_InitializeCheckers
   1359                                (anchor,
   1360                                procParams,
   1361                                numCerts,
   1362                                &checkers,
   1363                                plContext),
   1364                                PKIX_INITIALIZECHECKERSFAILED);
   1365                }
   1366 
   1367                /*
   1368                 * Validate the chain using this trust anchor and these
   1369                 * checkers.
   1370                 */
   1371                chainFailed = pkix_CheckChain
   1372                        (certs,
   1373                        numCerts,
   1374                        anchor,
   1375                        checkers,
   1376                        revChecker,
   1377                        validateCheckedCritExtOIDsList,
   1378                        procParams,
   1379                        &certIndex,
   1380                        &checkerIndex,
   1381                        &revChecking,
   1382                        &reasonCode,
   1383                        &nbioContext,
   1384                        &finalPubKey,
   1385                        &validPolicyTree,
   1386                        pVerifyTree,
   1387                        plContext);
   1388 
   1389                if (nbioContext != NULL) {
   1390                        *pCertIndex = certIndex;
   1391                        *pAnchorIndex = anchorIndex;
   1392                        *pCheckerIndex = checkerIndex;
   1393                        *pRevChecking = revChecking;
   1394                        PKIX_INCREF(checkers);
   1395                        *pCheckers = checkers;
   1396                        *pNBIOContext = nbioContext;
   1397                        goto cleanup;
   1398                }
   1399 
   1400                if (chainFailed) {
   1401 
   1402                        /* cert chain failed to validate */
   1403 
   1404                        PKIX_DECREF(chainFailed);
   1405                        PKIX_DECREF(anchor);
   1406                        PKIX_DECREF(checkers);
   1407                        PKIX_DECREF(validPolicyTree);
   1408 
   1409                        /* if last anchor, we fail; else, we try next anchor */
   1410                        if (i == (numAnchors - 1)) { /* last anchor */
   1411                                PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
   1412                        }
   1413 
   1414                } else {
   1415 
   1416                        /* XXX Remove this assertion after 2014-12-31.
   1417                         * See bug 946984. */
   1418                        PORT_Assert(reasonCode == 0);
   1419 
   1420                        /* cert chain successfully validated! */
   1421                        PKIX_CHECK(pkix_ValidateResult_Create
   1422                                (finalPubKey,
   1423                                anchor,
   1424                                validPolicyTree,
   1425                                &valResult,
   1426                                plContext),
   1427                                PKIX_VALIDATERESULTCREATEFAILED);
   1428 
   1429                        *pResult = valResult;
   1430 
   1431                        /* no need to try any more anchors in the loop */
   1432                        goto cleanup;
   1433                }
   1434        }
   1435 
   1436 cleanup:
   1437 
   1438        PKIX_DECREF(finalPubKey);
   1439        PKIX_DECREF(certs);
   1440        PKIX_DECREF(anchors);
   1441        PKIX_DECREF(anchor);
   1442        PKIX_DECREF(checkers);
   1443        PKIX_DECREF(revChecker);
   1444        PKIX_DECREF(validPolicyTree);
   1445        PKIX_DECREF(chainFailed);
   1446        PKIX_DECREF(procParams);
   1447        PKIX_DECREF(userCheckers);
   1448        PKIX_DECREF(validateCheckedCritExtOIDsList);
   1449 
   1450        PKIX_RETURN(VALIDATE);
   1451 }