1*d9f75844SAndroid Build Coastguard Worker /* 2*d9f75844SAndroid Build Coastguard Worker * Copyright 2011 The WebRTC Project Authors. All rights reserved. 3*d9f75844SAndroid Build Coastguard Worker * 4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license 5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source 6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found 7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may 8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree. 9*d9f75844SAndroid Build Coastguard Worker */ 10*d9f75844SAndroid Build Coastguard Worker 11*d9f75844SAndroid Build Coastguard Worker #ifndef P2P_BASE_DTLS_TRANSPORT_H_ 12*d9f75844SAndroid Build Coastguard Worker #define P2P_BASE_DTLS_TRANSPORT_H_ 13*d9f75844SAndroid Build Coastguard Worker 14*d9f75844SAndroid Build Coastguard Worker #include <memory> 15*d9f75844SAndroid Build Coastguard Worker #include <string> 16*d9f75844SAndroid Build Coastguard Worker #include <vector> 17*d9f75844SAndroid Build Coastguard Worker 18*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h" 19*d9f75844SAndroid Build Coastguard Worker #include "api/crypto/crypto_options.h" 20*d9f75844SAndroid Build Coastguard Worker #include "api/dtls_transport_interface.h" 21*d9f75844SAndroid Build Coastguard Worker #include "api/sequence_checker.h" 22*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/dtls_transport_internal.h" 23*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/ice_transport_internal.h" 24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/buffer.h" 25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/buffer_queue.h" 26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_stream_adapter.h" 27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/stream.h" 28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h" 29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/system/no_unique_address.h" 30*d9f75844SAndroid Build Coastguard Worker 31*d9f75844SAndroid Build Coastguard Worker namespace rtc { 32*d9f75844SAndroid Build Coastguard Worker class PacketTransportInternal; 33*d9f75844SAndroid Build Coastguard Worker } 34*d9f75844SAndroid Build Coastguard Worker 35*d9f75844SAndroid Build Coastguard Worker namespace cricket { 36*d9f75844SAndroid Build Coastguard Worker 37*d9f75844SAndroid Build Coastguard Worker // A bridge between a packet-oriented/transport-type interface on 38*d9f75844SAndroid Build Coastguard Worker // the bottom and a StreamInterface on the top. 39*d9f75844SAndroid Build Coastguard Worker class StreamInterfaceChannel : public rtc::StreamInterface { 40*d9f75844SAndroid Build Coastguard Worker public: 41*d9f75844SAndroid Build Coastguard Worker explicit StreamInterfaceChannel(IceTransportInternal* ice_transport); 42*d9f75844SAndroid Build Coastguard Worker 43*d9f75844SAndroid Build Coastguard Worker StreamInterfaceChannel(const StreamInterfaceChannel&) = delete; 44*d9f75844SAndroid Build Coastguard Worker StreamInterfaceChannel& operator=(const StreamInterfaceChannel&) = delete; 45*d9f75844SAndroid Build Coastguard Worker 46*d9f75844SAndroid Build Coastguard Worker // Push in a packet; this gets pulled out from Read(). 47*d9f75844SAndroid Build Coastguard Worker bool OnPacketReceived(const char* data, size_t size); 48*d9f75844SAndroid Build Coastguard Worker 49*d9f75844SAndroid Build Coastguard Worker // Implementations of StreamInterface 50*d9f75844SAndroid Build Coastguard Worker rtc::StreamState GetState() const override; 51*d9f75844SAndroid Build Coastguard Worker void Close() override; 52*d9f75844SAndroid Build Coastguard Worker rtc::StreamResult Read(rtc::ArrayView<uint8_t> buffer, 53*d9f75844SAndroid Build Coastguard Worker size_t& read, 54*d9f75844SAndroid Build Coastguard Worker int& error) override; 55*d9f75844SAndroid Build Coastguard Worker rtc::StreamResult Write(rtc::ArrayView<const uint8_t> data, 56*d9f75844SAndroid Build Coastguard Worker size_t& written, 57*d9f75844SAndroid Build Coastguard Worker int& error) override; 58*d9f75844SAndroid Build Coastguard Worker 59*d9f75844SAndroid Build Coastguard Worker private: 60*d9f75844SAndroid Build Coastguard Worker RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker sequence_checker_; 61*d9f75844SAndroid Build Coastguard Worker IceTransportInternal* const ice_transport_; // owned by DtlsTransport 62*d9f75844SAndroid Build Coastguard Worker rtc::StreamState state_ RTC_GUARDED_BY(sequence_checker_); 63*d9f75844SAndroid Build Coastguard Worker rtc::BufferQueue packets_ RTC_GUARDED_BY(sequence_checker_); 64*d9f75844SAndroid Build Coastguard Worker }; 65*d9f75844SAndroid Build Coastguard Worker 66*d9f75844SAndroid Build Coastguard Worker // This class provides a DTLS SSLStreamAdapter inside a TransportChannel-style 67*d9f75844SAndroid Build Coastguard Worker // packet-based interface, wrapping an existing TransportChannel instance 68*d9f75844SAndroid Build Coastguard Worker // (e.g a P2PTransportChannel) 69*d9f75844SAndroid Build Coastguard Worker // Here's the way this works: 70*d9f75844SAndroid Build Coastguard Worker // 71*d9f75844SAndroid Build Coastguard Worker // DtlsTransport { 72*d9f75844SAndroid Build Coastguard Worker // SSLStreamAdapter* dtls_ { 73*d9f75844SAndroid Build Coastguard Worker // StreamInterfaceChannel downward_ { 74*d9f75844SAndroid Build Coastguard Worker // IceTransportInternal* ice_transport_; 75*d9f75844SAndroid Build Coastguard Worker // } 76*d9f75844SAndroid Build Coastguard Worker // } 77*d9f75844SAndroid Build Coastguard Worker // } 78*d9f75844SAndroid Build Coastguard Worker // 79*d9f75844SAndroid Build Coastguard Worker // - Data which comes into DtlsTransport from the underlying 80*d9f75844SAndroid Build Coastguard Worker // ice_transport_ via OnReadPacket() is checked for whether it is DTLS 81*d9f75844SAndroid Build Coastguard Worker // or not, and if it is, is passed to DtlsTransport::HandleDtlsPacket, 82*d9f75844SAndroid Build Coastguard Worker // which pushes it into to downward_. dtls_ is listening for events on 83*d9f75844SAndroid Build Coastguard Worker // downward_, so it immediately calls downward_->Read(). 84*d9f75844SAndroid Build Coastguard Worker // 85*d9f75844SAndroid Build Coastguard Worker // - Data written to DtlsTransport is passed either to downward_ or directly 86*d9f75844SAndroid Build Coastguard Worker // to ice_transport_, depending on whether DTLS is negotiated and whether 87*d9f75844SAndroid Build Coastguard Worker // the flags include PF_SRTP_BYPASS 88*d9f75844SAndroid Build Coastguard Worker // 89*d9f75844SAndroid Build Coastguard Worker // - The SSLStreamAdapter writes to downward_->Write() which translates it 90*d9f75844SAndroid Build Coastguard Worker // into packet writes on ice_transport_. 91*d9f75844SAndroid Build Coastguard Worker // 92*d9f75844SAndroid Build Coastguard Worker // This class is not thread safe; all methods must be called on the same thread 93*d9f75844SAndroid Build Coastguard Worker // as the constructor. 94*d9f75844SAndroid Build Coastguard Worker class DtlsTransport : public DtlsTransportInternal { 95*d9f75844SAndroid Build Coastguard Worker public: 96*d9f75844SAndroid Build Coastguard Worker // `ice_transport` is the ICE transport this DTLS transport is wrapping. It 97*d9f75844SAndroid Build Coastguard Worker // must outlive this DTLS transport. 98*d9f75844SAndroid Build Coastguard Worker // 99*d9f75844SAndroid Build Coastguard Worker // `crypto_options` are the options used for the DTLS handshake. This affects 100*d9f75844SAndroid Build Coastguard Worker // whether GCM crypto suites are negotiated. 101*d9f75844SAndroid Build Coastguard Worker // 102*d9f75844SAndroid Build Coastguard Worker // `event_log` is an optional RtcEventLog for logging state changes. It should 103*d9f75844SAndroid Build Coastguard Worker // outlive the DtlsTransport. 104*d9f75844SAndroid Build Coastguard Worker DtlsTransport( 105*d9f75844SAndroid Build Coastguard Worker IceTransportInternal* ice_transport, 106*d9f75844SAndroid Build Coastguard Worker const webrtc::CryptoOptions& crypto_options, 107*d9f75844SAndroid Build Coastguard Worker webrtc::RtcEventLog* event_log, 108*d9f75844SAndroid Build Coastguard Worker rtc::SSLProtocolVersion max_version = rtc::SSL_PROTOCOL_DTLS_12); 109*d9f75844SAndroid Build Coastguard Worker 110*d9f75844SAndroid Build Coastguard Worker ~DtlsTransport() override; 111*d9f75844SAndroid Build Coastguard Worker 112*d9f75844SAndroid Build Coastguard Worker DtlsTransport(const DtlsTransport&) = delete; 113*d9f75844SAndroid Build Coastguard Worker DtlsTransport& operator=(const DtlsTransport&) = delete; 114*d9f75844SAndroid Build Coastguard Worker 115*d9f75844SAndroid Build Coastguard Worker webrtc::DtlsTransportState dtls_state() const override; 116*d9f75844SAndroid Build Coastguard Worker const std::string& transport_name() const override; 117*d9f75844SAndroid Build Coastguard Worker int component() const override; 118*d9f75844SAndroid Build Coastguard Worker 119*d9f75844SAndroid Build Coastguard Worker // DTLS is active if a local certificate was set. Otherwise this acts in a 120*d9f75844SAndroid Build Coastguard Worker // "passthrough" mode, sending packets directly through the underlying ICE 121*d9f75844SAndroid Build Coastguard Worker // transport. 122*d9f75844SAndroid Build Coastguard Worker // TODO(deadbeef): Remove this weirdness, and handle it in the upper layers. 123*d9f75844SAndroid Build Coastguard Worker bool IsDtlsActive() const override; 124*d9f75844SAndroid Build Coastguard Worker 125*d9f75844SAndroid Build Coastguard Worker // SetLocalCertificate is what makes DTLS active. It must be called before 126*d9f75844SAndroid Build Coastguard Worker // SetRemoteFinterprint. 127*d9f75844SAndroid Build Coastguard Worker // TODO(deadbeef): Once DtlsTransport no longer has the concept of being 128*d9f75844SAndroid Build Coastguard Worker // "active" or not (acting as a passthrough if not active), just require this 129*d9f75844SAndroid Build Coastguard Worker // certificate on construction or "Start". 130*d9f75844SAndroid Build Coastguard Worker bool SetLocalCertificate( 131*d9f75844SAndroid Build Coastguard Worker const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override; 132*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override; 133*d9f75844SAndroid Build Coastguard Worker 134*d9f75844SAndroid Build Coastguard Worker // SetRemoteFingerprint must be called after SetLocalCertificate, and any 135*d9f75844SAndroid Build Coastguard Worker // other methods like SetDtlsRole. It's what triggers the actual DTLS setup. 136*d9f75844SAndroid Build Coastguard Worker // TODO(deadbeef): Rename to "Start" like in ORTC? 137*d9f75844SAndroid Build Coastguard Worker bool SetRemoteFingerprint(absl::string_view digest_alg, 138*d9f75844SAndroid Build Coastguard Worker const uint8_t* digest, 139*d9f75844SAndroid Build Coastguard Worker size_t digest_len) override; 140*d9f75844SAndroid Build Coastguard Worker 141*d9f75844SAndroid Build Coastguard Worker // SetRemoteParameters must be called after SetLocalCertificate. 142*d9f75844SAndroid Build Coastguard Worker webrtc::RTCError SetRemoteParameters( 143*d9f75844SAndroid Build Coastguard Worker absl::string_view digest_alg, 144*d9f75844SAndroid Build Coastguard Worker const uint8_t* digest, 145*d9f75844SAndroid Build Coastguard Worker size_t digest_len, 146*d9f75844SAndroid Build Coastguard Worker absl::optional<rtc::SSLRole> role) override; 147*d9f75844SAndroid Build Coastguard Worker 148*d9f75844SAndroid Build Coastguard Worker // Called to send a packet (via DTLS, if turned on). 149*d9f75844SAndroid Build Coastguard Worker int SendPacket(const char* data, 150*d9f75844SAndroid Build Coastguard Worker size_t size, 151*d9f75844SAndroid Build Coastguard Worker const rtc::PacketOptions& options, 152*d9f75844SAndroid Build Coastguard Worker int flags) override; 153*d9f75844SAndroid Build Coastguard Worker 154*d9f75844SAndroid Build Coastguard Worker bool GetOption(rtc::Socket::Option opt, int* value) override; 155*d9f75844SAndroid Build Coastguard Worker 156*d9f75844SAndroid Build Coastguard Worker // Find out which TLS version was negotiated 157*d9f75844SAndroid Build Coastguard Worker bool GetSslVersionBytes(int* version) const override; 158*d9f75844SAndroid Build Coastguard Worker // Find out which DTLS-SRTP cipher was negotiated 159*d9f75844SAndroid Build Coastguard Worker bool GetSrtpCryptoSuite(int* cipher) override; 160*d9f75844SAndroid Build Coastguard Worker 161*d9f75844SAndroid Build Coastguard Worker bool GetDtlsRole(rtc::SSLRole* role) const override; 162*d9f75844SAndroid Build Coastguard Worker bool SetDtlsRole(rtc::SSLRole role) override; 163*d9f75844SAndroid Build Coastguard Worker 164*d9f75844SAndroid Build Coastguard Worker // Find out which DTLS cipher was negotiated 165*d9f75844SAndroid Build Coastguard Worker bool GetSslCipherSuite(int* cipher) override; 166*d9f75844SAndroid Build Coastguard Worker 167*d9f75844SAndroid Build Coastguard Worker // Once DTLS has been established, this method retrieves the certificate 168*d9f75844SAndroid Build Coastguard Worker // chain in use by the remote peer, for use in external identity 169*d9f75844SAndroid Build Coastguard Worker // verification. 170*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override; 171*d9f75844SAndroid Build Coastguard Worker 172*d9f75844SAndroid Build Coastguard Worker // Once DTLS has established (i.e., this ice_transport is writable), this 173*d9f75844SAndroid Build Coastguard Worker // method extracts the keys negotiated during the DTLS handshake, for use in 174*d9f75844SAndroid Build Coastguard Worker // external encryption. DTLS-SRTP uses this to extract the needed SRTP keys. 175*d9f75844SAndroid Build Coastguard Worker // See the SSLStreamAdapter documentation for info on the specific parameters. 176*d9f75844SAndroid Build Coastguard Worker bool ExportKeyingMaterial(absl::string_view label, 177*d9f75844SAndroid Build Coastguard Worker const uint8_t* context, 178*d9f75844SAndroid Build Coastguard Worker size_t context_len, 179*d9f75844SAndroid Build Coastguard Worker bool use_context, 180*d9f75844SAndroid Build Coastguard Worker uint8_t* result, 181*d9f75844SAndroid Build Coastguard Worker size_t result_len) override; 182*d9f75844SAndroid Build Coastguard Worker 183*d9f75844SAndroid Build Coastguard Worker IceTransportInternal* ice_transport() override; 184*d9f75844SAndroid Build Coastguard Worker 185*d9f75844SAndroid Build Coastguard Worker // For informational purposes. Tells if the DTLS handshake has finished. 186*d9f75844SAndroid Build Coastguard Worker // This may be true even if writable() is false, if the remote fingerprint 187*d9f75844SAndroid Build Coastguard Worker // has not yet been verified. 188*d9f75844SAndroid Build Coastguard Worker bool IsDtlsConnected(); 189*d9f75844SAndroid Build Coastguard Worker 190*d9f75844SAndroid Build Coastguard Worker bool receiving() const override; 191*d9f75844SAndroid Build Coastguard Worker bool writable() const override; 192*d9f75844SAndroid Build Coastguard Worker 193*d9f75844SAndroid Build Coastguard Worker int GetError() override; 194*d9f75844SAndroid Build Coastguard Worker 195*d9f75844SAndroid Build Coastguard Worker absl::optional<rtc::NetworkRoute> network_route() const override; 196*d9f75844SAndroid Build Coastguard Worker 197*d9f75844SAndroid Build Coastguard Worker int SetOption(rtc::Socket::Option opt, int value) override; 198*d9f75844SAndroid Build Coastguard Worker ToString()199*d9f75844SAndroid Build Coastguard Worker std::string ToString() const { 200*d9f75844SAndroid Build Coastguard Worker const absl::string_view RECEIVING_ABBREV[2] = {"_", "R"}; 201*d9f75844SAndroid Build Coastguard Worker const absl::string_view WRITABLE_ABBREV[2] = {"_", "W"}; 202*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder sb; 203*d9f75844SAndroid Build Coastguard Worker sb << "DtlsTransport[" << transport_name() << "|" << component_ << "|" 204*d9f75844SAndroid Build Coastguard Worker << RECEIVING_ABBREV[receiving()] << WRITABLE_ABBREV[writable()] << "]"; 205*d9f75844SAndroid Build Coastguard Worker return sb.Release(); 206*d9f75844SAndroid Build Coastguard Worker } 207*d9f75844SAndroid Build Coastguard Worker 208*d9f75844SAndroid Build Coastguard Worker private: 209*d9f75844SAndroid Build Coastguard Worker void ConnectToIceTransport(); 210*d9f75844SAndroid Build Coastguard Worker 211*d9f75844SAndroid Build Coastguard Worker void OnWritableState(rtc::PacketTransportInternal* transport); 212*d9f75844SAndroid Build Coastguard Worker void OnReadPacket(rtc::PacketTransportInternal* transport, 213*d9f75844SAndroid Build Coastguard Worker const char* data, 214*d9f75844SAndroid Build Coastguard Worker size_t size, 215*d9f75844SAndroid Build Coastguard Worker const int64_t& packet_time_us, 216*d9f75844SAndroid Build Coastguard Worker int flags); 217*d9f75844SAndroid Build Coastguard Worker void OnSentPacket(rtc::PacketTransportInternal* transport, 218*d9f75844SAndroid Build Coastguard Worker const rtc::SentPacket& sent_packet); 219*d9f75844SAndroid Build Coastguard Worker void OnReadyToSend(rtc::PacketTransportInternal* transport); 220*d9f75844SAndroid Build Coastguard Worker void OnReceivingState(rtc::PacketTransportInternal* transport); 221*d9f75844SAndroid Build Coastguard Worker void OnDtlsEvent(rtc::StreamInterface* stream_, int sig, int err); 222*d9f75844SAndroid Build Coastguard Worker void OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route); 223*d9f75844SAndroid Build Coastguard Worker bool SetupDtls(); 224*d9f75844SAndroid Build Coastguard Worker void MaybeStartDtls(); 225*d9f75844SAndroid Build Coastguard Worker bool HandleDtlsPacket(const char* data, size_t size); 226*d9f75844SAndroid Build Coastguard Worker void OnDtlsHandshakeError(rtc::SSLHandshakeError error); 227*d9f75844SAndroid Build Coastguard Worker void ConfigureHandshakeTimeout(); 228*d9f75844SAndroid Build Coastguard Worker 229*d9f75844SAndroid Build Coastguard Worker void set_receiving(bool receiving); 230*d9f75844SAndroid Build Coastguard Worker void set_writable(bool writable); 231*d9f75844SAndroid Build Coastguard Worker // Sets the DTLS state, signaling if necessary. 232*d9f75844SAndroid Build Coastguard Worker void set_dtls_state(webrtc::DtlsTransportState state); 233*d9f75844SAndroid Build Coastguard Worker 234*d9f75844SAndroid Build Coastguard Worker webrtc::SequenceChecker thread_checker_; 235*d9f75844SAndroid Build Coastguard Worker 236*d9f75844SAndroid Build Coastguard Worker const int component_; 237*d9f75844SAndroid Build Coastguard Worker webrtc::DtlsTransportState dtls_state_ = webrtc::DtlsTransportState::kNew; 238*d9f75844SAndroid Build Coastguard Worker // Underlying ice_transport, not owned by this class. 239*d9f75844SAndroid Build Coastguard Worker IceTransportInternal* const ice_transport_; 240*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<rtc::SSLStreamAdapter> dtls_; // The DTLS stream 241*d9f75844SAndroid Build Coastguard Worker StreamInterfaceChannel* 242*d9f75844SAndroid Build Coastguard Worker downward_; // Wrapper for ice_transport_, owned by dtls_. 243*d9f75844SAndroid Build Coastguard Worker const std::vector<int> srtp_ciphers_; // SRTP ciphers to use with DTLS. 244*d9f75844SAndroid Build Coastguard Worker bool dtls_active_ = false; 245*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<rtc::RTCCertificate> local_certificate_; 246*d9f75844SAndroid Build Coastguard Worker absl::optional<rtc::SSLRole> dtls_role_; 247*d9f75844SAndroid Build Coastguard Worker const rtc::SSLProtocolVersion ssl_max_version_; 248*d9f75844SAndroid Build Coastguard Worker rtc::Buffer remote_fingerprint_value_; 249*d9f75844SAndroid Build Coastguard Worker std::string remote_fingerprint_algorithm_; 250*d9f75844SAndroid Build Coastguard Worker 251*d9f75844SAndroid Build Coastguard Worker // Cached DTLS ClientHello packet that was received before we started the 252*d9f75844SAndroid Build Coastguard Worker // DTLS handshake. This could happen if the hello was received before the 253*d9f75844SAndroid Build Coastguard Worker // ice transport became writable, or before a remote fingerprint was received. 254*d9f75844SAndroid Build Coastguard Worker rtc::Buffer cached_client_hello_; 255*d9f75844SAndroid Build Coastguard Worker 256*d9f75844SAndroid Build Coastguard Worker bool receiving_ = false; 257*d9f75844SAndroid Build Coastguard Worker bool writable_ = false; 258*d9f75844SAndroid Build Coastguard Worker 259*d9f75844SAndroid Build Coastguard Worker webrtc::RtcEventLog* const event_log_; 260*d9f75844SAndroid Build Coastguard Worker }; 261*d9f75844SAndroid Build Coastguard Worker 262*d9f75844SAndroid Build Coastguard Worker } // namespace cricket 263*d9f75844SAndroid Build Coastguard Worker 264*d9f75844SAndroid Build Coastguard Worker #endif // P2P_BASE_DTLS_TRANSPORT_H_ 265