/* * FUNCTION: pkix_pl_CRL_ToString_Helper * DESCRIPTION: * * Helper function that creates a string representation of the CRL pointed * to by "crl" and stores it at "pString". * * PARAMETERS * "crl" * Address of CRL whose string representation is desired. * Must be non-NULL. * "pString" * Address where object pointer will be stored. 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 CRL Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ static PKIX_Error * pkix_pl_CRL_ToString_Helper( PKIX_PL_CRL *crl, PKIX_PL_String **pString, void *plContext) { char *asciiFormat = NULL; PKIX_UInt32 crlVersion; PKIX_PL_X500Name *crlIssuer = NULL; PKIX_PL_OID *nssSignatureAlgId = NULL; PKIX_PL_BigInt *crlNumber = NULL; PKIX_List *crlEntryList = NULL; PKIX_List *critExtOIDs = NULL; PKIX_PL_String *formatString = NULL; PKIX_PL_String *crlIssuerString = NULL; PKIX_PL_String *lastUpdateString = NULL; PKIX_PL_String *nextUpdateString = NULL; PKIX_PL_String *nssSignatureAlgIdString = NULL; PKIX_PL_String *crlNumberString = NULL; PKIX_PL_String *crlEntryListString = NULL; PKIX_PL_String *critExtOIDsString = NULL; PKIX_PL_String *crlString = NULL; PKIX_ENTER(CRL, "pkix_pl_CRL_ToString_Helper"); PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pString); asciiFormat = "[\n" "\tVersion: v%d\n" "\tIssuer: %s\n" "\tUpdate: [Last: %s\n" "\t Next: %s]\n" "\tSignatureAlgId: %s\n" "\tCRL Number : %s\n" "\n" "\tEntry List: %s\n" "\n" "\tCritExtOIDs: %s\n" "]\n"; PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, asciiFormat, 0, &formatString, plContext), PKIX_STRINGCREATEFAILED); /* Version */ PKIX_CHECK(pkix_pl_CRL_GetVersion(crl, &crlVersion, plContext), PKIX_CRLGETVERSIONFAILED); /* Issuer */ PKIX_CHECK(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext), PKIX_CRLGETISSUERFAILED); PKIX_CHECK(PKIX_PL_Object_ToString ((PKIX_PL_Object *)crlIssuer, &crlIssuerString, plContext), PKIX_X500NAMETOSTRINGFAILED); /* This update - No Date object created, use nss data directly */ PKIX_CHECK(pkix_pl_Date_ToString_Helper (&(crl->nssSignedCrl->crl.lastUpdate), &lastUpdateString, plContext), PKIX_DATETOSTRINGHELPERFAILED); /* Next update - No Date object created, use nss data directly */ PKIX_CHECK(pkix_pl_Date_ToString_Helper (&(crl->nssSignedCrl->crl.nextUpdate), &nextUpdateString, plContext), PKIX_DATETOSTRINGHELPERFAILED); /* Signature Algorithm Id */ PKIX_CHECK(pkix_pl_CRL_GetSignatureAlgId (crl, &nssSignatureAlgId, plContext), PKIX_CRLGETSIGNATUREALGIDFAILED); PKIX_CHECK(PKIX_PL_Object_ToString ((PKIX_PL_Object *)nssSignatureAlgId, &nssSignatureAlgIdString, plContext), PKIX_OIDTOSTRINGFAILED); /* CRL Number */ PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber (crl, &crlNumber, plContext), PKIX_CRLGETCRLNUMBERFAILED); PKIX_TOSTRING(crlNumber, &crlNumberString, plContext, PKIX_BIGINTTOSTRINGFAILED); /* CRL Entries */ PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext), PKIX_CRLGETCRLENTRIESFAILED); PKIX_TOSTRING(crlEntryList, &crlEntryListString, plContext, PKIX_LISTTOSTRINGFAILED); /* CriticalExtensionOIDs */ PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs (crl, &critExtOIDs, plContext), PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED); PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext, PKIX_LISTTOSTRINGFAILED); PKIX_CHECK(PKIX_PL_Sprintf (&crlString, plContext, formatString, crlVersion + 1, crlIssuerString, lastUpdateString, nextUpdateString, nssSignatureAlgIdString, crlNumberString, crlEntryListString, critExtOIDsString), PKIX_SPRINTFFAILED); *pString = crlString; cleanup: PKIX_DECREF(crlIssuer); PKIX_DECREF(nssSignatureAlgId); PKIX_DECREF(crlNumber); PKIX_DECREF(crlEntryList); PKIX_DECREF(critExtOIDs); PKIX_DECREF(crlIssuerString); PKIX_DECREF(lastUpdateString); PKIX_DECREF(nextUpdateString); PKIX_DECREF(nssSignatureAlgIdString); PKIX_DECREF(crlNumberString); PKIX_DECREF(crlEntryListString); PKIX_DECREF(critExtOIDsString); PKIX_DECREF(formatString); PKIX_RETURN(CRL); }
/* * FUNCTION: pkix_DefaultCRLChecker_CheckCRLs * * DESCRIPTION: * Check validity of "cert" based on CRLs at "crlList" that has correct * signature verification with "publicKey". * * PARAMETERS * "cert" * Address of Cert which has the certificate data. Must be non-NULL. * "certIssuer" * Address of Issuer that associates with the Cert. Must be non-NULL. * "certSerialNumber" * Address of Serial Number that associates with the Cert. Must be * non-NULL. * "publicKey" * Address of Public Key that associates with the Cert Issuer. * Must be non-NULL. * "crlList" * A List CRLs that the certificate is verified upon. Must be non-NULL. * "state" * Address of DefaultCRLCheckerState which keeps dynamic state data. * Must be non-NULL. * "pCrlEntryList" * Address of PKIX_PL_CrlEntry List that contains valid CrlEntries for * this Cert. May be NULL. * "plContext" * Platform-specific context pointer. * * THREAD SAFETY: * Conditionally 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_CheckCRLs( PKIX_PL_Cert *cert, PKIX_PL_X500Name *certIssuer, PKIX_PL_BigInt *certSerialNumber, PKIX_PL_PublicKey *publicKey, PKIX_List *crlList, pkix_DefaultCRLCheckerState *state, PKIX_List **pCrlEntryList, void *plContext) { PKIX_PL_CRL *crl = NULL; PKIX_PL_CRLEntry *crlEntry = NULL; PKIX_PL_PublicKey *pKey = NULL; PKIX_List *unresCrlCritExtOIDs = NULL; PKIX_List *unresCrlEntryCritExtOIDs = NULL; PKIX_List *crlEntryList = NULL; PKIX_Error *verifyFail = NULL; PKIX_UInt32 numCrls = 0; PKIX_UInt32 numKeys = 0; PKIX_UInt32 numCritExtOIDs = 0; PKIX_Boolean crlVerified = PKIX_FALSE; PKIX_Boolean crlRevoking = PKIX_FALSE; PKIX_Int32 reasonCode = 0; PKIX_UInt32 i; PKIX_Int32 j; PKIX_ENTER(CERTCHAINCHECKER, "pkix_DefaultCRLChecker_CheckCRLs"); PKIX_NULLCHECK_FOUR(cert, publicKey, crlList, state); PKIX_CHECK(PKIX_List_GetLength(crlList, &numCrls, plContext), PKIX_LISTGETLENGTHFAILED); if (state->prevPublicKeyList != NULL) { PKIX_CHECK(PKIX_List_GetLength (state->prevPublicKeyList, &numKeys, plContext), PKIX_LISTGETLENGTHFAILED); } /* Check if Cert is not revoked by any the the CRLs */ for (i = 0; i < numCrls; i++){ PKIX_CHECK(PKIX_List_GetItem (crlList, i, (PKIX_PL_Object **)&crl, plContext), PKIX_LISTGETITEMFAILED); /* * Checking serial number (issuer done in selector) then * verify signature. If matches, get the CRL reason(s). */ if (state->prevCertCrlSign == PKIX_TRUE) { verifyFail = PKIX_PL_CRL_VerifySignature (crl, publicKey, plContext); if (verifyFail == NULL) { crlVerified = PKIX_TRUE; } else { crlVerified = PKIX_FALSE; PKIX_DECREF(verifyFail); } } if (crlVerified == PKIX_FALSE) { /* Verify from old key(s) on the list */ for (j = numKeys - 1; j >= 0; j--) { PKIX_CHECK(PKIX_List_GetItem (state->prevPublicKeyList, j, (PKIX_PL_Object **) &pKey, plContext), PKIX_LISTGETITEMFAILED); verifyFail = PKIX_PL_CRL_VerifySignature (crl, pKey, plContext); if (verifyFail == NULL) { crlVerified = PKIX_TRUE; break; } else { crlVerified = PKIX_FALSE; PKIX_DECREF(verifyFail); } PKIX_DECREF(pKey); } } if (crlVerified == PKIX_FALSE) { /* try next one ... */ goto cleanup_loop; } state->certHasValidCrl = PKIX_TRUE; PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs (crl, &unresCrlCritExtOIDs, plContext), PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED); /* * XXX Advanced CRL work - should put a * Loop here to process and remove critical * extension oids. */ if (unresCrlCritExtOIDs) { PKIX_CHECK(PKIX_List_GetLength(unresCrlCritExtOIDs, &numCritExtOIDs, plContext), PKIX_LISTGETLENGTHFAILED); if (numCritExtOIDs != 0) { PKIX_DEFAULTCRLCHECKERSTATE_DEBUG (PKIX_CRLCRITICALEXTENSIONOIDSNOTPROCESSED); /* * Uncomment this after we have implemented * checkers for all the critical extensions. * * PKIX_ERROR * ("Unrecognized CRL Critical Extension"); */ } } PKIX_CHECK(PKIX_PL_CRL_GetCRLEntryForSerialNumber (crl, certSerialNumber, &crlEntry, plContext), PKIX_CRLGETCRLENTRYFORSERIALNUMBERFAILED); if (crlEntry == NULL) { goto cleanup_loop; } crlRevoking = PKIX_TRUE; PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode (crlEntry, &reasonCode, plContext), PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED); /* This is a valid CRLEntry, return it for caching */ if (crlEntryList == NULL) { PKIX_CHECK(PKIX_List_Create(&crlEntryList, plContext), PKIX_LISTCREATEFAILED); } PKIX_CHECK(PKIX_List_AppendItem (crlEntryList, (PKIX_PL_Object *) crlEntry, plContext), PKIX_LISTAPPENDITEMFAILED); /* Set reason code in state for advance CRL reviewing */ if (reasonCode >= 0) { if (reasonCode >= numReasonCodes) reasonCode = 0; state->reasonCodeMask |= 1 << reasonCode; PKIX_DEFAULTCRLCHECKERSTATE_DEBUG_ARG ("CRL revocation Reason: %s\n ", reasonCodeMsgString[reasonCode]); } else { PKIX_DEFAULTCRLCHECKERSTATE_DEBUG ("Revoked by Unknown CRL ReasonCode"); } PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs (crlEntry, &unresCrlEntryCritExtOIDs, plContext), PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED); if (unresCrlEntryCritExtOIDs) { PKIX_CHECK(pkix_List_Remove (unresCrlEntryCritExtOIDs, (PKIX_PL_Object *) state->crlReasonCodeOID, plContext), PKIX_LISTREMOVEFAILED); PKIX_CHECK(PKIX_List_GetLength(unresCrlEntryCritExtOIDs, &numCritExtOIDs, plContext), PKIX_LISTGETLENGTHFAILED); if (numCritExtOIDs != 0) { PKIX_DEFAULTCRLCHECKERSTATE_DEBUG (PKIX_CRLENTRYCRITICALEXTENSIONWASNOTPROCESSED); PKIX_ERROR(PKIX_UNRECOGNIZEDCRLENTRYCRITICALEXTENSION); } } cleanup_loop: PKIX_DECREF(pKey); PKIX_DECREF(verifyFail); PKIX_DECREF(pKey); PKIX_DECREF(crlEntry); PKIX_DECREF(crl); PKIX_DECREF(unresCrlCritExtOIDs); PKIX_DECREF(unresCrlEntryCritExtOIDs); } *pCrlEntryList = crlEntryList; if (crlRevoking == PKIX_TRUE) { PKIX_ERROR(PKIX_CERTIFICATEREVOKEDBYCRL); } cleanup: PKIX_DECREF(pKey); PKIX_DECREF(verifyFail); PKIX_DECREF(crlEntry); PKIX_DECREF(crl); PKIX_DECREF(unresCrlCritExtOIDs); PKIX_DECREF(unresCrlEntryCritExtOIDs); PKIX_RETURN(CERTCHAINCHECKER); }