Add histogram for DTLS peer signature algorithm

in order to estimate the impact of deprecating SHA1. Chromium UMA CL:
  https://chromium-review.googlesource.com/c/chromium/src/+/4894345

BUG=webrtc:15517

Change-Id: I5216ba2a8cbba2f276af20d31aa5e111e7c3a141
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/321620
Reviewed-by: David Benjamin <davidben@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#40882}
diff --git a/p2p/base/dtls_transport.cc b/p2p/base/dtls_transport.cc
index 3a61fd4..a9ff9d3 100644
--- a/p2p/base/dtls_transport.cc
+++ b/p2p/base/dtls_transport.cc
@@ -416,6 +416,13 @@
   return dtls_->GetSslVersionBytes(version);
 }
 
+uint16_t DtlsTransport::GetSslPeerSignatureAlgorithm() const {
+  if (dtls_state() != webrtc::DtlsTransportState::kConnected) {
+    return rtc::kSslSignatureAlgorithmUnknown;  // "not applicable"
+  }
+  return dtls_->GetPeerSignatureAlgorithm();
+}
+
 // Called from upper layers to send a media packet.
 int DtlsTransport::SendPacket(const char* data,
                               size_t size,
diff --git a/p2p/base/dtls_transport.h b/p2p/base/dtls_transport.h
index 4e21410..9408025 100644
--- a/p2p/base/dtls_transport.h
+++ b/p2p/base/dtls_transport.h
@@ -158,6 +158,12 @@
   // Find out which DTLS-SRTP cipher was negotiated
   bool GetSrtpCryptoSuite(int* cipher) override;
 
+  // Find out which signature algorithm was used by the peer. Returns values
+  // from
+  // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme
+  // If not applicable, it returns zero.
+  uint16_t GetSslPeerSignatureAlgorithm() const override;
+
   bool GetDtlsRole(rtc::SSLRole* role) const override;
   bool SetDtlsRole(rtc::SSLRole role) override;
 
diff --git a/p2p/base/dtls_transport_internal.h b/p2p/base/dtls_transport_internal.h
index 3d20d1b..cbcd2bd 100644
--- a/p2p/base/dtls_transport_internal.h
+++ b/p2p/base/dtls_transport_internal.h
@@ -71,6 +71,12 @@
   // TODO(zhihuang): Remove this once all dependencies implement this.
   virtual bool GetSslCipherSuite(int* cipher) = 0;
 
+  // Find out which signature algorithm was used by the peer. Returns values
+  // from
+  // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-signaturescheme
+  // If not applicable, it returns zero.
+  virtual uint16_t GetSslPeerSignatureAlgorithm() const = 0;
+
   // Gets the local RTCCertificate used for DTLS.
   virtual rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate()
       const = 0;
diff --git a/p2p/base/fake_dtls_transport.h b/p2p/base/fake_dtls_transport.h
index 283488b..5a3db48 100644
--- a/p2p/base/fake_dtls_transport.h
+++ b/p2p/base/fake_dtls_transport.h
@@ -205,6 +205,7 @@
   void SetSslCipherSuite(absl::optional<int> cipher_suite) {
     ssl_cipher_suite_ = cipher_suite;
   }
+  uint16_t GetSslPeerSignatureAlgorithm() const override { return 0; }
   rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override {
     return local_cert_;
   }
diff --git a/pc/jsep_transport.cc b/pc/jsep_transport.cc
index c7d41c8..2398a0a 100644
--- a/pc/jsep_transport.cc
+++ b/pc/jsep_transport.cc
@@ -704,6 +704,8 @@
           &substats.ice_transport_stats)) {
     return false;
   }
+  substats.ssl_peer_signature_algorithm =
+      dtls_transport->GetSslPeerSignatureAlgorithm();
   stats->channel_stats.push_back(substats);
   return true;
 }
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index cde3d91..e349da4 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -2885,6 +2885,36 @@
       }
     }
   }
+
+  uint16_t ssl_peer_signature_algorithm =
+      stats.channel_stats[0].ssl_peer_signature_algorithm;
+  if (ssl_peer_signature_algorithm != rtc::kSslSignatureAlgorithmUnknown) {
+    for (cricket::MediaType media_type : media_types) {
+      switch (media_type) {
+        case cricket::MEDIA_TYPE_AUDIO:
+          RTC_HISTOGRAM_ENUMERATION_SPARSE(
+              "WebRTC.PeerConnection.SslPeerSignatureAlgorithm.Audio",
+              ssl_peer_signature_algorithm,
+              rtc::kSslSignatureAlgorithmMaxValue);
+          break;
+        case cricket::MEDIA_TYPE_VIDEO:
+          RTC_HISTOGRAM_ENUMERATION_SPARSE(
+              "WebRTC.PeerConnection.SslPeerSignatureAlgorithm.Video",
+              ssl_peer_signature_algorithm,
+              rtc::kSslSignatureAlgorithmMaxValue);
+          break;
+        case cricket::MEDIA_TYPE_DATA:
+          RTC_HISTOGRAM_ENUMERATION_SPARSE(
+              "WebRTC.PeerConnection.SslPeerSignatureAlgorithm.Data",
+              ssl_peer_signature_algorithm,
+              rtc::kSslSignatureAlgorithmMaxValue);
+          break;
+        default:
+          RTC_DCHECK_NOTREACHED();
+          continue;
+      }
+    }
+  }
 }
 
 bool PeerConnection::OnTransportChanged(
diff --git a/pc/transport_stats.h b/pc/transport_stats.h
index e554385..46dccc9 100644
--- a/pc/transport_stats.h
+++ b/pc/transport_stats.h
@@ -34,6 +34,7 @@
   absl::optional<rtc::SSLRole> dtls_role;
   webrtc::DtlsTransportState dtls_state = webrtc::DtlsTransportState::kNew;
   IceTransportStats ice_transport_stats;
+  uint16_t ssl_peer_signature_algorithm = rtc::kSslSignatureAlgorithmUnknown;
 };
 
 // Information about all the channels of a transport.
diff --git a/rtc_base/openssl_stream_adapter.cc b/rtc_base/openssl_stream_adapter.cc
index cbbb8e9..353cbbe 100644
--- a/rtc_base/openssl_stream_adapter.cc
+++ b/rtc_base/openssl_stream_adapter.cc
@@ -469,6 +469,17 @@
   return true;
 }
 
+uint16_t OpenSSLStreamAdapter::GetPeerSignatureAlgorithm() const {
+  if (state_ != SSL_CONNECTED) {
+    return 0;
+  }
+#ifdef OPENSSL_IS_BORINGSSL
+  return SSL_get_peer_signature_algorithm(ssl_);
+#else
+  return kSslSignatureAlgorithmUnknown;
+#endif
+}
+
 bool OpenSSLStreamAdapter::SetDtlsSrtpCryptoSuites(
     const std::vector<int>& ciphers) {
   if (state_ != SSL_NONE) {
diff --git a/rtc_base/openssl_stream_adapter.h b/rtc_base/openssl_stream_adapter.h
index 579ca2a..42fdb08 100644
--- a/rtc_base/openssl_stream_adapter.h
+++ b/rtc_base/openssl_stream_adapter.h
@@ -124,6 +124,8 @@
                             uint8_t* result,
                             size_t result_len) override;
 
+  uint16_t GetPeerSignatureAlgorithm() const override;
+
   // DTLS-SRTP interface
   bool SetDtlsSrtpCryptoSuites(const std::vector<int>& crypto_suites) override;
   bool GetDtlsSrtpCryptoSuite(int* crypto_suite) override;
diff --git a/rtc_base/ssl_stream_adapter.h b/rtc_base/ssl_stream_adapter.h
index d8b66f1..701cc44 100644
--- a/rtc_base/ssl_stream_adapter.h
+++ b/rtc_base/ssl_stream_adapter.h
@@ -39,6 +39,10 @@
 constexpr int kSrtpAeadAes256Gcm = 0x0008;
 constexpr int kSrtpCryptoSuiteMaxValue = 0xFFFF;
 
+// Constants for SSL signature algorithms.
+constexpr int kSslSignatureAlgorithmUnknown = 0;
+constexpr int kSslSignatureAlgorithmMaxValue = 0xFFFF;
+
 // Names of SRTP profiles listed above.
 // 128-bit AES with 80-bit SHA-1 HMAC.
 extern const char kCsAesCm128HmacSha1_80[];
@@ -218,6 +222,9 @@
                                     uint8_t* result,
                                     size_t result_len);
 
+  // Returns the signature algorithm or 0 if not applicable.
+  virtual uint16_t GetPeerSignatureAlgorithm() const = 0;
+
   // DTLS-SRTP interface
   virtual bool SetDtlsSrtpCryptoSuites(const std::vector<int>& crypto_suites);
   virtual bool GetDtlsSrtpCryptoSuite(int* crypto_suite);