Bug 991815 - Part 1/2 - Allow intermediate OCSP responses up to 1 year old. r=keeler

--HG--
extra : rebase_source : 28d5336da1dc44932b92ce2c59fca5fcb2b8a3d8
This commit is contained in:
Camilo Viecco 2014-05-30 16:12:36 -07:00
parent c59515f41e
commit 553254501f
4 changed files with 28 additions and 12 deletions

View File

@ -185,6 +185,15 @@ NSSCertDBTrustDomain::CheckRevocation(
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,
@ -193,6 +202,7 @@ NSSCertDBTrustDomain::CheckRevocation(
PR_ASSERT(endEntityOrCA == EndEntityOrCA::MustBeEndEntity);
SECStatus rv = VerifyAndMaybeCacheEncodedOCSPResponse(cert, issuerCert,
time,
maxOCSPLifetimeInDays,
stapledOCSPResponse,
ResponseWasStapled);
if (rv == SECSuccess) {
@ -376,6 +386,7 @@ NSSCertDBTrustDomain::CheckRevocation(
}
SECStatus rv = VerifyAndMaybeCacheEncodedOCSPResponse(cert, issuerCert, time,
maxOCSPLifetimeInDays,
response,
ResponseIsFromNetwork);
if (rv == SECSuccess || mOCSPFetching != FetchOCSPForDVSoftFail) {
@ -399,13 +410,14 @@ NSSCertDBTrustDomain::CheckRevocation(
SECStatus
NSSCertDBTrustDomain::VerifyAndMaybeCacheEncodedOCSPResponse(
const CERTCertificate* cert, CERTCertificate* issuerCert, PRTime time,
const SECItem* encodedResponse, EncodedResponseSource responseSource)
uint16_t maxLifetimeInDays, const SECItem* encodedResponse,
EncodedResponseSource responseSource)
{
PRTime thisUpdate = 0;
PRTime validThrough = 0;
SECStatus rv = VerifyEncodedOCSPResponse(*this, cert, issuerCert, time,
encodedResponse, &thisUpdate,
&validThrough);
maxLifetimeInDays, 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.

View File

@ -90,7 +90,8 @@ private:
static const PRTime ServerFailureDelay = 5 * 60 * PR_USEC_PER_SEC;
SECStatus VerifyAndMaybeCacheEncodedOCSPResponse(
const CERTCertificate* cert, CERTCertificate* issuerCert, PRTime time,
const SECItem* encodedResponse, EncodedResponseSource responseSource);
uint16_t maxLifetimeInDays, const SECItem* encodedResponse,
EncodedResponseSource responseSource);
const SECTrustType mCertDBTrustType;
const OCSPFetching mOCSPFetching;

View File

@ -121,6 +121,7 @@ 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);

View File

@ -56,12 +56,14 @@ public:
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)
@ -78,6 +80,7 @@ public:
const CERTCertificate& cert;
CERTCertificate& issuerCert;
const PRTime time;
const uint16_t maxLifetimeInDays;
CertStatus certStatus;
PRTime* thisUpdate;
PRTime* validThrough;
@ -337,6 +340,7 @@ SECStatus
VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
const CERTCertificate* cert,
CERTCertificate* issuerCert, PRTime time,
uint16_t maxOCSPLifetimeInDays,
const SECItem* encodedResponse,
PRTime* thisUpdate,
PRTime* validThrough)
@ -355,9 +359,8 @@ VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
SetErrorToMalformedResponseOnBadDERError();
return SECFailure;
}
Context context(trustDomain, *cert, *issuerCert, time, thisUpdate,
validThrough);
Context context(trustDomain, *cert, *issuerCert, time, maxOCSPLifetimeInDays,
thisUpdate, validThrough);
if (der::Nested(input, der::SEQUENCE,
bind(OCSPResponse, _1, ref(context))) != der::Success) {
@ -672,9 +675,8 @@ SingleResponse(der::Input& input, Context& context)
// be available about the status of the certificate (nextUpdate) is
// greater than the current time.
// 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;
const PRTime maxLifetime =
context.maxLifetimeInDays * ONE_DAY;
PRTime thisUpdate;
if (der::GeneralizedTime(input, thisUpdate) != der::Success) {
@ -699,10 +701,10 @@ SingleResponse(der::Input& input, Context& context)
if (nextUpdate < thisUpdate) {
return der::Fail(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
}
if (nextUpdate - thisUpdate <= OLDEST_ACCEPTABLE) {
if (nextUpdate - thisUpdate <= maxLifetime) {
notAfter = nextUpdate;
} else {
notAfter = thisUpdate + OLDEST_ACCEPTABLE;
notAfter = thisUpdate + maxLifetime;
}
} else {
// NSS requires all OCSP responses without a nextUpdate to be recent.