Created
January 26, 2010 14:45
-
-
Save agl/286886 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/mozilla/security/nss/lib/certhigh/ocsp.c b/mozilla/security/nss/lib/certhigh/ocsp.c | |
index 0ffdb34..4a225df 100644 | |
--- a/mozilla/security/nss/lib/certhigh/ocsp.c | |
+++ b/mozilla/security/nss/lib/certhigh/ocsp.c | |
@@ -4797,6 +4797,112 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, | |
} | |
/* | |
+ * FUNCTION: CERT_CacheOCSPResponseFromSideChannel | |
+ * First, this function caches the OCSP cache to see if a positive response | |
+ * for the given certificate already exists. If it does, then the function | |
+ * returns successfully. | |
+ * | |
+ * If not, then it validates that the given OCSP response is a valid, | |
+ * positive, response for the given certificate and inserts it into the | |
+ * cache. | |
+ * | |
+ * This function is intended for use when OCSP responses are provided via a | |
+ * side-channel, i.e. TLS OCSP stapling (a.k.a. the status_request extension). | |
+ * | |
+ * INPUTS: | |
+ * CERTCertDBHandle *handle | |
+ * certificate DB of the cert that is being checked | |
+ * CERTCertificate *cert | |
+ * the certificate being checked | |
+ * int64 time | |
+ * time for which status is to be determined | |
+ * SECItem encodedResponse | |
+ * the DER encoded bytes of the OCSP response | |
+ * RETURN: | |
+ * SECSuccess if the cert was found in the cache, or if the OCSP response was | |
+ * found to be valid and inserted into the cache. SECFailure otherwise. | |
+ */ | |
+SECStatus | |
+CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle, | |
+ CERTCertificate *cert, | |
+ int64 time, | |
+ SECItem *encodedResponse) | |
+{ | |
+ CERTOCSPCertID *certID = NULL; | |
+ PRBool certIDWasConsumed = PR_FALSE; | |
+ SECStatus rv = SECFailure; | |
+ SECStatus rvOcsp; | |
+ SECErrorCodes dummy_error_code; /* we ignore this */ | |
+ CERTOCSPResponse *response = NULL; | |
+ CERTCertificate *signerCert = NULL; | |
+ CERTCertificate *issuerCert = NULL; | |
+ CERTOCSPSingleResponse *single = NULL; | |
+ | |
+ certID = CERT_CreateOCSPCertID(cert, time); | |
+ if (certID == NULL) | |
+ goto out; | |
+ rv = ocsp_GetCachedOCSPResponseStatusIfFresh( | |
+ certID, time, PR_FALSE /* ignoreGlobalOcspFailureSetting */, | |
+ &rvOcsp, &dummy_error_code); | |
+ if (rv == SECSuccess && rvOcsp == SECSuccess) { | |
+ /* The cached value is positive. We don't want to waste time validating | |
+ * this OCSP response. */ | |
+ rv = SECSuccess; | |
+ goto out; | |
+ } | |
+ | |
+ response = CERT_DecodeOCSPResponse(encodedResponse); | |
+ if (response == NULL) | |
+ goto out; | |
+ | |
+ /* We aren't interested unless the response is positive. */ | |
+ if (CERT_GetOCSPResponseStatus(response) != SECSuccess) | |
+ goto out; | |
+ | |
+ issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); | |
+ rv = CERT_VerifyOCSPResponseSignature( | |
+ response, handle, NULL /* pwArg not given */, &signerCert, | |
+ issuerCert); | |
+ if (rv != SECSuccess) | |
+ goto out; | |
+ | |
+ PORT_Assert(signerCert != NULL); /* internal consistency check */ | |
+ | |
+ rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, | |
+ signerCert, time, &single); | |
+ if (rv != SECSuccess) | |
+ goto out; | |
+ | |
+ rv = ocsp_SingleResponseCertHasGoodStatus(single, time); | |
+ if (rv != SECSuccess) | |
+ goto out; | |
+ | |
+ PR_EnterMonitor(OCSP_Global.monitor); | |
+ if (OCSP_Global.maxCacheEntries >= 0) { | |
+ ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, | |
+ &certIDWasConsumed); | |
+ /* ignore cache update failures */ | |
+ if (certIDWasConsumed) | |
+ certID = NULL; | |
+ } | |
+ PR_ExitMonitor(OCSP_Global.monitor); | |
+ rv = SECSuccess; | |
+ | |
+out: | |
+ /* single points within the response so there's no need to free it. */ | |
+ | |
+ if (issuerCert != NULL) | |
+ CERT_DestroyCertificate(issuerCert); | |
+ if (signerCert != NULL) | |
+ CERT_DestroyCertificate(signerCert); | |
+ if (response != NULL) | |
+ CERT_DestroyOCSPResponse(response); | |
+ if (certID != NULL) | |
+ CERT_DestroyOCSPCertID(certID); | |
+ return rv; | |
+} | |
+ | |
+/* | |
* Status in *certIDWasConsumed will always be correct, regardless of | |
* return value. | |
*/ | |
diff --git a/mozilla/security/nss/lib/certhigh/ocsp.h b/mozilla/security/nss/lib/certhigh/ocsp.h | |
index 04a406a..da4e16e 100644 | |
--- a/mozilla/security/nss/lib/certhigh/ocsp.h | |
+++ b/mozilla/security/nss/lib/certhigh/ocsp.h | |
@@ -550,6 +550,39 @@ CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath); | |
extern SECStatus | |
CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, | |
PRTime time, void *pwArg); | |
+ | |
+/* | |
+ * FUNCTION: CERT_CacheOCSPResponseFromSideChannel | |
+ * First, this function caches the OCSP cache to see if a positive response | |
+ * for the given certificate already exists. If it does, then the function | |
+ * returns successfully. | |
+ * | |
+ * If not, then it validates that the given OCSP response is a valid, | |
+ * positive, response for the given certificate and inserts it into the | |
+ * cache. | |
+ * | |
+ * This function is intended for use when OCSP responses are provided via a | |
+ * side-channel, i.e. TLS OCSP stapling (a.k.a. the status_request extension). | |
+ * | |
+ * INPUTS: | |
+ * CERTCertDBHandle *handle | |
+ * certificate DB of the cert that is being checked | |
+ * CERTCertificate *cert | |
+ * the certificate being checked | |
+ * int64 time | |
+ * time for which status is to be determined | |
+ * SECItem encodedResponse | |
+ * the DER encoded bytes of the OCSP response | |
+ * RETURN: | |
+ * SECSuccess if the cert was found in the cache, or if the OCSP response was | |
+ * found to be valid and inserted into the cache. SECFailure otherwise. | |
+ */ | |
+extern SECStatus | |
+CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle, | |
+ CERTCertificate *cert, | |
+ int64 time, | |
+ SECItem *encodedResponse); | |
+ | |
/* | |
* FUNCTION: CERT_GetOCSPStatusForCertID | |
* Returns the OCSP status contained in the passed in paramter response | |
diff --git a/mozilla/security/nss/lib/nss/nss.def b/mozilla/security/nss/lib/nss/nss.def | |
index 3447150..a2081b2 100644 | |
--- a/mozilla/security/nss/lib/nss/nss.def | |
+++ b/mozilla/security/nss/lib/nss/nss.def | |
@@ -993,6 +993,7 @@ SECMOD_GetSkipFirstFlag; | |
;+ global: | |
CERT_DistNamesFromCertList; | |
CERT_DupDistNames; | |
+CERT_CacheOCSPResponseFromSideChannel; | |
;+ local: | |
;+ *; | |
;+}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment