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