bug 1348713 - ensure CT information is set in the case of session resumption r=jcj
authorDavid Keeler <dkeeler@mozilla.com>
Mon, 20 Mar 2017 17:10:33 -0700
changeset 348716 afcb04dafd033d90eac3e896e097d21de96ca221
parent 348715 81e0dfa05b1966e28d7c817368f46a7047142ae7
child 348717 e22cc28b03c8f49ff8cdfdeb452ef744ff00fba2
push id31535
push usercbook@mozilla.com
push dateWed, 22 Mar 2017 13:25:07 +0000
treeherdermozilla-central@ee30286771eb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjcj
bugs1348713
milestone55.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 1348713 - ensure CT information is set in the case of session resumption r=jcj MozReview-Commit-ID: 7fLnMu9f1kC
security/manager/ssl/nsNSSCallbacks.cpp
--- a/security/manager/ssl/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/nsNSSCallbacks.cpp
@@ -1062,19 +1062,20 @@ AccumulateCipherSuite(Telemetry::Histogr
 // 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.
+// Similarly, we need to determine the certificate's CT status.
 static void
-DetermineEVStatusAndSetNewCert(RefPtr<nsSSLStatus> sslStatus, PRFileDesc* fd,
-                               nsNSSSocketInfo* infoObject)
+DetermineEVAndCTStatusAndSetNewCert(RefPtr<nsSSLStatus> sslStatus,
+                                    PRFileDesc* fd, nsNSSSocketInfo* infoObject)
 {
   MOZ_ASSERT(sslStatus);
   MOZ_ASSERT(fd);
   MOZ_ASSERT(infoObject);
 
   if (!sslStatus || !fd || !infoObject) {
     return;
   }
@@ -1110,41 +1111,52 @@ DetermineEVStatusAndSetNewCert(RefPtr<ns
   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;
+  CertificateTransparencyInfo certificateTransparencyInfo;
   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->GetOriginAttributes(),
-    &evOidPolicy);
+    &evOidPolicy,
+    nullptr, // OCSP stapling telemetry
+    nullptr, // key size telemetry
+    nullptr, // SHA-1 telemetry
+    nullptr, // pinning telemetry
+    &certificateTransparencyInfo);
 
   RefPtr<nsNSSCertificate> nssc(nsNSSCertificate::Create(cert.get()));
   if (rv == Success && evOidPolicy != SEC_OID_UNKNOWN) {
+    sslStatus->SetCertificateTransparencyInfo(certificateTransparencyInfo);
     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);
   }
+
+  if (rv == Success) {
+    sslStatus->SetCertificateTransparencyInfo(certificateTransparencyInfo);
+  }
 }
 
 void HandshakeCallback(PRFileDesc* fd, void* client_data) {
   nsNSSShutDownPreventionLock locker;
   SECStatus rv;
 
   nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
 
@@ -1285,17 +1297,17 @@ void HandshakeCallback(PRFileDesc* fd, v
                                                 infoObject->GetPort());
     }
   }
 
   if (status->HasServerCert()) {
     MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
            ("HandshakeCallback KEEPING existing cert\n"));
   } else {
-    DetermineEVStatusAndSetNewCert(status, fd, infoObject);
+    DetermineEVAndCTStatusAndSetNewCert(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);