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

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

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

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

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

mercurial