mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 19:50:12 +01:00
44b7f056d9
bug1001332, 56b691c003ad, bug1086145, bug1054069, bug1155922, bug991783, bug1125025, bug1162521, bug1162644, bug1132941, bug1164364, bug1166205, bug1166163, bug1166515, bug1138554, bug1167046, bug1167043, bug1169451, bug1172128, bug1170322, bug102794, bug1128184, bug557830, bug1174648, bug1180244, bug1177784, bug1173413, bug1169174, bug1084669, bug951455, bug1183395, bug1177430, bug1183827, bug1160139, bug1154106, bug1142209, bug1185033, bug1193467, bug1182667(with sha512 changes backed out, which breaks VC6 compilation), bug1158489, bug337796
439 lines
14 KiB
C
439 lines
14 KiB
C
/* 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);
|
|
}
|