diff options
Diffstat (limited to '')
-rw-r--r-- | security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c new file mode 100644 index 0000000000..d6f5b6bcc8 --- /dev/null +++ b/security/nss/lib/libpkix/pkix/checker/pkix_crlchecker.c @@ -0,0 +1,438 @@ +/* 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_defaultcrlchecker.c + * + * Functions for default CRL Checkers + * + */ +#include "pkix.h" +#include "pkix_crlchecker.h" +#include "pkix_tools.h" + +/* --Private-CRLChecker-Data-and-Types------------------------------- */ + +typedef struct pkix_CrlCheckerStruct { + /* RevocationMethod is the super class of CrlChecker. */ + pkix_RevocationMethod method; + PKIX_List *certStores; /* list of CertStore */ + PKIX_PL_VerifyCallback crlVerifyFn; +} pkix_CrlChecker; + + +/* --Private-CRLChecker-Functions----------------------------------- */ + +/* + * FUNCTION: pkix_CrlCheckerstate_Destroy + * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) + */ +static PKIX_Error * +pkix_CrlChecker_Destroy( + PKIX_PL_Object *object, + void *plContext) +{ + pkix_CrlChecker *state = NULL; + + PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Destroy"); + PKIX_NULLCHECK_ONE(object); + + /* Check that this object is a default CRL checker state */ + PKIX_CHECK( + pkix_CheckType(object, PKIX_CRLCHECKER_TYPE, plContext), + PKIX_OBJECTNOTCRLCHECKER); + + state = (pkix_CrlChecker *)object; + + PKIX_DECREF(state->certStores); + +cleanup: + + PKIX_RETURN(CRLCHECKER); +} + +/* + * FUNCTION: pkix_CrlChecker_RegisterSelf + * + * DESCRIPTION: + * Registers PKIX_CRLCHECKER_TYPE and its related functions + * with systemClasses[] + * + * THREAD SAFETY: + * Not Thread Safe (see Thread Safety Definitions in Programmer's Guide) + * + * 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_CrlChecker_RegisterSelf(void *plContext) +{ + extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; + pkix_ClassTable_Entry* entry = &systemClasses[PKIX_CRLCHECKER_TYPE]; + + PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_RegisterSelf"); + + entry->description = "CRLChecker"; + entry->typeObjectSize = sizeof(pkix_CrlChecker); + entry->destructor = pkix_CrlChecker_Destroy; + + PKIX_RETURN(CRLCHECKER); +} + +/* + * FUNCTION: pkix_CrlChecker_Create + * + * DESCRIPTION: + * Allocate and initialize CRLChecker state data. + * + * PARAMETERS + * "certStores" + * Address of CertStore List to be stored in state. Must be non-NULL. + * "testDate" + * Address of PKIX_PL_Date to be checked. May be NULL. + * "trustedPubKey" + * Trusted Anchor Public Key for verifying first Cert in the chain. + * Must be non-NULL. + * "certsRemaining" + * Number of certificates remaining in the chain. + * "nistCRLPolicyEnabled" + * If enabled, enforce nist crl policy. + * "pChecker" + * Address of CRLChecker 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 DefaultCrlChecker Error if the function fails in a + * non-fatal way. + * Returns a Fatal Error + */ +PKIX_Error * +pkix_CrlChecker_Create(PKIX_RevocationMethodType methodType, + PKIX_UInt32 flags, + PKIX_UInt32 priority, + pkix_LocalRevocationCheckFn localRevChecker, + pkix_ExternalRevocationCheckFn externalRevChecker, + PKIX_List *certStores, + PKIX_PL_VerifyCallback crlVerifyFn, + pkix_RevocationMethod **pChecker, + void *plContext) +{ + pkix_CrlChecker *crlChecker = NULL; + + PKIX_ENTER(CRLCHECKER, "pkix_CrlChecker_Create"); + PKIX_NULLCHECK_TWO(certStores, pChecker); + + PKIX_CHECK(PKIX_PL_Object_Alloc + (PKIX_CRLCHECKER_TYPE, + sizeof (pkix_CrlChecker), + (PKIX_PL_Object **)&crlChecker, + plContext), + PKIX_COULDNOTCREATECRLCHECKEROBJECT); + + pkixErrorResult = pkix_RevocationMethod_Init( + (pkix_RevocationMethod*)crlChecker, methodType, flags, priority, + localRevChecker, externalRevChecker, plContext); + if (pkixErrorResult) { + goto cleanup; + } + + /* Initialize fields */ + PKIX_INCREF(certStores); + crlChecker->certStores = certStores; + + crlChecker->crlVerifyFn = crlVerifyFn; + *pChecker = (pkix_RevocationMethod*)crlChecker; + crlChecker = NULL; + +cleanup: + PKIX_DECREF(crlChecker); + + PKIX_RETURN(CRLCHECKER); +} + +/* --Private-CRLChecker-Functions------------------------------------ */ + +/* + * FUNCTION: pkix_CrlChecker_CheckLocal + * + * DESCRIPTION: + * Check if the Cert has been revoked based the CRLs data. This function + * maintains the checker state to be current. + * + * PARAMETERS + * "checker" + * Address of CertChainChecker which has the state data. + * Must be non-NULL. + * "cert" + * Address of Certificate that is to be validated. Must be non-NULL. + * "unreslvdCrtExts" + * A List OIDs. Not **yet** used in this checker function. + * "plContext" + * Platform-specific context pointer. + * + * THREAD SAFETY: + * Not Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertChainChecker Error if the function fails in a non-fatal way. + * Returns a Fatal Error + */ +PKIX_Error * +pkix_CrlChecker_CheckLocal( + PKIX_PL_Cert *cert, + PKIX_PL_Cert *issuer, + PKIX_PL_Date *date, + pkix_RevocationMethod *checkerObject, + PKIX_ProcessingParams *procParams, + PKIX_UInt32 methodFlags, + PKIX_Boolean chainVerificationState, + PKIX_RevocationStatus *pRevStatus, + CERTCRLEntryReasonCode *pReasonCode, + void *plContext) +{ + PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn; + PKIX_CertStore *certStore = NULL; + pkix_CrlChecker *state = NULL; + PKIX_UInt32 crlStoreIndex = 0; + PKIX_UInt32 numCrlStores = 0; + PKIX_Boolean storeIsLocal = PKIX_FALSE; + PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; + + PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckLocal"); + PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, checkerObject); + + state = (pkix_CrlChecker*)checkerObject; + + PKIX_CHECK( + PKIX_List_GetLength(state->certStores, &numCrlStores, plContext), + PKIX_LISTGETLENGTHFAILED); + + for (;crlStoreIndex < numCrlStores;crlStoreIndex++) { + PKIX_CHECK( + PKIX_List_GetItem(state->certStores, crlStoreIndex, + (PKIX_PL_Object **)&certStore, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK( + PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal, + plContext), + PKIX_CERTSTOREGETLOCALFLAGFAILED); + if (storeIsLocal) { + PKIX_CHECK( + PKIX_CertStore_GetCrlCheckerFn(certStore, + &storeCheckRevocationFn, + plContext), + PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); + + if (storeCheckRevocationFn) { + PKIX_CHECK( + (*storeCheckRevocationFn)(certStore, cert, issuer, + /* delay sig check if building + * a chain by not specifying the time*/ + chainVerificationState ? date : NULL, + /* crl downloading is not done. */ + PKIX_FALSE, + pReasonCode, &revStatus, plContext), + PKIX_CERTSTORECRLCHECKFAILED); + if (revStatus == PKIX_RevStatus_Revoked) { + break; + } + } + } + PKIX_DECREF(certStore); + } /* while */ + +cleanup: + *pRevStatus = revStatus; + PKIX_DECREF(certStore); + + PKIX_RETURN(CERTCHAINCHECKER); +} + +/* + * FUNCTION: pkix_CrlChecker_CheckRemote + * + * DESCRIPTION: + * Check if the Cert has been revoked based the CRLs data. This function + * maintains the checker state to be current. + * + * PARAMETERS + * "checker" + * Address of CertChainChecker which has the state data. + * Must be non-NULL. + * "cert" + * Address of Certificate that is to be validated. Must be non-NULL. + * "unreslvdCrtExts" + * A List OIDs. Not **yet** used in this checker function. + * "plContext" + * Platform-specific context pointer. + * + * THREAD SAFETY: + * Not Thread Safe + * (see Thread Safety Definitions in Programmer's Guide) + * + * RETURNS: + * Returns NULL if the function succeeds. + * Returns a CertChainChecker Error if the function fails in a non-fatal way. + * Returns a Fatal Error + */ +PKIX_Error * +pkix_CrlChecker_CheckExternal( + PKIX_PL_Cert *cert, + PKIX_PL_Cert *issuer, + PKIX_PL_Date *date, + pkix_RevocationMethod *checkerObject, + PKIX_ProcessingParams *procParams, + PKIX_UInt32 methodFlags, + PKIX_RevocationStatus *pRevStatus, + CERTCRLEntryReasonCode *pReasonCode, + void **pNBIOContext, + void *plContext) +{ + PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn = NULL; + PKIX_CertStore_ImportCrlCallback storeImportCrlFn = NULL; + PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; + PKIX_CertStore *certStore = NULL; + PKIX_CertStore *localStore = NULL; + PKIX_CRLSelector *crlSelector = NULL; + PKIX_PL_X500Name *issuerName = NULL; + pkix_CrlChecker *state = NULL; + PKIX_UInt32 crlStoreIndex = 0; + PKIX_UInt32 numCrlStores = 0; + PKIX_Boolean storeIsLocal = PKIX_FALSE; + PKIX_List *crlList = NULL; + PKIX_List *dpList = NULL; + void *nbioContext = NULL; + + PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckExternal"); + PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, pNBIOContext); + + nbioContext = *pNBIOContext; + *pNBIOContext = NULL; /* prepare for Error exit */ + + state = (pkix_CrlChecker*)checkerObject; + + PKIX_CHECK( + PKIX_List_GetLength(state->certStores, &numCrlStores, plContext), + PKIX_LISTGETLENGTHFAILED); + + /* Find a cert store that is capable of storing crls */ + for (;crlStoreIndex < numCrlStores;crlStoreIndex++) { + PKIX_CHECK( + PKIX_List_GetItem(state->certStores, crlStoreIndex, + (PKIX_PL_Object **)&certStore, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK( + PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal, + plContext), + PKIX_CERTSTOREGETLOCALFLAGFAILED); + if (storeIsLocal) { + PKIX_CHECK( + PKIX_CertStore_GetImportCrlCallback(certStore, + &storeImportCrlFn, + plContext), + PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); + + PKIX_CHECK( + PKIX_CertStore_GetCrlCheckerFn(certStore, + &storeCheckRevocationFn, + plContext), + PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); + + if (storeImportCrlFn && storeCheckRevocationFn) { + localStore = certStore; + certStore = NULL; + break; + } + } + PKIX_DECREF(certStore); + } /* while */ + + /* Report unknown status if we can not check crl in one of the + * local stores. */ + if (!localStore) { + PKIX_ERROR_FATAL(PKIX_CRLCHECKERNOLOCALCERTSTOREFOUND); + } + PKIX_CHECK( + PKIX_PL_Cert_VerifyKeyUsage(issuer, PKIX_CRL_SIGN, plContext), + PKIX_CERTCHECKKEYUSAGEFAILED); + PKIX_CHECK( + PKIX_PL_Cert_GetCrlDp(cert, &dpList, plContext), + PKIX_CERTGETCRLDPFAILED); + if (!(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) && + (!dpList || !dpList->length)) { + goto cleanup; + } + PKIX_CHECK( + PKIX_PL_Cert_GetIssuer(cert, &issuerName, plContext), + PKIX_CERTGETISSUERFAILED); + PKIX_CHECK( + PKIX_CRLSelector_Create(issuer, dpList, date, &crlSelector, plContext), + PKIX_CRLCHECKERSETSELECTORFAILED); + /* Fetch crl and store in a local cert store */ + for (crlStoreIndex = 0;crlStoreIndex < numCrlStores;crlStoreIndex++) { + PKIX_CertStore_CRLCallback getCrlsFn; + + PKIX_CHECK( + PKIX_List_GetItem(state->certStores, crlStoreIndex, + (PKIX_PL_Object **)&certStore, + plContext), + PKIX_LISTGETITEMFAILED); + + PKIX_CHECK( + PKIX_CertStore_GetCRLCallback(certStore, &getCrlsFn, + plContext), + PKIX_CERTSTOREGETCRLCALLBACKFAILED); + + PKIX_CHECK( + (*getCrlsFn)(certStore, crlSelector, &nbioContext, + &crlList, plContext), + PKIX_GETCRLSFAILED); + + PKIX_CHECK( + (*storeImportCrlFn)(localStore, issuerName, crlList, plContext), + PKIX_CERTSTOREFAILTOIMPORTCRLLIST); + + PKIX_CHECK( + (*storeCheckRevocationFn)(certStore, cert, issuer, date, + /* done with crl downloading */ + PKIX_TRUE, + pReasonCode, &revStatus, plContext), + PKIX_CERTSTORECRLCHECKFAILED); + if (revStatus != PKIX_RevStatus_NoInfo) { + break; + } + PKIX_DECREF(crlList); + PKIX_DECREF(certStore); + } /* while */ + +cleanup: + /* Update return flags */ + if (revStatus == PKIX_RevStatus_NoInfo && + ((dpList && dpList->length > 0) || + (methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE)) && + methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) { + revStatus = PKIX_RevStatus_Revoked; + } + *pRevStatus = revStatus; + + PKIX_DECREF(dpList); + PKIX_DECREF(crlList); + PKIX_DECREF(certStore); + PKIX_DECREF(issuerName); + PKIX_DECREF(localStore); + PKIX_DECREF(crlSelector); + + PKIX_RETURN(CERTCHAINCHECKER); +} |