/* * 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, PKIX_UInt32 *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 reasonCode = 0; 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, &reasonCode, &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); }
/* * FUNCTION: pkix_DefaultCRLChecker_Check * * 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. * "unresolvedCriticalExtensions" * 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 */ static PKIX_Error * pkix_DefaultCRLChecker_Check( PKIX_CertChainChecker *checker, PKIX_PL_Cert *cert, PKIX_List *unresolvedCriticalExtensions, void **pNBIOContext, void *plContext) { pkix_DefaultCRLCheckerState *state = NULL; PKIX_PL_PublicKey *publicKey = NULL; PKIX_PL_PublicKey *newPublicKey = NULL; PKIX_Error *checkKeyUsageFail = NULL; PKIX_Boolean selfIssued = PKIX_FALSE; void *nbioContext = NULL; PKIX_ENTER(CERTCHAINCHECKER, "pkix_DefaultCRLChecker_Check"); PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); nbioContext = *pNBIOContext; *pNBIOContext = NULL; /* prepare for Error exit */ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState (checker, (PKIX_PL_Object **)&state, plContext), PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey (cert, &publicKey, plContext), PKIX_CERTGETSUBJECTPUBLICKEYFAILED); /* * If we already have a selector, we were in the middle of checking * when a certStore returned with non-blocking I/O pendning. */ if ((state->crlSelector) == NULL) { state->certsRemaining--; PKIX_NULLCHECK_ONE(state->prevPublicKey); if (state->prevCertCrlSign == PKIX_FALSE) { PKIX_ERROR (PKIX_KEYUSAGEKEYCRLSIGNBITNOTON); } /* Set up CRLSelector */ PKIX_CHECK(pkix_DefaultCRLChecker_Check_SetSelector (cert, state, plContext), PKIX_DEFAULTCRLCHECKERCHECKSETSELECTORFAILED); } PKIX_CHECK(pkix_DefaultCRLChecker_Check_Helper (checker, cert, state->prevPublicKey, state, unresolvedCriticalExtensions, PKIX_FALSE, &nbioContext, plContext), PKIX_DEFAULTCRLCHECKERCHECKHELPERFAILED); if (nbioContext != NULL) { *pNBIOContext = nbioContext; goto cleanup; } PKIX_DECREF(state->crlSelector); /* * Some NIST test case in 4.5.* use different publicKeys for * Cert and its CRL on the chain. Self-issued Certs are used * to speciy multiple keys for those cases. That is why we apply * the following algorithm: * * Check if Cert is self-issued. If so, the public key of the Cert * that issues this Cert (old key) can be used together with this * current key (new key) for key verification. If there are multiple * self-issued certs, keys of those Certs (old keys) can also be used * for key verification. Old key(s) is saved in a list (PrevPublickKey- * List) and cleared when a Cert is no longer self-issued. * PrevPublicKey keep key of the previous Cert. * PrevPublicKeyList keep key(s) of Cert before the previous one. */ PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext), PKIX_ISCERTSELFISSUEFAILED); if (selfIssued == PKIX_TRUE) { if (state->prevPublicKeyList == NULL) { PKIX_CHECK(PKIX_List_Create (&state->prevPublicKeyList, plContext), PKIX_LISTCREATEFAILED); } PKIX_CHECK(PKIX_List_AppendItem (state->prevPublicKeyList, (PKIX_PL_Object *) state->prevPublicKey, plContext), PKIX_LISTAPPENDITEMFAILED); } else { /* Not self-issued Cert any more, clear old key(s) saved */ PKIX_DECREF(state->prevPublicKeyList); } /* Make inheritance and save current Public Key */ PKIX_CHECK(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey (publicKey, state->prevPublicKey, &newPublicKey, plContext), PKIX_PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED); if (newPublicKey == NULL){ PKIX_INCREF(publicKey); newPublicKey = publicKey; } PKIX_DECREF(state->prevPublicKey); PKIX_INCREF(newPublicKey); state->prevPublicKey = newPublicKey; /* Save current Cert's crlSign bit for CRL checking later */ if (state->certsRemaining != 0) { checkKeyUsageFail = PKIX_PL_Cert_VerifyKeyUsage (cert, PKIX_CRL_SIGN, plContext); state->prevCertCrlSign = (checkKeyUsageFail == NULL)? PKIX_TRUE : PKIX_FALSE; PKIX_DECREF(checkKeyUsageFail); } /* PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState (checker, (PKIX_PL_Object *)state, plContext), PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED); */ cleanup: PKIX_DECREF(state); PKIX_DECREF(publicKey); PKIX_DECREF(newPublicKey); PKIX_DECREF(checkKeyUsageFail); PKIX_RETURN(CERTCHAINCHECKER); }