• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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