michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: /* michael@0: * pkix_certselector.c michael@0: * michael@0: * CertSelector Object Functions michael@0: * michael@0: */ michael@0: michael@0: #include "pkix_certselector.h" michael@0: michael@0: /* --Private-Functions-------------------------------------------- */ michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Destroy michael@0: * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Destroy( michael@0: PKIX_PL_Object *object, michael@0: void *plContext) michael@0: { michael@0: PKIX_CertSelector *selector = NULL; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Destroy"); michael@0: PKIX_NULLCHECK_ONE(object); michael@0: michael@0: /* Check that this object is a cert selector */ michael@0: PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSELECTOR_TYPE, plContext), michael@0: PKIX_OBJECTNOTCERTSELECTOR); michael@0: michael@0: selector = (PKIX_CertSelector *)object; michael@0: PKIX_DECREF(selector->params); michael@0: PKIX_DECREF(selector->context); michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Duplicate michael@0: * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h) michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Duplicate( michael@0: PKIX_PL_Object *object, michael@0: PKIX_PL_Object **pNewObject, michael@0: void *plContext) michael@0: { michael@0: PKIX_CertSelector *certSelector = NULL; michael@0: PKIX_CertSelector *certSelectorDuplicate = NULL; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Duplicate"); michael@0: PKIX_NULLCHECK_TWO(object, pNewObject); michael@0: michael@0: PKIX_CHECK(pkix_CheckType(object, PKIX_CERTSELECTOR_TYPE, plContext), michael@0: PKIX_OBJECTNOTCERTSELECTOR); michael@0: michael@0: certSelector = (PKIX_CertSelector *)object; michael@0: michael@0: PKIX_CHECK(PKIX_CertSelector_Create michael@0: (certSelector->matchCallback, michael@0: certSelector->context, michael@0: &certSelectorDuplicate, michael@0: plContext), michael@0: PKIX_CERTSELECTORCREATEFAILED); michael@0: michael@0: PKIX_CHECK(PKIX_PL_Object_Duplicate michael@0: ((PKIX_PL_Object *)certSelector->params, michael@0: (PKIX_PL_Object **)&certSelectorDuplicate->params, michael@0: plContext), michael@0: PKIX_OBJECTDUPLICATEFAILED); michael@0: michael@0: *pNewObject = (PKIX_PL_Object *)certSelectorDuplicate; michael@0: michael@0: cleanup: michael@0: michael@0: if (PKIX_ERROR_RECEIVED){ michael@0: PKIX_DECREF(certSelectorDuplicate); michael@0: } michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_BasicConstraint michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the Cert pointed to by "cert" matches the basic michael@0: * constraints criterion using the basic constraints field of the michael@0: * ComCertSelParams pointed to by "params". If the basic constraints field is michael@0: * -1, no basic constraints check is done and the Cert is considered to match michael@0: * the basic constraints criterion. If the Cert does not match the basic michael@0: * constraints criterion, an Error pointer is returned. michael@0: * michael@0: * In order to match against this criterion, there are several possibilities. michael@0: * michael@0: * 1) If the criterion's minimum path length is greater than or equal to zero, michael@0: * a certificate must include a BasicConstraints extension with a pathLen of michael@0: * at least this value. michael@0: * michael@0: * 2) If the criterion's minimum path length is -2, a certificate must be an michael@0: * end-entity certificate. michael@0: * michael@0: * 3) If the criterion's minimum path length is -1, no basic constraints check michael@0: * is done and all certificates are considered to match this criterion. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose basic constraints field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * OUTPUT PARAMETERS ON FAILURE: michael@0: * If the function returns a failure, michael@0: * the output parameters of this function are undefined. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_BasicConstraint( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_PL_CertBasicConstraints *basicConstraints = NULL; michael@0: PKIX_Boolean caFlag = PKIX_FALSE; /* EE Cert by default */ michael@0: PKIX_Int32 pathLength = 0; michael@0: PKIX_Int32 minPathLength = 0; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_BasicConstraint"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: *pResult = PKIX_TRUE; michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints michael@0: (params, &minPathLength, plContext), michael@0: PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED); michael@0: michael@0: /* If the minPathLength is unlimited (-1), no checking */ michael@0: if (minPathLength == PKIX_CERTSEL_ALL_MATCH_MIN_PATHLENGTH) { michael@0: goto cleanup; michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_PL_Cert_GetBasicConstraints michael@0: (cert, &basicConstraints, plContext), michael@0: PKIX_CERTGETBASICCONSTRAINTSFAILED); michael@0: michael@0: if (basicConstraints != NULL) { michael@0: PKIX_CHECK(PKIX_PL_BasicConstraints_GetCAFlag michael@0: (basicConstraints, &caFlag, plContext), michael@0: PKIX_BASICCONSTRAINTSGETCAFLAGFAILED); michael@0: michael@0: PKIX_CHECK(PKIX_PL_BasicConstraints_GetPathLenConstraint michael@0: (basicConstraints, &pathLength, plContext), michael@0: PKIX_BASICCONSTRAINTSGETPATHLENCONSTRAINTFAILED); michael@0: } michael@0: michael@0: /* michael@0: * if minPathLength >= 0, the cert must have a BasicConstraints ext and michael@0: * the pathLength in this cert michael@0: * BasicConstraints needs to be >= minPathLength. michael@0: */ michael@0: if (minPathLength >= 0){ michael@0: if ((!basicConstraints) || (caFlag == PKIX_FALSE)){ michael@0: PKIX_ERROR(PKIX_CERTNOTALLOWEDTOSIGNCERTIFICATES); michael@0: } else if ((pathLength != PKIX_UNLIMITED_PATH_CONSTRAINT) && michael@0: (pathLength < minPathLength)){ michael@0: PKIX_CERTSELECTOR_DEBUG michael@0: ("Basic Constraints path length match failed\n"); michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_PATHLENCONSTRAINTINVALID); michael@0: } michael@0: } michael@0: michael@0: /* if the minPathLength is -2, this cert must be an end-entity cert. */ michael@0: if (minPathLength == PKIX_CERTSEL_ENDENTITY_MIN_PATHLENGTH) { michael@0: if (caFlag == PKIX_TRUE) { michael@0: PKIX_CERTSELECTOR_DEBUG michael@0: ("Basic Constraints end-entity match failed\n"); michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_PATHLENCONSTRAINTINVALID); michael@0: } michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(basicConstraints); michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_Policies michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the Cert pointed to by "cert" matches the policy michael@0: * constraints specified in the ComCertsSelParams given by "params". michael@0: * If "params" specifies a policy constraint of NULL, all certificates michael@0: * match. If "params" specifies an empty list, "cert" must have at least michael@0: * some policy. Otherwise "cert" must include at least one of the michael@0: * policies in the list. See the description of PKIX_CertSelector in michael@0: * pkix_certsel.h for more. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose policy criterion (if any) is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_Policies( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_UInt32 numConstraintPolicies = 0; michael@0: PKIX_UInt32 numCertPolicies = 0; michael@0: PKIX_UInt32 certPolicyIndex = 0; michael@0: PKIX_Boolean result = PKIX_FALSE; michael@0: PKIX_List *constraintPolicies = NULL; /* List of PKIX_PL_OID */ michael@0: PKIX_List *certPolicyInfos = NULL; /* List of PKIX_PL_CertPolicyInfo */ michael@0: PKIX_PL_CertPolicyInfo *policyInfo = NULL; michael@0: PKIX_PL_OID *polOID = NULL; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_Policies"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetPolicy michael@0: (params, &constraintPolicies, plContext), michael@0: PKIX_COMCERTSELPARAMSGETPOLICYFAILED); michael@0: michael@0: /* If constraintPolicies is NULL, all certificates "match" */ michael@0: if (constraintPolicies) { michael@0: PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation michael@0: (cert, &certPolicyInfos, plContext), michael@0: PKIX_CERTGETPOLICYINFORMATIONFAILED); michael@0: michael@0: /* No hope of a match if cert has no policies */ michael@0: if (!certPolicyInfos) { michael@0: PKIX_CERTSELECTOR_DEBUG("Certificate has no policies\n"); michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHPOLICIESFAILED); michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_List_GetLength michael@0: (constraintPolicies, &numConstraintPolicies, plContext), michael@0: PKIX_LISTGETLENGTHFAILED); michael@0: michael@0: if (numConstraintPolicies > 0) { michael@0: michael@0: PKIX_CHECK(PKIX_List_GetLength michael@0: (certPolicyInfos, &numCertPolicies, plContext), michael@0: PKIX_LISTGETLENGTHFAILED); michael@0: michael@0: for (certPolicyIndex = 0; michael@0: ((!result) && (certPolicyIndex < numCertPolicies)); michael@0: certPolicyIndex++) { michael@0: michael@0: PKIX_CHECK(PKIX_List_GetItem michael@0: (certPolicyInfos, michael@0: certPolicyIndex, michael@0: (PKIX_PL_Object **)&policyInfo, michael@0: plContext), michael@0: PKIX_LISTGETELEMENTFAILED); michael@0: PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId michael@0: (policyInfo, &polOID, plContext), michael@0: PKIX_CERTPOLICYINFOGETPOLICYIDFAILED); michael@0: michael@0: PKIX_CHECK(pkix_List_Contains michael@0: (constraintPolicies, michael@0: (PKIX_PL_Object *)polOID, michael@0: &result, michael@0: plContext), michael@0: PKIX_LISTCONTAINSFAILED); michael@0: PKIX_DECREF(policyInfo); michael@0: PKIX_DECREF(polOID); michael@0: } michael@0: if (!result) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHPOLICIESFAILED); michael@0: } michael@0: } michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(constraintPolicies); michael@0: PKIX_DECREF(certPolicyInfos); michael@0: PKIX_DECREF(policyInfo); michael@0: PKIX_DECREF(polOID); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_CertificateValid michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the Cert pointed to by "cert" matches the certificate michael@0: * validity criterion using the CertificateValid field of the michael@0: * ComCertSelParams pointed to by "params". If the CertificateValid field is michael@0: * NULL, no validity check is done and the Cert is considered to match michael@0: * the CertificateValid criterion. If the CertificateValid field specifies a michael@0: * Date prior to the notBefore field in the Cert, or greater than the notAfter michael@0: * field in the Cert, an Error is returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose certValid field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_CertificateValid( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_PL_Date *validityTime = NULL; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_CertificateValid"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid michael@0: (params, &validityTime, plContext), michael@0: PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED); michael@0: michael@0: /* If the validityTime is not set, all certificates are acceptable */ michael@0: if (validityTime) { michael@0: PKIX_CHECK(PKIX_PL_Cert_CheckValidity michael@0: (cert, validityTime, plContext), michael@0: PKIX_CERTCHECKVALIDITYFAILED); michael@0: } michael@0: michael@0: cleanup: michael@0: if (PKIX_ERROR_RECEIVED) { michael@0: *pResult = PKIX_FALSE; michael@0: } michael@0: PKIX_DECREF(validityTime); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_NameConstraints michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the Cert pointed to by "cert" matches the name michael@0: * constraints criterion specified in the ComCertSelParams pointed to by michael@0: * "params". If the name constraints field is NULL, no name constraints check michael@0: * is done and the Cert is considered to match the name constraints criterion. michael@0: * If the Cert does not match the name constraints criterion, an Error pointer michael@0: * is returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose name constraints field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_NameConstraints( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_PL_CertNameConstraints *nameConstraints = NULL; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_NameConstraints"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetNameConstraints michael@0: (params, &nameConstraints, plContext), michael@0: PKIX_COMCERTSELPARAMSGETNAMECONSTRAINTSFAILED); michael@0: michael@0: if (nameConstraints != NULL) { michael@0: /* As only the end-entity certificate should have michael@0: * the common name constrained as if it was a dNSName, michael@0: * do not constrain the common name when building a michael@0: * forward path. michael@0: */ michael@0: PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints michael@0: (cert, nameConstraints, PKIX_FALSE, plContext), michael@0: PKIX_CERTCHECKNAMECONSTRAINTSFAILED); michael@0: } michael@0: michael@0: cleanup: michael@0: if (PKIX_ERROR_RECEIVED) { michael@0: *pResult = PKIX_FALSE; michael@0: } michael@0: michael@0: PKIX_DECREF(nameConstraints); michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_PathToNames michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the names at pathToNames in "params" complies with the michael@0: * NameConstraints pointed to by "cert". If the pathToNames field is NULL michael@0: * or there is no name constraints for this "cert", no checking is done michael@0: * and the Cert is considered to match the name constraints criterion. michael@0: * If the Cert does not match the name constraints criterion, an Error michael@0: * pointer is returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose PathToNames field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_PathToNames( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_List *pathToNamesList = NULL; michael@0: PKIX_Boolean passed = PKIX_FALSE; michael@0: PKIX_PL_CertNameConstraints *nameConstraints = NULL; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_PathToNames"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetPathToNames michael@0: (params, &pathToNamesList, plContext), michael@0: PKIX_COMCERTSELPARAMSGETPATHTONAMESFAILED); michael@0: michael@0: if (pathToNamesList != NULL) { michael@0: michael@0: PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints michael@0: (cert, &nameConstraints, plContext), michael@0: PKIX_CERTGETNAMECONSTRAINTSFAILED); michael@0: michael@0: if (nameConstraints != NULL) { michael@0: michael@0: PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace michael@0: (pathToNamesList, nameConstraints, &passed, plContext), michael@0: PKIX_CERTNAMECONSTRAINTSCHECKNAMESINNAMESPACEFAILED); michael@0: michael@0: if (passed != PKIX_TRUE) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHPATHTONAMESFAILED); michael@0: } michael@0: } michael@0: michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(nameConstraints); michael@0: PKIX_DECREF(pathToNamesList); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_SubjAltNames michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the names at subjAltNames in "params" match with the michael@0: * SubjAltNames pointed to by "cert". If the subjAltNames field is NULL, michael@0: * no name checking is done and the Cert is considered to match the michael@0: * criterion. If the Cert does not match the criterion, an Error pointer michael@0: * is returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose SubjAltNames field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_SubjAltNames( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_List *subjAltNamesList = NULL; michael@0: PKIX_List *certSubjAltNames = NULL; michael@0: PKIX_PL_GeneralName *name = NULL; michael@0: PKIX_Boolean checkPassed = PKIX_FALSE; michael@0: PKIX_Boolean matchAll = PKIX_TRUE; michael@0: PKIX_UInt32 i, numItems; michael@0: PKIX_UInt32 matchCount = 0; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjAltNames"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetMatchAllSubjAltNames michael@0: (params, &matchAll, plContext), michael@0: PKIX_COMCERTSELPARAMSGETMATCHALLSUBJALTNAMESFAILED); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetSubjAltNames michael@0: (params, &subjAltNamesList, plContext), michael@0: PKIX_COMCERTSELPARAMSGETSUBJALTNAMESFAILED); michael@0: michael@0: if (subjAltNamesList != NULL) { michael@0: michael@0: PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames michael@0: (cert, &certSubjAltNames, plContext), michael@0: PKIX_CERTGETSUBJALTNAMESFAILED); michael@0: michael@0: if (certSubjAltNames == NULL) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED); michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_List_GetLength michael@0: (subjAltNamesList, &numItems, plContext), michael@0: PKIX_LISTGETLENGTHFAILED); michael@0: michael@0: for (i = 0; i < numItems; i++) { michael@0: michael@0: PKIX_CHECK(PKIX_List_GetItem michael@0: (subjAltNamesList, michael@0: i, michael@0: (PKIX_PL_Object **) &name, michael@0: plContext), michael@0: PKIX_LISTGETITEMFAILED); michael@0: michael@0: PKIX_CHECK(pkix_List_Contains michael@0: (certSubjAltNames, michael@0: (PKIX_PL_Object *) name, michael@0: &checkPassed, michael@0: plContext), michael@0: PKIX_LISTCONTAINSFAILED); michael@0: michael@0: PKIX_DECREF(name); michael@0: michael@0: if (checkPassed == PKIX_TRUE) { michael@0: michael@0: if (matchAll == PKIX_FALSE) { michael@0: /* one match is good enough */ michael@0: matchCount = numItems; michael@0: break; michael@0: } else { michael@0: /* else continue checking next */ michael@0: matchCount++; michael@0: } michael@0: michael@0: } michael@0: michael@0: } michael@0: michael@0: if (matchCount != numItems) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED); michael@0: } michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(name); michael@0: PKIX_DECREF(certSubjAltNames); michael@0: PKIX_DECREF(subjAltNamesList); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_ExtendedKeyUsage michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the names at ExtKeyUsage in "params" matches with the michael@0: * ExtKeyUsage pointed to by "cert". If the ExtKeyUsage criterion or michael@0: * ExtKeyUsage in "cert" is NULL, no checking is done and the Cert is michael@0: * considered a match. If the Cert does not match, an Error pointer is michael@0: * returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose ExtKeyUsage field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_ExtendedKeyUsage( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_List *extKeyUsageList = NULL; michael@0: PKIX_List *certExtKeyUsageList = NULL; michael@0: PKIX_PL_OID *ekuOid = NULL; michael@0: PKIX_Boolean isContained = PKIX_FALSE; michael@0: PKIX_UInt32 numItems = 0; michael@0: PKIX_UInt32 i; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_ExtendedKeyUsage"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetExtendedKeyUsage michael@0: (params, &extKeyUsageList, plContext), michael@0: PKIX_COMCERTSELPARAMSGETEXTENDEDKEYUSAGEFAILED); michael@0: michael@0: if (extKeyUsageList == NULL) { michael@0: goto cleanup; michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage michael@0: (cert, &certExtKeyUsageList, plContext), michael@0: PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); michael@0: michael@0: if (certExtKeyUsageList != NULL) { michael@0: michael@0: PKIX_CHECK(PKIX_List_GetLength michael@0: (extKeyUsageList, &numItems, plContext), michael@0: PKIX_LISTGETLENGTHFAILED); michael@0: michael@0: for (i = 0; i < numItems; i++) { michael@0: michael@0: PKIX_CHECK(PKIX_List_GetItem michael@0: (extKeyUsageList, i, (PKIX_PL_Object **)&ekuOid, plContext), michael@0: PKIX_LISTGETITEMFAILED); michael@0: michael@0: PKIX_CHECK(pkix_List_Contains michael@0: (certExtKeyUsageList, michael@0: (PKIX_PL_Object *)ekuOid, michael@0: &isContained, michael@0: plContext), michael@0: PKIX_LISTCONTAINSFAILED); michael@0: michael@0: PKIX_DECREF(ekuOid); michael@0: michael@0: if (isContained != PKIX_TRUE) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED); michael@0: } michael@0: } michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(ekuOid); michael@0: PKIX_DECREF(extKeyUsageList); michael@0: PKIX_DECREF(certExtKeyUsageList); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_KeyUsage michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the bits at KeyUsage in "params" matches with the michael@0: * KeyUsage pointed to by "cert". If the KeyUsage in params is 0 michael@0: * no checking is done and the Cert is considered a match. If the Cert does michael@0: * not match, an Error pointer is returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose ExtKeyUsage field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_KeyUsage( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_UInt32 keyUsage = 0; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_KeyUsage"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetKeyUsage michael@0: (params, &keyUsage, plContext), michael@0: PKIX_COMCERTSELPARAMSGETKEYUSAGEFAILED); michael@0: michael@0: if (keyUsage != 0) { michael@0: michael@0: PKIX_CHECK(PKIX_PL_Cert_VerifyKeyUsage michael@0: (cert, keyUsage, plContext), michael@0: PKIX_CERTVERIFYKEYUSAGEFAILED); michael@0: michael@0: } michael@0: michael@0: cleanup: michael@0: if (PKIX_ERROR_RECEIVED) { michael@0: *pResult = PKIX_FALSE; michael@0: } michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_SubjKeyId michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the bytes at subjKeyId in "params" matches with the michael@0: * Subject Key Identifier pointed to by "cert". If the subjKeyId in params is michael@0: * set to NULL or the Cert doesn't have a Subject Key Identifier, no checking michael@0: * is done and the Cert is considered a match. If the Cert does not match, an michael@0: * Error pointer is returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose subjKeyId field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_SubjKeyId( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_PL_ByteArray *selSubjKeyId = NULL; michael@0: PKIX_PL_ByteArray *certSubjKeyId = NULL; michael@0: PKIX_Boolean equals = PKIX_FALSE; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjKeyId"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetSubjKeyIdentifier michael@0: (params, &selSubjKeyId, plContext), michael@0: PKIX_COMCERTSELPARAMSGETSUBJKEYIDENTIFIERFAILED); michael@0: michael@0: if (selSubjKeyId != NULL) { michael@0: michael@0: PKIX_CHECK(PKIX_PL_Cert_GetSubjectKeyIdentifier michael@0: (cert, &certSubjKeyId, plContext), michael@0: PKIX_CERTGETSUBJECTKEYIDENTIFIERFAILED); michael@0: michael@0: if (certSubjKeyId == NULL) { michael@0: goto cleanup; michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_PL_Object_Equals michael@0: ((PKIX_PL_Object *)selSubjKeyId, michael@0: (PKIX_PL_Object *)certSubjKeyId, michael@0: &equals, michael@0: plContext), michael@0: PKIX_OBJECTEQUALSFAILED); michael@0: michael@0: if (equals == PKIX_FALSE) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJKEYIDFAILED); michael@0: } michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(selSubjKeyId); michael@0: PKIX_DECREF(certSubjKeyId); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_AuthKeyId michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the bytes at authKeyId in "params" matches with the michael@0: * Authority Key Identifier pointed to by "cert". If the authKeyId in params michael@0: * is set to NULL, no checking is done and the Cert is considered a match. If michael@0: * the Cert does not match, an Error pointer is returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose authKeyId field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_AuthKeyId( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_PL_ByteArray *selAuthKeyId = NULL; michael@0: PKIX_PL_ByteArray *certAuthKeyId = NULL; michael@0: PKIX_Boolean equals = PKIX_FALSE; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_AuthKeyId"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetAuthorityKeyIdentifier michael@0: (params, &selAuthKeyId, plContext), michael@0: PKIX_COMCERTSELPARAMSGETAUTHORITYKEYIDENTIFIERFAILED); michael@0: michael@0: if (selAuthKeyId != NULL) { michael@0: michael@0: PKIX_CHECK(PKIX_PL_Cert_GetAuthorityKeyIdentifier michael@0: (cert, &certAuthKeyId, plContext), michael@0: PKIX_CERTGETAUTHORITYKEYIDENTIFIERFAILED); michael@0: michael@0: if (certAuthKeyId == NULL) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED); michael@0: } michael@0: PKIX_CHECK(PKIX_PL_Object_Equals michael@0: ((PKIX_PL_Object *)selAuthKeyId, michael@0: (PKIX_PL_Object *)certAuthKeyId, michael@0: &equals, michael@0: plContext), michael@0: PKIX_OBJECTEQUALSFAILED); michael@0: michael@0: if (equals != PKIX_TRUE) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED); michael@0: } michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(selAuthKeyId); michael@0: PKIX_DECREF(certAuthKeyId); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_SubjPKAlgId michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the OID at subjPKAlgId in "params" matches with the michael@0: * Subject Public Key Alg Id pointed to by "cert". If the subjPKAlgId in params michael@0: * is set to NULL, no checking is done and the Cert is considered a match. If michael@0: * the Cert does not match, an Error pointer is returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose subjPKAlgId field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_SubjPKAlgId( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_PL_OID *selPKAlgId = NULL; michael@0: PKIX_PL_OID *certPKAlgId = NULL; michael@0: PKIX_Boolean equals = PKIX_FALSE; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjPKAlgId"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetSubjPKAlgId michael@0: (params, &selPKAlgId, plContext), michael@0: PKIX_COMCERTSELPARAMSGETSUBJPKALGIDFAILED); michael@0: michael@0: if (selPKAlgId != NULL) { michael@0: michael@0: PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKeyAlgId michael@0: (cert, &certPKAlgId, plContext), michael@0: PKIX_CERTGETSUBJECTPUBLICKEYALGIDFAILED); michael@0: michael@0: if (certPKAlgId != NULL) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED); michael@0: } michael@0: PKIX_CHECK(PKIX_PL_Object_Equals michael@0: ((PKIX_PL_Object *)selPKAlgId, michael@0: (PKIX_PL_Object *)certPKAlgId, michael@0: &equals, michael@0: plContext), michael@0: PKIX_OBJECTEQUALSFAILED); michael@0: michael@0: if (equals != PKIX_TRUE) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED); michael@0: } michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(selPKAlgId); michael@0: PKIX_DECREF(certPKAlgId); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Match_SubjPubKey michael@0: * DESCRIPTION: michael@0: * michael@0: * Determines whether the key at subjPubKey in "params" matches with the michael@0: * Subject Public Key pointed to by "cert". If the subjPubKey in params michael@0: * is set to NULL, no checking is done and the Cert is considered a match. If michael@0: * the Cert does not match, an Error pointer is returned. michael@0: * michael@0: * PARAMETERS: michael@0: * "params" michael@0: * Address of ComCertSelParams whose subPubKey field is used. michael@0: * Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched. Must be non-NULL. michael@0: * "pResult" michael@0: * Address of PKIX_Boolean that returns the match result. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_Match_SubjPubKey( michael@0: PKIX_ComCertSelParams *params, michael@0: PKIX_PL_Cert *cert, michael@0: PKIX_Boolean *pResult, michael@0: void *plContext) michael@0: { michael@0: PKIX_PL_PublicKey *selPK = NULL; michael@0: PKIX_PL_PublicKey *certPK = NULL; michael@0: PKIX_Boolean equals = PKIX_FALSE; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_Match_SubjPubKey"); michael@0: PKIX_NULLCHECK_THREE(params, cert, pResult); michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetSubjPubKey michael@0: (params, &selPK, plContext), michael@0: PKIX_COMCERTSELPARAMSGETSUBJPUBKEYFAILED); michael@0: michael@0: if (selPK != NULL) { michael@0: michael@0: PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey michael@0: (cert, &certPK, plContext), michael@0: PKIX_CERTGETSUBJECTPUBLICKEYFAILED); michael@0: michael@0: if (certPK == NULL) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED); michael@0: } michael@0: PKIX_CHECK(PKIX_PL_Object_Equals michael@0: ((PKIX_PL_Object *)selPK, michael@0: (PKIX_PL_Object *)certPK, michael@0: &equals, michael@0: plContext), michael@0: PKIX_OBJECTEQUALSFAILED); michael@0: michael@0: if (equals != PKIX_TRUE) { michael@0: *pResult = PKIX_FALSE; michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED); michael@0: } michael@0: } michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(selPK); michael@0: PKIX_DECREF(certPK); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_DefaultMatch michael@0: * DESCRIPTION: michael@0: * michael@0: * This default match function determines whether the specified Cert pointed michael@0: * to by "cert" matches the criteria of the CertSelector pointed to by michael@0: * "selector". If the Cert does not match the CertSelector's michael@0: * criteria, an error will be thrown. michael@0: * michael@0: * This default match function understands how to process the most common michael@0: * parameters. Any common parameter that is not set is assumed to be disabled, michael@0: * which means this function will select all certificates without regard to michael@0: * that particular disabled parameter. For example, if the SerialNumber michael@0: * parameter is not set, this function will not filter out any certificate michael@0: * based on its serial number. As such, if no parameters are set, all are michael@0: * disabled and any certificate will match. If a parameter is disabled, its michael@0: * associated PKIX_ComCertSelParams_Get* function returns a default value. michael@0: * That value is -1 for PKIX_ComCertSelParams_GetBasicConstraints and michael@0: * PKIX_ComCertSelParams_GetVersion, 0 for PKIX_ComCertSelParams_GetKeyUsage, michael@0: * and NULL for all other Get functions. michael@0: * michael@0: * PARAMETERS: michael@0: * "selector" michael@0: * Address of CertSelector whose MatchCallback logic and parameters are michael@0: * to be used. Must be non-NULL. michael@0: * "cert" michael@0: * Address of Cert that is to be matched using "selector". michael@0: * Must be non-NULL. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Conditionally Thread Safe michael@0: * (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: static PKIX_Error * michael@0: pkix_CertSelector_DefaultMatch( michael@0: PKIX_CertSelector *selector, michael@0: PKIX_PL_Cert *cert, michael@0: void *plContext) michael@0: { michael@0: PKIX_ComCertSelParams *params = NULL; michael@0: PKIX_PL_X500Name *certSubject = NULL; michael@0: PKIX_PL_X500Name *selSubject = NULL; michael@0: PKIX_PL_X500Name *certIssuer = NULL; michael@0: PKIX_PL_X500Name *selIssuer = NULL; michael@0: PKIX_PL_BigInt *certSerialNumber = NULL; michael@0: PKIX_PL_BigInt *selSerialNumber = NULL; michael@0: PKIX_PL_Cert *selCert = NULL; michael@0: PKIX_PL_Date *selDate = NULL; michael@0: PKIX_UInt32 selVersion = 0xFFFFFFFF; michael@0: PKIX_UInt32 certVersion = 0; michael@0: PKIX_Boolean result = PKIX_TRUE; michael@0: PKIX_Boolean isLeafCert = PKIX_TRUE; michael@0: michael@0: #ifdef PKIX_BUILDDEBUG michael@0: PKIX_PL_String *certString = NULL; michael@0: void *certAscii = NULL; michael@0: PKIX_UInt32 certAsciiLen; michael@0: #endif michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_DefaultMatch"); michael@0: PKIX_NULLCHECK_TWO(selector, cert); michael@0: michael@0: PKIX_INCREF(selector->params); michael@0: params = selector->params; michael@0: michael@0: /* Are we looking for CAs? */ michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetLeafCertFlag michael@0: (params, &isLeafCert, plContext), michael@0: PKIX_COMCERTSELPARAMSGETLEAFCERTFLAGFAILED); michael@0: michael@0: if (params == NULL){ michael@0: goto cleanup; michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetVersion michael@0: (params, &selVersion, plContext), michael@0: PKIX_COMCERTSELPARAMSGETVERSIONFAILED); michael@0: michael@0: if (selVersion != 0xFFFFFFFF){ michael@0: PKIX_CHECK(PKIX_PL_Cert_GetVersion michael@0: (cert, &certVersion, plContext), michael@0: PKIX_CERTGETVERSIONFAILED); michael@0: michael@0: if (selVersion != certVersion) { michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTVERSIONFAILED); michael@0: } michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetSubject michael@0: (params, &selSubject, plContext), michael@0: PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); michael@0: michael@0: if (selSubject){ michael@0: PKIX_CHECK(PKIX_PL_Cert_GetSubject michael@0: (cert, &certSubject, plContext), michael@0: PKIX_CERTGETSUBJECTFAILED); michael@0: michael@0: if (certSubject){ michael@0: PKIX_CHECK(PKIX_PL_X500Name_Match michael@0: (selSubject, certSubject, &result, plContext), michael@0: PKIX_X500NAMEMATCHFAILED); michael@0: michael@0: if (result == PKIX_FALSE){ michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSUBJECTFAILED); michael@0: } michael@0: } else { /* cert has no subject */ michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSUBJECTFAILED); michael@0: } michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetIssuer michael@0: (params, &selIssuer, plContext), michael@0: PKIX_COMCERTSELPARAMSGETISSUERFAILED); michael@0: michael@0: if (selIssuer){ michael@0: PKIX_CHECK(PKIX_PL_Cert_GetIssuer michael@0: (cert, &certIssuer, plContext), michael@0: PKIX_CERTGETISSUERFAILED); michael@0: michael@0: PKIX_CHECK(PKIX_PL_X500Name_Match michael@0: (selIssuer, certIssuer, &result, plContext), michael@0: PKIX_X500NAMEMATCHFAILED); michael@0: michael@0: if (result == PKIX_FALSE){ michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTISSUERFAILED); michael@0: } michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetSerialNumber michael@0: (params, &selSerialNumber, plContext), michael@0: PKIX_COMCERTSELPARAMSGETSERIALNUMBERFAILED); michael@0: michael@0: if (selSerialNumber){ michael@0: PKIX_CHECK(PKIX_PL_Cert_GetSerialNumber michael@0: (cert, &certSerialNumber, plContext), michael@0: PKIX_CERTGETSERIALNUMBERFAILED); michael@0: michael@0: PKIX_CHECK(PKIX_PL_Object_Equals michael@0: ((PKIX_PL_Object *)selSerialNumber, michael@0: (PKIX_PL_Object *)certSerialNumber, michael@0: &result, michael@0: plContext), michael@0: PKIX_OBJECTEQUALSFAILED); michael@0: michael@0: if (result == PKIX_FALSE){ michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTSERIALNUMFAILED); michael@0: } michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetCertificate michael@0: (params, &selCert, plContext), michael@0: PKIX_COMCERTSELPARAMSGETCERTIFICATEFAILED); michael@0: michael@0: if (selCert){ michael@0: PKIX_CHECK(PKIX_PL_Object_Equals michael@0: ((PKIX_PL_Object *) selCert, michael@0: (PKIX_PL_Object *) cert, michael@0: &result, michael@0: plContext), michael@0: PKIX_OBJECTEQUALSFAILED); michael@0: michael@0: if (result == PKIX_FALSE){ michael@0: PKIX_ERROR(PKIX_CERTSELECTORMATCHCERTOBJECTFAILED); michael@0: } michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid michael@0: (params, &selDate, plContext), michael@0: PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED); michael@0: michael@0: if (selDate){ michael@0: PKIX_CHECK(PKIX_PL_Cert_CheckValidity michael@0: (cert, selDate, plContext), michael@0: PKIX_CERTCHECKVALIDITYFAILED); michael@0: } michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_BasicConstraint michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHBASICCONSTRAINTFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_Policies michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHPOLICIESFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_CertificateValid michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHCERTIFICATEVALIDFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_NameConstraints michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHNAMECONSTRAINTSFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_PathToNames michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHPATHTONAMESFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_SubjAltNames michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHSUBJALTNAMESFAILED); michael@0: michael@0: /* Check key usage and cert type based on certificate usage. */ michael@0: PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, !isLeafCert, michael@0: plContext), michael@0: PKIX_CERTVERIFYCERTTYPEFAILED); michael@0: michael@0: /* Next two check are for user supplied additional KU and EKU. */ michael@0: PKIX_CHECK(pkix_CertSelector_Match_ExtendedKeyUsage michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHEXTENDEDKEYUSAGEFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_KeyUsage michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHKEYUSAGEFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_SubjKeyId michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHSUBJKEYIDFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_AuthKeyId michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHAUTHKEYIDFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_SubjPKAlgId michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHSUBJPKALGIDFAILED); michael@0: michael@0: PKIX_CHECK(pkix_CertSelector_Match_SubjPubKey michael@0: (params, cert, &result, plContext), michael@0: PKIX_CERTSELECTORMATCHSUBJPUBKEYFAILED); michael@0: michael@0: /* if we reach here, the cert has successfully matched criteria */ michael@0: michael@0: michael@0: #ifdef PKIX_BUILDDEBUG michael@0: michael@0: PKIX_CHECK(pkix_pl_Cert_ToString_Helper michael@0: (cert, PKIX_TRUE, &certString, plContext), michael@0: PKIX_CERTTOSTRINGHELPERFAILED); michael@0: michael@0: PKIX_CHECK(PKIX_PL_String_GetEncoded michael@0: (certString, michael@0: PKIX_ESCASCII, michael@0: &certAscii, michael@0: &certAsciiLen, michael@0: plContext), michael@0: PKIX_STRINGGETENCODEDFAILED); michael@0: michael@0: PKIX_CERTSELECTOR_DEBUG_ARG("Cert Selected:\n%s\n", certAscii); michael@0: michael@0: #endif michael@0: michael@0: cleanup: michael@0: michael@0: #ifdef PKIX_BUILDDEBUG michael@0: PKIX_DECREF(certString); michael@0: PKIX_FREE(certAscii); michael@0: #endif michael@0: michael@0: PKIX_DECREF(certSubject); michael@0: PKIX_DECREF(selSubject); michael@0: PKIX_DECREF(certIssuer); michael@0: PKIX_DECREF(selIssuer); michael@0: PKIX_DECREF(certSerialNumber); michael@0: PKIX_DECREF(selSerialNumber); michael@0: PKIX_DECREF(selCert); michael@0: PKIX_DECREF(selDate); michael@0: PKIX_DECREF(params); michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_RegisterSelf michael@0: * DESCRIPTION: michael@0: * Registers PKIX_CERTSELECTOR_TYPE and its related functions with michael@0: * systemClasses[] michael@0: * THREAD SAFETY: michael@0: * Not Thread Safe - for performance and complexity reasons michael@0: * michael@0: * Since this function is only called by PKIX_PL_Initialize, which should michael@0: * only be called once, it is acceptable that this function is not michael@0: * thread-safe. michael@0: */ michael@0: PKIX_Error * michael@0: pkix_CertSelector_RegisterSelf(void *plContext) michael@0: { michael@0: extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; michael@0: pkix_ClassTable_Entry entry; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "pkix_CertSelector_RegisterSelf"); michael@0: michael@0: entry.description = "CertSelector"; michael@0: entry.objCounter = 0; michael@0: entry.typeObjectSize = sizeof(PKIX_CertSelector); michael@0: entry.destructor = pkix_CertSelector_Destroy; michael@0: entry.equalsFunction = NULL; michael@0: entry.hashcodeFunction = NULL; michael@0: entry.toStringFunction = NULL; michael@0: entry.comparator = NULL; michael@0: entry.duplicateFunction = pkix_CertSelector_Duplicate; michael@0: michael@0: systemClasses[PKIX_CERTSELECTOR_TYPE] = entry; michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* --Public-Functions--------------------------------------------- */ michael@0: michael@0: michael@0: /* michael@0: * FUNCTION: PKIX_CertSelector_Create (see comments in pkix_certsel.h) michael@0: */ michael@0: PKIX_Error * michael@0: PKIX_CertSelector_Create( michael@0: PKIX_CertSelector_MatchCallback callback, michael@0: PKIX_PL_Object *certSelectorContext, michael@0: PKIX_CertSelector **pSelector, michael@0: void *plContext) michael@0: { michael@0: PKIX_CertSelector *selector = NULL; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_Create"); michael@0: PKIX_NULLCHECK_ONE(pSelector); michael@0: michael@0: PKIX_CHECK(PKIX_PL_Object_Alloc michael@0: (PKIX_CERTSELECTOR_TYPE, michael@0: sizeof (PKIX_CertSelector), michael@0: (PKIX_PL_Object **)&selector, michael@0: plContext), michael@0: PKIX_COULDNOTCREATECERTSELECTOROBJECT); michael@0: michael@0: /* michael@0: * if user specified a particular match callback, we use that one. michael@0: * otherwise, we use the default match implementation which michael@0: * understands how to process PKIX_ComCertSelParams michael@0: */ michael@0: michael@0: if (callback){ michael@0: selector->matchCallback = callback; michael@0: } else { michael@0: selector->matchCallback = pkix_CertSelector_DefaultMatch; michael@0: } michael@0: michael@0: /* initialize other fields */ michael@0: selector->params = NULL; michael@0: michael@0: PKIX_INCREF(certSelectorContext); michael@0: selector->context = certSelectorContext; michael@0: michael@0: *pSelector = selector; michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: PKIX_CertSelector_GetMatchCallback michael@0: * (see comments in pkix_certsel.h) michael@0: */ michael@0: PKIX_Error * michael@0: PKIX_CertSelector_GetMatchCallback( michael@0: PKIX_CertSelector *selector, michael@0: PKIX_CertSelector_MatchCallback *pCallback, michael@0: void *plContext) michael@0: { michael@0: PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_GetMatchCallback"); michael@0: PKIX_NULLCHECK_TWO(selector, pCallback); michael@0: michael@0: *pCallback = selector->matchCallback; michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: PKIX_CertSelector_GetCertSelectorContext michael@0: * (see comments in pkix_certsel.h) michael@0: */ michael@0: PKIX_Error * michael@0: PKIX_CertSelector_GetCertSelectorContext( michael@0: PKIX_CertSelector *selector, michael@0: PKIX_PL_Object **pCertSelectorContext, michael@0: void *plContext) michael@0: { michael@0: PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_GetCertSelectorContext"); michael@0: PKIX_NULLCHECK_TWO(selector, pCertSelectorContext); michael@0: michael@0: PKIX_INCREF(selector->context); michael@0: michael@0: *pCertSelectorContext = selector->context; michael@0: michael@0: cleanup: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: PKIX_CertSelector_GetCommonCertSelectorParams michael@0: * (see comments in pkix_certsel.h) michael@0: */ michael@0: PKIX_Error * michael@0: PKIX_CertSelector_GetCommonCertSelectorParams( michael@0: PKIX_CertSelector *selector, michael@0: PKIX_ComCertSelParams **pParams, michael@0: void *plContext) michael@0: { michael@0: PKIX_ENTER(CERTSELECTOR, michael@0: "PKIX_CertSelector_GetCommonCertSelectorParams"); michael@0: michael@0: PKIX_NULLCHECK_TWO(selector, pParams); michael@0: michael@0: PKIX_INCREF(selector->params); michael@0: *pParams = selector->params; michael@0: michael@0: cleanup: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: PKIX_CertSelector_SetCommonCertSelectorParams michael@0: * (see comments in pkix_certsel.h) michael@0: */ michael@0: PKIX_Error * michael@0: PKIX_CertSelector_SetCommonCertSelectorParams( michael@0: PKIX_CertSelector *selector, michael@0: PKIX_ComCertSelParams *params, michael@0: void *plContext) michael@0: { michael@0: PKIX_ENTER(CERTSELECTOR, michael@0: "PKIX_CertSelector_SetCommonCertSelectorParams"); michael@0: michael@0: PKIX_NULLCHECK_ONE(selector); michael@0: michael@0: PKIX_DECREF(selector->params); michael@0: PKIX_INCREF(params); michael@0: selector->params = params; michael@0: michael@0: PKIX_CHECK(PKIX_PL_Object_InvalidateCache michael@0: ((PKIX_PL_Object *)selector, plContext), michael@0: PKIX_OBJECTINVALIDATECACHEFAILED); michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: michael@0: } michael@0: michael@0: /* michael@0: * FUNCTION: pkix_CertSelector_Select michael@0: * DESCRIPTION: michael@0: * michael@0: * This function applies the selector pointed to by "selector" to each Cert, michael@0: * in turn, in the List pointed to by "before", and creates a List containing michael@0: * all the Certs that matched, or passed the selection process, storing that michael@0: * List at "pAfter". If no Certs match, an empty List is stored at "pAfter". michael@0: * michael@0: * The List returned in "pAfter" is immutable. michael@0: * michael@0: * PARAMETERS: michael@0: * "selector" michael@0: * Address of CertSelelector to be applied to the List. Must be non-NULL. michael@0: * "before" michael@0: * Address of List that is to be filtered. Must be non-NULL. michael@0: * "pAfter" michael@0: * Address at which resulting List, possibly empty, is stored. Must be michael@0: * non-NULL. michael@0: * "plContext" michael@0: * Platform-specific context pointer. michael@0: * THREAD SAFETY: michael@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) michael@0: * RETURNS: michael@0: * Returns NULL if the function succeeds. michael@0: * Returns a CertSelector Error if the function fails in a non-fatal way. michael@0: * Returns a Fatal Error if the function fails in an unrecoverable way. michael@0: */ michael@0: PKIX_Error * michael@0: pkix_CertSelector_Select( michael@0: PKIX_CertSelector *selector, michael@0: PKIX_List *before, michael@0: PKIX_List **pAfter, michael@0: void *plContext) michael@0: { michael@0: PKIX_UInt32 numBefore = 0; michael@0: PKIX_UInt32 i = 0; michael@0: PKIX_List *filtered = NULL; michael@0: PKIX_PL_Cert *candidate = NULL; michael@0: michael@0: PKIX_ENTER(CERTSELECTOR, "PKIX_CertSelector_Select"); michael@0: PKIX_NULLCHECK_THREE(selector, before, pAfter); michael@0: michael@0: PKIX_CHECK(PKIX_List_Create(&filtered, plContext), michael@0: PKIX_LISTCREATEFAILED); michael@0: michael@0: PKIX_CHECK(PKIX_List_GetLength(before, &numBefore, plContext), michael@0: PKIX_LISTGETLENGTHFAILED); michael@0: michael@0: for (i = 0; i < numBefore; i++) { michael@0: michael@0: PKIX_CHECK(PKIX_List_GetItem michael@0: (before, i, (PKIX_PL_Object **)&candidate, plContext), michael@0: PKIX_LISTGETITEMFAILED); michael@0: michael@0: PKIX_CHECK_ONLY_FATAL(selector->matchCallback michael@0: (selector, candidate, plContext), michael@0: PKIX_CERTSELECTORMATCHCALLBACKFAILED); michael@0: michael@0: if (!(PKIX_ERROR_RECEIVED)) { michael@0: michael@0: PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem michael@0: (filtered, michael@0: (PKIX_PL_Object *)candidate, michael@0: plContext), michael@0: PKIX_LISTAPPENDITEMFAILED); michael@0: } michael@0: michael@0: pkixTempErrorReceived = PKIX_FALSE; michael@0: PKIX_DECREF(candidate); michael@0: } michael@0: michael@0: PKIX_CHECK(PKIX_List_SetImmutable(filtered, plContext), michael@0: PKIX_LISTSETIMMUTABLEFAILED); michael@0: michael@0: /* Don't throw away the list if one Cert was bad! */ michael@0: pkixTempErrorReceived = PKIX_FALSE; michael@0: michael@0: *pAfter = filtered; michael@0: filtered = NULL; michael@0: michael@0: cleanup: michael@0: michael@0: PKIX_DECREF(filtered); michael@0: PKIX_DECREF(candidate); michael@0: michael@0: PKIX_RETURN(CERTSELECTOR); michael@0: michael@0: }