Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  pkix_validate.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * pkix_validate.c
 *
 * Top level validateChain function
 *
 */


#include "pkix_validate.h"
#include "pkix_pl_common.h"

/* --Private-Functions-------------------------------------------- */

/*
 * FUNCTION: pkix_AddToVerifyLog
 * DESCRIPTION:
 *
 *  This function returns immediately if the address for the VerifyNode tree
 *  pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode
 *  from the Cert pointed to by "cert" and the Error pointed to by "error",
 *  and inserts it at the depth in the VerifyNode tree determined by "depth". A
 *  depth of zero means that this function creates the root node of a new tree.
 *
 *  Note: this function does not include the means of choosing among branches
 *  of a tree. It is intended for non-branching trees, that is, where each
 *  parent node has only a single child node.
 *
 * PARAMETERS:
 *  "cert"
 *      The address of the Cert to be included in the new VerifyNode. Must be
 *      non-NULL.
 *  "depth"
 *      The UInt32 value of the depth.
 *  "error"
 *      The address of the Error to be included in the new VerifyNode.
 *  "pVerifyTree"
 *      The address of the VerifyNode tree into which the created VerifyNode
 *      is to be inserted. The node is not created if VerifyTree is NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a Validate Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */

static PKIX_Error *
pkix_AddToVerifyLog(
        PKIX_PL_Cert *cert,
        PKIX_UInt32 depth,
        PKIX_Error *error,
        PKIX_VerifyNode **pVerifyTree,
        void *plContext)
{

        PKIX_VerifyNode *verifyNode = NULL;

        PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog");
        PKIX_NULLCHECK_ONE(cert);

        if (pVerifyTree) { /* nothing to do if no address given for log */

                PKIX_CHECK(pkix_VerifyNode_Create
                        (cert, depth, error, &verifyNode, plContext),
                        PKIX_VERIFYNODECREATEFAILED);

                if (depth == 0) {
                        /* We just created the root node */
                        *pVerifyTree = verifyNode;
                } else {
                        PKIX_CHECK(pkix_VerifyNode_AddToChain
                                (*pVerifyTree, verifyNode, plContext),
                                PKIX_VERIFYNODEADDTOCHAINFAILED);
                }
        }

cleanup:

        PKIX_RETURN(VALIDATE);

}

/*
 * FUNCTION: pkix_CheckCert
 * DESCRIPTION:
 *
 *  Checks whether the Cert pointed to by "cert" successfully validates
 *  using the List of CertChainCheckers pointed to by "checkers". If the
 *  certificate does not validate, an Error pointer is returned.
 *
 *  This function should be called initially with the UInt32 pointed to by
 *  "pCheckerIndex" containing zero, and the pointer at "pNBIOContext"
 *  containing NULL. If a checker does non-blocking I/O, this function will
 *  return with the index of that checker stored at "pCheckerIndex" and a
 *  platform-dependent non-blocking I/O context stored at "pNBIOContext".
 *  A subsequent call to this function with those values intact will allow the
 *  checking to resume where it left off. This should be repeated until the
 *  function returns with NULL stored at "pNBIOContext".
 *
 * PARAMETERS:
 *  "cert"
 *      Address of Cert to validate. Must be non-NULL.
 *  "checkers"
 *      List of CertChainCheckers which must each validate the certificate.
 *      Must be non-NULL.
 *  "checkedExtOIDs"
 *      List of PKIX_PL_OID that has been processed. If called from building
 *      chain, it is the list of critical extension OIDs that has been
 *      processed prior to validation. May be NULL.
 *  "pCheckerIndex"
 *      Address at which is stored the the index, within the List "checkers",
 *      of a checker whose processing was interrupted by non-blocking I/O.
 *      Must be non-NULL.
 *  "pNBIOContext"
 *      Address at which is stored platform-specific non-blocking I/O context.
 *      Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a Validate Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */

static PKIX_Error *
pkix_CheckCert(
        PKIX_PL_Cert *cert,
        PKIX_List *checkers,
        PKIX_List *checkedExtOIDsList,
        PKIX_UInt32 *pCheckerIndex,
        void **pNBIOContext,
        void *plContext)
{
        PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
        PKIX_CertChainChecker *checker = NULL;
        PKIX_List *unresCritExtOIDs = NULL;
        PKIX_UInt32 numCheckers;
        PKIX_UInt32 numUnresCritExtOIDs = 0;
        PKIX_UInt32 checkerIndex = 0;
        void *nbioContext = NULL;

        PKIX_ENTER(VALIDATE, "pkix_CheckCert");
        PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext);

        nbioContext = *pNBIOContext;
        *pNBIOContext = NULL; /* prepare for case of error exit */

        PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
                    (cert, &unresCritExtOIDs, plContext),
                    PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);

        PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
                    PKIX_LISTGETLENGTHFAILED);

        for (checkerIndex = *pCheckerIndex;
                checkerIndex < numCheckers;
                checkerIndex++) {

                PKIX_CHECK(PKIX_List_GetItem
                        (checkers,
                        checkerIndex,
                        (PKIX_PL_Object **)&checker,
                        plContext),
                        PKIX_LISTGETITEMFAILED);

                PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
                        (checker, &checkerCheck, plContext),
                        PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);

                PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs,
                                        &nbioContext,  plContext),
                           PKIX_CERTCHAINCHECKERCHECKFAILED);

                if (nbioContext != NULL) {
                        *pCheckerIndex = checkerIndex;
                        *pNBIOContext = nbioContext;
                        goto cleanup;
                }

                PKIX_DECREF(checker);
        }

        if (unresCritExtOIDs){

#ifdef PKIX_VALIDATEDEBUG
                {
                        PKIX_PL_String *oidString = NULL;
                        PKIX_UInt32 length;
                        char *oidAscii = NULL;
                        PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext,
                                PKIX_LISTTOSTRINGFAILED);
                        PKIX_CHECK(PKIX_PL_String_GetEncoded
                                (oidString,
                                PKIX_ESCASCII,
                                (void **) &oidAscii,
                                &length,
                                plContext),
                                PKIX_STRINGGETENCODEDFAILED);
                        PKIX_VALIDATE_DEBUG_ARG
                                ("unrecognized critical extension OIDs:"
                                " %s\n", oidAscii);
                        PKIX_DECREF(oidString);
                        PKIX_PL_Free(oidAscii, plContext);
                }
#endif

                if (checkedExtOIDsList != NULL) {
                 /* Take out OID's that had been processed, if any */
                        PKIX_CHECK(pkix_List_RemoveItems
                                (unresCritExtOIDs,
                                checkedExtOIDsList,
                                plContext),
                                PKIX_LISTREMOVEITEMSFAILED);
                }

                PKIX_CHECK(PKIX_List_GetLength
                        (unresCritExtOIDs, &numUnresCritExtOIDs, plContext),
                        PKIX_LISTGETLENGTHFAILED);

                if (numUnresCritExtOIDs != 0){
                        PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION);
                }

        }

cleanup:

        PKIX_DECREF(checker);
        PKIX_DECREF(unresCritExtOIDs);

        PKIX_RETURN(VALIDATE);

}

/*
 * FUNCTION: pkix_InitializeCheckers
 * DESCRIPTION:
 *
 *  Creates several checkers and initializes them with values derived from the
 *  TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by
 *  "procParams", and the number of Certs in the Chain, represented by
 *  "numCerts". The List of checkers is stored at "pCheckers".
 *
 * PARAMETERS:
 *  "anchor"
 *      Address of TrustAnchor used to initialize the SignatureChecker and
 *      NameChainingChecker. Must be non-NULL.
 *  "procParams"
 *      Address of ProcessingParams used to initialize the ExpirationChecker
 *      and TargetCertChecker. Must be non-NULL.
 *  "numCerts"
 *      Number of certificates in the CertChain.
 *  "pCheckers"
 *      Address where object pointer will be stored. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a Validate Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */

static PKIX_Error *
pkix_InitializeCheckers(
        PKIX_TrustAnchor *anchor,
        PKIX_ProcessingParams *procParams,
        PKIX_UInt32 numCerts,
        PKIX_List **pCheckers,
        void *plContext)
{
        PKIX_CertChainChecker *targetCertChecker = NULL;
        PKIX_CertChainChecker *expirationChecker = NULL;
        PKIX_CertChainChecker *nameChainingChecker = NULL;
        PKIX_CertChainChecker *nameConstraintsChecker = NULL;
        PKIX_CertChainChecker *basicConstraintsChecker = NULL;
        PKIX_CertChainChecker *policyChecker = NULL;
        PKIX_CertChainChecker *sigChecker = NULL;
        PKIX_CertChainChecker *defaultCrlChecker = NULL;
        PKIX_CertChainChecker *userChecker = NULL;
        PKIX_PL_X500Name *trustedCAName = NULL;
        PKIX_PL_PublicKey *trustedPubKey = NULL;
        PKIX_List *checkers = NULL;
        PKIX_PL_Date *testDate = NULL;
        PKIX_CertSelector *certSelector = NULL;
        PKIX_PL_Cert *trustedCert = NULL;
        PKIX_PL_CertNameConstraints *trustedNC = NULL;
        PKIX_List *initialPolicies = NULL;
        PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
        PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
        PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
        PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
        PKIX_List *userCheckersList = NULL;
        PKIX_List *certStores = NULL;
        PKIX_UInt32 numCertCheckers = 0;
        PKIX_UInt32 i;

        PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers");
        PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers);
        PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
                    PKIX_LISTCREATEFAILED);

        /*
         * The TrustAnchor may have been created using CreateWithCert
         * (in which case GetCAPublicKey and GetCAName will return NULL)
         * or may have been created using CreateWithNameKeyPair (in which
         * case GetTrustedCert will return NULL. So we call GetTrustedCert
         * and populate trustedPubKey and trustedCAName accordingly.
         */


        PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
                (anchor, &trustedCert, plContext),
                    PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);

        if (trustedCert){
                PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
                            (trustedCert, &trustedPubKey, plContext),
                            PKIX_CERTGETSUBJECTPUBLICKEYFAILED);

                PKIX_CHECK(PKIX_PL_Cert_GetSubject
                            (trustedCert, &trustedCAName, plContext),
                            PKIX_CERTGETSUBJECTFAILED);
        } else {
                PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey
                            (anchor, &trustedPubKey, plContext),
                            PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED);

                PKIX_CHECK(PKIX_TrustAnchor_GetCAName
                            (anchor, &trustedCAName, plContext),
                            PKIX_TRUSTANCHORGETCANAMEFAILED);
        }

        PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName);

        PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
                (anchor, &trustedNC, plContext),
                PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
                (procParams, &certSelector, plContext),
                PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_GetDate
                (procParams, &testDate, plContext),
                PKIX_PROCESSINGPARAMSGETDATEFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
                (procParams, &initialPolicies, plContext),
                PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
                (procParams, &policyQualifiersRejected, plContext),
                PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
                (procParams, &initialPolicyMappingInhibit, plContext),
                PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
                (procParams, &initialAnyPolicyInhibit, plContext),
                PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
                (procParams, &initialExplicitPolicy, plContext),
                PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
                (procParams, &certStores, plContext),
                PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
                (procParams, &userCheckersList, plContext),
                PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);

        /* now, initialize all the checkers */
        PKIX_CHECK(pkix_TargetCertChecker_Initialize
                (certSelector, numCerts, &targetCertChecker, plContext),
                PKIX_TARGETCERTCHECKERINITIALIZEFAILED);

        PKIX_CHECK(pkix_ExpirationChecker_Initialize
                (testDate, &expirationChecker, plContext),
                PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);

        PKIX_CHECK(pkix_NameChainingChecker_Initialize
                (trustedCAName, &nameChainingChecker, plContext),
                PKIX_NAMECHAININGCHECKERINITIALIZEFAILED);

        PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
                (trustedNC, numCerts, &nameConstraintsChecker, plContext),
                PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);

        PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize
                (numCerts, &basicConstraintsChecker, plContext),
                PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED);

        PKIX_CHECK(pkix_PolicyChecker_Initialize
                (initialPolicies,
                policyQualifiersRejected,
                initialPolicyMappingInhibit,
                initialExplicitPolicy,
                initialAnyPolicyInhibit,
                numCerts,
                &policyChecker,
                plContext),
                PKIX_POLICYCHECKERINITIALIZEFAILED);

        PKIX_CHECK(pkix_SignatureChecker_Initialize
                    (trustedPubKey, numCerts, &sigChecker, plContext),
                    PKIX_SIGNATURECHECKERINITIALIZEFAILED);

        if (userCheckersList != NULL) {

                PKIX_CHECK(PKIX_List_GetLength
                    (userCheckersList, &numCertCheckers, plContext),
                    PKIX_LISTGETLENGTHFAILED);

                for (i = 0; i < numCertCheckers; i++) {

                        PKIX_CHECK(PKIX_List_GetItem
                            (userCheckersList,
                            i,
                            (PKIX_PL_Object **) &userChecker,
                            plContext),
                            PKIX_LISTGETITEMFAILED);

                        PKIX_CHECK(PKIX_List_AppendItem
                            (checkers,
                            (PKIX_PL_Object *)userChecker,
                            plContext),
                            PKIX_LISTAPPENDITEMFAILED);

                        PKIX_DECREF(userChecker);
                }
        }

        PKIX_CHECK(PKIX_List_AppendItem
            (checkers, (PKIX_PL_Object *)targetCertChecker, plContext),
            PKIX_LISTAPPENDITEMFAILED);

        PKIX_CHECK(PKIX_List_AppendItem
            (checkers, (PKIX_PL_Object *)expirationChecker, plContext),
            PKIX_LISTAPPENDITEMFAILED);

        PKIX_CHECK(PKIX_List_AppendItem
            (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext),
            PKIX_LISTAPPENDITEMFAILED);

        PKIX_CHECK(PKIX_List_AppendItem
            (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext),
            PKIX_LISTAPPENDITEMFAILED);

        PKIX_CHECK(PKIX_List_AppendItem
            (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext),
            PKIX_LISTAPPENDITEMFAILED);

        PKIX_CHECK(PKIX_List_AppendItem
            (checkers, (PKIX_PL_Object *)policyChecker, plContext),
            PKIX_LISTAPPENDITEMFAILED);

        PKIX_CHECK(PKIX_List_AppendItem
            (checkers, (PKIX_PL_Object *)sigChecker, plContext),
            PKIX_LISTAPPENDITEMFAILED);

        *pCheckers = checkers;

cleanup:

        if (PKIX_ERROR_RECEIVED){
                PKIX_DECREF(checkers);
        }

        PKIX_DECREF(certSelector);
        PKIX_DECREF(testDate);
        PKIX_DECREF(initialPolicies);
        PKIX_DECREF(targetCertChecker);
        PKIX_DECREF(expirationChecker);
        PKIX_DECREF(nameChainingChecker);
        PKIX_DECREF(nameConstraintsChecker);
        PKIX_DECREF(basicConstraintsChecker);
        PKIX_DECREF(policyChecker);
        PKIX_DECREF(sigChecker);
        PKIX_DECREF(trustedCAName);
        PKIX_DECREF(trustedPubKey);
        PKIX_DECREF(trustedNC);
        PKIX_DECREF(trustedCert);
        PKIX_DECREF(defaultCrlChecker);
        PKIX_DECREF(userCheckersList);
        PKIX_DECREF(certStores);
        PKIX_DECREF(userChecker);

        PKIX_RETURN(VALIDATE);
}

/*
 * FUNCTION: pkix_RetrieveOutputs
 * DESCRIPTION:
 *
 *  This function queries the respective states of the List of checkers in
 *  "checkers" to to obtain the final public key from the SignatureChecker
 *  and the policy tree from the PolicyChecker, storing those values at
 *  "pFinalSubjPubKey" and "pPolicyTree", respectively.
 *
 * PARAMETERS:
 *  "checkers"
 *      Address of List of checkers to be queried. Must be non-NULL.
 *  "pFinalSubjPubKey"
 *      Address where final public key will be stored. Must be non-NULL.
 *  "pPolicyTree"
 *      Address where policy tree will be stored. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a Validate Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */

static PKIX_Error *
pkix_RetrieveOutputs(
        PKIX_List *checkers,
        PKIX_PL_PublicKey **pFinalSubjPubKey,
        PKIX_PolicyNode **pPolicyTree,
        void *plContext)
{
        PKIX_PL_PublicKey *finalSubjPubKey = NULL;
        PKIX_PolicyNode *validPolicyTree = NULL;
        PKIX_CertChainChecker *checker = NULL;
        PKIX_PL_Object *state = NULL;
        PKIX_UInt32 numCheckers = 0;
        PKIX_UInt32 type;
        PKIX_Int32 j;

        PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs");

        PKIX_NULLCHECK_TWO(checkers, pPolicyTree);

        /*
         * To optimize the search, we guess that the sigChecker is
         * last in the tree and is preceded by the policyChecker. We
         * search toward the front of the chain. Remember that List
         * items are indexed 0..(numItems - 1).
         */


        PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
                PKIX_LISTGETLENGTHFAILED);

        for (j = numCheckers - 1; j >= 0; j--){
                PKIX_CHECK(PKIX_List_GetItem
                        (checkers, j, (PKIX_PL_Object **)&checker, plContext),
                        PKIX_LISTGETITEMFAILED);

                PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
                        (checker, &state, plContext),
                        PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);

                /* user defined checker may have no state */
                if (state != NULL) {

                    PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext),
                            PKIX_OBJECTGETTYPEFAILED);

                    if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){
                        /* final pubKey will include any inherited DSA params */
                        finalSubjPubKey =
                            ((pkix_SignatureCheckerState *)state)->
                                prevPublicKey;
                        PKIX_INCREF(finalSubjPubKey);
                        *pFinalSubjPubKey = finalSubjPubKey;
                    }

                    if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) {
                        validPolicyTree =
                            ((PKIX_PolicyCheckerState *)state)->validPolicyTree;
                        break;
                    }
                }

                PKIX_DECREF(checker);
                PKIX_DECREF(state);
        }

        PKIX_INCREF(validPolicyTree);
        *pPolicyTree = validPolicyTree;

cleanup:

        PKIX_DECREF(checker);
        PKIX_DECREF(state);

        PKIX_RETURN(VALIDATE);

}

/*
 * FUNCTION: pkix_CheckChain
 * DESCRIPTION:
 *
 *  Checks whether the List of Certs pointed to by "certs", containing
 *  "numCerts" entries, successfully validates using each CertChainChecker in
 *  the List pointed to by "checkers" and has not been revoked, according to any
 *  of the Revocation Checkers in the List pointed to by "revChecker". Checkers
 *  are expected to remove from "removeCheckedExtOIDs" and extensions that they
 *  process. Indices to the certChain and the checkerChain are obtained and
 *  returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These
 *  should be set to zero prior to the initial call, but may be changed (and
 *  must be supplied on subsequent calls) if processing is suspended for non-
 *  blocking I/O. Each time a Cert passes from being validated by one of the
 *  CertChainCheckers to being checked by a Revocation Checker, the Boolean
 *  stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is
 *  rejected by a Revocation Checker, its reason code is returned at
 *  "pReasonCode. If the List of Certs successfully validates, the public key i
 *  the final certificate is obtained and stored at "pFinalSubjPubKey" and the
 *  validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List
 *  of Certs fails to validate, an Error pointer is returned.
 *
 *  If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which
 *  tracks the results of the validation. That is, either each node in the
 *  chain has a NULL Error component, or the last node contains an Error
 *  which indicates why the validation failed.
 *
 *  The number of Certs in the List, represented by "numCerts", is used to
 *  determine which Cert is the final Cert.
 *
 * PARAMETERS:
 *  "certs"
 *      Address of List of Certs to validate. Must be non-NULL.
 *  "numCerts"
 *      Number of certificates in the List of certificates.
 *  "checkers"
 *      List of CertChainCheckers which must each validate the List of
 *      certificates. Must be non-NULL.
 *  "revChecker"
 *      List of RevocationCheckers which must each not reject the List of
 *      certificates. May be empty, but must be non-NULL.
 *  "removeCheckedExtOIDs"
 *      List of PKIX_PL_OID that has been processed. If called from building
 *      chain, it is the list of critical extension OIDs that has been
 *      processed prior to validation. Extension OIDs that may be processed by
 *      user defined checker processes are also in the list. May be NULL.
 *  "procParams"
 *      Address of ProcessingParams used to initialize various checkers. Must
 *      be non-NULL.
 *  "pCertCheckedIndex"
 *      Address where Int32 index to the Cert chain is obtained and
 *      returned. Must be non-NULL.
 *  "pCheckerIndex"
 *      Address where Int32 index to the CheckerChain is obtained and
 *      returned. Must be non-NULL.
 *  "pRevChecking"
 *      Address where Boolean is obtained and returned, indicating, if FALSE,
 *      that CertChainCheckers are being called; or, if TRUE, that RevChecker
 *      are being called. Must be non-NULL.
 *  "pReasonCode"
 *      Address where UInt32 results of revocation checking are stored. Must be
 *      non-NULL.
 *  "pNBIOContext"
 *      Address where platform-dependent context is stored if checking is
 *      suspended for non-blocking I/O. Must be non-NULL.
 *  "pFinalSubjPubKey"
 *      Address where the final public key will be stored. Must be non-NULL.
 *  "pPolicyTree"
 *      Address where the final validPolicyTree is stored. Must be non-NULL.
 *  "pVerifyTree"
 *      Address where a VerifyTree is stored, if non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a Validate Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */

PKIX_Error *
pkix_CheckChain(
        PKIX_List *certs,
        PKIX_UInt32 numCerts,
        PKIX_TrustAnchor *anchor,
        PKIX_List *checkers,
        PKIX_RevocationChecker *revChecker,
        PKIX_List *removeCheckedExtOIDs,
        PKIX_ProcessingParams *procParams,
        PKIX_UInt32 *pCertCheckedIndex,
        PKIX_UInt32 *pCheckerIndex,
        PKIX_Boolean *pRevChecking,
        PKIX_UInt32 *pReasonCode,
        void **pNBIOContext,
        PKIX_PL_PublicKey **pFinalSubjPubKey,
        PKIX_PolicyNode **pPolicyTree,
        PKIX_VerifyNode **pVerifyTree,
        void *plContext)
{
        PKIX_UInt32 j = 0;
        PKIX_Boolean revChecking = PKIX_FALSE;
        PKIX_Error *checkCertError = NULL;
        void *nbioContext = NULL;
        PKIX_PL_Cert *cert = NULL;
        PKIX_PL_Cert *issuer = NULL;
        PKIX_PL_NssContext *nssContext = NULL;
        CERTCertList *certList = NULL;
        const CERTChainVerifyCallback *chainVerifyCallback = NULL;
        CERTCertificate *nssCert = NULL;

        PKIX_ENTER(VALIDATE, "pkix_CheckChain");
        PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex);
        PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor);
        PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree);

        nbioContext = *pNBIOContext;
        *pNBIOContext = NULL;
        revChecking = *pRevChecking;
        nssContext = (PKIX_PL_NssContext *)plContext;
        chainVerifyCallback = &nssContext->chainVerifyCallback;

        if (chainVerifyCallback->isChainValid != NULL) {
                PRBool chainOK = PR_FALSE; /*assume failure*/
                SECStatus rv;

                certList = CERT_NewCertList();
                if (certList == NULL) {
                        PKIX_ERROR_ALLOC_ERROR();
                }

                /* Add the trust anchor to the list */
                PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
                        (anchor, &cert, plContext),
                        PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);

                PKIX_CHECK(
                        PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
                        PKIX_CERTGETCERTCERTIFICATEFAILED);

                rv = CERT_AddCertToListHead(certList, nssCert);
                if (rv != SECSuccess) {
                        PKIX_ERROR_ALLOC_ERROR();
                }
                /* the certList takes ownership of nssCert on success */
                nssCert = NULL;
                PKIX_DECREF(cert);

                /* Add the rest of the chain to the list */
                for (j = *pCertCheckedIndex; j < numCerts; j++) {
                        PKIX_CHECK(PKIX_List_GetItem(
                                certs, j, (PKIX_PL_Object **)&cert, plContext),
                                PKIX_LISTGETITEMFAILED);

                        PKIX_CHECK(
                                PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
                                PKIX_CERTGETCERTCERTIFICATEFAILED);

                        rv = CERT_AddCertToListHead(certList, nssCert);
                        if (rv != SECSuccess) {
                                PKIX_ERROR_ALLOC_ERROR();
                        }
                        /* the certList takes ownership of nssCert on success */
                        nssCert = NULL;
                        PKIX_DECREF(cert);
                }

                rv = (*chainVerifyCallback->isChainValid)
                     (chainVerifyCallback->isChainValidArg, certList, &chainOK);
                if (rv != SECSuccess) {
                       PKIX_ERROR_FATAL(PKIX_CHAINVERIFYCALLBACKFAILED);
                }

                if (!chainOK) {
                        PKIX_ERROR(PKIX_CHAINVERIFYCALLBACKFAILED);
                }

        }

        PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
                (anchor, &cert, plContext),
                   PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);

        for (j = *pCertCheckedIndex; j < numCerts; j++) {

                PORT_Assert(cert);
                PKIX_DECREF(issuer);
                issuer = cert;
                cert = NULL;

                PKIX_CHECK(PKIX_List_GetItem(
                               certs, j, (PKIX_PL_Object **)&cert, plContext),
                           PKIX_LISTGETITEMFAILED);
                
                /* check if cert pointer is valid */
                PORT_Assert(cert);
                if (cert == NULL) {
                    continue;
                }

                if (revChecking == PKIX_FALSE) {

                        PKIX_CHECK(pkix_CheckCert
                                (cert,
                                checkers,
                                removeCheckedExtOIDs,
                                pCheckerIndex,
                                &nbioContext,
                                plContext),
                                PKIX_CHECKCERTFAILED);

                        if (nbioContext != NULL) {
                                *pCertCheckedIndex = j;
                                *pRevChecking = revChecking;
                                *pNBIOContext = nbioContext;
                                goto cleanup;
                        }

                        revChecking = PKIX_TRUE;
                        *pCheckerIndex = 0;
                }

                if (revChecking == PKIX_TRUE) {
                        PKIX_RevocationStatus revStatus;
                        pkixErrorResult =
                            PKIX_RevocationChecker_Check(
                                      cert, issuer, revChecker,
                                      procParams, PKIX_TRUE,
                                      (j == numCerts - 1) ? PKIX_TRUE : PKIX_FALSE,
                                      &revStatus, pReasonCode,
                                      &nbioContext, plContext);
                        if (nbioContext != NULL) {
                                *pCertCheckedIndex = j;
                                *pRevChecking = revChecking;
                                *pNBIOContext = nbioContext;
                                goto cleanup;
                        }
                        if (revStatus == PKIX_RevStatus_Revoked ||
                            pkixErrorResult) {
                            if (!pkixErrorResult) {
                                /* if pkixErrorResult is returned then
                                 * use it as it has a detailed revocation
                                 * error code. Otherwise create a new error */

                                PKIX_ERROR_CREATE(VALIDATE,
                                                  PKIX_CERTIFICATEREVOKED,
                                                  pkixErrorResult);
                            }
                            goto cleanup;
                        }
                        revChecking = PKIX_FALSE;
                        *pCheckerIndex = 0;
                }

                PKIX_CHECK(pkix_AddToVerifyLog
                        (cert, j, NULL, pVerifyTree, plContext),
                        PKIX_ADDTOVERIFYLOGFAILED);
        }

        PKIX_CHECK(pkix_RetrieveOutputs
                    (checkers, pFinalSubjPubKey, pPolicyTree, plContext),
                    PKIX_RETRIEVEOUTPUTSFAILED);

        *pNBIOContext = NULL;

cleanup:
        if (PKIX_ERROR_RECEIVED && cert) {
            checkCertError = pkixErrorResult;
            
            PKIX_CHECK_FATAL(
                pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree,
                                    plContext),
                PKIX_ADDTOVERIFYLOGFAILED);
            pkixErrorResult = checkCertError;
            pkixErrorCode = pkixErrorResult->errCode;
            checkCertError = NULL;
        }

fatal:
        if (nssCert) {
                CERT_DestroyCertificate(nssCert);
        }

        if (certList) {
                CERT_DestroyCertList(certList);
        }

        PKIX_DECREF(checkCertError);
        PKIX_DECREF(cert);
        PKIX_DECREF(issuer);

        PKIX_RETURN(VALIDATE);
}

/*
 * FUNCTION: pkix_ExtractParameters
 * DESCRIPTION:
 *
 *  Extracts several parameters from the ValidateParams object pointed to by
 *  "valParams" and stores the CertChain at "pChain", the List of Certs at
 *  "pCerts", the number of Certs in the chain at "pNumCerts", the
 *  ProcessingParams object at "pProcParams", the List of TrustAnchors at
 *  "pAnchors", and the number of TrustAnchors at "pNumAnchors".
 *
 * PARAMETERS:
 *  "valParams"
 *      Address of ValidateParams from which the parameters are extracted.
 *      Must be non-NULL.
 *  "pCerts"
 *      Address where object pointer for List of Certs will be stored.
 *      Must be non-NULL.
 *  "pNumCerts"
 *      Address where number of Certs will be stored. Must be non-NULL.
 *  "pProcParams"
 *      Address where object pointer for ProcessingParams will be stored.
 *      Must be non-NULL.
 *  "pAnchors"
 *      Address where object pointer for List of Anchors will be stored.
 *      Must be non-NULL.
 *  "pNumAnchors"
 *      Address where number of Anchors will be stored. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a Validate Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */

static PKIX_Error *
pkix_ExtractParameters(
        PKIX_ValidateParams *valParams,
        PKIX_List **pCerts,
        PKIX_UInt32 *pNumCerts,
        PKIX_ProcessingParams **pProcParams,
        PKIX_List **pAnchors,
        PKIX_UInt32 *pNumAnchors,
        void *plContext)
{
        PKIX_ENTER(VALIDATE, "pkix_ExtractParameters");
        PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts);
        PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors);

        /* extract relevant parameters from chain */
        PKIX_CHECK(PKIX_ValidateParams_GetCertChain
                (valParams, pCerts, plContext),
                PKIX_VALIDATEPARAMSGETCERTCHAINFAILED);

        PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext),
                PKIX_LISTGETLENGTHFAILED);

        /* extract relevant parameters from procParams */
        PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams
                (valParams, pProcParams, plContext),
                PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
                (*pProcParams, pAnchors, plContext),
                PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);

        PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext),
                PKIX_LISTGETLENGTHFAILED);

cleanup:

        PKIX_RETURN(VALIDATE);
}

/* --Public-Functions--------------------------------------------- */

/*
 * FUNCTION: PKIX_ValidateChain (see comments in pkix.h)
 */

PKIX_Error *
PKIX_ValidateChain(
        PKIX_ValidateParams *valParams,
        PKIX_ValidateResult **pResult,
        PKIX_VerifyNode **pVerifyTree,
        void *plContext)
{
        PKIX_Error *chainFailed = NULL;

        PKIX_ProcessingParams *procParams = NULL;
        PKIX_CertChainChecker *userChecker = NULL;
        PKIX_RevocationChecker *revChecker = NULL;
        PKIX_List *certs = NULL;
        PKIX_List *checkers = NULL;
        PKIX_List *anchors = NULL;
        PKIX_List *userCheckers = NULL;
        PKIX_List *userCheckerExtOIDs = NULL;
        PKIX_List *validateCheckedCritExtOIDsList = NULL;
        PKIX_TrustAnchor *anchor = NULL;
        PKIX_ValidateResult *valResult = NULL;
        PKIX_PL_PublicKey *finalPubKey = NULL;
        PKIX_PolicyNode *validPolicyTree = NULL;
        PKIX_Boolean supportForwarding = PKIX_FALSE;
        PKIX_Boolean revChecking = PKIX_FALSE;
        PKIX_UInt32 i, numCerts, numAnchors;
        PKIX_UInt32 numUserCheckers = 0;
        PKIX_UInt32 certCheckedIndex = 0;
        PKIX_UInt32 checkerIndex = 0;
        PKIX_UInt32 reasonCode = 0;
        void *nbioContext = NULL;

        PKIX_ENTER(VALIDATE, "PKIX_ValidateChain");
        PKIX_NULLCHECK_TWO(valParams, pResult);

        /* extract various parameters from valParams */
        PKIX_CHECK(pkix_ExtractParameters
                    (valParams,
                    &certs,
                    &numCerts,
                    &procParams,
                    &anchors,
                    &numAnchors,
                    plContext),
                    PKIX_EXTRACTPARAMETERSFAILED);

        /*
         * setup an extension OID list that user had defined for his checker
         * processing. User checker is not responsible for taking out OIDs
         * from unresolved critical extension list as the libpkix checker
         * is doing. Here we add those user checkers' OIDs to the removal
         * list to be taken out by CheckChain
         */

        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
                    (procParams, &userCheckers, plContext),
                    PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);

        if (userCheckers != NULL) {

                PKIX_CHECK(PKIX_List_Create
                    (&validateCheckedCritExtOIDsList,
                    plContext),
                    PKIX_LISTCREATEFAILED);

                PKIX_CHECK(PKIX_List_GetLength
                    (userCheckers, &numUserCheckers, plContext),
                    PKIX_LISTGETLENGTHFAILED);

                for (i = 0; i < numUserCheckers; i++) {

                    PKIX_CHECK(PKIX_List_GetItem
                        (userCheckers,
                        i,
                        (PKIX_PL_Object **) &userChecker,
                        plContext),
                        PKIX_LISTGETITEMFAILED);

                    PKIX_CHECK
                        (PKIX_CertChainChecker_IsForwardCheckingSupported
                        (userChecker, &supportForwarding, plContext),
                        PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);

                    if (supportForwarding == PKIX_FALSE) {

                        PKIX_CHECK
                            (PKIX_CertChainChecker_GetSupportedExtensions
                            (userChecker, &userCheckerExtOIDs, plContext),
                            PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);

                        if (userCheckerExtOIDs != NULL) {
                            PKIX_CHECK(pkix_List_AppendList
                                (validateCheckedCritExtOIDsList,
                                userCheckerExtOIDs,
                                plContext),
                                PKIX_LISTAPPENDLISTFAILED);
                        }
                    }

                    PKIX_DECREF(userCheckerExtOIDs);
                    PKIX_DECREF(userChecker);
                }
        }

        PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
                (procParams, &revChecker, plContext),
                PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);

        /* try to validate the chain with each anchor */
        for (i = 0; i < numAnchors; i++){

                /* get trust anchor */
                PKIX_CHECK(PKIX_List_GetItem
                        (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
                        PKIX_LISTGETITEMFAILED);

                /* initialize checkers using information from trust anchor */
                PKIX_CHECK(pkix_InitializeCheckers
                        (anchor, procParams, numCerts, &checkers, plContext),
                        PKIX_INITIALIZECHECKERSFAILED);

                /*
                 * Validate the chain using this trust anchor and these
                 * checkers. (WARNING: checkers that use non-blocking I/O
                 * are not currently supported.)
                 */

                certCheckedIndex = 0;
                checkerIndex = 0;
                revChecking = PKIX_FALSE;
                chainFailed = pkix_CheckChain
                        (certs,
                        numCerts,
                        anchor,
                        checkers,
                        revChecker,
                        validateCheckedCritExtOIDsList,
                        procParams,
                        &certCheckedIndex,
                        &checkerIndex,
                        &revChecking,
                        &reasonCode,
                        &nbioContext,
                        &finalPubKey,
                        &validPolicyTree,
                        pVerifyTree,
                        plContext);

                if (chainFailed) {

                        /* cert chain failed to validate */

                        PKIX_DECREF(chainFailed);
                        PKIX_DECREF(anchor);
                        PKIX_DECREF(checkers);
                        PKIX_DECREF(validPolicyTree);

                        /* if last anchor, we fail; else, we try next anchor */
                        if (i == (numAnchors - 1)) { /* last anchor */
                                PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
                        }

                } else {

                        /* XXX Remove this assertion after 2014-12-31.
                         * See bug 946984. */

                        PORT_Assert(reasonCode == 0);

                        /* cert chain successfully validated! */
                        PKIX_CHECK(pkix_ValidateResult_Create
                                (finalPubKey,
                                anchor,
                                validPolicyTree,
                                &valResult,
                                plContext),
                                PKIX_VALIDATERESULTCREATEFAILED);

                        *pResult = valResult;

                        /* no need to try any more anchors in the loop */
                        goto cleanup;
                }
        }

cleanup:

        PKIX_DECREF(finalPubKey);
        PKIX_DECREF(certs);
        PKIX_DECREF(anchors);
        PKIX_DECREF(anchor);
        PKIX_DECREF(checkers);
        PKIX_DECREF(revChecker);
        PKIX_DECREF(validPolicyTree);
        PKIX_DECREF(chainFailed);
        PKIX_DECREF(procParams);
        PKIX_DECREF(userCheckers);
        PKIX_DECREF(validateCheckedCritExtOIDsList);

        PKIX_RETURN(VALIDATE);
}

/*
 * FUNCTION: pkix_Validate_BuildUserOIDs
 * DESCRIPTION:
 *
 *  This function creates a List of the OIDs that are processed by the user
 *  checkers in the List pointed to by "userCheckers", storing the resulting
 *  List at "pUserCritOIDs". If the List of userCheckers is NULL, the output
 *  List will be NULL. Otherwise the output List will be non-NULL, but may be
 *  empty.
 *
 * PARAMETERS:
 *  "userCheckers"
 *      The address of the List of userCheckers.
 *  "pUserCritOIDs"
 *      The address at which the List is stored. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a VALIDATE Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */

static PKIX_Error *
pkix_Validate_BuildUserOIDs(
        PKIX_List *userCheckers,
        PKIX_List **pUserCritOIDs,
        void *plContext)
{
        PKIX_UInt32 numUserCheckers = 0;
        PKIX_UInt32 i = 0;
        PKIX_List *userCritOIDs = NULL;
        PKIX_List *userCheckerExtOIDs = NULL;
        PKIX_Boolean supportForwarding = PKIX_FALSE;
        PKIX_CertChainChecker *userChecker = NULL;

        PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs");
        PKIX_NULLCHECK_ONE(pUserCritOIDs);

        if (userCheckers != NULL) {
            PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext),
                PKIX_LISTCREATEFAILED);

            PKIX_CHECK(PKIX_List_GetLength
                (userCheckers, &numUserCheckers, plContext),
                PKIX_LISTGETLENGTHFAILED);

            for (i = 0; i < numUserCheckers; i++) {
                PKIX_CHECK(PKIX_List_GetItem
                    (userCheckers,
                    i,
                    (PKIX_PL_Object **) &userChecker,
                    plContext),
                    PKIX_LISTGETITEMFAILED);

                PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported
                    (userChecker, &supportForwarding, plContext),
                    PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);

                if (supportForwarding == PKIX_FALSE) {

                    PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions
                        (userChecker, &userCheckerExtOIDs, plContext),
                        PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);

                    if (userCheckerExtOIDs != NULL) {
                        PKIX_CHECK(pkix_List_AppendList
                            (userCritOIDs, userCheckerExtOIDs, plContext),
                            PKIX_LISTAPPENDLISTFAILED);
                    }
                }

                PKIX_DECREF(userCheckerExtOIDs);
                PKIX_DECREF(userChecker);
            }
        }

        *pUserCritOIDs = userCritOIDs;

cleanup:

        if (PKIX_ERROR_RECEIVED){
                PKIX_DECREF(userCritOIDs);
        }

        PKIX_DECREF(userCheckerExtOIDs);
        PKIX_DECREF(userChecker);

        PKIX_RETURN(VALIDATE);
}

/*
 * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h)
 */
PKIX_Error *
PKIX_ValidateChain_NB(
        PKIX_ValidateParams *valParams,
        PKIX_UInt32 *pCertIndex,
        PKIX_UInt32 *pAnchorIndex,
        PKIX_UInt32 *pCheckerIndex,
        PKIX_Boolean *pRevChecking,
        PKIX_List **pCheckers,
        void **pNBIOContext,
        PKIX_ValidateResult **pResult,
        PKIX_VerifyNode **pVerifyTree,
        void *plContext)
{
        PKIX_UInt32 numCerts = 0;
        PKIX_UInt32 numAnchors = 0;
        PKIX_UInt32 i = 0;
        PKIX_UInt32 certIndex = 0;
        PKIX_UInt32 anchorIndex = 0;
        PKIX_UInt32 checkerIndex = 0;
        PKIX_UInt32 reasonCode = 0;
        PKIX_Boolean revChecking = PKIX_FALSE;
        PKIX_List *certs = NULL;
        PKIX_List *anchors = NULL;
        PKIX_List *checkers = NULL;
        PKIX_List *userCheckers = NULL;
        PKIX_List *validateCheckedCritExtOIDsList = NULL;
        PKIX_TrustAnchor *anchor = NULL;
        PKIX_ValidateResult *valResult = NULL;
        PKIX_PL_PublicKey *finalPubKey = NULL;
        PKIX_PolicyNode *validPolicyTree = NULL;
        PKIX_ProcessingParams *procParams = NULL;
        PKIX_RevocationChecker *revChecker = NULL;
        PKIX_Error *chainFailed = NULL;
        void *nbioContext = NULL;

        PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB");
        PKIX_NULLCHECK_FOUR
                (valParams, pCertIndex, pAnchorIndex, pCheckerIndex);
        PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult);

        nbioContext = *pNBIOContext;
        *pNBIOContext = NULL;

        /* extract various parameters from valParams */
        PKIX_CHECK(pkix_ExtractParameters
                    (valParams,
                    &certs,
                    &numCerts,
                    &procParams,
                    &anchors,
                    &numAnchors,
                    plContext),
                    PKIX_EXTRACTPARAMETERSFAILED);

        /*
         * Create a List of the OIDs that will be processed by the user
         * checkers. User checkers are not responsible for removing OIDs from
         * the List of unresolved critical extensions, as libpkix checkers are.
         * So we add those user checkers' OIDs to the removal list to be taken
         * out by CheckChain.
         */
        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
                (procParams, &userCheckers, plContext),
                PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);

        PKIX_CHECK(pkix_Validate_BuildUserOIDs
                (userCheckers, &validateCheckedCritExtOIDsList, plContext),
                PKIX_VALIDATEBUILDUSEROIDSFAILED);

        PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
                (procParams, &revChecker, plContext),
                PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);

        /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
        if (nbioContext != NULL) {
                /* Resuming */
                certIndex = *pCertIndex;
                anchorIndex = *pAnchorIndex;
                checkerIndex = *pCheckerIndex;
                revChecking = *pRevChecking;
                checkers = *pCheckers;
                *pCheckers = NULL;
        }

        /* try to validate the chain with each anchor */
        for (i = anchorIndex; i < numAnchors; i++) {

                /* get trust anchor */
                PKIX_CHECK(PKIX_List_GetItem
                        (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
                        PKIX_LISTGETITEMFAILED);

                /* initialize checkers using information from trust anchor */
                if (nbioContext == NULL) {
                        PKIX_CHECK(pkix_InitializeCheckers
                                (anchor,
                                procParams,
                                numCerts,
                                &checkers,
                                plContext),
                                PKIX_INITIALIZECHECKERSFAILED);
                }

                /*
                 * Validate the chain using this trust anchor and these
                 * checkers.
                 */
                chainFailed = pkix_CheckChain
                        (certs,
                        numCerts,
                        anchor,
                        checkers,
                        revChecker,
                        validateCheckedCritExtOIDsList,
                        procParams,
                        &certIndex,
                        &checkerIndex,
                        &revChecking,
                        &reasonCode,
                        &nbioContext,
                        &finalPubKey,
                        &validPolicyTree,
                        pVerifyTree,
                        plContext);

                if (nbioContext != NULL) {
                        *pCertIndex = certIndex;
                        *pAnchorIndex = anchorIndex;
                        *pCheckerIndex = checkerIndex;
                        *pRevChecking = revChecking;
                        PKIX_INCREF(checkers);
                        *pCheckers = checkers;
                        *pNBIOContext = nbioContext;
                        goto cleanup;
                }

                if (chainFailed) {

                        /* cert chain failed to validate */

                        PKIX_DECREF(chainFailed);
                        PKIX_DECREF(anchor);
                        PKIX_DECREF(checkers);
                        PKIX_DECREF(validPolicyTree);

                        /* if last anchor, we fail; else, we try next anchor */
                        if (i == (numAnchors - 1)) { /* last anchor */
                                PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
                        }

                } else {

                        /* XXX Remove this assertion after 2014-12-31.
                         * See bug 946984. */
                        PORT_Assert(reasonCode == 0);

                        /* cert chain successfully validated! */
                        PKIX_CHECK(pkix_ValidateResult_Create
                                (finalPubKey,
                                anchor,
                                validPolicyTree,
                                &valResult,
                                plContext),
                                PKIX_VALIDATERESULTCREATEFAILED);

                        *pResult = valResult;

                        /* no need to try any more anchors in the loop */
                        goto cleanup;
                }
        }

cleanup:

        PKIX_DECREF(finalPubKey);
        PKIX_DECREF(certs);
        PKIX_DECREF(anchors);
        PKIX_DECREF(anchor);
        PKIX_DECREF(checkers);
        PKIX_DECREF(revChecker);
        PKIX_DECREF(validPolicyTree);
        PKIX_DECREF(chainFailed);
        PKIX_DECREF(procParams);
        PKIX_DECREF(userCheckers);
        PKIX_DECREF(validateCheckedCritExtOIDsList);

        PKIX_RETURN(VALIDATE);
}

Messung V0.5
C=97 H=84 G=90

¤ Dauer der Verarbeitung: 0.8 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge