diff options
author | rrelyea%redhat.com <devnull@localhost> | 2007-09-25 23:48:04 +0000 |
---|---|---|
committer | rrelyea%redhat.com <devnull@localhost> | 2007-09-25 23:48:04 +0000 |
commit | cbe52331b484282db561068f318fb2b0061cef19 (patch) | |
tree | aa4d4107afc002b70c5595af3974d27ff75b959f | |
parent | ac354ae5f55ff6be918ec6b6632d0afb83d26cb3 (diff) | |
download | nss-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.h | 25 | ||||
-rw-r--r-- | security/nss/lib/certdb/certt.h | 191 | ||||
-rw-r--r-- | security/nss/lib/certhigh/certvfy.c | 597 | ||||
-rw-r--r-- | security/nss/lib/nss/nss.def | 1 |
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 = ¶msIn[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, + ¶msIn[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; |