Bug 1304923 - adding key exchange group and signature scheme details to devtools view, r?keeler, yulia draft
authorFranziskus Kiefer <franziskuskiefer@gmail.com>
Mon, 28 Aug 2017 15:29:19 +0200
changeset 654252 4d2ea64a216fbbb7d526399b561e1d7eb2064b93
parent 652802 22c304405b0103e6a684ad0b2721f243d51289b9
child 728521 5df7a915179de5bd89172e692eabcad364da594a
push id76524
push userfranziskuskiefer@gmail.com
push dateMon, 28 Aug 2017 13:33:34 +0000
reviewerskeeler, yulia
bugs1304923
milestone57.0a1
Bug 1304923 - adding key exchange group and signature scheme details to devtools view, r?keeler, yulia This patch adds the group used for TLS key exchange and the siganture scheme of the certificate to SSLStatus and displays it in devtools. MozReview-Commit-ID: 7aTj0U5GIvo * addressed review comments * added localisation for none/unknown * display signature scheme as well * bumped SSLStatus version and only process the new values when version 2 is set
devtools/client/locales/en-US/netmonitor.properties
devtools/client/netmonitor/src/components/security-panel.js
devtools/shared/webconsole/network-helper.js
security/manager/ssl/nsISSLStatus.idl
security/manager/ssl/nsNSSCallbacks.cpp
security/manager/ssl/nsSSLStatus.cpp
security/manager/ssl/nsSSLStatus.h
--- a/devtools/client/locales/en-US/netmonitor.properties
+++ b/devtools/client/locales/en-US/netmonitor.properties
@@ -757,16 +757,42 @@ netmonitor.security.error=An error occur
 # LOCALIZATION NOTE (netmonitor.security.protocolVersion): This is the label displayed
 # in the security tab describing TLS/SSL protocol version.
 netmonitor.security.protocolVersion=Protocol version:
 
 # LOCALIZATION NOTE (netmonitor.security.cipherSuite): This is the label displayed
 # in the security tab describing the cipher suite used to secure this connection.
 netmonitor.security.cipherSuite=Cipher suite:
 
+# LOCALIZATION NOTE (netmonitor.security.keaGroup): This is the label displayed
+# in the security tab describing the key exchange group suite used to secure
+# this connection.
+netmonitor.security.keaGroup=Key Exchange Group:
+
+# LOCALIZATION NOTE (netmonitor.security.keaGroup.none): This is the label
+# displayed in the security tab describing the case when no group was used.
+netmonitor.security.keaGroup.none=none
+
+# LOCALIZATION NOTE (netmonitor.security.keaGroup.unkown): This is the value
+# displayed in the security tab describing an unkown group.
+netmonitor.security.keaGroup.unknown=unknown group
+
+# LOCALIZATION NOTE (netmonitor.security.signatureScheme): This is the label
+# displayed in the security tab describing the signature scheme used by for
+# the server certificate in this connection.
+netmonitor.security.signatureScheme=Signature Scheme:
+
+# LOCALIZATION NOTE (netmonitor.security.signatureScheme): This is the label
+# displayed in the security tab describing the case when no signature was used.
+netmonitor.security.signatureScheme.none=none
+
+# LOCALIZATION NOTE (netmonitor.security.signatureScheme): This is the value
+# displayed in the security tab describing an unkown signature scheme.
+netmonitor.security.signatureScheme.unknown=unknown signature scheme
+
 # LOCALIZATION NOTE (netmonitor.security.hsts): This is the label displayed
 # in the security tab describing the usage of HTTP Strict Transport Security.
 netmonitor.security.hsts=HTTP Strict Transport Security:
 
 # LOCALIZATION NOTE (netmonitor.security.hpkp): This is the label displayed
 # in the security tab describing the usage of Public Key Pinning.
 netmonitor.security.hpkp=Public Key Pinning:
 
--- a/devtools/client/netmonitor/src/components/security-panel.js
+++ b/devtools/client/netmonitor/src/components/security-panel.js
@@ -40,16 +40,20 @@ function SecurityPanel({ request }) {
     const disabledLabel = L10N.getStr("netmonitor.security.disabled");
 
     object = {
       [L10N.getStr("netmonitor.security.connection")]: {
         [L10N.getStr("netmonitor.security.protocolVersion")]:
           securityInfo.protocolVersion || notAvailable,
         [L10N.getStr("netmonitor.security.cipherSuite")]:
           securityInfo.cipherSuite || notAvailable,
+        [L10N.getStr("netmonitor.security.keaGroup")]:
+          securityInfo.keaGroupName || notAvailable,
+        [L10N.getStr("netmonitor.security.signatureScheme")]:
+          securityInfo.signatureSchemeName || notAvailable,
       },
       [L10N.getFormatStr("netmonitor.security.hostHeader", getUrlHost(url))]: {
         [L10N.getStr("netmonitor.security.hsts")]:
           securityInfo.hsts ? enabledLabel : disabledLabel,
         [L10N.getStr("netmonitor.security.hpkp")]:
           securityInfo.hpkp ? enabledLabel : disabledLabel,
       },
       [L10N.getStr("netmonitor.security.certificate")]: {
--- a/devtools/shared/webconsole/network-helper.js
+++ b/devtools/shared/webconsole/network-helper.js
@@ -58,16 +58,18 @@
  */
 
 "use strict";
 
 const {components, Cc, Ci} = require("chrome");
 loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
 const DevToolsUtils = require("devtools/shared/DevToolsUtils");
 const Services = require("Services");
+const { LocalizationHelper } = require("devtools/shared/l10n");
+const L10N = new LocalizationHelper("devtools/client/locales/netmonitor.properties");
 
 // The cache used in the `nsIURL` function.
 const gNSURLStore = new Map();
 
 /**
  * Helper object for networking stuff.
  *
  * Most of the following functions have been taken from the Firebug source. They
@@ -615,16 +617,38 @@ var NetworkHelper = {
         DevToolsUtils.reportException("NetworkHelper.parseSecurityInfo",
           "Security state " + state + " has no known STATE_IS_* flags.");
         return info;
       }
 
       // Cipher suite.
       info.cipherSuite = SSLStatus.cipherName;
 
+      // Key exchange group name.
+      info.keaGroupName = SSLStatus.keaGroupName;
+      // Localise two special values.
+      if (info.keaGroupName == "none") {
+        info.keaGroupName = L10N.getStr("netmonitor.security.keaGroup.none");
+      }
+      if (info.keaGroupName == "unknown group") {
+        info.keaGroupName = L10N.getStr("netmonitor.security.keaGroup.unknown");
+      }
+
+      // Certificate signature scheme.
+      info.signatureSchemeName = SSLStatus.signatureSchemeName;
+      // Localise two special values.
+      if (info.signatureSchemeName == "none") {
+        info.signatureSchemeName =
+          L10N.getStr("netmonitor.security.signatureScheme.none");
+        }
+      if (info.signatureSchemeName == "unknown signature") {
+        info.signatureSchemeName =
+          L10N.getStr("netmonitor.security.signatureScheme.unknown");
+      }
+
       // Protocol version.
       info.protocolVersion =
         this.formatSecurityProtocol(SSLStatus.protocolVersion);
 
       // Certificate.
       info.cert = this.parseCertificateInfo(SSLStatus.serverCert);
 
       // HSTS and HPKP if available.
--- a/security/manager/ssl/nsISSLStatus.idl
+++ b/security/manager/ssl/nsISSLStatus.idl
@@ -13,16 +13,20 @@ interface nsISSLStatus : nsISupports {
   readonly attribute nsIX509Cert serverCert;
 
   [must_use]
   readonly attribute ACString cipherName;
   [must_use]
   readonly attribute unsigned long keyLength;
   [must_use]
   readonly attribute unsigned long secretKeyLength;
+  [must_use]
+  readonly attribute ACString keaGroupName;
+  [must_use]
+  readonly attribute ACString signatureSchemeName;
 
   const short SSL_VERSION_3   = 0;
   const short TLS_VERSION_1   = 1;
   const short TLS_VERSION_1_1 = 2;
   const short TLS_VERSION_1_2 = 3;
   const short TLS_VERSION_1_3 = 4;
   [must_use]
   readonly attribute unsigned short protocolVersion;
--- a/security/manager/ssl/nsNSSCallbacks.cpp
+++ b/security/manager/ssl/nsNSSCallbacks.cpp
@@ -821,16 +821,129 @@ PK11PasswordPrompt(PK11SlotInfo* slot, P
 {
   RefPtr<PK11PasswordPromptRunnable> runnable(
     new PK11PasswordPromptRunnable(slot,
                                    static_cast<nsIInterfaceRequestor*>(arg)));
   runnable->DispatchToMainThreadAndWait();
   return runnable->mResult;
 }
 
+static nsCString
+getKeaGroupName(uint32_t aKeaGroup)
+{
+  nsCString groupName;
+  switch (aKeaGroup) {
+    case ssl_grp_ec_secp256r1:
+      groupName = NS_LITERAL_CSTRING("P256");
+      break;
+    case ssl_grp_ec_secp384r1:
+      groupName = NS_LITERAL_CSTRING("P384");
+      break;
+    case ssl_grp_ec_secp521r1:
+      groupName = NS_LITERAL_CSTRING("P521");
+      break;
+    case ssl_grp_ec_curve25519:
+      groupName = NS_LITERAL_CSTRING("x25519");
+      break;
+    case ssl_grp_none:
+      groupName = NS_LITERAL_CSTRING("none");
+      break;
+    case ssl_grp_ffdhe_2048:
+      groupName = NS_LITERAL_CSTRING("FF 2048");
+      break;
+    case ssl_grp_ffdhe_3072:
+      groupName = NS_LITERAL_CSTRING("FF 3072");
+      break;
+    case ssl_grp_ffdhe_4096:
+      groupName = NS_LITERAL_CSTRING("FF 4096");
+      break;
+    case ssl_grp_ffdhe_6144:
+      groupName = NS_LITERAL_CSTRING("FF 6144");
+      break;
+    case ssl_grp_ffdhe_8192:
+      groupName = NS_LITERAL_CSTRING("FF 8192");
+      break;
+    default:
+      // This really shouldn't happen!
+      MOZ_ASSERT_UNREACHABLE("Invalid key exchange group.");
+      groupName = NS_LITERAL_CSTRING("unknown group");
+  }
+  return groupName;
+}
+
+static nsCString
+getSignatureName(uint32_t aSignatureScheme)
+{
+  nsCString signatureName;
+  switch (aSignatureScheme) {
+    case ssl_sig_none:
+      signatureName = NS_LITERAL_CSTRING("none");
+      break;
+    case ssl_sig_rsa_pkcs1_sha1:
+      signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA1");
+      break;
+    case ssl_sig_rsa_pkcs1_sha256:
+      signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA256");
+      break;
+    case ssl_sig_rsa_pkcs1_sha384:
+      signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA384");
+      break;
+    case  ssl_sig_rsa_pkcs1_sha512:
+      signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA512");
+      break;
+    case ssl_sig_ecdsa_secp256r1_sha256:
+      signatureName = NS_LITERAL_CSTRING("ECDSA-P256-SHA256");
+      break;
+    case ssl_sig_ecdsa_secp384r1_sha384:
+      signatureName = NS_LITERAL_CSTRING("ECDSA-P384-SHA384");
+      break;
+    case ssl_sig_ecdsa_secp521r1_sha512:
+      signatureName = NS_LITERAL_CSTRING("ECDSA-P521-SHA512");
+      break;
+    case ssl_sig_rsa_pss_sha256:
+      signatureName = NS_LITERAL_CSTRING("RSA-PSS-SHA256");
+      break;
+    case ssl_sig_rsa_pss_sha384:
+      signatureName = NS_LITERAL_CSTRING("RSA-PSS-SHA384");
+      break;
+    case ssl_sig_rsa_pss_sha512:
+      signatureName = NS_LITERAL_CSTRING("RSA-PSS-SHA512");
+      break;
+    case ssl_sig_ed25519:
+      signatureName = NS_LITERAL_CSTRING("ED25519");
+      break;
+    case ssl_sig_ed448:
+      signatureName = NS_LITERAL_CSTRING("ED448");
+      break;
+    case ssl_sig_dsa_sha1:
+      signatureName = NS_LITERAL_CSTRING("DSA-SHA1");
+      break;
+    case ssl_sig_dsa_sha256:
+      signatureName = NS_LITERAL_CSTRING("DSA-SHA256");
+      break;
+    case ssl_sig_dsa_sha384:
+      signatureName = NS_LITERAL_CSTRING("DSA-SHA384");
+      break;
+    case ssl_sig_dsa_sha512:
+      signatureName = NS_LITERAL_CSTRING("DSA-SHA512");
+      break;
+    case ssl_sig_ecdsa_sha1:
+      signatureName = NS_LITERAL_CSTRING("ECDSA-SHA1");
+      break;
+    case ssl_sig_rsa_pkcs1_sha1md5:
+      signatureName = NS_LITERAL_CSTRING("RSA-PKCS1-SHA1MD5");
+      break;
+    default:
+      // This really shouldn't happen!
+      MOZ_ASSERT_UNREACHABLE("Invalid signature scheme.");
+      signatureName = NS_LITERAL_CSTRING("unknown signature");
+  }
+  return signatureName;
+}
+
 // call with shutdown prevention lock held
 static void
 PreliminaryHandshakeDone(PRFileDesc* fd)
 {
   nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
   if (!infoObject)
     return;
 
@@ -847,16 +960,19 @@ PreliminaryHandshakeDone(PRFileDesc* fd)
       if (!status) {
         status = new nsSSLStatus();
         infoObject->SetSSLStatus(status);
       }
 
       status->mHaveCipherSuiteAndProtocol = true;
       status->mCipherSuite = channelInfo.cipherSuite;
       status->mProtocolVersion = channelInfo.protocolVersion & 0xFF;
+      status->mKeaGroup.Assign(getKeaGroupName(channelInfo.keaGroup));
+      status->mSignatureSchemeName.Assign(
+        getSignatureName(channelInfo.signatureScheme));
       infoObject->SetKEAUsed(channelInfo.keaType);
       infoObject->SetKEAKeyBits(channelInfo.keaKeyBits);
       infoObject->SetMACAlgorithmUsed(cipherInfo.macAlgorithm);
     }
   }
 
   // Don't update NPN details on renegotiation.
   if (infoObject->IsPreliminaryHandshakeDone()) {
--- a/security/manager/ssl/nsSSLStatus.cpp
+++ b/security/manager/ssl/nsSSLStatus.cpp
@@ -72,16 +72,38 @@ nsSSLStatus::GetCipherName(nsACString& a
     return NS_ERROR_FAILURE;
   }
 
   aCipherName.Assign(cipherInfo.cipherSuiteName);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsSSLStatus::GetKeaGroupName(nsACString& aKeaGroup)
+{
+  if (!mHaveCipherSuiteAndProtocol) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  aKeaGroup.Assign(mKeaGroup);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSSLStatus::GetSignatureSchemeName(nsACString& aSignatureScheme)
+{
+  if (!mHaveCipherSuiteAndProtocol) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  aSignatureScheme.Assign(mSignatureSchemeName);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsSSLStatus::GetProtocolVersion(uint16_t* aProtocolVersion)
 {
   NS_ENSURE_ARG_POINTER(aProtocolVersion);
   if (!mHaveCipherSuiteAndProtocol) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   *aProtocolVersion = mProtocolVersion;
@@ -189,24 +211,33 @@ nsSSLStatus::Read(nsIObjectInputStream* 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Added in version 1 (see bug 1305289).
   if (streamFormatVersion >= 1) {
     rv = aStream->Read16(&mCertificateTransparencyStatus);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  // Added in version 2 (see bug 1304923).
+  if (streamFormatVersion >= 2) {
+    rv = aStream->ReadCString(mKeaGroup);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = aStream->ReadCString(mSignatureSchemeName);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSSLStatus::Write(nsIObjectOutputStream* aStream)
 {
   // The current version of the binary stream format.
-  const uint8_t STREAM_FORMAT_VERSION = 1;
+  const uint8_t STREAM_FORMAT_VERSION = 2;
 
   nsresult rv = aStream->WriteCompoundObject(mServerCert,
                                              NS_GET_IID(nsIX509Cert),
                                              true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aStream->Write16(mCipherSuite);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -232,16 +263,23 @@ nsSSLStatus::Write(nsIObjectOutputStream
   NS_ENSURE_SUCCESS(rv, rv);
   rv = aStream->WriteBoolean(mHaveCertErrorBits);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Added in version 1.
   rv = aStream->Write16(mCertificateTransparencyStatus);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Added in version 2.
+  rv = aStream->WriteStringZ(mKeaGroup.get());
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aStream->WriteStringZ(mSignatureSchemeName.get());
+  NS_ENSURE_SUCCESS(rv, rv);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSSLStatus::GetInterfaces(uint32_t* aCount, nsIID*** aArray)
 {
   *aCount = 0;
   *aArray = nullptr;
@@ -295,16 +333,18 @@ nsSSLStatus::GetClassIDNoAlloc(nsCID* aC
   return NS_OK;
 }
 
 nsSSLStatus::nsSSLStatus()
 : mCipherSuite(0)
 , mProtocolVersion(0)
 , mCertificateTransparencyStatus(nsISSLStatus::
     CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE)
+, mKeaGroup()
+, mSignatureSchemeName()
 , mIsDomainMismatch(false)
 , mIsNotValidAtThisTime(false)
 , mIsUntrusted(false)
 , mIsEV(false)
 , mHasIsEVStatus(false)
 , mHaveCipherSuiteAndProtocol(false)
 , mHaveCertErrorBits(false)
 {
--- a/security/manager/ssl/nsSSLStatus.h
+++ b/security/manager/ssl/nsSSLStatus.h
@@ -45,16 +45,18 @@ public:
 
   void SetCertificateTransparencyInfo(
     const mozilla::psm::CertificateTransparencyInfo& info);
 
   /* public for initilization in this file */
   uint16_t mCipherSuite;
   uint16_t mProtocolVersion;
   uint16_t mCertificateTransparencyStatus;
+  nsCString mKeaGroup;
+  nsCString mSignatureSchemeName;
 
   bool mIsDomainMismatch;
   bool mIsNotValidAtThisTime;
   bool mIsUntrusted;
   bool mIsEV;
 
   bool mHasIsEVStatus;
   bool mHaveCipherSuiteAndProtocol;