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