bug 284531 Design new interfaces for certificate path building and verification for libPKIX

patch by stevep
review by rrelyea.


git-svn-id: svn://10.0.0.236/trunk@236687 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rrelyea%redhat.com 2007-09-25 23:48:04 +00:00
parent 76fab5eb65
commit d2cf075703
4 changed files with 815 additions and 3 deletions

View File

@ -37,7 +37,7 @@
/*
* cert.h - public data structures and prototypes for the certificate library
*
* $Id: cert.h,v 1.60 2007-09-07 18:45:51 neil.williams%sun.com Exp $
* $Id: cert.h,v 1.61 2007-09-25 23:48:02 rrelyea%redhat.com Exp $
*/
#ifndef _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_ */

View File

@ -36,7 +36,7 @@
/*
* certt.h - public data structures for the certificate library
*
* $Id: certt.h,v 1.38 2007-08-29 21:59:05 nelson%bolyard.com Exp $
* $Id: certt.h,v 1.39 2007-09-25 23:48:02 rrelyea%redhat.com Exp $
*/
#ifndef _CERTT_H_
#define _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

View File

@ -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;
}

View File

@ -912,6 +912,7 @@ CERT_EncodeUserNotice;
CERT_FindCRLEntryReasonExten;
CERT_FindCRLNumberExten;
CERT_FindNameConstraintsExten;
CERT_PKIXVerifyCert;
PK11_GetAllSlotsForCert;
PK11_GenerateKeyPairWithOpFlags;
SEC_GetRegisteredHttpClient;