blob: 8e40596541a8431162d1cd589860db9ae0e97eb0 [file] [log] [blame]
/* 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_policychecker.c
*
* Functions for Policy Checker
*
*/
#include "pkix_policychecker.h"
/* --Forward declarations----------------------------------------------- */
static PKIX_Error *
pkix_PolicyChecker_MakeSingleton(
PKIX_PL_Object *listItem,
PKIX_Boolean immutability,
PKIX_List **pList,
void *plContext);
/* --Private-PolicyCheckerState-Functions---------------------------------- */
/*
* FUNCTION:pkix_PolicyCheckerState_Destroy
* (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_PolicyCheckerState_Destroy(
PKIX_PL_Object *object,
void *plContext)
{
PKIX_PolicyCheckerState *checkerState = NULL;
PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Destroy");
PKIX_NULLCHECK_ONE(object);
PKIX_CHECK(pkix_CheckType
(object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext),
PKIX_OBJECTNOTPOLICYCHECKERSTATE);
checkerState = (PKIX_PolicyCheckerState *)object;
PKIX_DECREF(checkerState->certPoliciesExtension);
PKIX_DECREF(checkerState->policyMappingsExtension);
PKIX_DECREF(checkerState->policyConstraintsExtension);
PKIX_DECREF(checkerState->inhibitAnyPolicyExtension);
PKIX_DECREF(checkerState->anyPolicyOID);
PKIX_DECREF(checkerState->validPolicyTree);
PKIX_DECREF(checkerState->userInitialPolicySet);
PKIX_DECREF(checkerState->mappedUserInitialPolicySet);
checkerState->policyQualifiersRejected = PKIX_FALSE;
checkerState->explicitPolicy = 0;
checkerState->inhibitAnyPolicy = 0;
checkerState->policyMapping = 0;
checkerState->numCerts = 0;
checkerState->certsProcessed = 0;
checkerState->certPoliciesCritical = PKIX_FALSE;
PKIX_DECREF(checkerState->anyPolicyNodeAtBottom);
PKIX_DECREF(checkerState->newAnyPolicyNode);
PKIX_DECREF(checkerState->mappedPolicyOIDs);
cleanup:
PKIX_RETURN(CERTPOLICYCHECKERSTATE);
}
/*
* FUNCTION: pkix_PolicyCheckerState_ToString
* (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
*/
static PKIX_Error *
pkix_PolicyCheckerState_ToString(
PKIX_PL_Object *object,
PKIX_PL_String **pCheckerStateString,
void *plContext)
{
PKIX_PolicyCheckerState *state = NULL;
PKIX_PL_String *resultString = NULL;
PKIX_PL_String *policiesExtOIDString = NULL;
PKIX_PL_String *policyMapOIDString = NULL;
PKIX_PL_String *policyConstrOIDString = NULL;
PKIX_PL_String *inhAnyPolOIDString = NULL;
PKIX_PL_String *anyPolicyOIDString = NULL;
PKIX_PL_String *validPolicyTreeString = NULL;
PKIX_PL_String *userInitialPolicySetString = NULL;
PKIX_PL_String *mappedUserPolicySetString = NULL;
PKIX_PL_String *mappedPolicyOIDsString = NULL;
PKIX_PL_String *anyAtBottomString = NULL;
PKIX_PL_String *newAnyPolicyString = NULL;
PKIX_PL_String *formatString = NULL;
PKIX_PL_String *trueString = NULL;
PKIX_PL_String *falseString = NULL;
PKIX_PL_String *nullString = NULL;
PKIX_Boolean initialPolicyMappingInhibit = PKIX_FALSE;
PKIX_Boolean initialExplicitPolicy = PKIX_FALSE;
PKIX_Boolean initialAnyPolicyInhibit = PKIX_FALSE;
PKIX_Boolean initialIsAnyPolicy = PKIX_FALSE;
PKIX_Boolean policyQualifiersRejected = PKIX_FALSE;
PKIX_Boolean certPoliciesCritical = PKIX_FALSE;
char *asciiFormat =
"{\n"
"\tcertPoliciesExtension: \t%s\n"
"\tpolicyMappingsExtension: \t%s\n"
"\tpolicyConstraintsExtension:\t%s\n"
"\tinhibitAnyPolicyExtension:\t%s\n"
"\tanyPolicyOID: \t%s\n"
"\tinitialIsAnyPolicy: \t%s\n"
"\tvalidPolicyTree: \t%s\n"
"\tuserInitialPolicySet: \t%s\n"
"\tmappedUserPolicySet: \t%s\n"
"\tpolicyQualifiersRejected: \t%s\n"
"\tinitialPolMappingInhibit: \t%s\n"
"\tinitialExplicitPolicy: \t%s\n"
"\tinitialAnyPolicyInhibit: \t%s\n"
"\texplicitPolicy: \t%d\n"
"\tinhibitAnyPolicy: \t%d\n"
"\tpolicyMapping: \t%d\n"
"\tnumCerts: \t%d\n"
"\tcertsProcessed: \t%d\n"
"\tanyPolicyNodeAtBottom: \t%s\n"
"\tnewAnyPolicyNode: \t%s\n"
"\tcertPoliciesCritical: \t%s\n"
"\tmappedPolicyOIDs: \t%s\n"
"}";
PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_ToString");
PKIX_NULLCHECK_TWO(object, pCheckerStateString);
PKIX_CHECK(pkix_CheckType
(object, PKIX_CERTPOLICYCHECKERSTATE_TYPE, plContext),
PKIX_OBJECTNOTPOLICYCHECKERSTATE);
state = (PKIX_PolicyCheckerState *)object;
PKIX_NULLCHECK_THREE
(state->certPoliciesExtension,
state->policyMappingsExtension,
state->policyConstraintsExtension);
PKIX_NULLCHECK_THREE
(state->inhibitAnyPolicyExtension,
state->anyPolicyOID,
state->userInitialPolicySet);
PKIX_CHECK(PKIX_PL_String_Create
(PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext),
PKIX_STRINGCREATEFAILED);
/*
* Create TRUE, FALSE, and "NULL" PKIX_PL_Strings. But creating a
* PKIX_PL_String is complicated enough, it's worth checking, for
* each, to make sure the string is needed.
*/
initialPolicyMappingInhibit = state->initialPolicyMappingInhibit;
initialExplicitPolicy = state->initialExplicitPolicy;
initialAnyPolicyInhibit = state->initialAnyPolicyInhibit;
initialIsAnyPolicy = state->initialIsAnyPolicy;
policyQualifiersRejected = state->policyQualifiersRejected;
certPoliciesCritical = state->certPoliciesCritical;
if (initialPolicyMappingInhibit || initialExplicitPolicy ||
initialAnyPolicyInhibit || initialIsAnyPolicy ||
policyQualifiersRejected || certPoliciesCritical) {
PKIX_CHECK(PKIX_PL_String_Create
(PKIX_ESCASCII, "TRUE", 0, &trueString, plContext),
PKIX_STRINGCREATEFAILED);
}
if (!initialPolicyMappingInhibit || !initialExplicitPolicy ||
!initialAnyPolicyInhibit || !initialIsAnyPolicy ||
!policyQualifiersRejected || !certPoliciesCritical) {
PKIX_CHECK(PKIX_PL_String_Create
(PKIX_ESCASCII, "FALSE", 0, &falseString, plContext),
PKIX_STRINGCREATEFAILED);
}
if (!(state->anyPolicyNodeAtBottom) || !(state->newAnyPolicyNode)) {
PKIX_CHECK(PKIX_PL_String_Create
(PKIX_ESCASCII, "(null)", 0, &nullString, plContext),
PKIX_STRINGCREATEFAILED);
}
PKIX_TOSTRING
(state->certPoliciesExtension, &policiesExtOIDString, plContext,
PKIX_OBJECTTOSTRINGFAILED);
PKIX_TOSTRING
(state->policyMappingsExtension,
&policyMapOIDString,
plContext,
PKIX_OBJECTTOSTRINGFAILED);
PKIX_TOSTRING
(state->policyConstraintsExtension,
&policyConstrOIDString,
plContext,
PKIX_OBJECTTOSTRINGFAILED);
PKIX_TOSTRING
(state->inhibitAnyPolicyExtension,
&inhAnyPolOIDString,
plContext,
PKIX_OBJECTTOSTRINGFAILED);
PKIX_TOSTRING(state->anyPolicyOID, &anyPolicyOIDString, plContext,
PKIX_OBJECTTOSTRINGFAILED);
PKIX_TOSTRING(state->validPolicyTree, &validPolicyTreeString, plContext,
PKIX_OBJECTTOSTRINGFAILED);
PKIX_TOSTRING
(state->userInitialPolicySet,
&userInitialPolicySetString,
plContext,
PKIX_OBJECTTOSTRINGFAILED);
PKIX_TOSTRING
(state->mappedUserInitialPolicySet,
&mappedUserPolicySetString,
plContext,
PKIX_OBJECTTOSTRINGFAILED);
if (state->anyPolicyNodeAtBottom) {
PKIX_CHECK(pkix_SinglePolicyNode_ToString
(state->anyPolicyNodeAtBottom,
&anyAtBottomString,
plContext),
PKIX_SINGLEPOLICYNODETOSTRINGFAILED);
} else {
PKIX_INCREF(nullString);
anyAtBottomString = nullString;
}
if (state->newAnyPolicyNode) {
PKIX_CHECK(pkix_SinglePolicyNode_ToString
(state->newAnyPolicyNode,
&newAnyPolicyString,
plContext),
PKIX_SINGLEPOLICYNODETOSTRINGFAILED);
} else {
PKIX_INCREF(nullString);
newAnyPolicyString = nullString;
}
PKIX_TOSTRING
(state->mappedPolicyOIDs,
&mappedPolicyOIDsString,
plContext,
PKIX_OBJECTTOSTRINGFAILED);
PKIX_CHECK(PKIX_PL_Sprintf
(&resultString,
plContext,
formatString,
policiesExtOIDString,
policyMapOIDString,
policyConstrOIDString,
inhAnyPolOIDString,
anyPolicyOIDString,
initialIsAnyPolicy?trueString:falseString,
validPolicyTreeString,
userInitialPolicySetString,
mappedUserPolicySetString,
policyQualifiersRejected?trueString:falseString,
initialPolicyMappingInhibit?trueString:falseString,
initialExplicitPolicy?trueString:falseString,
initialAnyPolicyInhibit?trueString:falseString,
state->explicitPolicy,
state->inhibitAnyPolicy,
state->policyMapping,
state->numCerts,
state->certsProcessed,
anyAtBottomString,
newAnyPolicyString,
certPoliciesCritical?trueString:falseString,
mappedPolicyOIDsString),
PKIX_SPRINTFFAILED);
*pCheckerStateString = resultString;
cleanup:
PKIX_DECREF(policiesExtOIDString);
PKIX_DECREF(policyMapOIDString);
PKIX_DECREF(policyConstrOIDString);
PKIX_DECREF(inhAnyPolOIDString);
PKIX_DECREF(anyPolicyOIDString);
PKIX_DECREF(validPolicyTreeString);
PKIX_DECREF(userInitialPolicySetString);
PKIX_DECREF(mappedUserPolicySetString);
PKIX_DECREF(anyAtBottomString);
PKIX_DECREF(newAnyPolicyString);
PKIX_DECREF(mappedPolicyOIDsString);
PKIX_DECREF(formatString);
PKIX_DECREF(trueString);
PKIX_DECREF(falseString);
PKIX_DECREF(nullString);
PKIX_RETURN(CERTPOLICYCHECKERSTATE);
}
/*
* FUNCTION: pkix_PolicyCheckerState_RegisterSelf
* DESCRIPTION:
*
* Registers PKIX_POLICYCHECKERSTATE_TYPE and its related functions
* with systemClasses[]
*
* PARAMETERS:
* "plContext"
* Platform-specific context pointer.
* 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_PolicyCheckerState_RegisterSelf(void *plContext)
{
extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
pkix_ClassTable_Entry entry;
PKIX_ENTER
(CERTPOLICYCHECKERSTATE,
"pkix_PolicyCheckerState_RegisterSelf");
entry.description = "PolicyCheckerState";
entry.objCounter = 0;
entry.typeObjectSize = sizeof(PKIX_PolicyCheckerState);
entry.destructor = pkix_PolicyCheckerState_Destroy;
entry.equalsFunction = NULL;
entry.hashcodeFunction = NULL;
entry.toStringFunction = pkix_PolicyCheckerState_ToString;
entry.comparator = NULL;
entry.duplicateFunction = NULL;
systemClasses[PKIX_CERTPOLICYCHECKERSTATE_TYPE] = entry;
PKIX_RETURN(CERTPOLICYCHECKERSTATE);
}
/*
* FUNCTION:pkix_PolicyCheckerState_Create
* DESCRIPTION:
*
* Creates a PolicyCheckerState Object, using the List pointed to
* by "initialPolicies" for the user-initial-policy-set, the Boolean value
* of "policyQualifiersRejected" for the policyQualifiersRejected parameter,
* the Boolean value of "initialPolicyMappingInhibit" for the
* inhibitPolicyMappings parameter, the Boolean value of
* "initialExplicitPolicy" for the initialExplicitPolicy parameter, the
* Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy
* parameter, and the UInt32 value of "numCerts" as the number of
* certificates in the chain; and stores the Object at "pCheckerState".
*
* PARAMETERS:
* "initialPolicies"
* Address of List of OIDs comprising the user-initial-policy-set; the List
* may be empty, but must be non-NULL
* "policyQualifiersRejected"
* Boolean value of the policyQualifiersRejected parameter
* "initialPolicyMappingInhibit"
* Boolean value of the inhibitPolicyMappings parameter
* "initialExplicitPolicy"
* Boolean value of the initialExplicitPolicy parameter
* "initialAnyPolicyInhibit"
* Boolean value of the inhibitAnyPolicy parameter
* "numCerts"
* Number of certificates in the chain to be validated
* "pCheckerState"
* Address where PolicyCheckerState will be 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 CertPolicyCheckerState Error if the functions fails in a
* non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyCheckerState_Create(
PKIX_List *initialPolicies,
PKIX_Boolean policyQualifiersRejected,
PKIX_Boolean initialPolicyMappingInhibit,
PKIX_Boolean initialExplicitPolicy,
PKIX_Boolean initialAnyPolicyInhibit,
PKIX_UInt32 numCerts,
PKIX_PolicyCheckerState **pCheckerState,
void *plContext)
{
PKIX_PolicyCheckerState *checkerState = NULL;
PKIX_PolicyNode *policyNode = NULL;
PKIX_List *anyPolicyList = NULL;
PKIX_Boolean initialPoliciesIsEmpty = PKIX_FALSE;
PKIX_ENTER(CERTPOLICYCHECKERSTATE, "pkix_PolicyCheckerState_Create");
PKIX_NULLCHECK_TWO(initialPolicies, pCheckerState);
PKIX_CHECK(PKIX_PL_Object_Alloc
(PKIX_CERTPOLICYCHECKERSTATE_TYPE,
sizeof (PKIX_PolicyCheckerState),
(PKIX_PL_Object **)&checkerState,
plContext),
PKIX_COULDNOTCREATEPOLICYCHECKERSTATEOBJECT);
/* Create constant PKIX_PL_OIDs: */
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_CERTIFICATEPOLICIES_OID,
&(checkerState->certPoliciesExtension),
plContext),
PKIX_OIDCREATEFAILED);
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_POLICYMAPPINGS_OID,
&(checkerState->policyMappingsExtension),
plContext),
PKIX_OIDCREATEFAILED);
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_POLICYCONSTRAINTS_OID,
&(checkerState->policyConstraintsExtension),
plContext),
PKIX_OIDCREATEFAILED);
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_INHIBITANYPOLICY_OID,
&(checkerState->inhibitAnyPolicyExtension),
plContext),
PKIX_OIDCREATEFAILED);
PKIX_CHECK(PKIX_PL_OID_Create
(PKIX_CERTIFICATEPOLICIES_ANYPOLICY_OID,
&(checkerState->anyPolicyOID),
plContext),
PKIX_OIDCREATEFAILED);
/* Create an initial policy set from argument supplied */
PKIX_INCREF(initialPolicies);
checkerState->userInitialPolicySet = initialPolicies;
PKIX_INCREF(initialPolicies);
checkerState->mappedUserInitialPolicySet = initialPolicies;
PKIX_CHECK(PKIX_List_IsEmpty
(initialPolicies,
&initialPoliciesIsEmpty,
plContext),
PKIX_LISTISEMPTYFAILED);
if (initialPoliciesIsEmpty) {
checkerState->initialIsAnyPolicy = PKIX_TRUE;
} else {
PKIX_CHECK(pkix_List_Contains
(initialPolicies,
(PKIX_PL_Object *)(checkerState->anyPolicyOID),
&(checkerState->initialIsAnyPolicy),
plContext),
PKIX_LISTCONTAINSFAILED);
}
checkerState->policyQualifiersRejected =
policyQualifiersRejected;
checkerState->initialExplicitPolicy = initialExplicitPolicy;
checkerState->explicitPolicy =
(initialExplicitPolicy? 0: numCerts + 1);
checkerState->initialAnyPolicyInhibit = initialAnyPolicyInhibit;
checkerState->inhibitAnyPolicy =
(initialAnyPolicyInhibit? 0: numCerts + 1);
checkerState->initialPolicyMappingInhibit = initialPolicyMappingInhibit;
checkerState->policyMapping =
(initialPolicyMappingInhibit? 0: numCerts + 1);
;
checkerState->numCerts = numCerts;
checkerState->certsProcessed = 0;
checkerState->certPoliciesCritical = PKIX_FALSE;
/* Create a valid_policy_tree as in RFC3280 6.1.2(a) */
PKIX_CHECK(pkix_PolicyChecker_MakeSingleton
((PKIX_PL_Object *)(checkerState->anyPolicyOID),
PKIX_TRUE,
&anyPolicyList,
plContext),
PKIX_POLICYCHECKERMAKESINGLETONFAILED);
PKIX_CHECK(pkix_PolicyNode_Create
(checkerState->anyPolicyOID, /* validPolicy */
NULL, /* qualifier set */
PKIX_FALSE, /* criticality */
anyPolicyList, /* expectedPolicySet */
&policyNode,
plContext),
PKIX_POLICYNODECREATEFAILED);
checkerState->validPolicyTree = policyNode;
/*
* Since the initial validPolicyTree specifies
* ANY_POLICY, begin with a pointer to the root node.
*/
PKIX_INCREF(policyNode);
checkerState->anyPolicyNodeAtBottom = policyNode;
checkerState->newAnyPolicyNode = NULL;
checkerState->mappedPolicyOIDs = NULL;
*pCheckerState = checkerState;
checkerState = NULL;
cleanup:
PKIX_DECREF(checkerState);
PKIX_DECREF(anyPolicyList);
PKIX_RETURN(CERTPOLICYCHECKERSTATE);
}
/* --Private-PolicyChecker-Functions--------------------------------------- */
/*
* FUNCTION: pkix_PolicyChecker_MapContains
* DESCRIPTION:
*
* Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to
* determine whether the OID pointed to by "policy" is among the
* issuerDomainPolicies or subjectDomainPolicies of "certPolicyMaps", and
* stores the result in "pFound".
*
* This function is intended to allow an efficient check that the proscription
* against anyPolicy being mapped, described in RFC3280 Section 6.1.4(a), is
* not violated.
*
* PARAMETERS:
* "certPolicyMaps"
* Address of List of CertPolicyMaps to be searched. May be empty, but
* must be non-NULL
* "policy"
* Address of OID to be checked for. Must be non-NULL
* "pFound"
* Address where the result of the search will be 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 CertChainChecker 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_PolicyChecker_MapContains(
PKIX_List *certPolicyMaps,
PKIX_PL_OID *policy,
PKIX_Boolean *pFound,
void *plContext)
{
PKIX_PL_CertPolicyMap *map = NULL;
PKIX_UInt32 numEntries = 0;
PKIX_UInt32 index = 0;
PKIX_Boolean match = PKIX_FALSE;
PKIX_PL_OID *issuerDomainPolicy = NULL;
PKIX_PL_OID *subjectDomainPolicy = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MapContains");
PKIX_NULLCHECK_THREE(certPolicyMaps, policy, pFound);
PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext),
PKIX_LISTGETLENGTHFAILED);
for (index = 0; (!match) && (index < numEntries); index++) {
PKIX_CHECK(PKIX_List_GetItem
(certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext),
PKIX_LISTGETITEMFAILED);
PKIX_NULLCHECK_ONE(map);
PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
(map, &issuerDomainPolicy, plContext),
PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED);
PKIX_EQUALS
(policy, issuerDomainPolicy, &match, plContext,
PKIX_OBJECTEQUALSFAILED);
if (!match) {
PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy
(map, &subjectDomainPolicy, plContext),
PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED);
PKIX_EQUALS
(policy, subjectDomainPolicy, &match, plContext,
PKIX_OBJECTEQUALSFAILED);
}
PKIX_DECREF(map);
PKIX_DECREF(issuerDomainPolicy);
PKIX_DECREF(subjectDomainPolicy);
}
*pFound = match;
cleanup:
PKIX_DECREF(map);
PKIX_DECREF(issuerDomainPolicy);
PKIX_DECREF(subjectDomainPolicy);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_MapGetSubjectDomainPolicies
* DESCRIPTION:
*
* Checks the List of CertPolicyMaps pointed to by "certPolicyMaps", to create
* a list of all SubjectDomainPolicies for which the IssuerDomainPolicy is the
* policy pointed to by "policy", and stores the result in
* "pSubjectDomainPolicies".
*
* If the List of CertPolicyMaps provided in "certPolicyMaps" is NULL, the
* resulting List will be NULL. If there are CertPolicyMaps, but none that
* include "policy" as an IssuerDomainPolicy, the returned List pointer will
* be NULL. Otherwise, the returned List will contain the SubjectDomainPolicies
* of all CertPolicyMaps for which "policy" is the IssuerDomainPolicy. If a
* List is returned it will be immutable.
*
* PARAMETERS:
* "certPolicyMaps"
* Address of List of CertPolicyMaps to be searched. May be empty or NULL.
* "policy"
* Address of OID to be checked for. Must be non-NULL
* "pSubjectDomainPolicies"
* Address where the result of the search will be 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 CertChainChecker 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_PolicyChecker_MapGetSubjectDomainPolicies(
PKIX_List *certPolicyMaps,
PKIX_PL_OID *policy,
PKIX_List **pSubjectDomainPolicies,
void *plContext)
{
PKIX_PL_CertPolicyMap *map = NULL;
PKIX_List *subjectList = NULL;
PKIX_UInt32 numEntries = 0;
PKIX_UInt32 index = 0;
PKIX_Boolean match = PKIX_FALSE;
PKIX_PL_OID *issuerDomainPolicy = NULL;
PKIX_PL_OID *subjectDomainPolicy = NULL;
PKIX_ENTER
(CERTCHAINCHECKER,
"pkix_PolicyChecker_MapGetSubjectDomainPolicies");
PKIX_NULLCHECK_TWO(policy, pSubjectDomainPolicies);
if (certPolicyMaps) {
PKIX_CHECK(PKIX_List_GetLength
(certPolicyMaps,
&numEntries,
plContext),
PKIX_LISTGETLENGTHFAILED);
}
for (index = 0; index < numEntries; index++) {
PKIX_CHECK(PKIX_List_GetItem
(certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext),
PKIX_LISTGETITEMFAILED);
PKIX_NULLCHECK_ONE(map);
PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
(map, &issuerDomainPolicy, plContext),
PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED);
PKIX_EQUALS
(policy, issuerDomainPolicy, &match, plContext,
PKIX_OBJECTEQUALSFAILED);
if (match) {
if (!subjectList) {
PKIX_CHECK(PKIX_List_Create(&subjectList, plContext),
PKIX_LISTCREATEFAILED);
}
PKIX_CHECK(PKIX_PL_CertPolicyMap_GetSubjectDomainPolicy
(map, &subjectDomainPolicy, plContext),
PKIX_CERTPOLICYMAPGETSUBJECTDOMAINPOLICYFAILED);
PKIX_CHECK(PKIX_List_AppendItem
(subjectList,
(PKIX_PL_Object *)subjectDomainPolicy,
plContext),
PKIX_LISTAPPENDITEMFAILED);
}
PKIX_DECREF(map);
PKIX_DECREF(issuerDomainPolicy);
PKIX_DECREF(subjectDomainPolicy);
}
if (subjectList) {
PKIX_CHECK(PKIX_List_SetImmutable(subjectList, plContext),
PKIX_LISTSETIMMUTABLEFAILED);
}
*pSubjectDomainPolicies = subjectList;
cleanup:
if (PKIX_ERROR_RECEIVED) {
PKIX_DECREF(subjectList);
}
PKIX_DECREF(map);
PKIX_DECREF(issuerDomainPolicy);
PKIX_DECREF(subjectDomainPolicy);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_MapGetMappedPolicies
* DESCRIPTION:
*
* Checks the List of CertPolicyMaps pointed to by "certPolicyMaps" to create a
* List of all IssuerDomainPolicies, and stores the result in
* "pMappedPolicies".
*
* The caller may not rely on the IssuerDomainPolicies to be in any particular
* order. IssuerDomainPolicies that appear in more than one CertPolicyMap will
* only appear once in "pMappedPolicies". If "certPolicyMaps" is empty the
* result will be an empty List. The created List is mutable.
*
* PARAMETERS:
* "certPolicyMaps"
* Address of List of CertPolicyMaps to be searched. May be empty, but
* must be non-NULL.
* "pMappedPolicies"
* Address where the result will be 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 CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
PKIX_Error *
pkix_PolicyChecker_MapGetMappedPolicies(
PKIX_List *certPolicyMaps,
PKIX_List **pMappedPolicies,
void *plContext)
{
PKIX_PL_CertPolicyMap *map = NULL;
PKIX_List *mappedList = NULL;
PKIX_UInt32 numEntries = 0;
PKIX_UInt32 index = 0;
PKIX_Boolean isContained = PKIX_FALSE;
PKIX_PL_OID *issuerDomainPolicy = NULL;
PKIX_ENTER
(CERTCHAINCHECKER, "pkix_PolicyChecker_MapGetMappedPolicies");
PKIX_NULLCHECK_TWO(certPolicyMaps, pMappedPolicies);
PKIX_CHECK(PKIX_List_Create(&mappedList, plContext),
PKIX_LISTCREATEFAILED);
PKIX_CHECK(PKIX_List_GetLength(certPolicyMaps, &numEntries, plContext),
PKIX_LISTGETLENGTHFAILED);
for (index = 0; index < numEntries; index++) {
PKIX_CHECK(PKIX_List_GetItem
(certPolicyMaps, index, (PKIX_PL_Object **)&map, plContext),
PKIX_LISTGETITEMFAILED);
PKIX_NULLCHECK_ONE(map);
PKIX_CHECK(PKIX_PL_CertPolicyMap_GetIssuerDomainPolicy
(map, &issuerDomainPolicy, plContext),
PKIX_CERTPOLICYMAPGETISSUERDOMAINPOLICYFAILED);
PKIX_CHECK(pkix_List_Contains
(mappedList,
(PKIX_PL_Object *)issuerDomainPolicy,
&isContained,
plContext),
PKIX_LISTCONTAINSFAILED);
if (isContained == PKIX_FALSE) {
PKIX_CHECK(PKIX_List_AppendItem
(mappedList,
(PKIX_PL_Object *)issuerDomainPolicy,
plContext),
PKIX_LISTAPPENDITEMFAILED);
}
PKIX_DECREF(map);
PKIX_DECREF(issuerDomainPolicy);
}
*pMappedPolicies = mappedList;
cleanup:
if (PKIX_ERROR_RECEIVED) {
PKIX_DECREF(mappedList);
}
PKIX_DECREF(map);
PKIX_DECREF(issuerDomainPolicy);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_MakeMutableCopy
* DESCRIPTION:
*
* Creates a mutable copy of the List pointed to by "list", which may or may
* not be immutable, and stores the address at "pMutableCopy".
*
* PARAMETERS:
* "list"
* Address of List to be copied. Must be non-NULL.
* "pMutableCopy"
* Address where mutable copy will be 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 CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyChecker_MakeMutableCopy(
PKIX_List *list,
PKIX_List **pMutableCopy,
void *plContext)
{
PKIX_List *newList = NULL;
PKIX_UInt32 listLen = 0;
PKIX_UInt32 listIx = 0;
PKIX_PL_Object *object = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeMutableCopy");
PKIX_NULLCHECK_TWO(list, pMutableCopy);
PKIX_CHECK(PKIX_List_Create(&newList, plContext),
PKIX_LISTCREATEFAILED);
PKIX_CHECK(PKIX_List_GetLength(list, &listLen, plContext),
PKIX_LISTGETLENGTHFAILED);
for (listIx = 0; listIx < listLen; listIx++) {
PKIX_CHECK(PKIX_List_GetItem(list, listIx, &object, plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(PKIX_List_AppendItem(newList, object, plContext),
PKIX_LISTAPPENDITEMFAILED);
PKIX_DECREF(object);
}
*pMutableCopy = newList;
newList = NULL;
cleanup:
PKIX_DECREF(newList);
PKIX_DECREF(object);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_MakeSingleton
* DESCRIPTION:
*
* Creates a new List containing the Object pointed to by "listItem", using
* the Boolean value of "immutability" to determine whether to set the List
* immutable, and stores the address at "pList".
*
* PARAMETERS:
* "listItem"
* Address of Object to be inserted into the new List. Must be non-NULL.
* "immutability"
* Boolean value indicating whether new List is to be immutable
* "pList"
* Address where List will be 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 CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyChecker_MakeSingleton(
PKIX_PL_Object *listItem,
PKIX_Boolean immutability,
PKIX_List **pList,
void *plContext)
{
PKIX_List *newList = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_MakeSingleton");
PKIX_NULLCHECK_TWO(listItem, pList);
PKIX_CHECK(PKIX_List_Create(&newList, plContext),
PKIX_LISTCREATEFAILED);
PKIX_CHECK(PKIX_List_AppendItem
(newList, (PKIX_PL_Object *)listItem, plContext),
PKIX_LISTAPPENDITEMFAILED);
if (immutability) {
PKIX_CHECK(PKIX_List_SetImmutable(newList, plContext),
PKIX_LISTSETIMMUTABLEFAILED);
}
*pList = newList;
cleanup:
if (PKIX_ERROR_RECEIVED) {
PKIX_DECREF(newList);
}
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_Spawn
* DESCRIPTION:
*
* Creates a new childNode for the parent pointed to by "parent", using
* the OID pointed to by "policyOID", the List of CertPolicyQualifiers
* pointed to by "qualifiers", the List of OIDs pointed to by
* "subjectDomainPolicies", and the PolicyCheckerState pointed to by
* "state". The new node will be added to "parent".
*
* The validPolicy of the new node is set from the OID pointed to by
* "policyOID". The policy qualifiers for the new node is set from the
* List of qualifiers pointed to by "qualifiers", and may be NULL or
* empty if the argument provided was NULL or empty. The criticality is
* set according to the criticality obtained from the PolicyCheckerState.
* If "subjectDomainPolicies" is NULL, the expectedPolicySet of the
* child is set to contain the same policy as the validPolicy. If
* "subjectDomainPolicies" is not NULL, it is used as the value for
* the expectedPolicySet.
*
* The PolicyCheckerState also contains a constant, anyPolicy, which is
* compared to "policyOID". If they match, the address of the childNode
* is saved in the state's newAnyPolicyNode.
*
* PARAMETERS:
* "parent"
* Address of PolicyNode to which the child will be linked. Must be
* non-NULL.
* "policyOID"
* Address of OID of the new child's validPolicy and also, if
* subjectDomainPolicies is NULL, of the new child's expectedPolicySet.
* Must be non-NULL.
* "qualifiers"
* Address of List of CertPolicyQualifiers. May be NULL or empty.
* "subjectDomainPolicies"
* Address of List of OIDs indicating the policies to which "policy" is
* mapped. May be empty or NULL.
* "state"
* Address of the current PKIX_PolicyCheckerState. Must be non-NULL..
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds
* Returns a CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyChecker_Spawn(
PKIX_PolicyNode *parent,
PKIX_PL_OID *policyOID,
PKIX_List *qualifiers, /* CertPolicyQualifiers */
PKIX_List *subjectDomainPolicies,
PKIX_PolicyCheckerState *state,
void *plContext)
{
PKIX_List *expectedSet = NULL; /* OIDs */
PKIX_PolicyNode *childNode = NULL;
PKIX_Boolean match = PKIX_FALSE;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Spawn");
PKIX_NULLCHECK_THREE(policyOID, parent, state);
if (subjectDomainPolicies) {
PKIX_INCREF(subjectDomainPolicies);
expectedSet = subjectDomainPolicies;
} else {
/* Create the child's ExpectedPolicy Set */
PKIX_CHECK(pkix_PolicyChecker_MakeSingleton
((PKIX_PL_Object *)policyOID,
PKIX_TRUE, /* make expectedPolicySet immutable */
&expectedSet,
plContext),
PKIX_POLICYCHECKERMAKESINGLETONFAILED);
}
PKIX_CHECK(pkix_PolicyNode_Create
(policyOID,
qualifiers,
state->certPoliciesCritical,
expectedSet,
&childNode,
plContext),
PKIX_POLICYNODECREATEFAILED);
/*
* If we had a non-empty mapping, we know the new node could not
* have been created with a validPolicy of anyPolicy. Otherwise,
* check whether we just created a new node with anyPolicy, because
* in that case we want to save the child pointer in newAnyPolicyNode.
*/
if (!subjectDomainPolicies) {
PKIX_EQUALS(policyOID, state->anyPolicyOID, &match, plContext,
PKIX_OBJECTEQUALSFAILED);
if (match) {
PKIX_DECREF(state->newAnyPolicyNode);
PKIX_INCREF(childNode);
state->newAnyPolicyNode = childNode;
}
}
PKIX_CHECK(pkix_PolicyNode_AddToParent(parent, childNode, plContext),
PKIX_POLICYNODEADDTOPARENTFAILED);
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
cleanup:
PKIX_DECREF(childNode);
PKIX_DECREF(expectedSet);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_CheckPolicyRecursive
* DESCRIPTION:
*
* Performs policy processing for the policy whose OID is pointed to by
* "policyOID" and whose List of CertPolicyQualifiers is pointed to by
* "policyQualifiers", using the List of policy OIDs pointed to by
* "subjectDomainPolicies" and the PolicyNode pointed to by "currentNode",
* in accordance with the current PolicyCheckerState pointed to by "state",
* and setting "pChildNodeCreated" to TRUE if a new childNode is created.
* Note: "pChildNodeCreated" is not set to FALSE if no childNode is created.
* The intent of the design is that the caller can set a variable to FALSE
* initially, prior to a recursive set of calls. At the end, the variable
* can be tested to see whether *any* of the calls created a child node.
*
* If the currentNode is not at the bottom of the tree, this function
* calls itself recursively for each child of currentNode. At the bottom of
* the tree, it creates new child nodes as appropriate. This function will
* never be called with policy = anyPolicy.
*
* This function implements the processing described in RFC3280
* Section 6.1.3(d)(1)(i).
*
* PARAMETERS:
* "policyOID"
* Address of OID of the policy to be checked for. Must be non-NULL.
* "policyQualifiers"
* Address of List of CertPolicyQualifiers of the policy to be checked for.
* May be empty or NULL.
* "subjectDomainPolicies"
* Address of List of OIDs indicating the policies to which "policy" is
* mapped. May be empty or NULL.
* "currentNode"
* Address of PolicyNode whose descendants will be checked, if not at the
* bottom of the tree; or whose expectedPolicySet will be compared to
* "policy", if at the bottom. Must be non-NULL.
* "state"
* Address of PolicyCheckerState of the current PolicyChecker. Must be
* non-NULL.
* "pChildNodeCreated"
* Address of the Boolean that will be set TRUE if this function
* creates a child node. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds
* Returns a CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyChecker_CheckPolicyRecursive(
PKIX_PL_OID *policyOID,
PKIX_List *policyQualifiers,
PKIX_List *subjectDomainPolicies,
PKIX_PolicyNode *currentNode,
PKIX_PolicyCheckerState *state,
PKIX_Boolean *pChildNodeCreated,
void *plContext)
{
PKIX_UInt32 depth = 0;
PKIX_UInt32 numChildren = 0;
PKIX_UInt32 childIx = 0;
PKIX_Boolean isIncluded = PKIX_FALSE;
PKIX_List *children = NULL; /* PolicyNodes */
PKIX_PolicyNode *childNode = NULL;
PKIX_List *expectedPolicies = NULL; /* OIDs */
PKIX_ENTER
(CERTCHAINCHECKER,
"pkix_PolicyChecker_CheckPolicyRecursive");
PKIX_NULLCHECK_FOUR(policyOID, currentNode, state, pChildNodeCreated);
/* if not at the bottom of the tree */
PKIX_CHECK(PKIX_PolicyNode_GetDepth
(currentNode, &depth, plContext),
PKIX_POLICYNODEGETDEPTHFAILED);
if (depth < (state->certsProcessed)) {
PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable
(currentNode, &children, plContext),
PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED);
if (children) {
PKIX_CHECK(PKIX_List_GetLength
(children, &numChildren, plContext),
PKIX_LISTGETLENGTHFAILED);
}
for (childIx = 0; childIx < numChildren; childIx++) {
PKIX_CHECK(PKIX_List_GetItem
(children,
childIx,
(PKIX_PL_Object **)&childNode,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive
(policyOID,
policyQualifiers,
subjectDomainPolicies,
childNode,
state,
pChildNodeCreated,
plContext),
PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED);
PKIX_DECREF(childNode);
}
} else { /* if at the bottom of the tree */
/* Check whether policy is in this node's expectedPolicySet */
PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies
(currentNode, &expectedPolicies, plContext),
PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED);
PKIX_NULLCHECK_ONE(expectedPolicies);
PKIX_CHECK(pkix_List_Contains
(expectedPolicies,
(PKIX_PL_Object *)policyOID,
&isIncluded,
plContext),
PKIX_LISTCONTAINSFAILED);
if (isIncluded) {
PKIX_CHECK(pkix_PolicyChecker_Spawn
(currentNode,
policyOID,
policyQualifiers,
subjectDomainPolicies,
state,
plContext),
PKIX_POLICYCHECKERSPAWNFAILED);
*pChildNodeCreated = PKIX_TRUE;
}
}
cleanup:
PKIX_DECREF(children);
PKIX_DECREF(childNode);
PKIX_DECREF(expectedPolicies);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_CheckPolicy
* DESCRIPTION:
*
* Performs the non-recursive portion of the policy processing for the policy
* whose OID is pointed to by "policyOID" and whose List of
* CertPolicyQualifiers is pointed to by "policyQualifiers", for the
* Certificate pointed to by "cert" with the List of CertPolicyMaps pointed
* to by "maps", in accordance with the current PolicyCheckerState pointed
* to by "state".
*
* This function implements the processing described in RFC3280
* Section 6.1.3(d)(1)(i).
*
* PARAMETERS:
* "policyOID"
* Address of OID of the policy to be checked for. Must be non-NULL.
* "policyQualifiers"
* Address of List of CertPolicyQualifiers of the policy to be checked for.
* May be empty or NULL.
* "cert"
* Address of the current certificate. Must be non-NULL.
* "maps"
* Address of List of CertPolicyMaps for the current certificate
* "state"
* Address of PolicyCheckerState of the current PolicyChecker. Must be
* non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds
* Returns a CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyChecker_CheckPolicy(
PKIX_PL_OID *policyOID,
PKIX_List *policyQualifiers,
PKIX_PL_Cert *cert,
PKIX_List *maps,
PKIX_PolicyCheckerState *state,
void *plContext)
{
PKIX_Boolean childNodeCreated = PKIX_FALSE;
PKIX_Boolean okToSpawn = PKIX_FALSE;
PKIX_Boolean found = PKIX_FALSE;
PKIX_List *subjectDomainPolicies = NULL;
PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckPolicy");
PKIX_NULLCHECK_THREE(policyOID, cert, state);
/*
* If this is not the last certificate, get the set of
* subjectDomainPolicies that "policy" maps to, according to the
* current cert's policy mapping extension. That set will be NULL
* if the current cert does not have a policy mapping extension,
* or if the current policy is not mapped.
*/
if (state->certsProcessed != (state->numCerts - 1)) {
PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies
(maps, policyOID, &subjectDomainPolicies, plContext),
PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
}
/*
* Section 6.1.4(b)(2) tells us that if policyMapping is zero, we
* will have to delete any nodes created with validPolicies equal to
* policies that appear as issuerDomainPolicies in a policy mapping
* extension. Let's avoid creating any such nodes.
*/
if ((state->policyMapping) == 0) {
if (subjectDomainPolicies) {
goto cleanup;
}
}
PKIX_CHECK(pkix_PolicyChecker_CheckPolicyRecursive
(policyOID,
policyQualifiers,
subjectDomainPolicies,
state->validPolicyTree,
state,
&childNodeCreated,
plContext),
PKIX_POLICYCHECKERCHECKPOLICYRECURSIVEFAILED);
if (!childNodeCreated) {
/*
* Section 6.1.3(d)(1)(ii)
* There was no match. If there was a node at
* depth i-1 with valid policy anyPolicy,
* generate a node subordinate to that.
*
* But that means this created node would be in
* the valid-policy-node-set, and will be
* pruned in 6.1.5(g)(iii)(2) unless it is in
* the user-initial-policy-set or the user-
* initial-policy-set is {anyPolicy}. So check,
* and don't create it if it will be pruned.
*/
if (state->anyPolicyNodeAtBottom) {
if (state->initialIsAnyPolicy) {
okToSpawn = PKIX_TRUE;
} else {
PKIX_CHECK(pkix_List_Contains
(state->mappedUserInitialPolicySet,
(PKIX_PL_Object *)policyOID,
&okToSpawn,
plContext),
PKIX_LISTCONTAINSFAILED);
}
if (okToSpawn) {
PKIX_CHECK(pkix_PolicyChecker_Spawn
(state->anyPolicyNodeAtBottom,
policyOID,
policyQualifiers,
subjectDomainPolicies,
state,
plContext),
PKIX_POLICYCHECKERSPAWNFAILED);
childNodeCreated = PKIX_TRUE;
}
}
}
if (childNodeCreated) {
/*
* If this policy had qualifiers, and the certificate policies
* extension was marked critical, and the user cannot deal with
* policy qualifiers, throw an error.
*/
if (policyQualifiers &&
state->certPoliciesCritical &&
state->policyQualifiersRejected) {
PKIX_ERROR
(PKIX_QUALIFIERSINCRITICALCERTIFICATEPOLICYEXTENSION);
}
/*
* If the policy we just propagated was in the list of mapped
* policies, remove it from the list. That list is used, at the
* end, to determine policies that have not been propagated.
*/
if (state->mappedPolicyOIDs) {
PKIX_CHECK(pkix_List_Contains
(state->mappedPolicyOIDs,
(PKIX_PL_Object *)policyOID,
&found,
plContext),
PKIX_LISTCONTAINSFAILED);
if (found) {
PKIX_CHECK(pkix_List_Remove
(state->mappedPolicyOIDs,
(PKIX_PL_Object *)policyOID,
plContext),
PKIX_LISTREMOVEFAILED);
}
}
}
cleanup:
PKIX_DECREF(subjectDomainPolicies);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_CheckAny
* DESCRIPTION:
* Performs the creation of PolicyNodes, for the PolicyNode pointed to by
* "currentNode" and PolicyNodes subordinate to it, using the List of
* qualifiers pointed to by "qualsOfAny", in accordance with the current
* certificate's PolicyMaps pointed to by "policyMaps" and the current
* PolicyCheckerState pointed to by "state".
*
* If the currentNode is not just above the bottom of the validPolicyTree, this
* function calls itself recursively for each child of currentNode. At the
* level just above the bottom, for each policy in the currentNode's
* expectedPolicySet not already present in a child node, it creates a new
* child node. The validPolicy of the child created, and its expectedPolicySet,
* will be the policy from the currentNode's expectedPolicySet. The policy
* qualifiers will be the qualifiers from the current certificate's anyPolicy,
* the "qualsOfAny" parameter. If the currentNode's expectedSet includes
* anyPolicy, a childNode will be created with a policy of anyPolicy. This is
* the only way such a node can be created.
*
* This function is called only when anyPolicy is one of the current
* certificate's policies. This function implements the processing described
* in RFC3280 Section 6.1.3(d)(2).
*
* PARAMETERS:
* "currentNode"
* Address of PolicyNode whose descendants will be checked, if not at the
* bottom of the tree; or whose expectedPolicySet will be compared to those
* in "alreadyPresent", if at the bottom. Must be non-NULL.
* "qualsOfAny"
* Address of List of qualifiers of the anyPolicy in the current
* certificate. May be empty or NULL.
* "policyMaps"
* Address of the List of PolicyMaps of the current certificate. May be
* empty or NULL.
* "state"
* Address of the current state of the PKIX_PolicyChecker.
* Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds
* Returns a CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyChecker_CheckAny(
PKIX_PolicyNode *currentNode,
PKIX_List *qualsOfAny, /* CertPolicyQualifiers */
PKIX_List *policyMaps, /* CertPolicyMaps */
PKIX_PolicyCheckerState *state,
void *plContext)
{
PKIX_UInt32 depth = 0;
PKIX_UInt32 numChildren = 0;
PKIX_UInt32 childIx = 0;
PKIX_UInt32 numPolicies = 0;
PKIX_UInt32 polx = 0;
PKIX_Boolean isIncluded = PKIX_FALSE;
PKIX_List *children = NULL; /* PolicyNodes */
PKIX_PolicyNode *childNode = NULL;
PKIX_List *expectedPolicies = NULL; /* OIDs */
PKIX_PL_OID *policyOID = NULL;
PKIX_PL_OID *childPolicy = NULL;
PKIX_List *subjectDomainPolicies = NULL; /* OIDs */
PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_CheckAny");
PKIX_NULLCHECK_TWO(currentNode, state);
PKIX_CHECK(PKIX_PolicyNode_GetDepth
(currentNode, &depth, plContext),
PKIX_POLICYNODEGETDEPTHFAILED);
PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable
(currentNode, &children, plContext),
PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED);
if (children) {
PKIX_CHECK(PKIX_List_GetLength
(children, &numChildren, plContext),
PKIX_LISTGETLENGTHFAILED);
}
if (depth < (state->certsProcessed)) {
for (childIx = 0; childIx < numChildren; childIx++) {
PKIX_CHECK(PKIX_List_GetItem
(children,
childIx,
(PKIX_PL_Object **)&childNode,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_NULLCHECK_ONE(childNode);
PKIX_CHECK(pkix_PolicyChecker_CheckAny
(childNode,
qualsOfAny,
policyMaps,
state,
plContext),
PKIX_POLICYCHECKERCHECKANYFAILED);
PKIX_DECREF(childNode);
}
} else { /* if at the bottom of the tree */
PKIX_CHECK(PKIX_PolicyNode_GetExpectedPolicies
(currentNode, &expectedPolicies, plContext),
PKIX_POLICYNODEGETEXPECTEDPOLICIESFAILED);
/* Expected Policy Set is not allowed to be NULL */
PKIX_NULLCHECK_ONE(expectedPolicies);
PKIX_CHECK(PKIX_List_GetLength
(expectedPolicies, &numPolicies, plContext),
PKIX_LISTGETLENGTHFAILED);
for (polx = 0; polx < numPolicies; polx++) {
PKIX_CHECK(PKIX_List_GetItem
(expectedPolicies,
polx,
(PKIX_PL_Object **)&policyOID,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_NULLCHECK_ONE(policyOID);
isIncluded = PKIX_FALSE;
for (childIx = 0;
(!isIncluded && (childIx < numChildren));
childIx++) {
PKIX_CHECK(PKIX_List_GetItem
(children,
childIx,
(PKIX_PL_Object **)&childNode,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_NULLCHECK_ONE(childNode);
PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy
(childNode, &childPolicy, plContext),
PKIX_POLICYNODEGETVALIDPOLICYFAILED);
PKIX_NULLCHECK_ONE(childPolicy);
PKIX_EQUALS(policyOID, childPolicy, &isIncluded, plContext,
PKIX_OBJECTEQUALSFAILED);
PKIX_DECREF(childNode);
PKIX_DECREF(childPolicy);
}
if (!isIncluded) {
if (policyMaps) {
PKIX_CHECK
(pkix_PolicyChecker_MapGetSubjectDomainPolicies
(policyMaps,
policyOID,
&subjectDomainPolicies,
plContext),
PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
}
PKIX_CHECK(pkix_PolicyChecker_Spawn
(currentNode,
policyOID,
qualsOfAny,
subjectDomainPolicies,
state,
plContext),
PKIX_POLICYCHECKERSPAWNFAILED);
PKIX_DECREF(subjectDomainPolicies);
}
PKIX_DECREF(policyOID);
}
}
cleanup:
PKIX_DECREF(children);
PKIX_DECREF(childNode);
PKIX_DECREF(expectedPolicies);
PKIX_DECREF(policyOID);
PKIX_DECREF(childPolicy);
PKIX_DECREF(subjectDomainPolicies);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_CalculateIntersection
* DESCRIPTION:
*
* Processes the PolicyNode pointed to by "currentNode", and its descendants,
* using the PolicyCheckerState pointed to by "state", using the List at
* the address pointed to by "nominees" the OIDs of policies that are in the
* user-initial-policy-set but are not represented among the nodes at the
* bottom of the tree, and storing at "pShouldBePruned" the value TRUE if
* currentNode is childless at the end of this processing, FALSE if it has
* children or is at the bottom of the tree.
*
* When this function is called at the top level, "nominees" should be the List
* of all policies in the user-initial-policy-set. Policies that are
* represented in the valid-policy-node-set are removed from this List. As a
* result when nodes are created according to 6.1.5.(g)(iii)(3)(b), a node will
* be created for each policy remaining in this List.
*
* This function implements the calculation of the intersection of the
* validPolicyTree with the user-initial-policy-set, as described in
* RFC 3280 6.1.5(g)(iii).
*
* PARAMETERS:
* "currentNode"
* Address of PolicyNode whose descendants will be processed as described.
* Must be non-NULL.
* "state"
* Address of the current state of the PKIX_PolicyChecker. Must be non-NULL
* "nominees"
* Address of List of the OIDs for which nodes should be created to replace
* anyPolicy nodes. Must be non-NULL but may be empty.
* "pShouldBePruned"
* Address where Boolean return value, set to TRUE if this PolicyNode
* should be deleted, is stored. Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds
* Returns a CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyChecker_CalculateIntersection(
PKIX_PolicyNode *currentNode,
PKIX_PolicyCheckerState *state,
PKIX_List *nominees, /* OIDs */
PKIX_Boolean *pShouldBePruned,
void *plContext)
{
PKIX_Boolean currentPolicyIsAny = PKIX_FALSE;
PKIX_Boolean parentPolicyIsAny = PKIX_FALSE;
PKIX_Boolean currentPolicyIsValid = PKIX_FALSE;
PKIX_Boolean shouldBePruned = PKIX_FALSE;
PKIX_Boolean priorCriticality = PKIX_FALSE;
PKIX_UInt32 depth = 0;
PKIX_UInt32 numChildren = 0;
PKIX_UInt32 childIndex = 0;
PKIX_UInt32 numNominees = 0;
PKIX_UInt32 polIx = 0;
PKIX_PL_OID *currentPolicy = NULL;
PKIX_PL_OID *parentPolicy = NULL;
PKIX_PL_OID *substPolicy = NULL;
PKIX_PolicyNode *parent = NULL;
PKIX_PolicyNode *child = NULL;
PKIX_List *children = NULL; /* PolicyNodes */
PKIX_List *policyQualifiers = NULL;
PKIX_ENTER
(CERTCHAINCHECKER,
"pkix_PolicyChecker_CalculateIntersection");
/*
* We call this function if the valid_policy_tree is not NULL and
* the user-initial-policy-set is not any-policy.
*/
if (!state->validPolicyTree || state->initialIsAnyPolicy) {
PKIX_ERROR(PKIX_PRECONDITIONFAILED);
}
PKIX_NULLCHECK_FOUR(currentNode, state, nominees, pShouldBePruned);
PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy
(currentNode, &currentPolicy, plContext),
PKIX_POLICYNODEGETVALIDPOLICYFAILED);
PKIX_NULLCHECK_TWO(state->anyPolicyOID, currentPolicy);
PKIX_EQUALS
(state->anyPolicyOID,
currentPolicy,
&currentPolicyIsAny,
plContext,
PKIX_OBJECTEQUALSFAILED);
PKIX_CHECK(PKIX_PolicyNode_GetParent(currentNode, &parent, plContext),
PKIX_POLICYNODEGETPARENTFAILED);
if (currentPolicyIsAny == PKIX_FALSE) {
/*
* If we are at the top of the tree, or if our
* parent's validPolicy is anyPolicy, we are in
* the valid policy node set.
*/
if (parent) {
PKIX_CHECK(PKIX_PolicyNode_GetValidPolicy
(parent, &parentPolicy, plContext),
PKIX_POLICYNODEGETVALIDPOLICYFAILED);
PKIX_NULLCHECK_ONE(parentPolicy);
PKIX_EQUALS
(state->anyPolicyOID,
parentPolicy,
&parentPolicyIsAny,
plContext,
PKIX_OBJECTEQUALSFAILED);
}
/*
* Section 6.1.5(g)(iii)(2)
* If this node's policy is not in the user-initial-policy-set,
* it is not in the intersection. Prune it.
*/
if (!parent || parentPolicyIsAny) {
PKIX_CHECK(pkix_List_Contains
(state->userInitialPolicySet,
(PKIX_PL_Object *)currentPolicy,
&currentPolicyIsValid,
plContext),
PKIX_LISTCONTAINSFAILED);
if (!currentPolicyIsValid) {
*pShouldBePruned = PKIX_TRUE;
goto cleanup;
}
/*
* If this node's policy is in the user-initial-policy-
* set, it will propagate that policy into the next
* level of the tree. Remove the policy from the list
* of policies that an anyPolicy will spawn.
*/
PKIX_CHECK(pkix_List_Remove
(nominees,
(PKIX_PL_Object *)currentPolicy,
plContext),
PKIX_LISTREMOVEFAILED);
}
}
/* Are we at the bottom of the tree? */
PKIX_CHECK(PKIX_PolicyNode_GetDepth
(currentNode, &depth, plContext),
PKIX_POLICYNODEGETDEPTHFAILED);
if (depth == (state->numCerts)) {
/*
* Section 6.1.5(g)(iii)(3)
* Replace anyPolicy nodes...
*/
if (currentPolicyIsAny == PKIX_TRUE) {
/* replace this node */
PKIX_CHECK(PKIX_List_GetLength
(nominees, &numNominees, plContext),
PKIX_LISTGETLENGTHFAILED);
if (numNominees) {
PKIX_CHECK(PKIX_PolicyNode_GetPolicyQualifiers
(currentNode,
&policyQualifiers,
plContext),
PKIX_POLICYNODEGETPOLICYQUALIFIERSFAILED);
PKIX_CHECK(PKIX_PolicyNode_IsCritical
(currentNode, &priorCriticality, plContext),
PKIX_POLICYNODEISCRITICALFAILED);
}
PKIX_NULLCHECK_ONE(parent);
for (polIx = 0; polIx < numNominees; polIx++) {
PKIX_CHECK(PKIX_List_GetItem
(nominees,
polIx,
(PKIX_PL_Object **)&substPolicy,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(pkix_PolicyChecker_Spawn
(parent,
substPolicy,
policyQualifiers,
NULL,
state,
plContext),
PKIX_POLICYCHECKERSPAWNFAILED);
PKIX_DECREF(substPolicy);
}
/* remove currentNode from parent */
*pShouldBePruned = PKIX_TRUE;
/*
* We can get away with augmenting the parent's List
* of children because we started at the end and went
* toward the beginning. New nodes are added at the end.
*/
}
} else {
/*
* Section 6.1.5(g)(iii)(4)
* Prune any childless nodes above the bottom level
*/
PKIX_CHECK(pkix_PolicyNode_GetChildrenMutable
(currentNode, &children, plContext),
PKIX_POLICYNODEGETCHILDRENMUTABLEFAILED);
/* CurrentNode should have been pruned if childless. */
PKIX_NULLCHECK_ONE(children);
PKIX_CHECK(PKIX_List_GetLength
(children, &numChildren, plContext),
PKIX_LISTGETLENGTHFAILED);
for (childIndex = numChildren; childIndex > 0; childIndex--) {
PKIX_CHECK(PKIX_List_GetItem
(children,
childIndex - 1,
(PKIX_PL_Object **)&child,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection
(child, state, nominees, &shouldBePruned, plContext),
PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED);
if (PKIX_TRUE == shouldBePruned) {
PKIX_CHECK(PKIX_List_DeleteItem
(children, childIndex - 1, plContext),
PKIX_LISTDELETEITEMFAILED);
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
}
PKIX_DECREF(child);
}
PKIX_CHECK(PKIX_List_GetLength
(children, &numChildren, plContext),
PKIX_LISTGETLENGTHFAILED);
if (numChildren == 0) {
*pShouldBePruned = PKIX_TRUE;
}
}
cleanup:
PKIX_DECREF(currentPolicy);
PKIX_DECREF(parentPolicy);
PKIX_DECREF(substPolicy);
PKIX_DECREF(parent);
PKIX_DECREF(child);
PKIX_DECREF(children);
PKIX_DECREF(policyQualifiers);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_PolicyMapProcessing
* DESCRIPTION:
*
* Performs the processing of Policies in the List of CertPolicyMaps pointed
* to by "policyMaps", using and updating the PolicyCheckerState pointed to by
* "state".
*
* This function implements the policyMap processing described in RFC3280
* Section 6.1.4(b)(1), after certificate i has been processed, in preparation
* for certificate i+1. Section references are to that document.
*
* PARAMETERS:
* "policyMaps"
* Address of the List of CertPolicyMaps presented by certificate i.
* Must be non-NULL.
* "certPoliciesIncludeAny"
* Boolean value which is PKIX_TRUE if the current certificate asserts
* anyPolicy, PKIX_FALSE otherwise.
* "qualsOfAny"
* Address of List of qualifiers of the anyPolicy in the current
* certificate. May be empty or NULL.
* "state"
* Address of the current state of the PKIX_PolicyChecker.
* Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds
* Returns a CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyChecker_PolicyMapProcessing(
PKIX_List *policyMaps, /* CertPolicyMaps */
PKIX_Boolean certPoliciesIncludeAny,
PKIX_List *qualsOfAny,
PKIX_PolicyCheckerState *state,
void *plContext)
{
PKIX_UInt32 numPolicies = 0;
PKIX_UInt32 polX = 0;
PKIX_PL_OID *policyOID = NULL;
PKIX_List *newMappedPolicies = NULL; /* OIDs */
PKIX_List *subjectDomainPolicies = NULL; /* OIDs */
PKIX_ENTER
(CERTCHAINCHECKER,
"pkix_PolicyChecker_PolicyMapProcessing");
PKIX_NULLCHECK_THREE
(policyMaps,
state,
state->mappedUserInitialPolicySet);
/*
* For each policy in mappedUserInitialPolicySet, if it is not mapped,
* append it to new policySet; if it is mapped, append its
* subjectDomainPolicies to new policySet. When done, this new
* policySet will replace mappedUserInitialPolicySet.
*/
PKIX_CHECK(PKIX_List_Create
(&newMappedPolicies, plContext),
PKIX_LISTCREATEFAILED);
PKIX_CHECK(PKIX_List_GetLength
(state->mappedUserInitialPolicySet,
&numPolicies,
plContext),
PKIX_LISTGETLENGTHFAILED);
for (polX = 0; polX < numPolicies; polX++) {
PKIX_CHECK(PKIX_List_GetItem
(state->mappedUserInitialPolicySet,
polX,
(PKIX_PL_Object **)&policyOID,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies
(policyMaps,
policyOID,
&subjectDomainPolicies,
plContext),
PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
if (subjectDomainPolicies) {
PKIX_CHECK(pkix_List_AppendUnique
(newMappedPolicies,
subjectDomainPolicies,
plContext),
PKIX_LISTAPPENDUNIQUEFAILED);
PKIX_DECREF(subjectDomainPolicies);
} else {
PKIX_CHECK(PKIX_List_AppendItem
(newMappedPolicies,
(PKIX_PL_Object *)policyOID,
plContext),
PKIX_LISTAPPENDITEMFAILED);
}
PKIX_DECREF(policyOID);
}
/*
* For each policy ID-P remaining in mappedPolicyOIDs, it has not been
* propagated to the bottom of the tree (depth i). If policyMapping
* is greater than zero and this cert contains anyPolicy and the tree
* contains an anyPolicy node at depth i-1, then we must create a node
* with validPolicy ID-P, the policy qualifiers of anyPolicy in
* this certificate, and expectedPolicySet the subjectDomainPolicies
* that ID-P maps to. We also then add those subjectDomainPolicies to
* the list of policies that will be accepted in the next certificate,
* the mappedUserInitialPolicySet.
*/
if ((state->policyMapping > 0) && (certPoliciesIncludeAny) &&
(state->anyPolicyNodeAtBottom) && (state->mappedPolicyOIDs)) {
PKIX_CHECK(PKIX_List_GetLength
(state->mappedPolicyOIDs,
&numPolicies,
plContext),
PKIX_LISTGETLENGTHFAILED);
for (polX = 0; polX < numPolicies; polX++) {
PKIX_CHECK(PKIX_List_GetItem
(state->mappedPolicyOIDs,
polX,
(PKIX_PL_Object **)&policyOID,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(pkix_PolicyChecker_MapGetSubjectDomainPolicies
(policyMaps,
policyOID,
&subjectDomainPolicies,
plContext),
PKIX_POLICYCHECKERMAPGETSUBJECTDOMAINPOLICIESFAILED);
PKIX_CHECK(pkix_PolicyChecker_Spawn
(state->anyPolicyNodeAtBottom,
policyOID,
qualsOfAny,
subjectDomainPolicies,
state,
plContext),
PKIX_POLICYCHECKERSPAWNFAILED);
PKIX_CHECK(pkix_List_AppendUnique
(newMappedPolicies,
subjectDomainPolicies,
plContext),
PKIX_LISTAPPENDUNIQUEFAILED);
PKIX_DECREF(subjectDomainPolicies);
PKIX_DECREF(policyOID);
}
}
PKIX_CHECK(PKIX_List_SetImmutable(newMappedPolicies, plContext),
PKIX_LISTSETIMMUTABLEFAILED);
PKIX_DECREF(state->mappedUserInitialPolicySet);
PKIX_INCREF(newMappedPolicies);
state->mappedUserInitialPolicySet = newMappedPolicies;
cleanup:
PKIX_DECREF(policyOID);
PKIX_DECREF(newMappedPolicies);
PKIX_DECREF(subjectDomainPolicies);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_WrapUpProcessing
* DESCRIPTION:
*
* Performs the wrap-up processing for the Cert pointed to by "cert",
* using and updating the PolicyCheckerState pointed to by "state".
*
* This function implements the wrap-up processing described in RFC3280
* Section 6.1.5, after the final certificate has been processed. Section
* references in the comments are to that document.
*
* PARAMETERS:
* "cert"
* Address of the current (presumably the end entity) certificate.
* Must be non-NULL.
* "state"
* Address of the current state of the PKIX_PolicyChecker.
* Must be non-NULL.
* "plContext"
* Platform-specific context pointer.
* THREAD SAFETY:
* Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
* RETURNS:
* Returns NULL if the function succeeds
* Returns a CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
static PKIX_Error *
pkix_PolicyChecker_WrapUpProcessing(
PKIX_PL_Cert *cert,
PKIX_PolicyCheckerState *state,
void *plContext)
{
PKIX_Int32 explicitPolicySkipCerts = 0;
PKIX_Boolean isSelfIssued = PKIX_FALSE;
PKIX_Boolean shouldBePruned = PKIX_FALSE;
PKIX_List *nominees = NULL; /* OIDs */
#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
PKIX_PL_String *stateString = NULL;
char *stateAscii = NULL;
PKIX_UInt32 length;
#endif
PKIX_ENTER
(CERTCHAINCHECKER,
"pkix_PolicyChecker_WrapUpProcessing");
PKIX_NULLCHECK_THREE(cert, state, state->userInitialPolicySet);
#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
PKIX_CHECK(PKIX_PL_Object_ToString
((PKIX_PL_Object*)state, &stateString, plContext),
PKIX_OBJECTTOSTRINGFAILED);
PKIX_CHECK(PKIX_PL_String_GetEncoded
(stateString,
PKIX_ESCASCII,
(void **)&stateAscii,
&length,
plContext),
PKIX_STRINGGETENCODEDFAILED);
PKIX_DEBUG_ARG("%s\n", stateAscii);
PKIX_FREE(stateAscii);
PKIX_DECREF(stateString);
#endif
/* Section 6.1.5(a) ... */
PKIX_CHECK(pkix_IsCertSelfIssued
(cert, &isSelfIssued, plContext),
PKIX_ISCERTSELFISSUEDFAILED);
if (!isSelfIssued) {
if (state->explicitPolicy > 0) {
state->explicitPolicy--;
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
}
}
/* Section 6.1.5(b) ... */
PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
(cert, &explicitPolicySkipCerts, plContext),
PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
if (explicitPolicySkipCerts == 0) {
state->explicitPolicy = 0;
}
/* Section 6.1.5(g)(i) ... */
if (!(state->validPolicyTree)) {
goto cleanup;
}
/* Section 6.1.5(g)(ii) ... */
if (state->initialIsAnyPolicy) {
goto cleanup;
}
/*
* Section 6.1.5(g)(iii) ...
* Create a list of policies which could be substituted for anyPolicy.
* Start with a (mutable) copy of user-initial-policy-set.
*/
PKIX_CHECK(pkix_PolicyChecker_MakeMutableCopy
(state->userInitialPolicySet, &nominees, plContext),
PKIX_POLICYCHECKERMAKEMUTABLECOPYFAILED);
PKIX_CHECK(pkix_PolicyChecker_CalculateIntersection
(state->validPolicyTree, /* node at top of tree */
state,
nominees,
&shouldBePruned,
plContext),
PKIX_POLICYCHECKERCALCULATEINTERSECTIONFAILED);
if (PKIX_TRUE == shouldBePruned) {
PKIX_DECREF(state->validPolicyTree);
}
if (state->validPolicyTree) {
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state->validPolicyTree, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
}
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
if (state->validPolicyTree) {
PKIX_CHECK(PKIX_PL_Object_ToString
((PKIX_PL_Object*)state, &stateString, plContext),
PKIX_OBJECTTOSTRINGFAILED);
PKIX_CHECK(PKIX_PL_String_GetEncoded
(stateString,
PKIX_ESCASCII,
(void **)&stateAscii,
&length,
plContext),
PKIX_STRINGGETENCODEDFAILED);
PKIX_DEBUG_ARG
("After CalculateIntersection:\n%s\n", stateAscii);
PKIX_FREE(stateAscii);
PKIX_DECREF(stateString);
} else {
PKIX_DEBUG("validPolicyTree is NULL\n");
}
#endif
/* Section 6.1.5(g)(iii)(4) ... */
if (state->validPolicyTree) {
PKIX_CHECK(pkix_PolicyNode_Prune
(state->validPolicyTree,
state->numCerts,
&shouldBePruned,
plContext),
PKIX_POLICYNODEPRUNEFAILED);
if (shouldBePruned) {
PKIX_DECREF(state->validPolicyTree);
}
}
if (state->validPolicyTree) {
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state->validPolicyTree, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
}
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
PKIX_CHECK(PKIX_PL_Object_ToString
((PKIX_PL_Object*)state, &stateString, plContext),
PKIX_OBJECTTOSTRINGFAILED);
PKIX_CHECK(PKIX_PL_String_GetEncoded
(stateString,
PKIX_ESCASCII,
(void **)&stateAscii,
&length,
plContext),
PKIX_STRINGGETENCODEDFAILED);
PKIX_DEBUG_ARG("%s\n", stateAscii);
PKIX_FREE(stateAscii);
PKIX_DECREF(stateString);
#endif
cleanup:
PKIX_DECREF(nominees);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_Check
* (see comments in pkix_checker.h for PKIX_CertChainChecker_CheckCallback)
*
* Labels referring to sections, such as "Section 6.1.3(d)", refer to
* sections of RFC3280, Section 6.1.3 Basic Certificate Processing.
*
* If a non-fatal error occurs, it is unlikely that policy processing can
* continue. But it is still possible that chain validation could succeed if
* policy processing is non-critical. So if this function receives a non-fatal
* error from a lower level routine, it aborts policy processing by setting
* the validPolicyTree to NULL and tries to continue.
*
*/
static PKIX_Error *
pkix_PolicyChecker_Check(
PKIX_CertChainChecker *checker,
PKIX_PL_Cert *cert,
PKIX_List *unresolvedCriticals, /* OIDs */
void **pNBIOContext,
void *plContext)
{
PKIX_UInt32 numPolicies = 0;
PKIX_UInt32 polX = 0;
PKIX_Boolean result = PKIX_FALSE;
PKIX_Int32 inhibitMappingSkipCerts = 0;
PKIX_Int32 explicitPolicySkipCerts = 0;
PKIX_Int32 inhibitAnyPolicySkipCerts = 0;
PKIX_Boolean shouldBePruned = PKIX_FALSE;
PKIX_Boolean isSelfIssued = PKIX_FALSE;
PKIX_Boolean certPoliciesIncludeAny = PKIX_FALSE;
PKIX_Boolean doAnyPolicyProcessing = PKIX_FALSE;
PKIX_PolicyCheckerState *state = NULL;
PKIX_List *certPolicyInfos = NULL; /* CertPolicyInfos */
PKIX_PL_CertPolicyInfo *policy = NULL;
PKIX_PL_OID *policyOID = NULL;
PKIX_List *qualsOfAny = NULL; /* CertPolicyQualifiers */
PKIX_List *policyQualifiers = NULL; /* CertPolicyQualifiers */
PKIX_List *policyMaps = NULL; /* CertPolicyMaps */
PKIX_List *mappedPolicies = NULL; /* OIDs */
PKIX_Error *subroutineErr = NULL;
#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
PKIX_PL_String *stateString = NULL;
char *stateAscii = NULL;
PKIX_PL_String *certString = NULL;
char *certAscii = NULL;
PKIX_UInt32 length;
#endif
PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Check");
PKIX_NULLCHECK_FOUR(checker, cert, unresolvedCriticals, pNBIOContext);
*pNBIOContext = NULL; /* we never block on pending I/O */
PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
(checker, (PKIX_PL_Object **)&state, plContext),
PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);
PKIX_NULLCHECK_TWO(state, state->certPoliciesExtension);
#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
PKIX_CHECK(PKIX_PL_Object_ToString
((PKIX_PL_Object*)state, &stateString, plContext),
PKIX_OBJECTTOSTRINGFAILED);
PKIX_CHECK(PKIX_PL_String_GetEncoded
(stateString,
PKIX_ESCASCII,
(void **)&stateAscii,
&length,
plContext),
PKIX_STRINGGETENCODEDFAILED);
PKIX_DEBUG_ARG("On entry %s\n", stateAscii);
PKIX_FREE(stateAscii);
PKIX_DECREF(stateString);
#endif
/*
* Section 6.1.4(a)
* If this is not the last certificate, and if
* policyMapping extension is present, check that no
* issuerDomainPolicy or subjectDomainPolicy is equal to the
* special policy anyPolicy.
*/
if (state->certsProcessed != (state->numCerts - 1)) {
PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappings
(cert, &policyMaps, plContext),
PKIX_CERTGETPOLICYMAPPINGSFAILED);
}
if (policyMaps) {
PKIX_CHECK(pkix_PolicyChecker_MapContains
(policyMaps, state->anyPolicyOID, &result, plContext),
PKIX_POLICYCHECKERMAPCONTAINSFAILED);
if (result) {
PKIX_ERROR(PKIX_INVALIDPOLICYMAPPINGINCLUDESANYPOLICY);
}
PKIX_CHECK(pkix_PolicyChecker_MapGetMappedPolicies
(policyMaps, &mappedPolicies, plContext),
PKIX_POLICYCHECKERMAPGETMAPPEDPOLICIESFAILED);
PKIX_DECREF(state->mappedPolicyOIDs);
PKIX_INCREF(mappedPolicies);
state->mappedPolicyOIDs = mappedPolicies;
}
/* Section 6.1.3(d) */
if (state->validPolicyTree) {
PKIX_CHECK(PKIX_PL_Cert_GetPolicyInformation
(cert, &certPolicyInfos, plContext),
PKIX_CERTGETPOLICYINFORMATIONFAILED);
if (certPolicyInfos) {
PKIX_CHECK(PKIX_List_GetLength
(certPolicyInfos, &numPolicies, plContext),
PKIX_LISTGETLENGTHFAILED);
}
if (numPolicies > 0) {
PKIX_CHECK(PKIX_PL_Cert_AreCertPoliciesCritical
(cert, &(state->certPoliciesCritical), plContext),
PKIX_CERTARECERTPOLICIESCRITICALFAILED);
/* Section 6.1.3(d)(1) For each policy not equal to anyPolicy */
for (polX = 0; polX < numPolicies; polX++) {
PKIX_CHECK(PKIX_List_GetItem
(certPolicyInfos,
polX,
(PKIX_PL_Object **)&policy,
plContext),
PKIX_LISTGETITEMFAILED);
PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolicyId
(policy, &policyOID, plContext),
PKIX_CERTPOLICYINFOGETPOLICYIDFAILED);
PKIX_CHECK(PKIX_PL_CertPolicyInfo_GetPolQualifiers
(policy, &policyQualifiers, plContext),
PKIX_CERTPOLICYINFOGETPOLQUALIFIERSFAILED);
PKIX_EQUALS
(state->anyPolicyOID,
policyOID,
&result,
plContext,
PKIX_OIDEQUALFAILED);
if (result == PKIX_FALSE) {
/* Section 6.1.3(d)(1)(i) */
subroutineErr = pkix_PolicyChecker_CheckPolicy
(policyOID,
policyQualifiers,
cert,
policyMaps,
state,
plContext);
if (subroutineErr) {
goto subrErrorCleanup;
}
} else {
/*
* No descent (yet) for anyPolicy, but we will need
* the policyQualifiers for anyPolicy in 6.1.3(d)(2)
*/
PKIX_DECREF(qualsOfAny);
PKIX_INCREF(policyQualifiers);
qualsOfAny = policyQualifiers;
certPoliciesIncludeAny = PKIX_TRUE;
}
PKIX_DECREF(policy);
PKIX_DECREF(policyOID);
PKIX_DECREF(policyQualifiers);
}
/* Section 6.1.3(d)(2) */
if (certPoliciesIncludeAny == PKIX_TRUE) {
if (state->inhibitAnyPolicy > 0) {
doAnyPolicyProcessing = PKIX_TRUE;
} else {
/* We haven't yet counted the current cert */
if (((state->certsProcessed) + 1) <
(state->numCerts)) {
PKIX_CHECK(pkix_IsCertSelfIssued
(cert,
&doAnyPolicyProcessing,
plContext),
PKIX_ISCERTSELFISSUEDFAILED);
}
}
if (doAnyPolicyProcessing) {
subroutineErr = pkix_PolicyChecker_CheckAny
(state->validPolicyTree,
qualsOfAny,
policyMaps,
state,
plContext);
if (subroutineErr) {
goto subrErrorCleanup;
}
}
}
/* Section 6.1.3(d)(3) */
if (state->validPolicyTree) {
subroutineErr = pkix_PolicyNode_Prune
(state->validPolicyTree,
state->certsProcessed + 1,
&shouldBePruned,
plContext);
if (subroutineErr) {
goto subrErrorCleanup;
}
if (shouldBePruned) {
PKIX_DECREF(state->validPolicyTree);
PKIX_DECREF(state->anyPolicyNodeAtBottom);
}
}
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
} else {
/* Section 6.1.3(e) */
PKIX_DECREF(state->validPolicyTree);
PKIX_DECREF(state->anyPolicyNodeAtBottom);
PKIX_DECREF(state->newAnyPolicyNode);
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
}
}
/* Section 6.1.3(f) */
if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) {
PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION);
}
/*
* Remove Policy OIDs from list of unresolved critical
* extensions, if present.
*/
PKIX_CHECK(pkix_List_Remove
(unresolvedCriticals,
(PKIX_PL_Object *)state->certPoliciesExtension,
plContext),
PKIX_LISTREMOVEFAILED);
PKIX_CHECK(pkix_List_Remove
(unresolvedCriticals,
(PKIX_PL_Object *)state->policyMappingsExtension,
plContext),
PKIX_LISTREMOVEFAILED);
PKIX_CHECK(pkix_List_Remove
(unresolvedCriticals,
(PKIX_PL_Object *)state->policyConstraintsExtension,
plContext),
PKIX_LISTREMOVEFAILED);
PKIX_CHECK(pkix_List_Remove
(unresolvedCriticals,
(PKIX_PL_Object *)state->inhibitAnyPolicyExtension,
plContext),
PKIX_LISTREMOVEFAILED);
state->certsProcessed++;
/* If this was not the last certificate, do next-cert preparation */
if (state->certsProcessed != state->numCerts) {
if (policyMaps) {
subroutineErr = pkix_PolicyChecker_PolicyMapProcessing
(policyMaps,
certPoliciesIncludeAny,
qualsOfAny,
state,
plContext);
if (subroutineErr) {
goto subrErrorCleanup;
}
}
/* update anyPolicyNodeAtBottom pointer */
PKIX_DECREF(state->anyPolicyNodeAtBottom);
state->anyPolicyNodeAtBottom = state->newAnyPolicyNode;
state->newAnyPolicyNode = NULL;
/* Section 6.1.4(h) */
PKIX_CHECK(pkix_IsCertSelfIssued
(cert, &isSelfIssued, plContext),
PKIX_ISCERTSELFISSUEDFAILED);
if (!isSelfIssued) {
if (state->explicitPolicy > 0) {
state->explicitPolicy--;
}
if (state->policyMapping > 0) {
state->policyMapping--;
}
if (state->inhibitAnyPolicy > 0) {
state->inhibitAnyPolicy--;
}
}
/* Section 6.1.4(i) */
PKIX_CHECK(PKIX_PL_Cert_GetRequireExplicitPolicy
(cert, &explicitPolicySkipCerts, plContext),
PKIX_CERTGETREQUIREEXPLICITPOLICYFAILED);
if (explicitPolicySkipCerts != -1) {
if (((PKIX_UInt32)explicitPolicySkipCerts) <
(state->explicitPolicy)) {
state->explicitPolicy =
((PKIX_UInt32) explicitPolicySkipCerts);
}
}
PKIX_CHECK(PKIX_PL_Cert_GetPolicyMappingInhibited
(cert, &inhibitMappingSkipCerts, plContext),
PKIX_CERTGETPOLICYMAPPINGINHIBITEDFAILED);
if (inhibitMappingSkipCerts != -1) {
if (((PKIX_UInt32)inhibitMappingSkipCerts) <
(state->policyMapping)) {
state->policyMapping =
((PKIX_UInt32)inhibitMappingSkipCerts);
}
}
PKIX_CHECK(PKIX_PL_Cert_GetInhibitAnyPolicy
(cert, &inhibitAnyPolicySkipCerts, plContext),
PKIX_CERTGETINHIBITANYPOLICYFAILED);
if (inhibitAnyPolicySkipCerts != -1) {
if (((PKIX_UInt32)inhibitAnyPolicySkipCerts) <
(state->inhibitAnyPolicy)) {
state->inhibitAnyPolicy =
((PKIX_UInt32)inhibitAnyPolicySkipCerts);
}
}
PKIX_CHECK(PKIX_PL_Object_InvalidateCache
((PKIX_PL_Object *)state, plContext),
PKIX_OBJECTINVALIDATECACHEFAILED);
} else { /* If this was the last certificate, do wrap-up processing */
/* Section 6.1.5 */
subroutineErr = pkix_PolicyChecker_WrapUpProcessing
(cert, state, plContext);
if (subroutineErr) {
goto subrErrorCleanup;
}
if ((0 == state->explicitPolicy) && (!state->validPolicyTree)) {
PKIX_ERROR(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION);
}
PKIX_DECREF(state->anyPolicyNodeAtBottom);
PKIX_DECREF(state->newAnyPolicyNode);
}
if (subroutineErr) {
subrErrorCleanup:
/* We had an error. Was it a fatal error? */
pkixErrorClass = subroutineErr->errClass;
if (pkixErrorClass == PKIX_FATAL_ERROR) {
pkixErrorResult = subroutineErr;
subroutineErr = NULL;
goto cleanup;
}
/*
* Abort policy processing, and then determine whether
* we can continue without policy processing.
*/
PKIX_DECREF(state->validPolicyTree);
PKIX_DECREF(state->anyPolicyNodeAtBottom);
PKIX_DECREF(state->newAnyPolicyNode);
if (state->explicitPolicy == 0) {
PKIX_ERROR
(PKIX_CERTCHAINFAILSCERTIFICATEPOLICYVALIDATION);
}
}
/* Checking is complete. Save state for the next certificate. */
PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
(checker, (PKIX_PL_Object *)state, plContext),
PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
cleanup:
#if PKIX_CERTPOLICYCHECKERSTATEDEBUG
if (cert) {
PKIX_CHECK(PKIX_PL_Object_ToString
((PKIX_PL_Object*)cert, &certString, plContext),
PKIX_OBJECTTOSTRINGFAILED);
PKIX_CHECK(PKIX_PL_String_GetEncoded
(certString,
PKIX_ESCASCII,
(void **)&certAscii,
&length,
plContext),
PKIX_STRINGGETENCODEDFAILED);
PKIX_DEBUG_ARG("Cert was %s\n", certAscii);
PKIX_FREE(certAscii);
PKIX_DECREF(certString);
}
if (state) {
PKIX_CHECK(PKIX_PL_Object_ToString
((PKIX_PL_Object*)state, &stateString, plContext),
PKIX_OBJECTTOSTRINGFAILED);
PKIX_CHECK(PKIX_PL_String_GetEncoded
(stateString,
PKIX_ESCASCII,
(void **)&stateAscii,
&length,
plContext),
PKIX_STRINGGETENCODEDFAILED);
PKIX_DEBUG_ARG("On exit %s\n", stateAscii);
PKIX_FREE(stateAscii);
PKIX_DECREF(stateString);
}
#endif
PKIX_DECREF(state);
PKIX_DECREF(certPolicyInfos);
PKIX_DECREF(policy);
PKIX_DECREF(qualsOfAny);
PKIX_DECREF(policyQualifiers);
PKIX_DECREF(policyOID);
PKIX_DECREF(subroutineErr);
PKIX_DECREF(policyMaps);
PKIX_DECREF(mappedPolicies);
PKIX_RETURN(CERTCHAINCHECKER);
}
/*
* FUNCTION: pkix_PolicyChecker_Initialize
* DESCRIPTION:
*
* Creates and initializes a PolicyChecker, using the List pointed to
* by "initialPolicies" for the user-initial-policy-set, the Boolean value
* of "policyQualifiersRejected" for the policyQualifiersRejected parameter,
* the Boolean value of "initialPolicyMappingInhibit" for the
* inhibitPolicyMappings parameter, the Boolean value of
* "initialExplicitPolicy" for the initialExplicitPolicy parameter, the
* Boolean value of "initialAnyPolicyInhibit" for the inhibitAnyPolicy
* parameter, and the UInt32 value of "numCerts" as the number of
* certificates in the chain; and stores the Checker at "pChecker".
*
* PARAMETERS:
* "initialPolicies"
* Address of List of OIDs comprising the user-initial-policy-set; the List
* may be empty or NULL
* "policyQualifiersRejected"
* Boolean value of the policyQualifiersRejected parameter
* "initialPolicyMappingInhibit"
* Boolean value of the inhibitPolicyMappings parameter
* "initialExplicitPolicy"
* Boolean value of the initialExplicitPolicy parameter
* "initialAnyPolicyInhibit"
* Boolean value of the inhibitAnyPolicy parameter
* "numCerts"
* Number of certificates in the chain to be validated
* "pChecker"
* Address to store the created PolicyChecker. 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 CertChainChecker Error if the functions fails in a non-fatal way
* Returns a Fatal Error if the function fails in an unrecoverable way
*/
PKIX_Error *
pkix_PolicyChecker_Initialize(
PKIX_List *initialPolicies,
PKIX_Boolean policyQualifiersRejected,
PKIX_Boolean initialPolicyMappingInhibit,
PKIX_Boolean initialExplicitPolicy,
PKIX_Boolean initialAnyPolicyInhibit,
PKIX_UInt32 numCerts,
PKIX_CertChainChecker **pChecker,
void *plContext)
{
PKIX_PolicyCheckerState *polCheckerState = NULL;
PKIX_List *policyExtensions = NULL; /* OIDs */
PKIX_ENTER(CERTCHAINCHECKER, "pkix_PolicyChecker_Initialize");
PKIX_NULLCHECK_ONE(pChecker);
PKIX_CHECK(pkix_PolicyCheckerState_Create
(initialPolicies,
policyQualifiersRejected,
initialPolicyMappingInhibit,
initialExplicitPolicy,
initialAnyPolicyInhibit,
numCerts,
&polCheckerState,
plContext),
PKIX_POLICYCHECKERSTATECREATEFAILED);
/* Create the list of extensions that we handle */
PKIX_CHECK(pkix_PolicyChecker_MakeSingleton
((PKIX_PL_Object *)(polCheckerState->certPoliciesExtension),
PKIX_TRUE,
&policyExtensions,
plContext),
PKIX_POLICYCHECKERMAKESINGLETONFAILED);
PKIX_CHECK(PKIX_CertChainChecker_Create
(pkix_PolicyChecker_Check,
PKIX_FALSE, /* forwardCheckingSupported */
PKIX_FALSE,
policyExtensions,
(PKIX_PL_Object *)polCheckerState,
pChecker,
plContext),
PKIX_CERTCHAINCHECKERCREATEFAILED);
cleanup:
PKIX_DECREF(polCheckerState);
PKIX_DECREF(policyExtensions);
PKIX_RETURN(CERTCHAINCHECKER);
}