mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-10 18:00:15 +01:00
44b7f056d9
bug1001332, 56b691c003ad, bug1086145, bug1054069, bug1155922, bug991783, bug1125025, bug1162521, bug1162644, bug1132941, bug1164364, bug1166205, bug1166163, bug1166515, bug1138554, bug1167046, bug1167043, bug1169451, bug1172128, bug1170322, bug102794, bug1128184, bug557830, bug1174648, bug1180244, bug1177784, bug1173413, bug1169174, bug1084669, bug951455, bug1183395, bug1177430, bug1183827, bug1160139, bug1154106, bug1142209, bug1185033, bug1193467, bug1182667(with sha512 changes backed out, which breaks VC6 compilation), bug1158489, bug337796
2260 lines
68 KiB
C
2260 lines
68 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
/*
|
|
* nss_pkix_proxy.h
|
|
*
|
|
* PKIX - NSS proxy functions
|
|
*
|
|
* NOTE: All structures, functions, data types are parts of library private
|
|
* api and are subjects to change in any following releases.
|
|
*
|
|
*/
|
|
#include "prerror.h"
|
|
#include "prprf.h"
|
|
|
|
#include "nspr.h"
|
|
#include "pk11func.h"
|
|
#include "certdb.h"
|
|
#include "cert.h"
|
|
#include "secerr.h"
|
|
#include "nssb64.h"
|
|
#include "secasn1.h"
|
|
#include "secder.h"
|
|
#include "pkit.h"
|
|
|
|
#include "pkix_pl_common.h"
|
|
|
|
extern PRLogModuleInfo *pkixLog;
|
|
|
|
#ifdef PKIX_OBJECT_LEAK_TEST
|
|
|
|
extern PKIX_UInt32
|
|
pkix_pl_lifecycle_ObjectLeakCheck(int *);
|
|
|
|
extern SECStatus
|
|
pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable);
|
|
|
|
PRInt32 parallelFnInvocationCount;
|
|
#endif /* PKIX_OBJECT_LEAK_TEST */
|
|
|
|
|
|
static PRBool usePKIXValidationEngine = PR_FALSE;
|
|
|
|
/*
|
|
* FUNCTION: CERT_SetUsePKIXForValidation
|
|
* DESCRIPTION:
|
|
*
|
|
* Enables or disables use of libpkix for certificate validation
|
|
*
|
|
* PARAMETERS:
|
|
* "enable"
|
|
* PR_TRUE: enables use of libpkix for cert validation.
|
|
* PR_FALSE: disables.
|
|
* THREAD SAFETY:
|
|
* NOT Thread Safe.
|
|
* RETURNS:
|
|
* Returns SECSuccess if successfully enabled
|
|
*/
|
|
SECStatus
|
|
CERT_SetUsePKIXForValidation(PRBool enable)
|
|
{
|
|
usePKIXValidationEngine = (enable > 0) ? PR_TRUE : PR_FALSE;
|
|
return SECSuccess;
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: CERT_GetUsePKIXForValidation
|
|
* DESCRIPTION:
|
|
*
|
|
* Checks if libpkix building function should be use for certificate
|
|
* chain building.
|
|
*
|
|
* PARAMETERS:
|
|
* NONE
|
|
* THREAD SAFETY:
|
|
* NOT Thread Safe
|
|
* RETURNS:
|
|
* Returns PR_TRUE if libpkix should be used. PR_FALSE otherwise.
|
|
*/
|
|
PRBool
|
|
CERT_GetUsePKIXForValidation()
|
|
{
|
|
return usePKIXValidationEngine;
|
|
}
|
|
|
|
#ifdef NOTDEF
|
|
/*
|
|
* FUNCTION: cert_NssKeyUsagesToPkix
|
|
* DESCRIPTION:
|
|
*
|
|
* Converts nss key usage bit field(PRUint32) to pkix key usage
|
|
* bit field.
|
|
*
|
|
* PARAMETERS:
|
|
* "nssKeyUsage"
|
|
* Nss key usage bit field.
|
|
* "pkixKeyUsage"
|
|
* Pkix key usage big field.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds.
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way.
|
|
*/
|
|
static PKIX_Error*
|
|
cert_NssKeyUsagesToPkix(
|
|
PRUint32 nssKeyUsage,
|
|
PKIX_UInt32 *pPkixKeyUsage,
|
|
void *plContext)
|
|
{
|
|
PKIX_UInt32 pkixKeyUsage = 0;
|
|
|
|
PKIX_ENTER(CERTVFYPKIX, "cert_NssKeyUsagesToPkix");
|
|
PKIX_NULLCHECK_ONE(pPkixKeyUsage);
|
|
|
|
*pPkixKeyUsage = 0;
|
|
|
|
if (nssKeyUsage & KU_DIGITAL_SIGNATURE) {
|
|
pkixKeyUsage |= PKIX_DIGITAL_SIGNATURE;
|
|
}
|
|
|
|
if (nssKeyUsage & KU_NON_REPUDIATION) {
|
|
pkixKeyUsage |= PKIX_NON_REPUDIATION;
|
|
}
|
|
|
|
if (nssKeyUsage & KU_KEY_ENCIPHERMENT) {
|
|
pkixKeyUsage |= PKIX_KEY_ENCIPHERMENT;
|
|
}
|
|
|
|
if (nssKeyUsage & KU_DATA_ENCIPHERMENT) {
|
|
pkixKeyUsage |= PKIX_DATA_ENCIPHERMENT;
|
|
}
|
|
|
|
if (nssKeyUsage & KU_KEY_AGREEMENT) {
|
|
pkixKeyUsage |= PKIX_KEY_AGREEMENT;
|
|
}
|
|
|
|
if (nssKeyUsage & KU_KEY_CERT_SIGN) {
|
|
pkixKeyUsage |= PKIX_KEY_CERT_SIGN;
|
|
}
|
|
|
|
if (nssKeyUsage & KU_CRL_SIGN) {
|
|
pkixKeyUsage |= PKIX_CRL_SIGN;
|
|
}
|
|
|
|
if (nssKeyUsage & KU_ENCIPHER_ONLY) {
|
|
pkixKeyUsage |= PKIX_ENCIPHER_ONLY;
|
|
}
|
|
|
|
/* Not supported. XXX we should support this once it is
|
|
* fixed in NSS */
|
|
/* pkixKeyUsage |= PKIX_DECIPHER_ONLY; */
|
|
|
|
*pPkixKeyUsage = pkixKeyUsage;
|
|
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
}
|
|
|
|
extern SECOidTag ekuOidStrings[];
|
|
|
|
enum {
|
|
ekuIndexSSLServer = 0,
|
|
ekuIndexSSLClient,
|
|
ekuIndexCodeSigner,
|
|
ekuIndexEmail,
|
|
ekuIndexTimeStamp,
|
|
ekuIndexStatusResponder,
|
|
ekuIndexUnknown
|
|
} ekuIndex;
|
|
|
|
typedef struct {
|
|
SECCertUsage certUsage;
|
|
PRUint32 ekuStringIndex;
|
|
} SECCertUsageToEku;
|
|
|
|
const SECCertUsageToEku certUsageEkuStringMap[] = {
|
|
{certUsageSSLClient, ekuIndexSSLClient},
|
|
{certUsageSSLServer, ekuIndexSSLServer},
|
|
{certUsageSSLCA, ekuIndexSSLServer},
|
|
{certUsageEmailSigner, ekuIndexEmail},
|
|
{certUsageEmailRecipient, ekuIndexEmail},
|
|
{certUsageObjectSigner, ekuIndexCodeSigner},
|
|
{certUsageUserCertImport, ekuIndexUnknown},
|
|
{certUsageVerifyCA, ekuIndexUnknown},
|
|
{certUsageProtectedObjectSigner, ekuIndexUnknown},
|
|
{certUsageStatusResponder, ekuIndexStatusResponder},
|
|
{certUsageAnyCA, ekuIndexUnknown},
|
|
};
|
|
|
|
/*
|
|
* FUNCTION: cert_NssCertificateUsageToPkixKUAndEKU
|
|
* DESCRIPTION:
|
|
*
|
|
* Converts nss CERTCertificateUsage bit field to pkix key and
|
|
* extended key usages.
|
|
*
|
|
* PARAMETERS:
|
|
* "cert"
|
|
* Pointer to CERTCertificate structure of validating cert.
|
|
* "requiredCertUsages"
|
|
* Required usage that will be converted to pkix eku and ku.
|
|
* "requiredKeyUsage",
|
|
* Additional key usages impose to cert.
|
|
* "isCA",
|
|
* it true, convert usages for cert that is a CA cert.
|
|
* "ppkixEKUList"
|
|
* Returned address of a list of pkix extended key usages.
|
|
* "ppkixKU"
|
|
* Returned address of pkix required key usages bit field.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds.
|
|
* Returns a Cert Verify Error if the function fails in an unrecoverable way.
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way.
|
|
*/
|
|
static PKIX_Error*
|
|
cert_NssCertificateUsageToPkixKUAndEKU(
|
|
CERTCertificate *cert,
|
|
SECCertUsage requiredCertUsage,
|
|
PRUint32 requiredKeyUsages,
|
|
PRBool isCA,
|
|
PKIX_List **ppkixEKUList,
|
|
PKIX_UInt32 *ppkixKU,
|
|
void *plContext)
|
|
{
|
|
PKIX_List *ekuOidsList = NULL;
|
|
PKIX_PL_OID *ekuOid = NULL;
|
|
int i = 0;
|
|
int ekuIndex = ekuIndexUnknown;
|
|
|
|
PKIX_ENTER(CERTVFYPKIX, "cert_NssCertificateUsageToPkixEku");
|
|
PKIX_NULLCHECK_TWO(ppkixEKUList, ppkixKU);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_List_Create(&ekuOidsList, plContext),
|
|
PKIX_LISTCREATEFAILED);
|
|
|
|
for (;i < PR_ARRAY_SIZE(certUsageEkuStringMap);i++) {
|
|
const SECCertUsageToEku *usageToEkuElem =
|
|
&certUsageEkuStringMap[i];
|
|
if (usageToEkuElem->certUsage == requiredCertUsage) {
|
|
ekuIndex = usageToEkuElem->ekuStringIndex;
|
|
break;
|
|
}
|
|
}
|
|
if (ekuIndex != ekuIndexUnknown) {
|
|
PRUint32 reqKeyUsage = 0;
|
|
PRUint32 reqCertType = 0;
|
|
|
|
CERT_KeyUsageAndTypeForCertUsage(requiredCertUsage, isCA,
|
|
&reqKeyUsage,
|
|
&reqCertType);
|
|
|
|
requiredKeyUsages |= reqKeyUsage;
|
|
|
|
PKIX_CHECK(
|
|
PKIX_PL_OID_Create(ekuOidStrings[ekuIndex], &ekuOid,
|
|
plContext),
|
|
PKIX_OIDCREATEFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_List_AppendItem(ekuOidsList, (PKIX_PL_Object *)ekuOid,
|
|
plContext),
|
|
PKIX_LISTAPPENDITEMFAILED);
|
|
|
|
PKIX_DECREF(ekuOid);
|
|
}
|
|
|
|
PKIX_CHECK(
|
|
cert_NssKeyUsagesToPkix(requiredKeyUsages, ppkixKU, plContext),
|
|
PKIX_NSSCERTIFICATEUSAGETOPKIXKUANDEKUFAILED);
|
|
|
|
*ppkixEKUList = ekuOidsList;
|
|
ekuOidsList = NULL;
|
|
|
|
cleanup:
|
|
|
|
PKIX_DECREF(ekuOid);
|
|
PKIX_DECREF(ekuOidsList);
|
|
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
}
|
|
|
|
#endif
|
|
|
|
/*
|
|
* FUNCTION: cert_ProcessingParamsSetKeyAndCertUsage
|
|
* DESCRIPTION:
|
|
*
|
|
* Converts cert usage to pkix KU type and sets
|
|
* converted data into PKIX_ProcessingParams object. It also sets
|
|
* proper cert usage into nsscontext object.
|
|
*
|
|
* PARAMETERS:
|
|
* "procParams"
|
|
* Pointer to PKIX_ProcessingParams used during validation.
|
|
* "requiredCertUsage"
|
|
* Required certificate usages the certificate and chain is built and
|
|
* validated for.
|
|
* "requiredKeyUsage"
|
|
* Request additional key usages the certificate should be validated for.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds.
|
|
* Returns a Cert Verify Error if the function fails in an unrecoverable way.
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way.
|
|
*/
|
|
static PKIX_Error*
|
|
cert_ProcessingParamsSetKeyAndCertUsage(
|
|
PKIX_ProcessingParams *procParams,
|
|
SECCertUsage requiredCertUsage,
|
|
PRUint32 requiredKeyUsages,
|
|
void *plContext)
|
|
{
|
|
PKIX_CertSelector *certSelector = NULL;
|
|
PKIX_ComCertSelParams *certSelParams = NULL;
|
|
PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext*)plContext;
|
|
|
|
PKIX_ENTER(CERTVFYPKIX, "cert_ProcessingParamsSetKeyAndCertUsage");
|
|
PKIX_NULLCHECK_TWO(procParams, nssContext);
|
|
|
|
PKIX_CHECK(
|
|
pkix_pl_NssContext_SetCertUsage(
|
|
((SECCertificateUsage)1) << requiredCertUsage, nssContext),
|
|
PKIX_NSSCONTEXTSETCERTUSAGEFAILED);
|
|
|
|
if (requiredKeyUsages) {
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_GetTargetCertConstraints(procParams,
|
|
&certSelector, plContext),
|
|
PKIX_PROCESSINGPARAMSGETTARGETCERTCONSTRAINTSFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_CertSelector_GetCommonCertSelectorParams(certSelector,
|
|
&certSelParams, plContext),
|
|
PKIX_CERTSELECTORGETCOMMONCERTSELECTORPARAMSFAILED);
|
|
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ComCertSelParams_SetKeyUsage(certSelParams, requiredKeyUsages,
|
|
plContext),
|
|
PKIX_COMCERTSELPARAMSSETKEYUSAGEFAILED);
|
|
}
|
|
cleanup:
|
|
PKIX_DECREF(certSelector);
|
|
PKIX_DECREF(certSelParams);
|
|
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
}
|
|
|
|
/*
|
|
* Unused parameters:
|
|
*
|
|
* CERTCertList *initialChain,
|
|
* CERTCertStores certStores,
|
|
* CERTCertRevCheckers certRevCheckers,
|
|
* CERTCertChainCheckers certChainCheckers,
|
|
* SECItem *initPolicies,
|
|
* PRBool policyQualifierRejected,
|
|
* PRBool anyPolicyInhibited,
|
|
* PRBool reqExplicitPolicy,
|
|
* PRBool policyMappingInhibited,
|
|
* PKIX_CertSelector certConstraints,
|
|
*/
|
|
|
|
/*
|
|
* FUNCTION: cert_CreatePkixProcessingParams
|
|
* DESCRIPTION:
|
|
*
|
|
* Creates and fills in PKIX_ProcessingParams structure to be used
|
|
* for certificate chain building.
|
|
*
|
|
* PARAMETERS:
|
|
* "cert"
|
|
* Pointer to the CERTCertificate: the leaf certificate of a chain.
|
|
* "time"
|
|
* Validity time.
|
|
* "wincx"
|
|
* Nss db password token.
|
|
* "useArena"
|
|
* Flags to use arena for data allocation during chain building process.
|
|
* "pprocParams"
|
|
* Address to return created processing parameters.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds.
|
|
* Returns a Cert Verify Error if the function fails in an unrecoverable way.
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way.
|
|
*/
|
|
static PKIX_Error*
|
|
cert_CreatePkixProcessingParams(
|
|
CERTCertificate *cert,
|
|
PRBool checkSig, /* not used yet. See bug 391476 */
|
|
PRTime time,
|
|
void *wincx,
|
|
PRBool useArena,
|
|
PRBool disableOCSPRemoteFetching,
|
|
PKIX_ProcessingParams **pprocParams,
|
|
void **pplContext)
|
|
{
|
|
PKIX_List *anchors = NULL;
|
|
PKIX_PL_Cert *targetCert = NULL;
|
|
PKIX_PL_Date *date = NULL;
|
|
PKIX_ProcessingParams *procParams = NULL;
|
|
PKIX_CertSelector *certSelector = NULL;
|
|
PKIX_ComCertSelParams *certSelParams = NULL;
|
|
PKIX_CertStore *certStore = NULL;
|
|
PKIX_List *certStores = NULL;
|
|
PKIX_RevocationChecker *revChecker = NULL;
|
|
PKIX_UInt32 methodFlags = 0;
|
|
void *plContext = NULL;
|
|
CERTStatusConfig *statusConfig = NULL;
|
|
|
|
PKIX_ENTER(CERTVFYPKIX, "cert_CreatePkixProcessingParams");
|
|
PKIX_NULLCHECK_TWO(cert, pprocParams);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_PL_NssContext_Create(0, useArena, wincx, &plContext),
|
|
PKIX_NSSCONTEXTCREATEFAILED);
|
|
|
|
*pplContext = plContext;
|
|
|
|
#ifdef PKIX_NOTDEF
|
|
/* Functions should be implemented in patch for 390532 */
|
|
PKIX_CHECK(
|
|
pkix_pl_NssContext_SetCertSignatureCheck(checkSig,
|
|
(PKIX_PL_NssContext*)plContext),
|
|
PKIX_NSSCONTEXTSETCERTSIGNCHECKFAILED);
|
|
|
|
#endif /* PKIX_NOTDEF */
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_Create(&procParams, plContext),
|
|
PKIX_PROCESSINGPARAMSCREATEFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ComCertSelParams_Create(&certSelParams, plContext),
|
|
PKIX_COMCERTSELPARAMSCREATEFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_PL_Cert_CreateFromCERTCertificate(cert, &targetCert, plContext),
|
|
PKIX_CERTCREATEWITHNSSCERTFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ComCertSelParams_SetCertificate(certSelParams,
|
|
targetCert, plContext),
|
|
PKIX_COMCERTSELPARAMSSETCERTIFICATEFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext),
|
|
PKIX_COULDNOTCREATECERTSELECTOROBJECT);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_CertSelector_SetCommonCertSelectorParams(certSelector,
|
|
certSelParams, plContext),
|
|
PKIX_CERTSELECTORSETCOMMONCERTSELECTORPARAMSFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_SetTargetCertConstraints(procParams,
|
|
certSelector, plContext),
|
|
PKIX_PROCESSINGPARAMSSETTARGETCERTCONSTRAINTSFAILED);
|
|
|
|
/* Turn off quialification of target cert since leaf cert is
|
|
* already check for date validity, key usages and extended
|
|
* key usages. */
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_SetQualifyTargetCert(procParams, PKIX_FALSE,
|
|
plContext),
|
|
PKIX_PROCESSINGPARAMSSETQUALIFYTARGETCERTFLAGFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_PL_Pk11CertStore_Create(&certStore, plContext),
|
|
PKIX_PK11CERTSTORECREATEFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_List_Create(&certStores, plContext),
|
|
PKIX_UNABLETOCREATELIST);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore,
|
|
plContext),
|
|
PKIX_LISTAPPENDITEMFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_SetCertStores(procParams, certStores,
|
|
plContext),
|
|
PKIX_PROCESSINGPARAMSADDCERTSTOREFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_PL_Date_CreateFromPRTime(time, &date, plContext),
|
|
PKIX_DATECREATEFROMPRTIMEFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_SetDate(procParams, date, plContext),
|
|
PKIX_PROCESSINGPARAMSSETDATEFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_RevocationChecker_Create(
|
|
PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
|
|
PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT,
|
|
PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST |
|
|
PKIX_REV_MI_NO_OVERALL_INFO_REQUIREMENT,
|
|
&revChecker, plContext),
|
|
PKIX_REVOCATIONCHECKERCREATEFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_SetRevocationChecker(procParams, revChecker,
|
|
plContext),
|
|
PKIX_PROCESSINGPARAMSSETREVOCATIONCHECKERFAILED);
|
|
|
|
/* CRL method flags */
|
|
methodFlags =
|
|
PKIX_REV_M_TEST_USING_THIS_METHOD |
|
|
PKIX_REV_M_FORBID_NETWORK_FETCHING |
|
|
PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE | /* 0 */
|
|
PKIX_REV_M_IGNORE_MISSING_FRESH_INFO | /* 0 */
|
|
PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO;
|
|
|
|
/* add CRL revocation method to check the leaf certificate */
|
|
PKIX_CHECK(
|
|
PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
|
|
PKIX_RevocationMethod_CRL, methodFlags,
|
|
0, NULL, PKIX_TRUE, plContext),
|
|
PKIX_REVOCATIONCHECKERADDMETHODFAILED);
|
|
|
|
/* add CRL revocation method for other certs in the chain. */
|
|
PKIX_CHECK(
|
|
PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
|
|
PKIX_RevocationMethod_CRL, methodFlags,
|
|
0, NULL, PKIX_FALSE, plContext),
|
|
PKIX_REVOCATIONCHECKERADDMETHODFAILED);
|
|
|
|
/* For compatibility with the old code, need to check that
|
|
* statusConfig is set in the db handle and status checker
|
|
* is defined befor allow ocsp status check on the leaf cert.*/
|
|
statusConfig = CERT_GetStatusConfig(CERT_GetDefaultCertDB());
|
|
if (statusConfig != NULL && statusConfig->statusChecker != NULL) {
|
|
|
|
/* Enable OCSP revocation checking for the leaf cert. */
|
|
/* OCSP method flags */
|
|
methodFlags =
|
|
PKIX_REV_M_TEST_USING_THIS_METHOD |
|
|
PKIX_REV_M_ALLOW_NETWORK_FETCHING | /* 0 */
|
|
PKIX_REV_M_ALLOW_IMPLICIT_DEFAULT_SOURCE | /* 0 */
|
|
PKIX_REV_M_SKIP_TEST_ON_MISSING_SOURCE | /* 0 */
|
|
PKIX_REV_M_IGNORE_MISSING_FRESH_INFO | /* 0 */
|
|
PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO;
|
|
|
|
/* Disabling ocsp fetching when checking the status
|
|
* of ocsp response signer. Here and in the next if,
|
|
* adjust flags for ocsp signer cert validation case. */
|
|
if (disableOCSPRemoteFetching) {
|
|
methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING;
|
|
}
|
|
|
|
if (ocsp_FetchingFailureIsVerificationFailure()
|
|
&& !disableOCSPRemoteFetching) {
|
|
methodFlags |=
|
|
PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO;
|
|
}
|
|
|
|
/* add OCSP revocation method to check only the leaf certificate.*/
|
|
PKIX_CHECK(
|
|
PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
|
|
PKIX_RevocationMethod_OCSP, methodFlags,
|
|
1, NULL, PKIX_TRUE, plContext),
|
|
PKIX_REVOCATIONCHECKERADDMETHODFAILED);
|
|
}
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_SetAnyPolicyInhibited(procParams, PR_FALSE,
|
|
plContext),
|
|
PKIX_PROCESSINGPARAMSSETANYPOLICYINHIBITED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_SetExplicitPolicyRequired(procParams, PR_FALSE,
|
|
plContext),
|
|
PKIX_PROCESSINGPARAMSSETEXPLICITPOLICYREQUIRED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ProcessingParams_SetPolicyMappingInhibited(procParams, PR_FALSE,
|
|
plContext),
|
|
PKIX_PROCESSINGPARAMSSETPOLICYMAPPINGINHIBITED);
|
|
|
|
*pprocParams = procParams;
|
|
procParams = NULL;
|
|
|
|
cleanup:
|
|
PKIX_DECREF(anchors);
|
|
PKIX_DECREF(targetCert);
|
|
PKIX_DECREF(date);
|
|
PKIX_DECREF(certSelector);
|
|
PKIX_DECREF(certSelParams);
|
|
PKIX_DECREF(certStore);
|
|
PKIX_DECREF(certStores);
|
|
PKIX_DECREF(procParams);
|
|
PKIX_DECREF(revChecker);
|
|
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: cert_PkixToNssCertsChain
|
|
* DESCRIPTION:
|
|
*
|
|
* Converts pkix cert list into nss cert list.
|
|
*
|
|
* PARAMETERS:
|
|
* "pkixCertChain"
|
|
* Pkix certificate list.
|
|
* "pvalidChain"
|
|
* An address of returned nss certificate list.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds.
|
|
* Returns a Cert Verify Error if the function fails in an unrecoverable way.
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way.
|
|
*/
|
|
static PKIX_Error*
|
|
cert_PkixToNssCertsChain(
|
|
PKIX_List *pkixCertChain,
|
|
CERTCertList **pvalidChain,
|
|
void *plContext)
|
|
{
|
|
PLArenaPool *arena = NULL;
|
|
CERTCertificate *nssCert = NULL;
|
|
CERTCertList *validChain = NULL;
|
|
PKIX_PL_Object *certItem = NULL;
|
|
PKIX_UInt32 length = 0;
|
|
PKIX_UInt32 i = 0;
|
|
|
|
PKIX_ENTER(CERTVFYPKIX, "cert_PkixToNssCertsChain");
|
|
PKIX_NULLCHECK_ONE(pvalidChain);
|
|
|
|
if (pkixCertChain == NULL) {
|
|
goto cleanup;
|
|
}
|
|
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
|
if (arena == NULL) {
|
|
PKIX_ERROR(PKIX_OUTOFMEMORY);
|
|
}
|
|
validChain = (CERTCertList*)PORT_ArenaZAlloc(arena, sizeof(CERTCertList));
|
|
if (validChain == NULL) {
|
|
PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
|
|
}
|
|
PR_INIT_CLIST(&validChain->list);
|
|
validChain->arena = arena;
|
|
arena = NULL;
|
|
|
|
PKIX_CHECK(
|
|
PKIX_List_GetLength(pkixCertChain, &length, plContext),
|
|
PKIX_LISTGETLENGTHFAILED);
|
|
|
|
for (i = 0; i < length; i++){
|
|
CERTCertListNode *node = NULL;
|
|
|
|
PKIX_CHECK(
|
|
PKIX_List_GetItem(pkixCertChain, i, &certItem, plContext),
|
|
PKIX_LISTGETITEMFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_PL_Cert_GetCERTCertificate((PKIX_PL_Cert*)certItem, &nssCert,
|
|
plContext),
|
|
PKIX_CERTGETCERTCERTIFICATEFAILED);
|
|
|
|
node =
|
|
(CERTCertListNode *)PORT_ArenaZAlloc(validChain->arena,
|
|
sizeof(CERTCertListNode));
|
|
if ( node == NULL ) {
|
|
PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
|
|
}
|
|
|
|
PR_INSERT_BEFORE(&node->links, &validChain->list);
|
|
|
|
node->cert = nssCert;
|
|
nssCert = NULL;
|
|
|
|
PKIX_DECREF(certItem);
|
|
}
|
|
|
|
*pvalidChain = validChain;
|
|
|
|
cleanup:
|
|
if (PKIX_ERROR_RECEIVED){
|
|
if (validChain) {
|
|
CERT_DestroyCertList(validChain);
|
|
} else if (arena) {
|
|
PORT_FreeArena(arena, PR_FALSE);
|
|
}
|
|
if (nssCert) {
|
|
CERT_DestroyCertificate(nssCert);
|
|
}
|
|
}
|
|
PKIX_DECREF(certItem);
|
|
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
}
|
|
|
|
|
|
/*
|
|
* FUNCTION: cert_BuildAndValidateChain
|
|
* DESCRIPTION:
|
|
*
|
|
* The function builds and validates a cert chain based on certificate
|
|
* selection criterias from procParams. This function call PKIX_BuildChain
|
|
* to accomplish chain building. If PKIX_BuildChain returns with incomplete
|
|
* IO, the function waits with PR_Poll until the blocking IO is finished and
|
|
* return control back to PKIX_BuildChain.
|
|
*
|
|
* PARAMETERS:
|
|
* "procParams"
|
|
* Processing parameters to be used during chain building.
|
|
* "pResult"
|
|
* Returned build result.
|
|
* "pVerifyNode"
|
|
* Returned pointed to verify node structure: the tree-like structure
|
|
* that reports points of chain building failures.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds.
|
|
* Returns a Cert Verify Error if the function fails in an unrecoverable way.
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way.
|
|
*/
|
|
static PKIX_Error*
|
|
cert_BuildAndValidateChain(
|
|
PKIX_ProcessingParams *procParams,
|
|
PKIX_BuildResult **pResult,
|
|
PKIX_VerifyNode **pVerifyNode,
|
|
void *plContext)
|
|
{
|
|
PKIX_BuildResult *result = NULL;
|
|
PKIX_VerifyNode *verifyNode = NULL;
|
|
void *nbioContext = NULL;
|
|
void *state = NULL;
|
|
|
|
PKIX_ENTER(CERTVFYPKIX, "cert_BuildAndVerifyChain");
|
|
PKIX_NULLCHECK_TWO(procParams, pResult);
|
|
|
|
do {
|
|
if (nbioContext && state) {
|
|
/* PKIX-XXX: need to test functionality of NBIO handling in libPkix.
|
|
* See bug 391180 */
|
|
PRInt32 filesReady = 0;
|
|
PRPollDesc *pollDesc = (PRPollDesc*)nbioContext;
|
|
filesReady = PR_Poll(pollDesc, 1, PR_INTERVAL_NO_TIMEOUT);
|
|
if (filesReady <= 0) {
|
|
PKIX_ERROR(PKIX_PRPOLLRETBADFILENUM);
|
|
}
|
|
}
|
|
|
|
PKIX_CHECK(
|
|
PKIX_BuildChain(procParams, &nbioContext, &state,
|
|
&result, &verifyNode, plContext),
|
|
PKIX_UNABLETOBUILDCHAIN);
|
|
|
|
} while (nbioContext && state);
|
|
|
|
*pResult = result;
|
|
|
|
cleanup:
|
|
if (pVerifyNode) {
|
|
*pVerifyNode = verifyNode;
|
|
}
|
|
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
}
|
|
|
|
|
|
/*
|
|
* FUNCTION: cert_PkixErrorToNssCode
|
|
* DESCRIPTION:
|
|
*
|
|
* Converts pkix error(PKIX_Error) structure to PR error codes.
|
|
*
|
|
* PKIX-XXX to be implemented. See 391183.
|
|
*
|
|
* PARAMETERS:
|
|
* "error"
|
|
* Pkix error that will be converted.
|
|
* "nssCode"
|
|
* Corresponding nss error code.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds.
|
|
* Returns a Cert Verify Error if the function fails in an unrecoverable way.
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way.
|
|
*/
|
|
static PKIX_Error *
|
|
cert_PkixErrorToNssCode(
|
|
PKIX_Error *error,
|
|
SECErrorCodes *pNssErr,
|
|
void *plContext)
|
|
{
|
|
int errLevel = 0;
|
|
PKIX_Int32 nssErr = 0;
|
|
PKIX_Error *errPtr = error;
|
|
|
|
PKIX_ENTER(CERTVFYPKIX, "cert_PkixErrorToNssCode");
|
|
PKIX_NULLCHECK_TWO(error, pNssErr);
|
|
|
|
/* Loop until we find at least one error with non-null
|
|
* plErr code, that is going to be nss error code. */
|
|
while (errPtr) {
|
|
if (errPtr->plErr && !nssErr) {
|
|
nssErr = errPtr->plErr;
|
|
if (!pkixLog) break;
|
|
}
|
|
if (pkixLog) {
|
|
#ifdef PKIX_ERROR_DESCRIPTION
|
|
PR_LOG(pkixLog, 2, ("Error at level %d: %s\n", errLevel,
|
|
PKIX_ErrorText[errPtr->errCode]));
|
|
#else
|
|
PR_LOG(pkixLog, 2, ("Error at level %d: Error code %d\n", errLevel,
|
|
errPtr->errCode));
|
|
#endif /* PKIX_ERROR_DESCRIPTION */
|
|
}
|
|
errPtr = errPtr->cause;
|
|
errLevel += 1;
|
|
}
|
|
PORT_Assert(nssErr);
|
|
if (!nssErr) {
|
|
*pNssErr = SEC_ERROR_LIBPKIX_INTERNAL;
|
|
} else {
|
|
*pNssErr = nssErr;
|
|
}
|
|
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: cert_GetLogFromVerifyNode
|
|
* DESCRIPTION:
|
|
*
|
|
* Recursive function that converts verify node tree-like set of structures
|
|
* to CERTVerifyLog.
|
|
*
|
|
* PARAMETERS:
|
|
* "log"
|
|
* Pointed to already allocated CERTVerifyLog structure.
|
|
* "node"
|
|
* A node of PKIX_VerifyNode tree.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds.
|
|
* Returns a Cert Verify Error if the function fails in an unrecoverable way.
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way.
|
|
*/
|
|
static PKIX_Error *
|
|
cert_GetLogFromVerifyNode(
|
|
CERTVerifyLog *log,
|
|
PKIX_VerifyNode *node,
|
|
void *plContext)
|
|
{
|
|
PKIX_List *children = NULL;
|
|
PKIX_VerifyNode *childNode = NULL;
|
|
|
|
PKIX_ENTER(CERTVFYPKIX, "cert_GetLogFromVerifyNode");
|
|
|
|
children = node->children;
|
|
|
|
if (children == NULL) {
|
|
PKIX_ERRORCODE errCode = PKIX_ANCHORDIDNOTCHAINTOCERT;
|
|
if (node->error && node->error->errCode != errCode) {
|
|
if (log != NULL) {
|
|
SECErrorCodes nssErrorCode = 0;
|
|
CERTCertificate *cert = NULL;
|
|
|
|
cert = node->verifyCert->nssCert;
|
|
|
|
PKIX_CHECK(
|
|
cert_PkixErrorToNssCode(node->error, &nssErrorCode,
|
|
plContext),
|
|
PKIX_GETPKIXERRORCODEFAILED);
|
|
|
|
cert_AddToVerifyLog(log, cert, nssErrorCode, node->depth, NULL);
|
|
}
|
|
}
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
} else {
|
|
PRUint32 i = 0;
|
|
PKIX_UInt32 length = 0;
|
|
|
|
PKIX_CHECK(
|
|
PKIX_List_GetLength(children, &length, plContext),
|
|
PKIX_LISTGETLENGTHFAILED);
|
|
|
|
for (i = 0; i < length; i++){
|
|
|
|
PKIX_CHECK(
|
|
PKIX_List_GetItem(children, i, (PKIX_PL_Object**)&childNode,
|
|
plContext),
|
|
PKIX_LISTGETITEMFAILED);
|
|
|
|
PKIX_CHECK(
|
|
cert_GetLogFromVerifyNode(log, childNode, plContext),
|
|
PKIX_ERRORINRECURSIVEEQUALSCALL);
|
|
|
|
PKIX_DECREF(childNode);
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
PKIX_DECREF(childNode);
|
|
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: cert_GetBuildResults
|
|
* DESCRIPTION:
|
|
*
|
|
* Converts pkix build results to nss results. This function is called
|
|
* regardless of build result.
|
|
*
|
|
* If it called after chain was successfully constructed, then it will
|
|
* convert:
|
|
* * pkix cert list that represent the chain to nss cert list
|
|
* * trusted root the chain was anchored to nss certificate.
|
|
*
|
|
* In case of failure it will convert:
|
|
* * pkix error to PR error code(will set it with PORT_SetError)
|
|
* * pkix validation log to nss CERTVerifyLog
|
|
*
|
|
* PARAMETERS:
|
|
* "buildResult"
|
|
* Build results returned by PKIX_BuildChain.
|
|
* "verifyNode"
|
|
* Tree-like structure of chain building/validation failures
|
|
* returned by PKIX_BuildChain. Ignored in case of success.
|
|
* "error"
|
|
* Final error returned by PKIX_BuildChain. Should be NULL in
|
|
* case of success.
|
|
* "log"
|
|
* Address of pre-allocated(if not NULL) CERTVerifyLog structure.
|
|
* "ptrustedRoot"
|
|
* Address of returned trusted root the chain was anchored to.
|
|
* "pvalidChain"
|
|
* Address of returned valid chain.
|
|
* "plContext"
|
|
* Platform-specific context pointer.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* Returns NULL if the function succeeds.
|
|
* Returns a Cert Verify Error if the function fails in an unrecoverable way.
|
|
* Returns a Fatal Error if the function fails in an unrecoverable way.
|
|
*/
|
|
static PKIX_Error*
|
|
cert_GetBuildResults(
|
|
PKIX_BuildResult *buildResult,
|
|
PKIX_VerifyNode *verifyNode,
|
|
PKIX_Error *error,
|
|
CERTVerifyLog *log,
|
|
CERTCertificate **ptrustedRoot,
|
|
CERTCertList **pvalidChain,
|
|
void *plContext)
|
|
{
|
|
PKIX_ValidateResult *validResult = NULL;
|
|
CERTCertList *validChain = NULL;
|
|
CERTCertificate *trustedRoot = NULL;
|
|
PKIX_TrustAnchor *trustAnchor = NULL;
|
|
PKIX_PL_Cert *trustedCert = NULL;
|
|
PKIX_List *pkixCertChain = NULL;
|
|
|
|
PKIX_ENTER(CERTVFYPKIX, "cert_GetBuildResults");
|
|
if (buildResult == NULL && error == NULL) {
|
|
PKIX_ERROR(PKIX_NULLARGUMENT);
|
|
}
|
|
|
|
if (error) {
|
|
SECErrorCodes nssErrorCode = 0;
|
|
if (verifyNode) {
|
|
PKIX_Error *tmpError =
|
|
cert_GetLogFromVerifyNode(log, verifyNode, plContext);
|
|
if (tmpError) {
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
|
|
}
|
|
}
|
|
cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
|
|
PORT_SetError(nssErrorCode);
|
|
goto cleanup;
|
|
}
|
|
|
|
if (pvalidChain) {
|
|
PKIX_CHECK(
|
|
PKIX_BuildResult_GetCertChain(buildResult, &pkixCertChain,
|
|
plContext),
|
|
PKIX_BUILDRESULTGETCERTCHAINFAILED);
|
|
|
|
PKIX_CHECK(
|
|
cert_PkixToNssCertsChain(pkixCertChain, &validChain, plContext),
|
|
PKIX_CERTCHAINTONSSCHAINFAILED);
|
|
}
|
|
|
|
if (ptrustedRoot) {
|
|
PKIX_CHECK(
|
|
PKIX_BuildResult_GetValidateResult(buildResult, &validResult,
|
|
plContext),
|
|
PKIX_BUILDRESULTGETVALIDATERESULTFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_ValidateResult_GetTrustAnchor(validResult, &trustAnchor,
|
|
plContext),
|
|
PKIX_VALIDATERESULTGETTRUSTANCHORFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_TrustAnchor_GetTrustedCert(trustAnchor, &trustedCert,
|
|
plContext),
|
|
PKIX_TRUSTANCHORGETTRUSTEDCERTFAILED);
|
|
|
|
PKIX_CHECK(
|
|
PKIX_PL_Cert_GetCERTCertificate(trustedCert, &trustedRoot,
|
|
plContext),
|
|
PKIX_CERTGETCERTCERTIFICATEFAILED);
|
|
}
|
|
|
|
PORT_Assert(!PKIX_ERROR_RECEIVED);
|
|
|
|
if (trustedRoot) {
|
|
*ptrustedRoot = trustedRoot;
|
|
}
|
|
if (validChain) {
|
|
*pvalidChain = validChain;
|
|
}
|
|
|
|
cleanup:
|
|
if (PKIX_ERROR_RECEIVED) {
|
|
if (trustedRoot) {
|
|
CERT_DestroyCertificate(trustedRoot);
|
|
}
|
|
if (validChain) {
|
|
CERT_DestroyCertList(validChain);
|
|
}
|
|
}
|
|
PKIX_DECREF(trustAnchor);
|
|
PKIX_DECREF(trustedCert);
|
|
PKIX_DECREF(pkixCertChain);
|
|
PKIX_DECREF(validResult);
|
|
PKIX_DECREF(error);
|
|
PKIX_DECREF(verifyNode);
|
|
PKIX_DECREF(buildResult);
|
|
|
|
PKIX_RETURN(CERTVFYPKIX);
|
|
}
|
|
|
|
/*
|
|
* FUNCTION: cert_VerifyCertChainPkix
|
|
* DESCRIPTION:
|
|
*
|
|
* The main wrapper function that is called from CERT_VerifyCert and
|
|
* CERT_VerifyCACertForUsage functions to validate cert with libpkix.
|
|
*
|
|
* PARAMETERS:
|
|
* "cert"
|
|
* Leaf certificate of a chain we want to build.
|
|
* "checkSig"
|
|
* Certificate signatures will not be verified if this
|
|
* flag is set to PR_FALSE.
|
|
* "requiredUsage"
|
|
* Required usage for certificate and chain.
|
|
* "time"
|
|
* Validity time.
|
|
* "wincx"
|
|
* Nss database password token.
|
|
* "log"
|
|
* Address of already allocated CERTVerifyLog structure. Not
|
|
* used if NULL;
|
|
* "pSigerror"
|
|
* Address of PRBool. If not NULL, returns true is cert chain
|
|
* was invalidated because of bad certificate signature.
|
|
* "pRevoked"
|
|
* Address of PRBool. If not NULL, returns true is cert chain
|
|
* was invalidated because a revoked certificate was found in
|
|
* the chain.
|
|
* THREAD SAFETY:
|
|
* Thread Safe (see Thread Safety Definitions in Programmer's Guide)
|
|
* RETURNS:
|
|
* SECFailure is chain building process has failed. SECSuccess otherwise.
|
|
*/
|
|
SECStatus
|
|
cert_VerifyCertChainPkix(
|
|
CERTCertificate *cert,
|
|
PRBool checkSig,
|
|
SECCertUsage requiredUsage,
|
|
PRTime time,
|
|
void *wincx,
|
|
CERTVerifyLog *log,
|
|
PRBool *pSigerror,
|
|
PRBool *pRevoked)
|
|
{
|
|
PKIX_ProcessingParams *procParams = NULL;
|
|
PKIX_BuildResult *result = NULL;
|
|
PKIX_VerifyNode *verifyNode = NULL;
|
|
PKIX_Error *error = NULL;
|
|
|
|
SECStatus rv = SECFailure;
|
|
void *plContext = NULL;
|
|
|
|
#ifdef PKIX_OBJECT_LEAK_TEST
|
|
int leakedObjNum = 0;
|
|
int memLeakLoopCount = 0;
|
|
int objCountTable[PKIX_NUMTYPES];
|
|
int fnInvLocalCount = 0;
|
|
PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
|
|
|
|
if (usePKIXValidationEngine) {
|
|
/* current memory leak testing implementation does not allow
|
|
* to run simultaneous tests one the same or a different threads.
|
|
* Setting the variable to false, to make additional chain
|
|
* validations be handled by old nss. */
|
|
usePKIXValidationEngine = PR_FALSE;
|
|
}
|
|
testStartFnStackPosition = 2;
|
|
fnStackNameArr[0] = "cert_VerifyCertChainPkix";
|
|
fnStackInvCountArr[0] = 0;
|
|
PKIX_Boolean abortOnLeak =
|
|
(PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ?
|
|
PKIX_FALSE : PKIX_TRUE;
|
|
runningLeakTest = PKIX_TRUE;
|
|
|
|
/* Prevent multi-threaded run of object leak test */
|
|
fnInvLocalCount = PR_ATOMIC_INCREMENT(¶llelFnInvocationCount);
|
|
PORT_Assert(fnInvLocalCount == 1);
|
|
|
|
do {
|
|
rv = SECFailure;
|
|
plContext = NULL;
|
|
procParams = NULL;
|
|
result = NULL;
|
|
verifyNode = NULL;
|
|
error = NULL;
|
|
errorGenerated = PKIX_FALSE;
|
|
stackPosition = 0;
|
|
|
|
if (leakedObjNum) {
|
|
pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
|
|
}
|
|
memLeakLoopCount += 1;
|
|
#endif /* PKIX_OBJECT_LEAK_TEST */
|
|
|
|
error =
|
|
cert_CreatePkixProcessingParams(cert, checkSig, time, wincx,
|
|
PR_FALSE/*use arena*/,
|
|
requiredUsage == certUsageStatusResponder,
|
|
&procParams, &plContext);
|
|
if (error) {
|
|
goto cleanup;
|
|
}
|
|
|
|
error =
|
|
cert_ProcessingParamsSetKeyAndCertUsage(procParams, requiredUsage, 0,
|
|
plContext);
|
|
if (error) {
|
|
goto cleanup;
|
|
}
|
|
|
|
error =
|
|
cert_BuildAndValidateChain(procParams, &result, &verifyNode, plContext);
|
|
if (error) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (pRevoked) {
|
|
/* Currently always PR_FALSE. Will be fixed as a part of 394077 */
|
|
*pRevoked = PR_FALSE;
|
|
}
|
|
if (pSigerror) {
|
|
/* Currently always PR_FALSE. Will be fixed as a part of 394077 */
|
|
*pSigerror = PR_FALSE;
|
|
}
|
|
rv = SECSuccess;
|
|
|
|
cleanup:
|
|
error = cert_GetBuildResults(result, verifyNode, error, log, NULL, NULL,
|
|
plContext);
|
|
if (error) {
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
|
|
}
|
|
if (procParams) {
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
|
|
}
|
|
if (plContext) {
|
|
PKIX_PL_NssContext_Destroy(plContext);
|
|
}
|
|
|
|
#ifdef PKIX_OBJECT_LEAK_TEST
|
|
leakedObjNum =
|
|
pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
|
|
|
|
if (pkixLog && leakedObjNum) {
|
|
PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
|
|
"Stack %s\n", memLeakLoopCount, errorFnStackString));
|
|
}
|
|
PR_Free(errorFnStackString);
|
|
errorFnStackString = NULL;
|
|
if (abortOnLeak) {
|
|
PORT_Assert(leakedObjNum == 0);
|
|
}
|
|
|
|
} while (errorGenerated);
|
|
|
|
runningLeakTest = PKIX_FALSE;
|
|
PR_ATOMIC_DECREMENT(¶llelFnInvocationCount);
|
|
usePKIXValidationEngine = savedUsePkixEngFlag;
|
|
#endif /* PKIX_OBJECT_LEAK_TEST */
|
|
|
|
return rv;
|
|
}
|
|
|
|
PKIX_CertSelector *
|
|
cert_GetTargetCertConstraints(CERTCertificate *target, void *plContext)
|
|
{
|
|
PKIX_ComCertSelParams *certSelParams = NULL;
|
|
PKIX_CertSelector *certSelector = NULL;
|
|
PKIX_CertSelector *r= NULL;
|
|
PKIX_PL_Cert *eeCert = NULL;
|
|
PKIX_Error *error = NULL;
|
|
|
|
error = PKIX_PL_Cert_CreateFromCERTCertificate(target, &eeCert, plContext);
|
|
if (error != NULL) goto cleanup;
|
|
|
|
error = PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext);
|
|
if (error != NULL) goto cleanup;
|
|
|
|
error = PKIX_ComCertSelParams_Create(&certSelParams, plContext);
|
|
if (error != NULL) goto cleanup;
|
|
|
|
error = PKIX_ComCertSelParams_SetCertificate(
|
|
certSelParams, eeCert, plContext);
|
|
if (error != NULL) goto cleanup;
|
|
|
|
error = PKIX_CertSelector_SetCommonCertSelectorParams
|
|
(certSelector, certSelParams, plContext);
|
|
if (error != NULL) goto cleanup;
|
|
|
|
error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certSelector, plContext);
|
|
if (error == NULL) r = certSelector;
|
|
|
|
cleanup:
|
|
if (certSelParams != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelParams, plContext);
|
|
|
|
if (eeCert != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)eeCert, plContext);
|
|
|
|
if (certSelector != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
|
|
|
|
if (error != NULL) {
|
|
SECErrorCodes nssErr;
|
|
|
|
cert_PkixErrorToNssCode(error, &nssErr, plContext);
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
|
|
PORT_SetError(nssErr);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
static PKIX_List *
|
|
cert_GetCertStores(void *plContext)
|
|
{
|
|
PKIX_CertStore *certStore = NULL;
|
|
PKIX_List *certStores = NULL;
|
|
PKIX_List *r = NULL;
|
|
PKIX_Error *error = NULL;
|
|
|
|
error = PKIX_PL_Pk11CertStore_Create(&certStore, plContext);
|
|
if (error != NULL) goto cleanup;
|
|
|
|
error = PKIX_List_Create(&certStores, plContext);
|
|
if (error != NULL) goto cleanup;
|
|
|
|
error = PKIX_List_AppendItem( certStores,
|
|
(PKIX_PL_Object *)certStore, plContext);
|
|
if (error != NULL) goto cleanup;
|
|
|
|
error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)certStores, plContext);
|
|
if (error == NULL) r = certStores;
|
|
|
|
cleanup:
|
|
if (certStores != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
|
|
|
|
if (certStore != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStore, plContext);
|
|
|
|
if (error != NULL) {
|
|
SECErrorCodes nssErr;
|
|
|
|
cert_PkixErrorToNssCode(error, &nssErr, plContext);
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
|
|
PORT_SetError(nssErr);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
struct fake_PKIX_PL_CertStruct {
|
|
CERTCertificate *nssCert;
|
|
};
|
|
|
|
/* This needs to be part of the PKIX_PL_* */
|
|
/* This definitely needs to go away, and be replaced with
|
|
a real accessor function in PKIX */
|
|
static CERTCertificate *
|
|
cert_NSSCertFromPKIXCert(const PKIX_PL_Cert *pkix_cert)
|
|
{
|
|
struct fake_PKIX_PL_CertStruct *fcert = NULL;
|
|
|
|
fcert = (struct fake_PKIX_PL_CertStruct*)pkix_cert;
|
|
|
|
return CERT_DupCertificate(fcert->nssCert);
|
|
}
|
|
|
|
PKIX_List *cert_PKIXMakeOIDList(const SECOidTag *oids, int oidCount, void *plContext)
|
|
{
|
|
PKIX_List *r = NULL;
|
|
PKIX_List *policyList = NULL;
|
|
PKIX_PL_OID *policyOID = NULL;
|
|
PKIX_Error *error = NULL;
|
|
int i;
|
|
|
|
error = PKIX_List_Create(&policyList, plContext);
|
|
if (error != NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
for (i=0; i<oidCount; i++) {
|
|
error = PKIX_PL_OID_Create(oids[i], &policyOID, plContext);
|
|
if (error) {
|
|
goto cleanup;
|
|
}
|
|
error = PKIX_List_AppendItem(policyList,
|
|
(PKIX_PL_Object *)policyOID, plContext);
|
|
if (error != NULL) {
|
|
goto cleanup;
|
|
}
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
|
|
policyOID = NULL;
|
|
}
|
|
|
|
error = PKIX_List_SetImmutable(policyList, plContext);
|
|
if (error != NULL) goto cleanup;
|
|
|
|
error = PKIX_PL_Object_IncRef((PKIX_PL_Object *)policyList, plContext);
|
|
if (error == NULL) r = policyList;
|
|
|
|
cleanup:
|
|
if (policyOID != NULL) {
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
|
|
}
|
|
if (policyList != NULL) {
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyList, plContext);
|
|
}
|
|
if (error != NULL) {
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
CERTValOutParam *
|
|
cert_pkix_FindOutputParam(CERTValOutParam *params, const CERTValParamOutType t)
|
|
{
|
|
CERTValOutParam *i;
|
|
if (params == NULL) {
|
|
return NULL;
|
|
}
|
|
for (i = params; i->type != cert_po_end; i++) {
|
|
if (i->type == t) {
|
|
return i;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static PKIX_Error*
|
|
setRevocationMethod(PKIX_RevocationChecker *revChecker,
|
|
PKIX_ProcessingParams *procParams,
|
|
const CERTRevocationTests *revTest,
|
|
CERTRevocationMethodIndex certRevMethod,
|
|
PKIX_RevocationMethodType pkixRevMethod,
|
|
PKIX_Boolean verifyResponderUsages,
|
|
PKIX_Boolean isLeafTest,
|
|
void *plContext)
|
|
{
|
|
PKIX_UInt32 methodFlags = 0;
|
|
PKIX_Error *error = NULL;
|
|
PKIX_UInt32 priority = 0;
|
|
|
|
if (revTest->number_of_defined_methods <= (PRUint32)certRevMethod) {
|
|
return NULL;
|
|
}
|
|
if (revTest->preferred_methods) {
|
|
unsigned int i = 0;
|
|
for (;i < revTest->number_of_preferred_methods;i++) {
|
|
if (revTest->preferred_methods[i] == certRevMethod)
|
|
break;
|
|
}
|
|
priority = i;
|
|
}
|
|
methodFlags = revTest->cert_rev_flags_per_method[certRevMethod];
|
|
if (verifyResponderUsages &&
|
|
pkixRevMethod == PKIX_RevocationMethod_OCSP) {
|
|
methodFlags |= PKIX_REV_M_FORBID_NETWORK_FETCHING;
|
|
}
|
|
error =
|
|
PKIX_RevocationChecker_CreateAndAddMethod(revChecker, procParams,
|
|
pkixRevMethod, methodFlags,
|
|
priority, NULL,
|
|
isLeafTest, plContext);
|
|
return error;
|
|
}
|
|
|
|
|
|
SECStatus
|
|
cert_pkixSetParam(PKIX_ProcessingParams *procParams,
|
|
const CERTValInParam *param, void *plContext)
|
|
{
|
|
PKIX_Error * error = NULL;
|
|
SECStatus r=SECSuccess;
|
|
PKIX_PL_Date *date = NULL;
|
|
PKIX_List *policyOIDList = NULL;
|
|
PKIX_List *certListPkix = NULL;
|
|
const CERTRevocationFlags *flags;
|
|
SECErrorCodes errCode = SEC_ERROR_INVALID_ARGS;
|
|
const CERTCertList *certList = NULL;
|
|
CERTCertListNode *node;
|
|
PKIX_PL_Cert *certPkix = NULL;
|
|
PKIX_TrustAnchor *trustAnchor = NULL;
|
|
PKIX_PL_Date *revDate = NULL;
|
|
PKIX_RevocationChecker *revChecker = NULL;
|
|
PKIX_PL_NssContext *nssContext = (PKIX_PL_NssContext *)plContext;
|
|
|
|
/* XXX we need a way to map generic PKIX error to generic NSS errors */
|
|
|
|
switch (param->type) {
|
|
|
|
case cert_pi_policyOID:
|
|
|
|
/* needed? */
|
|
error = PKIX_ProcessingParams_SetExplicitPolicyRequired(
|
|
procParams, PKIX_TRUE, plContext);
|
|
|
|
if (error != NULL) {
|
|
break;
|
|
}
|
|
|
|
policyOIDList = cert_PKIXMakeOIDList(param->value.array.oids,
|
|
param->value.arraySize,plContext);
|
|
if (policyOIDList == NULL) {
|
|
r = SECFailure;
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
break;
|
|
}
|
|
|
|
error = PKIX_ProcessingParams_SetInitialPolicies(
|
|
procParams,policyOIDList,plContext);
|
|
break;
|
|
|
|
case cert_pi_date:
|
|
if (param->value.scalar.time == 0) {
|
|
error = PKIX_PL_Date_Create_UTCTime(NULL, &date, plContext);
|
|
if (error != NULL) {
|
|
errCode = SEC_ERROR_INVALID_TIME;
|
|
break;
|
|
}
|
|
} else {
|
|
error = pkix_pl_Date_CreateFromPRTime(param->value.scalar.time,
|
|
&date, plContext);
|
|
if (error != NULL) {
|
|
errCode = SEC_ERROR_INVALID_TIME;
|
|
break;
|
|
}
|
|
}
|
|
|
|
error = PKIX_ProcessingParams_SetDate(procParams, date, plContext);
|
|
if (error != NULL) {
|
|
errCode = SEC_ERROR_INVALID_TIME;
|
|
}
|
|
break;
|
|
|
|
case cert_pi_revocationFlags:
|
|
{
|
|
PKIX_UInt32 leafIMFlags = 0;
|
|
PKIX_UInt32 chainIMFlags = 0;
|
|
PKIX_Boolean validatingResponderCert = PKIX_FALSE;
|
|
|
|
flags = param->value.pointer.revocation;
|
|
if (!flags) {
|
|
PORT_SetError(errCode);
|
|
r = SECFailure;
|
|
break;
|
|
}
|
|
|
|
leafIMFlags =
|
|
flags->leafTests.cert_rev_method_independent_flags;
|
|
chainIMFlags =
|
|
flags->chainTests.cert_rev_method_independent_flags;
|
|
|
|
error =
|
|
PKIX_RevocationChecker_Create(leafIMFlags, chainIMFlags,
|
|
&revChecker, plContext);
|
|
if (error) {
|
|
break;
|
|
}
|
|
|
|
error =
|
|
PKIX_ProcessingParams_SetRevocationChecker(procParams,
|
|
revChecker, plContext);
|
|
if (error) {
|
|
break;
|
|
}
|
|
|
|
if (((PKIX_PL_NssContext*)plContext)->certificateUsage &
|
|
certificateUsageStatusResponder) {
|
|
validatingResponderCert = PKIX_TRUE;
|
|
}
|
|
|
|
error = setRevocationMethod(revChecker,
|
|
procParams, &flags->leafTests,
|
|
cert_revocation_method_crl,
|
|
PKIX_RevocationMethod_CRL,
|
|
validatingResponderCert,
|
|
PKIX_TRUE, plContext);
|
|
if (error) {
|
|
break;
|
|
}
|
|
|
|
error = setRevocationMethod(revChecker,
|
|
procParams, &flags->leafTests,
|
|
cert_revocation_method_ocsp,
|
|
PKIX_RevocationMethod_OCSP,
|
|
validatingResponderCert,
|
|
PKIX_TRUE, plContext);
|
|
if (error) {
|
|
break;
|
|
}
|
|
|
|
error = setRevocationMethod(revChecker,
|
|
procParams, &flags->chainTests,
|
|
cert_revocation_method_crl,
|
|
PKIX_RevocationMethod_CRL,
|
|
validatingResponderCert,
|
|
PKIX_FALSE, plContext);
|
|
if (error) {
|
|
break;
|
|
}
|
|
|
|
error = setRevocationMethod(revChecker,
|
|
procParams, &flags->chainTests,
|
|
cert_revocation_method_ocsp,
|
|
PKIX_RevocationMethod_OCSP,
|
|
validatingResponderCert,
|
|
PKIX_FALSE, plContext);
|
|
if (error) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case cert_pi_trustAnchors:
|
|
certList = param->value.pointer.chain;
|
|
if (!certList) {
|
|
PORT_SetError(errCode);
|
|
r = SECFailure;
|
|
break;
|
|
}
|
|
error = PKIX_List_Create(&certListPkix, plContext);
|
|
if (error != NULL) {
|
|
break;
|
|
}
|
|
for(node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList);
|
|
node = CERT_LIST_NEXT(node) ) {
|
|
error = PKIX_PL_Cert_CreateFromCERTCertificate(node->cert,
|
|
&certPkix, plContext);
|
|
if (error) {
|
|
break;
|
|
}
|
|
error = PKIX_TrustAnchor_CreateWithCert(certPkix, &trustAnchor,
|
|
plContext);
|
|
if (error) {
|
|
break;
|
|
}
|
|
error = PKIX_List_AppendItem(certListPkix,
|
|
(PKIX_PL_Object*)trustAnchor, plContext);
|
|
if (error) {
|
|
break;
|
|
}
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
|
|
trustAnchor = NULL;
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
|
|
certPkix = NULL;
|
|
}
|
|
error =
|
|
PKIX_ProcessingParams_SetTrustAnchors(procParams, certListPkix,
|
|
plContext);
|
|
break;
|
|
|
|
case cert_pi_useAIACertFetch:
|
|
error =
|
|
PKIX_ProcessingParams_SetUseAIAForCertFetching(procParams,
|
|
(PRBool)(param->value.scalar.b != 0),
|
|
plContext);
|
|
break;
|
|
|
|
case cert_pi_chainVerifyCallback:
|
|
{
|
|
const CERTChainVerifyCallback *chainVerifyCallback =
|
|
param->value.pointer.chainVerifyCallback;
|
|
if (!chainVerifyCallback || !chainVerifyCallback->isChainValid) {
|
|
PORT_SetError(errCode);
|
|
r = SECFailure;
|
|
break;
|
|
}
|
|
|
|
nssContext->chainVerifyCallback = *chainVerifyCallback;
|
|
}
|
|
break;
|
|
|
|
case cert_pi_useOnlyTrustAnchors:
|
|
error =
|
|
PKIX_ProcessingParams_SetUseOnlyTrustAnchors(procParams,
|
|
(PRBool)(param->value.scalar.b != 0),
|
|
plContext);
|
|
break;
|
|
|
|
default:
|
|
PORT_SetError(errCode);
|
|
r = SECFailure;
|
|
break;
|
|
}
|
|
|
|
if (policyOIDList != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOIDList, plContext);
|
|
|
|
if (date != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)date, plContext);
|
|
|
|
if (revDate != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)revDate, plContext);
|
|
|
|
if (revChecker != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)revChecker, plContext);
|
|
|
|
if (certListPkix)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)certListPkix, plContext);
|
|
|
|
if (trustAnchor)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
|
|
|
|
if (certPkix)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)certPkix, plContext);
|
|
|
|
if (error != NULL) {
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
|
|
PORT_SetError(errCode);
|
|
r = SECFailure;
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
void
|
|
cert_pkixDestroyValOutParam(CERTValOutParam *params)
|
|
{
|
|
CERTValOutParam *i;
|
|
|
|
if (params == NULL) {
|
|
return;
|
|
}
|
|
for (i = params; i->type != cert_po_end; i++) {
|
|
switch (i->type) {
|
|
case cert_po_trustAnchor:
|
|
if (i->value.pointer.cert) {
|
|
CERT_DestroyCertificate(i->value.pointer.cert);
|
|
i->value.pointer.cert = NULL;
|
|
}
|
|
break;
|
|
|
|
case cert_po_certList:
|
|
if (i->value.pointer.chain) {
|
|
CERT_DestroyCertList(i->value.pointer.chain);
|
|
i->value.pointer.chain = NULL;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags[2] = {
|
|
/* crl */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
| CERT_REV_M_FORBID_NETWORK_FETCHING
|
|
| CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
|
|
/* ocsp */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
};
|
|
|
|
static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags[2] = {
|
|
/* crl */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
| CERT_REV_M_FORBID_NETWORK_FETCHING
|
|
| CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
|
|
/* ocsp */
|
|
0
|
|
};
|
|
|
|
static CERTRevocationMethodIndex
|
|
certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference = {
|
|
cert_revocation_method_crl
|
|
};
|
|
|
|
static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy = {
|
|
{
|
|
/* leafTests */
|
|
2,
|
|
certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_LeafFlags,
|
|
1,
|
|
&certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_Method_Preference,
|
|
0
|
|
},
|
|
{
|
|
/* chainTests */
|
|
2,
|
|
certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy_ChainFlags,
|
|
0,
|
|
0,
|
|
0
|
|
}
|
|
};
|
|
|
|
extern const CERTRevocationFlags*
|
|
CERT_GetClassicOCSPEnabledSoftFailurePolicy()
|
|
{
|
|
return &certRev_NSS_3_11_Ocsp_Enabled_Soft_Policy;
|
|
}
|
|
|
|
|
|
static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags[2] = {
|
|
/* crl */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
| CERT_REV_M_FORBID_NETWORK_FETCHING
|
|
| CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
|
|
/* ocsp */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
| CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
|
|
};
|
|
|
|
static PRUint64 certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags[2] = {
|
|
/* crl */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
| CERT_REV_M_FORBID_NETWORK_FETCHING
|
|
| CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
|
|
/* ocsp */
|
|
0
|
|
};
|
|
|
|
static CERTRevocationMethodIndex
|
|
certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference = {
|
|
cert_revocation_method_crl
|
|
};
|
|
|
|
static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy = {
|
|
{
|
|
/* leafTests */
|
|
2,
|
|
certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_LeafFlags,
|
|
1,
|
|
&certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_Method_Preference,
|
|
0
|
|
},
|
|
{
|
|
/* chainTests */
|
|
2,
|
|
certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy_ChainFlags,
|
|
0,
|
|
0,
|
|
0
|
|
}
|
|
};
|
|
|
|
extern const CERTRevocationFlags*
|
|
CERT_GetClassicOCSPEnabledHardFailurePolicy()
|
|
{
|
|
return &certRev_NSS_3_11_Ocsp_Enabled_Hard_Policy;
|
|
}
|
|
|
|
|
|
static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags[2] = {
|
|
/* crl */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
| CERT_REV_M_FORBID_NETWORK_FETCHING
|
|
| CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
|
|
/* ocsp */
|
|
0
|
|
};
|
|
|
|
static PRUint64 certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags[2] = {
|
|
/* crl */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
| CERT_REV_M_FORBID_NETWORK_FETCHING
|
|
| CERT_REV_M_CONTINUE_TESTING_ON_FRESH_INFO,
|
|
/* ocsp */
|
|
0
|
|
};
|
|
|
|
static const CERTRevocationFlags certRev_NSS_3_11_Ocsp_Disabled_Policy = {
|
|
{
|
|
/* leafTests */
|
|
2,
|
|
certRev_NSS_3_11_Ocsp_Disabled_Policy_LeafFlags,
|
|
0,
|
|
0,
|
|
0
|
|
},
|
|
{
|
|
/* chainTests */
|
|
2,
|
|
certRev_NSS_3_11_Ocsp_Disabled_Policy_ChainFlags,
|
|
0,
|
|
0,
|
|
0
|
|
}
|
|
};
|
|
|
|
extern const CERTRevocationFlags*
|
|
CERT_GetClassicOCSPDisabledPolicy()
|
|
{
|
|
return &certRev_NSS_3_11_Ocsp_Disabled_Policy;
|
|
}
|
|
|
|
|
|
static PRUint64 certRev_PKIX_Verify_Nist_Policy_LeafFlags[2] = {
|
|
/* crl */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
| CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
|
|
| CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
|
|
/* ocsp */
|
|
0
|
|
};
|
|
|
|
static PRUint64 certRev_PKIX_Verify_Nist_Policy_ChainFlags[2] = {
|
|
/* crl */
|
|
CERT_REV_M_TEST_USING_THIS_METHOD
|
|
| CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO
|
|
| CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE,
|
|
/* ocsp */
|
|
0
|
|
};
|
|
|
|
static const CERTRevocationFlags certRev_PKIX_Verify_Nist_Policy = {
|
|
{
|
|
/* leafTests */
|
|
2,
|
|
certRev_PKIX_Verify_Nist_Policy_LeafFlags,
|
|
0,
|
|
0,
|
|
0
|
|
},
|
|
{
|
|
/* chainTests */
|
|
2,
|
|
certRev_PKIX_Verify_Nist_Policy_ChainFlags,
|
|
0,
|
|
0,
|
|
0
|
|
}
|
|
};
|
|
|
|
extern const CERTRevocationFlags*
|
|
CERT_GetPKIXVerifyNistRevocationPolicy()
|
|
{
|
|
return &certRev_PKIX_Verify_Nist_Policy;
|
|
}
|
|
|
|
CERTRevocationFlags *
|
|
CERT_AllocCERTRevocationFlags(
|
|
PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods,
|
|
PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods)
|
|
{
|
|
CERTRevocationFlags *flags;
|
|
|
|
flags = PORT_New(CERTRevocationFlags);
|
|
if (!flags)
|
|
return(NULL);
|
|
|
|
flags->leafTests.number_of_defined_methods = number_leaf_methods;
|
|
flags->leafTests.cert_rev_flags_per_method =
|
|
PORT_NewArray(PRUint64, number_leaf_methods);
|
|
|
|
flags->leafTests.number_of_preferred_methods = number_leaf_pref_methods;
|
|
flags->leafTests.preferred_methods =
|
|
PORT_NewArray(CERTRevocationMethodIndex, number_leaf_pref_methods);
|
|
|
|
flags->chainTests.number_of_defined_methods = number_chain_methods;
|
|
flags->chainTests.cert_rev_flags_per_method =
|
|
PORT_NewArray(PRUint64, number_chain_methods);
|
|
|
|
flags->chainTests.number_of_preferred_methods = number_chain_pref_methods;
|
|
flags->chainTests.preferred_methods =
|
|
PORT_NewArray(CERTRevocationMethodIndex, number_chain_pref_methods);
|
|
|
|
if (!flags->leafTests.cert_rev_flags_per_method
|
|
|| !flags->leafTests.preferred_methods
|
|
|| !flags->chainTests.cert_rev_flags_per_method
|
|
|| !flags->chainTests.preferred_methods) {
|
|
CERT_DestroyCERTRevocationFlags(flags);
|
|
return (NULL);
|
|
}
|
|
|
|
return flags;
|
|
}
|
|
|
|
void CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags)
|
|
{
|
|
if (!flags)
|
|
return;
|
|
|
|
if (flags->leafTests.cert_rev_flags_per_method)
|
|
PORT_Free(flags->leafTests.cert_rev_flags_per_method);
|
|
|
|
if (flags->leafTests.preferred_methods)
|
|
PORT_Free(flags->leafTests.preferred_methods);
|
|
|
|
if (flags->chainTests.cert_rev_flags_per_method)
|
|
PORT_Free(flags->chainTests.cert_rev_flags_per_method);
|
|
|
|
if (flags->chainTests.preferred_methods)
|
|
PORT_Free(flags->chainTests.preferred_methods);
|
|
|
|
PORT_Free(flags);
|
|
}
|
|
|
|
/*
|
|
* CERT_PKIXVerifyCert
|
|
*
|
|
* Verify a Certificate using the PKIX library.
|
|
*
|
|
* Parameters:
|
|
* cert - the target certificate to verify. Must be non-null
|
|
* params - an array of type/value parameters which can be
|
|
* used to modify the behavior of the validation
|
|
* algorithm, or supply additional constraints.
|
|
*
|
|
* outputTrustAnchor - the trust anchor which the certificate
|
|
* chains to. The caller is responsible
|
|
* for freeing this.
|
|
*
|
|
* Example Usage:
|
|
* CERTValParam args[3];
|
|
* args[0].type = cvpt_policyOID;
|
|
* args[0].value.si = oid;
|
|
* args[1].type = revCheckRequired;
|
|
* args[1].value.b = PR_TRUE;
|
|
* args[2].type = cvpt_end;
|
|
*
|
|
* CERT_PKIXVerifyCert(cert, &output, args
|
|
*/
|
|
SECStatus CERT_PKIXVerifyCert(
|
|
CERTCertificate *cert,
|
|
SECCertificateUsage usages,
|
|
CERTValInParam *paramsIn,
|
|
CERTValOutParam *paramsOut,
|
|
void *wincx)
|
|
{
|
|
SECStatus r = SECFailure;
|
|
PKIX_Error * error = NULL;
|
|
PKIX_ProcessingParams *procParams = NULL;
|
|
PKIX_BuildResult * buildResult = NULL;
|
|
void * nbioContext = NULL; /* for non-blocking IO */
|
|
void * buildState = NULL; /* for non-blocking IO */
|
|
PKIX_CertSelector * certSelector = NULL;
|
|
PKIX_List * certStores = NULL;
|
|
PKIX_ValidateResult * valResult = NULL;
|
|
PKIX_VerifyNode * verifyNode = NULL;
|
|
PKIX_TrustAnchor * trustAnchor = NULL;
|
|
PKIX_PL_Cert * trustAnchorCert = NULL;
|
|
PKIX_List * builtCertList = NULL;
|
|
CERTValOutParam * oparam = NULL;
|
|
int i=0;
|
|
|
|
void *plContext = NULL;
|
|
|
|
#ifdef PKIX_OBJECT_LEAK_TEST
|
|
int leakedObjNum = 0;
|
|
int memLeakLoopCount = 0;
|
|
int objCountTable[PKIX_NUMTYPES];
|
|
int fnInvLocalCount = 0;
|
|
PKIX_Boolean savedUsePkixEngFlag = usePKIXValidationEngine;
|
|
|
|
if (usePKIXValidationEngine) {
|
|
/* current memory leak testing implementation does not allow
|
|
* to run simultaneous tests one the same or a different threads.
|
|
* Setting the variable to false, to make additional chain
|
|
* validations be handled by old nss. */
|
|
usePKIXValidationEngine = PR_FALSE;
|
|
}
|
|
testStartFnStackPosition = 1;
|
|
fnStackNameArr[0] = "CERT_PKIXVerifyCert";
|
|
fnStackInvCountArr[0] = 0;
|
|
PKIX_Boolean abortOnLeak =
|
|
(PR_GetEnv("PKIX_OBJECT_LEAK_TEST_ABORT_ON_LEAK") == NULL) ?
|
|
PKIX_FALSE : PKIX_TRUE;
|
|
runningLeakTest = PKIX_TRUE;
|
|
|
|
/* Prevent multi-threaded run of object leak test */
|
|
fnInvLocalCount = PR_ATOMIC_INCREMENT(¶llelFnInvocationCount);
|
|
PORT_Assert(fnInvLocalCount == 1);
|
|
|
|
do {
|
|
r = SECFailure;
|
|
error = NULL;
|
|
procParams = NULL;
|
|
buildResult = NULL;
|
|
nbioContext = NULL; /* for non-blocking IO */
|
|
buildState = NULL; /* for non-blocking IO */
|
|
certSelector = NULL;
|
|
certStores = NULL;
|
|
valResult = NULL;
|
|
verifyNode = NULL;
|
|
trustAnchor = NULL;
|
|
trustAnchorCert = NULL;
|
|
builtCertList = NULL;
|
|
oparam = NULL;
|
|
i=0;
|
|
errorGenerated = PKIX_FALSE;
|
|
stackPosition = 0;
|
|
|
|
if (leakedObjNum) {
|
|
pkix_pl_lifecycle_ObjectTableUpdate(objCountTable);
|
|
}
|
|
memLeakLoopCount += 1;
|
|
#endif /* PKIX_OBJECT_LEAK_TEST */
|
|
|
|
error = PKIX_PL_NssContext_Create(
|
|
0, PR_FALSE /*use arena*/, wincx, &plContext);
|
|
if (error != NULL) { /* need pkix->nss error map */
|
|
PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
|
|
goto cleanup;
|
|
}
|
|
|
|
error = pkix_pl_NssContext_SetCertUsage(usages, plContext);
|
|
if (error != NULL) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
goto cleanup;
|
|
}
|
|
|
|
error = PKIX_ProcessingParams_Create(&procParams, plContext);
|
|
if (error != NULL) { /* need pkix->nss error map */
|
|
PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
|
|
goto cleanup;
|
|
}
|
|
|
|
/* local cert store should be set into procParams before
|
|
* filling in revocation settings. */
|
|
certStores = cert_GetCertStores(plContext);
|
|
if (certStores == NULL) {
|
|
goto cleanup;
|
|
}
|
|
error = PKIX_ProcessingParams_SetCertStores
|
|
(procParams, certStores, plContext);
|
|
if (error != NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
/* now process the extensible input parameters structure */
|
|
if (paramsIn != NULL) {
|
|
i=0;
|
|
while (paramsIn[i].type != cert_pi_end) {
|
|
if (paramsIn[i].type >= cert_pi_max) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
goto cleanup;
|
|
}
|
|
if (cert_pkixSetParam(procParams,
|
|
¶msIn[i],plContext) != SECSuccess) {
|
|
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
|
goto cleanup;
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
|
|
certSelector = cert_GetTargetCertConstraints(cert, plContext);
|
|
if (certSelector == NULL) {
|
|
goto cleanup;
|
|
}
|
|
error = PKIX_ProcessingParams_SetTargetCertConstraints
|
|
(procParams, certSelector, plContext);
|
|
if (error != NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
error = PKIX_BuildChain( procParams, &nbioContext,
|
|
&buildState, &buildResult, &verifyNode,
|
|
plContext);
|
|
if (error != NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
error = PKIX_BuildResult_GetValidateResult( buildResult, &valResult,
|
|
plContext);
|
|
if (error != NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
error = PKIX_ValidateResult_GetTrustAnchor( valResult, &trustAnchor,
|
|
plContext);
|
|
if (error != NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
if (trustAnchor != NULL) {
|
|
error = PKIX_TrustAnchor_GetTrustedCert( trustAnchor, &trustAnchorCert,
|
|
plContext);
|
|
if (error != NULL) {
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
#ifdef PKIX_OBJECT_LEAK_TEST
|
|
/* Can not continue if error was generated but not returned.
|
|
* Jumping to cleanup. */
|
|
if (errorGenerated) goto cleanup;
|
|
#endif /* PKIX_OBJECT_LEAK_TEST */
|
|
|
|
oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor);
|
|
if (oparam != NULL) {
|
|
if (trustAnchorCert != NULL) {
|
|
oparam->value.pointer.cert =
|
|
cert_NSSCertFromPKIXCert(trustAnchorCert);
|
|
} else {
|
|
oparam->value.pointer.cert = NULL;
|
|
}
|
|
}
|
|
|
|
error = PKIX_BuildResult_GetCertChain( buildResult, &builtCertList,
|
|
plContext);
|
|
if (error != NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_certList);
|
|
if (oparam != NULL) {
|
|
error = cert_PkixToNssCertsChain(builtCertList,
|
|
&oparam->value.pointer.chain,
|
|
plContext);
|
|
if (error) goto cleanup;
|
|
}
|
|
|
|
r = SECSuccess;
|
|
|
|
cleanup:
|
|
if (verifyNode) {
|
|
/* Return validation log only upon error. */
|
|
oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_errorLog);
|
|
#ifdef PKIX_OBJECT_LEAK_TEST
|
|
if (!errorGenerated)
|
|
#endif /* PKIX_OBJECT_LEAK_TEST */
|
|
if (r && oparam != NULL) {
|
|
PKIX_Error *tmpError =
|
|
cert_GetLogFromVerifyNode(oparam->value.pointer.log,
|
|
verifyNode, plContext);
|
|
if (tmpError) {
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)tmpError, plContext);
|
|
}
|
|
}
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)verifyNode, plContext);
|
|
}
|
|
|
|
if (procParams != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)procParams, plContext);
|
|
|
|
if (trustAnchorCert != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchorCert, plContext);
|
|
|
|
if (trustAnchor != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)trustAnchor, plContext);
|
|
|
|
if (valResult != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)valResult, plContext);
|
|
|
|
if (buildResult != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)buildResult, plContext);
|
|
|
|
if (certStores != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)certStores, plContext);
|
|
|
|
if (certSelector != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelector, plContext);
|
|
|
|
if (builtCertList != NULL)
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)builtCertList, plContext);
|
|
|
|
if (error != NULL) {
|
|
SECErrorCodes nssErrorCode = 0;
|
|
|
|
cert_PkixErrorToNssCode(error, &nssErrorCode, plContext);
|
|
cert_pkixDestroyValOutParam(paramsOut);
|
|
PORT_SetError(nssErrorCode);
|
|
PKIX_PL_Object_DecRef((PKIX_PL_Object *)error, plContext);
|
|
}
|
|
|
|
PKIX_PL_NssContext_Destroy(plContext);
|
|
|
|
#ifdef PKIX_OBJECT_LEAK_TEST
|
|
leakedObjNum =
|
|
pkix_pl_lifecycle_ObjectLeakCheck(leakedObjNum ? objCountTable : NULL);
|
|
|
|
if (pkixLog && leakedObjNum) {
|
|
PR_LOG(pkixLog, 1, ("The generated error caused an object leaks. Loop %d."
|
|
"Stack %s\n", memLeakLoopCount, errorFnStackString));
|
|
}
|
|
PR_Free(errorFnStackString);
|
|
errorFnStackString = NULL;
|
|
if (abortOnLeak) {
|
|
PORT_Assert(leakedObjNum == 0);
|
|
}
|
|
|
|
} while (errorGenerated);
|
|
|
|
runningLeakTest = PKIX_FALSE;
|
|
PR_ATOMIC_DECREMENT(¶llelFnInvocationCount);
|
|
usePKIXValidationEngine = savedUsePkixEngFlag;
|
|
#endif /* PKIX_OBJECT_LEAK_TEST */
|
|
|
|
return r;
|
|
}
|