Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1219)

Unified Diff: nss/mozilla/security/nss/lib/certhigh/ocsp.c

Issue 593027: Update NSS and NSPR to NSS_3_12_6_BETA1 and NSPR_4_8_4_BETA1.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/
Patch Set: Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « nss/mozilla/security/nss/lib/certhigh/ocsp.h ('k') | nss/mozilla/security/nss/lib/nss/nssinit.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: nss/mozilla/security/nss/lib/certhigh/ocsp.c
===================================================================
--- nss/mozilla/security/nss/lib/certhigh/ocsp.c (revision 38521)
+++ nss/mozilla/security/nss/lib/certhigh/ocsp.c (working copy)
@@ -39,7 +39,7 @@
* Implementation of OCSP services, for both client and server.
* (XXX, really, mostly just for client right now, but intended to do both.)
*
- * $Id: ocsp.c,v 1.61 2010/01/08 01:06:47 wtc%google.com Exp $
+ * $Id: ocsp.c,v 1.64 2010/02/01 20:09:31 wtc%google.com Exp $
*/
#include "prerror.h"
@@ -150,7 +150,19 @@
void *pwArg,
PRBool *certIDWasConsumed,
SECStatus *rv_ocsp);
+
static SECStatus
+ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle,
+ CERTOCSPCertID *certID,
+ CERTCertificate *cert,
+ int64 time,
+ void *pwArg,
+ SECItem *encodedResponse,
+ PRBool *certIDWasConsumed,
+ PRBool cacheNegative,
+ SECStatus *rv_ocsp);
+
+static SECStatus
ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle,
CERTOCSPResponse *response,
CERTOCSPCertID *certID,
@@ -4797,6 +4809,77 @@
}
/*
+ * FUNCTION: CERT_CacheOCSPResponseFromSideChannel
+ * First, this function checks the OCSP cache to see if a good 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,
+ * good 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
+ * void *pwArg
+ * argument for password prompting, if needed
+ * 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,
+ void *pwArg)
+{
+ CERTOCSPCertID *certID;
+ PRBool certIDWasConsumed = PR_FALSE;
+ SECStatus rv = SECFailure;
+ SECStatus rvOcsp;
+ SECErrorCodes dummy_error_code; /* we ignore this */
+
+ certID = CERT_CreateOCSPCertID(cert, time);
+ if (!certID)
+ return SECFailure;
+ rv = ocsp_GetCachedOCSPResponseStatusIfFresh(
+ certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */
+ &rvOcsp, &dummy_error_code);
+ if (rv == SECSuccess && rvOcsp == SECSuccess) {
+ /* The cached value is good. We don't want to waste time validating
+ * this OCSP response. */
+ CERT_DestroyOCSPCertID(certID);
+ return rv;
+ }
+
+ /* Since the OCSP response came from a side channel it is attacker
+ * controlled. The attacker can have chosen any valid OCSP response,
+ * including responses from the past. In this case,
+ * ocsp_GetVerifiedSingleResponseForCertID will fail. If we recorded a
+ * negative cache entry in this case, then the attacker would have
+ * 'poisoned' our cache (denial of service), so we don't record negative
+ * results. */
+ rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg,
+ encodedResponse, &certIDWasConsumed,
+ PR_FALSE /* don't cache failures */,
+ &rvOcsp);
+ if (!certIDWasConsumed) {
+ CERT_DestroyOCSPCertID(certID);
+ }
+ return rv == SECSuccess ? rvOcsp : rv;
+}
+
+/*
* Status in *certIDWasConsumed will always be correct, regardless of
* return value.
*/
@@ -4813,11 +4896,7 @@
PRBool locationIsDefault;
SECItem *encodedResponse = NULL;
CERTOCSPRequest *request = NULL;
- CERTOCSPResponse *response = NULL;
- CERTCertificate *signerCert = NULL;
- CERTCertificate *issuerCert = NULL;
SECStatus rv = SECFailure;
- CERTOCSPSingleResponse *single = NULL;
if (!certIDWasConsumed || !rv_ocsp) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -4879,6 +4958,75 @@
goto loser;
}
+ rv = ocsp_CacheEncodedOCSPResponse(handle, certID, cert, time, pwArg,
+ encodedResponse, certIDWasConsumed,
+ PR_TRUE /* cache failures */, rv_ocsp);
+
+loser:
+ if (request != NULL)
+ CERT_DestroyOCSPRequest(request);
+ if (encodedResponse != NULL)
+ SECITEM_FreeItem(encodedResponse, PR_TRUE);
+ if (location != NULL)
+ PORT_Free(location);
+
+ return rv;
+}
+
+/*
+ * FUNCTION: ocsp_CacheEncodedOCSPResponse
+ * This function decodes an OCSP response and checks for a valid response
+ * concerning the given certificate. If such a response is not found
+ * then nothing is cached. Otherwise, if it is a good response, or if
+ * cacheNegative is true, the results are stored in the OCSP cache.
+ *
+ * Note: a 'valid' response is one that parses successfully, is not an OCSP
+ * exception (see RFC 2560 Section 2.3), is correctly signed and is current.
+ * A 'good' response is a valid response that attests that the certificate
+ * is not currently revoked (see RFC 2560 Section 2.2).
+ *
+ * INPUTS:
+ * CERTCertDBHandle *handle
+ * certificate DB of the cert that is being checked
+ * CERTOCSPCertID *certID
+ * the cert ID corresponding to |cert|
+ * CERTCertificate *cert
+ * the certificate being checked
+ * int64 time
+ * time for which status is to be determined
+ * void *pwArg
+ * the opaque argument to the password prompting function.
+ * SECItem *encodedResponse
+ * the DER encoded bytes of the OCSP response
+ * PRBool *certIDWasConsumed
+ * (output) on return, this is true iff |certID| was consumed by this
+ * function.
+ * SECStatus *rv_ocsp
+ * (output) on return, this is SECSuccess iff the response is good (see
+ * definition of 'good' above).
+ * RETURN:
+ * SECSuccess iff the response is valid.
+ */
+static SECStatus
+ocsp_CacheEncodedOCSPResponse(CERTCertDBHandle *handle,
+ CERTOCSPCertID *certID,
+ CERTCertificate *cert,
+ int64 time,
+ void *pwArg,
+ SECItem *encodedResponse,
+ PRBool *certIDWasConsumed,
+ PRBool cacheNegative,
+ SECStatus *rv_ocsp)
+{
+ CERTOCSPResponse *response = NULL;
+ CERTCertificate *signerCert = NULL;
+ CERTCertificate *issuerCert = NULL;
+ CERTOCSPSingleResponse *single = NULL;
+ SECStatus rv = SECFailure;
+
+ *certIDWasConsumed = PR_FALSE;
+ *rv_ocsp = SECFailure;
+
response = CERT_DecodeOCSPResponse(encodedResponse);
if (response == NULL) {
goto loser;
@@ -4926,27 +5074,25 @@
*rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(single, time);
loser:
- PR_EnterMonitor(OCSP_Global.monitor);
- if (OCSP_Global.maxCacheEntries >= 0) {
- /* single == NULL means: remember response failure */
- ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single,
- certIDWasConsumed);
- /* ignore cache update failures */
+ if (cacheNegative || *rv_ocsp == SECSuccess) {
+ PR_EnterMonitor(OCSP_Global.monitor);
+ if (OCSP_Global.maxCacheEntries >= 0) {
+ /* single == NULL means: remember response failure */
+ ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single,
+ certIDWasConsumed);
+ /* ignore cache update failures */
+ }
+ PR_ExitMonitor(OCSP_Global.monitor);
}
- PR_ExitMonitor(OCSP_Global.monitor);
+ /* '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 (request != NULL)
- CERT_DestroyOCSPRequest(request);
- if (encodedResponse != NULL)
- SECITEM_FreeItem(encodedResponse, PR_TRUE);
- if (location != NULL)
- PORT_Free(location);
return rv;
}
« no previous file with comments | « nss/mozilla/security/nss/lib/certhigh/ocsp.h ('k') | nss/mozilla/security/nss/lib/nss/nssinit.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698