blob: 609f3d72150863d025a0a77c01924ee2cf6a02ab [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef P2P_BASE_DTLSTRANSPORT_H_
12#define P2P_BASE_DTLSTRANSPORT_H_
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000013
jbauch555604a2016-04-26 03:13:22 -070014#include <memory>
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000015#include <string>
16#include <vector>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "p2p/base/dtlstransportinternal.h"
19#include "p2p/base/icetransportinternal.h"
20#include "rtc_base/buffer.h"
21#include "rtc_base/bufferqueue.h"
22#include "rtc_base/constructormagic.h"
23#include "rtc_base/sslstreamadapter.h"
24#include "rtc_base/stream.h"
Steve Antonf7a64ec2018-07-19 15:42:17 -070025#include "rtc_base/thread_checker.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000026
johand89ab142016-10-25 10:50:32 -070027namespace rtc {
deadbeef5bd5ca32017-02-10 11:31:50 -080028class PacketTransportInternal;
johand89ab142016-10-25 10:50:32 -070029}
30
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000031namespace cricket {
32
zhihuangd06adf62017-01-12 15:58:31 -080033// A bridge between a packet-oriented/transport-type interface on
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000034// the bottom and a StreamInterface on the top.
Joachim Bauch6f2ef742015-05-21 17:52:01 +020035class StreamInterfaceChannel : public rtc::StreamInterface {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000036 public:
zhihuangb2cdd932017-01-19 16:54:25 -080037 explicit StreamInterfaceChannel(IceTransportInternal* ice_transport);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000038
39 // Push in a packet; this gets pulled out from Read().
40 bool OnPacketReceived(const char* data, size_t size);
41
42 // Implementations of StreamInterface
Steve Anton33f69db2017-10-30 10:01:15 -070043 rtc::StreamState GetState() const override;
guoweis4cc9f982016-02-24 11:10:06 -080044 void Close() override;
deadbeefcbecd352015-09-23 11:50:27 -070045 rtc::StreamResult Read(void* buffer,
46 size_t buffer_len,
47 size_t* read,
48 int* error) override;
49 rtc::StreamResult Write(const void* data,
50 size_t data_len,
51 size_t* written,
52 int* error) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000053
54 private:
zhihuangb2cdd932017-01-19 16:54:25 -080055 IceTransportInternal* ice_transport_; // owned by DtlsTransport
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000056 rtc::StreamState state_;
Joachim Bauch6f2ef742015-05-21 17:52:01 +020057 rtc::BufferQueue packets_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000058
henrikg3c089d72015-09-16 05:37:44 -070059 RTC_DISALLOW_COPY_AND_ASSIGN(StreamInterfaceChannel);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000060};
61
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000062// This class provides a DTLS SSLStreamAdapter inside a TransportChannel-style
63// packet-based interface, wrapping an existing TransportChannel instance
64// (e.g a P2PTransportChannel)
65// Here's the way this works:
66//
zhihuangb2cdd932017-01-19 16:54:25 -080067// DtlsTransport {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000068// SSLStreamAdapter* dtls_ {
69// StreamInterfaceChannel downward_ {
zhihuangb2cdd932017-01-19 16:54:25 -080070// IceTransportInternal* ice_transport_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000071// }
72// }
73// }
74//
zhihuangb2cdd932017-01-19 16:54:25 -080075// - Data which comes into DtlsTransport from the underlying
76// ice_transport_ via OnReadPacket() is checked for whether it is DTLS
77// or not, and if it is, is passed to DtlsTransport::HandleDtlsPacket,
78// which pushes it into to downward_. dtls_ is listening for events on
79// downward_, so it immediately calls downward_->Read().
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000080//
zhihuangb2cdd932017-01-19 16:54:25 -080081// - Data written to DtlsTransport is passed either to downward_ or directly
82// to ice_transport_, depending on whether DTLS is negotiated and whether
83// the flags include PF_SRTP_BYPASS
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000084//
zhihuangb2cdd932017-01-19 16:54:25 -080085// - The SSLStreamAdapter writes to downward_->Write() which translates it
86// into packet writes on ice_transport_.
Steve Antonf7a64ec2018-07-19 15:42:17 -070087//
88// This class is not thread safe; all methods must be called on the same thread
89// as the constructor.
zhihuangb2cdd932017-01-19 16:54:25 -080090class DtlsTransport : public DtlsTransportInternal {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000091 public:
deadbeef7914b8c2017-04-21 03:23:33 -070092 // |ice_transport| is the ICE transport this DTLS transport is wrapping.
93 //
94 // |crypto_options| are the options used for the DTLS handshake. This affects
95 // whether GCM crypto suites are negotiated.
Zhi Huange818b6e2018-02-22 15:26:27 -080096 // TODO(zhihuang): Remove this once we switch to JsepTransportController.
deadbeef7914b8c2017-04-21 03:23:33 -070097 explicit DtlsTransport(IceTransportInternal* ice_transport,
98 const rtc::CryptoOptions& crypto_options);
Zhi Huange818b6e2018-02-22 15:26:27 -080099 explicit DtlsTransport(std::unique_ptr<IceTransportInternal> ice_transport,
100 const rtc::CryptoOptions& crypto_options);
101
zhihuangb2cdd932017-01-19 16:54:25 -0800102 ~DtlsTransport() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000103
Steve Anton33f69db2017-10-30 10:01:15 -0700104 const rtc::CryptoOptions& crypto_options() const override;
105 DtlsTransportState dtls_state() const override;
106 const std::string& transport_name() const override;
107 int component() const override;
zhihuangb2cdd932017-01-19 16:54:25 -0800108
Taylor Brandstetter74cefe12017-12-14 15:38:57 -0800109 // DTLS is active if a local certificate was set. Otherwise this acts in a
110 // "passthrough" mode, sending packets directly through the underlying ICE
111 // transport.
112 // TODO(deadbeef): Remove this weirdness, and handle it in the upper layers.
Steve Anton33f69db2017-10-30 10:01:15 -0700113 bool IsDtlsActive() const override;
zhihuangb2cdd932017-01-19 16:54:25 -0800114
Taylor Brandstetter74cefe12017-12-14 15:38:57 -0800115 // SetLocalCertificate is what makes DTLS active. It must be called before
116 // SetRemoteFinterprint.
117 // TODO(deadbeef): Once DtlsTransport no longer has the concept of being
118 // "active" or not (acting as a passthrough if not active), just require this
119 // certificate on construction or "Start".
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200120 bool SetLocalCertificate(
121 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override;
122 rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000123
Taylor Brandstetter74cefe12017-12-14 15:38:57 -0800124 // SetRemoteFingerprint must be called after SetLocalCertificate, and any
Zhi Huange818b6e2018-02-22 15:26:27 -0800125 // other methods like SetDtlsRole. It's what triggers the actual DTLS setup.
Taylor Brandstetter74cefe12017-12-14 15:38:57 -0800126 // TODO(deadbeef): Rename to "Start" like in ORTC?
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200127 bool SetRemoteFingerprint(const std::string& digest_alg,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200128 const uint8_t* digest,
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200129 size_t digest_len) override;
deadbeef2b558672015-10-26 17:23:29 -0700130
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000131 // Called to send a packet (via DTLS, if turned on).
deadbeefcbecd352015-09-23 11:50:27 -0700132 int SendPacket(const char* data,
133 size_t size,
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200134 const rtc::PacketOptions& options,
135 int flags) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000136
Steve Anton33f69db2017-10-30 10:01:15 -0700137 bool GetOption(rtc::Socket::Option opt, int* value) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000138
Zhi Huange818b6e2018-02-22 15:26:27 -0800139 bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) override;
Joachim Bauch831c5582015-05-20 12:48:41 +0200140
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000141 // Find out which DTLS-SRTP cipher was negotiated
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800142 bool GetSrtpCryptoSuite(int* cipher) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000143
Zhi Huange818b6e2018-02-22 15:26:27 -0800144 bool GetDtlsRole(rtc::SSLRole* role) const override;
145 bool SetDtlsRole(rtc::SSLRole role) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000146
pthatcher@webrtc.org3ee4fe52015-02-11 22:34:36 +0000147 // Find out which DTLS cipher was negotiated
Guo-wei Shieh6caafbe2015-10-05 12:43:27 -0700148 bool GetSslCipherSuite(int* cipher) override;
pthatcher@webrtc.org3ee4fe52015-02-11 22:34:36 +0000149
Taylor Brandstetterc3928662018-02-23 13:04:51 -0800150 // Once DTLS has been established, this method retrieves the certificate
151 // chain in use by the remote peer, for use in external identity
152 // verification.
Zhi Huang70b820f2018-01-27 14:16:15 -0800153 std::unique_ptr<rtc::SSLCertChain> GetRemoteSSLCertChain() const override;
154
zhihuangb2cdd932017-01-19 16:54:25 -0800155 // Once DTLS has established (i.e., this ice_transport is writable), this
156 // method extracts the keys negotiated during the DTLS handshake, for use in
157 // external encryption. DTLS-SRTP uses this to extract the needed SRTP keys.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000158 // See the SSLStreamAdapter documentation for info on the specific parameters.
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200159 bool ExportKeyingMaterial(const std::string& label,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200160 const uint8_t* context,
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200161 size_t context_len,
162 bool use_context,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200163 uint8_t* result,
Steve Anton33f69db2017-10-30 10:01:15 -0700164 size_t result_len) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000165
Steve Anton33f69db2017-10-30 10:01:15 -0700166 IceTransportInternal* ice_transport() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000167
deadbeef89824f62016-09-30 11:55:43 -0700168 // For informational purposes. Tells if the DTLS handshake has finished.
169 // This may be true even if writable() is false, if the remote fingerprint
170 // has not yet been verified.
171 bool IsDtlsConnected();
172
Steve Anton33f69db2017-10-30 10:01:15 -0700173 bool receiving() const override;
174 bool writable() const override;
zhihuangb2cdd932017-01-19 16:54:25 -0800175
Steve Anton33f69db2017-10-30 10:01:15 -0700176 int GetError() override;
zhihuangb2cdd932017-01-19 16:54:25 -0800177
Danil Chapovalov00c71832018-06-15 15:58:38 +0200178 absl::optional<rtc::NetworkRoute> network_route() const override;
Zhi Huang942bc2e2017-11-13 13:26:07 -0800179
Steve Anton33f69db2017-10-30 10:01:15 -0700180 int SetOption(rtc::Socket::Option opt, int value) override;
zhihuangb2cdd932017-01-19 16:54:25 -0800181
zhihuangb2cdd932017-01-19 16:54:25 -0800182 std::string ToString() const {
183 const char RECEIVING_ABBREV[2] = {'_', 'R'};
184 const char WRITABLE_ABBREV[2] = {'_', 'W'};
185 std::stringstream ss;
186 ss << "DtlsTransport[" << transport_name_ << "|" << component_ << "|"
187 << RECEIVING_ABBREV[receiving()] << WRITABLE_ABBREV[writable()] << "]";
188 return ss.str();
189 }
190
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000191 private:
Zhi Huange818b6e2018-02-22 15:26:27 -0800192 void ConnectToIceTransport();
193
deadbeef5bd5ca32017-02-10 11:31:50 -0800194 void OnWritableState(rtc::PacketTransportInternal* transport);
195 void OnReadPacket(rtc::PacketTransportInternal* transport,
johand89ab142016-10-25 10:50:32 -0700196 const char* data,
197 size_t size,
198 const rtc::PacketTime& packet_time,
199 int flags);
deadbeef5bd5ca32017-02-10 11:31:50 -0800200 void OnSentPacket(rtc::PacketTransportInternal* transport,
stefanc1aeaf02015-10-15 07:26:07 -0700201 const rtc::SentPacket& sent_packet);
deadbeef5bd5ca32017-02-10 11:31:50 -0800202 void OnReadyToSend(rtc::PacketTransportInternal* transport);
203 void OnReceivingState(rtc::PacketTransportInternal* transport);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000204 void OnDtlsEvent(rtc::StreamInterface* stream_, int sig, int err);
Danil Chapovalov00c71832018-06-15 15:58:38 +0200205 void OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000206 bool SetupDtls();
deadbeef367efdc2016-07-13 12:10:17 -0700207 void MaybeStartDtls();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000208 bool HandleDtlsPacket(const char* data, size_t size);
zhihuangd82eee02016-08-26 11:25:05 -0700209 void OnDtlsHandshakeError(rtc::SSLHandshakeError error);
skvladd0309122017-02-02 17:18:37 -0800210 void ConfigureHandshakeTimeout();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000211
zhihuangb2cdd932017-01-19 16:54:25 -0800212 void set_receiving(bool receiving);
213 void set_writable(bool writable);
214 // Sets the DTLS state, signaling if necessary.
215 void set_dtls_state(DtlsTransportState state);
216
Steve Antonf7a64ec2018-07-19 15:42:17 -0700217 rtc::ThreadChecker thread_checker_;
218
zhihuangb2cdd932017-01-19 16:54:25 -0800219 std::string transport_name_;
220 int component_;
221 DtlsTransportState dtls_state_ = DTLS_TRANSPORT_NEW;
zhihuangb2cdd932017-01-19 16:54:25 -0800222 // Underlying ice_transport, not owned by this class.
223 IceTransportInternal* const ice_transport_;
Zhi Huange818b6e2018-02-22 15:26:27 -0800224 std::unique_ptr<IceTransportInternal> owned_ice_transport_;
jbauch555604a2016-04-26 03:13:22 -0700225 std::unique_ptr<rtc::SSLStreamAdapter> dtls_; // The DTLS stream
zhihuangb2cdd932017-01-19 16:54:25 -0800226 StreamInterfaceChannel*
227 downward_; // Wrapper for ice_transport_, owned by dtls_.
zhihuangca6d3b62017-08-23 18:05:50 -0700228 std::vector<int> srtp_ciphers_; // SRTP ciphers to use with DTLS.
deadbeef2b558672015-10-26 17:23:29 -0700229 bool dtls_active_ = false;
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200230 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate_;
Danil Chapovalov00c71832018-06-15 15:58:38 +0200231 absl::optional<rtc::SSLRole> dtls_role_;
Joachim Bauch831c5582015-05-20 12:48:41 +0200232 rtc::SSLProtocolVersion ssl_max_version_;
jbauch5869f502017-06-29 12:31:36 -0700233 rtc::CryptoOptions crypto_options_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000234 rtc::Buffer remote_fingerprint_value_;
235 std::string remote_fingerprint_algorithm_;
236
deadbeefe84cd2e2016-05-04 17:16:34 -0700237 // Cached DTLS ClientHello packet that was received before we started the
238 // DTLS handshake. This could happen if the hello was received before the
zhihuangb2cdd932017-01-19 16:54:25 -0800239 // ice transport became writable, or before a remote fingerprint was received.
deadbeefe84cd2e2016-05-04 17:16:34 -0700240 rtc::Buffer cached_client_hello_;
241
zhihuangb2cdd932017-01-19 16:54:25 -0800242 bool receiving_ = false;
243 bool writable_ = false;
244
245 RTC_DISALLOW_COPY_AND_ASSIGN(DtlsTransport);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000246};
247
248} // namespace cricket
249
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200250#endif // P2P_BASE_DTLSTRANSPORT_H_