Bug 1320567 - Certificate Transparency - telemetry reports of CT Policy compliance. r=keeler
MozReview-Commit-ID: GtIz5O3FJ6H
--- a/security/manager/ssl/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/SSLServerCertVerification.cpp
@@ -1266,16 +1266,17 @@ GatherTelemetryForSingleSCT(const ct::Ve
MOZ_ASSERT_UNREACHABLE("Unexpected VerifiedSCT::Status type");
}
Telemetry::Accumulate(Telemetry::SSL_SCTS_VERIFICATION_STATUS,
verificationStatus);
}
void
GatherCertificateTransparencyTelemetry(const UniqueCERTCertList& certList,
+ bool isEV,
const CertificateTransparencyInfo& info)
{
if (!info.enabled) {
// No telemetry is gathered when CT is disabled.
return;
}
for (const ct::VerifiedSCT& sct : info.verifyResult.verifiedScts) {
@@ -1289,16 +1290,69 @@ GatherCertificateTransparencyTelemetry(c
}
// Handle the histogram of SCTs counts.
uint32_t sctsCount =
static_cast<uint32_t>(info.verifyResult.verifiedScts.length());
// Note that sctsCount can also be 0 in case we've received SCT binary data,
// but it failed to parse (e.g. due to unsupported CT protocol version).
Telemetry::Accumulate(Telemetry::SSL_SCTS_PER_CONNECTION, sctsCount);
+
+ // Report CT Policy compliance of EV certificates.
+ if (isEV) {
+ uint32_t evCompliance = 0;
+ switch (info.policyCompliance) {
+ case ct::CTPolicyCompliance::Compliant:
+ evCompliance = 1;
+ break;
+ case ct::CTPolicyCompliance::NotEnoughScts:
+ evCompliance = 2;
+ break;
+ case ct::CTPolicyCompliance::NotDiverseScts:
+ evCompliance = 3;
+ break;
+ case ct::CTPolicyCompliance::Unknown:
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
+ }
+ Telemetry::Accumulate(Telemetry::SSL_CT_POLICY_COMPLIANCE_OF_EV_CERTS,
+ evCompliance);
+ }
+
+ // Get the root cert.
+ CERTCertListNode* rootNode = CERT_LIST_TAIL(certList);
+ MOZ_ASSERT(rootNode);
+ if (!rootNode) {
+ return;
+ }
+ MOZ_ASSERT(!CERT_LIST_END(rootNode, certList));
+ if (CERT_LIST_END(rootNode, certList)) {
+ return;
+ }
+ CERTCertificate* rootCert = rootNode->cert;
+ MOZ_ASSERT(rootCert);
+ if (!rootCert) {
+ return;
+ }
+
+ // Report CT Policy compliance by CA.
+ switch (info.policyCompliance) {
+ case ct::CTPolicyCompliance::Compliant:
+ AccumulateTelemetryForRootCA(
+ Telemetry::SSL_CT_POLICY_COMPLIANT_CONNECTIONS_BY_CA, rootCert);
+ break;
+ case ct::CTPolicyCompliance::NotEnoughScts:
+ case ct::CTPolicyCompliance::NotDiverseScts:
+ AccumulateTelemetryForRootCA(
+ Telemetry::SSL_CT_POLICY_NON_COMPLIANT_CONNECTIONS_BY_CA, rootCert);
+ break;
+ case ct::CTPolicyCompliance::Unknown:
+ default:
+ MOZ_ASSERT_UNREACHABLE("Unexpected CTPolicyCompliance type");
+ }
}
// Note: Takes ownership of |peerCertChain| if SECSuccess is not returned.
SECStatus
AuthCertificate(CertVerifier& certVerifier,
nsNSSSocketInfo* infoObject,
const UniqueCERTCertificate& cert,
UniqueCERTCertList& peerCertChain,
@@ -1373,16 +1427,17 @@ AuthCertificate(CertVerifier& certVerifi
if (rv == Success) {
// Certificate verification succeeded. Delete any potential record of
// certificate error bits.
RememberCertErrorsTable::GetInstance().RememberCertHasError(infoObject,
nullptr,
SECSuccess);
GatherSuccessfulValidationTelemetry(certList);
GatherCertificateTransparencyTelemetry(certList,
+ /*isEV*/ evOidPolicy != SEC_OID_UNKNOWN,
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();
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -8498,16 +8498,43 @@
},
"SSL_CERT_VERIFICATION_ERRORS": {
"alert_emails": ["seceng@mozilla.org"],
"expires_in_version": "default",
"kind": "enumerated",
"n_values": 100,
"description": "If certificate verification failed in a TLS handshake, what was the error? (see MapCertErrorToProbeValue in security/manager/ssl/SSLServerCertVerification.cpp and the values in security/pkix/include/pkix/Result.h)"
},
+ "SSL_CT_POLICY_COMPLIANCE_OF_EV_CERTS": {
+ "alert_emails": ["seceng-telemetry@mozilla.com"],
+ "expires_in_version": "62",
+ "kind": "enumerated",
+ "n_values": 10,
+ "bug_numbers": [1320567],
+ "releaseChannelCollection": "opt-out",
+ "description": "Certificate Transparency Policy compliance of successfully established SSL connections with EV certificate (1=Compliant, 2=Insufficient number of SCTs, 3=Insufficient diversity of CT Log operators)"
+ },
+ "SSL_CT_POLICY_COMPLIANT_CONNECTIONS_BY_CA": {
+ "alert_emails": ["seceng-telemetry@mozilla.com"],
+ "expires_in_version": "never",
+ "kind": "enumerated",
+ "n_values": 256,
+ "bug_numbers": [1320567],
+ "releaseChannelCollection": "opt-out",
+ "description": "Number of successfully established TLS connections compliant with the Certificate Transparency Policy, by CA. See https://dxr.mozilla.org/mozilla-central/source/security/manager/ssl/RootHashes.inc for names of CAs. Bucket zero holds CAs not present in the list."
+ },
+ "SSL_CT_POLICY_NON_COMPLIANT_CONNECTIONS_BY_CA": {
+ "alert_emails": ["seceng-telemetry@mozilla.com"],
+ "expires_in_version": "never",
+ "kind": "enumerated",
+ "n_values": 256,
+ "bug_numbers": [1320567],
+ "releaseChannelCollection": "opt-out",
+ "description": "Number of successfully established TLS connections NOT compliant with the Certificate Transparency Policy, by CA. See https://dxr.mozilla.org/mozilla-central/source/security/manager/ssl/RootHashes.inc for names of CAs. Bucket zero holds CAs not present in the list."
+ },
"SSL_PERMANENT_CERT_ERROR_OVERRIDES": {
"alert_emails": ["seceng@mozilla.org"],
"expires_in_version": "default",
"kind": "exponential",
"high": 1024,
"n_buckets": 10,
"description": "How many permanent certificate overrides a user has stored."
},
--- a/toolkit/components/telemetry/histogram-whitelists.json
+++ b/toolkit/components/telemetry/histogram-whitelists.json
@@ -1821,17 +1821,19 @@
"SSL_CERT_VERIFICATION_ERRORS",
"CERT_VALIDATION_SUCCESS_BY_CA",
"CERT_PINNING_FAILURES_BY_CA",
"CERT_PINNING_MOZ_RESULTS_BY_HOST",
"CERT_PINNING_MOZ_TEST_RESULTS_BY_HOST",
"GFX_CRASH",
"GC_REASON_2",
"GC_MINOR_REASON",
- "GC_MINOR_REASON_LONG"
+ "GC_MINOR_REASON_LONG",
+ "SSL_CT_POLICY_COMPLIANT_CONNECTIONS_BY_CA",
+ "SSL_CT_POLICY_NON_COMPLIANT_CONNECTIONS_BY_CA"
],
"expiry_default": [
"A11Y_CONSUMERS",
"IDLE_NOTIFY_IDLE_MS",
"CACHE_MEMORY_SEARCH_2",
"OSFILE_WORKER_LAUNCH_MS",
"GEOLOCATION_OSX_SOURCE_IS_MLS",
"TRANSLATION_OPPORTUNITIES_BY_LANGUAGE",