security/nss/lib/certhigh/certvfypkix.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
-rw-r--r--

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  * nss_pkix_proxy.h
     6  *
     7  * PKIX - NSS proxy functions
     8  *
     9  * NOTE: All structures, functions, data types are parts of library private
    10  * api and are subjects to change in any following releases.
    11  *
    12  */
    13 #include "prerror.h"
    14 #include "prprf.h"
    16 #include "nspr.h"
    17 #include "pk11func.h"
    18 #include "certdb.h"
    19 #include "cert.h"
    20 #include "secerr.h"
    21 #include "nssb64.h"
    22 #include "secasn1.h"
    23 #include "secder.h"
    24 #include "pkit.h"
    26 #include "pkix_pl_common.h"
    28 extern PRLogModuleInfo *pkixLog;
    30 #ifdef DEBUG_volkov
    31 /* Temporary declarations of functioins. Will be removed with fix for
    32  * 391183 */
    33 extern char *
    34 pkix_Error2ASCII(PKIX_Error *error, void *plContext);
    36 extern void
    37 cert_PrintCert(PKIX_PL_Cert *pkixCert, void *plContext);
    39 extern PKIX_Error *
    40 cert_PrintCertChain(PKIX_List *pkixCertChain, void *plContext);
    42 #endif /* DEBUG */
    44 #ifdef PKIX_OBJECT_LEAK_TEST
    46 extern PKIX_UInt32
    47 pkix_pl_lifecycle_ObjectLeakCheck(int *);
    49 extern SECStatus
    50 pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable);
    52 PRInt32 parallelFnInvocationCount;
    53 #endif /* PKIX_OBJECT_LEAK_TEST */
    56 static PRBool usePKIXValidationEngine = PR_FALSE;
    58 /*
    59  * FUNCTION: CERT_SetUsePKIXForValidation
    60  * DESCRIPTION:
    61  *
    62  * Enables or disables use of libpkix for certificate validation
    63  *
    64  * PARAMETERS:
    65  *  "enable"
    66  *      PR_TRUE: enables use of libpkix for cert validation.
    67  *      PR_FALSE: disables.
    68  * THREAD SAFETY:
    69  *  NOT Thread Safe.
    70  * RETURNS:
    71  *  Returns SECSuccess if successfully enabled
    72  */
    73 SECStatus
    74 CERT_SetUsePKIXForValidation(PRBool enable)
    75 {
    76     usePKIXValidationEngine = (enable > 0) ? PR_TRUE : PR_FALSE;
    77     return SECSuccess;
    78 }
    80 /*
    81  * FUNCTION: CERT_GetUsePKIXForValidation
    82  * DESCRIPTION:
    83  *
    84  * Checks if libpkix building function should be use for certificate
    85  * chain building.
    86  *
    87  * PARAMETERS:
    88  *  NONE
    89  * THREAD SAFETY:
    90  *  NOT Thread Safe
    91  * RETURNS:
    92  *  Returns PR_TRUE if libpkix should be used. PR_FALSE otherwise.
    93  */
    94 PRBool
    95 CERT_GetUsePKIXForValidation()
    96 {
    97     return usePKIXValidationEngine;
    98 }
   100 #ifdef NOTDEF
   101 /*
   102  * FUNCTION: cert_NssKeyUsagesToPkix
   103  * DESCRIPTION:
   104  *
   105  * Converts nss key usage bit field(PRUint32) to pkix key usage
   106  * bit field.
   107  *
   108  * PARAMETERS:
   109  *  "nssKeyUsage"
   110  *      Nss key usage bit field.
   111  *  "pkixKeyUsage"
   112  *      Pkix key usage big field.
   113  *  "plContext"
   114  *      Platform-specific context pointer.
   115  * THREAD SAFETY:
   116  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   117  * RETURNS:
   118  *  Returns NULL if the function succeeds.
   119  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   120  */
   121 static PKIX_Error*
   122 cert_NssKeyUsagesToPkix(
   123     PRUint32 nssKeyUsage,
   124     PKIX_UInt32 *pPkixKeyUsage,
   125     void *plContext)
   126 {
   127     PKIX_UInt32 pkixKeyUsage = 0;
   129     PKIX_ENTER(CERTVFYPKIX, "cert_NssKeyUsagesToPkix");
   130     PKIX_NULLCHECK_ONE(pPkixKeyUsage);
   132     *pPkixKeyUsage = 0;
   134     if (nssKeyUsage & KU_DIGITAL_SIGNATURE) {
   135         pkixKeyUsage |= PKIX_DIGITAL_SIGNATURE;
   136     }
   138     if (nssKeyUsage & KU_NON_REPUDIATION) {
   139         pkixKeyUsage |= PKIX_NON_REPUDIATION;
   140     }
   142     if (nssKeyUsage & KU_KEY_ENCIPHERMENT) {
   143         pkixKeyUsage |= PKIX_KEY_ENCIPHERMENT;
   144     }
   146     if (nssKeyUsage & KU_DATA_ENCIPHERMENT) {
   147         pkixKeyUsage |= PKIX_DATA_ENCIPHERMENT;
   148     }
   150     if (nssKeyUsage & KU_KEY_AGREEMENT) {
   151         pkixKeyUsage |= PKIX_KEY_AGREEMENT;
   152     }
   154     if (nssKeyUsage & KU_KEY_CERT_SIGN) {
   155         pkixKeyUsage |= PKIX_KEY_CERT_SIGN;
   156     }
   158     if (nssKeyUsage & KU_CRL_SIGN) {
   159         pkixKeyUsage |= PKIX_CRL_SIGN;
   160     }
   162     if (nssKeyUsage & KU_ENCIPHER_ONLY) {
   163         pkixKeyUsage |= PKIX_ENCIPHER_ONLY;
   164     }
   166     /* Not supported. XXX we should support this once it is
   167      * fixed in NSS */
   168     /* pkixKeyUsage |= PKIX_DECIPHER_ONLY; */
   170     *pPkixKeyUsage = pkixKeyUsage;
   172     PKIX_RETURN(CERTVFYPKIX);
   173 }
   175 extern SECOidTag ekuOidStrings[];
   177 enum {
   178     ekuIndexSSLServer = 0,
   179     ekuIndexSSLClient,
   180     ekuIndexCodeSigner,
   181     ekuIndexEmail,
   182     ekuIndexTimeStamp,
   183     ekuIndexStatusResponder,
   184     ekuIndexUnknown
   185 } ekuIndex;
   187 typedef struct {
   188     SECCertUsage certUsage;
   189     PRUint32 ekuStringIndex;
   190 } SECCertUsageToEku;
   192 const SECCertUsageToEku certUsageEkuStringMap[] = {
   193     {certUsageSSLClient,             ekuIndexSSLClient},
   194     {certUsageSSLServer,             ekuIndexSSLServer},
   195     {certUsageSSLCA,                 ekuIndexSSLServer},
   196     {certUsageEmailSigner,           ekuIndexEmail},
   197     {certUsageEmailRecipient,        ekuIndexEmail},
   198     {certUsageObjectSigner,          ekuIndexCodeSigner},
   199     {certUsageUserCertImport,        ekuIndexUnknown},
   200     {certUsageVerifyCA,              ekuIndexUnknown},
   201     {certUsageProtectedObjectSigner, ekuIndexUnknown},
   202     {certUsageStatusResponder,       ekuIndexStatusResponder},
   203     {certUsageAnyCA,                 ekuIndexUnknown},
   204 };
   206 /*
   207  * FUNCTION: cert_NssCertificateUsageToPkixKUAndEKU
   208  * DESCRIPTION:
   209  *
   210  * Converts nss CERTCertificateUsage bit field to pkix key and
   211  * extended key usages.
   212  *
   213  * PARAMETERS:
   214  *  "cert"
   215  *      Pointer to CERTCertificate structure of validating cert.
   216  *  "requiredCertUsages"
   217  *      Required usage that will be converted to pkix eku and ku. 
   218  *  "requiredKeyUsage",
   219  *      Additional key usages impose to cert.
   220  *  "isCA",
   221  *      it true, convert usages for cert that is a CA cert.  
   222  *  "ppkixEKUList"
   223  *      Returned address of a list of pkix extended key usages.
   224  *  "ppkixKU"
   225  *      Returned address of pkix required key usages bit field. 
   226  *  "plContext"
   227  *      Platform-specific context pointer.
   228  * THREAD SAFETY:
   229  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   230  * RETURNS:
   231  *  Returns NULL if the function succeeds.
   232  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   233  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   234  */
   235 static PKIX_Error*
   236 cert_NssCertificateUsageToPkixKUAndEKU(
   237     CERTCertificate *cert,
   238     SECCertUsage     requiredCertUsage,
   239     PRUint32         requiredKeyUsages,
   240     PRBool           isCA,
   241     PKIX_List      **ppkixEKUList,
   242     PKIX_UInt32     *ppkixKU,
   243     void            *plContext)
   244 {
   245     PKIX_List           *ekuOidsList = NULL;
   246     PKIX_PL_OID         *ekuOid = NULL;
   247     int                  i = 0;
   248     int                  ekuIndex = ekuIndexUnknown;
   250     PKIX_ENTER(CERTVFYPKIX, "cert_NssCertificateUsageToPkixEku");
   251     PKIX_NULLCHECK_TWO(ppkixEKUList, ppkixKU);
   253     PKIX_CHECK(
   254         PKIX_List_Create(&ekuOidsList, plContext),
   255         PKIX_LISTCREATEFAILED);
   257     for (;i < PR_ARRAY_SIZE(certUsageEkuStringMap);i++) {
   258         const SECCertUsageToEku *usageToEkuElem =
   259             &certUsageEkuStringMap[i];
   260         if (usageToEkuElem->certUsage == requiredCertUsage) {
   261             ekuIndex = usageToEkuElem->ekuStringIndex;
   262             break;
   263         }
   264     }
   265     if (ekuIndex != ekuIndexUnknown) {
   266         PRUint32             reqKeyUsage = 0;
   267         PRUint32             reqCertType = 0;
   269         CERT_KeyUsageAndTypeForCertUsage(requiredCertUsage, isCA,
   270                                          &reqKeyUsage,
   271                                          &reqCertType);
   273         requiredKeyUsages |= reqKeyUsage;
   275         PKIX_CHECK(
   276             PKIX_PL_OID_Create(ekuOidStrings[ekuIndex], &ekuOid,
   277                                plContext),
   278             PKIX_OIDCREATEFAILED);
   280         PKIX_CHECK(
   281             PKIX_List_AppendItem(ekuOidsList, (PKIX_PL_Object *)ekuOid,
   282                                  plContext),
   283             PKIX_LISTAPPENDITEMFAILED);
   285         PKIX_DECREF(ekuOid);
   286     }
   288     PKIX_CHECK(
   289         cert_NssKeyUsagesToPkix(requiredKeyUsages, ppkixKU, plContext),
   290         PKIX_NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED);
   292     *ppkixEKUList = ekuOidsList;
   293     ekuOidsList = NULL;
   295 cleanup:
   297     PKIX_DECREF(ekuOid);
   298     PKIX_DECREF(ekuOidsList);
   300     PKIX_RETURN(CERTVFYPKIX);
   301 }
   303 #endif
   305 /*
   306  * FUNCTION: cert_ProcessingParamsSetKeyAndCertUsage
   307  * DESCRIPTION:
   308  *
   309  * Converts cert usage to pkix KU type and sets
   310  * converted data into PKIX_ProcessingParams object. It also sets
   311  * proper cert usage into nsscontext object.
   312  *
   313  * PARAMETERS:
   314  *  "procParams"
   315  *      Pointer to PKIX_ProcessingParams used during validation.
   316  *  "requiredCertUsage"
   317  *      Required certificate usages the certificate and chain is built and
   318  *      validated for.
   319  *  "requiredKeyUsage"
   320  *      Request additional key usages the certificate should be validated for.
   321  *  "plContext"
   322  *      Platform-specific context pointer.
   323  * THREAD SAFETY:
   324  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   325  * RETURNS:
   326  *  Returns NULL if the function succeeds.
   327  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   328  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   329  */
   330 static PKIX_Error*
   331 cert_ProcessingParamsSetKeyAndCertUsage(
   332     PKIX_ProcessingParams *procParams,
   333     SECCertUsage           requiredCertUsage,
   334     PRUint32               requiredKeyUsages,
   335     void                  *plContext)
   336 {
   337     PKIX_CertSelector     *certSelector = NULL;
   338     PKIX_ComCertSelParams *certSelParams = NULL;
   339     PKIX_PL_NssContext    *nssContext = (PKIX_PL_NssContext*)plContext;
   341     PKIX_ENTER(CERTVFYPKIX, "cert_ProcessingParamsSetKeyAndCertUsage");
   342     PKIX_NULLCHECK_TWO(procParams, nssContext);
   344     PKIX_CHECK(
   345         pkix_pl_NssContext_SetCertUsage(
   346 	    ((SECCertificateUsage)1) << requiredCertUsage, nssContext),
   347 	    PKIX_NSSCONTEXTSETCERTUSAGEFAILED);
   349     if (requiredKeyUsages) {
   350         PKIX_CHECK(
   351             PKIX_ProcessingParams_GetTargetCertConstraints(procParams,
   352                                                            &certSelector, plContext),
   353             PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
   355         PKIX_CHECK(
   356             PKIX_CertSelector_GetCommonCertSelectorParams(certSelector,
   357                                                           &certSelParams, plContext),
   358             PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
   361         PKIX_CHECK(
   362             PKIX_ComCertSelParams_SetKeyUsage(certSelParams, requiredKeyUsages,
   363                                               plContext),
   364             PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED);
   365     }
   366 cleanup:
   367     PKIX_DECREF(certSelector);
   368     PKIX_DECREF(certSelParams);
   370     PKIX_RETURN(CERTVFYPKIX);
   371 }
   373 /*
   374  * Unused parameters: 
   375  *
   376  *  CERTCertList *initialChain,
   377  *  CERTCertStores certStores,
   378  *  CERTCertRevCheckers certRevCheckers,
   379  *  CERTCertChainCheckers certChainCheckers,
   380  *  SECItem *initPolicies,
   381  *  PRBool policyQualifierRejected,
   382  *  PRBool anyPolicyInhibited,
   383  *  PRBool reqExplicitPolicy,
   384  *  PRBool policyMappingInhibited,
   385  *  PKIX_CertSelector certConstraints,
   386  */
   388 /*
   389  * FUNCTION: cert_CreatePkixProcessingParams
   390  * DESCRIPTION:
   391  *
   392  * Creates and fills in PKIX_ProcessingParams structure to be used
   393  * for certificate chain building.
   394  *
   395  * PARAMETERS:
   396  *  "cert"
   397  *      Pointer to the CERTCertificate: the leaf certificate of a chain.
   398  *  "time"
   399  *      Validity time.
   400  *  "wincx"
   401  *      Nss db password token.
   402  *  "useArena"
   403  *      Flags to use arena for data allocation during chain building process.
   404  *  "pprocParams"
   405  *      Address to return created processing parameters.
   406  *  "plContext"
   407  *      Platform-specific context pointer.
   408  * THREAD SAFETY:
   409  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   410  * RETURNS:
   411  *  Returns NULL if the function succeeds.
   412  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   413  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   414  */
   415 static PKIX_Error*
   416 cert_CreatePkixProcessingParams(
   417     CERTCertificate        *cert,
   418     PRBool                  checkSig, /* not used yet. See bug 391476 */
   419     PRTime                  time,
   420     void                   *wincx,
   421     PRBool                  useArena,
   422     PRBool                  disableOCSPRemoteFetching,
   423     PKIX_ProcessingParams **pprocParams,
   424     void                  **pplContext)
   425 {
   426     PKIX_List             *anchors = NULL;
   427     PKIX_PL_Cert          *targetCert = NULL;
   428     PKIX_PL_Date          *date = NULL;
   429     PKIX_ProcessingParams *procParams = NULL;
   430     PKIX_CertSelector     *certSelector = NULL;
   431     PKIX_ComCertSelParams *certSelParams = NULL;
   432     PKIX_CertStore        *certStore = NULL;
   433     PKIX_List             *certStores = NULL;
   434     PKIX_RevocationChecker *revChecker = NULL;
   435     PKIX_UInt32           methodFlags = 0;
   436     void                  *plContext = NULL;
   437     CERTStatusConfig      *statusConfig = NULL;
   439     PKIX_ENTER(CERTVFYPKIX, "cert_CreatePkixProcessingParams");
   440     PKIX_NULLCHECK_TWO(cert, pprocParams);
   442     PKIX_CHECK(
   443         PKIX_PL_NssContext_Create(0, useArena, wincx, &plContext),
   444         PKIX_NSSCONTEXTCREATEFAILED);
   446     *pplContext = plContext;
   448 #ifdef PKIX_NOTDEF 
   449     /* Functions should be implemented in patch for 390532 */
   450     PKIX_CHECK(
   451         pkix_pl_NssContext_SetCertSignatureCheck(checkSig,
   452                                                  (PKIX_PL_NssContext*)plContext),
   453         PKIX_NSSCONTEXTSETCERTSIGNCHECKFAILED);
   455 #endif /* PKIX_NOTDEF */
   457     PKIX_CHECK(
   458         PKIX_ProcessingParams_Create(&procParams, plContext),
   459         PKIX_PROCESSINGPARAMSCREATEFAILED);
   461     PKIX_CHECK(
   462         PKIX_ComCertSelParams_Create(&certSelParams, plContext),
   463         PKIX_COMCERTSELPARAMSCREATEFAILED);
   465     PKIX_CHECK(
   466         PKIX_PL_Cert_CreateFromCERTCertificate(cert, &targetCert, plContext),
   467         PKIX_CERTCREATEWITHNSSCERTFAILED);
   469     PKIX_CHECK(
   470         PKIX_ComCertSelParams_SetCertificate(certSelParams,
   471                                              targetCert, plContext),
   472         PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED);
   474     PKIX_CHECK(
   475         PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext),
   476         PKIX_COULDNOTCREATECERTSELECTOROBJECT);
   478     PKIX_CHECK(
   479         PKIX_CertSelector_SetCommonCertSelectorParams(certSelector,
   480                                                       certSelParams, plContext),
   481         PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
   483     PKIX_CHECK(
   484         PKIX_ProcessingParams_SetTargetCertConstraints(procParams,
   485                                                        certSelector, plContext),
   486         PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED);
   488     /* Turn off quialification of target cert since leaf cert is
   489      * already check for date validity, key usages and extended
   490      * key usages. */
   491     PKIX_CHECK(
   492         PKIX_ProcessingParams_SetQualifyTargetCert(procParams, PKIX_FALSE,
   493                                                    plContext),
   494         PKIX_PROCESSINGPARAMSSETQUALIFYTARGETCERTFLAGFAILED);
   496     PKIX_CHECK(
   497         PKIX_PL_Pk11CertStore_Create(&certStore, plContext),
   498         PKIX_PK11CERTSTORECREATEFAILED);
   500     PKIX_CHECK(
   501         PKIX_List_Create(&certStores, plContext),
   502         PKIX_UNABLETOCREATELIST);
   504     PKIX_CHECK(
   505         PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore,
   506                              plContext),
   507         PKIX_LISTAPPENDITEMFAILED);
   509     PKIX_CHECK(
   510         PKIX_ProcessingParams_SetCertStores(procParams, certStores,
   511                                             plContext),
   512         PKIX_PROCESSINGPARAMSADDCERTSTOREFAILED);
   514     PKIX_CHECK(
   515         PKIX_PL_Date_CreateFromPRTime(time, &date, plContext),
   516         PKIX_DATECREATEFROMPRTIMEFAILED);
   518     PKIX_CHECK(
   519         PKIX_ProcessingParams_SetDate(procParams, date, plContext),
   520         PKIX_PROCESSINGPARAMSSETDATEFAILED);
   522     PKIX_CHECK(
   523         PKIX_RevocationChecker_Create(
   524                                   PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
   525                                   PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT,
   526                                   PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
   527                                   PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT,
   528                                   &revChecker, plContext),
   529         PKIX_REVOCATIONCHECKERCREATEFAILED);
   531     PKIX_CHECK(
   532         PKIX_ProcessingParams_SetRevocationChecker(procParams, revChecker,
   533                                                    plContext),
   534         PKIX_PROCESSINGPARAMSSETREVOCATIONCHECKERFAILED);
   536     /* CRL method flags */
   537     methodFlags = 
   538         PKIX_REV_M_TEST_USING_THIS_METHOD |
   539         PKIX_REV_M_FORBID_NETWORK_FETCHING |
   540         PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE |   /* 0 */
   541         PKIX_REV_M_IGNORE_MISSING_FRESH_INFO |     /* 0 */
   542         PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO;
   544     /* add CRL revocation method to check the leaf certificate */
   545     PKIX_CHECK(
   546         PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
   547                                          PKIX_RevocationMethod_CRL, methodFlags,
   548                                          0, NULL, PKIX_TRUE, plContext),
   549         PKIX_REVOCATIONCHECKERADDMETHODFAILED);
   551     /* add CRL revocation method for other certs in the chain. */
   552     PKIX_CHECK(
   553         PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
   554                                          PKIX_RevocationMethod_CRL, methodFlags,
   555                                          0, NULL, PKIX_FALSE, plContext),
   556         PKIX_REVOCATIONCHECKERADDMETHODFAILED);
   558     /* For compatibility with the old code, need to check that
   559      * statusConfig is set in the db handle and status checker
   560      * is defined befor allow ocsp status check on the leaf cert.*/
   561     statusConfig = CERT_GetStatusConfig(CERT_GetDefaultCertDB());
   562     if (statusConfig != NULL && statusConfig->statusChecker != NULL) {
   564         /* Enable OCSP revocation checking for the leaf cert. */
   565         /* OCSP method flags */
   566         methodFlags =
   567             PKIX_REV_M_TEST_USING_THIS_METHOD |
   568             PKIX_REV_M_ALLOW_NETWORK_FETCHING |         /* 0 */
   569             PKIX_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE |  /* 0 */
   570             PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE |    /* 0 */
   571             PKIX_REV_M_IGNORE_MISSING_FRESH_INFO |      /* 0 */
   572             PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO;
   574         /* Disabling ocsp fetching when checking the status
   575          * of ocsp response signer. Here and in the next if,
   576          * adjust flags for ocsp signer cert validation case. */
   577         if (disableOCSPRemoteFetching) {
   578             methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING;
   579         }
   581         if (ocsp_FetchingFailureIsVerificationFailure()
   582             && !disableOCSPRemoteFetching) {
   583             methodFlags |=
   584                 PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO;
   585         }
   587         /* add OCSP revocation method to check only the leaf certificate.*/
   588         PKIX_CHECK(
   589             PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
   590                                      PKIX_RevocationMethod_OCSP, methodFlags,
   591                                      1, NULL, PKIX_TRUE, plContext),
   592             PKIX_REVOCATIONCHECKERADDMETHODFAILED);
   593     }
   595     PKIX_CHECK(
   596         PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams, PR_FALSE,
   597                                                     plContext),
   598         PKIX_PROCESSINGPARAMSSETANYPOLICYINHIBITED);
   600     PKIX_CHECK(
   601         PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams, PR_FALSE,
   602                                                        plContext),
   603         PKIX_PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED);
   605     PKIX_CHECK(
   606         PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams, PR_FALSE,
   607                                                         plContext),
   608         PKIX_PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED);
   610     *pprocParams = procParams;
   611     procParams = NULL;
   613 cleanup:
   614     PKIX_DECREF(anchors);
   615     PKIX_DECREF(targetCert);
   616     PKIX_DECREF(date);
   617     PKIX_DECREF(certSelector);
   618     PKIX_DECREF(certSelParams);
   619     PKIX_DECREF(certStore);
   620     PKIX_DECREF(certStores);
   621     PKIX_DECREF(procParams);
   622     PKIX_DECREF(revChecker);
   624     PKIX_RETURN(CERTVFYPKIX);
   625 }
   627 /*
   628  * FUNCTION: cert_PkixToNssCertsChain
   629  * DESCRIPTION:
   630  *
   631  * Converts pkix cert list into nss cert list.
   632  * 
   633  * PARAMETERS:
   634  *  "pkixCertChain"
   635  *      Pkix certificate list.     
   636  *  "pvalidChain"
   637  *      An address of returned nss certificate list.
   638  *  "plContext"
   639  *      Platform-specific context pointer.
   640  * THREAD SAFETY:
   641  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   642  * RETURNS:
   643  *  Returns NULL if the function succeeds.
   644  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   645  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   646  */
   647 static PKIX_Error*
   648 cert_PkixToNssCertsChain(
   649     PKIX_List *pkixCertChain, 
   650     CERTCertList **pvalidChain, 
   651     void *plContext)
   652 {
   653     PLArenaPool     *arena = NULL;
   654     CERTCertificate *nssCert = NULL;
   655     CERTCertList    *validChain = NULL;
   656     PKIX_PL_Object  *certItem = NULL;
   657     PKIX_UInt32      length = 0;
   658     PKIX_UInt32      i = 0;
   660     PKIX_ENTER(CERTVFYPKIX, "cert_PkixToNssCertsChain");
   661     PKIX_NULLCHECK_ONE(pvalidChain);
   663     if (pkixCertChain == NULL) {
   664         goto cleanup;
   665     }
   666     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   667     if (arena == NULL) {
   668         PKIX_ERROR(PKIX_OUTOFMEMORY);
   669     }
   670     validChain = (CERTCertList*)PORT_ArenaZAlloc(arena, sizeof(CERTCertList));
   671     if (validChain == NULL) {
   672         PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
   673     }
   674     PR_INIT_CLIST(&validChain->list);
   675     validChain->arena = arena;
   676     arena = NULL;
   678     PKIX_CHECK(
   679         PKIX_List_GetLength(pkixCertChain, &length, plContext),
   680         PKIX_LISTGETLENGTHFAILED);
   682     for (i = 0; i < length; i++){
   683         CERTCertListNode *node = NULL;
   685         PKIX_CHECK(
   686             PKIX_List_GetItem(pkixCertChain, i, &certItem, plContext),
   687             PKIX_LISTGETITEMFAILED);
   689         PKIX_CHECK(
   690             PKIX_PL_Cert_GetCERTCertificate((PKIX_PL_Cert*)certItem, &nssCert,
   691                                     plContext),
   692             PKIX_CERTGETCERTCERTIFICATEFAILED);
   694         node =
   695             (CERTCertListNode *)PORT_ArenaZAlloc(validChain->arena,
   696                                                  sizeof(CERTCertListNode));
   697         if ( node == NULL ) {
   698             PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
   699         }
   701         PR_INSERT_BEFORE(&node->links, &validChain->list);
   703         node->cert = nssCert;
   704         nssCert = NULL;
   706         PKIX_DECREF(certItem);
   707     }
   709     *pvalidChain = validChain;
   711 cleanup:
   712     if (PKIX_ERROR_RECEIVED){
   713         if (validChain) {
   714             CERT_DestroyCertList(validChain);
   715         } else if (arena) {
   716             PORT_FreeArena(arena, PR_FALSE);
   717         }
   718         if (nssCert) {
   719             CERT_DestroyCertificate(nssCert);
   720         }
   721     }
   722     PKIX_DECREF(certItem);
   724     PKIX_RETURN(CERTVFYPKIX);
   725 }
   728 /*
   729  * FUNCTION: cert_BuildAndValidateChain
   730  * DESCRIPTION:
   731  *
   732  * The function builds and validates a cert chain based on certificate
   733  * selection criterias from procParams. This function call PKIX_BuildChain
   734  * to accomplish chain building. If PKIX_BuildChain returns with incomplete
   735  * IO, the function waits with PR_Poll until the blocking IO is finished and
   736  * return control back to PKIX_BuildChain.
   737  *
   738  * PARAMETERS:
   739  *  "procParams"
   740  *      Processing parameters to be used during chain building.
   741  *  "pResult"
   742  *      Returned build result.
   743  *  "pVerifyNode"
   744  *      Returned pointed to verify node structure: the tree-like structure
   745  *      that reports points of chain building failures.
   746  *  "plContext"
   747  *      Platform-specific context pointer.
   748  * THREAD SAFETY:
   749  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   750  * RETURNS:
   751  *  Returns NULL if the function succeeds.
   752  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   753  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   754  */
   755 static PKIX_Error*
   756 cert_BuildAndValidateChain(
   757     PKIX_ProcessingParams *procParams,
   758     PKIX_BuildResult **pResult,
   759     PKIX_VerifyNode **pVerifyNode,
   760     void *plContext)
   761 {
   762     PKIX_BuildResult *result = NULL;
   763     PKIX_VerifyNode  *verifyNode = NULL;
   764     void             *nbioContext = NULL;
   765     void             *state = NULL;
   767     PKIX_ENTER(CERTVFYPKIX, "cert_BuildAndVerifyChain");
   768     PKIX_NULLCHECK_TWO(procParams, pResult);
   770     do {
   771         if (nbioContext && state) {
   772             /* PKIX-XXX: need to test functionality of NBIO handling in libPkix.
   773              * See bug 391180 */
   774             PRInt32 filesReady = 0;
   775             PRPollDesc *pollDesc = (PRPollDesc*)nbioContext;
   776             filesReady = PR_Poll(pollDesc, 1, PR_INTERVAL_NO_TIMEOUT);
   777             if (filesReady <= 0) {
   778                 PKIX_ERROR(PKIX_PRPOLLRETBADFILENUM);
   779             }
   780         }
   782         PKIX_CHECK(
   783             PKIX_BuildChain(procParams, &nbioContext, &state,
   784                             &result, &verifyNode, plContext),
   785             PKIX_UNABLETOBUILDCHAIN);
   787     } while (nbioContext && state);
   789     *pResult = result;
   791 cleanup:
   792     if (pVerifyNode) {
   793         *pVerifyNode = verifyNode;
   794     }
   796     PKIX_RETURN(CERTVFYPKIX);
   797 }
   800 /*
   801  * FUNCTION: cert_PkixErrorToNssCode
   802  * DESCRIPTION:
   803  *
   804  * Converts pkix error(PKIX_Error) structure to PR error codes.
   805  *
   806  * PKIX-XXX to be implemented. See 391183.
   807  *
   808  * PARAMETERS:
   809  *  "error"
   810  *      Pkix error that will be converted.
   811  *  "nssCode"
   812  *      Corresponding nss error code.
   813  *  "plContext"
   814  *      Platform-specific context pointer.
   815  * THREAD SAFETY:
   816  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   817  * RETURNS:
   818  *  Returns NULL if the function succeeds.
   819  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   820  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   821  */
   822 static PKIX_Error *
   823 cert_PkixErrorToNssCode(
   824     PKIX_Error *error,
   825     SECErrorCodes *pNssErr,
   826     void *plContext)
   827 {
   828     int errLevel = 0;
   829     PKIX_Int32 nssErr = 0;
   830     PKIX_Error *errPtr = error;
   832     PKIX_ENTER(CERTVFYPKIX, "cert_PkixErrorToNssCode");
   833     PKIX_NULLCHECK_TWO(error, pNssErr);
   835     /* Loop until we find at least one error with non-null
   836      * plErr code, that is going to be nss error code. */
   837     while (errPtr) {
   838         if (errPtr->plErr && !nssErr) {
   839             nssErr = errPtr->plErr;
   840             if (!pkixLog) break;
   841         }
   842         if (pkixLog) {
   843 #ifdef PKIX_ERROR_DESCRIPTION            
   844             PR_LOG(pkixLog, 2, ("Error at level %d: %s\n", errLevel,
   845                                 PKIX_ErrorText[errPtr->errCode]));
   846 #else
   847             PR_LOG(pkixLog, 2, ("Error at level %d: Error code %d\n", errLevel,
   848                                 errPtr->errCode));
   849 #endif /* PKIX_ERROR_DESCRIPTION */
   850         }
   851         errPtr = errPtr->cause;
   852         errLevel += 1; 
   853     }
   854     PORT_Assert(nssErr);
   855     if (!nssErr) {
   856         *pNssErr = SEC_ERROR_LIBPKIX_INTERNAL;
   857     } else {
   858         *pNssErr = nssErr;
   859     }
   861     PKIX_RETURN(CERTVFYPKIX);
   862 }
   864 /*
   865  * FUNCTION: cert_GetLogFromVerifyNode
   866  * DESCRIPTION:
   867  *
   868  * Recursive function that converts verify node tree-like set of structures
   869  * to CERTVerifyLog.
   870  *
   871  * PARAMETERS:
   872  *  "log"
   873  *      Pointed to already allocated CERTVerifyLog structure. 
   874  *  "node"
   875  *      A node of PKIX_VerifyNode tree.
   876  *  "plContext"
   877  *      Platform-specific context pointer.
   878  * THREAD SAFETY:
   879  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   880  * RETURNS:
   881  *  Returns NULL if the function succeeds.
   882  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   883  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   884  */
   885 static PKIX_Error *
   886 cert_GetLogFromVerifyNode(
   887     CERTVerifyLog *log,
   888     PKIX_VerifyNode *node,
   889     void *plContext)
   890 {
   891     PKIX_List       *children = NULL;
   892     PKIX_VerifyNode *childNode = NULL;
   894     PKIX_ENTER(CERTVFYPKIX, "cert_GetLogFromVerifyNode");
   896     children = node->children;
   898     if (children == NULL) {
   899         PKIX_ERRORCODE errCode = PKIX_ANCHORDIDNOTCHAINTOCERT;
   900         if (node->error && node->error->errCode != errCode) {
   901 #ifdef DEBUG_volkov
   902             char *string = pkix_Error2ASCII(node->error, plContext);
   903             fprintf(stderr, "Branch search finished with error: \t%s\n", string);
   904             PKIX_PL_Free(string, NULL);
   905 #endif
   906             if (log != NULL) {
   907                 SECErrorCodes nssErrorCode = 0;
   908                 CERTCertificate *cert = NULL;
   910                 cert = node->verifyCert->nssCert;
   912                 PKIX_CHECK(
   913                     cert_PkixErrorToNssCode(node->error, &nssErrorCode,
   914                                             plContext),
   915                     PKIX_GETPKIXERRORCODEFAILED);
   917                 cert_AddToVerifyLog(log, cert, nssErrorCode, node->depth, NULL);
   918             }
   919         }
   920         PKIX_RETURN(CERTVFYPKIX);
   921     } else {
   922         PRUint32      i = 0;
   923         PKIX_UInt32   length = 0;
   925         PKIX_CHECK(
   926             PKIX_List_GetLength(children, &length, plContext),
   927             PKIX_LISTGETLENGTHFAILED);
   929         for (i = 0; i < length; i++){
   931             PKIX_CHECK(
   932                 PKIX_List_GetItem(children, i, (PKIX_PL_Object**)&childNode,
   933                                   plContext),
   934                 PKIX_LISTGETITEMFAILED);
   936             PKIX_CHECK(
   937                 cert_GetLogFromVerifyNode(log, childNode, plContext),
   938                 PKIX_ERRORINRECURSIVEEQUALSCALL);
   940             PKIX_DECREF(childNode);
   941         }
   942     }
   944 cleanup:
   945     PKIX_DECREF(childNode);
   947     PKIX_RETURN(CERTVFYPKIX);
   948 }
   950 /*
   951  * FUNCTION: cert_GetBuildResults
   952  * DESCRIPTION:
   953  *
   954  * Converts pkix build results to nss results. This function is called
   955  * regardless of build result.
   956  *
   957  * If it called after chain was successfully constructed, then it will
   958  * convert:
   959  *   * pkix cert list that represent the chain to nss cert list
   960  *   * trusted root the chain was anchored to nss certificate.
   961  *
   962  * In case of failure it will convert:
   963  *   * pkix error to PR error code(will set it with PORT_SetError)
   964  *   * pkix validation log to nss CERTVerifyLog
   965  *   
   966  * PARAMETERS:
   967  *  "buildResult"
   968  *      Build results returned by PKIX_BuildChain.
   969  *  "verifyNode"
   970  *      Tree-like structure of chain building/validation failures
   971  *      returned by PKIX_BuildChain. Ignored in case of success.
   972  *  "error"
   973  *      Final error returned by PKIX_BuildChain. Should be NULL in
   974  *      case of success.
   975  *  "log"
   976  *      Address of pre-allocated(if not NULL) CERTVerifyLog structure.
   977  *  "ptrustedRoot"
   978  *      Address of returned trusted root the chain was anchored to.
   979  *  "pvalidChain"
   980  *      Address of returned valid chain.
   981  *  "plContext"
   982  *      Platform-specific context pointer.
   983  * THREAD SAFETY:
   984  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   985  * RETURNS:
   986  *  Returns NULL if the function succeeds.
   987  *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   988  *  Returns a Fatal Error if the function fails in an unrecoverable way.
   989  */
   990 static PKIX_Error*
   991 cert_GetBuildResults(
   992     PKIX_BuildResult *buildResult,
   993     PKIX_VerifyNode  *verifyNode,
   994     PKIX_Error       *error,
   995     CERTVerifyLog    *log,
   996     CERTCertificate **ptrustedRoot,
   997     CERTCertList    **pvalidChain,
   998     void             *plContext)
   999 {
  1000     PKIX_ValidateResult *validResult = NULL;
  1001     CERTCertList        *validChain = NULL;
  1002     CERTCertificate     *trustedRoot = NULL;
  1003     PKIX_TrustAnchor    *trustAnchor = NULL;
  1004     PKIX_PL_Cert        *trustedCert = NULL;
  1005     PKIX_List           *pkixCertChain = NULL;
  1006 #ifdef DEBUG_volkov
  1007     PKIX_Error          *tmpPkixError = NULL;
  1008 #endif /* DEBUG */
  1010     PKIX_ENTER(CERTVFYPKIX, "cert_GetBuildResults");
  1011     if (buildResult == NULL && error == NULL) {
  1012         PKIX_ERROR(PKIX_NULLARGUMENT);
  1015     if (error) {
  1016         SECErrorCodes nssErrorCode = 0;
  1017 #ifdef DEBUG_volkov        
  1018         char *temp = pkix_Error2ASCII(error, plContext);
  1019         fprintf(stderr, "BUILD ERROR:\n%s\n", temp);
  1020         PKIX_PL_Free(temp, NULL);
  1021 #endif /* DEBUG */
  1022         if (verifyNode) {
  1023             PKIX_Error *tmpError =
  1024                 cert_GetLogFromVerifyNode(log, verifyNode, plContext);
  1025             if (tmpError) {
  1026                 PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
  1029         cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
  1030         PORT_SetError(nssErrorCode);
  1031         goto cleanup;
  1034     if (pvalidChain) {
  1035         PKIX_CHECK(
  1036             PKIX_BuildResult_GetCertChain(buildResult, &pkixCertChain,
  1037                                           plContext),
  1038             PKIX_BUILDRESULTGETCERTCHAINFAILED);
  1040 #ifdef DEBUG_volkov
  1041         tmpPkixError = cert_PrintCertChain(pkixCertChain, plContext);
  1042         if (tmpPkixError) {
  1043             PKIX_PL_Object_DecRef((PKIX_PL_Object*)tmpPkixError, plContext);
  1045 #endif        
  1047         PKIX_CHECK(
  1048             cert_PkixToNssCertsChain(pkixCertChain, &validChain, plContext),
  1049             PKIX_CERTCHAINTONSSCHAINFAILED);
  1052     if (ptrustedRoot) {
  1053         PKIX_CHECK(
  1054             PKIX_BuildResult_GetValidateResult(buildResult, &validResult,
  1055                                                plContext),
  1056             PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
  1058         PKIX_CHECK(
  1059             PKIX_ValidateResult_GetTrustAnchor(validResult, &trustAnchor,
  1060                                                plContext),
  1061             PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
  1063         PKIX_CHECK(
  1064             PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustedCert,
  1065                                             plContext),
  1066             PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  1068 #ifdef DEBUG_volkov
  1069         if (pvalidChain == NULL) {
  1070             cert_PrintCert(trustedCert, plContext);
  1072 #endif        
  1074        PKIX_CHECK(
  1075             PKIX_PL_Cert_GetCERTCertificate(trustedCert, &trustedRoot,
  1076                                             plContext),
  1077             PKIX_CERTGETCERTCERTIFICATEFAILED);
  1080     PORT_Assert(!PKIX_ERROR_RECEIVED);
  1082     if (trustedRoot) {
  1083         *ptrustedRoot = trustedRoot;
  1085     if (validChain) {
  1086         *pvalidChain = validChain;
  1089 cleanup:
  1090     if (PKIX_ERROR_RECEIVED) {
  1091         if (trustedRoot) {
  1092             CERT_DestroyCertificate(trustedRoot);
  1094         if (validChain) {
  1095             CERT_DestroyCertList(validChain);
  1098     PKIX_DECREF(trustAnchor);
  1099     PKIX_DECREF(trustedCert);
  1100     PKIX_DECREF(pkixCertChain);
  1101     PKIX_DECREF(validResult);
  1102     PKIX_DECREF(error);
  1103     PKIX_DECREF(verifyNode);
  1104     PKIX_DECREF(buildResult);
  1106     PKIX_RETURN(CERTVFYPKIX);
  1109 /*
  1110  * FUNCTION: cert_VerifyCertChainPkix
  1111  * DESCRIPTION:
  1113  * The main wrapper function that is called from CERT_VerifyCert and
  1114  * CERT_VerifyCACertForUsage functions to validate cert with libpkix.
  1116  * PARAMETERS:
  1117  *  "cert"
  1118  *      Leaf certificate of a chain we want to build.
  1119  *  "checkSig"
  1120  *      Certificate signatures will not be verified if this
  1121  *      flag is set to PR_FALSE.
  1122  *  "requiredUsage"
  1123  *      Required usage for certificate and chain.
  1124  *  "time"
  1125  *      Validity time.
  1126  *  "wincx"
  1127  *      Nss database password token.
  1128  *  "log"
  1129  *      Address of already allocated CERTVerifyLog structure. Not
  1130  *      used if NULL;
  1131  *  "pSigerror"
  1132  *      Address of PRBool. If not NULL, returns true is cert chain
  1133  *      was invalidated because of bad certificate signature.
  1134  *  "pRevoked"
  1135  *      Address of PRBool. If not NULL, returns true is cert chain
  1136  *      was invalidated because a revoked certificate was found in
  1137  *      the chain.
  1138  * THREAD SAFETY:
  1139  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1140  * RETURNS:
  1141  *  SECFailure is chain building process has failed. SECSuccess otherwise.
  1142  */
  1143 SECStatus
  1144 cert_VerifyCertChainPkix(
  1145     CERTCertificate *cert,
  1146     PRBool           checkSig,
  1147     SECCertUsage     requiredUsage,
  1148     PRTime           time,
  1149     void            *wincx,
  1150     CERTVerifyLog   *log,
  1151     PRBool          *pSigerror,
  1152     PRBool          *pRevoked)
  1154     PKIX_ProcessingParams *procParams = NULL;
  1155     PKIX_BuildResult      *result = NULL;
  1156     PKIX_VerifyNode       *verifyNode = NULL;
  1157     PKIX_Error            *error = NULL;
  1159     SECStatus              rv = SECFailure;
  1160     void                  *plContext = NULL;
  1161 #ifdef DEBUG_volkov
  1162     CERTCertificate       *trustedRoot = NULL;
  1163     CERTCertList          *validChain = NULL;
  1164 #endif /* DEBUG */
  1166 #ifdef PKIX_OBJECT_LEAK_TEST
  1167     int  leakedObjNum = 0;
  1168     int  memLeakLoopCount = 0;
  1169     int  objCountTable[PKIX_NUMTYPES]; 
  1170     int  fnInvLocalCount = 0;
  1171     PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
  1173     if (usePKIXValidationEngine) {
  1174         /* current memory leak testing implementation does not allow
  1175          * to run simultaneous tests one the same or a different threads.
  1176          * Setting the variable to false, to make additional chain
  1177          * validations be handled by old nss. */
  1178         usePKIXValidationEngine = PR_FALSE;
  1180     testStartFnStackPosition = 2;
  1181     fnStackNameArr[0] = "cert_VerifyCertChainPkix";
  1182     fnStackInvCountArr[0] = 0;
  1183     PKIX_Boolean abortOnLeak = 
  1184         (PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ?
  1185                                                    PKIX_FALSE : PKIX_TRUE;
  1186     runningLeakTest = PKIX_TRUE;
  1188     /* Prevent multi-threaded run of object leak test */
  1189     fnInvLocalCount = PR_ATOMIC_INCREMENT(&parallelFnInvocationCount);
  1190     PORT_Assert(fnInvLocalCount == 1);
  1192 do {
  1193     rv = SECFailure;
  1194     plContext = NULL;
  1195     procParams = NULL;
  1196     result = NULL;
  1197     verifyNode = NULL;
  1198     error = NULL;
  1199 #ifdef DEBUG_volkov
  1200     trustedRoot = NULL;
  1201     validChain = NULL;
  1202 #endif /* DEBUG */
  1203     errorGenerated = PKIX_FALSE;
  1204     stackPosition = 0;
  1206     if (leakedObjNum) {
  1207         pkix_pl_lifecycle_ObjectTableUpdate(objCountTable); 
  1209     memLeakLoopCount += 1;
  1210 #endif /* PKIX_OBJECT_LEAK_TEST */
  1212     error =
  1213         cert_CreatePkixProcessingParams(cert, checkSig, time, wincx,
  1214                                     PR_FALSE/*use arena*/,
  1215                                     requiredUsage == certUsageStatusResponder,
  1216                                     &procParams, &plContext);
  1217     if (error) {
  1218         goto cleanup;
  1221     error =
  1222         cert_ProcessingParamsSetKeyAndCertUsage(procParams, requiredUsage, 0,
  1223                                                 plContext);
  1224     if (error) {
  1225         goto cleanup;
  1228     error = 
  1229         cert_BuildAndValidateChain(procParams, &result, &verifyNode, plContext);
  1230     if (error) {
  1231         goto cleanup;
  1234     if (pRevoked) {
  1235         /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
  1236         *pRevoked = PR_FALSE;
  1238     if (pSigerror) {
  1239         /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
  1240         *pSigerror = PR_FALSE;
  1242     rv = SECSuccess;
  1244 cleanup:
  1245     error = cert_GetBuildResults(result, verifyNode, error, log,
  1246 #ifdef DEBUG_volkov                                 
  1247                                  &trustedRoot, &validChain,
  1248 #else
  1249                                  NULL, NULL,
  1250 #endif /* DEBUG */
  1251                                  plContext);
  1252     if (error) {
  1253 #ifdef DEBUG_volkov        
  1254         char *temp = pkix_Error2ASCII(error, plContext);
  1255         fprintf(stderr, "GET BUILD RES ERRORS:\n%s\n", temp);
  1256         PKIX_PL_Free(temp, NULL);
  1257 #endif /* DEBUG */
  1258         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1260 #ifdef DEBUG_volkov
  1261     if (trustedRoot) {
  1262         CERT_DestroyCertificate(trustedRoot);
  1264     if (validChain) {
  1265         CERT_DestroyCertList(validChain);
  1267 #endif /* DEBUG */
  1268     if (procParams) {
  1269         PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
  1271     if (plContext) {
  1272         PKIX_PL_NssContext_Destroy(plContext);
  1275 #ifdef PKIX_OBJECT_LEAK_TEST
  1276     leakedObjNum =
  1277         pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
  1279     if (pkixLog && leakedObjNum) {
  1280         PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
  1281                             "Stack %s\n", memLeakLoopCount, errorFnStackString));
  1283     PR_Free(errorFnStackString);
  1284     errorFnStackString = NULL;
  1285     if (abortOnLeak) {
  1286         PORT_Assert(leakedObjNum == 0);
  1289 } while (errorGenerated);
  1291     runningLeakTest = PKIX_FALSE; 
  1292     PR_ATOMIC_DECREMENT(&parallelFnInvocationCount);
  1293     usePKIXValidationEngine = savedUsePkixEngFlag;
  1294 #endif /* PKIX_OBJECT_LEAK_TEST */
  1296     return rv;
  1299 PKIX_CertSelector *
  1300 cert_GetTargetCertConstraints(CERTCertificate *target, void *plContext) 
  1302     PKIX_ComCertSelParams *certSelParams = NULL;
  1303     PKIX_CertSelector *certSelector = NULL;
  1304     PKIX_CertSelector *r= NULL;
  1305     PKIX_PL_Cert *eeCert = NULL;
  1306     PKIX_Error *error = NULL;
  1308     error = PKIX_PL_Cert_CreateFromCERTCertificate(target, &eeCert, plContext);
  1309     if (error != NULL) goto cleanup;
  1311     error = PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext);
  1312     if (error != NULL) goto cleanup;
  1314     error = PKIX_ComCertSelParams_Create(&certSelParams, plContext);
  1315     if (error != NULL) goto cleanup;
  1317     error = PKIX_ComCertSelParams_SetCertificate(
  1318                                 certSelParams, eeCert, plContext);
  1319     if (error != NULL) goto cleanup;
  1321     error = PKIX_CertSelector_SetCommonCertSelectorParams
  1322         (certSelector, certSelParams, plContext);
  1323     if (error != NULL) goto cleanup;
  1325     error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certSelector, plContext);
  1326     if (error == NULL) r = certSelector;
  1328 cleanup:
  1329     if (certSelParams != NULL) 
  1330         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelParams, plContext);
  1332     if (eeCert != NULL) 
  1333         PKIX_PL_Object_DecRef((PKIX_PL_Object *)eeCert, plContext);
  1335     if (certSelector != NULL) 
  1336         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
  1338     if (error != NULL) {
  1339 	SECErrorCodes nssErr;
  1341 	cert_PkixErrorToNssCode(error, &nssErr, plContext);
  1342         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1343 	PORT_SetError(nssErr);
  1346     return r;
  1349 static PKIX_List *
  1350 cert_GetCertStores(void *plContext)
  1352     PKIX_CertStore *certStore = NULL;
  1353     PKIX_List *certStores = NULL;
  1354     PKIX_List *r = NULL;
  1355     PKIX_Error *error = NULL;
  1357     error = PKIX_PL_Pk11CertStore_Create(&certStore, plContext);
  1358     if (error != NULL) goto cleanup;
  1360     error = PKIX_List_Create(&certStores, plContext);
  1361     if (error != NULL)  goto cleanup;
  1363     error = PKIX_List_AppendItem( certStores, 
  1364                           (PKIX_PL_Object *)certStore, plContext);
  1365     if (error != NULL)  goto cleanup;
  1367     error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certStores, plContext);
  1368     if (error == NULL) r = certStores;
  1370 cleanup:
  1371     if (certStores != NULL) 
  1372         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
  1374     if (certStore != NULL) 
  1375         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStore, plContext);
  1377     if (error != NULL) {
  1378 	SECErrorCodes nssErr;
  1380 	cert_PkixErrorToNssCode(error, &nssErr, plContext);
  1381         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1382 	PORT_SetError(nssErr);
  1385     return r;
  1389 struct fake_PKIX_PL_CertStruct {
  1390         CERTCertificate *nssCert;
  1391 };
  1393 /* This needs to be part of the PKIX_PL_* */
  1394 /* This definitely needs to go away, and be replaced with
  1395    a real accessor function in PKIX */
  1396 static CERTCertificate *
  1397 cert_NSSCertFromPKIXCert(const PKIX_PL_Cert *pkix_cert)
  1399     struct fake_PKIX_PL_CertStruct *fcert = NULL;
  1401     fcert = (struct fake_PKIX_PL_CertStruct*)pkix_cert;
  1403     return CERT_DupCertificate(fcert->nssCert);
  1406 PKIX_List *cert_PKIXMakeOIDList(const SECOidTag *oids, int oidCount, void *plContext)
  1408     PKIX_List *r = NULL;
  1409     PKIX_List *policyList = NULL;
  1410     PKIX_PL_OID *policyOID = NULL;
  1411     PKIX_Error *error = NULL;
  1412     int i;
  1414     error = PKIX_List_Create(&policyList, plContext);
  1415     if (error != NULL) {
  1416 	goto cleanup;
  1419     for (i=0; i<oidCount; i++) {
  1420         error = PKIX_PL_OID_Create(oids[i], &policyOID, plContext);
  1421         if (error) {
  1422             goto cleanup;
  1424         error = PKIX_List_AppendItem(policyList, 
  1425                 (PKIX_PL_Object *)policyOID, plContext);
  1426         if (error != NULL) {
  1427             goto cleanup;
  1429         PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
  1430         policyOID = NULL;
  1433     error = PKIX_List_SetImmutable(policyList, plContext);
  1434     if (error != NULL) goto cleanup;
  1436     error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)policyList, plContext);
  1437     if (error == NULL) r = policyList;
  1439 cleanup:
  1440     if (policyOID != NULL)  {
  1441         PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
  1443     if (policyList != NULL)  {
  1444         PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyList, plContext);
  1446     if (error != NULL)  {
  1447         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1450     return r;
  1453 CERTValOutParam *
  1454 cert_pkix_FindOutputParam(CERTValOutParam *params, const CERTValParamOutType t)
  1456     CERTValOutParam *i;
  1457     if (params == NULL) {
  1458         return NULL;
  1460     for (i = params; i->type != cert_po_end; i++) {
  1461         if (i->type == t) {
  1462              return i;
  1465     return NULL;
  1469 static PKIX_Error*
  1470 setRevocationMethod(PKIX_RevocationChecker *revChecker,
  1471                     PKIX_ProcessingParams *procParams,
  1472                     const CERTRevocationTests *revTest,
  1473                     CERTRevocationMethodIndex certRevMethod,
  1474                     PKIX_RevocationMethodType pkixRevMethod,
  1475                     PKIX_Boolean verifyResponderUsages,
  1476                     PKIX_Boolean isLeafTest,
  1477                     void *plContext)
  1479     PKIX_UInt32 methodFlags = 0;
  1480     PKIX_Error *error = NULL;
  1481     int priority = 0;
  1483     if (revTest->number_of_defined_methods <= certRevMethod) {
  1484         return NULL;
  1486     if (revTest->preferred_methods) {
  1487         int i = 0;
  1488         for (;i < revTest->number_of_preferred_methods;i++) {
  1489             if (revTest->preferred_methods[i] == certRevMethod) 
  1490                 break;
  1492         priority = i;
  1494     methodFlags = revTest->cert_rev_flags_per_method[certRevMethod];
  1495     if (verifyResponderUsages &&
  1496         pkixRevMethod == PKIX_RevocationMethod_OCSP) {
  1497         methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING;
  1499     error =
  1500         PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
  1501                                          pkixRevMethod, methodFlags,
  1502                                          priority, NULL,
  1503                                          isLeafTest, plContext);
  1504     return error;
  1508 SECStatus
  1509 cert_pkixSetParam(PKIX_ProcessingParams *procParams, 
  1510   const CERTValInParam *param, void *plContext)
  1512     PKIX_Error * error = NULL;
  1513     SECStatus r=SECSuccess;
  1514     PKIX_PL_Date *date = NULL;
  1515     PKIX_List *policyOIDList = NULL;
  1516     PKIX_List *certListPkix = NULL;
  1517     const CERTRevocationFlags *flags;
  1518     SECErrorCodes errCode = SEC_ERROR_INVALID_ARGS;
  1519     const CERTCertList *certList = NULL;
  1520     CERTCertListNode *node;
  1521     PKIX_PL_Cert *certPkix = NULL;
  1522     PKIX_TrustAnchor *trustAnchor = NULL;
  1523     PKIX_PL_Date *revDate = NULL;
  1524     PKIX_RevocationChecker *revChecker = NULL;
  1525     PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext *)plContext;
  1527     /* XXX we need a way to map generic PKIX error to generic NSS errors */
  1529     switch (param->type) {
  1531         case cert_pi_policyOID:
  1533             /* needed? */
  1534             error = PKIX_ProcessingParams_SetExplicitPolicyRequired(
  1535                                 procParams, PKIX_TRUE, plContext);
  1537             if (error != NULL) { 
  1538                 break;
  1541             policyOIDList = cert_PKIXMakeOIDList(param->value.array.oids,
  1542                                 param->value.arraySize,plContext);
  1543 	    if (policyOIDList == NULL) {
  1544 		r = SECFailure;
  1545 		PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1546 		break;
  1549             error = PKIX_ProcessingParams_SetInitialPolicies(
  1550                                 procParams,policyOIDList,plContext);
  1551             break;
  1553         case cert_pi_date:
  1554             if (param->value.scalar.time == 0) {
  1555                 error = PKIX_PL_Date_Create_UTCTime(NULL, &date, plContext);
  1556                 if (error != NULL) {
  1557                     errCode = SEC_ERROR_INVALID_TIME;
  1558                     break;
  1560             } else {
  1561                 error = pkix_pl_Date_CreateFromPRTime(param->value.scalar.time,
  1562                                                        &date, plContext);
  1563                 if (error != NULL) {
  1564                     errCode = SEC_ERROR_INVALID_TIME;
  1565                     break;
  1569             error = PKIX_ProcessingParams_SetDate(procParams, date, plContext);
  1570             if (error != NULL) {
  1571                 errCode = SEC_ERROR_INVALID_TIME;
  1573             break;
  1575         case cert_pi_revocationFlags:
  1577             PKIX_UInt32 leafIMFlags = 0;
  1578             PKIX_UInt32 chainIMFlags = 0;
  1579             PKIX_Boolean validatingResponderCert = PKIX_FALSE;
  1581             flags = param->value.pointer.revocation;
  1582             if (!flags) {
  1583                 PORT_SetError(errCode);
  1584                 r = SECFailure;
  1585                 break;
  1588             leafIMFlags = 
  1589                 flags->leafTests.cert_rev_method_independent_flags;
  1590             chainIMFlags =
  1591                 flags->chainTests.cert_rev_method_independent_flags;
  1593             error =
  1594                 PKIX_RevocationChecker_Create(leafIMFlags, chainIMFlags,
  1595                                               &revChecker, plContext);
  1596             if (error) {
  1597                 break;
  1600             error =
  1601                 PKIX_ProcessingParams_SetRevocationChecker(procParams,
  1602                                                 revChecker, plContext);
  1603             if (error) {
  1604                 break;
  1607             if (((PKIX_PL_NssContext*)plContext)->certificateUsage &
  1608                 certificateUsageStatusResponder) {
  1609                 validatingResponderCert = PKIX_TRUE;
  1612             error = setRevocationMethod(revChecker,
  1613                                         procParams, &flags->leafTests,
  1614                                         cert_revocation_method_crl,
  1615                                         PKIX_RevocationMethod_CRL,
  1616                                         validatingResponderCert,
  1617                                         PKIX_TRUE, plContext);
  1618             if (error) {
  1619                 break;
  1622             error = setRevocationMethod(revChecker,
  1623                                         procParams, &flags->leafTests,
  1624                                         cert_revocation_method_ocsp,
  1625                                         PKIX_RevocationMethod_OCSP,
  1626                                         validatingResponderCert,
  1627                                         PKIX_TRUE, plContext);
  1628             if (error) {
  1629                 break;
  1632             error = setRevocationMethod(revChecker,
  1633                                         procParams, &flags->chainTests,
  1634                                         cert_revocation_method_crl,
  1635                                         PKIX_RevocationMethod_CRL,
  1636                                         validatingResponderCert,
  1637                                         PKIX_FALSE, plContext);
  1638             if (error) {
  1639                 break;
  1642             error = setRevocationMethod(revChecker,
  1643                                         procParams, &flags->chainTests,
  1644                                         cert_revocation_method_ocsp,
  1645                                         PKIX_RevocationMethod_OCSP,
  1646                                         validatingResponderCert,
  1647                                         PKIX_FALSE, plContext);
  1648             if (error) {
  1649                 break;
  1653         break;
  1655         case cert_pi_trustAnchors:
  1656             certList = param->value.pointer.chain;
  1657             if (!certList) {
  1658                 PORT_SetError(errCode);
  1659                 r = SECFailure;
  1660                 break;
  1662             error = PKIX_List_Create(&certListPkix, plContext);
  1663             if (error != NULL) {
  1664                 break;
  1666             for(node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
  1667                 node = CERT_LIST_NEXT(node) ) {
  1668                 error = PKIX_PL_Cert_CreateFromCERTCertificate(node->cert,
  1669                                                       &certPkix, plContext);
  1670                 if (error) {
  1671                     break;
  1673                 error = PKIX_TrustAnchor_CreateWithCert(certPkix, &trustAnchor,
  1674                                                         plContext);
  1675                 if (error) {
  1676                     break;
  1678                 error = PKIX_List_AppendItem(certListPkix,
  1679                                  (PKIX_PL_Object*)trustAnchor, plContext);
  1680                  if (error) {
  1681                     break;
  1683                 PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
  1684                 trustAnchor = NULL;
  1685                 PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
  1686                 certPkix = NULL;
  1688             error =
  1689                 PKIX_ProcessingParams_SetTrustAnchors(procParams, certListPkix,
  1690                                                       plContext);
  1691             break;
  1693         case cert_pi_useAIACertFetch:
  1694             error =
  1695                 PKIX_ProcessingParams_SetUseAIAForCertFetching(procParams,
  1696                                      (PRBool)(param->value.scalar.b != 0),
  1697                                                                plContext);
  1698             break;
  1700         case cert_pi_chainVerifyCallback:
  1702             const CERTChainVerifyCallback *chainVerifyCallback =
  1703                 param->value.pointer.chainVerifyCallback;
  1704             if (!chainVerifyCallback || !chainVerifyCallback->isChainValid) {
  1705                 PORT_SetError(errCode);
  1706                 r = SECFailure;
  1707                 break;
  1710             nssContext->chainVerifyCallback = *chainVerifyCallback;
  1712         break;
  1714         case cert_pi_useOnlyTrustAnchors:
  1715             error =
  1716                 PKIX_ProcessingParams_SetUseOnlyTrustAnchors(procParams,
  1717                                       (PRBool)(param->value.scalar.b != 0),
  1718                                                              plContext);
  1719             break;
  1721         default:
  1722             PORT_SetError(errCode);
  1723             r = SECFailure;
  1724             break;
  1727     if (policyOIDList != NULL)
  1728         PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOIDList, plContext);
  1730     if (date != NULL) 
  1731         PKIX_PL_Object_DecRef((PKIX_PL_Object *)date, plContext);
  1733     if (revDate != NULL) 
  1734         PKIX_PL_Object_DecRef((PKIX_PL_Object *)revDate, plContext);
  1736     if (revChecker != NULL) 
  1737         PKIX_PL_Object_DecRef((PKIX_PL_Object *)revChecker, plContext);
  1739     if (certListPkix) 
  1740         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certListPkix, plContext);
  1742     if (trustAnchor) 
  1743         PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
  1745     if (certPkix) 
  1746         PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
  1748     if (error != NULL) {
  1749         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1750         PORT_SetError(errCode);
  1751         r = SECFailure;
  1754     return r; 
  1758 void
  1759 cert_pkixDestroyValOutParam(CERTValOutParam *params)
  1761     CERTValOutParam *i;
  1763     if (params == NULL) {
  1764         return;
  1766     for (i = params; i->type != cert_po_end; i++) {
  1767         switch (i->type) {
  1768         case cert_po_trustAnchor:
  1769             if (i->value.pointer.cert) {
  1770                 CERT_DestroyCertificate(i->value.pointer.cert);
  1771                 i->value.pointer.cert = NULL;
  1773             break;
  1775         case cert_po_certList:
  1776             if (i->value.pointer.chain) {
  1777                 CERT_DestroyCertList(i->value.pointer.chain);
  1778                 i->value.pointer.chain = NULL;
  1780             break;
  1782         default:
  1783             break;
  1788 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags[2] = {
  1789   /* crl */
  1790   CERT_REV_M_TEST_USING_THIS_METHOD 
  1791   | CERT_REV_M_FORBID_NETWORK_FETCHING
  1792   | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1793   /* ocsp */
  1794   CERT_REV_M_TEST_USING_THIS_METHOD
  1795 };
  1797 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags[2] = {
  1798   /* crl */
  1799   CERT_REV_M_TEST_USING_THIS_METHOD
  1800   | CERT_REV_M_FORBID_NETWORK_FETCHING
  1801   | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1802   /* ocsp */
  1804 };
  1806 static CERTRevocationMethodIndex 
  1807 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference = {
  1808   cert_revocation_method_crl
  1809 };
  1811 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy = {
  1813     /* leafTests */
  1814     2,
  1815     certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags,
  1816     1,
  1817     &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference,
  1819   },
  1821     /* chainTests */
  1822     2,
  1823     certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags,
  1824     0,
  1825     0,
  1828 };
  1830 extern const CERTRevocationFlags*
  1831 CERT_GetClassicOCSPEnabledSoftFailurePolicy()
  1833     return &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy;
  1837 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
  1838   /* crl */
  1839   CERT_REV_M_TEST_USING_THIS_METHOD 
  1840   | CERT_REV_M_FORBID_NETWORK_FETCHING
  1841   | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1842   /* ocsp */
  1843   CERT_REV_M_TEST_USING_THIS_METHOD
  1844   | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
  1845 };
  1847 static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
  1848   /* crl */
  1849   CERT_REV_M_TEST_USING_THIS_METHOD
  1850   | CERT_REV_M_FORBID_NETWORK_FETCHING
  1851   | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1852   /* ocsp */
  1854 };
  1856 static CERTRevocationMethodIndex 
  1857 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference = {
  1858   cert_revocation_method_crl
  1859 };
  1861 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy = {
  1863     /* leafTests */
  1864     2,
  1865     certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags,
  1866     1,
  1867     &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference,
  1869   },
  1871     /* chainTests */
  1872     2,
  1873     certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags,
  1874     0,
  1875     0,
  1878 };
  1880 extern const CERTRevocationFlags*
  1881 CERT_GetClassicOCSPEnabledHardFailurePolicy()
  1883     return &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy;
  1887 static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags[2] = {
  1888   /* crl */
  1889   CERT_REV_M_TEST_USING_THIS_METHOD
  1890   | CERT_REV_M_FORBID_NETWORK_FETCHING
  1891   | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1892   /* ocsp */
  1894 };
  1896 static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags[2] = {
  1897   /* crl */
  1898   CERT_REV_M_TEST_USING_THIS_METHOD
  1899   | CERT_REV_M_FORBID_NETWORK_FETCHING
  1900   | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1901   /* ocsp */
  1903 };
  1905 static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Disabled_Policy = {
  1907     /* leafTests */
  1908     2,
  1909     certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags,
  1910     0,
  1911     0,
  1913   },
  1915     /* chainTests */
  1916     2,
  1917     certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags,
  1918     0,
  1919     0,
  1922 };
  1924 extern const CERTRevocationFlags*
  1925 CERT_GetClassicOCSPDisabledPolicy()
  1927     return &certRev_NSS_3_11_Ocsp_Disabled_Policy;
  1931 static PRUint64 certRev_PKIX_Verify_Nist_Policy_LeafFlags[2] = {
  1932   /* crl */
  1933   CERT_REV_M_TEST_USING_THIS_METHOD
  1934   | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
  1935   | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
  1936   /* ocsp */
  1938 };
  1940 static PRUint64 certRev_PKIX_Verify_Nist_Policy_ChainFlags[2] = {
  1941   /* crl */
  1942   CERT_REV_M_TEST_USING_THIS_METHOD
  1943   | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
  1944   | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
  1945   /* ocsp */
  1947 };
  1949 static const CERTRevocationFlags certRev_PKIX_Verify_Nist_Policy = {
  1951     /* leafTests */
  1952     2,
  1953     certRev_PKIX_Verify_Nist_Policy_LeafFlags,
  1954     0,
  1955     0,
  1957   },
  1959     /* chainTests */
  1960     2,
  1961     certRev_PKIX_Verify_Nist_Policy_ChainFlags,
  1962     0,
  1963     0,
  1966 };
  1968 extern const CERTRevocationFlags*
  1969 CERT_GetPKIXVerifyNistRevocationPolicy()
  1971     return &certRev_PKIX_Verify_Nist_Policy;
  1974 CERTRevocationFlags *
  1975 CERT_AllocCERTRevocationFlags(
  1976     PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods,
  1977     PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods)
  1979     CERTRevocationFlags *flags;
  1981     flags = PORT_New(CERTRevocationFlags);
  1982     if (!flags)
  1983         return(NULL);
  1985     flags->leafTests.number_of_defined_methods = number_leaf_methods;
  1986     flags->leafTests.cert_rev_flags_per_method = 
  1987         PORT_NewArray(PRUint64, number_leaf_methods);
  1989     flags->leafTests.number_of_preferred_methods = number_leaf_pref_methods;
  1990     flags->leafTests.preferred_methods = 
  1991         PORT_NewArray(CERTRevocationMethodIndex, number_leaf_pref_methods);
  1993     flags->chainTests.number_of_defined_methods = number_chain_methods;
  1994     flags->chainTests.cert_rev_flags_per_method = 
  1995         PORT_NewArray(PRUint64, number_chain_methods);
  1997     flags->chainTests.number_of_preferred_methods = number_chain_pref_methods;
  1998     flags->chainTests.preferred_methods = 
  1999         PORT_NewArray(CERTRevocationMethodIndex, number_chain_pref_methods);
  2001     if (!flags->leafTests.cert_rev_flags_per_method
  2002         || !flags->leafTests.preferred_methods
  2003         || !flags->chainTests.cert_rev_flags_per_method
  2004         || !flags->chainTests.preferred_methods) {
  2005         CERT_DestroyCERTRevocationFlags(flags);
  2006         return (NULL);
  2009     return flags;
  2012 void CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags)
  2014     if (!flags)
  2015 	return;
  2017     if (flags->leafTests.cert_rev_flags_per_method)
  2018         PORT_Free(flags->leafTests.cert_rev_flags_per_method);
  2020     if (flags->leafTests.preferred_methods)
  2021         PORT_Free(flags->leafTests.preferred_methods);
  2023     if (flags->chainTests.cert_rev_flags_per_method)
  2024         PORT_Free(flags->chainTests.cert_rev_flags_per_method);
  2026     if (flags->chainTests.preferred_methods)
  2027         PORT_Free(flags->chainTests.preferred_methods);
  2029      PORT_Free(flags);
  2032 /*
  2033  * CERT_PKIXVerifyCert
  2035  * Verify a Certificate using the PKIX library.
  2037  * Parameters:
  2038  *  cert    - the target certificate to verify. Must be non-null
  2039  *  params  - an array of type/value parameters which can be
  2040  *            used to modify the behavior of the validation
  2041  *            algorithm, or supply additional constraints.
  2043  *  outputTrustAnchor - the trust anchor which the certificate
  2044  *                      chains to. The caller is responsible
  2045  *                      for freeing this.
  2047  * Example Usage:
  2048  *    CERTValParam args[3];
  2049  *    args[0].type = cvpt_policyOID;
  2050  *    args[0].value.si = oid;
  2051  *    args[1].type = revCheckRequired;
  2052  *    args[1].value.b = PR_TRUE;
  2053  *    args[2].type = cvpt_end;
  2055  *    CERT_PKIXVerifyCert(cert, &output, args
  2056  */
  2057 SECStatus CERT_PKIXVerifyCert(
  2058  CERTCertificate *cert,
  2059  SECCertificateUsage usages,
  2060  CERTValInParam *paramsIn,
  2061  CERTValOutParam *paramsOut,
  2062  void *wincx)
  2064     SECStatus             r = SECFailure;
  2065     PKIX_Error *          error = NULL;
  2066     PKIX_ProcessingParams *procParams = NULL;
  2067     PKIX_BuildResult *    buildResult = NULL;
  2068     void *                nbioContext = NULL;  /* for non-blocking IO */
  2069     void *                buildState = NULL;   /* for non-blocking IO */
  2070     PKIX_CertSelector *   certSelector = NULL;
  2071     PKIX_List *           certStores = NULL;
  2072     PKIX_ValidateResult * valResult = NULL;
  2073     PKIX_VerifyNode     * verifyNode = NULL;
  2074     PKIX_TrustAnchor *    trustAnchor = NULL;
  2075     PKIX_PL_Cert *        trustAnchorCert = NULL;
  2076     PKIX_List *           builtCertList = NULL;
  2077     CERTValOutParam *     oparam = NULL;
  2078     int i=0;
  2080     void *plContext = NULL;
  2082 #ifdef PKIX_OBJECT_LEAK_TEST
  2083     int  leakedObjNum = 0;
  2084     int  memLeakLoopCount = 0;
  2085     int  objCountTable[PKIX_NUMTYPES];
  2086     int  fnInvLocalCount = 0;
  2087     PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
  2089     if (usePKIXValidationEngine) {
  2090         /* current memory leak testing implementation does not allow
  2091          * to run simultaneous tests one the same or a different threads.
  2092          * Setting the variable to false, to make additional chain
  2093          * validations be handled by old nss. */
  2094         usePKIXValidationEngine = PR_FALSE;
  2096     testStartFnStackPosition = 1;
  2097     fnStackNameArr[0] = "CERT_PKIXVerifyCert";
  2098     fnStackInvCountArr[0] = 0;
  2099     PKIX_Boolean abortOnLeak = 
  2100         (PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ?
  2101                                                    PKIX_FALSE : PKIX_TRUE;
  2102     runningLeakTest = PKIX_TRUE;
  2104     /* Prevent multi-threaded run of object leak test */
  2105     fnInvLocalCount = PR_ATOMIC_INCREMENT(&parallelFnInvocationCount);
  2106     PORT_Assert(fnInvLocalCount == 1);
  2108 do {
  2109     r = SECFailure;
  2110     error = NULL;
  2111     procParams = NULL;
  2112     buildResult = NULL;
  2113     nbioContext = NULL;  /* for non-blocking IO */
  2114     buildState = NULL;   /* for non-blocking IO */
  2115     certSelector = NULL;
  2116     certStores = NULL;
  2117     valResult = NULL;
  2118     verifyNode = NULL;
  2119     trustAnchor = NULL;
  2120     trustAnchorCert = NULL;
  2121     builtCertList = NULL;
  2122     oparam = NULL;
  2123     i=0;
  2124     errorGenerated = PKIX_FALSE;
  2125     stackPosition = 0;
  2127     if (leakedObjNum) {
  2128         pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
  2130     memLeakLoopCount += 1;
  2131 #endif /* PKIX_OBJECT_LEAK_TEST */
  2133     error = PKIX_PL_NssContext_Create(
  2134             0, PR_FALSE /*use arena*/, wincx, &plContext);
  2135     if (error != NULL) {        /* need pkix->nss error map */
  2136         PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
  2137         goto cleanup;
  2140     error = pkix_pl_NssContext_SetCertUsage(usages, plContext);
  2141     if (error != NULL) {
  2142         PORT_SetError(SEC_ERROR_INVALID_ARGS);
  2143         goto cleanup;
  2146     error = PKIX_ProcessingParams_Create(&procParams, plContext);
  2147     if (error != NULL) {              /* need pkix->nss error map */
  2148         PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
  2149         goto cleanup;
  2152     /* local cert store should be set into procParams before
  2153      * filling in revocation settings. */
  2154     certStores = cert_GetCertStores(plContext);
  2155     if (certStores == NULL) {
  2156         goto cleanup;
  2158     error = PKIX_ProcessingParams_SetCertStores
  2159         (procParams, certStores, plContext);
  2160     if (error != NULL) {
  2161         goto cleanup;
  2164     /* now process the extensible input parameters structure */
  2165     if (paramsIn != NULL) {
  2166         i=0;
  2167         while (paramsIn[i].type != cert_pi_end) {
  2168             if (paramsIn[i].type >= cert_pi_max) {
  2169                 PORT_SetError(SEC_ERROR_INVALID_ARGS);
  2170                 goto cleanup;
  2172             if (cert_pkixSetParam(procParams,
  2173                      &paramsIn[i],plContext) != SECSuccess) {
  2174                 PORT_SetError(SEC_ERROR_INVALID_ARGS);
  2175                 goto cleanup;
  2177             i++;
  2181     certSelector = cert_GetTargetCertConstraints(cert, plContext);
  2182     if (certSelector == NULL) {
  2183         goto cleanup;
  2185     error = PKIX_ProcessingParams_SetTargetCertConstraints
  2186         (procParams, certSelector, plContext);
  2187     if (error != NULL) {
  2188         goto cleanup;
  2191     error = PKIX_BuildChain( procParams, &nbioContext,
  2192                              &buildState, &buildResult, &verifyNode,
  2193                              plContext);
  2194     if (error != NULL) {
  2195         goto cleanup;
  2198     error = PKIX_BuildResult_GetValidateResult( buildResult, &valResult,
  2199                                                 plContext);
  2200     if (error != NULL) {
  2201         goto cleanup;
  2204     error = PKIX_ValidateResult_GetTrustAnchor( valResult, &trustAnchor,
  2205                                                 plContext);
  2206     if (error != NULL) {
  2207         goto cleanup;
  2210     if (trustAnchor != NULL) {
  2211         error = PKIX_TrustAnchor_GetTrustedCert( trustAnchor, &trustAnchorCert,
  2212                                                  plContext);
  2213         if (error != NULL) {
  2214             goto cleanup;
  2218 #ifdef PKIX_OBJECT_LEAK_TEST
  2219     /* Can not continue if error was generated but not returned.
  2220      * Jumping to cleanup. */
  2221     if (errorGenerated) goto cleanup;
  2222 #endif /* PKIX_OBJECT_LEAK_TEST */
  2224     oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor);
  2225     if (oparam != NULL) {
  2226         if (trustAnchorCert != NULL) {
  2227             oparam->value.pointer.cert =
  2228                     cert_NSSCertFromPKIXCert(trustAnchorCert);
  2229         } else {
  2230             oparam->value.pointer.cert = NULL;
  2234     error = PKIX_BuildResult_GetCertChain( buildResult, &builtCertList,
  2235                                                 plContext);
  2236     if (error != NULL) {
  2237         goto cleanup;
  2240     oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_certList);
  2241     if (oparam != NULL) {
  2242         error = cert_PkixToNssCertsChain(builtCertList,
  2243                                          &oparam->value.pointer.chain,
  2244                                          plContext);
  2245         if (error) goto cleanup;
  2248     r = SECSuccess;
  2250 cleanup:
  2251     if (verifyNode) {
  2252         /* Return validation log only upon error. */
  2253         oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_errorLog);
  2254 #ifdef PKIX_OBJECT_LEAK_TEST
  2255         if (!errorGenerated)
  2256 #endif /* PKIX_OBJECT_LEAK_TEST */
  2257         if (r && oparam != NULL) {
  2258             PKIX_Error *tmpError =
  2259                 cert_GetLogFromVerifyNode(oparam->value.pointer.log,
  2260                                           verifyNode, plContext);
  2261             if (tmpError) {
  2262                 PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
  2265         PKIX_PL_Object_DecRef((PKIX_PL_Object *)verifyNode, plContext);
  2268     if (procParams != NULL) 
  2269        PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
  2271     if (trustAnchorCert != NULL) 
  2272        PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchorCert, plContext);
  2274     if (trustAnchor != NULL) 
  2275        PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
  2277     if (valResult != NULL) 
  2278        PKIX_PL_Object_DecRef((PKIX_PL_Object *)valResult, plContext);
  2280     if (buildResult != NULL) 
  2281        PKIX_PL_Object_DecRef((PKIX_PL_Object *)buildResult, plContext);
  2283     if (certStores != NULL) 
  2284        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
  2286     if (certSelector != NULL) 
  2287        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
  2289     if (builtCertList != NULL) 
  2290        PKIX_PL_Object_DecRef((PKIX_PL_Object *)builtCertList, plContext);
  2292     if (error != NULL) {
  2293         SECErrorCodes         nssErrorCode = 0;
  2295         cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
  2296         cert_pkixDestroyValOutParam(paramsOut);
  2297         PORT_SetError(nssErrorCode);
  2298         PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  2301     PKIX_PL_NssContext_Destroy(plContext);
  2303 #ifdef PKIX_OBJECT_LEAK_TEST
  2304     leakedObjNum =
  2305         pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
  2307     if (pkixLog && leakedObjNum) {
  2308         PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
  2309                             "Stack %s\n", memLeakLoopCount, errorFnStackString));
  2311     PR_Free(errorFnStackString);
  2312     errorFnStackString = NULL;
  2313     if (abortOnLeak) {
  2314         PORT_Assert(leakedObjNum == 0);
  2317 } while (errorGenerated);
  2319     runningLeakTest = PKIX_FALSE; 
  2320     PR_ATOMIC_DECREMENT(&parallelFnInvocationCount);
  2321     usePKIXValidationEngine = savedUsePkixEngFlag;
  2322 #endif /* PKIX_OBJECT_LEAK_TEST */
  2324     return r;

mercurial