andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: /* andre@0: * pkix_nameconstraintschecker.c andre@0: * andre@0: * Functions for Name Constraints Checkers andre@0: * andre@0: */ andre@0: andre@0: #include "pkix_nameconstraintschecker.h" andre@0: andre@0: /* --Private-NameConstraintsCheckerState-Functions---------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: pkix_NameConstraintsCheckerstate_Destroy andre@0: * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_NameConstraintsCheckerState_Destroy( andre@0: PKIX_PL_Object *object, andre@0: void *plContext) andre@0: { andre@0: pkix_NameConstraintsCheckerState *state = NULL; andre@0: andre@0: PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE, andre@0: "pkix_NameConstraintsCheckerState_Destroy"); andre@0: PKIX_NULLCHECK_ONE(object); andre@0: andre@0: /* Check that object type */ andre@0: PKIX_CHECK(pkix_CheckType andre@0: (object, PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE, plContext), andre@0: PKIX_OBJECTNOTNAMECONSTRAINTSCHECKERSTATE); andre@0: andre@0: state = (pkix_NameConstraintsCheckerState *)object; andre@0: andre@0: PKIX_DECREF(state->nameConstraints); andre@0: PKIX_DECREF(state->nameConstraintsOID); andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_NameConstraintsCheckerState_RegisterSelf andre@0: * andre@0: * DESCRIPTION: andre@0: * Registers PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE and its related andre@0: * functions with systemClasses[] andre@0: * andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe - for performance and complexity reasons andre@0: * andre@0: * Since this function is only called by PKIX_PL_Initialize, which should andre@0: * only be called once, it is acceptable that this function is not andre@0: * thread-safe. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_NameConstraintsCheckerState_RegisterSelf(void *plContext) andre@0: { andre@0: extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; andre@0: pkix_ClassTable_Entry entry; andre@0: andre@0: PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE, andre@0: "pkix_NameConstraintsCheckerState_RegisterSelf"); andre@0: andre@0: entry.description = "NameConstraintsCheckerState"; andre@0: entry.objCounter = 0; andre@0: entry.typeObjectSize = sizeof(pkix_NameConstraintsCheckerState); andre@0: entry.destructor = pkix_NameConstraintsCheckerState_Destroy; andre@0: entry.equalsFunction = NULL; andre@0: entry.hashcodeFunction = NULL; andre@0: entry.toStringFunction = NULL; andre@0: entry.comparator = NULL; andre@0: entry.duplicateFunction = NULL; andre@0: andre@0: systemClasses[PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE] = entry; andre@0: andre@0: PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_NameConstraintsCheckerState_Create andre@0: * andre@0: * DESCRIPTION: andre@0: * Allocate and initialize NameConstraintsChecker state data. andre@0: * andre@0: * PARAMETERS andre@0: * "nameConstraints" andre@0: * Address of NameConstraints to be stored in state. May be NULL. andre@0: * "numCerts" andre@0: * Number of certificates in the validation chain. This data is used andre@0: * to identify end-entity. andre@0: * "pCheckerState" andre@0: * Address of NameConstraintsCheckerState that is returned. Must be andre@0: * non-NULL. andre@0: * "plContext" - Platform-specific context pointer. andre@0: * andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a CERTNAMECONSTRAINTSCHECKERSTATE Error if the function fails in andre@0: * a non-fatal way. andre@0: * Returns a Fatal Error andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_NameConstraintsCheckerState_Create( andre@0: PKIX_PL_CertNameConstraints *nameConstraints, andre@0: PKIX_UInt32 numCerts, andre@0: pkix_NameConstraintsCheckerState **pCheckerState, andre@0: void *plContext) andre@0: { andre@0: pkix_NameConstraintsCheckerState *state = NULL; andre@0: andre@0: PKIX_ENTER(CERTNAMECONSTRAINTSCHECKERSTATE, andre@0: "pkix_NameConstraintsCheckerState_Create"); andre@0: PKIX_NULLCHECK_ONE(pCheckerState); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_CERTNAMECONSTRAINTSCHECKERSTATE_TYPE, andre@0: sizeof (pkix_NameConstraintsCheckerState), andre@0: (PKIX_PL_Object **)&state, andre@0: plContext), andre@0: PKIX_COULDNOTCREATENAMECONSTRAINTSCHECKERSTATEOBJECT); andre@0: andre@0: /* Initialize fields */ andre@0: andre@0: PKIX_CHECK(PKIX_PL_OID_Create andre@0: (PKIX_NAMECONSTRAINTS_OID, andre@0: &state->nameConstraintsOID, andre@0: plContext), andre@0: PKIX_OIDCREATEFAILED); andre@0: andre@0: PKIX_INCREF(nameConstraints); andre@0: andre@0: state->nameConstraints = nameConstraints; andre@0: state->certsRemaining = numCerts; andre@0: andre@0: *pCheckerState = state; andre@0: state = NULL; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(state); andre@0: andre@0: PKIX_RETURN(CERTNAMECONSTRAINTSCHECKERSTATE); andre@0: } andre@0: andre@0: /* --Private-NameConstraintsChecker-Functions------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: pkix_NameConstraintsChecker_Check andre@0: * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_NameConstraintsChecker_Check( andre@0: PKIX_CertChainChecker *checker, andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_List *unresolvedCriticalExtensions, andre@0: void **pNBIOContext, andre@0: void *plContext) andre@0: { andre@0: pkix_NameConstraintsCheckerState *state = NULL; andre@0: PKIX_PL_CertNameConstraints *nameConstraints = NULL; andre@0: PKIX_PL_CertNameConstraints *mergedNameConstraints = NULL; andre@0: PKIX_Boolean selfIssued = PKIX_FALSE; andre@0: PKIX_Boolean lastCert = PKIX_FALSE; andre@0: andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Check"); andre@0: PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); andre@0: andre@0: *pNBIOContext = NULL; /* we never block on pending I/O */ andre@0: andre@0: PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState andre@0: (checker, (PKIX_PL_Object **)&state, plContext), andre@0: PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); andre@0: andre@0: state->certsRemaining--; andre@0: lastCert = state->certsRemaining == 0; andre@0: andre@0: /* Get status of self issued */ andre@0: PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext), andre@0: PKIX_ISCERTSELFISSUEDFAILED); andre@0: andre@0: /* Check on non self-issued and if so only for last cert */ andre@0: if (selfIssued == PKIX_FALSE || andre@0: (selfIssued == PKIX_TRUE && lastCert)) { andre@0: PKIX_CHECK(PKIX_PL_Cert_CheckNameConstraints andre@0: (cert, state->nameConstraints, lastCert, andre@0: plContext), andre@0: PKIX_CERTCHECKNAMECONSTRAINTSFAILED); andre@0: } andre@0: andre@0: if (!lastCert) { andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints andre@0: (cert, &nameConstraints, plContext), andre@0: PKIX_CERTGETNAMECONSTRAINTSFAILED); andre@0: andre@0: /* Merge with previous name constraints kept in state */ andre@0: andre@0: if (nameConstraints != NULL) { andre@0: andre@0: if (state->nameConstraints == NULL) { andre@0: andre@0: state->nameConstraints = nameConstraints; andre@0: andre@0: } else { andre@0: andre@0: PKIX_CHECK(PKIX_PL_Cert_MergeNameConstraints andre@0: (nameConstraints, andre@0: state->nameConstraints, andre@0: &mergedNameConstraints, andre@0: plContext), andre@0: PKIX_CERTMERGENAMECONSTRAINTSFAILED); andre@0: andre@0: PKIX_DECREF(nameConstraints); andre@0: PKIX_DECREF(state->nameConstraints); andre@0: andre@0: state->nameConstraints = mergedNameConstraints; andre@0: } andre@0: andre@0: /* Remove Name Constraints Extension OID from list */ andre@0: if (unresolvedCriticalExtensions != NULL) { andre@0: PKIX_CHECK(pkix_List_Remove andre@0: (unresolvedCriticalExtensions, andre@0: (PKIX_PL_Object *)state->nameConstraintsOID, andre@0: plContext), andre@0: PKIX_LISTREMOVEFAILED); andre@0: } andre@0: } andre@0: } andre@0: andre@0: PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState andre@0: (checker, (PKIX_PL_Object *)state, plContext), andre@0: PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(state); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_NameConstraintsChecker_Initialize andre@0: * andre@0: * DESCRIPTION: andre@0: * Create a CertChainChecker with a NameConstraintsCheckerState. The andre@0: * NameConstraintsCheckerState is created with "trustedNC" and "numCerts" andre@0: * as its initial state. The CertChainChecker for the NameConstraints is andre@0: * returned at address of "pChecker". andre@0: * andre@0: * PARAMETERS andre@0: * "trustedNC" andre@0: * The NameConstraints from trusted anchor Cert is stored at "trustedNC" andre@0: * for initialization. May be NULL. andre@0: * "numCerts" andre@0: * Number of certificates in the validation chain. This data is used andre@0: * to identify end-entity. andre@0: * "pChecker" andre@0: * Address of CertChainChecker to bo created and returned. andre@0: * Must be non-NULL. andre@0: * "plContext" - Platform-specific context pointer. andre@0: * andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns a CERTCHAINCHECKER Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error andre@0: */ andre@0: PKIX_Error * andre@0: pkix_NameConstraintsChecker_Initialize( andre@0: PKIX_PL_CertNameConstraints *trustedNC, andre@0: PKIX_UInt32 numCerts, andre@0: PKIX_CertChainChecker **pChecker, andre@0: void *plContext) andre@0: { andre@0: pkix_NameConstraintsCheckerState *state = NULL; andre@0: andre@0: PKIX_ENTER(CERTCHAINCHECKER, "pkix_NameConstraintsChecker_Initialize"); andre@0: PKIX_NULLCHECK_ONE(pChecker); andre@0: andre@0: PKIX_CHECK(pkix_NameConstraintsCheckerState_Create andre@0: (trustedNC, numCerts, &state, plContext), andre@0: PKIX_NAMECONSTRAINTSCHECKERSTATECREATEFAILED); andre@0: andre@0: PKIX_CHECK(PKIX_CertChainChecker_Create andre@0: (pkix_NameConstraintsChecker_Check, andre@0: PKIX_FALSE, andre@0: PKIX_FALSE, andre@0: NULL, andre@0: (PKIX_PL_Object *) state, andre@0: pChecker, andre@0: plContext), andre@0: PKIX_CERTCHAINCHECKERCREATEFAILED); andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_DECREF(state); andre@0: andre@0: PKIX_RETURN(CERTCHAINCHECKER); andre@0: }