Backed out changeset af7af149b5dd (burning aurora windows)
authorCamilo Viecco <cviecco@mozilla.com>
Tue, 03 Jun 2014 13:34:56 -0700
changeset 199400 4c21b252632f4ce4600ff438efe8ce1b6b4d2a80
parent 199399 af7af149b5dd64cb14958a2932b208c6fa37d474
child 199401 13f8ae33faf89125bf7cce33f60c0c2cadd02a80
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone31.0a2
backs outaf7af149b5dd64cb14958a2932b208c6fa37d474
Backed out changeset af7af149b5dd (burning aurora windows)
security/certverifier/NSSCertDBTrustDomain.cpp
security/certverifier/NSSCertDBTrustDomain.h
security/manager/ssl/tests/unit/head_psm.js
security/manager/ssl/tests/unit/test_ev_certs.js
security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
security/manager/ssl/tests/unit/tlsserver/cmd/GenerateOCSPResponse.cpp
security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.h
security/pkix/include/pkix/pkix.h
security/pkix/lib/pkixocsp.cpp
--- a/security/certverifier/NSSCertDBTrustDomain.cpp
+++ b/security/certverifier/NSSCertDBTrustDomain.cpp
@@ -174,34 +174,24 @@ NSSCertDBTrustDomain::CheckRevocation(
 
   PORT_Assert(cert);
   PORT_Assert(issuerCert);
   if (!cert || !issuerCert) {
     PORT_SetError(SEC_ERROR_INVALID_ARGS);
     return SECFailure;
   }
 
-  // Bug 991815: The BR allow OCSP for intermediates to be up to one year old.
-  // Since this affects EV there is no reason why DV should be more strict
-  // so all intermediatates are allowed to have OCSP responses up to one year
-  // old.
-  uint16_t maxOCSPLifetimeInDays = 10;
-  if (endEntityOrCA == EndEntityOrCA::MustBeCA) {
-    maxOCSPLifetimeInDays = 365;
-  }
-
   // If we have a stapled OCSP response then the verification of that response
   // determines the result unless the OCSP response is expired. We make an
   // exception for expired responses because some servers, nginx in particular,
   // are known to serve expired responses due to bugs.
   if (stapledOCSPResponse) {
     PR_ASSERT(endEntityOrCA == MustBeEndEntity);
     SECStatus rv = VerifyAndMaybeCacheEncodedOCSPResponse(cert, issuerCert,
                                                           time,
-                                                          maxOCSPLifetimeInDays,
                                                           stapledOCSPResponse,
                                                           ResponseWasStapled);
     if (rv == SECSuccess) {
       // stapled OCSP response present and good
       Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 1);
       PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
              ("NSSCertDBTrustDomain: stapled OCSP response: good"));
       return rv;
@@ -373,17 +363,16 @@ NSSCertDBTrustDomain::CheckRevocation(
 
     PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
            ("NSSCertDBTrustDomain: returning SECSuccess after "
             "OCSP request failure"));
     return SECSuccess; // Soft fail -> success :(
   }
 
   SECStatus rv = VerifyAndMaybeCacheEncodedOCSPResponse(cert, issuerCert, time,
-                                                        maxOCSPLifetimeInDays,
                                                         response,
                                                         ResponseIsFromNetwork);
   if (rv == SECSuccess || mOCSPFetching != FetchOCSPForDVSoftFail) {
     PR_LOG(gCertVerifierLog, PR_LOG_DEBUG,
       ("NSSCertDBTrustDomain: returning after VerifyEncodedOCSPResponse"));
     return rv;
   }
 
@@ -397,24 +386,23 @@ NSSCertDBTrustDomain::CheckRevocation(
          ("NSSCertDBTrustDomain: end of CheckRevocation"));
 
   return SECSuccess;
 }
 
 SECStatus
 NSSCertDBTrustDomain::VerifyAndMaybeCacheEncodedOCSPResponse(
   const CERTCertificate* cert, CERTCertificate* issuerCert, PRTime time,
-  uint16_t maxLifetimeInDays, const SECItem* encodedResponse,
-  EncodedResponseSource responseSource)
+  const SECItem* encodedResponse, EncodedResponseSource responseSource)
 {
   PRTime thisUpdate = 0;
   PRTime validThrough = 0;
   SECStatus rv = VerifyEncodedOCSPResponse(*this, cert, issuerCert, time,
-                                           maxLifetimeInDays, encodedResponse,
-                                           &thisUpdate, &validThrough);
+                                           encodedResponse, &thisUpdate,
+                                           &validThrough);
   PRErrorCode error = (rv == SECSuccess ? 0 : PR_GetError());
   // validThrough is only trustworthy if the response successfully verifies
   // or it indicates a revoked or unknown certificate.
   // If this isn't the case, store an indication of failure (to prevent
   // repeatedly requesting a response from a failing server).
   if (rv != SECSuccess && error != SEC_ERROR_REVOKED_CERTIFICATE &&
       error != SEC_ERROR_OCSP_UNKNOWN_CERT) {
     validThrough = time + ServerFailureDelay;
--- a/security/certverifier/NSSCertDBTrustDomain.h
+++ b/security/certverifier/NSSCertDBTrustDomain.h
@@ -81,18 +81,17 @@ public:
 private:
   enum EncodedResponseSource {
     ResponseIsFromNetwork = 1,
     ResponseWasStapled = 2
   };
   static const PRTime ServerFailureDelay = 5 * 60 * PR_USEC_PER_SEC;
   SECStatus VerifyAndMaybeCacheEncodedOCSPResponse(
     const CERTCertificate* cert, CERTCertificate* issuerCert, PRTime time,
-    uint16_t maxLifetimeInDays, const SECItem* encodedResponse,
-    EncodedResponseSource responseSource);
+    const SECItem* encodedResponse, EncodedResponseSource responseSource);
 
   const SECTrustType mCertDBTrustType;
   const OCSPFetching mOCSPFetching;
   OCSPCache& mOCSPCache; // non-owning!
   void* mPinArg; // non-owning!
 };
 
 } } // namespace mozilla::psm
--- a/security/manager/ssl/tests/unit/head_psm.js
+++ b/security/manager/ssl/tests/unit/head_psm.js
@@ -428,58 +428,42 @@ function getFailingHttpServer(serverPort
 //   will cause a test failure
 // nssDBlocaion is the location of the NSS database from where the OCSP
 //   responses will be generated (assumes appropiate keys are present)
 // expectedCertNames is an array of nicks of the certs to be responsed
 // expectedBasePaths is an optional array that is used to indicate
 //   what is the expected base path of the OCSP request.
 function startOCSPResponder(serverPort, identity, invalidIdentities,
                             nssDBLocation, expectedCertNames,
-                            expectedBasePaths, expectedMethods,
-                            expectedResponseTypes) {
+                            expectedBasePaths) {
   let httpServer = new HttpServer();
   httpServer.registerPrefixHandler("/",
     function handleServerCallback(aRequest, aResponse) {
       invalidIdentities.forEach(function(identity) {
         do_check_neq(aRequest.host, identity)
       });
-      do_print("got request for: " + aRequest.path);
       let basePath = aRequest.path.slice(1).split("/")[0];
       if (expectedBasePaths.length >= 1) {
         do_check_eq(basePath, expectedBasePaths.shift());
       }
       do_check_true(expectedCertNames.length >= 1);
-      if (expectedMethods && expectedMethods.length >= 1) {
-        do_check_eq(aRequest.method, expectedMethods.shift());
-      }
-      let responseType = "good";
-      if (expectedResponseTypes && expectedResponseTypes.length >= 1) {
-        responseType = expectedResponseTypes.shift();
-      }
-      do_check_true(expectedCertNames.length >= 1);
       let expectedNick = expectedCertNames.shift();
-      do_print("Generating ocsp response(" + responseType + ") for '" +
-               expectedNick + "(" + basePath + ")'");
+      do_print("Generating ocsp response for '" + expectedNick + "(" +
+               basePath + ")'");
       aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
       aResponse.setHeader("Content-Type", "application/ocsp-response");
-      let args = [ [responseType, expectedNick, "unused" ] ];
+      let args = [ ["good", expectedNick, "unused" ] ];
       let retArray = generateOCSPResponses(args, nssDBLocation);
       let responseBody = retArray[0];
       aResponse.bodyOutputStream.write(responseBody, responseBody.length);
     });
   httpServer.identity.setPrimary("http", identity, serverPort);
   invalidIdentities.forEach(function(identity) {
     httpServer.identity.add("http", identity, serverPort);
   });
   httpServer.start(serverPort);
   return {
     stop: function(callback) {
       do_check_eq(expectedCertNames.length, 0);
-       if (expectedBasePaths) {
-         do_check_eq(expectedBasePaths.length, 0);
-       }
-      if (expectedResponseTypes) {
-        do_check_eq(expectedResponseTypes.length, 0);
-      }
       httpServer.stop(callback);
     }
   };
 }
--- a/security/manager/ssl/tests/unit/test_ev_certs.js
+++ b/security/manager/ssl/tests/unit/test_ev_certs.js
@@ -205,75 +205,16 @@ function add_tests_in_mode(useMozillaPKI
       do_check_eq(error,
                   isDebugBuild ? 0
                                : (useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
                                                  : SEC_ERROR_EXTENSION_NOT_FOUND));
       failingOcspResponder.stop(run_next_test);
     });
   });
 
-  // Bug 991815 old but valid intermediates are OK
-  add_test(function () {
-    clearOCSPCache();
-    let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
-                          "test_ev_certs",
-                          isDebugBuild ? ["int-ev-valid", "ev-valid"]
-                                       : ["ev-valid"],
-                          [], [],
-                          isDebugBuild ? ["longvalidityalmostold", "good"]
-                                       : ["good"]);
-    check_ee_for_ev("ev-valid", isDebugBuild);
-    ocspResponder.stop(run_next_test);
-  });
-
-  // Bug 991815 old but valid end-entities are NOT OK for EV
-  // Unfortunatelly because of soft-fail we consider these OK for DV
-  // libpkix does not enforce the age restriction and thus EV is valid
-  add_test(function () {
-    clearOCSPCache();
-    // Since Mozilla::pkix does not consider the old amost invalid OCSP
-    // response valid, it does not cache the old response and thus
-    // makes a separate request for DV
-    let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
-    let debugResponseArray = ["good", "longvalidityalmostold",
-                              "longvalidityalmostold"];
-    if (!useMozillaPKIX) {
-      debugCertNickArray = ["int-ev-valid", "ev-valid"];
-      debugResponseArray = ["good", "longvalidityalmostold"];
-    }
-    let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
-                          "test_ev_certs",
-                          isDebugBuild ? debugCertNickArray : ["ev-valid"],
-                          [], [],
-                          isDebugBuild ? debugResponseArray
-                                       : ["longvalidityalmostold"]);
-    check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
-    ocspResponder.stop(run_next_test);
-  });
-
-  // Bug 991815 Valid but Ancient (almost two year old) responses are Not OK for
-  // EV (still OK for soft fail DV)
-  add_test(function () {
-    clearOCSPCache();
-    let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
-    let debugResponseArray = ["good", "ancientstillvalid",
-                              "ancientstillvalid"];
-    if (!useMozillaPKIX) {
-      debugCertNickArray = ["int-ev-valid", "ev-valid"];
-      debugResponseArray = ["good", "ancientstillvalid"];
-    }
-    let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
-                          "test_ev_certs",
-                          isDebugBuild ? debugCertNickArray : ["ev-valid"],
-                          [], [],
-                          isDebugBuild ? debugResponseArray
-                                       : ["ancientstillvalid"]);
-    check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
-    ocspResponder.stop(run_next_test);
-  });
 }
 
 // bug 950240: add FLAG_MUST_BE_EV to CertVerifier::VerifyCert
 // to prevent spurious OCSP requests that race with OCSP stapling.
 // This has the side-effect of saying an EV certificate is not EV if
 // it hasn't already been verified (e.g. on the verification thread when
 // connecting to a site).
 // This flag is mostly a hack that should be removed once FLAG_LOCAL_ONLY
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
@@ -95,40 +95,22 @@ function add_tests_in_mode(useMozillaPKI
                 getXPCOMStatusFromNSS(SEC_ERROR_REVOKED_CERTIFICATE),
                 ocspResponseRevoked);
   add_ocsp_test("ocsp-stapling-expired-fresh-ca.example.com",
                 getXPCOMStatusFromNSS(SEC_ERROR_REVOKED_CERTIFICATE),
                 ocspResponseRevoked);
   add_ocsp_test("ocsp-stapling-expired.example.com",
                 getXPCOMStatusFromNSS(SEC_ERROR_OCSP_UNKNOWN_CERT),
                 ocspResponseUnknown);
-
-  if (useMozillaPKIX) {
-    // These tests are verifying that an valid but very old response
-    // is rejected as a valid stapled response, requiring a fetch
-    // from the ocsp responder.
-    add_ocsp_test("ocsp-stapling-ancient-valid.example.com", Cr.NS_OK,
-                  ocspResponseGood);
-    add_ocsp_test("ocsp-stapling-ancient-valid.example.com",
-                  getXPCOMStatusFromNSS(SEC_ERROR_REVOKED_CERTIFICATE),
-                  ocspResponseRevoked);
-    add_ocsp_test("ocsp-stapling-ancient-valid.example.com",
-                  getXPCOMStatusFromNSS(SEC_ERROR_OCSP_UNKNOWN_CERT),
-                  ocspResponseUnknown);
-  }
 }
 
 function check_ocsp_stapling_telemetry() {
   let histogram = Cc["@mozilla.org/base/telemetry;1"]
                     .getService(Ci.nsITelemetry)
                     .getHistogramById("SSL_OCSP_STAPLING")
                     .snapshot();
   do_check_eq(histogram.counts[0], 2 * 0); // histogram bucket 0 is unused
   do_check_eq(histogram.counts[1], 2 * 0); // 0 connections with a good response
   do_check_eq(histogram.counts[2], 2 * 0); // 0 connections with no stapled resp.
-  do_check_eq(histogram.counts[3], 2 * 9 + 3); // 9 connections with an expired response
-                                               // 3 connection with a response
-                                               // considered expired due to being
-                                               // old but having an overly-long
-                                               // validity period
+  do_check_eq(histogram.counts[3], 2 * 9); // 9 connections with an expired response
   do_check_eq(histogram.counts[4], 2 * 0); // 0 connections with bad responses
   run_next_test();
 }
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/GenerateOCSPResponse.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/GenerateOCSPResponse.cpp
@@ -51,22 +51,16 @@ const static OCSPResponseName kOCSPRespo
   { "serverr",         ORTSrverr},         // the response indicates there was a
                                            //   server error
   { "trylater",        ORTTryLater},       // the responder replied with
                                            //   "try again later"
   { "resp-unsigned",   ORTNeedsSig},       // the response needs a signature
   { "unauthorized",    ORTUnauthorized},   // the responder does not know about
                                            //   the cert
   { "bad-signature",   ORTBadSignature},   // the response has a bad signature
-  { "longvalidityalmostold", ORTLongValidityAlmostExpired}, // the response is
-                                           // still valid, but the generation
-                                           // is almost a year old
-  { "ancientstillvalid", ORTAncientAlmostExpired}, // The response is still
-                                           // valid but the generation is almost
-                                           // two years old
 };
 
 
 bool
 stringToOCSPResponseType(const char* respText,
                          /*out*/ OCSPResponseType* OCSPType)
 {
   if (!OCSPType) {
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
@@ -44,17 +44,16 @@ const OCSPHost sOCSPHosts[] =
   { "ocsp-stapling-delegated-included.example.com", ORTDelegatedIncluded, "delegatedSigner" },
   { "ocsp-stapling-delegated-included-last.example.com", ORTDelegatedIncludedLast, "delegatedSigner" },
   { "ocsp-stapling-delegated-missing.example.com", ORTDelegatedMissing, "delegatedSigner" },
   { "ocsp-stapling-delegated-missing-multiple.example.com", ORTDelegatedMissingMultiple, "delegatedSigner" },
   { "ocsp-stapling-delegated-no-extKeyUsage.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerNoExtKeyUsage" },
   { "ocsp-stapling-delegated-from-intermediate.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerFromIntermediate" },
   { "ocsp-stapling-delegated-keyUsage-crlSigning.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerKeyUsageCrlSigning" },
   { "ocsp-stapling-delegated-wrong-extKeyUsage.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerWrongExtKeyUsage" },
-  { "ocsp-stapling-ancient-valid.example.com", ORTAncientAlmostExpired, nullptr},
   { nullptr, ORTNull, nullptr }
 };
 
 int32_t
 DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
                   uint32_t aSrvNameArrSize, void *aArg)
 {
   const OCSPHost *host = GetHostForSNI(aSrvNameArr, aSrvNameArrSize,
--- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.cpp
@@ -103,22 +103,16 @@ GetOCSPResponseForType(OCSPResponseType 
   }
   if (aORT == ORTSkipResponseBytes) {
     context.skipResponseBytes = true;
   }
   if (aORT == ORTExpired || aORT == ORTExpiredFreshCA) {
     context.thisUpdate = oldNow;
     context.nextUpdate = oldNow + 10 * PR_USEC_PER_SEC;
   }
-  if (aORT == ORTLongValidityAlmostExpired) {
-    context.thisUpdate = now - (320 * oneDay);
-  }
-  if (aORT == ORTAncientAlmostExpired) {
-    context.thisUpdate = now - (640 * oneDay);
-  }
   if (aORT == ORTRevoked) {
     context.certStatus = 1;
   }
   if (aORT == ORTUnknown) {
     context.certStatus = 2;
   }
   if (aORT == ORTBadSignature) {
     context.badSignature = true;
--- a/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.h
+++ b/security/manager/ssl/tests/unit/tlsserver/lib/OCSPCommon.h
@@ -32,18 +32,16 @@ enum OCSPResponseType
   ORTSkipResponseBytes, // the response does not include responseBytes
   ORTCriticalExtension, // the response includes a critical extension
   ORTNoncriticalExtension, // the response includes an extension that is not critical
   ORTEmptyExtensions,  // the response includes a SEQUENCE OF Extension that is empty
   ORTDelegatedIncluded, // the response is signed by an included delegated responder
   ORTDelegatedIncludedLast, // same, but multiple other certificates are included
   ORTDelegatedMissing, // the response is signed by a not included delegated responder
   ORTDelegatedMissingMultiple, // same, but multiple other certificates are included
-  ORTLongValidityAlmostExpired, // a good response, but that was generated a almost a year ago
-  ORTAncientAlmostExpired, // a good response, with a validity of almost two years almost expiring
 };
 
 struct OCSPHost
 {
   const char *mHostName;
   OCSPResponseType mORT;
   const char *mAdditionalCertName; // useful for ORTGoodOtherCert, etc.
 };
--- a/security/pkix/include/pkix/pkix.h
+++ b/security/pkix/include/pkix/pkix.h
@@ -109,16 +109,15 @@ SECItem* CreateEncodedOCSPRequest(PLAren
 // trustworthy. If the response is not trustworthy, thisUpdate will be 0.
 // Similarly, the optional parameter validThrough will be the time through
 // which the encoded response is considered trustworthy (that is, if a response had a
 // thisUpdate time of validThrough, it would be considered trustworthy).
 SECStatus VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
                                     const CERTCertificate* cert,
                                     CERTCertificate* issuerCert,
                                     PRTime time,
-                                    uint16_t maxLifetimeInDays,
                                     const SECItem* encodedResponse,
                  /* optional out */ PRTime* thisUpdate,
                  /* optional out */ PRTime* validThrough);
 
 } } // namespace mozilla::pkix
 
 #endif // mozilla_pkix__pkix_h
--- a/security/pkix/lib/pkixocsp.cpp
+++ b/security/pkix/lib/pkixocsp.cpp
@@ -51,41 +51,38 @@ ENUM_CLASS CertStatus : uint8_t {
 
 class Context
 {
 public:
   Context(TrustDomain& trustDomain,
           const CERTCertificate& cert,
           CERTCertificate& issuerCert,
           PRTime time,
-          uint16_t maxLifetimeInDays,
           PRTime* thisUpdate,
           PRTime* validThrough)
     : trustDomain(trustDomain)
     , cert(cert)
     , issuerCert(issuerCert)
     , time(time)
-    , maxLifetimeInDays(maxLifetimeInDays)
     , certStatus(CertStatus::Unknown)
     , thisUpdate(thisUpdate)
     , validThrough(validThrough)
   {
     if (thisUpdate) {
       *thisUpdate = 0;
     }
     if (validThrough) {
       *validThrough = 0;
     }
   }
 
   TrustDomain& trustDomain;
   const CERTCertificate& cert;
   CERTCertificate& issuerCert;
   const PRTime time;
-  const uint16_t maxLifetimeInDays;
   CertStatus certStatus;
   PRTime* thisUpdate;
   PRTime* validThrough;
 
 private:
   Context(const Context&); // delete
   void operator=(const Context&); // delete
 };
@@ -321,17 +318,16 @@ SetErrorToMalformedResponseOnBadDERError
     PR_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE, 0);
   }
 }
 
 SECStatus
 VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
                           const CERTCertificate* cert,
                           CERTCertificate* issuerCert, PRTime time,
-                          uint16_t maxOCSPLifetimeInDays,
                           const SECItem* encodedResponse,
                           PRTime* thisUpdate,
                           PRTime* validThrough)
 {
   PR_ASSERT(cert);
   PR_ASSERT(issuerCert);
   // TODO: PR_Assert(pinArg)
   PR_ASSERT(encodedResponse);
@@ -340,18 +336,19 @@ VerifyEncodedOCSPResponse(TrustDomain& t
     return SECFailure;
   }
 
   der::Input input;
   if (input.Init(encodedResponse->data, encodedResponse->len) != der::Success) {
     SetErrorToMalformedResponseOnBadDERError();
     return SECFailure;
   }
-  Context context(trustDomain, *cert, *issuerCert, time, maxOCSPLifetimeInDays,
-                  thisUpdate, validThrough);
+
+  Context context(trustDomain, *cert, *issuerCert, time, thisUpdate,
+                  validThrough);
 
   if (der::Nested(input, der::SEQUENCE,
                   bind(OCSPResponse, _1, ref(context))) != der::Success) {
     SetErrorToMalformedResponseOnBadDERError();
     return SECFailure;
   }
 
   if (der::End(input) != der::Success) {
@@ -662,18 +659,19 @@ SingleResponse(der::Input& input, Contex
 
   // http://tools.ietf.org/html/rfc6960#section-3.2
   // 5. The time at which the status being indicated is known to be
   //    correct (thisUpdate) is sufficiently recent;
   // 6. When available, the time at or before which newer information will
   //    be available about the status of the certificate (nextUpdate) is
   //    greater than the current time.
 
-  const PRTime maxLifetime =
-    context.maxLifetimeInDays * ONE_DAY;
+  // We won't accept any OCSP responses that are more than 10 days old, even if
+  // the nextUpdate time is further in the future.
+  static const PRTime OLDEST_ACCEPTABLE = INT64_C(10) * ONE_DAY;
 
   PRTime thisUpdate;
   if (der::GeneralizedTime(input, thisUpdate) != der::Success) {
     return der::Failure;
   }
 
   if (thisUpdate > context.time + SLOP) {
     return der::Fail(SEC_ERROR_OCSP_FUTURE_RESPONSE);
@@ -688,20 +686,20 @@ SingleResponse(der::Input& input, Contex
                     bind(der::GeneralizedTime, _1, ref(nextUpdate)))
           != der::Success) {
       return der::Failure;
     }
 
     if (nextUpdate < thisUpdate) {
       return der::Fail(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
     }
-    if (nextUpdate - thisUpdate <= maxLifetime) {
+    if (nextUpdate - thisUpdate <= OLDEST_ACCEPTABLE) {
       notAfter = nextUpdate;
     } else {
-      notAfter = thisUpdate + maxLifetime;
+      notAfter = thisUpdate + OLDEST_ACCEPTABLE;
     }
   } else {
     // NSS requires all OCSP responses without a nextUpdate to be recent.
     // Match that stricter behavior.
     notAfter = thisUpdate + ONE_DAY;
   }
 
   if (context.time < SLOP) { // prevent underflow