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