From 3ee4fe5a940128cbfe76c8609a56c69c2aeb0175 Mon Sep 17 00:00:00 2001 From: "pthatcher@webrtc.org" Date: Wed, 11 Feb 2015 22:34:36 +0000 Subject: [PATCH] Re-land: Add API to get negotiated SSL ciphers This CL adds an API to the SSL stream adapters and transport channels to get the SSL cipher that was negotiated with the remote peer. The previously approved CL https://webrtc-codereview.appspot.com/26009004/ was reverted in https://webrtc-codereview.appspot.com/40689004/ due to compilation issues while rolling into Chromium. As the new method has landed in Chromium in https://crrev.com/bc321c76ace6e1d5a03440e554ccb207159802ec, this should be safe to land here now. BUG=3976 R=pthatcher@webrtc.org Review URL: https://webrtc-codereview.appspot.com/37209004 Cr-Commit-Position: refs/heads/master@{#8343} git-svn-id: http://webrtc.googlecode.com/svn/trunk@8343 4adac7df-926f-26a2-2b94-8c16560cd09d --- AUTHORS | 1 + webrtc/base/nssstreamadapter.cc | 29 ++++ webrtc/base/nssstreamadapter.h | 3 + webrtc/base/opensslstreamadapter.cc | 128 ++++++++++++++++++ webrtc/base/opensslstreamadapter.h | 7 + webrtc/base/sslstreamadapter.cc | 9 ++ webrtc/base/sslstreamadapter.h | 10 ++ webrtc/base/sslstreamadapter_unittest.cc | 21 +++ webrtc/p2p/base/dtlstransportchannel.cc | 8 ++ webrtc/p2p/base/dtlstransportchannel.h | 3 + .../p2p/base/dtlstransportchannel_unittest.cc | 18 +++ webrtc/p2p/base/fakesession.h | 4 + webrtc/p2p/base/p2ptransportchannel.h | 7 +- webrtc/p2p/base/rawtransportchannel.h | 7 +- webrtc/p2p/base/transport.cc | 7 +- webrtc/p2p/base/transport.h | 2 + webrtc/p2p/base/transportchannel.h | 5 +- webrtc/p2p/base/transportchannelproxy.cc | 8 ++ webrtc/p2p/base/transportchannelproxy.h | 1 + 19 files changed, 273 insertions(+), 5 deletions(-) diff --git a/AUTHORS b/AUTHORS index 09e4f62500..069c3322e2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -37,5 +37,6 @@ Intel Corporation MIPS Technologies Mozilla Foundation Opera Software ASA +struktur AG Temasys Communications Vonage Holdings Corp. diff --git a/webrtc/base/nssstreamadapter.cc b/webrtc/base/nssstreamadapter.cc index 7152eda5c6..1286bf96b4 100644 --- a/webrtc/base/nssstreamadapter.cc +++ b/webrtc/base/nssstreamadapter.cc @@ -66,6 +66,10 @@ static const SrtpCipherMapEntry kSrtpCipherMap[] = { }; #endif +// Default cipher used between NSS stream adapters. +// This needs to be updated when the default of the SSL library changes. +static const char kDefaultSslCipher[] = "TLS_RSA_WITH_AES_128_CBC_SHA"; + // Implementation of NSPR methods static PRStatus StreamClose(PRFileDesc *socket) { @@ -866,6 +870,27 @@ SECStatus NSSStreamAdapter::GetClientAuthDataHook(void *arg, PRFileDesc *fd, return SECSuccess; } +bool NSSStreamAdapter::GetSslCipher(std::string* cipher) { + ASSERT(state_ == SSL_CONNECTED); + if (state_ != SSL_CONNECTED) + return false; + + SSLChannelInfo channel_info; + SECStatus rv = SSL_GetChannelInfo(ssl_fd_, &channel_info, + sizeof(channel_info)); + if (rv == SECFailure) + return false; + + SSLCipherSuiteInfo ciphersuite_info; + rv = SSL_GetCipherSuiteInfo(channel_info.cipherSuite, &ciphersuite_info, + sizeof(ciphersuite_info)); + if (rv == SECFailure) + return false; + + *cipher = ciphersuite_info.cipherSuiteName; + return true; +} + // RFC 5705 Key Exporter bool NSSStreamAdapter::ExportKeyingMaterial(const std::string& label, const uint8* context, @@ -1011,6 +1036,10 @@ bool NSSStreamAdapter::HaveExporter() { return true; } +std::string NSSStreamAdapter::GetDefaultSslCipher() { + return kDefaultSslCipher; +} + } // namespace rtc #endif // HAVE_NSS_SSL_H diff --git a/webrtc/base/nssstreamadapter.h b/webrtc/base/nssstreamadapter.h index 210a47933d..afa2eb690f 100644 --- a/webrtc/base/nssstreamadapter.h +++ b/webrtc/base/nssstreamadapter.h @@ -61,6 +61,8 @@ class NSSStreamAdapter : public SSLStreamAdapterHelper { size_t* written, int* error); void OnMessage(Message *msg); + virtual bool GetSslCipher(std::string* cipher); + // Key Extractor interface virtual bool ExportKeyingMaterial(const std::string& label, const uint8* context, @@ -77,6 +79,7 @@ class NSSStreamAdapter : public SSLStreamAdapterHelper { static bool HaveDtls(); static bool HaveDtlsSrtp(); static bool HaveExporter(); + static std::string GetDefaultSslCipher(); protected: // Override SSLStreamAdapter diff --git a/webrtc/base/opensslstreamadapter.cc b/webrtc/base/opensslstreamadapter.cc index c18295f577..0f82d281f8 100644 --- a/webrtc/base/opensslstreamadapter.cc +++ b/webrtc/base/opensslstreamadapter.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,99 @@ static SrtpCipherMapEntry SrtpCipherMap[] = { }; #endif +// Cipher name table. Maps internal OpenSSL cipher ids to the RFC name. +struct SslCipherMapEntry { + uint32_t openssl_id; + const char* rfc_name; +}; + +#define DEFINE_CIPHER_ENTRY_SSL3(name) {SSL3_CK_##name, "TLS_"#name} +#define DEFINE_CIPHER_ENTRY_TLS1(name) {TLS1_CK_##name, "TLS_"#name} + +// There currently is no method available to get a RFC-compliant name for a +// cipher suite from BoringSSL, so we need to define the mapping manually here. +// This should go away once BoringSSL supports "SSL_CIPHER_standard_name" +// (as available in OpenSSL if compiled with tracing enabled) or a similar +// method. +static const SslCipherMapEntry kSslCipherMap[] = { + // TLS v1.0 ciphersuites from RFC2246. + DEFINE_CIPHER_ENTRY_SSL3(RSA_RC4_128_SHA), + {SSL3_CK_RSA_DES_192_CBC3_SHA, + "TLS_RSA_WITH_3DES_EDE_CBC_SHA"}, + + // AES ciphersuites from RFC3268. + {TLS1_CK_RSA_WITH_AES_128_SHA, + "TLS_RSA_WITH_AES_128_CBC_SHA"}, + {TLS1_CK_DHE_RSA_WITH_AES_128_SHA, + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"}, + {TLS1_CK_RSA_WITH_AES_256_SHA, + "TLS_RSA_WITH_AES_256_CBC_SHA"}, + {TLS1_CK_DHE_RSA_WITH_AES_256_SHA, + "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"}, + + // ECC ciphersuites from RFC4492. + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_RC4_128_SHA), + {TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, + "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"}, + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_128_CBC_SHA), + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_256_CBC_SHA), + + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_RC4_128_SHA), + {TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA, + "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"}, + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_128_CBC_SHA), + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_256_CBC_SHA), + + // TLS v1.2 ciphersuites. + {TLS1_CK_RSA_WITH_AES_128_SHA256, + "TLS_RSA_WITH_AES_128_CBC_SHA256"}, + {TLS1_CK_RSA_WITH_AES_256_SHA256, + "TLS_RSA_WITH_AES_256_CBC_SHA256"}, + {TLS1_CK_DHE_RSA_WITH_AES_128_SHA256, + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"}, + {TLS1_CK_DHE_RSA_WITH_AES_256_SHA256, + "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"}, + + // TLS v1.2 GCM ciphersuites from RFC5288. + DEFINE_CIPHER_ENTRY_TLS1(RSA_WITH_AES_128_GCM_SHA256), + DEFINE_CIPHER_ENTRY_TLS1(RSA_WITH_AES_256_GCM_SHA384), + DEFINE_CIPHER_ENTRY_TLS1(DHE_RSA_WITH_AES_128_GCM_SHA256), + DEFINE_CIPHER_ENTRY_TLS1(DHE_RSA_WITH_AES_256_GCM_SHA384), + DEFINE_CIPHER_ENTRY_TLS1(DH_RSA_WITH_AES_128_GCM_SHA256), + DEFINE_CIPHER_ENTRY_TLS1(DH_RSA_WITH_AES_256_GCM_SHA384), + + // ECDH HMAC based ciphersuites from RFC5289. + {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256, + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"}, + {TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384, + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"}, + {TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"}, + {TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"}, + + // ECDH GCM based ciphersuites from RFC5289. + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_128_GCM_SHA256), + DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_256_GCM_SHA384), + +#ifdef OPENSSL_IS_BORINGSSL + {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"}, + {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, + "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"}, + {TLS1_CK_DHE_RSA_CHACHA20_POLY1305, + "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"}, +#endif + + {0, NULL} +}; + +// Default cipher used between OpenSSL/BoringSSL stream adapters. +// This needs to be updated when the default of the SSL library changes. +static const char kDefaultSslCipher[] = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; + ////////////////////////////////////////////////////////////////////// // StreamBIO ////////////////////////////////////////////////////////////////////// @@ -222,6 +316,36 @@ bool OpenSSLStreamAdapter::SetPeerCertificateDigest(const std::string return true; } +const char* OpenSSLStreamAdapter::GetRfcSslCipherName( + const SSL_CIPHER* cipher) { + ASSERT(cipher != NULL); + for (const SslCipherMapEntry* entry = kSslCipherMap; entry->rfc_name; + ++entry) { + if (cipher->id == entry->openssl_id) { + return entry->rfc_name; + } + } + return NULL; +} + +bool OpenSSLStreamAdapter::GetSslCipher(std::string* cipher) { + if (state_ != SSL_CONNECTED) + return false; + + const SSL_CIPHER* current_cipher = SSL_get_current_cipher(ssl_); + if (current_cipher == NULL) { + return false; + } + + const char* cipher_name = GetRfcSslCipherName(current_cipher); + if (cipher_name == NULL) { + return false; + } + + *cipher = cipher_name; + return true; +} + // Key Extractor interface bool OpenSSLStreamAdapter::ExportKeyingMaterial(const std::string& label, const uint8* context, @@ -877,6 +1001,10 @@ bool OpenSSLStreamAdapter::HaveExporter() { #endif } +std::string OpenSSLStreamAdapter::GetDefaultSslCipher() { + return kDefaultSslCipher; +} + } // namespace rtc #endif // HAVE_OPENSSL_SSL_H diff --git a/webrtc/base/opensslstreamadapter.h b/webrtc/base/opensslstreamadapter.h index 9506217b4c..a9d98fd692 100644 --- a/webrtc/base/opensslstreamadapter.h +++ b/webrtc/base/opensslstreamadapter.h @@ -20,6 +20,7 @@ typedef struct ssl_st SSL; typedef struct ssl_ctx_st SSL_CTX; +typedef struct ssl_cipher_st SSL_CIPHER; typedef struct x509_store_ctx_st X509_STORE_CTX; namespace rtc { @@ -81,6 +82,11 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter { virtual void Close(); virtual StreamState GetState() const; + // Return the RFC (5246, 3268, etc.) cipher name for an OpenSSL cipher. + static const char* GetRfcSslCipherName(const SSL_CIPHER* cipher); + + virtual bool GetSslCipher(std::string* cipher); + // Key Extractor interface virtual bool ExportKeyingMaterial(const std::string& label, const uint8* context, @@ -98,6 +104,7 @@ class OpenSSLStreamAdapter : public SSLStreamAdapter { static bool HaveDtls(); static bool HaveDtlsSrtp(); static bool HaveExporter(); + static std::string GetDefaultSslCipher(); protected: virtual void OnEvent(StreamInterface* stream, int events, int err); diff --git a/webrtc/base/sslstreamadapter.cc b/webrtc/base/sslstreamadapter.cc index 44df2eedd9..513ae8caf7 100644 --- a/webrtc/base/sslstreamadapter.cc +++ b/webrtc/base/sslstreamadapter.cc @@ -50,6 +50,9 @@ SSLStreamAdapter* SSLStreamAdapter::Create(StreamInterface* stream) { bool SSLStreamAdapter::HaveDtls() { return false; } bool SSLStreamAdapter::HaveDtlsSrtp() { return false; } bool SSLStreamAdapter::HaveExporter() { return false; } +std::string SSLStreamAdapter::GetDefaultSslCipher() { + return std::string(); +} #elif SSL_USE_OPENSSL bool SSLStreamAdapter::HaveDtls() { return OpenSSLStreamAdapter::HaveDtls(); @@ -60,6 +63,9 @@ bool SSLStreamAdapter::HaveDtlsSrtp() { bool SSLStreamAdapter::HaveExporter() { return OpenSSLStreamAdapter::HaveExporter(); } +std::string SSLStreamAdapter::GetDefaultSslCipher() { + return OpenSSLStreamAdapter::GetDefaultSslCipher(); +} #elif SSL_USE_NSS bool SSLStreamAdapter::HaveDtls() { return NSSStreamAdapter::HaveDtls(); @@ -70,6 +76,9 @@ bool SSLStreamAdapter::HaveDtlsSrtp() { bool SSLStreamAdapter::HaveExporter() { return NSSStreamAdapter::HaveExporter(); } +std::string SSLStreamAdapter::GetDefaultSslCipher() { + return NSSStreamAdapter::GetDefaultSslCipher(); +} #endif // !SSL_USE_SCHANNEL && !SSL_USE_OPENSSL && !SSL_USE_NSS /////////////////////////////////////////////////////////////////////////////// diff --git a/webrtc/base/sslstreamadapter.h b/webrtc/base/sslstreamadapter.h index ea966c54e1..c940ecb68d 100644 --- a/webrtc/base/sslstreamadapter.h +++ b/webrtc/base/sslstreamadapter.h @@ -119,6 +119,12 @@ class SSLStreamAdapter : public StreamAdapterInterface { // chain. The returned certificate is owned by the caller. virtual bool GetPeerCertificate(SSLCertificate** cert) const = 0; + // Retrieves the name of the cipher suite used for the connection + // (e.g. "TLS_RSA_WITH_AES_128_CBC_SHA"). + virtual bool GetSslCipher(std::string* cipher) { + return false; + } + // Key Exporter interface from RFC 5705 // Arguments are: // label -- the exporter label. @@ -155,6 +161,10 @@ class SSLStreamAdapter : public StreamAdapterInterface { static bool HaveDtlsSrtp(); static bool HaveExporter(); + // Returns the default Ssl cipher used between streams of this class. + // This is used by the unit tests. + static std::string GetDefaultSslCipher(); + private: // If true, the server certificate need not match the configured // server_name, and in fact missing certificate authority and other diff --git a/webrtc/base/sslstreamadapter_unittest.cc b/webrtc/base/sslstreamadapter_unittest.cc index b9d477d151..677be35f67 100644 --- a/webrtc/base/sslstreamadapter_unittest.cc +++ b/webrtc/base/sslstreamadapter_unittest.cc @@ -388,6 +388,13 @@ class SSLStreamAdapterTestBase : public testing::Test, return server_ssl_->GetPeerCertificate(cert); } + bool GetSslCipher(bool client, std::string *retval) { + if (client) + return client_ssl_->GetSslCipher(retval); + else + return server_ssl_->GetSslCipher(retval); + } + bool ExportKeyingMaterial(const char *label, const unsigned char *context, size_t context_len, @@ -939,3 +946,17 @@ TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestDTLSGetPeerCertificate) { rtc::SSLCertChain* server_peer_chain; ASSERT_FALSE(server_peer_cert->GetChain(&server_peer_chain)); } + +// Test getting the used DTLS ciphers. +TEST_F(SSLStreamAdapterTestDTLS, TestGetSslCipher) { + MAYBE_SKIP_TEST(HaveDtls); + TestHandshake(); + + std::string client_cipher; + ASSERT_TRUE(GetSslCipher(true, &client_cipher)); + std::string server_cipher; + ASSERT_TRUE(GetSslCipher(false, &server_cipher)); + + ASSERT_EQ(client_cipher, server_cipher); + ASSERT_EQ(rtc::SSLStreamAdapter::GetDefaultSslCipher(), client_cipher); +} diff --git a/webrtc/p2p/base/dtlstransportchannel.cc b/webrtc/p2p/base/dtlstransportchannel.cc index 9cceca350a..956c52aec8 100644 --- a/webrtc/p2p/base/dtlstransportchannel.cc +++ b/webrtc/p2p/base/dtlstransportchannel.cc @@ -186,6 +186,14 @@ bool DtlsTransportChannelWrapper::GetSslRole(rtc::SSLRole* role) const { return true; } +bool DtlsTransportChannelWrapper::GetSslCipher(std::string* cipher) { + if (dtls_state_ != STATE_OPEN) { + return false; + } + + return dtls_->GetSslCipher(cipher); +} + bool DtlsTransportChannelWrapper::SetRemoteFingerprint( const std::string& digest_alg, const uint8* digest, diff --git a/webrtc/p2p/base/dtlstransportchannel.h b/webrtc/p2p/base/dtlstransportchannel.h index 4c9c879b78..03a916b767 100644 --- a/webrtc/p2p/base/dtlstransportchannel.h +++ b/webrtc/p2p/base/dtlstransportchannel.h @@ -150,6 +150,9 @@ class DtlsTransportChannelWrapper : public TransportChannelImpl { virtual bool GetSslRole(rtc::SSLRole* role) const; virtual bool SetSslRole(rtc::SSLRole role); + // Find out which DTLS cipher was negotiated + virtual bool GetSslCipher(std::string* cipher); + // Once DTLS has been established, this method retrieves the certificate in // use by the remote peer, for use in external identity verification. virtual bool GetRemoteCertificate(rtc::SSLCertificate** cert) const; diff --git a/webrtc/p2p/base/dtlstransportchannel_unittest.cc b/webrtc/p2p/base/dtlstransportchannel_unittest.cc index 52f8c1e721..f3086bb3a0 100644 --- a/webrtc/p2p/base/dtlstransportchannel_unittest.cc +++ b/webrtc/p2p/base/dtlstransportchannel_unittest.cc @@ -213,6 +213,22 @@ class DtlsTestClient : public sigslot::has_slots<> { } } + void CheckSsl(const std::string& expected_cipher) { + for (std::vector::iterator it = + channels_.begin(); it != channels_.end(); ++it) { + std::string cipher; + + bool rv = (*it)->GetSslCipher(&cipher); + if (negotiated_dtls_ && !expected_cipher.empty()) { + ASSERT_TRUE(rv); + + ASSERT_EQ(cipher, expected_cipher); + } else { + ASSERT_FALSE(rv); + } + } + } + void SendPackets(size_t channel, size_t size, size_t count, bool srtp) { ASSERT(channel < channels_.size()); rtc::scoped_ptr packet(new char[size]); @@ -433,6 +449,8 @@ class DtlsTransportChannelTest : public testing::Test { client1_.CheckSrtp(""); client2_.CheckSrtp(""); } + client1_.CheckSsl(rtc::SSLStreamAdapter::GetDefaultSslCipher()); + client2_.CheckSsl(rtc::SSLStreamAdapter::GetDefaultSslCipher()); return true; } diff --git a/webrtc/p2p/base/fakesession.h b/webrtc/p2p/base/fakesession.h index 13eceefe19..6f43b65de0 100644 --- a/webrtc/p2p/base/fakesession.h +++ b/webrtc/p2p/base/fakesession.h @@ -246,6 +246,10 @@ class FakeTransportChannel : public TransportChannelImpl, return false; } + virtual bool GetSslCipher(std::string* cipher) { + return false; + } + virtual bool GetLocalIdentity(rtc::SSLIdentity** identity) const { if (!identity_) return false; diff --git a/webrtc/p2p/base/p2ptransportchannel.h b/webrtc/p2p/base/p2ptransportchannel.h index f8756dc02d..cd852d06ae 100644 --- a/webrtc/p2p/base/p2ptransportchannel.h +++ b/webrtc/p2p/base/p2ptransportchannel.h @@ -109,11 +109,16 @@ class P2PTransportChannel : public TransportChannelImpl, return false; } - // Find out which DTLS-SRTP cipher was negotiated + // Find out which DTLS-SRTP cipher was negotiated. virtual bool GetSrtpCipher(std::string* cipher) { return false; } + // Find out which DTLS cipher was negotiated. + virtual bool GetSslCipher(std::string* cipher) { + return false; + } + // Returns false because the channel is not encrypted by default. virtual bool GetLocalIdentity(rtc::SSLIdentity** identity) const { return false; diff --git a/webrtc/p2p/base/rawtransportchannel.h b/webrtc/p2p/base/rawtransportchannel.h index a4d9ce01d0..3455325c51 100644 --- a/webrtc/p2p/base/rawtransportchannel.h +++ b/webrtc/p2p/base/rawtransportchannel.h @@ -114,11 +114,16 @@ class RawTransportChannel : public TransportChannelImpl, return false; } - // Find out which DTLS-SRTP cipher was negotiated + // Find out which DTLS-SRTP cipher was negotiated. virtual bool GetSrtpCipher(std::string* cipher) { return false; } + // Find out which DTLS cipher was negotiated. + virtual bool GetSslCipher(std::string* cipher) { + return false; + } + // Returns false because the channel is not DTLS. virtual bool GetLocalIdentity(rtc::SSLIdentity** identity) const { return false; diff --git a/webrtc/p2p/base/transport.cc b/webrtc/p2p/base/transport.cc index b03e2d5f7a..0569cc0418 100644 --- a/webrtc/p2p/base/transport.cc +++ b/webrtc/p2p/base/transport.cc @@ -454,9 +454,12 @@ bool Transport::GetStats_w(TransportStats* stats) { for (ChannelMap::iterator iter = channels_.begin(); iter != channels_.end(); ++iter) { + ChannelMapEntry& entry = iter->second; TransportChannelStats substats; - substats.component = iter->second->component(); - if (!iter->second->GetStats(&substats.connection_infos)) { + substats.component = entry->component(); + entry->GetSrtpCipher(&substats.srtp_cipher); + entry->GetSslCipher(&substats.ssl_cipher); + if (!entry->GetStats(&substats.connection_infos)) { return false; } stats->channel_stats.push_back(substats); diff --git a/webrtc/p2p/base/transport.h b/webrtc/p2p/base/transport.h index abead7face..32c6bb3570 100644 --- a/webrtc/p2p/base/transport.h +++ b/webrtc/p2p/base/transport.h @@ -106,6 +106,8 @@ typedef std::vector ConnectionInfos; struct TransportChannelStats { int component; ConnectionInfos connection_infos; + std::string srtp_cipher; + std::string ssl_cipher; }; // Information about all the channels of a transport. diff --git a/webrtc/p2p/base/transportchannel.h b/webrtc/p2p/base/transportchannel.h index d26a18534d..3d32b63267 100644 --- a/webrtc/p2p/base/transportchannel.h +++ b/webrtc/p2p/base/transportchannel.h @@ -100,9 +100,12 @@ class TransportChannel : public sigslot::has_slots<> { // Sets up the ciphers to use for DTLS-SRTP. virtual bool SetSrtpCiphers(const std::vector& ciphers) = 0; - // Finds out which DTLS-SRTP cipher was negotiated + // Finds out which DTLS-SRTP cipher was negotiated. virtual bool GetSrtpCipher(std::string* cipher) = 0; + // Finds out which DTLS cipher was negotiated. + virtual bool GetSslCipher(std::string* cipher) = 0; + // Gets a copy of the local SSL identity, owned by the caller. virtual bool GetLocalIdentity(rtc::SSLIdentity** identity) const = 0; diff --git a/webrtc/p2p/base/transportchannelproxy.cc b/webrtc/p2p/base/transportchannelproxy.cc index a8535fa461..a278d96466 100644 --- a/webrtc/p2p/base/transportchannelproxy.cc +++ b/webrtc/p2p/base/transportchannelproxy.cc @@ -186,6 +186,14 @@ bool TransportChannelProxy::GetSrtpCipher(std::string* cipher) { return impl_->GetSrtpCipher(cipher); } +bool TransportChannelProxy::GetSslCipher(std::string* cipher) { + ASSERT(rtc::Thread::Current() == worker_thread_); + if (!impl_) { + return false; + } + return impl_->GetSslCipher(cipher); +} + bool TransportChannelProxy::GetLocalIdentity( rtc::SSLIdentity** identity) const { ASSERT(rtc::Thread::Current() == worker_thread_); diff --git a/webrtc/p2p/base/transportchannelproxy.h b/webrtc/p2p/base/transportchannelproxy.h index 46803f7369..19870028bf 100644 --- a/webrtc/p2p/base/transportchannelproxy.h +++ b/webrtc/p2p/base/transportchannelproxy.h @@ -61,6 +61,7 @@ class TransportChannelProxy : public TransportChannel, virtual bool SetSslRole(rtc::SSLRole role); virtual bool SetSrtpCiphers(const std::vector& ciphers); virtual bool GetSrtpCipher(std::string* cipher); + virtual bool GetSslCipher(std::string* cipher); virtual bool GetLocalIdentity(rtc::SSLIdentity** identity) const; virtual bool GetRemoteCertificate(rtc::SSLCertificate** cert) const; virtual bool ExportKeyingMaterial(const std::string& label,