blob: 4c0432c3d7d8806bf3e1d3b77cbfcfa34f20a949 [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
zhihuangca6d3b62017-08-23 18:05:50 -070011#ifndef WEBRTC_P2P_BASE_DTLSTRANSPORT_H_
12#define WEBRTC_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
zhihuangb2cdd932017-01-19 16:54:25 -080018#include "webrtc/p2p/base/dtlstransportinternal.h"
zhihuangd06adf62017-01-12 15:58:31 -080019#include "webrtc/p2p/base/icetransportinternal.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020020#include "webrtc/rtc_base/buffer.h"
21#include "webrtc/rtc_base/bufferqueue.h"
22#include "webrtc/rtc_base/constructormagic.h"
23#include "webrtc/rtc_base/sslstreamadapter.h"
24#include "webrtc/rtc_base/stream.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000025
johand89ab142016-10-25 10:50:32 -070026namespace rtc {
deadbeef5bd5ca32017-02-10 11:31:50 -080027class PacketTransportInternal;
johand89ab142016-10-25 10:50:32 -070028}
29
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000030namespace cricket {
31
zhihuangd06adf62017-01-12 15:58:31 -080032// A bridge between a packet-oriented/transport-type interface on
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000033// the bottom and a StreamInterface on the top.
Joachim Bauch6f2ef742015-05-21 17:52:01 +020034class StreamInterfaceChannel : public rtc::StreamInterface {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000035 public:
zhihuangb2cdd932017-01-19 16:54:25 -080036 explicit StreamInterfaceChannel(IceTransportInternal* ice_transport);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000037
38 // Push in a packet; this gets pulled out from Read().
39 bool OnPacketReceived(const char* data, size_t size);
40
41 // Implementations of StreamInterface
Henrik Boströmf3ecdb92015-09-08 12:11:54 +020042 rtc::StreamState GetState() const override { return state_; }
guoweis4cc9f982016-02-24 11:10:06 -080043 void Close() override;
deadbeefcbecd352015-09-23 11:50:27 -070044 rtc::StreamResult Read(void* buffer,
45 size_t buffer_len,
46 size_t* read,
47 int* error) override;
48 rtc::StreamResult Write(const void* data,
49 size_t data_len,
50 size_t* written,
51 int* error) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000052
53 private:
zhihuangb2cdd932017-01-19 16:54:25 -080054 IceTransportInternal* ice_transport_; // owned by DtlsTransport
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000055 rtc::StreamState state_;
Joachim Bauch6f2ef742015-05-21 17:52:01 +020056 rtc::BufferQueue packets_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000057
henrikg3c089d72015-09-16 05:37:44 -070058 RTC_DISALLOW_COPY_AND_ASSIGN(StreamInterfaceChannel);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000059};
60
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000061// This class provides a DTLS SSLStreamAdapter inside a TransportChannel-style
62// packet-based interface, wrapping an existing TransportChannel instance
63// (e.g a P2PTransportChannel)
64// Here's the way this works:
65//
zhihuangb2cdd932017-01-19 16:54:25 -080066// DtlsTransport {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000067// SSLStreamAdapter* dtls_ {
68// StreamInterfaceChannel downward_ {
zhihuangb2cdd932017-01-19 16:54:25 -080069// IceTransportInternal* ice_transport_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000070// }
71// }
72// }
73//
zhihuangb2cdd932017-01-19 16:54:25 -080074// - Data which comes into DtlsTransport from the underlying
75// ice_transport_ via OnReadPacket() is checked for whether it is DTLS
76// or not, and if it is, is passed to DtlsTransport::HandleDtlsPacket,
77// which pushes it into to downward_. dtls_ is listening for events on
78// downward_, so it immediately calls downward_->Read().
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000079//
zhihuangb2cdd932017-01-19 16:54:25 -080080// - Data written to DtlsTransport is passed either to downward_ or directly
81// to ice_transport_, depending on whether DTLS is negotiated and whether
82// the flags include PF_SRTP_BYPASS
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000083//
zhihuangb2cdd932017-01-19 16:54:25 -080084// - The SSLStreamAdapter writes to downward_->Write() which translates it
85// into packet writes on ice_transport_.
86class DtlsTransport : public DtlsTransportInternal {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000087 public:
deadbeef7914b8c2017-04-21 03:23:33 -070088 // |ice_transport| is the ICE transport this DTLS transport is wrapping.
89 //
90 // |crypto_options| are the options used for the DTLS handshake. This affects
91 // whether GCM crypto suites are negotiated.
92 explicit DtlsTransport(IceTransportInternal* ice_transport,
93 const rtc::CryptoOptions& crypto_options);
zhihuangb2cdd932017-01-19 16:54:25 -080094 ~DtlsTransport() override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000095
jbauch5869f502017-06-29 12:31:36 -070096 const rtc::CryptoOptions& crypto_options() const override {
97 return crypto_options_;
98 }
99
zhihuangb2cdd932017-01-19 16:54:25 -0800100 DtlsTransportState dtls_state() const override { return dtls_state_; }
101
102 const std::string& transport_name() const override { return transport_name_; }
103
104 int component() const override { return component_; }
105
106 // Returns false if no local certificate was set, or if the peer doesn't
107 // support DTLS.
108 bool IsDtlsActive() const override { return dtls_active_; }
109
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200110 bool SetLocalCertificate(
111 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) override;
112 rtc::scoped_refptr<rtc::RTCCertificate> GetLocalCertificate() const override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000113
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200114 bool SetRemoteFingerprint(const std::string& digest_alg,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200115 const uint8_t* digest,
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200116 size_t digest_len) override;
deadbeef2b558672015-10-26 17:23:29 -0700117
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000118 // Called to send a packet (via DTLS, if turned on).
deadbeefcbecd352015-09-23 11:50:27 -0700119 int SendPacket(const char* data,
120 size_t size,
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200121 const rtc::PacketOptions& options,
122 int flags) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000123
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200124 bool GetOption(rtc::Socket::Option opt, int* value) override {
zhihuangb2cdd932017-01-19 16:54:25 -0800125 return ice_transport_->GetOption(opt, value);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000126 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000127
Joachim Bauch04e5b492015-05-29 09:40:39 +0200128 virtual bool SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version);
Joachim Bauch831c5582015-05-20 12:48:41 +0200129
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000130 // Find out which DTLS-SRTP cipher was negotiated
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800131 bool GetSrtpCryptoSuite(int* cipher) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000132
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200133 bool GetSslRole(rtc::SSLRole* role) const override;
134 bool SetSslRole(rtc::SSLRole role) override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000135
pthatcher@webrtc.org3ee4fe52015-02-11 22:34:36 +0000136 // Find out which DTLS cipher was negotiated
Guo-wei Shieh6caafbe2015-10-05 12:43:27 -0700137 bool GetSslCipherSuite(int* cipher) override;
pthatcher@webrtc.org3ee4fe52015-02-11 22:34:36 +0000138
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000139 // Once DTLS has been established, this method retrieves the certificate in
140 // use by the remote peer, for use in external identity verification.
jbauch555604a2016-04-26 03:13:22 -0700141 std::unique_ptr<rtc::SSLCertificate> GetRemoteSSLCertificate() const override;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000142
zhihuangb2cdd932017-01-19 16:54:25 -0800143 // Once DTLS has established (i.e., this ice_transport is writable), this
144 // method extracts the keys negotiated during the DTLS handshake, for use in
145 // external encryption. DTLS-SRTP uses this to extract the needed SRTP keys.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000146 // See the SSLStreamAdapter documentation for info on the specific parameters.
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200147 bool ExportKeyingMaterial(const std::string& label,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200148 const uint8_t* context,
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200149 size_t context_len,
150 bool use_context,
Peter Boström0c4e06b2015-10-07 12:23:21 +0200151 uint8_t* result,
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200152 size_t result_len) override {
zhihuangca6d3b62017-08-23 18:05:50 -0700153 return (dtls_.get())
154 ? dtls_->ExportKeyingMaterial(label, context, context_len,
155 use_context, result, result_len)
156 : false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000157 }
158
zhihuangb2cdd932017-01-19 16:54:25 -0800159 IceTransportInternal* ice_transport() override { return ice_transport_; }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000160
deadbeef89824f62016-09-30 11:55:43 -0700161 // For informational purposes. Tells if the DTLS handshake has finished.
162 // This may be true even if writable() is false, if the remote fingerprint
163 // has not yet been verified.
164 bool IsDtlsConnected();
165
zhihuangb2cdd932017-01-19 16:54:25 -0800166 bool receiving() const override { return receiving_; }
167
168 bool writable() const override { return writable_; }
169
170 int GetError() override { return ice_transport_->GetError(); }
171
172 int SetOption(rtc::Socket::Option opt, int value) override {
173 return ice_transport_->SetOption(opt, value);
174 }
175
zhihuangb2cdd932017-01-19 16:54:25 -0800176 std::string ToString() const {
177 const char RECEIVING_ABBREV[2] = {'_', 'R'};
178 const char WRITABLE_ABBREV[2] = {'_', 'W'};
179 std::stringstream ss;
180 ss << "DtlsTransport[" << transport_name_ << "|" << component_ << "|"
181 << RECEIVING_ABBREV[receiving()] << WRITABLE_ABBREV[writable()] << "]";
182 return ss.str();
183 }
184
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000185 private:
deadbeef5bd5ca32017-02-10 11:31:50 -0800186 void OnWritableState(rtc::PacketTransportInternal* transport);
187 void OnReadPacket(rtc::PacketTransportInternal* transport,
johand89ab142016-10-25 10:50:32 -0700188 const char* data,
189 size_t size,
190 const rtc::PacketTime& packet_time,
191 int flags);
deadbeef5bd5ca32017-02-10 11:31:50 -0800192 void OnSentPacket(rtc::PacketTransportInternal* transport,
stefanc1aeaf02015-10-15 07:26:07 -0700193 const rtc::SentPacket& sent_packet);
deadbeef5bd5ca32017-02-10 11:31:50 -0800194 void OnReadyToSend(rtc::PacketTransportInternal* transport);
195 void OnReceivingState(rtc::PacketTransportInternal* transport);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000196 void OnDtlsEvent(rtc::StreamInterface* stream_, int sig, int err);
197 bool SetupDtls();
deadbeef367efdc2016-07-13 12:10:17 -0700198 void MaybeStartDtls();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000199 bool HandleDtlsPacket(const char* data, size_t size);
zhihuangd82eee02016-08-26 11:25:05 -0700200 void OnDtlsHandshakeError(rtc::SSLHandshakeError error);
skvladd0309122017-02-02 17:18:37 -0800201 void ConfigureHandshakeTimeout();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000202
zhihuangb2cdd932017-01-19 16:54:25 -0800203 void set_receiving(bool receiving);
204 void set_writable(bool writable);
205 // Sets the DTLS state, signaling if necessary.
206 void set_dtls_state(DtlsTransportState state);
207
208 std::string transport_name_;
209 int component_;
210 DtlsTransportState dtls_state_ = DTLS_TRANSPORT_NEW;
johan27c3d5b2016-10-17 00:54:57 -0700211 rtc::Thread* network_thread_; // Everything should occur on this thread.
zhihuangb2cdd932017-01-19 16:54:25 -0800212 // Underlying ice_transport, not owned by this class.
213 IceTransportInternal* const ice_transport_;
jbauch555604a2016-04-26 03:13:22 -0700214 std::unique_ptr<rtc::SSLStreamAdapter> dtls_; // The DTLS stream
zhihuangb2cdd932017-01-19 16:54:25 -0800215 StreamInterfaceChannel*
216 downward_; // Wrapper for ice_transport_, owned by dtls_.
zhihuangca6d3b62017-08-23 18:05:50 -0700217 std::vector<int> srtp_ciphers_; // SRTP ciphers to use with DTLS.
deadbeef2b558672015-10-26 17:23:29 -0700218 bool dtls_active_ = false;
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200219 rtc::scoped_refptr<rtc::RTCCertificate> local_certificate_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000220 rtc::SSLRole ssl_role_;
Joachim Bauch831c5582015-05-20 12:48:41 +0200221 rtc::SSLProtocolVersion ssl_max_version_;
jbauch5869f502017-06-29 12:31:36 -0700222 rtc::CryptoOptions crypto_options_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000223 rtc::Buffer remote_fingerprint_value_;
224 std::string remote_fingerprint_algorithm_;
225
deadbeefe84cd2e2016-05-04 17:16:34 -0700226 // Cached DTLS ClientHello packet that was received before we started the
227 // DTLS handshake. This could happen if the hello was received before the
zhihuangb2cdd932017-01-19 16:54:25 -0800228 // ice transport became writable, or before a remote fingerprint was received.
deadbeefe84cd2e2016-05-04 17:16:34 -0700229 rtc::Buffer cached_client_hello_;
230
zhihuangb2cdd932017-01-19 16:54:25 -0800231 bool receiving_ = false;
232 bool writable_ = false;
233
234 RTC_DISALLOW_COPY_AND_ASSIGN(DtlsTransport);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000235};
236
237} // namespace cricket
238
zhihuangca6d3b62017-08-23 18:05:50 -0700239#endif // WEBRTC_P2P_BASE_DTLSTRANSPORT_H_