andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: /* andre@0: * pkix_pl_ocspcertid.c andre@0: * andre@0: * Certificate ID Object for OCSP andre@0: * andre@0: */ andre@0: andre@0: #include "pkix_pl_ocspcertid.h" andre@0: andre@0: /* --Private-Cert-Functions------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_OcspCertID_Destroy andre@0: * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) andre@0: */ andre@0: static PKIX_Error * andre@0: pkix_pl_OcspCertID_Destroy( andre@0: PKIX_PL_Object *object, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_OcspCertID *certID = NULL; andre@0: andre@0: PKIX_ENTER(OCSPCERTID, "pkix_pl_OcspCertID_Destroy"); andre@0: andre@0: PKIX_NULLCHECK_ONE(object); andre@0: andre@0: PKIX_CHECK(pkix_CheckType(object, PKIX_OCSPCERTID_TYPE, plContext), andre@0: PKIX_OBJECTNOTOCSPCERTID); andre@0: andre@0: certID = (PKIX_PL_OcspCertID *)object; andre@0: andre@0: if (certID->certID) { andre@0: CERT_DestroyOCSPCertID(certID->certID); andre@0: } andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(OCSPCERTID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: pkix_pl_OcspCertID_RegisterSelf andre@0: * DESCRIPTION: andre@0: * Registers PKIX_PUBLICKEY_TYPE and its related functions andre@0: * with systemClasses[] andre@0: * THREAD SAFETY: andre@0: * Not Thread Safe - for performance and complexity reasons andre@0: * andre@0: * Since this function is only called by PKIX_PL_Initialize, which should andre@0: * only be called once, it is acceptable that this function is not andre@0: * thread-safe. andre@0: */ andre@0: PKIX_Error * andre@0: pkix_pl_OcspCertID_RegisterSelf(void *plContext) andre@0: { andre@0: extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; andre@0: pkix_ClassTable_Entry entry; andre@0: andre@0: PKIX_ENTER(OCSPCERTID, "pkix_pl_OcspCertID_RegisterSelf"); andre@0: andre@0: entry.description = "OcspCertID"; andre@0: entry.objCounter = 0; andre@0: entry.typeObjectSize = sizeof(PKIX_PL_OcspCertID); andre@0: entry.destructor = pkix_pl_OcspCertID_Destroy; andre@0: entry.equalsFunction = NULL; andre@0: entry.hashcodeFunction = NULL; andre@0: entry.toStringFunction = NULL; andre@0: entry.comparator = NULL; andre@0: entry.duplicateFunction = pkix_duplicateImmutable; andre@0: systemClasses[PKIX_OCSPCERTID_TYPE] = entry; andre@0: andre@0: PKIX_RETURN(OCSPCERTID); andre@0: } andre@0: andre@0: /* --Public-Functions------------------------------------------------------- */ andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_OcspCertID_Create andre@0: * DESCRIPTION: andre@0: * andre@0: * This function creates an OcspCertID for a given certificate, andre@0: * to be used with OCSP transactions. andre@0: * andre@0: * If a Date is provided in "validity" it may be used in the search for the andre@0: * issuer of "cert" but has no effect on the request itself. andre@0: * andre@0: * PARAMETERS: andre@0: * "cert" andre@0: * Address of the Cert for which an OcspCertID is to be created. Must be andre@0: * non-NULL. andre@0: * "validity" andre@0: * Address of the Date for which the Cert's validity is to be determined. andre@0: * May be NULL. andre@0: * "object" andre@0: * Address at which the result is stored. Must be non-NULL. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * THREAD SAFETY: andre@0: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns an OcspCertID Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_OcspCertID_Create( andre@0: PKIX_PL_Cert *cert, andre@0: PKIX_PL_Date *validity, andre@0: PKIX_PL_OcspCertID **object, andre@0: void *plContext) andre@0: { andre@0: PKIX_PL_OcspCertID *cid = NULL; andre@0: PRTime time = 0; andre@0: andre@0: PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_Create"); andre@0: PKIX_NULLCHECK_TWO(cert, object); andre@0: andre@0: PKIX_CHECK(PKIX_PL_Object_Alloc andre@0: (PKIX_OCSPCERTID_TYPE, andre@0: sizeof (PKIX_PL_OcspCertID), andre@0: (PKIX_PL_Object **)&cid, andre@0: plContext), andre@0: PKIX_COULDNOTCREATEOBJECT); andre@0: andre@0: if (validity != NULL) { andre@0: PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext), andre@0: PKIX_DATEGETPRTIMEFAILED); andre@0: } else { andre@0: time = PR_Now(); andre@0: } andre@0: andre@0: cid->certID = CERT_CreateOCSPCertID(cert->nssCert, time); andre@0: if (!cid->certID) { andre@0: PKIX_ERROR(PKIX_COULDNOTCREATEOBJECT); andre@0: } andre@0: andre@0: *object = cid; andre@0: cid = NULL; andre@0: cleanup: andre@0: PKIX_DECREF(cid); andre@0: PKIX_RETURN(OCSPCERTID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_OcspCertID_GetFreshCacheStatus andre@0: * DESCRIPTION: andre@0: * andre@0: * This function may return cached OCSP results for the provided andre@0: * certificate, but only if stored information is still considered to be andre@0: * fresh. andre@0: * andre@0: * PARAMETERS andre@0: * "cid" andre@0: * A certificate ID as used by OCSP andre@0: * "validity" andre@0: * Optional date parameter to request validity for a specifc time. andre@0: * "hasFreshStatus" andre@0: * Output parameter, if the function successed to find fresh cached andre@0: * information, this will be set to true. Must be non-NULL. andre@0: * "statusIsGood" andre@0: * The good/bad result stored in the cache. Must be non-NULL. andre@0: * "missingResponseError" andre@0: * If OCSP status is "bad", this variable may indicate the exact andre@0: * reason why the previous OCSP request had failed. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns an OcspCertID Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_OcspCertID_GetFreshCacheStatus( andre@0: PKIX_PL_OcspCertID *cid, andre@0: PKIX_PL_Date *validity, andre@0: PKIX_Boolean *hasFreshStatus, andre@0: PKIX_Boolean *statusIsGood, andre@0: SECErrorCodes *missingResponseError, andre@0: void *plContext) andre@0: { andre@0: PRTime time = 0; andre@0: SECStatus rv; andre@0: SECStatus rvOcsp; andre@0: OCSPFreshness freshness; andre@0: andre@0: PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_GetFreshCacheStatus"); andre@0: PKIX_NULLCHECK_THREE(cid, hasFreshStatus, statusIsGood); andre@0: andre@0: if (validity != NULL) { andre@0: PKIX_CHECK(pkix_pl_Date_GetPRTime(validity, &time, plContext), andre@0: PKIX_DATEGETPRTIMEFAILED); andre@0: } else { andre@0: time = PR_Now(); andre@0: } andre@0: andre@0: rv = ocsp_GetCachedOCSPResponseStatus( andre@0: cid->certID, time, PR_TRUE, /*ignoreGlobalOcspFailureSetting*/ andre@0: &rvOcsp, missingResponseError, &freshness); andre@0: andre@0: *hasFreshStatus = (rv == SECSuccess && freshness == ocspFresh); andre@0: if (*hasFreshStatus) { andre@0: *statusIsGood = (rvOcsp == SECSuccess); andre@0: } andre@0: cleanup: andre@0: PKIX_RETURN(OCSPCERTID); andre@0: } andre@0: andre@0: /* andre@0: * FUNCTION: PKIX_PL_OcspCertID_RememberOCSPProcessingFailure andre@0: * DESCRIPTION: andre@0: * andre@0: * Information about the current failure associated to the given certID andre@0: * will be remembered in the cache, potentially allowing future calls andre@0: * to prevent repetitive OCSP requests. andre@0: * After this function got called, it may no longer be safe to andre@0: * use the provided cid parameter, because ownership might have been andre@0: * transfered to the cache. This status will be recorded inside the andre@0: * cid object. andre@0: * andre@0: * PARAMETERS andre@0: * "cid" andre@0: * The certificate ID associated to a failed OCSP processing. andre@0: * "plContext" andre@0: * Platform-specific context pointer. andre@0: * RETURNS: andre@0: * Returns NULL if the function succeeds. andre@0: * Returns an OcspCertID Error if the function fails in a non-fatal way. andre@0: * Returns a Fatal Error if the function fails in an unrecoverable way. andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_OcspCertID_RememberOCSPProcessingFailure( andre@0: PKIX_PL_OcspCertID *cid, andre@0: void *plContext) andre@0: { andre@0: PRBool certIDWasConsumed = PR_FALSE; andre@0: andre@0: PKIX_ENTER(DATE, "PKIX_PL_OcspCertID_RememberOCSPProcessingFailure"); andre@0: PKIX_NULLCHECK_TWO(cid, cid->certID); andre@0: andre@0: cert_RememberOCSPProcessingFailure(cid->certID, &certIDWasConsumed); andre@0: andre@0: if (certIDWasConsumed) { andre@0: cid->certID = NULL; andre@0: } andre@0: andre@0: PKIX_RETURN(OCSPCERTID); andre@0: } andre@0: