Implement crypto stats on DTLS transport Bug: chromium:1018077 Change-Id: I585d4064f39e5f9d268b408ebf6ae13a056c778a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158403 Reviewed-by: Henrik Boström <hbos@webrtc.org> Reviewed-by: Steve Anton <steveanton@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29628}
diff --git a/pc/jsep_transport.cc b/pc/jsep_transport.cc index ca44ec8..13618c7 100644 --- a/pc/jsep_transport.cc +++ b/pc/jsep_transport.cc
@@ -772,6 +772,7 @@ } else { substats.component = ICE_CANDIDATE_COMPONENT_RTP; } + dtls_transport->GetSslVersionBytes(&substats.ssl_version_bytes); dtls_transport->GetSrtpCryptoSuite(&substats.srtp_crypto_suite); dtls_transport->GetSslCipherSuite(&substats.ssl_cipher_suite); substats.dtls_state = dtls_transport->dtls_state();
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index ab12c65..481e255 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc
@@ -1721,6 +1721,26 @@ transport_stats->local_certificate_id = local_certificate_id; if (!remote_certificate_id.empty()) transport_stats->remote_certificate_id = remote_certificate_id; + // Crypto information + if (channel_stats.ssl_version_bytes) { + char bytes[5]; + snprintf(bytes, sizeof(bytes), "%04X", channel_stats.ssl_version_bytes); + transport_stats->tls_version = bytes; + } + if (channel_stats.ssl_cipher_suite != rtc::TLS_NULL_WITH_NULL_NULL && + rtc::SSLStreamAdapter::SslCipherSuiteToName( + channel_stats.ssl_cipher_suite) + .length()) { + transport_stats->dtls_cipher = + rtc::SSLStreamAdapter::SslCipherSuiteToName( + channel_stats.ssl_cipher_suite); + } + if (channel_stats.srtp_crypto_suite != rtc::SRTP_INVALID_CRYPTO_SUITE && + rtc::SrtpCryptoSuiteToName(channel_stats.srtp_crypto_suite) + .length()) { + transport_stats->srtp_cipher = + rtc::SrtpCryptoSuiteToName(channel_stats.srtp_crypto_suite); + } report->AddStats(std::move(transport_stats)); } }
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index ce2d54e..95c2a9b 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc
@@ -2202,6 +2202,68 @@ report->Get(expected_rtcp_transport.id())->cast_to<RTCTransportStats>()); } +TEST_F(RTCStatsCollectorTest, CollectRTCTransportStatsWithCrypto) { + const char kTransportName[] = "transport"; + + pc_->AddVoiceChannel("audio", kTransportName); + + std::unique_ptr<cricket::Candidate> rtp_local_candidate = + CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI, + cricket::LOCAL_PORT_TYPE, 42); + std::unique_ptr<cricket::Candidate> rtp_remote_candidate = + CreateFakeCandidate("42.42.42.42", 42, "protocol", + rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE, + 42); + std::unique_ptr<cricket::Candidate> rtcp_local_candidate = + CreateFakeCandidate("42.42.42.42", 42, "protocol", rtc::ADAPTER_TYPE_WIFI, + cricket::LOCAL_PORT_TYPE, 42); + std::unique_ptr<cricket::Candidate> rtcp_remote_candidate = + CreateFakeCandidate("42.42.42.42", 42, "protocol", + rtc::ADAPTER_TYPE_UNKNOWN, cricket::LOCAL_PORT_TYPE, + 42); + + cricket::ConnectionInfo rtp_connection_info; + rtp_connection_info.best_connection = false; + rtp_connection_info.local_candidate = *rtp_local_candidate.get(); + rtp_connection_info.remote_candidate = *rtp_remote_candidate.get(); + rtp_connection_info.sent_total_bytes = 42; + rtp_connection_info.recv_total_bytes = 1337; + cricket::TransportChannelStats rtp_transport_channel_stats; + rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; + rtp_transport_channel_stats.ice_transport_stats.connection_infos.push_back( + rtp_connection_info); + // The state must be connected in order for crypto parameters to show up. + rtp_transport_channel_stats.dtls_state = cricket::DTLS_TRANSPORT_CONNECTED; + rtp_transport_channel_stats.ice_transport_stats + .selected_candidate_pair_changes = 1; + rtp_transport_channel_stats.ssl_version_bytes = 0x0203; + // 0x2F is TLS_RSA_WITH_AES_128_CBC_SHA according to IANA + rtp_transport_channel_stats.ssl_cipher_suite = 0x2F; + rtp_transport_channel_stats.srtp_crypto_suite = rtc::SRTP_AES128_CM_SHA1_80; + pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats}); + + // Get stats + rtc::scoped_refptr<const RTCStatsReport> report = stats_->GetStatsReport(); + + RTCTransportStats expected_rtp_transport( + "RTCTransport_transport_" + + rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP), + report->timestamp_us()); + expected_rtp_transport.bytes_sent = 42; + expected_rtp_transport.bytes_received = 1337; + expected_rtp_transport.dtls_state = RTCDtlsTransportState::kConnected; + expected_rtp_transport.selected_candidate_pair_changes = 1; + // Crypto parameters + expected_rtp_transport.tls_version = "0203"; + expected_rtp_transport.dtls_cipher = "TLS_RSA_WITH_AES_128_CBC_SHA"; + expected_rtp_transport.srtp_cipher = "AES_CM_128_HMAC_SHA1_80"; + + ASSERT_TRUE(report->Get(expected_rtp_transport.id())); + EXPECT_EQ( + expected_rtp_transport, + report->Get(expected_rtp_transport.id())->cast_to<RTCTransportStats>()); +} + TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRTPStreamStats_Audio) { cricket::VoiceMediaInfo voice_media_info;
diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc index 9000ff9..31258a2a 100644 --- a/pc/rtc_stats_integrationtest.cc +++ b/pc/rtc_stats_integrationtest.cc
@@ -973,6 +973,9 @@ RTCCertificateStats::kType); verifier.TestMemberIsIDReference(transport.remote_certificate_id, RTCCertificateStats::kType); + verifier.TestMemberIsDefined(transport.tls_version); + verifier.TestMemberIsDefined(transport.dtls_cipher); + verifier.TestMemberIsDefined(transport.srtp_cipher); verifier.TestMemberIsPositive<uint32_t>( transport.selected_candidate_pair_changes); return verifier.ExpectAllMembersSuccessfullyTested();
diff --git a/pc/transport_stats.h b/pc/transport_stats.h index 4f6ce2a..7cb95f4 100644 --- a/pc/transport_stats.h +++ b/pc/transport_stats.h
@@ -27,6 +27,7 @@ ~TransportChannelStats(); int component = 0; + int ssl_version_bytes = 0; int srtp_crypto_suite = rtc::SRTP_INVALID_CRYPTO_SUITE; int ssl_cipher_suite = rtc::TLS_NULL_WITH_NULL_NULL; DtlsTransportState dtls_state = DTLS_TRANSPORT_NEW;