bug 1313491 - include more context when determining EV status r?Cykesiopka,jcj,mgoodwin
When doing TLS session resumption, the AuthCertificate hook is bypassed, which
means that the front-end doesn't know whether or not to show the EV indicator.
To deal with this, the platform attempts an EV verification. Before this patch,
this verification lacked much of the original context (e.g. stapled OCSP
responses, SCTs, the hostname, and in particular the first-party origin key).
Furthermore, it was unclear from a code architecture standpoint that a full
verification was even occurring. This patch brings the necessary context to the
verification and makes it much more clear that it is happening. It also takes
the opportunity to remove some unnecessary EV-related fields and information in
code and data structures that don't require it.
MozReview-Commit-ID: LTmZU4Z1YXL
--- a/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
+++ b/security/manager/locales/en-US/chrome/pipnss/pipnss.properties
@@ -167,17 +167,16 @@ CertDumpKeyCompromise=Key Compromise
CertDumpCACompromise=CA Compromise
CertDumpAffiliationChanged=Affiliation Changed
CertDumpSuperseded=Superseded
CertDumpCessation=Cessation of Operation
CertDumpHold=Certificate Hold
CertDumpOCSPResponder=OCSP
CertDumpCAIssuers=CA Issuers
CertDumpCPSPointer=Certification Practice Statement pointer
-CertDumpPolicyOidEV=Extended Validation (EV) SSL Server Certificate
CertDumpUserNotice=User Notice
CertDumpLogotype=Logotype
CertDumpECPublicKey=Elliptic Curve Public Key
CertDumpECDSAWithSHA1=X9.62 ECDSA Signature with SHA1
CertDumpECprime192v1=ANSI X9.62 elliptic curve prime192v1 (aka secp192r1, NIST P-192)
CertDumpECprime192v2=ANSI X9.62 elliptic curve prime192v2
CertDumpECprime192v3=ANSI X9.62 elliptic curve prime192v3
CertDumpECprime239v1=ANSI X9.62 elliptic curve prime239v1
--- a/security/manager/ssl/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/SSLServerCertVerification.cpp
@@ -99,35 +99,40 @@
#include "BRNameMatchingPolicy.h"
#include "CertVerifier.h"
#include "CryptoTask.h"
#include "ExtendedValidation.h"
#include "NSSCertDBTrustDomain.h"
#include "PSMRunnable.h"
#include "RootCertificateTelemetryUtils.h"
#include "ScopedNSSTypes.h"
+#include "SharedCertVerifier.h"
#include "SharedSSLState.h"
+#include "TransportSecurityInfo.h" // For RememberCertErrorsTable
#include "cert.h"
#include "mozilla/Assertions.h"
#include "mozilla/Casting.h"
#include "mozilla/Mutex.h"
+#include "mozilla/RefPtr.h"
#include "mozilla/Telemetry.h"
#include "mozilla/UniquePtr.h"
+#include "mozilla/Unused.h"
#include "mozilla/net/DNS.h"
-#include "mozilla/Unused.h"
#include "nsComponentManagerUtils.h"
#include "nsContentUtils.h"
#include "nsIBadCertListener2.h"
#include "nsICertOverrideService.h"
#include "nsISiteSecurityService.h"
#include "nsISocketProvider.h"
#include "nsIThreadPool.h"
+#include "nsNSSCertificate.h"
#include "nsNSSComponent.h"
#include "nsNSSIOLayer.h"
#include "nsNSSShutDown.h"
+#include "nsSSLStatus.h"
#include "nsServiceManagerUtils.h"
#include "nsURLHelper.h"
#include "nsXPCOMCIDInternal.h"
#include "pkix/pkix.h"
#include "pkix/pkixnss.h"
#include "secerr.h"
#include "secoidt.h"
#include "secport.h"
@@ -1364,63 +1369,47 @@ AuthCertificate(CertVerifier& certVerifi
pinningTelemetryInfo.rootBucket);
}
if (pinningTelemetryInfo.accumulateResult) {
Telemetry::Accumulate(pinningTelemetryInfo.certPinningResultHistogram,
pinningTelemetryInfo.certPinningResultBucket);
}
- RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
- RefPtr<nsNSSCertificate> nsc;
-
- if (!status || !status->HasServerCert()) {
- if (rv == Success) {
- nsc = nsNSSCertificate::Create(cert.get(), &evOidPolicy);
- } else {
- nsc = nsNSSCertificate::Create(cert.get());
- }
- }
-
if (rv == Success) {
+ // Certificate verification succeeded. Delete any potential record of
+ // certificate error bits.
+ RememberCertErrorsTable::GetInstance().RememberCertHasError(infoObject,
+ nullptr,
+ SECSuccess);
GatherSuccessfulValidationTelemetry(certList);
GatherCertificateTransparencyTelemetry(certList,
certificateTransparencyInfo);
// The connection may get terminated, for example, if the server requires
// a client cert. Let's provide a minimal SSLStatus
// to the caller that contains at least the cert and its status.
+ RefPtr<nsSSLStatus> status(infoObject->SSLStatus());
if (!status) {
status = new nsSSLStatus();
infoObject->SetSSLStatus(status);
}
- if (rv == Success) {
- // Certificate verification succeeded delete any potential record
- // of certificate error bits.
- RememberCertErrorsTable::GetInstance().RememberCertHasError(infoObject,
- nullptr,
- SECSuccess);
- } else {
- // Certificate verification failed, update the status' bits.
- RememberCertErrorsTable::GetInstance().LookupCertErrorBits(
- infoObject, status);
- }
-
- if (status && !status->HasServerCert()) {
- nsNSSCertificate::EVStatus evStatus;
- if (evOidPolicy == SEC_OID_UNKNOWN || rv != Success) {
- evStatus = nsNSSCertificate::ev_status_invalid;
+ if (!status->HasServerCert()) {
+ EVStatus evStatus;
+ if (evOidPolicy == SEC_OID_UNKNOWN) {
+ evStatus = EVStatus::NotEV;
} else {
- evStatus = nsNSSCertificate::ev_status_valid;
+ evStatus = EVStatus::EV;
}
+ RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(cert.get());
status->SetServerCert(nsc, evStatus);
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
- ("AuthCertificate setting NEW cert %p\n", nsc.get()));
+ ("AuthCertificate setting NEW cert %p", nsc.get()));
}
status->SetCertificateTransparencyInfo(certificateTransparencyInfo);
}
if (rv != Success) {
// Certificate validation failed; store the peer certificate chain on
// infoObject so it can be used for error reporting.
--- a/security/manager/ssl/TransportSecurityInfo.cpp
+++ b/security/manager/ssl/TransportSecurityInfo.cpp
@@ -1051,17 +1051,17 @@ TransportSecurityInfo::SetStatusErrorBit
uint32_t collected_errors)
{
MutexAutoLock lock(mMutex);
if (!mSSLStatus) {
mSSLStatus = new nsSSLStatus();
}
- mSSLStatus->SetServerCert(cert, nsNSSCertificate::ev_status_invalid);
+ mSSLStatus->SetServerCert(cert, EVStatus::NotEV);
mSSLStatus->mHaveCertErrorBits = true;
mSSLStatus->mIsDomainMismatch =
collected_errors & nsICertOverrideService::ERROR_MISMATCH;
mSSLStatus->mIsNotValidAtThisTime =
collected_errors & nsICertOverrideService::ERROR_TIME;
mSSLStatus->mIsUntrusted =
collected_errors & nsICertOverrideService::ERROR_UNTRUSTED;
--- a/security/manager/ssl/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/nsNSSCallbacks.cpp
@@ -1,39 +1,42 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsNSSCallbacks.h"
+#include "PSMRunnable.h"
+#include "ScopedNSSTypes.h"
+#include "SharedCertVerifier.h"
+#include "SharedSSLState.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Casting.h"
+#include "mozilla/RefPtr.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Unused.h"
#include "nsContentUtils.h"
#include "nsICertOverrideService.h"
#include "nsIHttpChannelInternal.h"
#include "nsIPrompt.h"
#include "nsISupportsPriority.h"
#include "nsITokenDialogs.h"
#include "nsIUploadChannel.h"
#include "nsIWebProgressListener.h"
-#include "nsNetUtil.h"
+#include "nsNSSCertificate.h"
#include "nsNSSComponent.h"
#include "nsNSSIOLayer.h"
+#include "nsNetUtil.h"
#include "nsProtectedAuthThread.h"
#include "nsProxyRelease.h"
#include "pkix/pkixtypes.h"
-#include "PSMRunnable.h"
-#include "ScopedNSSTypes.h"
-#include "SharedSSLState.h"
#include "ssl.h"
#include "sslproto.h"
using namespace mozilla;
using namespace mozilla::psm;
extern LazyLogModule gPIPNSSLog;
@@ -1078,16 +1081,99 @@ AccumulateCipherSuite(Telemetry::ID prob
default:
value = 0;
break;
}
MOZ_ASSERT(value != 0);
Telemetry::Accumulate(probe, value);
}
+// In the case of session resumption, the AuthCertificate hook has been bypassed
+// (because we've previously successfully connected to our peer). That being the
+// case, we unfortunately don't know if the peer's server certificate verified
+// as extended validation or not. To address this, we attempt to build a
+// verified EV certificate chain here using as much of the original context as
+// possible (e.g. stapled OCSP responses, SCTs, the hostname, the first party
+// domain, etc.). Note that because we are on the socket thread, this must not
+// cause any network requests, hence the use of FLAG_LOCAL_ONLY.
+static void
+DetermineEVStatusAndSetNewCert(RefPtr<nsSSLStatus> sslStatus, PRFileDesc* fd,
+ nsNSSSocketInfo* infoObject)
+{
+ MOZ_ASSERT(sslStatus);
+ MOZ_ASSERT(fd);
+ MOZ_ASSERT(infoObject);
+
+ if (!sslStatus || !fd || !infoObject) {
+ return;
+ }
+
+ UniqueCERTCertificate cert(SSL_PeerCertificate(fd));
+ MOZ_ASSERT(cert, "SSL_PeerCertificate failed in TLS handshake callback?");
+ if (!cert) {
+ return;
+ }
+
+ RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
+ MOZ_ASSERT(certVerifier,
+ "Certificate verifier uninitialized in TLS handshake callback?");
+ if (!certVerifier) {
+ return;
+ }
+
+ // We don't own these pointers.
+ const SECItemArray* stapledOCSPResponses = SSL_PeerStapledOCSPResponses(fd);
+ const SECItem* stapledOCSPResponse = nullptr;
+ // we currently only support single stapled responses
+ if (stapledOCSPResponses && stapledOCSPResponses->len == 1) {
+ stapledOCSPResponse = &stapledOCSPResponses->items[0];
+ }
+ const SECItem* sctsFromTLSExtension = SSL_PeerSignedCertTimestamps(fd);
+ if (sctsFromTLSExtension && sctsFromTLSExtension->len == 0) {
+ // SSL_PeerSignedCertTimestamps returns null on error and empty item
+ // when no extension was returned by the server. We always use null when
+ // no extension was received (for whatever reason), ignoring errors.
+ sctsFromTLSExtension = nullptr;
+ }
+
+ int flags = mozilla::psm::CertVerifier::FLAG_LOCAL_ONLY |
+ mozilla::psm::CertVerifier::FLAG_MUST_BE_EV;
+ if (!infoObject->SharedState().IsOCSPStaplingEnabled() ||
+ !infoObject->SharedState().IsOCSPMustStapleEnabled()) {
+ flags |= CertVerifier::FLAG_TLS_IGNORE_STATUS_REQUEST;
+ }
+
+ SECOidTag evOidPolicy;
+ UniqueCERTCertList unusedBuiltChain;
+ const bool saveIntermediates = false;
+ mozilla::pkix::Result rv = certVerifier->VerifySSLServerCert(
+ cert,
+ stapledOCSPResponse,
+ sctsFromTLSExtension,
+ mozilla::pkix::Now(),
+ infoObject,
+ infoObject->GetHostNameRaw(),
+ unusedBuiltChain,
+ saveIntermediates,
+ flags,
+ infoObject->GetFirstPartyDomainRaw(),
+ &evOidPolicy);
+
+ RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(cert.get()));
+ if (rv == Success && evOidPolicy != SEC_OID_UNKNOWN) {
+ MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
+ ("HandshakeCallback using NEW cert %p (is EV)", nssc.get()));
+ sslStatus->SetServerCert(nssc, EVStatus::EV);
+ } else {
+ MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
+ ("HandshakeCallback using NEW cert %p (is not EV)", nssc.get()));
+ sslStatus->SetServerCert(nssc, EVStatus::NotEV);
+ }
+}
+
void HandshakeCallback(PRFileDesc* fd, void* client_data) {
nsNSSShutDownPreventionLock locker;
SECStatus rv;
nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
// Do the bookkeeping that needs to be done after the
// server's ServerHello...ServerHelloDone have been processed, but that doesn't
@@ -1231,21 +1317,17 @@ void HandshakeCallback(PRFileDesc* fd, v
}
}
}
if (status->HasServerCert()) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("HandshakeCallback KEEPING existing cert\n"));
} else {
- UniqueCERTCertificate serverCert(SSL_PeerCertificate(fd));
- RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(serverCert.get()));
- MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
- ("HandshakeCallback using NEW cert %p\n", nssc.get()));
- status->SetServerCert(nssc, nsNSSCertificate::ev_status_unknown);
+ DetermineEVStatusAndSetNewCert(status, fd, infoObject);
}
bool domainMismatch;
bool untrusted;
bool notValidAtThisTime;
// These all return NS_OK, so don't even bother checking the return values.
Unused << status->GetIsDomainMismatch(&domainMismatch);
Unused << status->GetIsUntrusted(&untrusted);
--- a/security/manager/ssl/nsNSSCertHelper.cpp
+++ b/security/manager/ssl/nsNSSCertHelper.cpp
@@ -1228,17 +1228,16 @@ ProcessUserNotice(SECItem* derNotice, ns
}
return NS_OK;
}
static nsresult
ProcessCertificatePolicies(SECItem *extData,
nsAString &text,
- SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
nsINSSComponent *nssComponent)
{
CERTPolicyInfo **policyInfos, *policyInfo;
CERTPolicyQualifier **policyQualifiers, *policyQualifier;
nsAutoString local;
nsresult rv = NS_OK;
UniqueCERTCertificatePolicies policies(
@@ -1255,36 +1254,20 @@ ProcessCertificatePolicies(SECItem *ext
nssComponent->GetPIPNSSBundleString("CertDumpVerisignNotices", local);
text.Append(local);
break;
default:
GetDefaultOIDFormat(&policyInfo->policyID, nssComponent, local, '.');
text.Append(local);
}
- bool needColon = true;
- if (ev_oid_tag != SEC_OID_UNKNOWN) {
- // This is an EV cert. Let's see if this oid is the EV oid,
- // because we want to display the EV information string
- // next to the correct OID.
-
- if (policyInfo->oid == ev_oid_tag) {
- text.Append(':');
- text.AppendLiteral(SEPARATOR);
- needColon = false;
- nssComponent->GetPIPNSSBundleString("CertDumpPolicyOidEV", local);
- text.Append(local);
- }
- }
-
if (policyInfo->policyQualifiers) {
/* Add all qualifiers on separate lines, indented */
policyQualifiers = policyInfo->policyQualifiers;
- if (needColon)
- text.Append(':');
+ text.Append(':');
text.AppendLiteral(SEPARATOR);
while (*policyQualifiers) {
text.AppendLiteral(" ");
policyQualifier = *policyQualifiers++;
switch(policyQualifier->oid) {
case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
nssComponent->GetPIPNSSBundleString("CertDumpCPSPointer", local);
text.Append(local);
@@ -1495,17 +1478,16 @@ ProcessMSCAVersion(SECItem *extData,
text.AppendASCII(buf);
return NS_OK;
}
static nsresult
ProcessExtensionData(SECOidTag oidTag, SECItem *extData,
nsAString &text,
- SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
nsINSSComponent *nssComponent)
{
nsresult rv;
switch (oidTag) {
case SEC_OID_X509_KEY_USAGE:
rv = ProcessKeyUsageExtension(extData, text, nssComponent);
break;
case SEC_OID_X509_BASIC_CONSTRAINTS:
@@ -1520,17 +1502,17 @@ ProcessExtensionData(SECOidTag oidTag, S
break;
case SEC_OID_X509_SUBJECT_KEY_ID:
rv = ProcessSubjectKeyId(extData, text, nssComponent);
break;
case SEC_OID_X509_AUTH_KEY_ID:
rv = ProcessAuthKeyId(extData, text, nssComponent);
break;
case SEC_OID_X509_CERTIFICATE_POLICIES:
- rv = ProcessCertificatePolicies(extData, text, ev_oid_tag, nssComponent);
+ rv = ProcessCertificatePolicies(extData, text, nssComponent);
break;
case SEC_OID_X509_CRL_DIST_POINTS:
rv = ProcessCrlDistPoints(extData, text, nssComponent);
break;
case SEC_OID_X509_AUTH_INFO_ACCESS:
rv = ProcessAuthInfoAccess(extData, text, nssComponent);
break;
default:
@@ -1545,17 +1527,16 @@ ProcessExtensionData(SECOidTag oidTag, S
rv = ProcessRawBytes(nssComponent, extData, text);
break;
}
return rv;
}
static nsresult
ProcessSingleExtension(CERTCertExtension *extension,
- SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
nsINSSComponent *nssComponent,
nsIASN1PrintableItem **retExtension)
{
nsAutoString text, extvalue;
GetOIDText(&extension->id, nssComponent, text);
nsCOMPtr<nsIASN1PrintableItem>extensionItem = new nsNSSASN1PrintableItem();
extensionItem->SetDisplayName(text);
@@ -1567,17 +1548,17 @@ ProcessSingleExtension(CERTCertExtension
} else {
nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
}
} else {
nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
}
text.AppendLiteral(SEPARATOR);
nsresult rv = ProcessExtensionData(oidTag, &extension->value, extvalue,
- ev_oid_tag, nssComponent);
+ nssComponent);
if (NS_FAILED(rv)) {
extvalue.Truncate();
rv = ProcessRawBytes(nssComponent, &extension->value, extvalue, false);
}
text.Append(extvalue);
extensionItem->SetDisplayValue(text);
extensionItem.forget(retExtension);
@@ -1763,32 +1744,30 @@ ProcessSubjectPublicKeyInfo(CERTSubjectP
parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
asn1Objects->AppendElement(spkiSequence, false);
return NS_OK;
}
static nsresult
ProcessExtensions(CERTCertExtension **extensions,
nsIASN1Sequence *parentSequence,
- SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
nsINSSComponent *nssComponent)
{
nsCOMPtr<nsIASN1Sequence> extensionSequence = new nsNSSASN1Sequence;
nsString text;
nssComponent->GetPIPNSSBundleString("CertDumpExtensions", text);
extensionSequence->SetDisplayName(text);
int32_t i;
nsresult rv;
nsCOMPtr<nsIASN1PrintableItem> newExtension;
nsCOMPtr<nsIMutableArray> asn1Objects;
extensionSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
for (i=0; extensions[i] != nullptr; i++) {
rv = ProcessSingleExtension(extensions[i],
- ev_oid_tag,
nssComponent,
getter_AddRefs(newExtension));
if (NS_FAILED(rv))
return rv;
asn1Objects->AppendElement(newExtension, false);
}
parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
@@ -1961,29 +1940,17 @@ nsNSSCertificate::CreateTBSCertificateAS
printableItem->SetDisplayValue(text);
nssComponent->GetPIPNSSBundleString("CertDumpSubjectUniqueID", text);
printableItem->SetDisplayName(text);
asn1Objects->AppendElement(printableItem, false);
}
if (mCert->extensions) {
- SECOidTag ev_oid_tag = SEC_OID_UNKNOWN;
-
- bool validEV;
- rv = hasValidEVOidTag(ev_oid_tag, validEV);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- if (!validEV) {
- ev_oid_tag = SEC_OID_UNKNOWN;
- }
-
- rv = ProcessExtensions(mCert->extensions, sequence, ev_oid_tag, nssComponent);
+ rv = ProcessExtensions(mCert->extensions, sequence, nssComponent);
if (NS_FAILED(rv))
return rv;
}
sequence.forget(retSequence);
return NS_OK;
}
nsresult
--- a/security/manager/ssl/nsNSSCertificate.cpp
+++ b/security/manager/ssl/nsNSSCertificate.cpp
@@ -65,24 +65,24 @@ extern LazyLogModule gPIPNSSLog;
NS_IMPL_ISUPPORTS(nsNSSCertificate,
nsIX509Cert,
nsISerializable,
nsIClassInfo)
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
/*static*/ nsNSSCertificate*
-nsNSSCertificate::Create(CERTCertificate* cert, SECOidTag* evOidPolicy)
+nsNSSCertificate::Create(CERTCertificate* cert)
{
if (GeckoProcessType_Default != XRE_GetProcessType()) {
NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
return nullptr;
}
if (cert)
- return new nsNSSCertificate(cert, evOidPolicy);
+ return new nsNSSCertificate(cert);
else
return new nsNSSCertificate();
}
nsNSSCertificate*
nsNSSCertificate::ConstructFromDER(char* certDER, int derLen)
{
// On non-chrome process prevent instantiation
@@ -117,51 +117,39 @@ nsNSSCertificate::InitFromDER(char* cert
{
aCert->dbhandle = CERT_GetDefaultCertDB();
}
mCert.reset(aCert);
return true;
}
-nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert,
- SECOidTag* evOidPolicy)
+nsNSSCertificate::nsNSSCertificate(CERTCertificate* cert)
: mCert(nullptr)
, mPermDelete(false)
, mCertType(CERT_TYPE_NOT_YET_INITIALIZED)
- , mCachedEVStatus(ev_status_unknown)
{
#if defined(DEBUG)
if (GeckoProcessType_Default != XRE_GetProcessType())
NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
#endif
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return;
if (cert) {
mCert.reset(CERT_DupCertificate(cert));
- if (evOidPolicy) {
- if (*evOidPolicy == SEC_OID_UNKNOWN) {
- mCachedEVStatus = ev_status_invalid;
- }
- else {
- mCachedEVStatus = ev_status_valid;
- }
- mCachedEVOidTag = *evOidPolicy;
- }
}
}
-nsNSSCertificate::nsNSSCertificate() :
- mCert(nullptr),
- mPermDelete(false),
- mCertType(CERT_TYPE_NOT_YET_INITIALIZED),
- mCachedEVStatus(ev_status_unknown)
+nsNSSCertificate::nsNSSCertificate()
+ : mCert(nullptr)
+ , mPermDelete(false)
+ , mCertType(CERT_TYPE_NOT_YET_INITIALIZED)
{
if (GeckoProcessType_Default != XRE_GetProcessType())
NS_ERROR("Trying to initialize nsNSSCertificate in a non-chrome process!");
}
nsNSSCertificate::~nsNSSCertificate()
{
nsNSSShutDownPreventionLock locker;
@@ -1129,95 +1117,16 @@ nsNSSCertificate::Equals(nsIX509Cert* ot
NS_ENSURE_ARG(other);
NS_ENSURE_ARG(result);
UniqueCERTCertificate cert(other->GetCert());
*result = (mCert.get() == cert.get());
return NS_OK;
}
-nsresult
-nsNSSCertificate::hasValidEVOidTag(SECOidTag& resultOidTag, bool& validEV)
-{
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- RefPtr<mozilla::psm::SharedCertVerifier>
- certVerifier(mozilla::psm::GetDefaultCertVerifier());
- NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
-
- validEV = false;
- resultOidTag = SEC_OID_UNKNOWN;
-
- uint32_t flags = mozilla::psm::CertVerifier::FLAG_LOCAL_ONLY |
- mozilla::psm::CertVerifier::FLAG_MUST_BE_EV;
- UniqueCERTCertList unusedBuiltChain;
- mozilla::pkix::Result result = certVerifier->VerifyCert(mCert.get(),
- certificateUsageSSLServer, mozilla::pkix::Now(),
- nullptr /* XXX pinarg */,
- nullptr /* hostname */,
- unusedBuiltChain,
- flags,
- nullptr /* stapledOCSPResponse */,
- nullptr /* sctsFromTLSExtension */,
- nullptr /* firstPartyDomain */,
- &resultOidTag);
-
- if (result != mozilla::pkix::Success) {
- resultOidTag = SEC_OID_UNKNOWN;
- }
- if (resultOidTag != SEC_OID_UNKNOWN) {
- validEV = true;
- }
- return NS_OK;
-}
-
-nsresult
-nsNSSCertificate::getValidEVOidTag(SECOidTag& resultOidTag, bool& validEV)
-{
- if (mCachedEVStatus != ev_status_unknown) {
- validEV = (mCachedEVStatus == ev_status_valid);
- if (validEV) {
- resultOidTag = mCachedEVOidTag;
- }
- return NS_OK;
- }
-
- nsresult rv = hasValidEVOidTag(resultOidTag, validEV);
- if (NS_SUCCEEDED(rv)) {
- if (validEV) {
- mCachedEVOidTag = resultOidTag;
- }
- mCachedEVStatus = validEV ? ev_status_valid : ev_status_invalid;
- }
- return rv;
-}
-
-nsresult
-nsNSSCertificate::GetIsExtendedValidation(bool* aIsEV)
-{
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- NS_ENSURE_ARG(aIsEV);
- *aIsEV = false;
-
- if (mCachedEVStatus != ev_status_unknown) {
- *aIsEV = (mCachedEVStatus == ev_status_valid);
- return NS_OK;
- }
-
- SECOidTag oid_tag;
- return getValidEVOidTag(oid_tag, *aIsEV);
-}
-
namespace mozilla {
// TODO(bug 1036065): It seems like we only construct CERTCertLists for the
// purpose of constructing nsNSSCertLists, so maybe we should change this
// function to output an nsNSSCertList instead.
SECStatus
ConstructCERTCertListFromReversedDERArray(
const mozilla::pkix::DERArray& certArray,
@@ -1623,46 +1532,39 @@ nsNSSCertListEnumerator::GetNext(nsISupp
return NS_OK;
}
// NB: This serialization must match that of nsNSSCertificateFakeTransport.
NS_IMETHODIMP
nsNSSCertificate::Write(nsIObjectOutputStream* aStream)
{
NS_ENSURE_STATE(mCert);
- nsresult rv = aStream->Write32(static_cast<uint32_t>(mCachedEVStatus));
+ // This field used to be the cached EV status, but it is no longer necessary.
+ nsresult rv = aStream->Write32(0);
if (NS_FAILED(rv)) {
return rv;
}
rv = aStream->Write32(mCert->derCert.len);
if (NS_FAILED(rv)) {
return rv;
}
return aStream->WriteByteArray(mCert->derCert.data, mCert->derCert.len);
}
NS_IMETHODIMP
nsNSSCertificate::Read(nsIObjectInputStream* aStream)
{
NS_ENSURE_STATE(!mCert);
- uint32_t cachedEVStatus;
- nsresult rv = aStream->Read32(&cachedEVStatus);
+ // This field is no longer used.
+ uint32_t unusedCachedEVStatus;
+ nsresult rv = aStream->Read32(&unusedCachedEVStatus);
if (NS_FAILED(rv)) {
return rv;
}
- if (cachedEVStatus == static_cast<uint32_t>(ev_status_unknown)) {
- mCachedEVStatus = ev_status_unknown;
- } else if (cachedEVStatus == static_cast<uint32_t>(ev_status_valid)) {
- mCachedEVStatus = ev_status_valid;
- } else if (cachedEVStatus == static_cast<uint32_t>(ev_status_invalid)) {
- mCachedEVStatus = ev_status_invalid;
- } else {
- return NS_ERROR_UNEXPECTED;
- }
uint32_t len;
rv = aStream->Read32(&len);
if (NS_FAILED(rv)) {
return rv;
}
nsXPIDLCString str;
--- a/security/manager/ssl/nsNSSCertificate.h
+++ b/security/manager/ssl/nsNSSCertificate.h
@@ -32,28 +32,20 @@ class nsNSSCertificate final : public ns
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIX509CERT
NS_DECL_NSISERIALIZABLE
NS_DECL_NSICLASSINFO
friend class nsNSSCertificateFakeTransport;
- explicit nsNSSCertificate(CERTCertificate* cert, SECOidTag* evOidPolicy = nullptr);
+ explicit nsNSSCertificate(CERTCertificate* cert);
nsNSSCertificate();
- static nsNSSCertificate* Create(CERTCertificate*cert = nullptr,
- SECOidTag* evOidPolicy = nullptr);
+ static nsNSSCertificate* Create(CERTCertificate* cert = nullptr);
static nsNSSCertificate* ConstructFromDER(char* certDER, int derLen);
- nsresult GetIsExtendedValidation(bool* aIsEV);
-
- enum EVStatus {
- ev_status_invalid = 0,
- ev_status_valid = 1,
- ev_status_unknown = 2
- };
// This is a separate static method so nsNSSComponent can use it during NSS
// initialization. Other code should probably not use it.
static nsresult GetDbKey(const mozilla::UniqueCERTCertificate& cert,
nsACString& aDbKey);
private:
virtual ~nsNSSCertificate();
@@ -65,21 +57,16 @@ private:
nsresult CreateTBSCertificateASN1Struct(nsIASN1Sequence** retSequence,
nsINSSComponent* nssComponent);
nsresult GetSortableDate(PRTime aTime, nsAString& _aSortableDate);
virtual void virtualDestroyNSSReference() override;
void destructorSafeDestroyNSSReference();
bool InitFromDER(char* certDER, int derLen); // return false on failure
nsresult GetCertificateHash(nsAString& aFingerprint, SECOidTag aHashAlg);
-
- EVStatus mCachedEVStatus;
- SECOidTag mCachedEVOidTag;
- nsresult hasValidEVOidTag(SECOidTag& resultOidTag, bool& validEV);
- nsresult getValidEVOidTag(SECOidTag& resultOidTag, bool& validEV);
};
namespace mozilla {
SECStatus ConstructCERTCertListFromReversedDERArray(
const mozilla::pkix::DERArray& certArray,
/*out*/ mozilla::UniqueCERTCertList& certList);
--- a/security/manager/ssl/nsNSSCertificateFakeTransport.cpp
+++ b/security/manager/ssl/nsNSSCertificateFakeTransport.cpp
@@ -213,40 +213,39 @@ nsNSSCertificateFakeTransport::GetSha256
// NB: This serialization must match that of nsNSSCertificate.
NS_IMETHODIMP
nsNSSCertificateFakeTransport::Write(nsIObjectOutputStream* aStream)
{
// On a non-chrome process we don't have mCert because we lack
// nsNSSComponent. nsNSSCertificateFakeTransport object is used only to
// carry the certificate serialization.
- // This serialization has to match that of nsNSSCertificate,
- // so write a fake cached EV Status.
- uint32_t status = static_cast<uint32_t>(nsNSSCertificate::ev_status_unknown);
- nsresult rv = aStream->Write32(status);
+ // This serialization has to match that of nsNSSCertificate, so include this
+ // now-unused field.
+ nsresult rv = aStream->Write32(0);
if (NS_FAILED(rv)) {
return rv;
}
rv = aStream->Write32(mCertSerialization->len);
if (NS_FAILED(rv)) {
return rv;
}
return aStream->WriteByteArray(mCertSerialization->data,
mCertSerialization->len);
}
NS_IMETHODIMP
nsNSSCertificateFakeTransport::Read(nsIObjectInputStream* aStream)
{
- // This serialization has to match that of nsNSSCertificate,
- // so read the cachedEVStatus but don't actually use it.
- uint32_t cachedEVStatus;
- nsresult rv = aStream->Read32(&cachedEVStatus);
+ // This serialization has to match that of nsNSSCertificate, so read the (now
+ // unused) cachedEVStatus.
+ uint32_t unusedCachedEVStatus;
+ nsresult rv = aStream->Read32(&unusedCachedEVStatus);
if (NS_FAILED(rv)) {
return rv;
}
uint32_t len;
rv = aStream->Read32(&len);
if (NS_FAILED(rv)) {
return rv;
--- a/security/manager/ssl/nsSSLStatus.cpp
+++ b/security/manager/ssl/nsSSLStatus.cpp
@@ -1,20 +1,20 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Casting.h"
#include "nsSSLStatus.h"
-#include "plstr.h"
#include "nsIClassInfoImpl.h"
#include "nsIObjectOutputStream.h"
#include "nsIObjectInputStream.h"
+#include "nsNSSCertificate.h"
#include "SignedCertificateTimestamp.h"
#include "ssl.h"
NS_IMETHODIMP
nsSSLStatus::GetServerCert(nsIX509Cert** aServerCert)
{
NS_ENSURE_ARG_POINTER(aServerCert);
@@ -312,34 +312,23 @@ nsSSLStatus::nsSSLStatus()
NS_IMPL_ISUPPORTS(nsSSLStatus, nsISSLStatus, nsISerializable, nsIClassInfo)
nsSSLStatus::~nsSSLStatus()
{
}
void
-nsSSLStatus::SetServerCert(nsNSSCertificate* aServerCert,
- nsNSSCertificate::EVStatus aEVStatus)
+nsSSLStatus::SetServerCert(nsNSSCertificate* aServerCert, EVStatus aEVStatus)
{
- mServerCert = aServerCert;
+ MOZ_ASSERT(aServerCert);
- if (aEVStatus != nsNSSCertificate::ev_status_unknown) {
- mIsEV = (aEVStatus == nsNSSCertificate::ev_status_valid);
- mHasIsEVStatus = true;
- return;
- }
-
- if (aServerCert) {
- nsresult rv = aServerCert->GetIsExtendedValidation(&mIsEV);
- if (NS_FAILED(rv)) {
- return;
- }
- mHasIsEVStatus = true;
- }
+ mServerCert = aServerCert;
+ mIsEV = (aEVStatus == EVStatus::EV);
+ mHasIsEVStatus = true;
}
void
nsSSLStatus::SetCertificateTransparencyInfo(
const mozilla::psm::CertificateTransparencyInfo& info)
{
using mozilla::ct::SignedCertificateTimestamp;
--- a/security/manager/ssl/nsSSLStatus.h
+++ b/security/manager/ssl/nsSSLStatus.h
@@ -9,35 +9,40 @@
#include "CertVerifier.h" // For CertificateTransparencyInfo
#include "nsISSLStatus.h"
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsIX509Cert.h"
#include "nsISerializable.h"
#include "nsIClassInfo.h"
-#include "nsNSSCertificate.h" // For EVStatus
+
+class nsNSSCertificate;
+
+enum class EVStatus {
+ NotEV = 0,
+ EV = 1,
+};
class nsSSLStatus final
: public nsISSLStatus
, public nsISerializable
, public nsIClassInfo
{
protected:
virtual ~nsSSLStatus();
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSISSLSTATUS
NS_DECL_NSISERIALIZABLE
NS_DECL_NSICLASSINFO
nsSSLStatus();
- void SetServerCert(nsNSSCertificate* aServerCert,
- nsNSSCertificate::EVStatus aEVStatus);
+ void SetServerCert(nsNSSCertificate* aServerCert, EVStatus aEVStatus);
bool HasServerCert() {
return mServerCert != nullptr;
}
void SetCertificateTransparencyInfo(
const mozilla::psm::CertificateTransparencyInfo& info);