tor-browser

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

certvfypkix.c (72061B)


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