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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/libpkix/pkix/top/pkix_validate.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1451 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +/*
     1.8 + * pkix_validate.c
     1.9 + *
    1.10 + * Top level validateChain function
    1.11 + *
    1.12 + */
    1.13 +
    1.14 +#include "pkix_validate.h"
    1.15 +#include "pkix_pl_common.h"
    1.16 +
    1.17 +/* --Private-Functions-------------------------------------------- */
    1.18 +
    1.19 +/*
    1.20 + * FUNCTION: pkix_AddToVerifyLog
    1.21 + * DESCRIPTION:
    1.22 + *
    1.23 + *  This function returns immediately if the address for the VerifyNode tree
    1.24 + *  pointed to by "pVerifyTree" is NULL. Otherwise it creates a new VerifyNode
    1.25 + *  from the Cert pointed to by "cert" and the Error pointed to by "error",
    1.26 + *  and inserts it at the depth in the VerifyNode tree determined by "depth". A
    1.27 + *  depth of zero means that this function creates the root node of a new tree.
    1.28 + *
    1.29 + *  Note: this function does not include the means of choosing among branches
    1.30 + *  of a tree. It is intended for non-branching trees, that is, where each
    1.31 + *  parent node has only a single child node.
    1.32 + *
    1.33 + * PARAMETERS:
    1.34 + *  "cert"
    1.35 + *      The address of the Cert to be included in the new VerifyNode. Must be
    1.36 + *      non-NULL.
    1.37 + *  "depth"
    1.38 + *      The UInt32 value of the depth.
    1.39 + *  "error"
    1.40 + *      The address of the Error to be included in the new VerifyNode.
    1.41 + *  "pVerifyTree"
    1.42 + *      The address of the VerifyNode tree into which the created VerifyNode
    1.43 + *      is to be inserted. The node is not created if VerifyTree is NULL.
    1.44 + *  "plContext"
    1.45 + *      Platform-specific context pointer.
    1.46 + * THREAD SAFETY:
    1.47 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    1.48 + * RETURNS:
    1.49 + *  Returns NULL if the function succeeds.
    1.50 + *  Returns a Validate Error if the function fails in a non-fatal way.
    1.51 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
    1.52 + */
    1.53 +static PKIX_Error *
    1.54 +pkix_AddToVerifyLog(
    1.55 +        PKIX_PL_Cert *cert,
    1.56 +        PKIX_UInt32 depth,
    1.57 +        PKIX_Error *error,
    1.58 +        PKIX_VerifyNode **pVerifyTree,
    1.59 +        void *plContext)
    1.60 +{
    1.61 +
    1.62 +        PKIX_VerifyNode *verifyNode = NULL;
    1.63 +
    1.64 +        PKIX_ENTER(VALIDATE, "pkix_AddToVerifyLog");
    1.65 +        PKIX_NULLCHECK_ONE(cert);
    1.66 +
    1.67 +        if (pVerifyTree) { /* nothing to do if no address given for log */
    1.68 +
    1.69 +                PKIX_CHECK(pkix_VerifyNode_Create
    1.70 +                        (cert, depth, error, &verifyNode, plContext),
    1.71 +                        PKIX_VERIFYNODECREATEFAILED);
    1.72 +
    1.73 +                if (depth == 0) {
    1.74 +                        /* We just created the root node */
    1.75 +                        *pVerifyTree = verifyNode;
    1.76 +                } else {
    1.77 +                        PKIX_CHECK(pkix_VerifyNode_AddToChain
    1.78 +                                (*pVerifyTree, verifyNode, plContext),
    1.79 +                                PKIX_VERIFYNODEADDTOCHAINFAILED);
    1.80 +                }
    1.81 +        }
    1.82 +
    1.83 +cleanup:
    1.84 +
    1.85 +        PKIX_RETURN(VALIDATE);
    1.86 +
    1.87 +}
    1.88 +
    1.89 +/*
    1.90 + * FUNCTION: pkix_CheckCert
    1.91 + * DESCRIPTION:
    1.92 + *
    1.93 + *  Checks whether the Cert pointed to by "cert" successfully validates
    1.94 + *  using the List of CertChainCheckers pointed to by "checkers". If the
    1.95 + *  certificate does not validate, an Error pointer is returned.
    1.96 + *
    1.97 + *  This function should be called initially with the UInt32 pointed to by
    1.98 + *  "pCheckerIndex" containing zero, and the pointer at "pNBIOContext"
    1.99 + *  containing NULL. If a checker does non-blocking I/O, this function will
   1.100 + *  return with the index of that checker stored at "pCheckerIndex" and a
   1.101 + *  platform-dependent non-blocking I/O context stored at "pNBIOContext".
   1.102 + *  A subsequent call to this function with those values intact will allow the
   1.103 + *  checking to resume where it left off. This should be repeated until the
   1.104 + *  function returns with NULL stored at "pNBIOContext".
   1.105 + *
   1.106 + * PARAMETERS:
   1.107 + *  "cert"
   1.108 + *      Address of Cert to validate. Must be non-NULL.
   1.109 + *  "checkers"
   1.110 + *      List of CertChainCheckers which must each validate the certificate.
   1.111 + *      Must be non-NULL.
   1.112 + *  "checkedExtOIDs"
   1.113 + *      List of PKIX_PL_OID that has been processed. If called from building
   1.114 + *      chain, it is the list of critical extension OIDs that has been
   1.115 + *      processed prior to validation. May be NULL.
   1.116 + *  "pCheckerIndex"
   1.117 + *      Address at which is stored the the index, within the List "checkers",
   1.118 + *      of a checker whose processing was interrupted by non-blocking I/O.
   1.119 + *      Must be non-NULL.
   1.120 + *  "pNBIOContext"
   1.121 + *      Address at which is stored platform-specific non-blocking I/O context.
   1.122 + *      Must be non-NULL.
   1.123 + *  "plContext"
   1.124 + *      Platform-specific context pointer.
   1.125 + * THREAD SAFETY:
   1.126 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.127 + * RETURNS:
   1.128 + *  Returns NULL if the function succeeds.
   1.129 + *  Returns a Validate Error if the function fails in a non-fatal way.
   1.130 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.131 + */
   1.132 +static PKIX_Error *
   1.133 +pkix_CheckCert(
   1.134 +        PKIX_PL_Cert *cert,
   1.135 +        PKIX_List *checkers,
   1.136 +        PKIX_List *checkedExtOIDsList,
   1.137 +        PKIX_UInt32 *pCheckerIndex,
   1.138 +        void **pNBIOContext,
   1.139 +        void *plContext)
   1.140 +{
   1.141 +        PKIX_CertChainChecker_CheckCallback checkerCheck = NULL;
   1.142 +        PKIX_CertChainChecker *checker = NULL;
   1.143 +        PKIX_List *unresCritExtOIDs = NULL;
   1.144 +        PKIX_UInt32 numCheckers;
   1.145 +        PKIX_UInt32 numUnresCritExtOIDs = 0;
   1.146 +        PKIX_UInt32 checkerIndex = 0;
   1.147 +        void *nbioContext = NULL;
   1.148 +
   1.149 +        PKIX_ENTER(VALIDATE, "pkix_CheckCert");
   1.150 +        PKIX_NULLCHECK_FOUR(cert, checkers, pCheckerIndex, pNBIOContext);
   1.151 +
   1.152 +        nbioContext = *pNBIOContext;
   1.153 +        *pNBIOContext = NULL; /* prepare for case of error exit */
   1.154 +
   1.155 +        PKIX_CHECK(PKIX_PL_Cert_GetCriticalExtensionOIDs
   1.156 +                    (cert, &unresCritExtOIDs, plContext),
   1.157 +                    PKIX_CERTGETCRITICALEXTENSIONOIDSFAILED);
   1.158 +
   1.159 +        PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
   1.160 +                    PKIX_LISTGETLENGTHFAILED);
   1.161 +
   1.162 +        for (checkerIndex = *pCheckerIndex;
   1.163 +                checkerIndex < numCheckers;
   1.164 +                checkerIndex++) {
   1.165 +
   1.166 +                PKIX_CHECK(PKIX_List_GetItem
   1.167 +                        (checkers,
   1.168 +                        checkerIndex,
   1.169 +                        (PKIX_PL_Object **)&checker,
   1.170 +                        plContext),
   1.171 +                        PKIX_LISTGETITEMFAILED);
   1.172 +
   1.173 +                PKIX_CHECK(PKIX_CertChainChecker_GetCheckCallback
   1.174 +                        (checker, &checkerCheck, plContext),
   1.175 +                        PKIX_CERTCHAINCHECKERGETCHECKCALLBACKFAILED);
   1.176 +
   1.177 +                PKIX_CHECK(checkerCheck(checker, cert, unresCritExtOIDs,
   1.178 +                                        &nbioContext,  plContext),
   1.179 +                           PKIX_CERTCHAINCHECKERCHECKFAILED);
   1.180 +
   1.181 +                if (nbioContext != NULL) {
   1.182 +                        *pCheckerIndex = checkerIndex;
   1.183 +                        *pNBIOContext = nbioContext;
   1.184 +                        goto cleanup;
   1.185 +                }
   1.186 +
   1.187 +                PKIX_DECREF(checker);
   1.188 +        }
   1.189 +
   1.190 +        if (unresCritExtOIDs){
   1.191 +
   1.192 +#ifdef PKIX_VALIDATEDEBUG
   1.193 +                {
   1.194 +                        PKIX_PL_String *oidString = NULL;
   1.195 +                        PKIX_UInt32 length;
   1.196 +                        char *oidAscii = NULL;
   1.197 +                        PKIX_TOSTRING(unresCritExtOIDs, &oidString, plContext,
   1.198 +                                PKIX_LISTTOSTRINGFAILED);
   1.199 +                        PKIX_CHECK(PKIX_PL_String_GetEncoded
   1.200 +                                (oidString,
   1.201 +                                PKIX_ESCASCII,
   1.202 +                                (void **) &oidAscii,
   1.203 +                                &length,
   1.204 +                                plContext),
   1.205 +                                PKIX_STRINGGETENCODEDFAILED);
   1.206 +                        PKIX_VALIDATE_DEBUG_ARG
   1.207 +                                ("unrecognized critical extension OIDs:"
   1.208 +                                " %s\n", oidAscii);
   1.209 +                        PKIX_DECREF(oidString);
   1.210 +                        PKIX_PL_Free(oidAscii, plContext);
   1.211 +                }
   1.212 +#endif
   1.213 +
   1.214 +                if (checkedExtOIDsList != NULL) {
   1.215 +                 /* Take out OID's that had been processed, if any */
   1.216 +                        PKIX_CHECK(pkix_List_RemoveItems
   1.217 +                                (unresCritExtOIDs,
   1.218 +                                checkedExtOIDsList,
   1.219 +                                plContext),
   1.220 +                                PKIX_LISTREMOVEITEMSFAILED);
   1.221 +                }
   1.222 +
   1.223 +                PKIX_CHECK(PKIX_List_GetLength
   1.224 +                        (unresCritExtOIDs, &numUnresCritExtOIDs, plContext),
   1.225 +                        PKIX_LISTGETLENGTHFAILED);
   1.226 +
   1.227 +                if (numUnresCritExtOIDs != 0){
   1.228 +                        PKIX_ERROR(PKIX_UNRECOGNIZEDCRITICALEXTENSION);
   1.229 +                }
   1.230 +
   1.231 +        }
   1.232 +
   1.233 +cleanup:
   1.234 +
   1.235 +        PKIX_DECREF(checker);
   1.236 +        PKIX_DECREF(unresCritExtOIDs);
   1.237 +
   1.238 +        PKIX_RETURN(VALIDATE);
   1.239 +
   1.240 +}
   1.241 +
   1.242 +/*
   1.243 + * FUNCTION: pkix_InitializeCheckers
   1.244 + * DESCRIPTION:
   1.245 + *
   1.246 + *  Creates several checkers and initializes them with values derived from the
   1.247 + *  TrustAnchor pointed to by "anchor", the ProcessingParams pointed to by
   1.248 + *  "procParams", and the number of Certs in the Chain, represented by
   1.249 + *  "numCerts". The List of checkers is stored at "pCheckers".
   1.250 + *
   1.251 + * PARAMETERS:
   1.252 + *  "anchor"
   1.253 + *      Address of TrustAnchor used to initialize the SignatureChecker and
   1.254 + *      NameChainingChecker. Must be non-NULL.
   1.255 + *  "procParams"
   1.256 + *      Address of ProcessingParams used to initialize the ExpirationChecker
   1.257 + *      and TargetCertChecker. Must be non-NULL.
   1.258 + *  "numCerts"
   1.259 + *      Number of certificates in the CertChain.
   1.260 + *  "pCheckers"
   1.261 + *      Address where object pointer will be stored. Must be non-NULL.
   1.262 + *  "plContext"
   1.263 + *      Platform-specific context pointer.
   1.264 + * THREAD SAFETY:
   1.265 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.266 + * RETURNS:
   1.267 + *  Returns NULL if the function succeeds.
   1.268 + *  Returns a Validate Error if the function fails in a non-fatal way.
   1.269 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.270 + */
   1.271 +static PKIX_Error *
   1.272 +pkix_InitializeCheckers(
   1.273 +        PKIX_TrustAnchor *anchor,
   1.274 +        PKIX_ProcessingParams *procParams,
   1.275 +        PKIX_UInt32 numCerts,
   1.276 +        PKIX_List **pCheckers,
   1.277 +        void *plContext)
   1.278 +{
   1.279 +        PKIX_CertChainChecker *targetCertChecker = NULL;
   1.280 +        PKIX_CertChainChecker *expirationChecker = NULL;
   1.281 +        PKIX_CertChainChecker *nameChainingChecker = NULL;
   1.282 +        PKIX_CertChainChecker *nameConstraintsChecker = NULL;
   1.283 +        PKIX_CertChainChecker *basicConstraintsChecker = NULL;
   1.284 +        PKIX_CertChainChecker *policyChecker = NULL;
   1.285 +        PKIX_CertChainChecker *sigChecker = NULL;
   1.286 +        PKIX_CertChainChecker *defaultCrlChecker = NULL;
   1.287 +        PKIX_CertChainChecker *userChecker = NULL;
   1.288 +        PKIX_PL_X500Name *trustedCAName = NULL;
   1.289 +        PKIX_PL_PublicKey *trustedPubKey = NULL;
   1.290 +        PKIX_List *checkers = NULL;
   1.291 +        PKIX_PL_Date *testDate = NULL;
   1.292 +        PKIX_CertSelector *certSelector = NULL;
   1.293 +        PKIX_PL_Cert *trustedCert = NULL;
   1.294 +        PKIX_PL_CertNameConstraints *trustedNC = NULL;
   1.295 +        PKIX_List *initialPolicies = NULL;
   1.296 +        PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
   1.297 +        PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
   1.298 +        PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
   1.299 +        PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
   1.300 +        PKIX_List *userCheckersList = NULL;
   1.301 +        PKIX_List *certStores = NULL;
   1.302 +        PKIX_UInt32 numCertCheckers = 0;
   1.303 +        PKIX_UInt32 i;
   1.304 +
   1.305 +        PKIX_ENTER(VALIDATE, "pkix_InitializeCheckers");
   1.306 +        PKIX_NULLCHECK_THREE(anchor, procParams, pCheckers);
   1.307 +        PKIX_CHECK(PKIX_List_Create(&checkers, plContext),
   1.308 +                    PKIX_LISTCREATEFAILED);
   1.309 +
   1.310 +        /*
   1.311 +         * The TrustAnchor may have been created using CreateWithCert
   1.312 +         * (in which case GetCAPublicKey and GetCAName will return NULL)
   1.313 +         * or may have been created using CreateWithNameKeyPair (in which
   1.314 +         * case GetTrustedCert will return NULL. So we call GetTrustedCert
   1.315 +         * and populate trustedPubKey and trustedCAName accordingly.
   1.316 +         */
   1.317 +
   1.318 +        PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
   1.319 +                (anchor, &trustedCert, plContext),
   1.320 +                    PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
   1.321 +
   1.322 +        if (trustedCert){
   1.323 +                PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
   1.324 +                            (trustedCert, &trustedPubKey, plContext),
   1.325 +                            PKIX_CERTGETSUBJECTPUBLICKEYFAILED);
   1.326 +
   1.327 +                PKIX_CHECK(PKIX_PL_Cert_GetSubject
   1.328 +                            (trustedCert, &trustedCAName, plContext),
   1.329 +                            PKIX_CERTGETSUBJECTFAILED);
   1.330 +        } else {
   1.331 +                PKIX_CHECK(PKIX_TrustAnchor_GetCAPublicKey
   1.332 +                            (anchor, &trustedPubKey, plContext),
   1.333 +                            PKIX_TRUSTANCHORGETCAPUBLICKEYFAILED);
   1.334 +
   1.335 +                PKIX_CHECK(PKIX_TrustAnchor_GetCAName
   1.336 +                            (anchor, &trustedCAName, plContext),
   1.337 +                            PKIX_TRUSTANCHORGETCANAMEFAILED);
   1.338 +        }
   1.339 +
   1.340 +        PKIX_NULLCHECK_TWO(trustedPubKey, trustedCAName);
   1.341 +
   1.342 +        PKIX_CHECK(PKIX_TrustAnchor_GetNameConstraints
   1.343 +                (anchor, &trustedNC, plContext),
   1.344 +                PKIX_TRUSTANCHORGETNAMECONSTRAINTSFAILED);
   1.345 +
   1.346 +        PKIX_CHECK(PKIX_ProcessingParams_GetTargetCertConstraints
   1.347 +                (procParams, &certSelector, plContext),
   1.348 +                PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
   1.349 +
   1.350 +        PKIX_CHECK(PKIX_ProcessingParams_GetDate
   1.351 +                (procParams, &testDate, plContext),
   1.352 +                PKIX_PROCESSINGPARAMSGETDATEFAILED);
   1.353 +
   1.354 +        PKIX_CHECK(PKIX_ProcessingParams_GetInitialPolicies
   1.355 +                (procParams, &initialPolicies, plContext),
   1.356 +                PKIX_PROCESSINGPARAMSGETINITIALPOLICIESFAILED);
   1.357 +
   1.358 +        PKIX_CHECK(PKIX_ProcessingParams_GetPolicyQualifiersRejected
   1.359 +                (procParams, &policyQualifiersRejected, plContext),
   1.360 +                PKIX_PROCESSINGPARAMSGETPOLICYQUALIFIERSREJECTEDFAILED);
   1.361 +
   1.362 +        PKIX_CHECK(PKIX_ProcessingParams_IsPolicyMappingInhibited
   1.363 +                (procParams, &initialPolicyMappingInhibit, plContext),
   1.364 +                PKIX_PROCESSINGPARAMSISPOLICYMAPPINGINHIBITEDFAILED);
   1.365 +
   1.366 +        PKIX_CHECK(PKIX_ProcessingParams_IsAnyPolicyInhibited
   1.367 +                (procParams, &initialAnyPolicyInhibit, plContext),
   1.368 +                PKIX_PROCESSINGPARAMSISANYPOLICYINHIBITEDFAILED);
   1.369 +
   1.370 +        PKIX_CHECK(PKIX_ProcessingParams_IsExplicitPolicyRequired
   1.371 +                (procParams, &initialExplicitPolicy, plContext),
   1.372 +                PKIX_PROCESSINGPARAMSISEXPLICITPOLICYREQUIREDFAILED);
   1.373 +
   1.374 +        PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
   1.375 +                (procParams, &certStores, plContext),
   1.376 +                PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
   1.377 +
   1.378 +        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
   1.379 +                (procParams, &userCheckersList, plContext),
   1.380 +                PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
   1.381 +
   1.382 +        /* now, initialize all the checkers */
   1.383 +        PKIX_CHECK(pkix_TargetCertChecker_Initialize
   1.384 +                (certSelector, numCerts, &targetCertChecker, plContext),
   1.385 +                PKIX_TARGETCERTCHECKERINITIALIZEFAILED);
   1.386 +
   1.387 +        PKIX_CHECK(pkix_ExpirationChecker_Initialize
   1.388 +                (testDate, &expirationChecker, plContext),
   1.389 +                PKIX_EXPIRATIONCHECKERINITIALIZEFAILED);
   1.390 +
   1.391 +        PKIX_CHECK(pkix_NameChainingChecker_Initialize
   1.392 +                (trustedCAName, &nameChainingChecker, plContext),
   1.393 +                PKIX_NAMECHAININGCHECKERINITIALIZEFAILED);
   1.394 +
   1.395 +        PKIX_CHECK(pkix_NameConstraintsChecker_Initialize
   1.396 +                (trustedNC, numCerts, &nameConstraintsChecker, plContext),
   1.397 +                PKIX_NAMECONSTRAINTSCHECKERINITIALIZEFAILED);
   1.398 +
   1.399 +        PKIX_CHECK(pkix_BasicConstraintsChecker_Initialize
   1.400 +                (numCerts, &basicConstraintsChecker, plContext),
   1.401 +                PKIX_BASICCONSTRAINTSCHECKERINITIALIZEFAILED);
   1.402 +
   1.403 +        PKIX_CHECK(pkix_PolicyChecker_Initialize
   1.404 +                (initialPolicies,
   1.405 +                policyQualifiersRejected,
   1.406 +                initialPolicyMappingInhibit,
   1.407 +                initialExplicitPolicy,
   1.408 +                initialAnyPolicyInhibit,
   1.409 +                numCerts,
   1.410 +                &policyChecker,
   1.411 +                plContext),
   1.412 +                PKIX_POLICYCHECKERINITIALIZEFAILED);
   1.413 +
   1.414 +        PKIX_CHECK(pkix_SignatureChecker_Initialize
   1.415 +                    (trustedPubKey, numCerts, &sigChecker, plContext),
   1.416 +                    PKIX_SIGNATURECHECKERINITIALIZEFAILED);
   1.417 +
   1.418 +        if (userCheckersList != NULL) {
   1.419 +
   1.420 +                PKIX_CHECK(PKIX_List_GetLength
   1.421 +                    (userCheckersList, &numCertCheckers, plContext),
   1.422 +                    PKIX_LISTGETLENGTHFAILED);
   1.423 +
   1.424 +                for (i = 0; i < numCertCheckers; i++) {
   1.425 +
   1.426 +                        PKIX_CHECK(PKIX_List_GetItem
   1.427 +                            (userCheckersList,
   1.428 +                            i,
   1.429 +                            (PKIX_PL_Object **) &userChecker,
   1.430 +                            plContext),
   1.431 +                            PKIX_LISTGETITEMFAILED);
   1.432 +
   1.433 +                        PKIX_CHECK(PKIX_List_AppendItem
   1.434 +                            (checkers,
   1.435 +                            (PKIX_PL_Object *)userChecker,
   1.436 +                            plContext),
   1.437 +                            PKIX_LISTAPPENDITEMFAILED);
   1.438 +
   1.439 +                        PKIX_DECREF(userChecker);
   1.440 +                }
   1.441 +        }
   1.442 +
   1.443 +        PKIX_CHECK(PKIX_List_AppendItem
   1.444 +            (checkers, (PKIX_PL_Object *)targetCertChecker, plContext),
   1.445 +            PKIX_LISTAPPENDITEMFAILED);
   1.446 +
   1.447 +        PKIX_CHECK(PKIX_List_AppendItem
   1.448 +            (checkers, (PKIX_PL_Object *)expirationChecker, plContext),
   1.449 +            PKIX_LISTAPPENDITEMFAILED);
   1.450 +
   1.451 +        PKIX_CHECK(PKIX_List_AppendItem
   1.452 +            (checkers, (PKIX_PL_Object *)nameChainingChecker, plContext),
   1.453 +            PKIX_LISTAPPENDITEMFAILED);
   1.454 +
   1.455 +        PKIX_CHECK(PKIX_List_AppendItem
   1.456 +            (checkers, (PKIX_PL_Object *)nameConstraintsChecker, plContext),
   1.457 +            PKIX_LISTAPPENDITEMFAILED);
   1.458 +
   1.459 +        PKIX_CHECK(PKIX_List_AppendItem
   1.460 +            (checkers, (PKIX_PL_Object *)basicConstraintsChecker, plContext),
   1.461 +            PKIX_LISTAPPENDITEMFAILED);
   1.462 +
   1.463 +        PKIX_CHECK(PKIX_List_AppendItem
   1.464 +            (checkers, (PKIX_PL_Object *)policyChecker, plContext),
   1.465 +            PKIX_LISTAPPENDITEMFAILED);
   1.466 +
   1.467 +        PKIX_CHECK(PKIX_List_AppendItem
   1.468 +            (checkers, (PKIX_PL_Object *)sigChecker, plContext),
   1.469 +            PKIX_LISTAPPENDITEMFAILED);
   1.470 +
   1.471 +        *pCheckers = checkers;
   1.472 +
   1.473 +cleanup:
   1.474 +
   1.475 +        if (PKIX_ERROR_RECEIVED){
   1.476 +                PKIX_DECREF(checkers);
   1.477 +        }
   1.478 +
   1.479 +        PKIX_DECREF(certSelector);
   1.480 +        PKIX_DECREF(testDate);
   1.481 +        PKIX_DECREF(initialPolicies);
   1.482 +        PKIX_DECREF(targetCertChecker);
   1.483 +        PKIX_DECREF(expirationChecker);
   1.484 +        PKIX_DECREF(nameChainingChecker);
   1.485 +        PKIX_DECREF(nameConstraintsChecker);
   1.486 +        PKIX_DECREF(basicConstraintsChecker);
   1.487 +        PKIX_DECREF(policyChecker);
   1.488 +        PKIX_DECREF(sigChecker);
   1.489 +        PKIX_DECREF(trustedCAName);
   1.490 +        PKIX_DECREF(trustedPubKey);
   1.491 +        PKIX_DECREF(trustedNC);
   1.492 +        PKIX_DECREF(trustedCert);
   1.493 +        PKIX_DECREF(defaultCrlChecker);
   1.494 +        PKIX_DECREF(userCheckersList);
   1.495 +        PKIX_DECREF(certStores);
   1.496 +        PKIX_DECREF(userChecker);
   1.497 +
   1.498 +        PKIX_RETURN(VALIDATE);
   1.499 +}
   1.500 +
   1.501 +/*
   1.502 + * FUNCTION: pkix_RetrieveOutputs
   1.503 + * DESCRIPTION:
   1.504 + *
   1.505 + *  This function queries the respective states of the List of checkers in
   1.506 + *  "checkers" to to obtain the final public key from the SignatureChecker
   1.507 + *  and the policy tree from the PolicyChecker, storing those values at
   1.508 + *  "pFinalSubjPubKey" and "pPolicyTree", respectively.
   1.509 + *
   1.510 + * PARAMETERS:
   1.511 + *  "checkers"
   1.512 + *      Address of List of checkers to be queried. Must be non-NULL.
   1.513 + *  "pFinalSubjPubKey"
   1.514 + *      Address where final public key will be stored. Must be non-NULL.
   1.515 + *  "pPolicyTree"
   1.516 + *      Address where policy tree will be stored. Must be non-NULL.
   1.517 + *  "plContext"
   1.518 + *      Platform-specific context pointer.
   1.519 + * THREAD SAFETY:
   1.520 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.521 + * RETURNS:
   1.522 + *  Returns NULL if the function succeeds.
   1.523 + *  Returns a Validate Error if the function fails in a non-fatal way.
   1.524 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.525 + */
   1.526 +static PKIX_Error *
   1.527 +pkix_RetrieveOutputs(
   1.528 +        PKIX_List *checkers,
   1.529 +        PKIX_PL_PublicKey **pFinalSubjPubKey,
   1.530 +        PKIX_PolicyNode **pPolicyTree,
   1.531 +        void *plContext)
   1.532 +{
   1.533 +        PKIX_PL_PublicKey *finalSubjPubKey = NULL;
   1.534 +        PKIX_PolicyNode *validPolicyTree = NULL;
   1.535 +        PKIX_CertChainChecker *checker = NULL;
   1.536 +        PKIX_PL_Object *state = NULL;
   1.537 +        PKIX_UInt32 numCheckers = 0;
   1.538 +        PKIX_UInt32 type;
   1.539 +        PKIX_Int32 j;
   1.540 +
   1.541 +        PKIX_ENTER(VALIDATE, "pkix_RetrieveOutputs");
   1.542 +
   1.543 +        PKIX_NULLCHECK_TWO(checkers, pPolicyTree);
   1.544 +
   1.545 +        /*
   1.546 +         * To optimize the search, we guess that the sigChecker is
   1.547 +         * last in the tree and is preceded by the policyChecker. We
   1.548 +         * search toward the front of the chain. Remember that List
   1.549 +         * items are indexed 0..(numItems - 1).
   1.550 +         */
   1.551 +
   1.552 +        PKIX_CHECK(PKIX_List_GetLength(checkers, &numCheckers, plContext),
   1.553 +                PKIX_LISTGETLENGTHFAILED);
   1.554 +
   1.555 +        for (j = numCheckers - 1; j >= 0; j--){
   1.556 +                PKIX_CHECK(PKIX_List_GetItem
   1.557 +                        (checkers, j, (PKIX_PL_Object **)&checker, plContext),
   1.558 +                        PKIX_LISTGETITEMFAILED);
   1.559 +
   1.560 +                PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
   1.561 +                        (checker, &state, plContext),
   1.562 +                        PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
   1.563 +
   1.564 +                /* user defined checker may have no state */
   1.565 +                if (state != NULL) {
   1.566 +
   1.567 +                    PKIX_CHECK(PKIX_PL_Object_GetType(state, &type, plContext),
   1.568 +                            PKIX_OBJECTGETTYPEFAILED);
   1.569 +
   1.570 +                    if (type == PKIX_SIGNATURECHECKERSTATE_TYPE){
   1.571 +                        /* final pubKey will include any inherited DSA params */
   1.572 +                        finalSubjPubKey =
   1.573 +                            ((pkix_SignatureCheckerState *)state)->
   1.574 +                                prevPublicKey;
   1.575 +                        PKIX_INCREF(finalSubjPubKey);
   1.576 +                        *pFinalSubjPubKey = finalSubjPubKey;
   1.577 +                    }
   1.578 +
   1.579 +                    if (type == PKIX_CERTPOLICYCHECKERSTATE_TYPE) {
   1.580 +                        validPolicyTree =
   1.581 +                            ((PKIX_PolicyCheckerState *)state)->validPolicyTree;
   1.582 +                        break;
   1.583 +                    }
   1.584 +                }
   1.585 +
   1.586 +                PKIX_DECREF(checker);
   1.587 +                PKIX_DECREF(state);
   1.588 +        }
   1.589 +
   1.590 +        PKIX_INCREF(validPolicyTree);
   1.591 +        *pPolicyTree = validPolicyTree;
   1.592 +
   1.593 +cleanup:
   1.594 +
   1.595 +        PKIX_DECREF(checker);
   1.596 +        PKIX_DECREF(state);
   1.597 +
   1.598 +        PKIX_RETURN(VALIDATE);
   1.599 +
   1.600 +}
   1.601 +
   1.602 +/*
   1.603 + * FUNCTION: pkix_CheckChain
   1.604 + * DESCRIPTION:
   1.605 + *
   1.606 + *  Checks whether the List of Certs pointed to by "certs", containing
   1.607 + *  "numCerts" entries, successfully validates using each CertChainChecker in
   1.608 + *  the List pointed to by "checkers" and has not been revoked, according to any
   1.609 + *  of the Revocation Checkers in the List pointed to by "revChecker". Checkers
   1.610 + *  are expected to remove from "removeCheckedExtOIDs" and extensions that they
   1.611 + *  process. Indices to the certChain and the checkerChain are obtained and
   1.612 + *  returned in "pCertCheckedIndex" and "pCheckerIndex", respectively. These
   1.613 + *  should be set to zero prior to the initial call, but may be changed (and
   1.614 + *  must be supplied on subsequent calls) if processing is suspended for non-
   1.615 + *  blocking I/O. Each time a Cert passes from being validated by one of the
   1.616 + *  CertChainCheckers to being checked by a Revocation Checker, the Boolean
   1.617 + *  stored at "pRevChecking" is changed from FALSE to TRUE. If the Cert is
   1.618 + *  rejected by a Revocation Checker, its reason code is returned at
   1.619 + *  "pReasonCode. If the List of Certs successfully validates, the public key i
   1.620 + *  the final certificate is obtained and stored at "pFinalSubjPubKey" and the
   1.621 + *  validPolicyTree, which could be NULL, is stored at pPolicyTree. If the List
   1.622 + *  of Certs fails to validate, an Error pointer is returned.
   1.623 + *
   1.624 + *  If "pVerifyTree" is non-NULL, a chain of VerifyNodes is created which
   1.625 + *  tracks the results of the validation. That is, either each node in the
   1.626 + *  chain has a NULL Error component, or the last node contains an Error
   1.627 + *  which indicates why the validation failed.
   1.628 + *
   1.629 + *  The number of Certs in the List, represented by "numCerts", is used to
   1.630 + *  determine which Cert is the final Cert.
   1.631 + *
   1.632 + * PARAMETERS:
   1.633 + *  "certs"
   1.634 + *      Address of List of Certs to validate. Must be non-NULL.
   1.635 + *  "numCerts"
   1.636 + *      Number of certificates in the List of certificates.
   1.637 + *  "checkers"
   1.638 + *      List of CertChainCheckers which must each validate the List of
   1.639 + *      certificates. Must be non-NULL.
   1.640 + *  "revChecker"
   1.641 + *      List of RevocationCheckers which must each not reject the List of
   1.642 + *      certificates. May be empty, but must be non-NULL.
   1.643 + *  "removeCheckedExtOIDs"
   1.644 + *      List of PKIX_PL_OID that has been processed. If called from building
   1.645 + *      chain, it is the list of critical extension OIDs that has been
   1.646 + *      processed prior to validation. Extension OIDs that may be processed by
   1.647 + *      user defined checker processes are also in the list. May be NULL.
   1.648 + *  "procParams"
   1.649 + *      Address of ProcessingParams used to initialize various checkers. Must
   1.650 + *      be non-NULL.
   1.651 + *  "pCertCheckedIndex"
   1.652 + *      Address where Int32 index to the Cert chain is obtained and
   1.653 + *      returned. Must be non-NULL.
   1.654 + *  "pCheckerIndex"
   1.655 + *      Address where Int32 index to the CheckerChain is obtained and
   1.656 + *      returned. Must be non-NULL.
   1.657 + *  "pRevChecking"
   1.658 + *      Address where Boolean is obtained and returned, indicating, if FALSE,
   1.659 + *      that CertChainCheckers are being called; or, if TRUE, that RevChecker
   1.660 + *      are being called. Must be non-NULL.
   1.661 + *  "pReasonCode"
   1.662 + *      Address where UInt32 results of revocation checking are stored. Must be
   1.663 + *      non-NULL.
   1.664 + *  "pNBIOContext"
   1.665 + *      Address where platform-dependent context is stored if checking is
   1.666 + *      suspended for non-blocking I/O. Must be non-NULL.
   1.667 + *  "pFinalSubjPubKey"
   1.668 + *      Address where the final public key will be stored. Must be non-NULL.
   1.669 + *  "pPolicyTree"
   1.670 + *      Address where the final validPolicyTree is stored. Must be non-NULL.
   1.671 + *  "pVerifyTree"
   1.672 + *      Address where a VerifyTree is stored, if non-NULL.
   1.673 + *  "plContext"
   1.674 + *      Platform-specific context pointer.
   1.675 + * THREAD SAFETY:
   1.676 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.677 + * RETURNS:
   1.678 + *  Returns NULL if the function succeeds.
   1.679 + *  Returns a Validate Error if the function fails in a non-fatal way.
   1.680 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.681 + */
   1.682 +PKIX_Error *
   1.683 +pkix_CheckChain(
   1.684 +        PKIX_List *certs,
   1.685 +        PKIX_UInt32 numCerts,
   1.686 +        PKIX_TrustAnchor *anchor,
   1.687 +        PKIX_List *checkers,
   1.688 +        PKIX_RevocationChecker *revChecker,
   1.689 +        PKIX_List *removeCheckedExtOIDs,
   1.690 +        PKIX_ProcessingParams *procParams,
   1.691 +        PKIX_UInt32 *pCertCheckedIndex,
   1.692 +        PKIX_UInt32 *pCheckerIndex,
   1.693 +        PKIX_Boolean *pRevChecking,
   1.694 +        PKIX_UInt32 *pReasonCode,
   1.695 +        void **pNBIOContext,
   1.696 +        PKIX_PL_PublicKey **pFinalSubjPubKey,
   1.697 +        PKIX_PolicyNode **pPolicyTree,
   1.698 +        PKIX_VerifyNode **pVerifyTree,
   1.699 +        void *plContext)
   1.700 +{
   1.701 +        PKIX_UInt32 j = 0;
   1.702 +        PKIX_Boolean revChecking = PKIX_FALSE;
   1.703 +        PKIX_Error *checkCertError = NULL;
   1.704 +        void *nbioContext = NULL;
   1.705 +        PKIX_PL_Cert *cert = NULL;
   1.706 +        PKIX_PL_Cert *issuer = NULL;
   1.707 +        PKIX_PL_NssContext *nssContext = NULL;
   1.708 +        CERTCertList *certList = NULL;
   1.709 +        const CERTChainVerifyCallback *chainVerifyCallback = NULL;
   1.710 +        CERTCertificate *nssCert = NULL;
   1.711 +
   1.712 +        PKIX_ENTER(VALIDATE, "pkix_CheckChain");
   1.713 +        PKIX_NULLCHECK_FOUR(certs, checkers, revChecker, pCertCheckedIndex);
   1.714 +        PKIX_NULLCHECK_FOUR(pCheckerIndex, pRevChecking, pReasonCode, anchor);
   1.715 +        PKIX_NULLCHECK_THREE(pNBIOContext, pFinalSubjPubKey, pPolicyTree);
   1.716 +
   1.717 +        nbioContext = *pNBIOContext;
   1.718 +        *pNBIOContext = NULL;
   1.719 +        revChecking = *pRevChecking;
   1.720 +        nssContext = (PKIX_PL_NssContext *)plContext;
   1.721 +        chainVerifyCallback = &nssContext->chainVerifyCallback;
   1.722 +
   1.723 +        if (chainVerifyCallback->isChainValid != NULL) {
   1.724 +                PRBool chainOK = PR_FALSE; /*assume failure*/
   1.725 +                SECStatus rv;
   1.726 +
   1.727 +                certList = CERT_NewCertList();
   1.728 +                if (certList == NULL) {
   1.729 +                        PKIX_ERROR_ALLOC_ERROR();
   1.730 +                }
   1.731 +
   1.732 +                /* Add the trust anchor to the list */
   1.733 +                PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
   1.734 +                        (anchor, &cert, plContext),
   1.735 +                        PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
   1.736 +
   1.737 +                PKIX_CHECK(
   1.738 +                        PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
   1.739 +                        PKIX_CERTGETCERTCERTIFICATEFAILED);
   1.740 +
   1.741 +                rv = CERT_AddCertToListHead(certList, nssCert);
   1.742 +                if (rv != SECSuccess) {
   1.743 +                        PKIX_ERROR_ALLOC_ERROR();
   1.744 +                }
   1.745 +                /* the certList takes ownership of nssCert on success */
   1.746 +                nssCert = NULL;
   1.747 +                PKIX_DECREF(cert);
   1.748 +
   1.749 +                /* Add the rest of the chain to the list */
   1.750 +                for (j = *pCertCheckedIndex; j < numCerts; j++) {
   1.751 +                        PKIX_CHECK(PKIX_List_GetItem(
   1.752 +                                certs, j, (PKIX_PL_Object **)&cert, plContext),
   1.753 +                                PKIX_LISTGETITEMFAILED);
   1.754 +
   1.755 +                        PKIX_CHECK(
   1.756 +                                PKIX_PL_Cert_GetCERTCertificate(cert, &nssCert, plContext),
   1.757 +                                PKIX_CERTGETCERTCERTIFICATEFAILED);
   1.758 +
   1.759 +                        rv = CERT_AddCertToListHead(certList, nssCert);
   1.760 +                        if (rv != SECSuccess) {
   1.761 +                                PKIX_ERROR_ALLOC_ERROR();
   1.762 +                        }
   1.763 +                        /* the certList takes ownership of nssCert on success */
   1.764 +                        nssCert = NULL;
   1.765 +                        PKIX_DECREF(cert);
   1.766 +                }
   1.767 +
   1.768 +                rv = (*chainVerifyCallback->isChainValid)
   1.769 +                     (chainVerifyCallback->isChainValidArg, certList, &chainOK);
   1.770 +                if (rv != SECSuccess) {
   1.771 +                       PKIX_ERROR_FATAL(PKIX_CHAINVERIFYCALLBACKFAILED);
   1.772 +                }
   1.773 +
   1.774 +                if (!chainOK) {
   1.775 +                        PKIX_ERROR(PKIX_CHAINVERIFYCALLBACKFAILED);
   1.776 +                }
   1.777 +
   1.778 +        }
   1.779 +
   1.780 +        PKIX_CHECK(PKIX_TrustAnchor_GetTrustedCert
   1.781 +                (anchor, &cert, plContext),
   1.782 +                   PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
   1.783 +
   1.784 +        for (j = *pCertCheckedIndex; j < numCerts; j++) {
   1.785 +
   1.786 +                PORT_Assert(cert);
   1.787 +                PKIX_DECREF(issuer);
   1.788 +                issuer = cert;
   1.789 +                cert = NULL;
   1.790 +
   1.791 +                PKIX_CHECK(PKIX_List_GetItem(
   1.792 +                               certs, j, (PKIX_PL_Object **)&cert, plContext),
   1.793 +                           PKIX_LISTGETITEMFAILED);
   1.794 +                
   1.795 +                /* check if cert pointer is valid */
   1.796 +                PORT_Assert(cert);
   1.797 +                if (cert == NULL) {
   1.798 +                    continue;
   1.799 +                }
   1.800 +
   1.801 +                if (revChecking == PKIX_FALSE) {
   1.802 +
   1.803 +                        PKIX_CHECK(pkix_CheckCert
   1.804 +                                (cert,
   1.805 +                                checkers,
   1.806 +                                removeCheckedExtOIDs,
   1.807 +                                pCheckerIndex,
   1.808 +                                &nbioContext,
   1.809 +                                plContext),
   1.810 +                                PKIX_CHECKCERTFAILED);
   1.811 +
   1.812 +                        if (nbioContext != NULL) {
   1.813 +                                *pCertCheckedIndex = j;
   1.814 +                                *pRevChecking = revChecking;
   1.815 +                                *pNBIOContext = nbioContext;
   1.816 +                                goto cleanup;
   1.817 +                        }
   1.818 +
   1.819 +                        revChecking = PKIX_TRUE;
   1.820 +                        *pCheckerIndex = 0;
   1.821 +                }
   1.822 +
   1.823 +                if (revChecking == PKIX_TRUE) {
   1.824 +                        PKIX_RevocationStatus revStatus;
   1.825 +                        pkixErrorResult =
   1.826 +                            PKIX_RevocationChecker_Check(
   1.827 +                                      cert, issuer, revChecker,
   1.828 +                                      procParams, PKIX_TRUE,
   1.829 +                                      (j == numCerts - 1) ? PKIX_TRUE : PKIX_FALSE,
   1.830 +                                      &revStatus, pReasonCode,
   1.831 +                                      &nbioContext, plContext);
   1.832 +                        if (nbioContext != NULL) {
   1.833 +                                *pCertCheckedIndex = j;
   1.834 +                                *pRevChecking = revChecking;
   1.835 +                                *pNBIOContext = nbioContext;
   1.836 +                                goto cleanup;
   1.837 +                        }
   1.838 +                        if (revStatus == PKIX_RevStatus_Revoked ||
   1.839 +                            pkixErrorResult) {
   1.840 +                            if (!pkixErrorResult) {
   1.841 +                                /* if pkixErrorResult is returned then
   1.842 +                                 * use it as it has a detailed revocation
   1.843 +                                 * error code. Otherwise create a new error */
   1.844 +                                PKIX_ERROR_CREATE(VALIDATE,
   1.845 +                                                  PKIX_CERTIFICATEREVOKED,
   1.846 +                                                  pkixErrorResult);
   1.847 +                            }
   1.848 +                            goto cleanup;
   1.849 +                        }
   1.850 +                        revChecking = PKIX_FALSE;
   1.851 +                        *pCheckerIndex = 0;
   1.852 +                }
   1.853 +
   1.854 +                PKIX_CHECK(pkix_AddToVerifyLog
   1.855 +                        (cert, j, NULL, pVerifyTree, plContext),
   1.856 +                        PKIX_ADDTOVERIFYLOGFAILED);
   1.857 +        }
   1.858 +
   1.859 +        PKIX_CHECK(pkix_RetrieveOutputs
   1.860 +                    (checkers, pFinalSubjPubKey, pPolicyTree, plContext),
   1.861 +                    PKIX_RETRIEVEOUTPUTSFAILED);
   1.862 +
   1.863 +        *pNBIOContext = NULL;
   1.864 +
   1.865 +cleanup:
   1.866 +        if (PKIX_ERROR_RECEIVED && cert) {
   1.867 +            checkCertError = pkixErrorResult;
   1.868 +            
   1.869 +            PKIX_CHECK_FATAL(
   1.870 +                pkix_AddToVerifyLog(cert, j, checkCertError, pVerifyTree,
   1.871 +                                    plContext),
   1.872 +                PKIX_ADDTOVERIFYLOGFAILED);
   1.873 +            pkixErrorResult = checkCertError;
   1.874 +            pkixErrorCode = pkixErrorResult->errCode;
   1.875 +            checkCertError = NULL;
   1.876 +        }
   1.877 +
   1.878 +fatal:
   1.879 +        if (nssCert) {
   1.880 +                CERT_DestroyCertificate(nssCert);
   1.881 +        }
   1.882 +
   1.883 +        if (certList) {
   1.884 +                CERT_DestroyCertList(certList);
   1.885 +        }
   1.886 +
   1.887 +        PKIX_DECREF(checkCertError);
   1.888 +        PKIX_DECREF(cert);
   1.889 +        PKIX_DECREF(issuer);
   1.890 +
   1.891 +        PKIX_RETURN(VALIDATE);
   1.892 +}
   1.893 +
   1.894 +/*
   1.895 + * FUNCTION: pkix_ExtractParameters
   1.896 + * DESCRIPTION:
   1.897 + *
   1.898 + *  Extracts several parameters from the ValidateParams object pointed to by
   1.899 + *  "valParams" and stores the CertChain at "pChain", the List of Certs at
   1.900 + *  "pCerts", the number of Certs in the chain at "pNumCerts", the
   1.901 + *  ProcessingParams object at "pProcParams", the List of TrustAnchors at
   1.902 + *  "pAnchors", and the number of TrustAnchors at "pNumAnchors".
   1.903 + *
   1.904 + * PARAMETERS:
   1.905 + *  "valParams"
   1.906 + *      Address of ValidateParams from which the parameters are extracted.
   1.907 + *      Must be non-NULL.
   1.908 + *  "pCerts"
   1.909 + *      Address where object pointer for List of Certs will be stored.
   1.910 + *      Must be non-NULL.
   1.911 + *  "pNumCerts"
   1.912 + *      Address where number of Certs will be stored. Must be non-NULL.
   1.913 + *  "pProcParams"
   1.914 + *      Address where object pointer for ProcessingParams will be stored.
   1.915 + *      Must be non-NULL.
   1.916 + *  "pAnchors"
   1.917 + *      Address where object pointer for List of Anchors will be stored.
   1.918 + *      Must be non-NULL.
   1.919 + *  "pNumAnchors"
   1.920 + *      Address where number of Anchors will be stored. Must be non-NULL.
   1.921 + *  "plContext"
   1.922 + *      Platform-specific context pointer.
   1.923 + * THREAD SAFETY:
   1.924 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.925 + * RETURNS:
   1.926 + *  Returns NULL if the function succeeds.
   1.927 + *  Returns a Validate Error if the function fails in a non-fatal way.
   1.928 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.929 + */
   1.930 +static PKIX_Error *
   1.931 +pkix_ExtractParameters(
   1.932 +        PKIX_ValidateParams *valParams,
   1.933 +        PKIX_List **pCerts,
   1.934 +        PKIX_UInt32 *pNumCerts,
   1.935 +        PKIX_ProcessingParams **pProcParams,
   1.936 +        PKIX_List **pAnchors,
   1.937 +        PKIX_UInt32 *pNumAnchors,
   1.938 +        void *plContext)
   1.939 +{
   1.940 +        PKIX_ENTER(VALIDATE, "pkix_ExtractParameters");
   1.941 +        PKIX_NULLCHECK_THREE(valParams, pCerts, pNumCerts);
   1.942 +        PKIX_NULLCHECK_THREE(pProcParams, pAnchors, pNumAnchors);
   1.943 +
   1.944 +        /* extract relevant parameters from chain */
   1.945 +        PKIX_CHECK(PKIX_ValidateParams_GetCertChain
   1.946 +                (valParams, pCerts, plContext),
   1.947 +                PKIX_VALIDATEPARAMSGETCERTCHAINFAILED);
   1.948 +
   1.949 +        PKIX_CHECK(PKIX_List_GetLength(*pCerts, pNumCerts, plContext),
   1.950 +                PKIX_LISTGETLENGTHFAILED);
   1.951 +
   1.952 +        /* extract relevant parameters from procParams */
   1.953 +        PKIX_CHECK(PKIX_ValidateParams_GetProcessingParams
   1.954 +                (valParams, pProcParams, plContext),
   1.955 +                PKIX_VALIDATEPARAMSGETPROCESSINGPARAMSFAILED);
   1.956 +
   1.957 +        PKIX_CHECK(PKIX_ProcessingParams_GetTrustAnchors
   1.958 +                (*pProcParams, pAnchors, plContext),
   1.959 +                PKIX_PROCESSINGPARAMSGETTRUSTANCHORSFAILED);
   1.960 +
   1.961 +        PKIX_CHECK(PKIX_List_GetLength(*pAnchors, pNumAnchors, plContext),
   1.962 +                PKIX_LISTGETLENGTHFAILED);
   1.963 +
   1.964 +cleanup:
   1.965 +
   1.966 +        PKIX_RETURN(VALIDATE);
   1.967 +}
   1.968 +
   1.969 +/* --Public-Functions--------------------------------------------- */
   1.970 +
   1.971 +/*
   1.972 + * FUNCTION: PKIX_ValidateChain (see comments in pkix.h)
   1.973 + */
   1.974 +PKIX_Error *
   1.975 +PKIX_ValidateChain(
   1.976 +        PKIX_ValidateParams *valParams,
   1.977 +        PKIX_ValidateResult **pResult,
   1.978 +        PKIX_VerifyNode **pVerifyTree,
   1.979 +        void *plContext)
   1.980 +{
   1.981 +        PKIX_Error *chainFailed = NULL;
   1.982 +
   1.983 +        PKIX_ProcessingParams *procParams = NULL;
   1.984 +        PKIX_CertChainChecker *userChecker = NULL;
   1.985 +        PKIX_RevocationChecker *revChecker = NULL;
   1.986 +        PKIX_List *certs = NULL;
   1.987 +        PKIX_List *checkers = NULL;
   1.988 +        PKIX_List *anchors = NULL;
   1.989 +        PKIX_List *userCheckers = NULL;
   1.990 +        PKIX_List *userCheckerExtOIDs = NULL;
   1.991 +        PKIX_List *validateCheckedCritExtOIDsList = NULL;
   1.992 +        PKIX_TrustAnchor *anchor = NULL;
   1.993 +        PKIX_ValidateResult *valResult = NULL;
   1.994 +        PKIX_PL_PublicKey *finalPubKey = NULL;
   1.995 +        PKIX_PolicyNode *validPolicyTree = NULL;
   1.996 +        PKIX_Boolean supportForwarding = PKIX_FALSE;
   1.997 +        PKIX_Boolean revChecking = PKIX_FALSE;
   1.998 +        PKIX_UInt32 i, numCerts, numAnchors;
   1.999 +        PKIX_UInt32 numUserCheckers = 0;
  1.1000 +        PKIX_UInt32 certCheckedIndex = 0;
  1.1001 +        PKIX_UInt32 checkerIndex = 0;
  1.1002 +        PKIX_UInt32 reasonCode = 0;
  1.1003 +        void *nbioContext = NULL;
  1.1004 +
  1.1005 +        PKIX_ENTER(VALIDATE, "PKIX_ValidateChain");
  1.1006 +        PKIX_NULLCHECK_TWO(valParams, pResult);
  1.1007 +
  1.1008 +        /* extract various parameters from valParams */
  1.1009 +        PKIX_CHECK(pkix_ExtractParameters
  1.1010 +                    (valParams,
  1.1011 +                    &certs,
  1.1012 +                    &numCerts,
  1.1013 +                    &procParams,
  1.1014 +                    &anchors,
  1.1015 +                    &numAnchors,
  1.1016 +                    plContext),
  1.1017 +                    PKIX_EXTRACTPARAMETERSFAILED);
  1.1018 +
  1.1019 +        /*
  1.1020 +         * setup an extension OID list that user had defined for his checker
  1.1021 +         * processing. User checker is not responsible for taking out OIDs
  1.1022 +         * from unresolved critical extension list as the libpkix checker
  1.1023 +         * is doing. Here we add those user checkers' OIDs to the removal
  1.1024 +         * list to be taken out by CheckChain
  1.1025 +         */
  1.1026 +        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
  1.1027 +                    (procParams, &userCheckers, plContext),
  1.1028 +                    PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
  1.1029 +
  1.1030 +        if (userCheckers != NULL) {
  1.1031 +
  1.1032 +                PKIX_CHECK(PKIX_List_Create
  1.1033 +                    (&validateCheckedCritExtOIDsList,
  1.1034 +                    plContext),
  1.1035 +                    PKIX_LISTCREATEFAILED);
  1.1036 +
  1.1037 +                PKIX_CHECK(PKIX_List_GetLength
  1.1038 +                    (userCheckers, &numUserCheckers, plContext),
  1.1039 +                    PKIX_LISTGETLENGTHFAILED);
  1.1040 +
  1.1041 +                for (i = 0; i < numUserCheckers; i++) {
  1.1042 +
  1.1043 +                    PKIX_CHECK(PKIX_List_GetItem
  1.1044 +                        (userCheckers,
  1.1045 +                        i,
  1.1046 +                        (PKIX_PL_Object **) &userChecker,
  1.1047 +                        plContext),
  1.1048 +                        PKIX_LISTGETITEMFAILED);
  1.1049 +
  1.1050 +                    PKIX_CHECK
  1.1051 +                        (PKIX_CertChainChecker_IsForwardCheckingSupported
  1.1052 +                        (userChecker, &supportForwarding, plContext),
  1.1053 +                        PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
  1.1054 +
  1.1055 +                    if (supportForwarding == PKIX_FALSE) {
  1.1056 +
  1.1057 +                        PKIX_CHECK
  1.1058 +                            (PKIX_CertChainChecker_GetSupportedExtensions
  1.1059 +                            (userChecker, &userCheckerExtOIDs, plContext),
  1.1060 +                            PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
  1.1061 +
  1.1062 +                        if (userCheckerExtOIDs != NULL) {
  1.1063 +                            PKIX_CHECK(pkix_List_AppendList
  1.1064 +                                (validateCheckedCritExtOIDsList,
  1.1065 +                                userCheckerExtOIDs,
  1.1066 +                                plContext),
  1.1067 +                                PKIX_LISTAPPENDLISTFAILED);
  1.1068 +                        }
  1.1069 +                    }
  1.1070 +
  1.1071 +                    PKIX_DECREF(userCheckerExtOIDs);
  1.1072 +                    PKIX_DECREF(userChecker);
  1.1073 +                }
  1.1074 +        }
  1.1075 +
  1.1076 +        PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
  1.1077 +                (procParams, &revChecker, plContext),
  1.1078 +                PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
  1.1079 +
  1.1080 +        /* try to validate the chain with each anchor */
  1.1081 +        for (i = 0; i < numAnchors; i++){
  1.1082 +
  1.1083 +                /* get trust anchor */
  1.1084 +                PKIX_CHECK(PKIX_List_GetItem
  1.1085 +                        (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
  1.1086 +                        PKIX_LISTGETITEMFAILED);
  1.1087 +
  1.1088 +                /* initialize checkers using information from trust anchor */
  1.1089 +                PKIX_CHECK(pkix_InitializeCheckers
  1.1090 +                        (anchor, procParams, numCerts, &checkers, plContext),
  1.1091 +                        PKIX_INITIALIZECHECKERSFAILED);
  1.1092 +
  1.1093 +                /*
  1.1094 +                 * Validate the chain using this trust anchor and these
  1.1095 +                 * checkers. (WARNING: checkers that use non-blocking I/O
  1.1096 +                 * are not currently supported.)
  1.1097 +                 */
  1.1098 +                certCheckedIndex = 0;
  1.1099 +                checkerIndex = 0;
  1.1100 +                revChecking = PKIX_FALSE;
  1.1101 +                chainFailed = pkix_CheckChain
  1.1102 +                        (certs,
  1.1103 +                        numCerts,
  1.1104 +                        anchor,
  1.1105 +                        checkers,
  1.1106 +                        revChecker,
  1.1107 +                        validateCheckedCritExtOIDsList,
  1.1108 +                        procParams,
  1.1109 +                        &certCheckedIndex,
  1.1110 +                        &checkerIndex,
  1.1111 +                        &revChecking,
  1.1112 +                        &reasonCode,
  1.1113 +                        &nbioContext,
  1.1114 +                        &finalPubKey,
  1.1115 +                        &validPolicyTree,
  1.1116 +                        pVerifyTree,
  1.1117 +                        plContext);
  1.1118 +
  1.1119 +                if (chainFailed) {
  1.1120 +
  1.1121 +                        /* cert chain failed to validate */
  1.1122 +
  1.1123 +                        PKIX_DECREF(chainFailed);
  1.1124 +                        PKIX_DECREF(anchor);
  1.1125 +                        PKIX_DECREF(checkers);
  1.1126 +                        PKIX_DECREF(validPolicyTree);
  1.1127 +
  1.1128 +                        /* if last anchor, we fail; else, we try next anchor */
  1.1129 +                        if (i == (numAnchors - 1)) { /* last anchor */
  1.1130 +                                PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
  1.1131 +                        }
  1.1132 +
  1.1133 +                } else {
  1.1134 +
  1.1135 +                        /* XXX Remove this assertion after 2014-12-31.
  1.1136 +                         * See bug 946984. */
  1.1137 +                        PORT_Assert(reasonCode == 0);
  1.1138 +
  1.1139 +                        /* cert chain successfully validated! */
  1.1140 +                        PKIX_CHECK(pkix_ValidateResult_Create
  1.1141 +                                (finalPubKey,
  1.1142 +                                anchor,
  1.1143 +                                validPolicyTree,
  1.1144 +                                &valResult,
  1.1145 +                                plContext),
  1.1146 +                                PKIX_VALIDATERESULTCREATEFAILED);
  1.1147 +
  1.1148 +                        *pResult = valResult;
  1.1149 +
  1.1150 +                        /* no need to try any more anchors in the loop */
  1.1151 +                        goto cleanup;
  1.1152 +                }
  1.1153 +        }
  1.1154 +
  1.1155 +cleanup:
  1.1156 +
  1.1157 +        PKIX_DECREF(finalPubKey);
  1.1158 +        PKIX_DECREF(certs);
  1.1159 +        PKIX_DECREF(anchors);
  1.1160 +        PKIX_DECREF(anchor);
  1.1161 +        PKIX_DECREF(checkers);
  1.1162 +        PKIX_DECREF(revChecker);
  1.1163 +        PKIX_DECREF(validPolicyTree);
  1.1164 +        PKIX_DECREF(chainFailed);
  1.1165 +        PKIX_DECREF(procParams);
  1.1166 +        PKIX_DECREF(userCheckers);
  1.1167 +        PKIX_DECREF(validateCheckedCritExtOIDsList);
  1.1168 +
  1.1169 +        PKIX_RETURN(VALIDATE);
  1.1170 +}
  1.1171 +
  1.1172 +/*
  1.1173 + * FUNCTION: pkix_Validate_BuildUserOIDs
  1.1174 + * DESCRIPTION:
  1.1175 + *
  1.1176 + *  This function creates a List of the OIDs that are processed by the user
  1.1177 + *  checkers in the List pointed to by "userCheckers", storing the resulting
  1.1178 + *  List at "pUserCritOIDs". If the List of userCheckers is NULL, the output
  1.1179 + *  List will be NULL. Otherwise the output List will be non-NULL, but may be
  1.1180 + *  empty.
  1.1181 + *
  1.1182 + * PARAMETERS:
  1.1183 + *  "userCheckers"
  1.1184 + *      The address of the List of userCheckers.
  1.1185 + *  "pUserCritOIDs"
  1.1186 + *      The address at which the List is stored. Must be non-NULL.
  1.1187 + *  "plContext"
  1.1188 + *      Platform-specific context pointer.
  1.1189 + * THREAD SAFETY:
  1.1190 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1191 + * RETURNS:
  1.1192 + *  Returns NULL if the function succeeds.
  1.1193 + *  Returns a VALIDATE Error if the function fails in a non-fatal way.
  1.1194 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
  1.1195 + */
  1.1196 +static PKIX_Error *
  1.1197 +pkix_Validate_BuildUserOIDs(
  1.1198 +        PKIX_List *userCheckers,
  1.1199 +        PKIX_List **pUserCritOIDs,
  1.1200 +        void *plContext)
  1.1201 +{
  1.1202 +        PKIX_UInt32 numUserCheckers = 0;
  1.1203 +        PKIX_UInt32 i = 0;
  1.1204 +        PKIX_List *userCritOIDs = NULL;
  1.1205 +        PKIX_List *userCheckerExtOIDs = NULL;
  1.1206 +        PKIX_Boolean supportForwarding = PKIX_FALSE;
  1.1207 +        PKIX_CertChainChecker *userChecker = NULL;
  1.1208 +
  1.1209 +        PKIX_ENTER(VALIDATE, "pkix_Validate_BuildUserOIDs");
  1.1210 +        PKIX_NULLCHECK_ONE(pUserCritOIDs);
  1.1211 +
  1.1212 +        if (userCheckers != NULL) {
  1.1213 +            PKIX_CHECK(PKIX_List_Create(&userCritOIDs, plContext),
  1.1214 +                PKIX_LISTCREATEFAILED);
  1.1215 +
  1.1216 +            PKIX_CHECK(PKIX_List_GetLength
  1.1217 +                (userCheckers, &numUserCheckers, plContext),
  1.1218 +                PKIX_LISTGETLENGTHFAILED);
  1.1219 +
  1.1220 +            for (i = 0; i < numUserCheckers; i++) {
  1.1221 +                PKIX_CHECK(PKIX_List_GetItem
  1.1222 +                    (userCheckers,
  1.1223 +                    i,
  1.1224 +                    (PKIX_PL_Object **) &userChecker,
  1.1225 +                    plContext),
  1.1226 +                    PKIX_LISTGETITEMFAILED);
  1.1227 +
  1.1228 +                PKIX_CHECK(PKIX_CertChainChecker_IsForwardCheckingSupported
  1.1229 +                    (userChecker, &supportForwarding, plContext),
  1.1230 +                    PKIX_CERTCHAINCHECKERISFORWARDCHECKINGSUPPORTEDFAILED);
  1.1231 +
  1.1232 +                if (supportForwarding == PKIX_FALSE) {
  1.1233 +
  1.1234 +                    PKIX_CHECK(PKIX_CertChainChecker_GetSupportedExtensions
  1.1235 +                        (userChecker, &userCheckerExtOIDs, plContext),
  1.1236 +                        PKIX_CERTCHAINCHECKERGETSUPPORTEDEXTENSIONSFAILED);
  1.1237 +
  1.1238 +                    if (userCheckerExtOIDs != NULL) {
  1.1239 +                        PKIX_CHECK(pkix_List_AppendList
  1.1240 +                            (userCritOIDs, userCheckerExtOIDs, plContext),
  1.1241 +                            PKIX_LISTAPPENDLISTFAILED);
  1.1242 +                    }
  1.1243 +                }
  1.1244 +
  1.1245 +                PKIX_DECREF(userCheckerExtOIDs);
  1.1246 +                PKIX_DECREF(userChecker);
  1.1247 +            }
  1.1248 +        }
  1.1249 +
  1.1250 +        *pUserCritOIDs = userCritOIDs;
  1.1251 +
  1.1252 +cleanup:
  1.1253 +
  1.1254 +        if (PKIX_ERROR_RECEIVED){
  1.1255 +                PKIX_DECREF(userCritOIDs);
  1.1256 +        }
  1.1257 +
  1.1258 +        PKIX_DECREF(userCheckerExtOIDs);
  1.1259 +        PKIX_DECREF(userChecker);
  1.1260 +
  1.1261 +        PKIX_RETURN(VALIDATE);
  1.1262 +}
  1.1263 +
  1.1264 +/*
  1.1265 + * FUNCTION: PKIX_ValidateChain_nb (see comments in pkix.h)
  1.1266 + */
  1.1267 +PKIX_Error *
  1.1268 +PKIX_ValidateChain_NB(
  1.1269 +        PKIX_ValidateParams *valParams,
  1.1270 +        PKIX_UInt32 *pCertIndex,
  1.1271 +        PKIX_UInt32 *pAnchorIndex,
  1.1272 +        PKIX_UInt32 *pCheckerIndex,
  1.1273 +        PKIX_Boolean *pRevChecking,
  1.1274 +        PKIX_List **pCheckers,
  1.1275 +        void **pNBIOContext,
  1.1276 +        PKIX_ValidateResult **pResult,
  1.1277 +        PKIX_VerifyNode **pVerifyTree,
  1.1278 +        void *plContext)
  1.1279 +{
  1.1280 +        PKIX_UInt32 numCerts = 0;
  1.1281 +        PKIX_UInt32 numAnchors = 0;
  1.1282 +        PKIX_UInt32 i = 0;
  1.1283 +        PKIX_UInt32 certIndex = 0;
  1.1284 +        PKIX_UInt32 anchorIndex = 0;
  1.1285 +        PKIX_UInt32 checkerIndex = 0;
  1.1286 +        PKIX_UInt32 reasonCode = 0;
  1.1287 +        PKIX_Boolean revChecking = PKIX_FALSE;
  1.1288 +        PKIX_List *certs = NULL;
  1.1289 +        PKIX_List *anchors = NULL;
  1.1290 +        PKIX_List *checkers = NULL;
  1.1291 +        PKIX_List *userCheckers = NULL;
  1.1292 +        PKIX_List *validateCheckedCritExtOIDsList = NULL;
  1.1293 +        PKIX_TrustAnchor *anchor = NULL;
  1.1294 +        PKIX_ValidateResult *valResult = NULL;
  1.1295 +        PKIX_PL_PublicKey *finalPubKey = NULL;
  1.1296 +        PKIX_PolicyNode *validPolicyTree = NULL;
  1.1297 +        PKIX_ProcessingParams *procParams = NULL;
  1.1298 +        PKIX_RevocationChecker *revChecker = NULL;
  1.1299 +        PKIX_Error *chainFailed = NULL;
  1.1300 +        void *nbioContext = NULL;
  1.1301 +
  1.1302 +        PKIX_ENTER(VALIDATE, "PKIX_ValidateChain_NB");
  1.1303 +        PKIX_NULLCHECK_FOUR
  1.1304 +                (valParams, pCertIndex, pAnchorIndex, pCheckerIndex);
  1.1305 +        PKIX_NULLCHECK_FOUR(pRevChecking, pCheckers, pNBIOContext, pResult);
  1.1306 +
  1.1307 +        nbioContext = *pNBIOContext;
  1.1308 +        *pNBIOContext = NULL;
  1.1309 +
  1.1310 +        /* extract various parameters from valParams */
  1.1311 +        PKIX_CHECK(pkix_ExtractParameters
  1.1312 +                    (valParams,
  1.1313 +                    &certs,
  1.1314 +                    &numCerts,
  1.1315 +                    &procParams,
  1.1316 +                    &anchors,
  1.1317 +                    &numAnchors,
  1.1318 +                    plContext),
  1.1319 +                    PKIX_EXTRACTPARAMETERSFAILED);
  1.1320 +
  1.1321 +        /*
  1.1322 +         * Create a List of the OIDs that will be processed by the user
  1.1323 +         * checkers. User checkers are not responsible for removing OIDs from
  1.1324 +         * the List of unresolved critical extensions, as libpkix checkers are.
  1.1325 +         * So we add those user checkers' OIDs to the removal list to be taken
  1.1326 +         * out by CheckChain.
  1.1327 +         */
  1.1328 +        PKIX_CHECK(PKIX_ProcessingParams_GetCertChainCheckers
  1.1329 +                (procParams, &userCheckers, plContext),
  1.1330 +                PKIX_PROCESSINGPARAMSGETCERTCHAINCHECKERSFAILED);
  1.1331 +
  1.1332 +        PKIX_CHECK(pkix_Validate_BuildUserOIDs
  1.1333 +                (userCheckers, &validateCheckedCritExtOIDsList, plContext),
  1.1334 +                PKIX_VALIDATEBUILDUSEROIDSFAILED);
  1.1335 +
  1.1336 +        PKIX_CHECK(PKIX_ProcessingParams_GetRevocationChecker
  1.1337 +                (procParams, &revChecker, plContext),
  1.1338 +                PKIX_PROCESSINGPARAMSGETREVOCATIONCHECKERFAILED);
  1.1339 +
  1.1340 +        /* Are we resuming after a WOULDBLOCK return, or starting anew ? */
  1.1341 +        if (nbioContext != NULL) {
  1.1342 +                /* Resuming */
  1.1343 +                certIndex = *pCertIndex;
  1.1344 +                anchorIndex = *pAnchorIndex;
  1.1345 +                checkerIndex = *pCheckerIndex;
  1.1346 +                revChecking = *pRevChecking;
  1.1347 +                checkers = *pCheckers;
  1.1348 +                *pCheckers = NULL;
  1.1349 +        }
  1.1350 +
  1.1351 +        /* try to validate the chain with each anchor */
  1.1352 +        for (i = anchorIndex; i < numAnchors; i++) {
  1.1353 +
  1.1354 +                /* get trust anchor */
  1.1355 +                PKIX_CHECK(PKIX_List_GetItem
  1.1356 +                        (anchors, i, (PKIX_PL_Object **)&anchor, plContext),
  1.1357 +                        PKIX_LISTGETITEMFAILED);
  1.1358 +
  1.1359 +                /* initialize checkers using information from trust anchor */
  1.1360 +                if (nbioContext == NULL) {
  1.1361 +                        PKIX_CHECK(pkix_InitializeCheckers
  1.1362 +                                (anchor,
  1.1363 +                                procParams,
  1.1364 +                                numCerts,
  1.1365 +                                &checkers,
  1.1366 +                                plContext),
  1.1367 +                                PKIX_INITIALIZECHECKERSFAILED);
  1.1368 +                }
  1.1369 +
  1.1370 +                /*
  1.1371 +                 * Validate the chain using this trust anchor and these
  1.1372 +                 * checkers.
  1.1373 +                 */
  1.1374 +                chainFailed = pkix_CheckChain
  1.1375 +                        (certs,
  1.1376 +                        numCerts,
  1.1377 +                        anchor,
  1.1378 +                        checkers,
  1.1379 +                        revChecker,
  1.1380 +                        validateCheckedCritExtOIDsList,
  1.1381 +                        procParams,
  1.1382 +                        &certIndex,
  1.1383 +                        &checkerIndex,
  1.1384 +                        &revChecking,
  1.1385 +                        &reasonCode,
  1.1386 +                        &nbioContext,
  1.1387 +                        &finalPubKey,
  1.1388 +                        &validPolicyTree,
  1.1389 +                        pVerifyTree,
  1.1390 +                        plContext);
  1.1391 +
  1.1392 +                if (nbioContext != NULL) {
  1.1393 +                        *pCertIndex = certIndex;
  1.1394 +                        *pAnchorIndex = anchorIndex;
  1.1395 +                        *pCheckerIndex = checkerIndex;
  1.1396 +                        *pRevChecking = revChecking;
  1.1397 +                        PKIX_INCREF(checkers);
  1.1398 +                        *pCheckers = checkers;
  1.1399 +                        *pNBIOContext = nbioContext;
  1.1400 +                        goto cleanup;
  1.1401 +                }
  1.1402 +
  1.1403 +                if (chainFailed) {
  1.1404 +
  1.1405 +                        /* cert chain failed to validate */
  1.1406 +
  1.1407 +                        PKIX_DECREF(chainFailed);
  1.1408 +                        PKIX_DECREF(anchor);
  1.1409 +                        PKIX_DECREF(checkers);
  1.1410 +                        PKIX_DECREF(validPolicyTree);
  1.1411 +
  1.1412 +                        /* if last anchor, we fail; else, we try next anchor */
  1.1413 +                        if (i == (numAnchors - 1)) { /* last anchor */
  1.1414 +                                PKIX_ERROR(PKIX_VALIDATECHAINFAILED);
  1.1415 +                        }
  1.1416 +
  1.1417 +                } else {
  1.1418 +
  1.1419 +                        /* XXX Remove this assertion after 2014-12-31.
  1.1420 +                         * See bug 946984. */
  1.1421 +                        PORT_Assert(reasonCode == 0);
  1.1422 +
  1.1423 +                        /* cert chain successfully validated! */
  1.1424 +                        PKIX_CHECK(pkix_ValidateResult_Create
  1.1425 +                                (finalPubKey,
  1.1426 +                                anchor,
  1.1427 +                                validPolicyTree,
  1.1428 +                                &valResult,
  1.1429 +                                plContext),
  1.1430 +                                PKIX_VALIDATERESULTCREATEFAILED);
  1.1431 +
  1.1432 +                        *pResult = valResult;
  1.1433 +
  1.1434 +                        /* no need to try any more anchors in the loop */
  1.1435 +                        goto cleanup;
  1.1436 +                }
  1.1437 +        }
  1.1438 +
  1.1439 +cleanup:
  1.1440 +
  1.1441 +        PKIX_DECREF(finalPubKey);
  1.1442 +        PKIX_DECREF(certs);
  1.1443 +        PKIX_DECREF(anchors);
  1.1444 +        PKIX_DECREF(anchor);
  1.1445 +        PKIX_DECREF(checkers);
  1.1446 +        PKIX_DECREF(revChecker);
  1.1447 +        PKIX_DECREF(validPolicyTree);
  1.1448 +        PKIX_DECREF(chainFailed);
  1.1449 +        PKIX_DECREF(procParams);
  1.1450 +        PKIX_DECREF(userCheckers);
  1.1451 +        PKIX_DECREF(validateCheckedCritExtOIDsList);
  1.1452 +
  1.1453 +        PKIX_RETURN(VALIDATE);
  1.1454 +}

mercurial