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