Bug 1196039 - Telemetry for certificate lifetime. r=rbarnes,vladan
authorKate McKinley <kmckinley@mozilla.com>
Thu, 17 Sep 2015 10:04:52 -0700
changeset 295814 2955c61e6ecfcf8ee76272191fdcb190c6d97951
parent 295813 dc1cbf8e88a97e00e9daeaa6b7fd279d40cbd016
child 295815 58e036ba3d666dfad9e0d6d7bc3958d33236669a
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrbarnes, vladan
bugs1196039
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1196039 - Telemetry for certificate lifetime. r=rbarnes,vladan
security/manager/ssl/SSLServerCertVerification.cpp
toolkit/components/telemetry/Histograms.json
--- a/security/manager/ssl/SSLServerCertVerification.cpp
+++ b/security/manager/ssl/SSLServerCertVerification.cpp
@@ -1138,24 +1138,69 @@ GatherRootCATelemetry(const ScopedCERTCe
   PR_ASSERT(rootCert);
   if (!rootCert) {
     return;
   }
   AccumulateTelemetryForRootCA(Telemetry::CERT_VALIDATION_SUCCESS_BY_CA,
                                rootCert);
 }
 
+// These time are appoximate, i.e., doesn't account for leap seconds, etc
+const uint64_t ONE_WEEK_IN_SECONDS = (7 * (24 * 60 *60));
+const uint64_t ONE_YEAR_IN_WEEKS   = 52;
+
+// Gathers telemetry on the certificate lifetimes we observe in the wild
+void
+GatherEndEntityTelemetry(const ScopedCERTCertList& certList)
+{
+  CERTCertListNode* endEntityNode = CERT_LIST_HEAD(certList);
+  PR_ASSERT(endEntityNode);
+  if (!endEntityNode) {
+    return;
+  }
+
+  CERTCertificate * endEntityCert = endEntityNode->cert;
+  PR_ASSERT(endEntityCert);
+  if (!endEntityCert) {
+    return;
+  }
+
+  PRTime notBefore;
+  PRTime notAfter;
+
+  if (CERT_GetCertTimes(endEntityCert, &notBefore, &notAfter) != SECSuccess) {
+    return;
+  }
+
+  PR_ASSERT(notAfter > notBefore);
+  if (notAfter <= notBefore) {
+    return;
+  }
+
+  uint64_t durationInWeeks = (notAfter - notBefore)
+    / PR_USEC_PER_SEC
+    / ONE_WEEK_IN_SECONDS;
+
+  if (durationInWeeks > (2 * ONE_YEAR_IN_WEEKS)) {
+    durationInWeeks = (2 * ONE_YEAR_IN_WEEKS) + 1;
+  }
+
+  Telemetry::Accumulate(Telemetry::SSL_OBSERVED_END_ENTITY_CERTIFICATE_LIFETIME,
+      durationInWeeks);
+}
+
 // There are various things that we want to measure about certificate
 // chains that we accept.  This is a single entry point for all of them.
 void
 GatherSuccessfulValidationTelemetry(const ScopedCERTCertList& certList)
 {
   GatherBaselineRequirementsTelemetry(certList);
   GatherEKUTelemetry(certList);
   GatherRootCATelemetry(certList);
+  GatherEndEntityTelemetry(certList);
 }
 
 SECStatus
 AuthCertificate(CertVerifier& certVerifier,
                 TransportSecurityInfo* infoObject,
                 CERTCertificate* cert,
                 ScopedCERTCertList& peerCertChain,
                 SECItem* stapledOCSPResponse,
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1363,16 +1363,24 @@
     "description": "SSL Handshake Key Exchange Algorithm for full handshake (null=0, rsa=1, dh=2, fortezza=3, ecdh=4)"
   },
   "SSL_KEY_EXCHANGE_ALGORITHM_RESUMED": {
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 16,
     "description": "SSL Handshake Key Exchange Algorithm for resumed handshake (null=0, rsa=1, dh=2, fortezza=3, ecdh=4)"
   },
+  "SSL_OBSERVED_END_ENTITY_CERTIFICATE_LIFETIME": {
+    "expires_in_version": "55",
+    "alert_emails": ["seceng-telemetry@mozilla.com"],
+    "kind": "enumerated",
+    "n_values": 125,
+    "releaseChannelCollection": "opt-out",
+    "description": "The lifetime of accepted HTTPS server certificates, in weeks, up to 2 years. Bucket 105 is all end-entity HTTPS server certificates with a lifetime > 2 years."
+  },
   "WEBSOCKETS_HANDSHAKE_TYPE": {
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 16,
     "description": "Websockets Handshake Results (ws-ok-plain, ws-ok-proxy, ws-failed-plain, ws-failed-proxy, wss-ok-plain, wss-ok-proxy, wss-failed-plain, wss-failed-proxy)"
   },
   "SPDY_VERSION2": {
     "expires_in_version": "never",