summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrrelyea%redhat.com <devnull@localhost>2007-09-25 23:48:04 +0000
committerrrelyea%redhat.com <devnull@localhost>2007-09-25 23:48:04 +0000
commitcbe52331b484282db561068f318fb2b0061cef19 (patch)
treeaa4d4107afc002b70c5595af3974d27ff75b959f
parentac354ae5f55ff6be918ec6b6632d0afb83d26cb3 (diff)
downloadnss-hg-cbe52331b484282db561068f318fb2b0061cef19.tar.gz
bug 284531 Design new interfaces for certificate path building and verification for libPKIX
patch by stevep review by rrelyea.
-rw-r--r--security/nss/lib/certdb/cert.h25
-rw-r--r--security/nss/lib/certdb/certt.h191
-rw-r--r--security/nss/lib/certhigh/certvfy.c597
-rw-r--r--security/nss/lib/nss/nss.def1
4 files changed, 813 insertions, 1 deletions
diff --git a/security/nss/lib/certdb/cert.h b/security/nss/lib/certdb/cert.h
index acba01268..492e78fb3 100644
--- a/security/nss/lib/certdb/cert.h
+++ b/security/nss/lib/certdb/cert.h
@@ -1596,6 +1596,31 @@ CERT_EncodeNoticeReference(PRArenaPool *arena,
CERTNoticeReference *reference,
SECItem *dest);
+
+/*
+ * Verify a Cert with libpkix
+ * paramsIn control the verification options. If a value isn't specified
+ * in paramsIn, it reverts to the application default.
+ * paramsOut specifies the parameters the caller would like to get back.
+ * the caller may pass NULL, in which case no parameters are returned.
+ */
+extern SECStatus CERT_PKIXVerifyCert(
+ CERTCertificate *cert,
+ SECCertificateUsage usages,
+ CERTValInParam *paramsIn,
+ CERTValOutParam *paramsOut,
+ void *wincx);
+/*
+ * This function changes the application defaults for the Verify function.
+ * It should be called once at app initialization time, and only changes
+ * if the default configuration changes.
+ *
+ * This changes the default values for the parameters specified. These
+ * defaults can be overridden in CERT_PKIXVerifyCert() by explicitly
+ * setting the value in paramsIn.
+ */
+extern SECStatus CERT_PKIXSetDefaults(CERTValInParam *paramsIn);
+
SEC_END_PROTOS
#endif /* _CERT_H_ */
diff --git a/security/nss/lib/certdb/certt.h b/security/nss/lib/certdb/certt.h
index 56922ee15..e925f719a 100644
--- a/security/nss/lib/certdb/certt.h
+++ b/security/nss/lib/certdb/certt.h
@@ -886,6 +886,197 @@ typedef struct {
SECItem inhibitMappingSkipCerts;
} CERTCertificatePolicyConstraints;
+
+/*
+ * these types are for the CERT_PKIX* Verification functions
+ * These are all optional parameters.
+ */
+
+typedef enum {
+ cert_pi_end = 0, /* SPECIAL: signifies end of array of
+ * CERTValParam* */
+ cert_pi_nbioContext = 1, /* specify a non-blocking IO context used to
+ * resume a session. If this argument is
+ * specified, no other arguments should be.
+ * Specified in value.pointer.p. If the
+ * operation completes the context will be
+ * freed. */
+ cert_pi_nbioAbort = 2, /* specify a non-blocking IO context for an
+ * existing operation which the caller wants
+ * to abort. If this argument is
+ * specified, no other arguments should be.
+ * Specified in value.pointer.p. If the
+ * operation succeeds the context will be
+ * freed. */
+ cert_pi_certList = 3, /* specify the chain to validate against. If
+ * this value is given, then the path
+ * construction step in the validation is
+ * skipped. Specified in value.pointer.chain */
+ cert_pi_policyOID = 4, /* validate certificate for policy OID.
+ * Specified in value.array.oids. Cert must
+ * be good for at least one OID in order
+ * to validate. Default is no policyOID */
+ cert_pi_policyFlags = 5, /* flags for each policy specified in policyOID.
+ * Specified in value.scalar.ul. Policy flags
+ * apply to all specified oids.
+ * Use CERT_POLICY_FLAG_* macros below. If not
+ * specified policy flags default to 0 */
+ cert_pi_keyusage = 6, /* specify what the keyusages the certificate
+ * will be evaluated against, specified in
+ * value.scalar.ui. The cert must validate for
+ * at least one of the specified key usages.
+ * Values match the KU_ bit flags defined
+ * in this file. Default is derived from
+ * the 'usages' function argument */
+ cert_pi_extendedKeyusage= 7, /* specify what the required extended key
+ * usage of the certificate. Specified as
+ * an array of oidTags in value.array.oids.
+ * The cert must validate for at least one
+ * of the specified extended key usages.
+ * If not specified, no extended key usages
+ * will be checked. */
+ cert_pi_date = 8, /* validate certificate is valid as of date
+ * specified in value.scalar.time. A special
+ * value '0' indicates 'now'. default is '0' */
+ cert_pi_revocationFlags = 9, /* Specify what revocation checking to do.
+ * See CERT_REV_FLAG_* macros below
+ * Set in value.scalar.ul */
+ cert_pi_certStores = 10,/* Bitmask of Cert Store flags (see below)
+ * Set in value.scalar.ui */
+
+ cert_pi_max /* SPECIAL: signifies maximum allowed value,
+ * can increase in future releases */
+} CERTValParamInType;
+
+/*
+ * for all out parameters:
+ * out parameters are only returned if the caller asks for them in
+ * the CERTValOutParam array. Caller is responsible for the CERTValOutParam
+ * array itself. The pkix verify function will allocate and other arrays
+ * pointers, or objects. The Caller is responsible for freeing those results.
+ * If SECWouldBlock is returned, only cert_pi_nbioContext is returned.
+ */
+typedef enum {
+ cert_po_end = 0, /* SPECIAL: signifies end of array of
+ * CERTValParam* */
+ cert_po_nbioContext = 1, /* Return a nonblocking context. If no
+ * non-blocking context is specified, then
+ * blocking IO will be used.
+ * Returned in value.pointer.p. The context is
+ * freed after an abort or a complete operation.
+ * This value is only returned on SECWouldBlock.
+ */
+ cert_po_trustAnchor = 2, /* Return the trust anchor for the chain that
+ * was validated. Returned in
+ * value.pointer.cert, this value is only
+ * returned on SECSuccess. */
+ cert_po_certList = 3, /* Return the entire chain that was validated.
+ * Returned in value.pointer.certList. If no
+ * chain could be constructed, this value
+ * would be NULL. */
+ cert_po_policyOID = 4, /* Return the policies that were found to be
+ * valid. Returned in value.array.oids as an
+ * array. This is only returned on
+ * SECSuccess. */
+ cert_po_errorLog = 5, /* Return a log of problems with the chain.
+ * Returned in value.pointer.log */
+ cert_po_usages = 6, /* Return what usages the certificate is valid
+ for. Returned in value.scalar.usages */
+ cert_po_keyUsage = 7, /* Return what key usages the certificate
+ * is valid for.
+ * Returned in value.scalar.usage */
+ cert_po_extendedKeyusage= 8, /* Return what extended key usages the
+ * certificate is valid for.
+ * Returned in value.array.oids */
+ cert_po_max /* SPECIAL: signifies maximum allowed value,
+ * can increase in future releases */
+
+} CERTValParamOutType;
+
+typedef struct CERTValParamInValueStr {
+ union {
+ PRBool b;
+ PRInt32 i;
+ PRUint32 ui;
+ PRInt64 l;
+ PRUint64 ul;
+ PRTime time;
+ } scalar;
+ union {
+ const void* p;
+ const char* s;
+ const CERTCertificate* cert;
+ const CERTCertList *chain;
+ } pointer;
+ union {
+ const PRInt32 *pi;
+ const PRUint32 *pui;
+ const PRInt64 *pl;
+ const PRUint64 *pul;
+ const SECOidTag *oids;
+ } array;
+ int arraySize;
+} CERTValParamInValue;
+
+
+typedef struct CERTValParamOutValueStr {
+ union {
+ PRBool b;
+ PRInt32 i;
+ PRUint32 ui;
+ PRInt64 l;
+ PRUint64 ul;
+ SECCertificateUsage usages;
+ } scalar;
+ union {
+ void* p;
+ char* s;
+ CERTVerifyLog *log;
+ CERTCertificate* cert;
+ CERTCertList *chain;
+ } pointer;
+ union {
+ void *p;
+ SECOidTag *oids;
+ } array;
+ int arraySize;
+} CERTValParamOutValue;
+
+typedef struct {
+ CERTValParamInType type;
+ CERTValParamInValue value;
+} CERTValInParam;
+
+typedef struct {
+ CERTValParamOutType type;
+ CERTValParamOutValue value;
+} CERTValOutParam;
+
+/*
+ * policy flag defines
+ */
+#define CERT_POLICY_FLAG_NO_MAPPING 1
+#define CERT_POLICY_FLAG_EXPLICIT 2
+#define CERT_POLICY_FLAG_NO_ANY 4
+
+/*
+ * revocation flags
+ */
+#define CERT_REV_FLAG_OCSP 1
+#define CERT_REV_FLAG_OCSP_LEAF_ONLY 2
+#define CERT_REV_FLAG_CRL 4
+#define CERT_REV_FLAG_CRL_LEAF_ONLY 8
+/* set if we don't want to fail because we were unable to get revocation
+ * data */
+#define CERT_REV_FAIL_SOFT 0x10
+#define CERT_REV_NIST (CERT_REV_FLAG_OCSP|CERT_REV_FLAG_CRL)
+
+/*
+ * CertStore flags
+ */
+#define CERT_ENABLE_LDAP_FETCH 1
+#define CERT_ENABLE_HTTP_FETCH 2
+
/* XXX Lisa thinks the template declarations belong in cert.h, not here? */
#include "secasn1t.h" /* way down here because I expect template stuff to
diff --git a/security/nss/lib/certhigh/certvfy.c b/security/nss/lib/certhigh/certvfy.c
index ee3e487b8..10fbbcd7a 100644
--- a/security/nss/lib/certhigh/certvfy.c
+++ b/security/nss/lib/certhigh/certvfy.c
@@ -45,6 +45,10 @@
#include "certdb.h"
#include "certi.h"
#include "cryptohi.h"
+#include "pkix.h"
+/*#include "pkix_sample_modules.h" */
+#include "pkix_pl_cert.h"
+
#ifndef NSS_3_4_CODE
#define NSS_3_4_CODE
@@ -55,7 +59,6 @@
#include "pki3hack.h"
#include "base.h"
-
/*
* Check the validity times of a certificate
*/
@@ -2059,3 +2062,595 @@ CERT_GetCertChainFromCert(CERTCertificate *cert, int64 time, SECCertUsage usage)
PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
return chain;
}
+
+
+
+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;
+
+ pkix_pl_Cert_CreateWithNSSCert
+ (target, &eeCert, plContext);
+
+
+ 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_Create(NULL, NULL, &certSelector, 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 *)certSelParams, plContext);
+ if (error == NULL) r = certSelParams;
+
+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 (certSelParams != NULL)
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)certSelParams, plContext);
+
+ return r;
+}
+
+
+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);
+
+ return r;
+}
+
+
+/* XXX
+ * There is no NSS SECItem -> PKIX OID
+ * conversion function. For now, I go via the ascii
+ * representation
+ * this should be in PKIX_PL_*
+ */
+
+PKIX_PL_OID *
+CERT_PKIXOIDFromNSSOid(SECOidTag tag, void*plContext)
+{
+ char *oidstring = NULL;
+ char *oidstring_adj = NULL;
+ PKIX_PL_OID *policyOID = NULL;
+ SECOidData *data;
+
+ data = SECOID_FindOIDByTag(tag);
+ if (data != NULL) {
+ oidstring = CERT_GetOidString(&data->oid);
+ if (oidstring == NULL) {
+ goto cleanup;
+ }
+ oidstring_adj = oidstring;
+ if (PORT_Strncmp("OID.",oidstring_adj,4) == 0) {
+ oidstring_adj += 4;
+ }
+
+ PKIX_PL_OID_Create(oidstring_adj, &policyOID, plContext);
+ }
+cleanup:
+ if (oidstring != NULL) PR_smprintf_free(oidstring);
+
+ return policyOID;
+}
+
+
+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 */
+CERTCertificate *
+cert_NSSCertFromPKIXCert(const PKIX_PL_Cert *pkix_cert, void *plContext)
+{
+ 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;
+
+ PKIX_List_Create(&policyList, plContext);
+
+ for (i=0; i<oidCount; i++) {
+ policyOID = CERT_PKIXOIDFromNSSOid(oids[i],plContext);
+ if (policyOID == NULL) {
+ goto cleanup;
+ }
+ error = PKIX_List_AppendItem(policyList,
+ (PKIX_PL_Object *)policyOID, plContext);
+ if (error != NULL) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOID, plContext);
+ goto cleanup;
+ }
+ }
+
+ 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 (policyList != NULL) {
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyList, plContext);
+ }
+
+ return r;
+}
+
+CERTValOutParam *
+cert_pkix_FindOutputParam(const 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;
+}
+
+
+
+
+
+SECStatus
+cert_pkixSetParam(PKIX_ProcessingParams *procParams,
+ const CERTValInParam *param, void *plContext)
+{
+ PKIX_Error * error = NULL;
+ SECStatus r=SECSuccess;
+ PKIX_PL_Date *d = NULL;
+ PKIX_List *policyOIDList = NULL;
+
+ /* 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) {
+ r = SECFailure;
+ break;
+ }
+
+ policyOIDList = cert_PKIXMakeOIDList(param->value.array.oids,
+ param->value.arraySize,plContext);
+
+ error = PKIX_ProcessingParams_SetInitialPolicies(
+ procParams,policyOIDList,plContext);
+ if (error != NULL) {
+ r = SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ }
+ break;
+
+ case cert_pi_date:
+ if (param->value.scalar.time == 0) {
+ error = PKIX_PL_Date_Create_UTCTime(NULL, &d, plContext);
+ } else {
+ error = pkix_pl_Date_CreateFromPRTime( param->value.scalar.time,
+ &d, plContext);
+ if (error != NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_TIME);
+ r = SECFailure;
+ }
+ }
+
+ error = PKIX_ProcessingParams_SetDate( procParams, d, plContext );
+ if (error != NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_TIME);
+ r = SECFailure;
+ }
+ break;
+ /*
+ case cvpt_revCheckRequired:
+ error = PKIX_ProcessingParams_SetRevocationEnabled(
+ procParams, param->value.b?PKIX_TRUE:PKIX_FALSE, plContext);
+
+ if (error != NULL) r = SECFailure;
+ break;
+ */
+
+ default:
+ r = SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ }
+
+ if (policyOIDList != NULL)
+ PKIX_PL_Object_DecRef((PKIX_PL_Object *)policyOIDList, plContext);
+
+ if (d != NULL) PKIX_PL_Object_DecRef((PKIX_PL_Object *)d, plContext);
+
+ return r;
+
+ }
+
+#define EV_TEST_HACK 1
+#ifdef EV_TEST_HACK
+
+/* This function checks if the certificate asserts the given policy oid.
+ * It does not check if the certificate is authorized to assert that oid.
+ *
+ * This function is mainly here for testing purposes, to support the
+ * EV_HACK_INSECURE_OID_CHECK mode.
+ *
+ */
+
+SECStatus
+cert_hasPolicy(CERTCertificate *cert, SECOidTag tag)
+{
+ SECStatus r=SECFailure;
+ SECStatus rv=SECFailure;
+ SECItem policyItem = {siBuffer,0};
+ CERTPolicyInfo **cpi=NULL;
+ CERTCertificatePolicies *policyExt = NULL;
+ SECOidTag tagincert;
+
+
+ rv = CERT_FindCertExtension(cert, SEC_OID_X509_CERTIFICATE_POLICIES,
+ &policyItem);
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
+ return SECFailure;
+ }
+
+ policyExt = CERT_DecodeCertificatePoliciesExtension(&policyItem);
+ if (policyExt == NULL) goto loser;
+
+ for (cpi = policyExt->policyInfos; *cpi; cpi++) {
+ tagincert = SECOID_FindOIDTag(&(*cpi)->policyID);
+ if (tagincert == tag) {
+ r = SECSuccess;
+ break;
+ }
+ }
+
+loser:
+ if (policyExt != NULL) CERT_DestroyCertificatePoliciesExtension(policyExt);
+ if (policyItem.data) PORT_Free(policyItem.data);
+ return r;
+
+}
+
+
+/* determine which EV test mode we are in by reading an environment variable
+ * 'NSS_EV_TEST_HACK'.
+ */
+#define EV_HACK_ALWAYS_FAIL 0
+#define EV_HACK_USE_PKIX 1
+#define EV_HACK_INSECURE_OID_CHECK 2
+
+int cert_GetEVMode()
+{
+ static int firsttime = 1;
+ static char *mode_string = NULL;
+ static int mode = EV_HACK_ALWAYS_FAIL;
+
+ if (firsttime) {
+ firsttime = 0;
+#if (defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS)) && !defined(_WIN32_WCE)
+ mode_string = getenv("NSS_EV_TEST_HACK");
+#endif
+ if (mode_string != NULL) {
+ if (PORT_Strcmp(mode_string, "ALWAYS_FAIL") == 0) {
+ mode = EV_HACK_ALWAYS_FAIL;
+ } else if (PORT_Strcmp(mode_string, "USE_PKIX") == 0) {
+ mode = EV_HACK_USE_PKIX;
+ } else if (PORT_Strcmp(mode_string, "INSECURE_OID_CHECK") == 0) {
+ mode = EV_HACK_INSECURE_OID_CHECK;
+ }
+ }
+ }
+ return mode;
+}
+
+#endif
+
+/*
+ * 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
+ *
+ *
+ * NOTE: Currently, the behavior of this function can be modified
+ * to allow for testing, using the environment variable
+ * 'NSS_EV_TEST_HACK'. This variable can have the following values,
+ *
+ * ALWAYS_FAIL - always returns SECFailure (default)
+ *
+ * INSECURE_OID_CHECK - do no validation, just check if the
+ * target cert has the policy OID, if
+ * specified
+ *
+ * USE_PKIX - use PKIX calls, validating the full chain
+ *
+ */
+SECStatus CERT_PKIXVerifyCert(
+ CERTCertificate *cert,
+ SECCertificateUsage usages,
+ CERTValInParam *paramsIn,
+ CERTValOutParam *paramsOut,
+ void *wincx)
+{
+ SECStatus r = SECFailure;
+ PKIX_List * anchors = NULL;
+ 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_TrustAnchor * trustAnchor = NULL;
+ PKIX_PL_Cert * trustAnchorCert = NULL;
+ CERTValInParam * param = NULL;
+ CERTValOutParam * oparam = NULL;
+ int mode = EV_HACK_ALWAYS_FAIL;
+ int i=0;
+
+ void *plContext = NULL;
+
+#ifdef EV_TEST_HACK
+
+ /* XXX - check temporary env variable - this needs to go away */
+ mode = cert_GetEVMode();
+
+ if (mode == EV_HACK_ALWAYS_FAIL) {
+ /* this error is probably too generic - need to create specific
+ policy error codes */
+ PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
+ goto cleanup;
+ }
+
+ /* XXX This needs to go away */
+ if (mode == EV_HACK_INSECURE_OID_CHECK) {
+ if (paramsIn != NULL) {
+ for (i=0; paramsIn[i].type != cert_pi_end; i++) {
+ if (paramsIn[i].type == cert_pi_policyOID) {
+ param = &paramsIn[i];
+ }
+ }
+ if (param == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto cleanup;
+ }
+ for (i=0; i<param->value.arraySize; i++) {
+ if (cert_hasPolicy(cert,param->value.array.oids[i]) == SECSuccess) {
+ CERTCertList *certChain = NULL;
+ CERTCertListNode *node = NULL;
+ CERTCertListNode *next_node = NULL;
+
+ oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor);
+ if (oparam != NULL) {
+ certChain = CERT_GetCertChainFromCert(cert, PR_Now(),
+ usages);
+ for (node = CERT_LIST_HEAD(certChain);
+ !CERT_LIST_END(node, certChain);
+ node = next_node) {
+ next_node = CERT_LIST_NEXT(node);
+ if (CERT_LIST_END(next_node, certChain)) {
+ /* We arrived at the top level cert */
+ oparam->value.pointer.cert =
+ CERT_DupCertificate(node->cert);
+ }
+ }
+ CERT_DestroyCertList(certChain);
+ }
+ r = SECSuccess;
+ goto cleanup;
+ }
+ }
+ PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
+ goto cleanup;
+ }
+ }
+
+ if (mode != EV_HACK_USE_PKIX) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto cleanup;
+ }
+#endif
+
+ /* From this point on, we are going to do a PKIX validation */
+
+ 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;
+ }
+
+
+ /* The 'anchors' parameter must be supplied, but it can be an
+ empty list. PKIX will use the NSS trust database to form
+ the anchors list */
+ PKIX_List_Create(&anchors, plContext);
+ error = PKIX_ProcessingParams_Create(anchors, &procParams, plContext);
+ if (error != NULL) { /* need pkix->nss error map */
+ PORT_SetError(SEC_ERROR_CERT_NOT_VALID);
+ 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,
+ &paramsIn[i],plContext) != SECSuccess) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto cleanup;
+ }
+ i++;
+ }
+ }
+
+
+ certSelector = cert_GetTargetCertConstraints(cert, plContext);
+ error = PKIX_ProcessingParams_SetTargetCertConstraints
+ (procParams, certSelector, plContext);
+ if (error != NULL) {
+ PORT_SetError(SEC_ERROR_IO); /* need pkix->nss error map */
+ goto cleanup;
+ }
+
+ certStores = CERT_GetCertStores(plContext);
+ error = PKIX_ProcessingParams_SetCertStores
+ (procParams, certStores, plContext);
+ if (error != NULL) {
+ PORT_SetError(SEC_ERROR_IO); /* need pkix->nss error map */
+ goto cleanup;
+ }
+
+ error = PKIX_BuildChain( procParams, &nbioContext,
+ &buildState, &buildResult, NULL,
+ plContext);
+ if (error != NULL) {
+ PORT_SetError(SEC_ERROR_IO); /* need pkix->nss error map */
+ goto cleanup;
+ }
+
+ error = PKIX_BuildResult_GetValidateResult( buildResult, &valResult,
+ plContext);
+ if (error != NULL) {
+ PORT_SetError(SEC_ERROR_IO); /* need pkix->nss error map */
+ goto cleanup;
+ }
+
+ error = PKIX_ValidateResult_GetTrustAnchor( valResult, &trustAnchor,
+ plContext);
+ if (error != NULL) {
+ PORT_SetError(SEC_ERROR_IO); /* need pkix->nss error map */
+ goto cleanup;
+ }
+
+ error = PKIX_TrustAnchor_GetTrustedCert( trustAnchor, &trustAnchorCert,
+ plContext);
+ if (error != NULL) {
+ PORT_SetError(SEC_ERROR_IO); /* need pkix->nss error map */
+ goto cleanup;
+ }
+
+ oparam = cert_pkix_FindOutputParam(paramsOut, cert_po_trustAnchor);
+ if (oparam != NULL) {
+ oparam->value.pointer.cert =
+ cert_NSSCertFromPKIXCert(trustAnchorCert,plContext);
+ }
+
+ r = SECSuccess;
+
+cleanup:
+ 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);
+
+ PKIX_PL_NssContext_Destroy(plContext);
+
+ return r;
+}
+
diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def
index 6551029d2..a1291ddb7 100644
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -912,6 +912,7 @@ CERT_EncodeUserNotice;
CERT_FindCRLEntryReasonExten;
CERT_FindCRLNumberExten;
CERT_FindNameConstraintsExten;
+CERT_PKIXVerifyCert;
PK11_GetAllSlotsForCert;
PK11_GenerateKeyPairWithOpFlags;
SEC_GetRegisteredHttpClient;