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