security/nss/lib/certhigh/certvfypkix.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/certhigh/certvfypkix.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2325 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +/*
     1.8 + * nss_pkix_proxy.h
     1.9 + *
    1.10 + * PKIX - NSS proxy functions
    1.11 + *
    1.12 + * NOTE: All structures, functions, data types are parts of library private
    1.13 + * api and are subjects to change in any following releases.
    1.14 + *
    1.15 + */
    1.16 +#include "prerror.h"
    1.17 +#include "prprf.h"
    1.18 + 
    1.19 +#include "nspr.h"
    1.20 +#include "pk11func.h"
    1.21 +#include "certdb.h"
    1.22 +#include "cert.h"
    1.23 +#include "secerr.h"
    1.24 +#include "nssb64.h"
    1.25 +#include "secasn1.h"
    1.26 +#include "secder.h"
    1.27 +#include "pkit.h"
    1.28 +
    1.29 +#include "pkix_pl_common.h"
    1.30 +
    1.31 +extern PRLogModuleInfo *pkixLog;
    1.32 +
    1.33 +#ifdef DEBUG_volkov
    1.34 +/* Temporary declarations of functioins. Will be removed with fix for
    1.35 + * 391183 */
    1.36 +extern char *
    1.37 +pkix_Error2ASCII(PKIX_Error *error, void *plContext);
    1.38 +
    1.39 +extern void
    1.40 +cert_PrintCert(PKIX_PL_Cert *pkixCert, void *plContext);
    1.41 +
    1.42 +extern PKIX_Error *
    1.43 +cert_PrintCertChain(PKIX_List *pkixCertChain, void *plContext);
    1.44 +
    1.45 +#endif /* DEBUG */
    1.46 +
    1.47 +#ifdef PKIX_OBJECT_LEAK_TEST
    1.48 +
    1.49 +extern PKIX_UInt32
    1.50 +pkix_pl_lifecycle_ObjectLeakCheck(int *);
    1.51 +
    1.52 +extern SECStatus
    1.53 +pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable);
    1.54 +
    1.55 +PRInt32 parallelFnInvocationCount;
    1.56 +#endif /* PKIX_OBJECT_LEAK_TEST */
    1.57 +
    1.58 +
    1.59 +static PRBool usePKIXValidationEngine = PR_FALSE;
    1.60 +
    1.61 +/*
    1.62 + * FUNCTION: CERT_SetUsePKIXForValidation
    1.63 + * DESCRIPTION:
    1.64 + *
    1.65 + * Enables or disables use of libpkix for certificate validation
    1.66 + *
    1.67 + * PARAMETERS:
    1.68 + *  "enable"
    1.69 + *      PR_TRUE: enables use of libpkix for cert validation.
    1.70 + *      PR_FALSE: disables.
    1.71 + * THREAD SAFETY:
    1.72 + *  NOT Thread Safe.
    1.73 + * RETURNS:
    1.74 + *  Returns SECSuccess if successfully enabled
    1.75 + */
    1.76 +SECStatus
    1.77 +CERT_SetUsePKIXForValidation(PRBool enable)
    1.78 +{
    1.79 +    usePKIXValidationEngine = (enable > 0) ? PR_TRUE : PR_FALSE;
    1.80 +    return SECSuccess;
    1.81 +}
    1.82 +
    1.83 +/*
    1.84 + * FUNCTION: CERT_GetUsePKIXForValidation
    1.85 + * DESCRIPTION:
    1.86 + *
    1.87 + * Checks if libpkix building function should be use for certificate
    1.88 + * chain building.
    1.89 + *
    1.90 + * PARAMETERS:
    1.91 + *  NONE
    1.92 + * THREAD SAFETY:
    1.93 + *  NOT Thread Safe
    1.94 + * RETURNS:
    1.95 + *  Returns PR_TRUE if libpkix should be used. PR_FALSE otherwise.
    1.96 + */
    1.97 +PRBool
    1.98 +CERT_GetUsePKIXForValidation()
    1.99 +{
   1.100 +    return usePKIXValidationEngine;
   1.101 +}
   1.102 +
   1.103 +#ifdef NOTDEF
   1.104 +/*
   1.105 + * FUNCTION: cert_NssKeyUsagesToPkix
   1.106 + * DESCRIPTION:
   1.107 + *
   1.108 + * Converts nss key usage bit field(PRUint32) to pkix key usage
   1.109 + * bit field.
   1.110 + *
   1.111 + * PARAMETERS:
   1.112 + *  "nssKeyUsage"
   1.113 + *      Nss key usage bit field.
   1.114 + *  "pkixKeyUsage"
   1.115 + *      Pkix key usage big field.
   1.116 + *  "plContext"
   1.117 + *      Platform-specific context pointer.
   1.118 + * THREAD SAFETY:
   1.119 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.120 + * RETURNS:
   1.121 + *  Returns NULL if the function succeeds.
   1.122 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.123 + */
   1.124 +static PKIX_Error*
   1.125 +cert_NssKeyUsagesToPkix(
   1.126 +    PRUint32 nssKeyUsage,
   1.127 +    PKIX_UInt32 *pPkixKeyUsage,
   1.128 +    void *plContext)
   1.129 +{
   1.130 +    PKIX_UInt32 pkixKeyUsage = 0;
   1.131 +
   1.132 +    PKIX_ENTER(CERTVFYPKIX, "cert_NssKeyUsagesToPkix");
   1.133 +    PKIX_NULLCHECK_ONE(pPkixKeyUsage);
   1.134 +
   1.135 +    *pPkixKeyUsage = 0;
   1.136 +
   1.137 +    if (nssKeyUsage & KU_DIGITAL_SIGNATURE) {
   1.138 +        pkixKeyUsage |= PKIX_DIGITAL_SIGNATURE;
   1.139 +    }
   1.140 +    
   1.141 +    if (nssKeyUsage & KU_NON_REPUDIATION) {
   1.142 +        pkixKeyUsage |= PKIX_NON_REPUDIATION;
   1.143 +    }
   1.144 +
   1.145 +    if (nssKeyUsage & KU_KEY_ENCIPHERMENT) {
   1.146 +        pkixKeyUsage |= PKIX_KEY_ENCIPHERMENT;
   1.147 +    }
   1.148 +    
   1.149 +    if (nssKeyUsage & KU_DATA_ENCIPHERMENT) {
   1.150 +        pkixKeyUsage |= PKIX_DATA_ENCIPHERMENT;
   1.151 +    }
   1.152 +    
   1.153 +    if (nssKeyUsage & KU_KEY_AGREEMENT) {
   1.154 +        pkixKeyUsage |= PKIX_KEY_AGREEMENT;
   1.155 +    }
   1.156 +    
   1.157 +    if (nssKeyUsage & KU_KEY_CERT_SIGN) {
   1.158 +        pkixKeyUsage |= PKIX_KEY_CERT_SIGN;
   1.159 +    }
   1.160 +    
   1.161 +    if (nssKeyUsage & KU_CRL_SIGN) {
   1.162 +        pkixKeyUsage |= PKIX_CRL_SIGN;
   1.163 +    }
   1.164 +
   1.165 +    if (nssKeyUsage & KU_ENCIPHER_ONLY) {
   1.166 +        pkixKeyUsage |= PKIX_ENCIPHER_ONLY;
   1.167 +    }
   1.168 +    
   1.169 +    /* Not supported. XXX we should support this once it is
   1.170 +     * fixed in NSS */
   1.171 +    /* pkixKeyUsage |= PKIX_DECIPHER_ONLY; */
   1.172 +
   1.173 +    *pPkixKeyUsage = pkixKeyUsage;
   1.174 +
   1.175 +    PKIX_RETURN(CERTVFYPKIX);
   1.176 +}
   1.177 +
   1.178 +extern SECOidTag ekuOidStrings[];
   1.179 +
   1.180 +enum {
   1.181 +    ekuIndexSSLServer = 0,
   1.182 +    ekuIndexSSLClient,
   1.183 +    ekuIndexCodeSigner,
   1.184 +    ekuIndexEmail,
   1.185 +    ekuIndexTimeStamp,
   1.186 +    ekuIndexStatusResponder,
   1.187 +    ekuIndexUnknown
   1.188 +} ekuIndex;
   1.189 +
   1.190 +typedef struct {
   1.191 +    SECCertUsage certUsage;
   1.192 +    PRUint32 ekuStringIndex;
   1.193 +} SECCertUsageToEku;
   1.194 +
   1.195 +const SECCertUsageToEku certUsageEkuStringMap[] = {
   1.196 +    {certUsageSSLClient,             ekuIndexSSLClient},
   1.197 +    {certUsageSSLServer,             ekuIndexSSLServer},
   1.198 +    {certUsageSSLCA,                 ekuIndexSSLServer},
   1.199 +    {certUsageEmailSigner,           ekuIndexEmail},
   1.200 +    {certUsageEmailRecipient,        ekuIndexEmail},
   1.201 +    {certUsageObjectSigner,          ekuIndexCodeSigner},
   1.202 +    {certUsageUserCertImport,        ekuIndexUnknown},
   1.203 +    {certUsageVerifyCA,              ekuIndexUnknown},
   1.204 +    {certUsageProtectedObjectSigner, ekuIndexUnknown},
   1.205 +    {certUsageStatusResponder,       ekuIndexStatusResponder},
   1.206 +    {certUsageAnyCA,                 ekuIndexUnknown},
   1.207 +};
   1.208 +
   1.209 +/*
   1.210 + * FUNCTION: cert_NssCertificateUsageToPkixKUAndEKU
   1.211 + * DESCRIPTION:
   1.212 + *
   1.213 + * Converts nss CERTCertificateUsage bit field to pkix key and
   1.214 + * extended key usages.
   1.215 + *
   1.216 + * PARAMETERS:
   1.217 + *  "cert"
   1.218 + *      Pointer to CERTCertificate structure of validating cert.
   1.219 + *  "requiredCertUsages"
   1.220 + *      Required usage that will be converted to pkix eku and ku. 
   1.221 + *  "requiredKeyUsage",
   1.222 + *      Additional key usages impose to cert.
   1.223 + *  "isCA",
   1.224 + *      it true, convert usages for cert that is a CA cert.  
   1.225 + *  "ppkixEKUList"
   1.226 + *      Returned address of a list of pkix extended key usages.
   1.227 + *  "ppkixKU"
   1.228 + *      Returned address of pkix required key usages bit field. 
   1.229 + *  "plContext"
   1.230 + *      Platform-specific context pointer.
   1.231 + * THREAD SAFETY:
   1.232 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.233 + * RETURNS:
   1.234 + *  Returns NULL if the function succeeds.
   1.235 + *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   1.236 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.237 + */
   1.238 +static PKIX_Error*
   1.239 +cert_NssCertificateUsageToPkixKUAndEKU(
   1.240 +    CERTCertificate *cert,
   1.241 +    SECCertUsage     requiredCertUsage,
   1.242 +    PRUint32         requiredKeyUsages,
   1.243 +    PRBool           isCA,
   1.244 +    PKIX_List      **ppkixEKUList,
   1.245 +    PKIX_UInt32     *ppkixKU,
   1.246 +    void            *plContext)
   1.247 +{
   1.248 +    PKIX_List           *ekuOidsList = NULL;
   1.249 +    PKIX_PL_OID         *ekuOid = NULL;
   1.250 +    int                  i = 0;
   1.251 +    int                  ekuIndex = ekuIndexUnknown;
   1.252 +
   1.253 +    PKIX_ENTER(CERTVFYPKIX, "cert_NssCertificateUsageToPkixEku");
   1.254 +    PKIX_NULLCHECK_TWO(ppkixEKUList, ppkixKU);
   1.255 +    
   1.256 +    PKIX_CHECK(
   1.257 +        PKIX_List_Create(&ekuOidsList, plContext),
   1.258 +        PKIX_LISTCREATEFAILED);
   1.259 +
   1.260 +    for (;i < PR_ARRAY_SIZE(certUsageEkuStringMap);i++) {
   1.261 +        const SECCertUsageToEku *usageToEkuElem =
   1.262 +            &certUsageEkuStringMap[i];
   1.263 +        if (usageToEkuElem->certUsage == requiredCertUsage) {
   1.264 +            ekuIndex = usageToEkuElem->ekuStringIndex;
   1.265 +            break;
   1.266 +        }
   1.267 +    }
   1.268 +    if (ekuIndex != ekuIndexUnknown) {
   1.269 +        PRUint32             reqKeyUsage = 0;
   1.270 +        PRUint32             reqCertType = 0;
   1.271 +
   1.272 +        CERT_KeyUsageAndTypeForCertUsage(requiredCertUsage, isCA,
   1.273 +                                         &reqKeyUsage,
   1.274 +                                         &reqCertType);
   1.275 +        
   1.276 +        requiredKeyUsages |= reqKeyUsage;
   1.277 +        
   1.278 +        PKIX_CHECK(
   1.279 +            PKIX_PL_OID_Create(ekuOidStrings[ekuIndex], &ekuOid,
   1.280 +                               plContext),
   1.281 +            PKIX_OIDCREATEFAILED);
   1.282 +        
   1.283 +        PKIX_CHECK(
   1.284 +            PKIX_List_AppendItem(ekuOidsList, (PKIX_PL_Object *)ekuOid,
   1.285 +                                 plContext),
   1.286 +            PKIX_LISTAPPENDITEMFAILED);
   1.287 +        
   1.288 +        PKIX_DECREF(ekuOid);
   1.289 +    }
   1.290 +
   1.291 +    PKIX_CHECK(
   1.292 +        cert_NssKeyUsagesToPkix(requiredKeyUsages, ppkixKU, plContext),
   1.293 +        PKIX_NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED);
   1.294 +
   1.295 +    *ppkixEKUList = ekuOidsList;
   1.296 +    ekuOidsList = NULL;
   1.297 +
   1.298 +cleanup:
   1.299 +    
   1.300 +    PKIX_DECREF(ekuOid);
   1.301 +    PKIX_DECREF(ekuOidsList);
   1.302 +
   1.303 +    PKIX_RETURN(CERTVFYPKIX);
   1.304 +}
   1.305 +
   1.306 +#endif
   1.307 +
   1.308 +/*
   1.309 + * FUNCTION: cert_ProcessingParamsSetKeyAndCertUsage
   1.310 + * DESCRIPTION:
   1.311 + *
   1.312 + * Converts cert usage to pkix KU type and sets
   1.313 + * converted data into PKIX_ProcessingParams object. It also sets
   1.314 + * proper cert usage into nsscontext object.
   1.315 + *
   1.316 + * PARAMETERS:
   1.317 + *  "procParams"
   1.318 + *      Pointer to PKIX_ProcessingParams used during validation.
   1.319 + *  "requiredCertUsage"
   1.320 + *      Required certificate usages the certificate and chain is built and
   1.321 + *      validated for.
   1.322 + *  "requiredKeyUsage"
   1.323 + *      Request additional key usages the certificate should be validated for.
   1.324 + *  "plContext"
   1.325 + *      Platform-specific context pointer.
   1.326 + * THREAD SAFETY:
   1.327 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.328 + * RETURNS:
   1.329 + *  Returns NULL if the function succeeds.
   1.330 + *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   1.331 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.332 + */
   1.333 +static PKIX_Error*
   1.334 +cert_ProcessingParamsSetKeyAndCertUsage(
   1.335 +    PKIX_ProcessingParams *procParams,
   1.336 +    SECCertUsage           requiredCertUsage,
   1.337 +    PRUint32               requiredKeyUsages,
   1.338 +    void                  *plContext)
   1.339 +{
   1.340 +    PKIX_CertSelector     *certSelector = NULL;
   1.341 +    PKIX_ComCertSelParams *certSelParams = NULL;
   1.342 +    PKIX_PL_NssContext    *nssContext = (PKIX_PL_NssContext*)plContext;
   1.343 + 
   1.344 +    PKIX_ENTER(CERTVFYPKIX, "cert_ProcessingParamsSetKeyAndCertUsage");
   1.345 +    PKIX_NULLCHECK_TWO(procParams, nssContext);
   1.346 +    
   1.347 +    PKIX_CHECK(
   1.348 +        pkix_pl_NssContext_SetCertUsage(
   1.349 +	    ((SECCertificateUsage)1) << requiredCertUsage, nssContext),
   1.350 +	    PKIX_NSSCONTEXTSETCERTUSAGEFAILED);
   1.351 +
   1.352 +    if (requiredKeyUsages) {
   1.353 +        PKIX_CHECK(
   1.354 +            PKIX_ProcessingParams_GetTargetCertConstraints(procParams,
   1.355 +                                                           &certSelector, plContext),
   1.356 +            PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
   1.357 +        
   1.358 +        PKIX_CHECK(
   1.359 +            PKIX_CertSelector_GetCommonCertSelectorParams(certSelector,
   1.360 +                                                          &certSelParams, plContext),
   1.361 +            PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
   1.362 +        
   1.363 +        
   1.364 +        PKIX_CHECK(
   1.365 +            PKIX_ComCertSelParams_SetKeyUsage(certSelParams, requiredKeyUsages,
   1.366 +                                              plContext),
   1.367 +            PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED);
   1.368 +    }
   1.369 +cleanup:
   1.370 +    PKIX_DECREF(certSelector);
   1.371 +    PKIX_DECREF(certSelParams);
   1.372 +
   1.373 +    PKIX_RETURN(CERTVFYPKIX);
   1.374 +}
   1.375 +
   1.376 +/*
   1.377 + * Unused parameters: 
   1.378 + *
   1.379 + *  CERTCertList *initialChain,
   1.380 + *  CERTCertStores certStores,
   1.381 + *  CERTCertRevCheckers certRevCheckers,
   1.382 + *  CERTCertChainCheckers certChainCheckers,
   1.383 + *  SECItem *initPolicies,
   1.384 + *  PRBool policyQualifierRejected,
   1.385 + *  PRBool anyPolicyInhibited,
   1.386 + *  PRBool reqExplicitPolicy,
   1.387 + *  PRBool policyMappingInhibited,
   1.388 + *  PKIX_CertSelector certConstraints,
   1.389 + */
   1.390 +
   1.391 +/*
   1.392 + * FUNCTION: cert_CreatePkixProcessingParams
   1.393 + * DESCRIPTION:
   1.394 + *
   1.395 + * Creates and fills in PKIX_ProcessingParams structure to be used
   1.396 + * for certificate chain building.
   1.397 + *
   1.398 + * PARAMETERS:
   1.399 + *  "cert"
   1.400 + *      Pointer to the CERTCertificate: the leaf certificate of a chain.
   1.401 + *  "time"
   1.402 + *      Validity time.
   1.403 + *  "wincx"
   1.404 + *      Nss db password token.
   1.405 + *  "useArena"
   1.406 + *      Flags to use arena for data allocation during chain building process.
   1.407 + *  "pprocParams"
   1.408 + *      Address to return created processing parameters.
   1.409 + *  "plContext"
   1.410 + *      Platform-specific context pointer.
   1.411 + * THREAD SAFETY:
   1.412 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.413 + * RETURNS:
   1.414 + *  Returns NULL if the function succeeds.
   1.415 + *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   1.416 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.417 + */
   1.418 +static PKIX_Error*
   1.419 +cert_CreatePkixProcessingParams(
   1.420 +    CERTCertificate        *cert,
   1.421 +    PRBool                  checkSig, /* not used yet. See bug 391476 */
   1.422 +    PRTime                  time,
   1.423 +    void                   *wincx,
   1.424 +    PRBool                  useArena,
   1.425 +    PRBool                  disableOCSPRemoteFetching,
   1.426 +    PKIX_ProcessingParams **pprocParams,
   1.427 +    void                  **pplContext)
   1.428 +{
   1.429 +    PKIX_List             *anchors = NULL;
   1.430 +    PKIX_PL_Cert          *targetCert = NULL;
   1.431 +    PKIX_PL_Date          *date = NULL;
   1.432 +    PKIX_ProcessingParams *procParams = NULL;
   1.433 +    PKIX_CertSelector     *certSelector = NULL;
   1.434 +    PKIX_ComCertSelParams *certSelParams = NULL;
   1.435 +    PKIX_CertStore        *certStore = NULL;
   1.436 +    PKIX_List             *certStores = NULL;
   1.437 +    PKIX_RevocationChecker *revChecker = NULL;
   1.438 +    PKIX_UInt32           methodFlags = 0;
   1.439 +    void                  *plContext = NULL;
   1.440 +    CERTStatusConfig      *statusConfig = NULL;
   1.441 +    
   1.442 +    PKIX_ENTER(CERTVFYPKIX, "cert_CreatePkixProcessingParams");
   1.443 +    PKIX_NULLCHECK_TWO(cert, pprocParams);
   1.444 + 
   1.445 +    PKIX_CHECK(
   1.446 +        PKIX_PL_NssContext_Create(0, useArena, wincx, &plContext),
   1.447 +        PKIX_NSSCONTEXTCREATEFAILED);
   1.448 +
   1.449 +    *pplContext = plContext;
   1.450 +
   1.451 +#ifdef PKIX_NOTDEF 
   1.452 +    /* Functions should be implemented in patch for 390532 */
   1.453 +    PKIX_CHECK(
   1.454 +        pkix_pl_NssContext_SetCertSignatureCheck(checkSig,
   1.455 +                                                 (PKIX_PL_NssContext*)plContext),
   1.456 +        PKIX_NSSCONTEXTSETCERTSIGNCHECKFAILED);
   1.457 +
   1.458 +#endif /* PKIX_NOTDEF */
   1.459 +
   1.460 +    PKIX_CHECK(
   1.461 +        PKIX_ProcessingParams_Create(&procParams, plContext),
   1.462 +        PKIX_PROCESSINGPARAMSCREATEFAILED);
   1.463 +    
   1.464 +    PKIX_CHECK(
   1.465 +        PKIX_ComCertSelParams_Create(&certSelParams, plContext),
   1.466 +        PKIX_COMCERTSELPARAMSCREATEFAILED);
   1.467 +    
   1.468 +    PKIX_CHECK(
   1.469 +        PKIX_PL_Cert_CreateFromCERTCertificate(cert, &targetCert, plContext),
   1.470 +        PKIX_CERTCREATEWITHNSSCERTFAILED);
   1.471 +
   1.472 +    PKIX_CHECK(
   1.473 +        PKIX_ComCertSelParams_SetCertificate(certSelParams,
   1.474 +                                             targetCert, plContext),
   1.475 +        PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED);
   1.476 +    
   1.477 +    PKIX_CHECK(
   1.478 +        PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext),
   1.479 +        PKIX_COULDNOTCREATECERTSELECTOROBJECT);
   1.480 +    
   1.481 +    PKIX_CHECK(
   1.482 +        PKIX_CertSelector_SetCommonCertSelectorParams(certSelector,
   1.483 +                                                      certSelParams, plContext),
   1.484 +        PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
   1.485 +    
   1.486 +    PKIX_CHECK(
   1.487 +        PKIX_ProcessingParams_SetTargetCertConstraints(procParams,
   1.488 +                                                       certSelector, plContext),
   1.489 +        PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED);
   1.490 +
   1.491 +    /* Turn off quialification of target cert since leaf cert is
   1.492 +     * already check for date validity, key usages and extended
   1.493 +     * key usages. */
   1.494 +    PKIX_CHECK(
   1.495 +        PKIX_ProcessingParams_SetQualifyTargetCert(procParams, PKIX_FALSE,
   1.496 +                                                   plContext),
   1.497 +        PKIX_PROCESSINGPARAMSSETQUALIFYTARGETCERTFLAGFAILED);
   1.498 +
   1.499 +    PKIX_CHECK(
   1.500 +        PKIX_PL_Pk11CertStore_Create(&certStore, plContext),
   1.501 +        PKIX_PK11CERTSTORECREATEFAILED);
   1.502 +    
   1.503 +    PKIX_CHECK(
   1.504 +        PKIX_List_Create(&certStores, plContext),
   1.505 +        PKIX_UNABLETOCREATELIST);
   1.506 +    
   1.507 +    PKIX_CHECK(
   1.508 +        PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore,
   1.509 +                             plContext),
   1.510 +        PKIX_LISTAPPENDITEMFAILED);
   1.511 +
   1.512 +    PKIX_CHECK(
   1.513 +        PKIX_ProcessingParams_SetCertStores(procParams, certStores,
   1.514 +                                            plContext),
   1.515 +        PKIX_PROCESSINGPARAMSADDCERTSTOREFAILED);
   1.516 +
   1.517 +    PKIX_CHECK(
   1.518 +        PKIX_PL_Date_CreateFromPRTime(time, &date, plContext),
   1.519 +        PKIX_DATECREATEFROMPRTIMEFAILED);
   1.520 +
   1.521 +    PKIX_CHECK(
   1.522 +        PKIX_ProcessingParams_SetDate(procParams, date, plContext),
   1.523 +        PKIX_PROCESSINGPARAMSSETDATEFAILED);
   1.524 +
   1.525 +    PKIX_CHECK(
   1.526 +        PKIX_RevocationChecker_Create(
   1.527 +                                  PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
   1.528 +                                  PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT,
   1.529 +                                  PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
   1.530 +                                  PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT,
   1.531 +                                  &revChecker, plContext),
   1.532 +        PKIX_REVOCATIONCHECKERCREATEFAILED);
   1.533 +
   1.534 +    PKIX_CHECK(
   1.535 +        PKIX_ProcessingParams_SetRevocationChecker(procParams, revChecker,
   1.536 +                                                   plContext),
   1.537 +        PKIX_PROCESSINGPARAMSSETREVOCATIONCHECKERFAILED);
   1.538 +
   1.539 +    /* CRL method flags */
   1.540 +    methodFlags = 
   1.541 +        PKIX_REV_M_TEST_USING_THIS_METHOD |
   1.542 +        PKIX_REV_M_FORBID_NETWORK_FETCHING |
   1.543 +        PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE |   /* 0 */
   1.544 +        PKIX_REV_M_IGNORE_MISSING_FRESH_INFO |     /* 0 */
   1.545 +        PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO;
   1.546 +
   1.547 +    /* add CRL revocation method to check the leaf certificate */
   1.548 +    PKIX_CHECK(
   1.549 +        PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
   1.550 +                                         PKIX_RevocationMethod_CRL, methodFlags,
   1.551 +                                         0, NULL, PKIX_TRUE, plContext),
   1.552 +        PKIX_REVOCATIONCHECKERADDMETHODFAILED);
   1.553 +
   1.554 +    /* add CRL revocation method for other certs in the chain. */
   1.555 +    PKIX_CHECK(
   1.556 +        PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
   1.557 +                                         PKIX_RevocationMethod_CRL, methodFlags,
   1.558 +                                         0, NULL, PKIX_FALSE, plContext),
   1.559 +        PKIX_REVOCATIONCHECKERADDMETHODFAILED);
   1.560 +    
   1.561 +    /* For compatibility with the old code, need to check that
   1.562 +     * statusConfig is set in the db handle and status checker
   1.563 +     * is defined befor allow ocsp status check on the leaf cert.*/
   1.564 +    statusConfig = CERT_GetStatusConfig(CERT_GetDefaultCertDB());
   1.565 +    if (statusConfig != NULL && statusConfig->statusChecker != NULL) {
   1.566 +
   1.567 +        /* Enable OCSP revocation checking for the leaf cert. */
   1.568 +        /* OCSP method flags */
   1.569 +        methodFlags =
   1.570 +            PKIX_REV_M_TEST_USING_THIS_METHOD |
   1.571 +            PKIX_REV_M_ALLOW_NETWORK_FETCHING |         /* 0 */
   1.572 +            PKIX_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE |  /* 0 */
   1.573 +            PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE |    /* 0 */
   1.574 +            PKIX_REV_M_IGNORE_MISSING_FRESH_INFO |      /* 0 */
   1.575 +            PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO;
   1.576 +        
   1.577 +        /* Disabling ocsp fetching when checking the status
   1.578 +         * of ocsp response signer. Here and in the next if,
   1.579 +         * adjust flags for ocsp signer cert validation case. */
   1.580 +        if (disableOCSPRemoteFetching) {
   1.581 +            methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING;
   1.582 +        }
   1.583 +        
   1.584 +        if (ocsp_FetchingFailureIsVerificationFailure()
   1.585 +            && !disableOCSPRemoteFetching) {
   1.586 +            methodFlags |=
   1.587 +                PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO;
   1.588 +        }
   1.589 +        
   1.590 +        /* add OCSP revocation method to check only the leaf certificate.*/
   1.591 +        PKIX_CHECK(
   1.592 +            PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
   1.593 +                                     PKIX_RevocationMethod_OCSP, methodFlags,
   1.594 +                                     1, NULL, PKIX_TRUE, plContext),
   1.595 +            PKIX_REVOCATIONCHECKERADDMETHODFAILED);
   1.596 +    }
   1.597 +
   1.598 +    PKIX_CHECK(
   1.599 +        PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams, PR_FALSE,
   1.600 +                                                    plContext),
   1.601 +        PKIX_PROCESSINGPARAMSSETANYPOLICYINHIBITED);
   1.602 +
   1.603 +    PKIX_CHECK(
   1.604 +        PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams, PR_FALSE,
   1.605 +                                                       plContext),
   1.606 +        PKIX_PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED);
   1.607 +
   1.608 +    PKIX_CHECK(
   1.609 +        PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams, PR_FALSE,
   1.610 +                                                        plContext),
   1.611 +        PKIX_PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED);
   1.612 + 
   1.613 +    *pprocParams = procParams;
   1.614 +    procParams = NULL;
   1.615 +
   1.616 +cleanup:
   1.617 +    PKIX_DECREF(anchors);
   1.618 +    PKIX_DECREF(targetCert);
   1.619 +    PKIX_DECREF(date);
   1.620 +    PKIX_DECREF(certSelector);
   1.621 +    PKIX_DECREF(certSelParams);
   1.622 +    PKIX_DECREF(certStore);
   1.623 +    PKIX_DECREF(certStores);
   1.624 +    PKIX_DECREF(procParams);
   1.625 +    PKIX_DECREF(revChecker);
   1.626 +
   1.627 +    PKIX_RETURN(CERTVFYPKIX);
   1.628 +}
   1.629 +
   1.630 +/*
   1.631 + * FUNCTION: cert_PkixToNssCertsChain
   1.632 + * DESCRIPTION:
   1.633 + *
   1.634 + * Converts pkix cert list into nss cert list.
   1.635 + * 
   1.636 + * PARAMETERS:
   1.637 + *  "pkixCertChain"
   1.638 + *      Pkix certificate list.     
   1.639 + *  "pvalidChain"
   1.640 + *      An address of returned nss certificate list.
   1.641 + *  "plContext"
   1.642 + *      Platform-specific context pointer.
   1.643 + * THREAD SAFETY:
   1.644 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.645 + * RETURNS:
   1.646 + *  Returns NULL if the function succeeds.
   1.647 + *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   1.648 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.649 + */
   1.650 +static PKIX_Error*
   1.651 +cert_PkixToNssCertsChain(
   1.652 +    PKIX_List *pkixCertChain, 
   1.653 +    CERTCertList **pvalidChain, 
   1.654 +    void *plContext)
   1.655 +{
   1.656 +    PLArenaPool     *arena = NULL;
   1.657 +    CERTCertificate *nssCert = NULL;
   1.658 +    CERTCertList    *validChain = NULL;
   1.659 +    PKIX_PL_Object  *certItem = NULL;
   1.660 +    PKIX_UInt32      length = 0;
   1.661 +    PKIX_UInt32      i = 0;
   1.662 +
   1.663 +    PKIX_ENTER(CERTVFYPKIX, "cert_PkixToNssCertsChain");
   1.664 +    PKIX_NULLCHECK_ONE(pvalidChain);
   1.665 +
   1.666 +    if (pkixCertChain == NULL) {
   1.667 +        goto cleanup;
   1.668 +    }
   1.669 +    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1.670 +    if (arena == NULL) {
   1.671 +        PKIX_ERROR(PKIX_OUTOFMEMORY);
   1.672 +    }
   1.673 +    validChain = (CERTCertList*)PORT_ArenaZAlloc(arena, sizeof(CERTCertList));
   1.674 +    if (validChain == NULL) {
   1.675 +        PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
   1.676 +    }
   1.677 +    PR_INIT_CLIST(&validChain->list);
   1.678 +    validChain->arena = arena;
   1.679 +    arena = NULL;
   1.680 +
   1.681 +    PKIX_CHECK(
   1.682 +        PKIX_List_GetLength(pkixCertChain, &length, plContext),
   1.683 +        PKIX_LISTGETLENGTHFAILED);
   1.684 +
   1.685 +    for (i = 0; i < length; i++){
   1.686 +        CERTCertListNode *node = NULL;
   1.687 +
   1.688 +        PKIX_CHECK(
   1.689 +            PKIX_List_GetItem(pkixCertChain, i, &certItem, plContext),
   1.690 +            PKIX_LISTGETITEMFAILED);
   1.691 +        
   1.692 +        PKIX_CHECK(
   1.693 +            PKIX_PL_Cert_GetCERTCertificate((PKIX_PL_Cert*)certItem, &nssCert,
   1.694 +                                    plContext),
   1.695 +            PKIX_CERTGETCERTCERTIFICATEFAILED);
   1.696 +        
   1.697 +        node =
   1.698 +            (CERTCertListNode *)PORT_ArenaZAlloc(validChain->arena,
   1.699 +                                                 sizeof(CERTCertListNode));
   1.700 +        if ( node == NULL ) {
   1.701 +            PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
   1.702 +        }
   1.703 +
   1.704 +        PR_INSERT_BEFORE(&node->links, &validChain->list);
   1.705 +
   1.706 +        node->cert = nssCert;
   1.707 +        nssCert = NULL;
   1.708 +
   1.709 +        PKIX_DECREF(certItem);
   1.710 +    }
   1.711 +
   1.712 +    *pvalidChain = validChain;
   1.713 +
   1.714 +cleanup:
   1.715 +    if (PKIX_ERROR_RECEIVED){
   1.716 +        if (validChain) {
   1.717 +            CERT_DestroyCertList(validChain);
   1.718 +        } else if (arena) {
   1.719 +            PORT_FreeArena(arena, PR_FALSE);
   1.720 +        }
   1.721 +        if (nssCert) {
   1.722 +            CERT_DestroyCertificate(nssCert);
   1.723 +        }
   1.724 +    }
   1.725 +    PKIX_DECREF(certItem);
   1.726 +
   1.727 +    PKIX_RETURN(CERTVFYPKIX);
   1.728 +}
   1.729 +
   1.730 +
   1.731 +/*
   1.732 + * FUNCTION: cert_BuildAndValidateChain
   1.733 + * DESCRIPTION:
   1.734 + *
   1.735 + * The function builds and validates a cert chain based on certificate
   1.736 + * selection criterias from procParams. This function call PKIX_BuildChain
   1.737 + * to accomplish chain building. If PKIX_BuildChain returns with incomplete
   1.738 + * IO, the function waits with PR_Poll until the blocking IO is finished and
   1.739 + * return control back to PKIX_BuildChain.
   1.740 + *
   1.741 + * PARAMETERS:
   1.742 + *  "procParams"
   1.743 + *      Processing parameters to be used during chain building.
   1.744 + *  "pResult"
   1.745 + *      Returned build result.
   1.746 + *  "pVerifyNode"
   1.747 + *      Returned pointed to verify node structure: the tree-like structure
   1.748 + *      that reports points of chain building failures.
   1.749 + *  "plContext"
   1.750 + *      Platform-specific context pointer.
   1.751 + * THREAD SAFETY:
   1.752 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.753 + * RETURNS:
   1.754 + *  Returns NULL if the function succeeds.
   1.755 + *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   1.756 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.757 + */
   1.758 +static PKIX_Error*
   1.759 +cert_BuildAndValidateChain(
   1.760 +    PKIX_ProcessingParams *procParams,
   1.761 +    PKIX_BuildResult **pResult,
   1.762 +    PKIX_VerifyNode **pVerifyNode,
   1.763 +    void *plContext)
   1.764 +{
   1.765 +    PKIX_BuildResult *result = NULL;
   1.766 +    PKIX_VerifyNode  *verifyNode = NULL;
   1.767 +    void             *nbioContext = NULL;
   1.768 +    void             *state = NULL;
   1.769 +    
   1.770 +    PKIX_ENTER(CERTVFYPKIX, "cert_BuildAndVerifyChain");
   1.771 +    PKIX_NULLCHECK_TWO(procParams, pResult);
   1.772 + 
   1.773 +    do {
   1.774 +        if (nbioContext && state) {
   1.775 +            /* PKIX-XXX: need to test functionality of NBIO handling in libPkix.
   1.776 +             * See bug 391180 */
   1.777 +            PRInt32 filesReady = 0;
   1.778 +            PRPollDesc *pollDesc = (PRPollDesc*)nbioContext;
   1.779 +            filesReady = PR_Poll(pollDesc, 1, PR_INTERVAL_NO_TIMEOUT);
   1.780 +            if (filesReady <= 0) {
   1.781 +                PKIX_ERROR(PKIX_PRPOLLRETBADFILENUM);
   1.782 +            }
   1.783 +        }
   1.784 +
   1.785 +        PKIX_CHECK(
   1.786 +            PKIX_BuildChain(procParams, &nbioContext, &state,
   1.787 +                            &result, &verifyNode, plContext),
   1.788 +            PKIX_UNABLETOBUILDCHAIN);
   1.789 +        
   1.790 +    } while (nbioContext && state);
   1.791 +
   1.792 +    *pResult = result;
   1.793 +
   1.794 +cleanup:
   1.795 +    if (pVerifyNode) {
   1.796 +        *pVerifyNode = verifyNode;
   1.797 +    }
   1.798 +
   1.799 +    PKIX_RETURN(CERTVFYPKIX);
   1.800 +}
   1.801 +
   1.802 +
   1.803 +/*
   1.804 + * FUNCTION: cert_PkixErrorToNssCode
   1.805 + * DESCRIPTION:
   1.806 + *
   1.807 + * Converts pkix error(PKIX_Error) structure to PR error codes.
   1.808 + *
   1.809 + * PKIX-XXX to be implemented. See 391183.
   1.810 + *
   1.811 + * PARAMETERS:
   1.812 + *  "error"
   1.813 + *      Pkix error that will be converted.
   1.814 + *  "nssCode"
   1.815 + *      Corresponding nss error code.
   1.816 + *  "plContext"
   1.817 + *      Platform-specific context pointer.
   1.818 + * THREAD SAFETY:
   1.819 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.820 + * RETURNS:
   1.821 + *  Returns NULL if the function succeeds.
   1.822 + *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   1.823 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.824 + */
   1.825 +static PKIX_Error *
   1.826 +cert_PkixErrorToNssCode(
   1.827 +    PKIX_Error *error,
   1.828 +    SECErrorCodes *pNssErr,
   1.829 +    void *plContext)
   1.830 +{
   1.831 +    int errLevel = 0;
   1.832 +    PKIX_Int32 nssErr = 0;
   1.833 +    PKIX_Error *errPtr = error;
   1.834 +
   1.835 +    PKIX_ENTER(CERTVFYPKIX, "cert_PkixErrorToNssCode");
   1.836 +    PKIX_NULLCHECK_TWO(error, pNssErr);
   1.837 +    
   1.838 +    /* Loop until we find at least one error with non-null
   1.839 +     * plErr code, that is going to be nss error code. */
   1.840 +    while (errPtr) {
   1.841 +        if (errPtr->plErr && !nssErr) {
   1.842 +            nssErr = errPtr->plErr;
   1.843 +            if (!pkixLog) break;
   1.844 +        }
   1.845 +        if (pkixLog) {
   1.846 +#ifdef PKIX_ERROR_DESCRIPTION            
   1.847 +            PR_LOG(pkixLog, 2, ("Error at level %d: %s\n", errLevel,
   1.848 +                                PKIX_ErrorText[errPtr->errCode]));
   1.849 +#else
   1.850 +            PR_LOG(pkixLog, 2, ("Error at level %d: Error code %d\n", errLevel,
   1.851 +                                errPtr->errCode));
   1.852 +#endif /* PKIX_ERROR_DESCRIPTION */
   1.853 +        }
   1.854 +        errPtr = errPtr->cause;
   1.855 +        errLevel += 1; 
   1.856 +    }
   1.857 +    PORT_Assert(nssErr);
   1.858 +    if (!nssErr) {
   1.859 +        *pNssErr = SEC_ERROR_LIBPKIX_INTERNAL;
   1.860 +    } else {
   1.861 +        *pNssErr = nssErr;
   1.862 +    }
   1.863 +
   1.864 +    PKIX_RETURN(CERTVFYPKIX);
   1.865 +}
   1.866 +
   1.867 +/*
   1.868 + * FUNCTION: cert_GetLogFromVerifyNode
   1.869 + * DESCRIPTION:
   1.870 + *
   1.871 + * Recursive function that converts verify node tree-like set of structures
   1.872 + * to CERTVerifyLog.
   1.873 + *
   1.874 + * PARAMETERS:
   1.875 + *  "log"
   1.876 + *      Pointed to already allocated CERTVerifyLog structure. 
   1.877 + *  "node"
   1.878 + *      A node of PKIX_VerifyNode tree.
   1.879 + *  "plContext"
   1.880 + *      Platform-specific context pointer.
   1.881 + * THREAD SAFETY:
   1.882 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.883 + * RETURNS:
   1.884 + *  Returns NULL if the function succeeds.
   1.885 + *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   1.886 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.887 + */
   1.888 +static PKIX_Error *
   1.889 +cert_GetLogFromVerifyNode(
   1.890 +    CERTVerifyLog *log,
   1.891 +    PKIX_VerifyNode *node,
   1.892 +    void *plContext)
   1.893 +{
   1.894 +    PKIX_List       *children = NULL;
   1.895 +    PKIX_VerifyNode *childNode = NULL;
   1.896 +
   1.897 +    PKIX_ENTER(CERTVFYPKIX, "cert_GetLogFromVerifyNode");
   1.898 +
   1.899 +    children = node->children;
   1.900 +
   1.901 +    if (children == NULL) {
   1.902 +        PKIX_ERRORCODE errCode = PKIX_ANCHORDIDNOTCHAINTOCERT;
   1.903 +        if (node->error && node->error->errCode != errCode) {
   1.904 +#ifdef DEBUG_volkov
   1.905 +            char *string = pkix_Error2ASCII(node->error, plContext);
   1.906 +            fprintf(stderr, "Branch search finished with error: \t%s\n", string);
   1.907 +            PKIX_PL_Free(string, NULL);
   1.908 +#endif
   1.909 +            if (log != NULL) {
   1.910 +                SECErrorCodes nssErrorCode = 0;
   1.911 +                CERTCertificate *cert = NULL;
   1.912 +
   1.913 +                cert = node->verifyCert->nssCert;
   1.914 +
   1.915 +                PKIX_CHECK(
   1.916 +                    cert_PkixErrorToNssCode(node->error, &nssErrorCode,
   1.917 +                                            plContext),
   1.918 +                    PKIX_GETPKIXERRORCODEFAILED);
   1.919 +                
   1.920 +                cert_AddToVerifyLog(log, cert, nssErrorCode, node->depth, NULL);
   1.921 +            }
   1.922 +        }
   1.923 +        PKIX_RETURN(CERTVFYPKIX);
   1.924 +    } else {
   1.925 +        PRUint32      i = 0;
   1.926 +        PKIX_UInt32   length = 0;
   1.927 +
   1.928 +        PKIX_CHECK(
   1.929 +            PKIX_List_GetLength(children, &length, plContext),
   1.930 +            PKIX_LISTGETLENGTHFAILED);
   1.931 +        
   1.932 +        for (i = 0; i < length; i++){
   1.933 +
   1.934 +            PKIX_CHECK(
   1.935 +                PKIX_List_GetItem(children, i, (PKIX_PL_Object**)&childNode,
   1.936 +                                  plContext),
   1.937 +                PKIX_LISTGETITEMFAILED);
   1.938 +            
   1.939 +            PKIX_CHECK(
   1.940 +                cert_GetLogFromVerifyNode(log, childNode, plContext),
   1.941 +                PKIX_ERRORINRECURSIVEEQUALSCALL);
   1.942 +
   1.943 +            PKIX_DECREF(childNode);
   1.944 +        }
   1.945 +    }
   1.946 +
   1.947 +cleanup:
   1.948 +    PKIX_DECREF(childNode);
   1.949 +
   1.950 +    PKIX_RETURN(CERTVFYPKIX);
   1.951 +}
   1.952 +
   1.953 +/*
   1.954 + * FUNCTION: cert_GetBuildResults
   1.955 + * DESCRIPTION:
   1.956 + *
   1.957 + * Converts pkix build results to nss results. This function is called
   1.958 + * regardless of build result.
   1.959 + *
   1.960 + * If it called after chain was successfully constructed, then it will
   1.961 + * convert:
   1.962 + *   * pkix cert list that represent the chain to nss cert list
   1.963 + *   * trusted root the chain was anchored to nss certificate.
   1.964 + *
   1.965 + * In case of failure it will convert:
   1.966 + *   * pkix error to PR error code(will set it with PORT_SetError)
   1.967 + *   * pkix validation log to nss CERTVerifyLog
   1.968 + *   
   1.969 + * PARAMETERS:
   1.970 + *  "buildResult"
   1.971 + *      Build results returned by PKIX_BuildChain.
   1.972 + *  "verifyNode"
   1.973 + *      Tree-like structure of chain building/validation failures
   1.974 + *      returned by PKIX_BuildChain. Ignored in case of success.
   1.975 + *  "error"
   1.976 + *      Final error returned by PKIX_BuildChain. Should be NULL in
   1.977 + *      case of success.
   1.978 + *  "log"
   1.979 + *      Address of pre-allocated(if not NULL) CERTVerifyLog structure.
   1.980 + *  "ptrustedRoot"
   1.981 + *      Address of returned trusted root the chain was anchored to.
   1.982 + *  "pvalidChain"
   1.983 + *      Address of returned valid chain.
   1.984 + *  "plContext"
   1.985 + *      Platform-specific context pointer.
   1.986 + * THREAD SAFETY:
   1.987 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1.988 + * RETURNS:
   1.989 + *  Returns NULL if the function succeeds.
   1.990 + *  Returns a Cert Verify Error if the function fails in an unrecoverable way.
   1.991 + *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1.992 + */
   1.993 +static PKIX_Error*
   1.994 +cert_GetBuildResults(
   1.995 +    PKIX_BuildResult *buildResult,
   1.996 +    PKIX_VerifyNode  *verifyNode,
   1.997 +    PKIX_Error       *error,
   1.998 +    CERTVerifyLog    *log,
   1.999 +    CERTCertificate **ptrustedRoot,
  1.1000 +    CERTCertList    **pvalidChain,
  1.1001 +    void             *plContext)
  1.1002 +{
  1.1003 +    PKIX_ValidateResult *validResult = NULL;
  1.1004 +    CERTCertList        *validChain = NULL;
  1.1005 +    CERTCertificate     *trustedRoot = NULL;
  1.1006 +    PKIX_TrustAnchor    *trustAnchor = NULL;
  1.1007 +    PKIX_PL_Cert        *trustedCert = NULL;
  1.1008 +    PKIX_List           *pkixCertChain = NULL;
  1.1009 +#ifdef DEBUG_volkov
  1.1010 +    PKIX_Error          *tmpPkixError = NULL;
  1.1011 +#endif /* DEBUG */
  1.1012 +            
  1.1013 +    PKIX_ENTER(CERTVFYPKIX, "cert_GetBuildResults");
  1.1014 +    if (buildResult == NULL && error == NULL) {
  1.1015 +        PKIX_ERROR(PKIX_NULLARGUMENT);
  1.1016 +    }
  1.1017 +
  1.1018 +    if (error) {
  1.1019 +        SECErrorCodes nssErrorCode = 0;
  1.1020 +#ifdef DEBUG_volkov        
  1.1021 +        char *temp = pkix_Error2ASCII(error, plContext);
  1.1022 +        fprintf(stderr, "BUILD ERROR:\n%s\n", temp);
  1.1023 +        PKIX_PL_Free(temp, NULL);
  1.1024 +#endif /* DEBUG */
  1.1025 +        if (verifyNode) {
  1.1026 +            PKIX_Error *tmpError =
  1.1027 +                cert_GetLogFromVerifyNode(log, verifyNode, plContext);
  1.1028 +            if (tmpError) {
  1.1029 +                PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
  1.1030 +            }
  1.1031 +        }
  1.1032 +        cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
  1.1033 +        PORT_SetError(nssErrorCode);
  1.1034 +        goto cleanup;
  1.1035 +    }
  1.1036 +
  1.1037 +    if (pvalidChain) {
  1.1038 +        PKIX_CHECK(
  1.1039 +            PKIX_BuildResult_GetCertChain(buildResult, &pkixCertChain,
  1.1040 +                                          plContext),
  1.1041 +            PKIX_BUILDRESULTGETCERTCHAINFAILED);
  1.1042 +
  1.1043 +#ifdef DEBUG_volkov
  1.1044 +        tmpPkixError = cert_PrintCertChain(pkixCertChain, plContext);
  1.1045 +        if (tmpPkixError) {
  1.1046 +            PKIX_PL_Object_DecRef((PKIX_PL_Object*)tmpPkixError, plContext);
  1.1047 +        }
  1.1048 +#endif        
  1.1049 +
  1.1050 +        PKIX_CHECK(
  1.1051 +            cert_PkixToNssCertsChain(pkixCertChain, &validChain, plContext),
  1.1052 +            PKIX_CERTCHAINTONSSCHAINFAILED);
  1.1053 +    }
  1.1054 +
  1.1055 +    if (ptrustedRoot) {
  1.1056 +        PKIX_CHECK(
  1.1057 +            PKIX_BuildResult_GetValidateResult(buildResult, &validResult,
  1.1058 +                                               plContext),
  1.1059 +            PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
  1.1060 +
  1.1061 +        PKIX_CHECK(
  1.1062 +            PKIX_ValidateResult_GetTrustAnchor(validResult, &trustAnchor,
  1.1063 +                                               plContext),
  1.1064 +            PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
  1.1065 +
  1.1066 +        PKIX_CHECK(
  1.1067 +            PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustedCert,
  1.1068 +                                            plContext),
  1.1069 +            PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
  1.1070 +
  1.1071 +#ifdef DEBUG_volkov
  1.1072 +        if (pvalidChain == NULL) {
  1.1073 +            cert_PrintCert(trustedCert, plContext);
  1.1074 +        }
  1.1075 +#endif        
  1.1076 +
  1.1077 +       PKIX_CHECK(
  1.1078 +            PKIX_PL_Cert_GetCERTCertificate(trustedCert, &trustedRoot,
  1.1079 +                                            plContext),
  1.1080 +            PKIX_CERTGETCERTCERTIFICATEFAILED);
  1.1081 +    }
  1.1082 + 
  1.1083 +    PORT_Assert(!PKIX_ERROR_RECEIVED);
  1.1084 +
  1.1085 +    if (trustedRoot) {
  1.1086 +        *ptrustedRoot = trustedRoot;
  1.1087 +    }
  1.1088 +    if (validChain) {
  1.1089 +        *pvalidChain = validChain;
  1.1090 +    }
  1.1091 +
  1.1092 +cleanup:
  1.1093 +    if (PKIX_ERROR_RECEIVED) {
  1.1094 +        if (trustedRoot) {
  1.1095 +            CERT_DestroyCertificate(trustedRoot);
  1.1096 +        }
  1.1097 +        if (validChain) {
  1.1098 +            CERT_DestroyCertList(validChain);
  1.1099 +        }
  1.1100 +    }
  1.1101 +    PKIX_DECREF(trustAnchor);
  1.1102 +    PKIX_DECREF(trustedCert);
  1.1103 +    PKIX_DECREF(pkixCertChain);
  1.1104 +    PKIX_DECREF(validResult);
  1.1105 +    PKIX_DECREF(error);
  1.1106 +    PKIX_DECREF(verifyNode);
  1.1107 +    PKIX_DECREF(buildResult);
  1.1108 +    
  1.1109 +    PKIX_RETURN(CERTVFYPKIX);
  1.1110 +}
  1.1111 +
  1.1112 +/*
  1.1113 + * FUNCTION: cert_VerifyCertChainPkix
  1.1114 + * DESCRIPTION:
  1.1115 + *
  1.1116 + * The main wrapper function that is called from CERT_VerifyCert and
  1.1117 + * CERT_VerifyCACertForUsage functions to validate cert with libpkix.
  1.1118 + *
  1.1119 + * PARAMETERS:
  1.1120 + *  "cert"
  1.1121 + *      Leaf certificate of a chain we want to build.
  1.1122 + *  "checkSig"
  1.1123 + *      Certificate signatures will not be verified if this
  1.1124 + *      flag is set to PR_FALSE.
  1.1125 + *  "requiredUsage"
  1.1126 + *      Required usage for certificate and chain.
  1.1127 + *  "time"
  1.1128 + *      Validity time.
  1.1129 + *  "wincx"
  1.1130 + *      Nss database password token.
  1.1131 + *  "log"
  1.1132 + *      Address of already allocated CERTVerifyLog structure. Not
  1.1133 + *      used if NULL;
  1.1134 + *  "pSigerror"
  1.1135 + *      Address of PRBool. If not NULL, returns true is cert chain
  1.1136 + *      was invalidated because of bad certificate signature.
  1.1137 + *  "pRevoked"
  1.1138 + *      Address of PRBool. If not NULL, returns true is cert chain
  1.1139 + *      was invalidated because a revoked certificate was found in
  1.1140 + *      the chain.
  1.1141 + * THREAD SAFETY:
  1.1142 + *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  1.1143 + * RETURNS:
  1.1144 + *  SECFailure is chain building process has failed. SECSuccess otherwise.
  1.1145 + */
  1.1146 +SECStatus
  1.1147 +cert_VerifyCertChainPkix(
  1.1148 +    CERTCertificate *cert,
  1.1149 +    PRBool           checkSig,
  1.1150 +    SECCertUsage     requiredUsage,
  1.1151 +    PRTime           time,
  1.1152 +    void            *wincx,
  1.1153 +    CERTVerifyLog   *log,
  1.1154 +    PRBool          *pSigerror,
  1.1155 +    PRBool          *pRevoked)
  1.1156 +{
  1.1157 +    PKIX_ProcessingParams *procParams = NULL;
  1.1158 +    PKIX_BuildResult      *result = NULL;
  1.1159 +    PKIX_VerifyNode       *verifyNode = NULL;
  1.1160 +    PKIX_Error            *error = NULL;
  1.1161 +
  1.1162 +    SECStatus              rv = SECFailure;
  1.1163 +    void                  *plContext = NULL;
  1.1164 +#ifdef DEBUG_volkov
  1.1165 +    CERTCertificate       *trustedRoot = NULL;
  1.1166 +    CERTCertList          *validChain = NULL;
  1.1167 +#endif /* DEBUG */
  1.1168 +
  1.1169 +#ifdef PKIX_OBJECT_LEAK_TEST
  1.1170 +    int  leakedObjNum = 0;
  1.1171 +    int  memLeakLoopCount = 0;
  1.1172 +    int  objCountTable[PKIX_NUMTYPES]; 
  1.1173 +    int  fnInvLocalCount = 0;
  1.1174 +    PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
  1.1175 +
  1.1176 +    if (usePKIXValidationEngine) {
  1.1177 +        /* current memory leak testing implementation does not allow
  1.1178 +         * to run simultaneous tests one the same or a different threads.
  1.1179 +         * Setting the variable to false, to make additional chain
  1.1180 +         * validations be handled by old nss. */
  1.1181 +        usePKIXValidationEngine = PR_FALSE;
  1.1182 +    }
  1.1183 +    testStartFnStackPosition = 2;
  1.1184 +    fnStackNameArr[0] = "cert_VerifyCertChainPkix";
  1.1185 +    fnStackInvCountArr[0] = 0;
  1.1186 +    PKIX_Boolean abortOnLeak = 
  1.1187 +        (PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ?
  1.1188 +                                                   PKIX_FALSE : PKIX_TRUE;
  1.1189 +    runningLeakTest = PKIX_TRUE;
  1.1190 +
  1.1191 +    /* Prevent multi-threaded run of object leak test */
  1.1192 +    fnInvLocalCount = PR_ATOMIC_INCREMENT(&parallelFnInvocationCount);
  1.1193 +    PORT_Assert(fnInvLocalCount == 1);
  1.1194 +
  1.1195 +do {
  1.1196 +    rv = SECFailure;
  1.1197 +    plContext = NULL;
  1.1198 +    procParams = NULL;
  1.1199 +    result = NULL;
  1.1200 +    verifyNode = NULL;
  1.1201 +    error = NULL;
  1.1202 +#ifdef DEBUG_volkov
  1.1203 +    trustedRoot = NULL;
  1.1204 +    validChain = NULL;
  1.1205 +#endif /* DEBUG */
  1.1206 +    errorGenerated = PKIX_FALSE;
  1.1207 +    stackPosition = 0;
  1.1208 +
  1.1209 +    if (leakedObjNum) {
  1.1210 +        pkix_pl_lifecycle_ObjectTableUpdate(objCountTable); 
  1.1211 +    }
  1.1212 +    memLeakLoopCount += 1;
  1.1213 +#endif /* PKIX_OBJECT_LEAK_TEST */
  1.1214 +
  1.1215 +    error =
  1.1216 +        cert_CreatePkixProcessingParams(cert, checkSig, time, wincx,
  1.1217 +                                    PR_FALSE/*use arena*/,
  1.1218 +                                    requiredUsage == certUsageStatusResponder,
  1.1219 +                                    &procParams, &plContext);
  1.1220 +    if (error) {
  1.1221 +        goto cleanup;
  1.1222 +    }
  1.1223 +
  1.1224 +    error =
  1.1225 +        cert_ProcessingParamsSetKeyAndCertUsage(procParams, requiredUsage, 0,
  1.1226 +                                                plContext);
  1.1227 +    if (error) {
  1.1228 +        goto cleanup;
  1.1229 +    }
  1.1230 +
  1.1231 +    error = 
  1.1232 +        cert_BuildAndValidateChain(procParams, &result, &verifyNode, plContext);
  1.1233 +    if (error) {
  1.1234 +        goto cleanup;
  1.1235 +    }
  1.1236 +    
  1.1237 +    if (pRevoked) {
  1.1238 +        /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
  1.1239 +        *pRevoked = PR_FALSE;
  1.1240 +    }
  1.1241 +    if (pSigerror) {
  1.1242 +        /* Currently always PR_FALSE. Will be fixed as a part of 394077 */
  1.1243 +        *pSigerror = PR_FALSE;
  1.1244 +    }
  1.1245 +    rv = SECSuccess;
  1.1246 +
  1.1247 +cleanup:
  1.1248 +    error = cert_GetBuildResults(result, verifyNode, error, log,
  1.1249 +#ifdef DEBUG_volkov                                 
  1.1250 +                                 &trustedRoot, &validChain,
  1.1251 +#else
  1.1252 +                                 NULL, NULL,
  1.1253 +#endif /* DEBUG */
  1.1254 +                                 plContext);
  1.1255 +    if (error) {
  1.1256 +#ifdef DEBUG_volkov        
  1.1257 +        char *temp = pkix_Error2ASCII(error, plContext);
  1.1258 +        fprintf(stderr, "GET BUILD RES ERRORS:\n%s\n", temp);
  1.1259 +        PKIX_PL_Free(temp, NULL);
  1.1260 +#endif /* DEBUG */
  1.1261 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1.1262 +    }
  1.1263 +#ifdef DEBUG_volkov
  1.1264 +    if (trustedRoot) {
  1.1265 +        CERT_DestroyCertificate(trustedRoot);
  1.1266 +    }
  1.1267 +    if (validChain) {
  1.1268 +        CERT_DestroyCertList(validChain);
  1.1269 +    }
  1.1270 +#endif /* DEBUG */
  1.1271 +    if (procParams) {
  1.1272 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
  1.1273 +    }
  1.1274 +    if (plContext) {
  1.1275 +        PKIX_PL_NssContext_Destroy(plContext);
  1.1276 +    }
  1.1277 +
  1.1278 +#ifdef PKIX_OBJECT_LEAK_TEST
  1.1279 +    leakedObjNum =
  1.1280 +        pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
  1.1281 +    
  1.1282 +    if (pkixLog && leakedObjNum) {
  1.1283 +        PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
  1.1284 +                            "Stack %s\n", memLeakLoopCount, errorFnStackString));
  1.1285 +    }
  1.1286 +    PR_Free(errorFnStackString);
  1.1287 +    errorFnStackString = NULL;
  1.1288 +    if (abortOnLeak) {
  1.1289 +        PORT_Assert(leakedObjNum == 0);
  1.1290 +    }
  1.1291 +
  1.1292 +} while (errorGenerated);
  1.1293 +
  1.1294 +    runningLeakTest = PKIX_FALSE; 
  1.1295 +    PR_ATOMIC_DECREMENT(&parallelFnInvocationCount);
  1.1296 +    usePKIXValidationEngine = savedUsePkixEngFlag;
  1.1297 +#endif /* PKIX_OBJECT_LEAK_TEST */
  1.1298 +
  1.1299 +    return rv;
  1.1300 +}
  1.1301 +
  1.1302 +PKIX_CertSelector *
  1.1303 +cert_GetTargetCertConstraints(CERTCertificate *target, void *plContext) 
  1.1304 +{
  1.1305 +    PKIX_ComCertSelParams *certSelParams = NULL;
  1.1306 +    PKIX_CertSelector *certSelector = NULL;
  1.1307 +    PKIX_CertSelector *r= NULL;
  1.1308 +    PKIX_PL_Cert *eeCert = NULL;
  1.1309 +    PKIX_Error *error = NULL;
  1.1310 +
  1.1311 +    error = PKIX_PL_Cert_CreateFromCERTCertificate(target, &eeCert, plContext);
  1.1312 +    if (error != NULL) goto cleanup;
  1.1313 +
  1.1314 +    error = PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext);
  1.1315 +    if (error != NULL) goto cleanup;
  1.1316 +
  1.1317 +    error = PKIX_ComCertSelParams_Create(&certSelParams, plContext);
  1.1318 +    if (error != NULL) goto cleanup;
  1.1319 +
  1.1320 +    error = PKIX_ComCertSelParams_SetCertificate(
  1.1321 +                                certSelParams, eeCert, plContext);
  1.1322 +    if (error != NULL) goto cleanup;
  1.1323 +
  1.1324 +    error = PKIX_CertSelector_SetCommonCertSelectorParams
  1.1325 +        (certSelector, certSelParams, plContext);
  1.1326 +    if (error != NULL) goto cleanup;
  1.1327 +
  1.1328 +    error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certSelector, plContext);
  1.1329 +    if (error == NULL) r = certSelector;
  1.1330 +
  1.1331 +cleanup:
  1.1332 +    if (certSelParams != NULL) 
  1.1333 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelParams, plContext);
  1.1334 +
  1.1335 +    if (eeCert != NULL) 
  1.1336 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)eeCert, plContext);
  1.1337 +
  1.1338 +    if (certSelector != NULL) 
  1.1339 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
  1.1340 +
  1.1341 +    if (error != NULL) {
  1.1342 +	SECErrorCodes nssErr;
  1.1343 +
  1.1344 +	cert_PkixErrorToNssCode(error, &nssErr, plContext);
  1.1345 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1.1346 +	PORT_SetError(nssErr);
  1.1347 +    }
  1.1348 +
  1.1349 +    return r;
  1.1350 +}
  1.1351 +
  1.1352 +static PKIX_List *
  1.1353 +cert_GetCertStores(void *plContext)
  1.1354 +{
  1.1355 +    PKIX_CertStore *certStore = NULL;
  1.1356 +    PKIX_List *certStores = NULL;
  1.1357 +    PKIX_List *r = NULL;
  1.1358 +    PKIX_Error *error = NULL;
  1.1359 +
  1.1360 +    error = PKIX_PL_Pk11CertStore_Create(&certStore, plContext);
  1.1361 +    if (error != NULL) goto cleanup;
  1.1362 +
  1.1363 +    error = PKIX_List_Create(&certStores, plContext);
  1.1364 +    if (error != NULL)  goto cleanup;
  1.1365 +
  1.1366 +    error = PKIX_List_AppendItem( certStores, 
  1.1367 +                          (PKIX_PL_Object *)certStore, plContext);
  1.1368 +    if (error != NULL)  goto cleanup;
  1.1369 +
  1.1370 +    error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certStores, plContext);
  1.1371 +    if (error == NULL) r = certStores;
  1.1372 +
  1.1373 +cleanup:
  1.1374 +    if (certStores != NULL) 
  1.1375 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
  1.1376 +
  1.1377 +    if (certStore != NULL) 
  1.1378 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStore, plContext);
  1.1379 +
  1.1380 +    if (error != NULL) {
  1.1381 +	SECErrorCodes nssErr;
  1.1382 +
  1.1383 +	cert_PkixErrorToNssCode(error, &nssErr, plContext);
  1.1384 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1.1385 +	PORT_SetError(nssErr);
  1.1386 +    }
  1.1387 +
  1.1388 +    return r;
  1.1389 +}
  1.1390 +
  1.1391 +
  1.1392 +struct fake_PKIX_PL_CertStruct {
  1.1393 +        CERTCertificate *nssCert;
  1.1394 +};
  1.1395 +
  1.1396 +/* This needs to be part of the PKIX_PL_* */
  1.1397 +/* This definitely needs to go away, and be replaced with
  1.1398 +   a real accessor function in PKIX */
  1.1399 +static CERTCertificate *
  1.1400 +cert_NSSCertFromPKIXCert(const PKIX_PL_Cert *pkix_cert)
  1.1401 +{
  1.1402 +    struct fake_PKIX_PL_CertStruct *fcert = NULL;
  1.1403 +
  1.1404 +    fcert = (struct fake_PKIX_PL_CertStruct*)pkix_cert;
  1.1405 +
  1.1406 +    return CERT_DupCertificate(fcert->nssCert);
  1.1407 +}
  1.1408 +
  1.1409 +PKIX_List *cert_PKIXMakeOIDList(const SECOidTag *oids, int oidCount, void *plContext)
  1.1410 +{
  1.1411 +    PKIX_List *r = NULL;
  1.1412 +    PKIX_List *policyList = NULL;
  1.1413 +    PKIX_PL_OID *policyOID = NULL;
  1.1414 +    PKIX_Error *error = NULL;
  1.1415 +    int i;
  1.1416 +
  1.1417 +    error = PKIX_List_Create(&policyList, plContext);
  1.1418 +    if (error != NULL) {
  1.1419 +	goto cleanup;
  1.1420 +    }
  1.1421 +
  1.1422 +    for (i=0; i<oidCount; i++) {
  1.1423 +        error = PKIX_PL_OID_Create(oids[i], &policyOID, plContext);
  1.1424 +        if (error) {
  1.1425 +            goto cleanup;
  1.1426 +        }
  1.1427 +        error = PKIX_List_AppendItem(policyList, 
  1.1428 +                (PKIX_PL_Object *)policyOID, plContext);
  1.1429 +        if (error != NULL) {
  1.1430 +            goto cleanup;
  1.1431 +        }
  1.1432 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
  1.1433 +        policyOID = NULL;
  1.1434 +    }
  1.1435 +
  1.1436 +    error = PKIX_List_SetImmutable(policyList, plContext);
  1.1437 +    if (error != NULL) goto cleanup;
  1.1438 +
  1.1439 +    error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)policyList, plContext);
  1.1440 +    if (error == NULL) r = policyList;
  1.1441 +
  1.1442 +cleanup:
  1.1443 +    if (policyOID != NULL)  {
  1.1444 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
  1.1445 +    }
  1.1446 +    if (policyList != NULL)  {
  1.1447 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyList, plContext);
  1.1448 +    }
  1.1449 +    if (error != NULL)  {
  1.1450 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1.1451 +    }
  1.1452 +
  1.1453 +    return r;
  1.1454 +}
  1.1455 +
  1.1456 +CERTValOutParam *
  1.1457 +cert_pkix_FindOutputParam(CERTValOutParam *params, const CERTValParamOutType t)
  1.1458 +{
  1.1459 +    CERTValOutParam *i;
  1.1460 +    if (params == NULL) {
  1.1461 +        return NULL;
  1.1462 +    }
  1.1463 +    for (i = params; i->type != cert_po_end; i++) {
  1.1464 +        if (i->type == t) {
  1.1465 +             return i;
  1.1466 +        }
  1.1467 +    }
  1.1468 +    return NULL;
  1.1469 +}
  1.1470 +
  1.1471 +
  1.1472 +static PKIX_Error*
  1.1473 +setRevocationMethod(PKIX_RevocationChecker *revChecker,
  1.1474 +                    PKIX_ProcessingParams *procParams,
  1.1475 +                    const CERTRevocationTests *revTest,
  1.1476 +                    CERTRevocationMethodIndex certRevMethod,
  1.1477 +                    PKIX_RevocationMethodType pkixRevMethod,
  1.1478 +                    PKIX_Boolean verifyResponderUsages,
  1.1479 +                    PKIX_Boolean isLeafTest,
  1.1480 +                    void *plContext)
  1.1481 +{
  1.1482 +    PKIX_UInt32 methodFlags = 0;
  1.1483 +    PKIX_Error *error = NULL;
  1.1484 +    int priority = 0;
  1.1485 +    
  1.1486 +    if (revTest->number_of_defined_methods <= certRevMethod) {
  1.1487 +        return NULL;
  1.1488 +    }
  1.1489 +    if (revTest->preferred_methods) {
  1.1490 +        int i = 0;
  1.1491 +        for (;i < revTest->number_of_preferred_methods;i++) {
  1.1492 +            if (revTest->preferred_methods[i] == certRevMethod) 
  1.1493 +                break;
  1.1494 +        }
  1.1495 +        priority = i;
  1.1496 +    }
  1.1497 +    methodFlags = revTest->cert_rev_flags_per_method[certRevMethod];
  1.1498 +    if (verifyResponderUsages &&
  1.1499 +        pkixRevMethod == PKIX_RevocationMethod_OCSP) {
  1.1500 +        methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING;
  1.1501 +    }
  1.1502 +    error =
  1.1503 +        PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
  1.1504 +                                         pkixRevMethod, methodFlags,
  1.1505 +                                         priority, NULL,
  1.1506 +                                         isLeafTest, plContext);
  1.1507 +    return error;
  1.1508 +}
  1.1509 +
  1.1510 +
  1.1511 +SECStatus
  1.1512 +cert_pkixSetParam(PKIX_ProcessingParams *procParams, 
  1.1513 +  const CERTValInParam *param, void *plContext)
  1.1514 +{
  1.1515 +    PKIX_Error * error = NULL;
  1.1516 +    SECStatus r=SECSuccess;
  1.1517 +    PKIX_PL_Date *date = NULL;
  1.1518 +    PKIX_List *policyOIDList = NULL;
  1.1519 +    PKIX_List *certListPkix = NULL;
  1.1520 +    const CERTRevocationFlags *flags;
  1.1521 +    SECErrorCodes errCode = SEC_ERROR_INVALID_ARGS;
  1.1522 +    const CERTCertList *certList = NULL;
  1.1523 +    CERTCertListNode *node;
  1.1524 +    PKIX_PL_Cert *certPkix = NULL;
  1.1525 +    PKIX_TrustAnchor *trustAnchor = NULL;
  1.1526 +    PKIX_PL_Date *revDate = NULL;
  1.1527 +    PKIX_RevocationChecker *revChecker = NULL;
  1.1528 +    PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext *)plContext;
  1.1529 +
  1.1530 +    /* XXX we need a way to map generic PKIX error to generic NSS errors */
  1.1531 +
  1.1532 +    switch (param->type) {
  1.1533 +
  1.1534 +        case cert_pi_policyOID:
  1.1535 +
  1.1536 +            /* needed? */
  1.1537 +            error = PKIX_ProcessingParams_SetExplicitPolicyRequired(
  1.1538 +                                procParams, PKIX_TRUE, plContext);
  1.1539 +
  1.1540 +            if (error != NULL) { 
  1.1541 +                break;
  1.1542 +            }
  1.1543 +
  1.1544 +            policyOIDList = cert_PKIXMakeOIDList(param->value.array.oids,
  1.1545 +                                param->value.arraySize,plContext);
  1.1546 +	    if (policyOIDList == NULL) {
  1.1547 +		r = SECFailure;
  1.1548 +		PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.1549 +		break;
  1.1550 +	    }
  1.1551 +
  1.1552 +            error = PKIX_ProcessingParams_SetInitialPolicies(
  1.1553 +                                procParams,policyOIDList,plContext);
  1.1554 +            break;
  1.1555 +
  1.1556 +        case cert_pi_date:
  1.1557 +            if (param->value.scalar.time == 0) {
  1.1558 +                error = PKIX_PL_Date_Create_UTCTime(NULL, &date, plContext);
  1.1559 +                if (error != NULL) {
  1.1560 +                    errCode = SEC_ERROR_INVALID_TIME;
  1.1561 +                    break;
  1.1562 +                }
  1.1563 +            } else {
  1.1564 +                error = pkix_pl_Date_CreateFromPRTime(param->value.scalar.time,
  1.1565 +                                                       &date, plContext);
  1.1566 +                if (error != NULL) {
  1.1567 +                    errCode = SEC_ERROR_INVALID_TIME;
  1.1568 +                    break;
  1.1569 +                }
  1.1570 +            }
  1.1571 +
  1.1572 +            error = PKIX_ProcessingParams_SetDate(procParams, date, plContext);
  1.1573 +            if (error != NULL) {
  1.1574 +                errCode = SEC_ERROR_INVALID_TIME;
  1.1575 +            }
  1.1576 +            break;
  1.1577 +
  1.1578 +        case cert_pi_revocationFlags:
  1.1579 +        {
  1.1580 +            PKIX_UInt32 leafIMFlags = 0;
  1.1581 +            PKIX_UInt32 chainIMFlags = 0;
  1.1582 +            PKIX_Boolean validatingResponderCert = PKIX_FALSE;
  1.1583 +
  1.1584 +            flags = param->value.pointer.revocation;
  1.1585 +            if (!flags) {
  1.1586 +                PORT_SetError(errCode);
  1.1587 +                r = SECFailure;
  1.1588 +                break;
  1.1589 +            }
  1.1590 +
  1.1591 +            leafIMFlags = 
  1.1592 +                flags->leafTests.cert_rev_method_independent_flags;
  1.1593 +            chainIMFlags =
  1.1594 +                flags->chainTests.cert_rev_method_independent_flags;
  1.1595 +
  1.1596 +            error =
  1.1597 +                PKIX_RevocationChecker_Create(leafIMFlags, chainIMFlags,
  1.1598 +                                              &revChecker, plContext);
  1.1599 +            if (error) {
  1.1600 +                break;
  1.1601 +            }
  1.1602 +
  1.1603 +            error =
  1.1604 +                PKIX_ProcessingParams_SetRevocationChecker(procParams,
  1.1605 +                                                revChecker, plContext);
  1.1606 +            if (error) {
  1.1607 +                break;
  1.1608 +            }
  1.1609 +
  1.1610 +            if (((PKIX_PL_NssContext*)plContext)->certificateUsage &
  1.1611 +                certificateUsageStatusResponder) {
  1.1612 +                validatingResponderCert = PKIX_TRUE;
  1.1613 +            }
  1.1614 +
  1.1615 +            error = setRevocationMethod(revChecker,
  1.1616 +                                        procParams, &flags->leafTests,
  1.1617 +                                        cert_revocation_method_crl,
  1.1618 +                                        PKIX_RevocationMethod_CRL,
  1.1619 +                                        validatingResponderCert,
  1.1620 +                                        PKIX_TRUE, plContext);
  1.1621 +            if (error) {
  1.1622 +                break;
  1.1623 +            }
  1.1624 +
  1.1625 +            error = setRevocationMethod(revChecker,
  1.1626 +                                        procParams, &flags->leafTests,
  1.1627 +                                        cert_revocation_method_ocsp,
  1.1628 +                                        PKIX_RevocationMethod_OCSP,
  1.1629 +                                        validatingResponderCert,
  1.1630 +                                        PKIX_TRUE, plContext);
  1.1631 +            if (error) {
  1.1632 +                break;
  1.1633 +            }
  1.1634 +
  1.1635 +            error = setRevocationMethod(revChecker,
  1.1636 +                                        procParams, &flags->chainTests,
  1.1637 +                                        cert_revocation_method_crl,
  1.1638 +                                        PKIX_RevocationMethod_CRL,
  1.1639 +                                        validatingResponderCert,
  1.1640 +                                        PKIX_FALSE, plContext);
  1.1641 +            if (error) {
  1.1642 +                break;
  1.1643 +            }
  1.1644 +
  1.1645 +            error = setRevocationMethod(revChecker,
  1.1646 +                                        procParams, &flags->chainTests,
  1.1647 +                                        cert_revocation_method_ocsp,
  1.1648 +                                        PKIX_RevocationMethod_OCSP,
  1.1649 +                                        validatingResponderCert,
  1.1650 +                                        PKIX_FALSE, plContext);
  1.1651 +            if (error) {
  1.1652 +                break;
  1.1653 +            }
  1.1654 +
  1.1655 +        }
  1.1656 +        break;
  1.1657 +
  1.1658 +        case cert_pi_trustAnchors:
  1.1659 +            certList = param->value.pointer.chain;
  1.1660 +            if (!certList) {
  1.1661 +                PORT_SetError(errCode);
  1.1662 +                r = SECFailure;
  1.1663 +                break;
  1.1664 +            }
  1.1665 +            error = PKIX_List_Create(&certListPkix, plContext);
  1.1666 +            if (error != NULL) {
  1.1667 +                break;
  1.1668 +            }
  1.1669 +            for(node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
  1.1670 +                node = CERT_LIST_NEXT(node) ) {
  1.1671 +                error = PKIX_PL_Cert_CreateFromCERTCertificate(node->cert,
  1.1672 +                                                      &certPkix, plContext);
  1.1673 +                if (error) {
  1.1674 +                    break;
  1.1675 +                }
  1.1676 +                error = PKIX_TrustAnchor_CreateWithCert(certPkix, &trustAnchor,
  1.1677 +                                                        plContext);
  1.1678 +                if (error) {
  1.1679 +                    break;
  1.1680 +                }
  1.1681 +                error = PKIX_List_AppendItem(certListPkix,
  1.1682 +                                 (PKIX_PL_Object*)trustAnchor, plContext);
  1.1683 +                 if (error) {
  1.1684 +                    break;
  1.1685 +                }
  1.1686 +                PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
  1.1687 +                trustAnchor = NULL;
  1.1688 +                PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
  1.1689 +                certPkix = NULL;
  1.1690 +            }
  1.1691 +            error =
  1.1692 +                PKIX_ProcessingParams_SetTrustAnchors(procParams, certListPkix,
  1.1693 +                                                      plContext);
  1.1694 +            break;
  1.1695 +
  1.1696 +        case cert_pi_useAIACertFetch:
  1.1697 +            error =
  1.1698 +                PKIX_ProcessingParams_SetUseAIAForCertFetching(procParams,
  1.1699 +                                     (PRBool)(param->value.scalar.b != 0),
  1.1700 +                                                               plContext);
  1.1701 +            break;
  1.1702 +
  1.1703 +        case cert_pi_chainVerifyCallback:
  1.1704 +        {
  1.1705 +            const CERTChainVerifyCallback *chainVerifyCallback =
  1.1706 +                param->value.pointer.chainVerifyCallback;
  1.1707 +            if (!chainVerifyCallback || !chainVerifyCallback->isChainValid) {
  1.1708 +                PORT_SetError(errCode);
  1.1709 +                r = SECFailure;
  1.1710 +                break;
  1.1711 +            }
  1.1712 +
  1.1713 +            nssContext->chainVerifyCallback = *chainVerifyCallback;
  1.1714 +        }
  1.1715 +        break;
  1.1716 +
  1.1717 +        case cert_pi_useOnlyTrustAnchors:
  1.1718 +            error =
  1.1719 +                PKIX_ProcessingParams_SetUseOnlyTrustAnchors(procParams,
  1.1720 +                                      (PRBool)(param->value.scalar.b != 0),
  1.1721 +                                                             plContext);
  1.1722 +            break;
  1.1723 +
  1.1724 +        default:
  1.1725 +            PORT_SetError(errCode);
  1.1726 +            r = SECFailure;
  1.1727 +            break;
  1.1728 +    }
  1.1729 +
  1.1730 +    if (policyOIDList != NULL)
  1.1731 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOIDList, plContext);
  1.1732 +
  1.1733 +    if (date != NULL) 
  1.1734 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)date, plContext);
  1.1735 +
  1.1736 +    if (revDate != NULL) 
  1.1737 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)revDate, plContext);
  1.1738 +
  1.1739 +    if (revChecker != NULL) 
  1.1740 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)revChecker, plContext);
  1.1741 +
  1.1742 +    if (certListPkix) 
  1.1743 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certListPkix, plContext);
  1.1744 +
  1.1745 +    if (trustAnchor) 
  1.1746 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
  1.1747 +
  1.1748 +    if (certPkix) 
  1.1749 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
  1.1750 +
  1.1751 +    if (error != NULL) {
  1.1752 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1.1753 +        PORT_SetError(errCode);
  1.1754 +        r = SECFailure;
  1.1755 +    }
  1.1756 +
  1.1757 +    return r; 
  1.1758 +
  1.1759 +}
  1.1760 +
  1.1761 +void
  1.1762 +cert_pkixDestroyValOutParam(CERTValOutParam *params)
  1.1763 +{
  1.1764 +    CERTValOutParam *i;
  1.1765 +
  1.1766 +    if (params == NULL) {
  1.1767 +        return;
  1.1768 +    }
  1.1769 +    for (i = params; i->type != cert_po_end; i++) {
  1.1770 +        switch (i->type) {
  1.1771 +        case cert_po_trustAnchor:
  1.1772 +            if (i->value.pointer.cert) {
  1.1773 +                CERT_DestroyCertificate(i->value.pointer.cert);
  1.1774 +                i->value.pointer.cert = NULL;
  1.1775 +            }
  1.1776 +            break;
  1.1777 +
  1.1778 +        case cert_po_certList:
  1.1779 +            if (i->value.pointer.chain) {
  1.1780 +                CERT_DestroyCertList(i->value.pointer.chain);
  1.1781 +                i->value.pointer.chain = NULL;
  1.1782 +            }
  1.1783 +            break;
  1.1784 +
  1.1785 +        default:
  1.1786 +            break;
  1.1787 +        }
  1.1788 +    }
  1.1789 +}
  1.1790 +
  1.1791 +static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags[2] = {
  1.1792 +  /* crl */
  1.1793 +  CERT_REV_M_TEST_USING_THIS_METHOD 
  1.1794 +  | CERT_REV_M_FORBID_NETWORK_FETCHING
  1.1795 +  | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1.1796 +  /* ocsp */
  1.1797 +  CERT_REV_M_TEST_USING_THIS_METHOD
  1.1798 +};
  1.1799 +
  1.1800 +static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags[2] = {
  1.1801 +  /* crl */
  1.1802 +  CERT_REV_M_TEST_USING_THIS_METHOD
  1.1803 +  | CERT_REV_M_FORBID_NETWORK_FETCHING
  1.1804 +  | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1.1805 +  /* ocsp */
  1.1806 +  0
  1.1807 +};
  1.1808 +
  1.1809 +static CERTRevocationMethodIndex 
  1.1810 +certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference = {
  1.1811 +  cert_revocation_method_crl
  1.1812 +};
  1.1813 +
  1.1814 +static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy = {
  1.1815 +  {
  1.1816 +    /* leafTests */
  1.1817 +    2,
  1.1818 +    certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags,
  1.1819 +    1,
  1.1820 +    &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference,
  1.1821 +    0
  1.1822 +  },
  1.1823 +  {
  1.1824 +    /* chainTests */
  1.1825 +    2,
  1.1826 +    certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags,
  1.1827 +    0,
  1.1828 +    0,
  1.1829 +    0
  1.1830 +  }
  1.1831 +};
  1.1832 +
  1.1833 +extern const CERTRevocationFlags*
  1.1834 +CERT_GetClassicOCSPEnabledSoftFailurePolicy()
  1.1835 +{
  1.1836 +    return &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy;
  1.1837 +}
  1.1838 +
  1.1839 +
  1.1840 +static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
  1.1841 +  /* crl */
  1.1842 +  CERT_REV_M_TEST_USING_THIS_METHOD 
  1.1843 +  | CERT_REV_M_FORBID_NETWORK_FETCHING
  1.1844 +  | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1.1845 +  /* ocsp */
  1.1846 +  CERT_REV_M_TEST_USING_THIS_METHOD
  1.1847 +  | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
  1.1848 +};
  1.1849 +
  1.1850 +static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
  1.1851 +  /* crl */
  1.1852 +  CERT_REV_M_TEST_USING_THIS_METHOD
  1.1853 +  | CERT_REV_M_FORBID_NETWORK_FETCHING
  1.1854 +  | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1.1855 +  /* ocsp */
  1.1856 +  0
  1.1857 +};
  1.1858 +
  1.1859 +static CERTRevocationMethodIndex 
  1.1860 +certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference = {
  1.1861 +  cert_revocation_method_crl
  1.1862 +};
  1.1863 +
  1.1864 +static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy = {
  1.1865 +  {
  1.1866 +    /* leafTests */
  1.1867 +    2,
  1.1868 +    certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags,
  1.1869 +    1,
  1.1870 +    &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference,
  1.1871 +    0
  1.1872 +  },
  1.1873 +  {
  1.1874 +    /* chainTests */
  1.1875 +    2,
  1.1876 +    certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags,
  1.1877 +    0,
  1.1878 +    0,
  1.1879 +    0
  1.1880 +  }
  1.1881 +};
  1.1882 +
  1.1883 +extern const CERTRevocationFlags*
  1.1884 +CERT_GetClassicOCSPEnabledHardFailurePolicy()
  1.1885 +{
  1.1886 +    return &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy;
  1.1887 +}
  1.1888 +
  1.1889 +
  1.1890 +static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags[2] = {
  1.1891 +  /* crl */
  1.1892 +  CERT_REV_M_TEST_USING_THIS_METHOD
  1.1893 +  | CERT_REV_M_FORBID_NETWORK_FETCHING
  1.1894 +  | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1.1895 +  /* ocsp */
  1.1896 +  0
  1.1897 +};
  1.1898 +
  1.1899 +static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags[2] = {
  1.1900 +  /* crl */
  1.1901 +  CERT_REV_M_TEST_USING_THIS_METHOD
  1.1902 +  | CERT_REV_M_FORBID_NETWORK_FETCHING
  1.1903 +  | CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
  1.1904 +  /* ocsp */
  1.1905 +  0
  1.1906 +};
  1.1907 +
  1.1908 +static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Disabled_Policy = {
  1.1909 +  {
  1.1910 +    /* leafTests */
  1.1911 +    2,
  1.1912 +    certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags,
  1.1913 +    0,
  1.1914 +    0,
  1.1915 +    0
  1.1916 +  },
  1.1917 +  {
  1.1918 +    /* chainTests */
  1.1919 +    2,
  1.1920 +    certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags,
  1.1921 +    0,
  1.1922 +    0,
  1.1923 +    0
  1.1924 +  }
  1.1925 +};
  1.1926 +
  1.1927 +extern const CERTRevocationFlags*
  1.1928 +CERT_GetClassicOCSPDisabledPolicy()
  1.1929 +{
  1.1930 +    return &certRev_NSS_3_11_Ocsp_Disabled_Policy;
  1.1931 +}
  1.1932 +
  1.1933 +
  1.1934 +static PRUint64 certRev_PKIX_Verify_Nist_Policy_LeafFlags[2] = {
  1.1935 +  /* crl */
  1.1936 +  CERT_REV_M_TEST_USING_THIS_METHOD
  1.1937 +  | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
  1.1938 +  | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
  1.1939 +  /* ocsp */
  1.1940 +  0
  1.1941 +};
  1.1942 +
  1.1943 +static PRUint64 certRev_PKIX_Verify_Nist_Policy_ChainFlags[2] = {
  1.1944 +  /* crl */
  1.1945 +  CERT_REV_M_TEST_USING_THIS_METHOD
  1.1946 +  | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
  1.1947 +  | CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
  1.1948 +  /* ocsp */
  1.1949 +  0
  1.1950 +};
  1.1951 +
  1.1952 +static const CERTRevocationFlags certRev_PKIX_Verify_Nist_Policy = {
  1.1953 +  {
  1.1954 +    /* leafTests */
  1.1955 +    2,
  1.1956 +    certRev_PKIX_Verify_Nist_Policy_LeafFlags,
  1.1957 +    0,
  1.1958 +    0,
  1.1959 +    0
  1.1960 +  },
  1.1961 +  {
  1.1962 +    /* chainTests */
  1.1963 +    2,
  1.1964 +    certRev_PKIX_Verify_Nist_Policy_ChainFlags,
  1.1965 +    0,
  1.1966 +    0,
  1.1967 +    0
  1.1968 +  }
  1.1969 +};
  1.1970 +
  1.1971 +extern const CERTRevocationFlags*
  1.1972 +CERT_GetPKIXVerifyNistRevocationPolicy()
  1.1973 +{
  1.1974 +    return &certRev_PKIX_Verify_Nist_Policy;
  1.1975 +}
  1.1976 +
  1.1977 +CERTRevocationFlags *
  1.1978 +CERT_AllocCERTRevocationFlags(
  1.1979 +    PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods,
  1.1980 +    PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods)
  1.1981 +{
  1.1982 +    CERTRevocationFlags *flags;
  1.1983 +    
  1.1984 +    flags = PORT_New(CERTRevocationFlags);
  1.1985 +    if (!flags)
  1.1986 +        return(NULL);
  1.1987 +    
  1.1988 +    flags->leafTests.number_of_defined_methods = number_leaf_methods;
  1.1989 +    flags->leafTests.cert_rev_flags_per_method = 
  1.1990 +        PORT_NewArray(PRUint64, number_leaf_methods);
  1.1991 +
  1.1992 +    flags->leafTests.number_of_preferred_methods = number_leaf_pref_methods;
  1.1993 +    flags->leafTests.preferred_methods = 
  1.1994 +        PORT_NewArray(CERTRevocationMethodIndex, number_leaf_pref_methods);
  1.1995 +
  1.1996 +    flags->chainTests.number_of_defined_methods = number_chain_methods;
  1.1997 +    flags->chainTests.cert_rev_flags_per_method = 
  1.1998 +        PORT_NewArray(PRUint64, number_chain_methods);
  1.1999 +
  1.2000 +    flags->chainTests.number_of_preferred_methods = number_chain_pref_methods;
  1.2001 +    flags->chainTests.preferred_methods = 
  1.2002 +        PORT_NewArray(CERTRevocationMethodIndex, number_chain_pref_methods);
  1.2003 +    
  1.2004 +    if (!flags->leafTests.cert_rev_flags_per_method
  1.2005 +        || !flags->leafTests.preferred_methods
  1.2006 +        || !flags->chainTests.cert_rev_flags_per_method
  1.2007 +        || !flags->chainTests.preferred_methods) {
  1.2008 +        CERT_DestroyCERTRevocationFlags(flags);
  1.2009 +        return (NULL);
  1.2010 +    }
  1.2011 +    
  1.2012 +    return flags;
  1.2013 +}
  1.2014 +
  1.2015 +void CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags)
  1.2016 +{
  1.2017 +    if (!flags)
  1.2018 +	return;
  1.2019 +  
  1.2020 +    if (flags->leafTests.cert_rev_flags_per_method)
  1.2021 +        PORT_Free(flags->leafTests.cert_rev_flags_per_method);
  1.2022 +
  1.2023 +    if (flags->leafTests.preferred_methods)
  1.2024 +        PORT_Free(flags->leafTests.preferred_methods);
  1.2025 +    
  1.2026 +    if (flags->chainTests.cert_rev_flags_per_method)
  1.2027 +        PORT_Free(flags->chainTests.cert_rev_flags_per_method);
  1.2028 +
  1.2029 +    if (flags->chainTests.preferred_methods)
  1.2030 +        PORT_Free(flags->chainTests.preferred_methods);
  1.2031 +
  1.2032 +     PORT_Free(flags);
  1.2033 +}
  1.2034 +
  1.2035 +/*
  1.2036 + * CERT_PKIXVerifyCert
  1.2037 + *
  1.2038 + * Verify a Certificate using the PKIX library.
  1.2039 + *
  1.2040 + * Parameters:
  1.2041 + *  cert    - the target certificate to verify. Must be non-null
  1.2042 + *  params  - an array of type/value parameters which can be
  1.2043 + *            used to modify the behavior of the validation
  1.2044 + *            algorithm, or supply additional constraints.
  1.2045 + *
  1.2046 + *  outputTrustAnchor - the trust anchor which the certificate
  1.2047 + *                      chains to. The caller is responsible
  1.2048 + *                      for freeing this.
  1.2049 + *
  1.2050 + * Example Usage:
  1.2051 + *    CERTValParam args[3];
  1.2052 + *    args[0].type = cvpt_policyOID;
  1.2053 + *    args[0].value.si = oid;
  1.2054 + *    args[1].type = revCheckRequired;
  1.2055 + *    args[1].value.b = PR_TRUE;
  1.2056 + *    args[2].type = cvpt_end;
  1.2057 + *
  1.2058 + *    CERT_PKIXVerifyCert(cert, &output, args
  1.2059 + */
  1.2060 +SECStatus CERT_PKIXVerifyCert(
  1.2061 + CERTCertificate *cert,
  1.2062 + SECCertificateUsage usages,
  1.2063 + CERTValInParam *paramsIn,
  1.2064 + CERTValOutParam *paramsOut,
  1.2065 + void *wincx)
  1.2066 +{
  1.2067 +    SECStatus             r = SECFailure;
  1.2068 +    PKIX_Error *          error = NULL;
  1.2069 +    PKIX_ProcessingParams *procParams = NULL;
  1.2070 +    PKIX_BuildResult *    buildResult = NULL;
  1.2071 +    void *                nbioContext = NULL;  /* for non-blocking IO */
  1.2072 +    void *                buildState = NULL;   /* for non-blocking IO */
  1.2073 +    PKIX_CertSelector *   certSelector = NULL;
  1.2074 +    PKIX_List *           certStores = NULL;
  1.2075 +    PKIX_ValidateResult * valResult = NULL;
  1.2076 +    PKIX_VerifyNode     * verifyNode = NULL;
  1.2077 +    PKIX_TrustAnchor *    trustAnchor = NULL;
  1.2078 +    PKIX_PL_Cert *        trustAnchorCert = NULL;
  1.2079 +    PKIX_List *           builtCertList = NULL;
  1.2080 +    CERTValOutParam *     oparam = NULL;
  1.2081 +    int i=0;
  1.2082 +
  1.2083 +    void *plContext = NULL;
  1.2084 +
  1.2085 +#ifdef PKIX_OBJECT_LEAK_TEST
  1.2086 +    int  leakedObjNum = 0;
  1.2087 +    int  memLeakLoopCount = 0;
  1.2088 +    int  objCountTable[PKIX_NUMTYPES];
  1.2089 +    int  fnInvLocalCount = 0;
  1.2090 +    PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
  1.2091 +
  1.2092 +    if (usePKIXValidationEngine) {
  1.2093 +        /* current memory leak testing implementation does not allow
  1.2094 +         * to run simultaneous tests one the same or a different threads.
  1.2095 +         * Setting the variable to false, to make additional chain
  1.2096 +         * validations be handled by old nss. */
  1.2097 +        usePKIXValidationEngine = PR_FALSE;
  1.2098 +    }
  1.2099 +    testStartFnStackPosition = 1;
  1.2100 +    fnStackNameArr[0] = "CERT_PKIXVerifyCert";
  1.2101 +    fnStackInvCountArr[0] = 0;
  1.2102 +    PKIX_Boolean abortOnLeak = 
  1.2103 +        (PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ?
  1.2104 +                                                   PKIX_FALSE : PKIX_TRUE;
  1.2105 +    runningLeakTest = PKIX_TRUE;
  1.2106 +
  1.2107 +    /* Prevent multi-threaded run of object leak test */
  1.2108 +    fnInvLocalCount = PR_ATOMIC_INCREMENT(&parallelFnInvocationCount);
  1.2109 +    PORT_Assert(fnInvLocalCount == 1);
  1.2110 +
  1.2111 +do {
  1.2112 +    r = SECFailure;
  1.2113 +    error = NULL;
  1.2114 +    procParams = NULL;
  1.2115 +    buildResult = NULL;
  1.2116 +    nbioContext = NULL;  /* for non-blocking IO */
  1.2117 +    buildState = NULL;   /* for non-blocking IO */
  1.2118 +    certSelector = NULL;
  1.2119 +    certStores = NULL;
  1.2120 +    valResult = NULL;
  1.2121 +    verifyNode = NULL;
  1.2122 +    trustAnchor = NULL;
  1.2123 +    trustAnchorCert = NULL;
  1.2124 +    builtCertList = NULL;
  1.2125 +    oparam = NULL;
  1.2126 +    i=0;
  1.2127 +    errorGenerated = PKIX_FALSE;
  1.2128 +    stackPosition = 0;
  1.2129 +
  1.2130 +    if (leakedObjNum) {
  1.2131 +        pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
  1.2132 +    }
  1.2133 +    memLeakLoopCount += 1;
  1.2134 +#endif /* PKIX_OBJECT_LEAK_TEST */
  1.2135 +
  1.2136 +    error = PKIX_PL_NssContext_Create(
  1.2137 +            0, PR_FALSE /*use arena*/, wincx, &plContext);
  1.2138 +    if (error != NULL) {        /* need pkix->nss error map */
  1.2139 +        PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
  1.2140 +        goto cleanup;
  1.2141 +    }
  1.2142 +
  1.2143 +    error = pkix_pl_NssContext_SetCertUsage(usages, plContext);
  1.2144 +    if (error != NULL) {
  1.2145 +        PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.2146 +        goto cleanup;
  1.2147 +    }
  1.2148 +
  1.2149 +    error = PKIX_ProcessingParams_Create(&procParams, plContext);
  1.2150 +    if (error != NULL) {              /* need pkix->nss error map */
  1.2151 +        PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
  1.2152 +        goto cleanup;
  1.2153 +    }
  1.2154 +
  1.2155 +    /* local cert store should be set into procParams before
  1.2156 +     * filling in revocation settings. */
  1.2157 +    certStores = cert_GetCertStores(plContext);
  1.2158 +    if (certStores == NULL) {
  1.2159 +        goto cleanup;
  1.2160 +    }
  1.2161 +    error = PKIX_ProcessingParams_SetCertStores
  1.2162 +        (procParams, certStores, plContext);
  1.2163 +    if (error != NULL) {
  1.2164 +        goto cleanup;
  1.2165 +    }
  1.2166 +
  1.2167 +    /* now process the extensible input parameters structure */
  1.2168 +    if (paramsIn != NULL) {
  1.2169 +        i=0;
  1.2170 +        while (paramsIn[i].type != cert_pi_end) {
  1.2171 +            if (paramsIn[i].type >= cert_pi_max) {
  1.2172 +                PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.2173 +                goto cleanup;
  1.2174 +            }
  1.2175 +            if (cert_pkixSetParam(procParams,
  1.2176 +                     &paramsIn[i],plContext) != SECSuccess) {
  1.2177 +                PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.2178 +                goto cleanup;
  1.2179 +            }
  1.2180 +            i++;
  1.2181 +        }
  1.2182 +    }
  1.2183 +
  1.2184 +    certSelector = cert_GetTargetCertConstraints(cert, plContext);
  1.2185 +    if (certSelector == NULL) {
  1.2186 +        goto cleanup;
  1.2187 +    }
  1.2188 +    error = PKIX_ProcessingParams_SetTargetCertConstraints
  1.2189 +        (procParams, certSelector, plContext);
  1.2190 +    if (error != NULL) {
  1.2191 +        goto cleanup;
  1.2192 +    }
  1.2193 +
  1.2194 +    error = PKIX_BuildChain( procParams, &nbioContext,
  1.2195 +                             &buildState, &buildResult, &verifyNode,
  1.2196 +                             plContext);
  1.2197 +    if (error != NULL) {
  1.2198 +        goto cleanup;
  1.2199 +    }
  1.2200 +
  1.2201 +    error = PKIX_BuildResult_GetValidateResult( buildResult, &valResult,
  1.2202 +                                                plContext);
  1.2203 +    if (error != NULL) {
  1.2204 +        goto cleanup;
  1.2205 +    }
  1.2206 +
  1.2207 +    error = PKIX_ValidateResult_GetTrustAnchor( valResult, &trustAnchor,
  1.2208 +                                                plContext);
  1.2209 +    if (error != NULL) {
  1.2210 +        goto cleanup;
  1.2211 +    }
  1.2212 +
  1.2213 +    if (trustAnchor != NULL) {
  1.2214 +        error = PKIX_TrustAnchor_GetTrustedCert( trustAnchor, &trustAnchorCert,
  1.2215 +                                                 plContext);
  1.2216 +        if (error != NULL) {
  1.2217 +            goto cleanup;
  1.2218 +        }
  1.2219 +    }
  1.2220 +
  1.2221 +#ifdef PKIX_OBJECT_LEAK_TEST
  1.2222 +    /* Can not continue if error was generated but not returned.
  1.2223 +     * Jumping to cleanup. */
  1.2224 +    if (errorGenerated) goto cleanup;
  1.2225 +#endif /* PKIX_OBJECT_LEAK_TEST */
  1.2226 +
  1.2227 +    oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor);
  1.2228 +    if (oparam != NULL) {
  1.2229 +        if (trustAnchorCert != NULL) {
  1.2230 +            oparam->value.pointer.cert =
  1.2231 +                    cert_NSSCertFromPKIXCert(trustAnchorCert);
  1.2232 +        } else {
  1.2233 +            oparam->value.pointer.cert = NULL;
  1.2234 +        }
  1.2235 +    }
  1.2236 +
  1.2237 +    error = PKIX_BuildResult_GetCertChain( buildResult, &builtCertList,
  1.2238 +                                                plContext);
  1.2239 +    if (error != NULL) {
  1.2240 +        goto cleanup;
  1.2241 +    }
  1.2242 +
  1.2243 +    oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_certList);
  1.2244 +    if (oparam != NULL) {
  1.2245 +        error = cert_PkixToNssCertsChain(builtCertList,
  1.2246 +                                         &oparam->value.pointer.chain,
  1.2247 +                                         plContext);
  1.2248 +        if (error) goto cleanup;
  1.2249 +    }
  1.2250 +
  1.2251 +    r = SECSuccess;
  1.2252 +
  1.2253 +cleanup:
  1.2254 +    if (verifyNode) {
  1.2255 +        /* Return validation log only upon error. */
  1.2256 +        oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_errorLog);
  1.2257 +#ifdef PKIX_OBJECT_LEAK_TEST
  1.2258 +        if (!errorGenerated)
  1.2259 +#endif /* PKIX_OBJECT_LEAK_TEST */
  1.2260 +        if (r && oparam != NULL) {
  1.2261 +            PKIX_Error *tmpError =
  1.2262 +                cert_GetLogFromVerifyNode(oparam->value.pointer.log,
  1.2263 +                                          verifyNode, plContext);
  1.2264 +            if (tmpError) {
  1.2265 +                PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
  1.2266 +            }
  1.2267 +        }
  1.2268 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)verifyNode, plContext);
  1.2269 +    }
  1.2270 +
  1.2271 +    if (procParams != NULL) 
  1.2272 +       PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
  1.2273 +
  1.2274 +    if (trustAnchorCert != NULL) 
  1.2275 +       PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchorCert, plContext);
  1.2276 +
  1.2277 +    if (trustAnchor != NULL) 
  1.2278 +       PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
  1.2279 +
  1.2280 +    if (valResult != NULL) 
  1.2281 +       PKIX_PL_Object_DecRef((PKIX_PL_Object *)valResult, plContext);
  1.2282 +
  1.2283 +    if (buildResult != NULL) 
  1.2284 +       PKIX_PL_Object_DecRef((PKIX_PL_Object *)buildResult, plContext);
  1.2285 +
  1.2286 +    if (certStores != NULL) 
  1.2287 +       PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
  1.2288 +
  1.2289 +    if (certSelector != NULL) 
  1.2290 +       PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
  1.2291 +
  1.2292 +    if (builtCertList != NULL) 
  1.2293 +       PKIX_PL_Object_DecRef((PKIX_PL_Object *)builtCertList, plContext);
  1.2294 +
  1.2295 +    if (error != NULL) {
  1.2296 +        SECErrorCodes         nssErrorCode = 0;
  1.2297 +
  1.2298 +        cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
  1.2299 +        cert_pkixDestroyValOutParam(paramsOut);
  1.2300 +        PORT_SetError(nssErrorCode);
  1.2301 +        PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
  1.2302 +    }
  1.2303 +
  1.2304 +    PKIX_PL_NssContext_Destroy(plContext);
  1.2305 +
  1.2306 +#ifdef PKIX_OBJECT_LEAK_TEST
  1.2307 +    leakedObjNum =
  1.2308 +        pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
  1.2309 +
  1.2310 +    if (pkixLog && leakedObjNum) {
  1.2311 +        PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
  1.2312 +                            "Stack %s\n", memLeakLoopCount, errorFnStackString));
  1.2313 +    }
  1.2314 +    PR_Free(errorFnStackString);
  1.2315 +    errorFnStackString = NULL;
  1.2316 +    if (abortOnLeak) {
  1.2317 +        PORT_Assert(leakedObjNum == 0);
  1.2318 +    }
  1.2319 +    
  1.2320 +} while (errorGenerated);
  1.2321 +
  1.2322 +    runningLeakTest = PKIX_FALSE; 
  1.2323 +    PR_ATOMIC_DECREMENT(&parallelFnInvocationCount);
  1.2324 +    usePKIXValidationEngine = savedUsePkixEngFlag;
  1.2325 +#endif /* PKIX_OBJECT_LEAK_TEST */
  1.2326 +
  1.2327 +    return r;
  1.2328 +}

mercurial