diff --git a/p2p/base/dtls_transport.cc b/p2p/base/dtls_transport.cc index 3a61fd4029..a9ff9d3784 100644 --- a/p2p/base/dtls_transport.cc +++ b/p2p/base/dtls_transport.cc @@ -416,6 +416,13 @@ bool DtlsTransport::GetSslVersionBytes(int* version) const { 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 4e21410b76..9408025be5 100644 --- a/p2p/base/dtls_transport.h +++ b/p2p/base/dtls_transport.h @@ -158,6 +158,12 @@ class DtlsTransport : public DtlsTransportInternal { // 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 3d20d1bfd6..cbcd2bdf88 100644 --- a/p2p/base/dtls_transport_internal.h +++ b/p2p/base/dtls_transport_internal.h @@ -71,6 +71,12 @@ class DtlsTransportInternal : public rtc::PacketTransportInternal { // 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 GetLocalCertificate() const = 0; diff --git a/p2p/base/fake_dtls_transport.h b/p2p/base/fake_dtls_transport.h index 283488bc38..5a3db4886b 100644 --- a/p2p/base/fake_dtls_transport.h +++ b/p2p/base/fake_dtls_transport.h @@ -205,6 +205,7 @@ class FakeDtlsTransport : public DtlsTransportInternal { void SetSslCipherSuite(absl::optional cipher_suite) { ssl_cipher_suite_ = cipher_suite; } + uint16_t GetSslPeerSignatureAlgorithm() const override { return 0; } rtc::scoped_refptr GetLocalCertificate() const override { return local_cert_; } diff --git a/pc/jsep_transport.cc b/pc/jsep_transport.cc index c7d41c8a4c..2398a0ad2d 100644 --- a/pc/jsep_transport.cc +++ b/pc/jsep_transport.cc @@ -704,6 +704,8 @@ bool JsepTransport::GetTransportStats(DtlsTransportInternal* dtls_transport, &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 cde3d91047..e349da42c9 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -2885,6 +2885,36 @@ void PeerConnection::ReportNegotiatedCiphers( } } } + + 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 e554385954..46dccc97f8 100644 --- a/pc/transport_stats.h +++ b/pc/transport_stats.h @@ -34,6 +34,7 @@ struct TransportChannelStats { absl::optional 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 cbbb8e96ab..353cbbe681 100644 --- a/rtc_base/openssl_stream_adapter.cc +++ b/rtc_base/openssl_stream_adapter.cc @@ -469,6 +469,17 @@ bool OpenSSLStreamAdapter::ExportKeyingMaterial(absl::string_view label, 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& ciphers) { if (state_ != SSL_NONE) { diff --git a/rtc_base/openssl_stream_adapter.h b/rtc_base/openssl_stream_adapter.h index 579ca2a1f8..42fdb08aae 100644 --- a/rtc_base/openssl_stream_adapter.h +++ b/rtc_base/openssl_stream_adapter.h @@ -124,6 +124,8 @@ class OpenSSLStreamAdapter final : public SSLStreamAdapter, uint8_t* result, size_t result_len) override; + uint16_t GetPeerSignatureAlgorithm() const override; + // DTLS-SRTP interface bool SetDtlsSrtpCryptoSuites(const std::vector& 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 d8b66f11e8..701cc4437b 100644 --- a/rtc_base/ssl_stream_adapter.h +++ b/rtc_base/ssl_stream_adapter.h @@ -39,6 +39,10 @@ constexpr int kSrtpAeadAes128Gcm = 0x0007; 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 @@ class SSLStreamAdapter : public StreamInterface { 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& crypto_suites); virtual bool GetDtlsSrtpCryptoSuite(int* crypto_suite);