blob: 5f32a9b70bb07467d381e8c8d96ee1859bb9bd28 [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#include <algorithm>
jbauch555604a2016-04-26 03:13:22 -070012#include <memory>
kwiberg0eb15ed2015-12-17 03:04:15 -080013#include <utility>
14
zhihuangca6d3b62017-08-23 18:05:50 -070015#include "webrtc/p2p/base/dtlstransport.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000016
17#include "webrtc/p2p/base/common.h"
deadbeef5bd5ca32017-02-10 11:31:50 -080018#include "webrtc/p2p/base/packettransportinternal.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020019#include "webrtc/rtc_base/buffer.h"
20#include "webrtc/rtc_base/checks.h"
21#include "webrtc/rtc_base/dscp.h"
22#include "webrtc/rtc_base/messagequeue.h"
23#include "webrtc/rtc_base/sslstreamadapter.h"
24#include "webrtc/rtc_base/stream.h"
25#include "webrtc/rtc_base/thread.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000026
27namespace cricket {
28
29// We don't pull the RTP constants from rtputils.h, to avoid a layer violation.
30static const size_t kDtlsRecordHeaderLen = 13;
31static const size_t kMaxDtlsPacketLen = 2048;
32static const size_t kMinRtpPacketLen = 12;
33
Joachim Bauch6f2ef742015-05-21 17:52:01 +020034// Maximum number of pending packets in the queue. Packets are read immediately
35// after they have been written, so a capacity of "1" is sufficient.
36static const size_t kMaxPendingPackets = 1;
37
skvladd0309122017-02-02 17:18:37 -080038// Minimum and maximum values for the initial DTLS handshake timeout. We'll pick
39// an initial timeout based on ICE RTT estimates, but clamp it to this range.
40static const int kMinHandshakeTimeout = 50;
41static const int kMaxHandshakeTimeout = 3000;
42
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000043static bool IsDtlsPacket(const char* data, size_t len) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020044 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000045 return (len >= kDtlsRecordHeaderLen && (u[0] > 19 && u[0] < 64));
46}
deadbeefe84cd2e2016-05-04 17:16:34 -070047static bool IsDtlsClientHelloPacket(const char* data, size_t len) {
48 if (!IsDtlsPacket(data, len)) {
49 return false;
50 }
51 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
52 return len > 17 && u[0] == 22 && u[13] == 1;
53}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000054static bool IsRtpPacket(const char* data, size_t len) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020055 const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000056 return (len >= kMinRtpPacketLen && (u[0] & 0xC0) == 0x80);
57}
58
zhihuangb2cdd932017-01-19 16:54:25 -080059StreamInterfaceChannel::StreamInterfaceChannel(
60 IceTransportInternal* ice_transport)
61 : ice_transport_(ice_transport),
Joachim Bauch6f2ef742015-05-21 17:52:01 +020062 state_(rtc::SS_OPEN),
zhihuangd06adf62017-01-12 15:58:31 -080063 packets_(kMaxPendingPackets, kMaxDtlsPacketLen) {}
Joachim Bauch6f2ef742015-05-21 17:52:01 +020064
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000065rtc::StreamResult StreamInterfaceChannel::Read(void* buffer,
zhihuangca6d3b62017-08-23 18:05:50 -070066 size_t buffer_len,
67 size_t* read,
68 int* error) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000069 if (state_ == rtc::SS_CLOSED)
70 return rtc::SR_EOS;
71 if (state_ == rtc::SS_OPENING)
72 return rtc::SR_BLOCK;
73
Joachim Bauch6f2ef742015-05-21 17:52:01 +020074 if (!packets_.ReadFront(buffer, buffer_len, read)) {
75 return rtc::SR_BLOCK;
76 }
77
78 return rtc::SR_SUCCESS;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000079}
80
81rtc::StreamResult StreamInterfaceChannel::Write(const void* data,
zhihuangca6d3b62017-08-23 18:05:50 -070082 size_t data_len,
83 size_t* written,
84 int* error) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000085 // Always succeeds, since this is an unreliable transport anyway.
zhihuangb2cdd932017-01-19 16:54:25 -080086 // TODO(zhihuang): Should this block if ice_transport_'s temporarily
87 // unwritable?
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000088 rtc::PacketOptions packet_options;
zhihuangb2cdd932017-01-19 16:54:25 -080089 ice_transport_->SendPacket(static_cast<const char*>(data), data_len,
90 packet_options);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000091 if (written) {
92 *written = data_len;
93 }
94 return rtc::SR_SUCCESS;
95}
96
97bool StreamInterfaceChannel::OnPacketReceived(const char* data, size_t size) {
Joachim Bauch6f2ef742015-05-21 17:52:01 +020098 // We force a read event here to ensure that we don't overflow our queue.
99 bool ret = packets_.WriteBack(data, size, NULL);
henrikg91d6ede2015-09-17 00:24:34 -0700100 RTC_CHECK(ret) << "Failed to write packet to queue.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000101 if (ret) {
102 SignalEvent(this, rtc::SE_READ, 0);
103 }
104 return ret;
105}
106
guoweis4cc9f982016-02-24 11:10:06 -0800107void StreamInterfaceChannel::Close() {
108 packets_.Clear();
109 state_ = rtc::SS_CLOSED;
110}
111
deadbeef7914b8c2017-04-21 03:23:33 -0700112DtlsTransport::DtlsTransport(IceTransportInternal* ice_transport,
113 const rtc::CryptoOptions& crypto_options)
zhihuangb2cdd932017-01-19 16:54:25 -0800114 : transport_name_(ice_transport->transport_name()),
115 component_(ice_transport->component()),
johan27c3d5b2016-10-17 00:54:57 -0700116 network_thread_(rtc::Thread::Current()),
zhihuangb2cdd932017-01-19 16:54:25 -0800117 ice_transport_(ice_transport),
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000118 downward_(NULL),
deadbeef7914b8c2017-04-21 03:23:33 -0700119 srtp_ciphers_(GetSupportedDtlsSrtpCryptoSuites(crypto_options)),
Joachim Bauch831c5582015-05-20 12:48:41 +0200120 ssl_role_(rtc::SSL_CLIENT),
jbauch5869f502017-06-29 12:31:36 -0700121 ssl_max_version_(rtc::SSL_PROTOCOL_DTLS_12),
122 crypto_options_(crypto_options) {
zhihuangb2cdd932017-01-19 16:54:25 -0800123 ice_transport_->SignalWritableState.connect(this,
124 &DtlsTransport::OnWritableState);
125 ice_transport_->SignalReadPacket.connect(this, &DtlsTransport::OnReadPacket);
126 ice_transport_->SignalSentPacket.connect(this, &DtlsTransport::OnSentPacket);
127 ice_transport_->SignalReadyToSend.connect(this,
128 &DtlsTransport::OnReadyToSend);
129 ice_transport_->SignalReceivingState.connect(
130 this, &DtlsTransport::OnReceivingState);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000131}
132
zhihuangb2cdd932017-01-19 16:54:25 -0800133DtlsTransport::~DtlsTransport() {}
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000134
zhihuangb2cdd932017-01-19 16:54:25 -0800135bool DtlsTransport::SetLocalCertificate(
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200136 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
deadbeef2b558672015-10-26 17:23:29 -0700137 if (dtls_active_) {
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200138 if (certificate == local_certificate_) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000139 // This may happen during renegotiation.
140 LOG_J(LS_INFO, this) << "Ignoring identical DTLS identity";
141 return true;
142 } else {
143 LOG_J(LS_ERROR, this) << "Can't change DTLS local identity in this state";
144 return false;
145 }
146 }
147
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200148 if (certificate) {
149 local_certificate_ = certificate;
deadbeef2b558672015-10-26 17:23:29 -0700150 dtls_active_ = true;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000151 } else {
152 LOG_J(LS_INFO, this) << "NULL DTLS identity supplied. Not doing DTLS";
153 }
154
155 return true;
156}
157
zhihuangb2cdd932017-01-19 16:54:25 -0800158rtc::scoped_refptr<rtc::RTCCertificate> DtlsTransport::GetLocalCertificate()
159 const {
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200160 return local_certificate_;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000161}
162
zhihuangb2cdd932017-01-19 16:54:25 -0800163bool DtlsTransport::SetSslMaxProtocolVersion(rtc::SSLProtocolVersion version) {
deadbeef2b558672015-10-26 17:23:29 -0700164 if (dtls_active_) {
Joachim Bauch831c5582015-05-20 12:48:41 +0200165 LOG(LS_ERROR) << "Not changing max. protocol version "
166 << "while DTLS is negotiating";
Joachim Bauch04e5b492015-05-29 09:40:39 +0200167 return false;
Joachim Bauch831c5582015-05-20 12:48:41 +0200168 }
169
170 ssl_max_version_ = version;
Joachim Bauch04e5b492015-05-29 09:40:39 +0200171 return true;
Joachim Bauch831c5582015-05-20 12:48:41 +0200172}
173
zhihuangb2cdd932017-01-19 16:54:25 -0800174bool DtlsTransport::SetSslRole(rtc::SSLRole role) {
deadbeef89824f62016-09-30 11:55:43 -0700175 if (dtls_) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000176 if (ssl_role_ != role) {
177 LOG(LS_ERROR) << "SSL Role can't be reversed after the session is setup.";
178 return false;
179 }
180 return true;
181 }
182
183 ssl_role_ = role;
184 return true;
185}
186
zhihuangb2cdd932017-01-19 16:54:25 -0800187bool DtlsTransport::GetSslRole(rtc::SSLRole* role) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000188 *role = ssl_role_;
189 return true;
190}
191
zhihuangb2cdd932017-01-19 16:54:25 -0800192bool DtlsTransport::GetSslCipherSuite(int* cipher) {
deadbeef2b558672015-10-26 17:23:29 -0700193 if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
pthatcher@webrtc.org3ee4fe52015-02-11 22:34:36 +0000194 return false;
195 }
196
Guo-wei Shieh456696a2015-09-30 21:48:54 -0700197 return dtls_->GetSslCipherSuite(cipher);
pthatcher@webrtc.org3ee4fe52015-02-11 22:34:36 +0000198}
199
zhihuangb2cdd932017-01-19 16:54:25 -0800200bool DtlsTransport::SetRemoteFingerprint(const std::string& digest_alg,
201 const uint8_t* digest,
202 size_t digest_len) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000203 rtc::Buffer remote_fingerprint_value(digest, digest_len);
204
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800205 // Once we have the local certificate, the same remote fingerprint can be set
206 // multiple times.
deadbeef2b558672015-10-26 17:23:29 -0700207 if (dtls_active_ && remote_fingerprint_value_ == remote_fingerprint_value &&
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000208 !digest_alg.empty()) {
209 // This may happen during renegotiation.
210 LOG_J(LS_INFO, this) << "Ignoring identical remote DTLS fingerprint";
211 return true;
212 }
213
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800214 // If the other side doesn't support DTLS, turn off |dtls_active_|.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000215 if (digest_alg.empty()) {
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800216 RTC_DCHECK(!digest_len);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000217 LOG_J(LS_INFO, this) << "Other side didn't support DTLS.";
deadbeef2b558672015-10-26 17:23:29 -0700218 dtls_active_ = false;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000219 return true;
220 }
221
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800222 // Otherwise, we must have a local certificate before setting remote
223 // fingerprint.
224 if (!dtls_active_) {
225 LOG_J(LS_ERROR, this) << "Can't set DTLS remote settings in this state.";
226 return false;
227 }
228
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000229 // At this point we know we are doing DTLS
deadbeef89824f62016-09-30 11:55:43 -0700230 bool fingerprint_changing = remote_fingerprint_value_.size() > 0u;
kwiberg0eb15ed2015-12-17 03:04:15 -0800231 remote_fingerprint_value_ = std::move(remote_fingerprint_value);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000232 remote_fingerprint_algorithm_ = digest_alg;
233
deadbeef89824f62016-09-30 11:55:43 -0700234 if (dtls_ && !fingerprint_changing) {
235 // This can occur if DTLS is set up before a remote fingerprint is
236 // received. For instance, if we set up DTLS due to receiving an early
237 // ClientHello.
238 rtc::SSLPeerCertificateDigestError err;
239 if (!dtls_->SetPeerCertificateDigest(
240 remote_fingerprint_algorithm_,
241 reinterpret_cast<unsigned char*>(remote_fingerprint_value_.data()),
242 remote_fingerprint_value_.size(), &err)) {
243 LOG_J(LS_ERROR, this) << "Couldn't set DTLS certificate digest.";
244 set_dtls_state(DTLS_TRANSPORT_FAILED);
245 // If the error is "verification failed", don't return false, because
246 // this means the fingerprint was formatted correctly but didn't match
247 // the certificate from the DTLS handshake. Thus the DTLS state should go
248 // to "failed", but SetRemoteDescription shouldn't fail.
249 return err == rtc::SSLPeerCertificateDigestError::VERIFICATION_FAILED;
250 }
251 return true;
252 }
253
254 // If the fingerprint is changing, we'll tear down the DTLS association and
255 // create a new one, resetting our state.
256 if (dtls_ && fingerprint_changing) {
deadbeef367efdc2016-07-13 12:10:17 -0700257 dtls_.reset(nullptr);
258 set_dtls_state(DTLS_TRANSPORT_NEW);
259 set_writable(false);
260 }
Guo-wei Shieh1218d7a2015-12-05 09:59:56 -0800261
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000262 if (!SetupDtls()) {
deadbeef2b558672015-10-26 17:23:29 -0700263 set_dtls_state(DTLS_TRANSPORT_FAILED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000264 return false;
265 }
266
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000267 return true;
268}
269
zhihuangb2cdd932017-01-19 16:54:25 -0800270std::unique_ptr<rtc::SSLCertificate> DtlsTransport::GetRemoteSSLCertificate()
271 const {
deadbeef2b558672015-10-26 17:23:29 -0700272 if (!dtls_) {
kwibergb4d01c42016-04-06 05:15:06 -0700273 return nullptr;
deadbeef2b558672015-10-26 17:23:29 -0700274 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000275
kwibergb4d01c42016-04-06 05:15:06 -0700276 return dtls_->GetPeerCertificate();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000277}
278
zhihuangb2cdd932017-01-19 16:54:25 -0800279bool DtlsTransport::SetupDtls() {
280 StreamInterfaceChannel* downward = new StreamInterfaceChannel(ice_transport_);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000281
282 dtls_.reset(rtc::SSLStreamAdapter::Create(downward));
283 if (!dtls_) {
284 LOG_J(LS_ERROR, this) << "Failed to create DTLS adapter.";
285 delete downward;
286 return false;
287 }
288
289 downward_ = downward;
290
Henrik Boströmf3ecdb92015-09-08 12:11:54 +0200291 dtls_->SetIdentity(local_certificate_->identity()->GetReference());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000292 dtls_->SetMode(rtc::SSL_MODE_DTLS);
Joachim Bauch831c5582015-05-20 12:48:41 +0200293 dtls_->SetMaxProtocolVersion(ssl_max_version_);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000294 dtls_->SetServerRole(ssl_role_);
zhihuangb2cdd932017-01-19 16:54:25 -0800295 dtls_->SignalEvent.connect(this, &DtlsTransport::OnDtlsEvent);
296 dtls_->SignalSSLHandshakeError.connect(this,
297 &DtlsTransport::OnDtlsHandshakeError);
deadbeef89824f62016-09-30 11:55:43 -0700298 if (remote_fingerprint_value_.size() &&
299 !dtls_->SetPeerCertificateDigest(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000300 remote_fingerprint_algorithm_,
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000301 reinterpret_cast<unsigned char*>(remote_fingerprint_value_.data()),
deadbeef81f6f4f2016-09-19 17:20:52 -0700302 remote_fingerprint_value_.size())) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000303 LOG_J(LS_ERROR, this) << "Couldn't set DTLS certificate digest.";
304 return false;
305 }
306
307 // Set up DTLS-SRTP, if it's been enabled.
308 if (!srtp_ciphers_.empty()) {
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800309 if (!dtls_->SetDtlsSrtpCryptoSuites(srtp_ciphers_)) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000310 LOG_J(LS_ERROR, this) << "Couldn't set DTLS-SRTP ciphers.";
311 return false;
312 }
313 } else {
deadbeef2b558672015-10-26 17:23:29 -0700314 LOG_J(LS_INFO, this) << "Not using DTLS-SRTP.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000315 }
316
317 LOG_J(LS_INFO, this) << "DTLS setup complete.";
deadbeef367efdc2016-07-13 12:10:17 -0700318
zhihuangb2cdd932017-01-19 16:54:25 -0800319 // If the underlying ice_transport is already writable at this point, we may
320 // be able to start DTLS right away.
deadbeef367efdc2016-07-13 12:10:17 -0700321 MaybeStartDtls();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000322 return true;
323}
324
zhihuangb2cdd932017-01-19 16:54:25 -0800325bool DtlsTransport::GetSrtpCryptoSuite(int* cipher) {
deadbeef2b558672015-10-26 17:23:29 -0700326 if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000327 return false;
328 }
329
Guo-wei Shieh521ed7b2015-11-18 19:41:53 -0800330 return dtls_->GetDtlsSrtpCryptoSuite(cipher);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000331}
332
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000333// Called from upper layers to send a media packet.
zhihuangb2cdd932017-01-19 16:54:25 -0800334int DtlsTransport::SendPacket(const char* data,
335 size_t size,
336 const rtc::PacketOptions& options,
337 int flags) {
deadbeef2b558672015-10-26 17:23:29 -0700338 if (!dtls_active_) {
339 // Not doing DTLS.
zhihuangb2cdd932017-01-19 16:54:25 -0800340 return ice_transport_->SendPacket(data, size, options);
deadbeef2b558672015-10-26 17:23:29 -0700341 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000342
deadbeef2b558672015-10-26 17:23:29 -0700343 switch (dtls_state()) {
344 case DTLS_TRANSPORT_NEW:
345 // Can't send data until the connection is active.
346 // TODO(ekr@rtfm.com): assert here if dtls_ is NULL?
347 return -1;
348 case DTLS_TRANSPORT_CONNECTING:
349 // Can't send data until the connection is active.
350 return -1;
351 case DTLS_TRANSPORT_CONNECTED:
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000352 if (flags & PF_SRTP_BYPASS) {
nisseede5da42017-01-12 05:15:36 -0800353 RTC_DCHECK(!srtp_ciphers_.empty());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000354 if (!IsRtpPacket(data, size)) {
deadbeef2b558672015-10-26 17:23:29 -0700355 return -1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000356 }
357
zhihuangb2cdd932017-01-19 16:54:25 -0800358 return ice_transport_->SendPacket(data, size, options);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000359 } else {
deadbeef2b558672015-10-26 17:23:29 -0700360 return (dtls_->WriteAll(data, size, NULL, NULL) == rtc::SR_SUCCESS)
361 ? static_cast<int>(size)
362 : -1;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000363 }
deadbeef2b558672015-10-26 17:23:29 -0700364 case DTLS_TRANSPORT_FAILED:
365 case DTLS_TRANSPORT_CLOSED:
366 // Can't send anything when we're closed.
367 return -1;
368 default:
nissec80e7412017-01-11 05:56:46 -0800369 RTC_NOTREACHED();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000370 return -1;
371 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000372}
373
zhihuangb2cdd932017-01-19 16:54:25 -0800374bool DtlsTransport::IsDtlsConnected() {
deadbeef89824f62016-09-30 11:55:43 -0700375 return dtls_ && dtls_->IsTlsConnected();
376}
377
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000378// The state transition logic here is as follows:
379// (1) If we're not doing DTLS-SRTP, then the state is just the
380// state of the underlying impl()
381// (2) If we're doing DTLS-SRTP:
Peter Thatcher04ac81f2015-09-21 11:48:28 -0700382// - Prior to the DTLS handshake, the state is neither receiving nor
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000383// writable
384// - When the impl goes writable for the first time we
385// start the DTLS handshake
386// - Once the DTLS handshake completes, the state is that of the
387// impl again
deadbeef5bd5ca32017-02-10 11:31:50 -0800388void DtlsTransport::OnWritableState(rtc::PacketTransportInternal* transport) {
nisseede5da42017-01-12 05:15:36 -0800389 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
zhihuangb2cdd932017-01-19 16:54:25 -0800390 RTC_DCHECK(transport == ice_transport_);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000391 LOG_J(LS_VERBOSE, this)
zhihuangb2cdd932017-01-19 16:54:25 -0800392 << "DTLSTransportChannelWrapper: ice_transport writable state changed to "
393 << ice_transport_->writable();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000394
deadbeef2b558672015-10-26 17:23:29 -0700395 if (!dtls_active_) {
396 // Not doing DTLS.
397 // Note: SignalWritableState fired by set_writable.
zhihuangb2cdd932017-01-19 16:54:25 -0800398 set_writable(ice_transport_->writable());
deadbeef2b558672015-10-26 17:23:29 -0700399 return;
400 }
401
402 switch (dtls_state()) {
403 case DTLS_TRANSPORT_NEW:
deadbeef367efdc2016-07-13 12:10:17 -0700404 MaybeStartDtls();
deadbeef2b558672015-10-26 17:23:29 -0700405 break;
406 case DTLS_TRANSPORT_CONNECTED:
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000407 // Note: SignalWritableState fired by set_writable.
zhihuangb2cdd932017-01-19 16:54:25 -0800408 set_writable(ice_transport_->writable());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000409 break;
deadbeef2b558672015-10-26 17:23:29 -0700410 case DTLS_TRANSPORT_CONNECTING:
411 // Do nothing.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000412 break;
deadbeef2b558672015-10-26 17:23:29 -0700413 case DTLS_TRANSPORT_FAILED:
414 case DTLS_TRANSPORT_CLOSED:
415 // Should not happen. Do nothing.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000416 break;
417 }
418}
419
deadbeef5bd5ca32017-02-10 11:31:50 -0800420void DtlsTransport::OnReceivingState(rtc::PacketTransportInternal* transport) {
nisseede5da42017-01-12 05:15:36 -0800421 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
zhihuangb2cdd932017-01-19 16:54:25 -0800422 RTC_DCHECK(transport == ice_transport_);
423 LOG_J(LS_VERBOSE, this) << "DTLSTransportChannelWrapper: ice_transport "
424 "receiving state changed to "
425 << ice_transport_->receiving();
deadbeef2b558672015-10-26 17:23:29 -0700426 if (!dtls_active_ || dtls_state() == DTLS_TRANSPORT_CONNECTED) {
Peter Thatcher54360512015-07-08 11:08:35 -0700427 // Note: SignalReceivingState fired by set_receiving.
zhihuangb2cdd932017-01-19 16:54:25 -0800428 set_receiving(ice_transport_->receiving());
Peter Thatcher54360512015-07-08 11:08:35 -0700429 }
430}
431
deadbeef5bd5ca32017-02-10 11:31:50 -0800432void DtlsTransport::OnReadPacket(rtc::PacketTransportInternal* transport,
zhihuangb2cdd932017-01-19 16:54:25 -0800433 const char* data,
434 size_t size,
435 const rtc::PacketTime& packet_time,
436 int flags) {
nisseede5da42017-01-12 05:15:36 -0800437 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
zhihuangb2cdd932017-01-19 16:54:25 -0800438 RTC_DCHECK(transport == ice_transport_);
nisseede5da42017-01-12 05:15:36 -0800439 RTC_DCHECK(flags == 0);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000440
deadbeef2b558672015-10-26 17:23:29 -0700441 if (!dtls_active_) {
442 // Not doing DTLS.
443 SignalReadPacket(this, data, size, packet_time, 0);
444 return;
445 }
446
447 switch (dtls_state()) {
448 case DTLS_TRANSPORT_NEW:
449 if (dtls_) {
deadbeefe84cd2e2016-05-04 17:16:34 -0700450 LOG_J(LS_INFO, this) << "Packet received before DTLS started.";
deadbeef2b558672015-10-26 17:23:29 -0700451 } else {
deadbeefe84cd2e2016-05-04 17:16:34 -0700452 LOG_J(LS_WARNING, this) << "Packet received before we know if we are "
453 << "doing DTLS or not.";
454 }
455 // Cache a client hello packet received before DTLS has actually started.
456 if (IsDtlsClientHelloPacket(data, size)) {
457 LOG_J(LS_INFO, this) << "Caching DTLS ClientHello packet until DTLS is "
458 << "started.";
459 cached_client_hello_.SetData(data, size);
deadbeef89824f62016-09-30 11:55:43 -0700460 // If we haven't started setting up DTLS yet (because we don't have a
461 // remote fingerprint/role), we can use the client hello as a clue that
462 // the peer has chosen the client role, and proceed with the handshake.
463 // The fingerprint will be verified when it's set.
464 if (!dtls_ && local_certificate_) {
465 SetSslRole(rtc::SSL_SERVER);
466 SetupDtls();
467 }
deadbeefe84cd2e2016-05-04 17:16:34 -0700468 } else {
469 LOG_J(LS_INFO, this) << "Not a DTLS ClientHello packet; dropping.";
deadbeef2b558672015-10-26 17:23:29 -0700470 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000471 break;
472
deadbeef2b558672015-10-26 17:23:29 -0700473 case DTLS_TRANSPORT_CONNECTING:
474 case DTLS_TRANSPORT_CONNECTED:
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000475 // We should only get DTLS or SRTP packets; STUN's already been demuxed.
476 // Is this potentially a DTLS packet?
477 if (IsDtlsPacket(data, size)) {
478 if (!HandleDtlsPacket(data, size)) {
479 LOG_J(LS_ERROR, this) << "Failed to handle DTLS packet.";
480 return;
481 }
482 } else {
483 // Not a DTLS packet; our handshake should be complete by now.
deadbeef2b558672015-10-26 17:23:29 -0700484 if (dtls_state() != DTLS_TRANSPORT_CONNECTED) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000485 LOG_J(LS_ERROR, this) << "Received non-DTLS packet before DTLS "
486 << "complete.";
487 return;
488 }
489
490 // And it had better be a SRTP packet.
491 if (!IsRtpPacket(data, size)) {
492 LOG_J(LS_ERROR, this) << "Received unexpected non-DTLS packet.";
493 return;
494 }
495
496 // Sanity check.
nisseede5da42017-01-12 05:15:36 -0800497 RTC_DCHECK(!srtp_ciphers_.empty());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000498
499 // Signal this upwards as a bypass packet.
500 SignalReadPacket(this, data, size, packet_time, PF_SRTP_BYPASS);
501 }
502 break;
deadbeef2b558672015-10-26 17:23:29 -0700503 case DTLS_TRANSPORT_FAILED:
504 case DTLS_TRANSPORT_CLOSED:
505 // This shouldn't be happening. Drop the packet.
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000506 break;
507 }
508}
509
deadbeef5bd5ca32017-02-10 11:31:50 -0800510void DtlsTransport::OnSentPacket(rtc::PacketTransportInternal* transport,
zhihuangb2cdd932017-01-19 16:54:25 -0800511 const rtc::SentPacket& sent_packet) {
nisseede5da42017-01-12 05:15:36 -0800512 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
stefanc1aeaf02015-10-15 07:26:07 -0700513
514 SignalSentPacket(this, sent_packet);
515}
516
deadbeef5bd5ca32017-02-10 11:31:50 -0800517void DtlsTransport::OnReadyToSend(rtc::PacketTransportInternal* transport) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000518 if (writable()) {
519 SignalReadyToSend(this);
520 }
521}
522
zhihuangb2cdd932017-01-19 16:54:25 -0800523void DtlsTransport::OnDtlsEvent(rtc::StreamInterface* dtls, int sig, int err) {
nisseede5da42017-01-12 05:15:36 -0800524 RTC_DCHECK(rtc::Thread::Current() == network_thread_);
525 RTC_DCHECK(dtls == dtls_.get());
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000526 if (sig & rtc::SE_OPEN) {
527 // This is the first time.
528 LOG_J(LS_INFO, this) << "DTLS handshake complete.";
529 if (dtls_->GetState() == rtc::SS_OPEN) {
530 // The check for OPEN shouldn't be necessary but let's make
531 // sure we don't accidentally frob the state if it's closed.
deadbeef2b558672015-10-26 17:23:29 -0700532 set_dtls_state(DTLS_TRANSPORT_CONNECTED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000533 set_writable(true);
534 }
535 }
536 if (sig & rtc::SE_READ) {
537 char buf[kMaxDtlsPacketLen];
538 size_t read;
deadbeef89824f62016-09-30 11:55:43 -0700539 int read_error;
jbauch7d0a77e2017-07-07 13:44:07 -0700540 rtc::StreamResult ret;
541 // The underlying DTLS stream may have received multiple DTLS records in
542 // one packet, so read all of them.
543 do {
544 ret = dtls_->Read(buf, sizeof(buf), &read, &read_error);
545 if (ret == rtc::SR_SUCCESS) {
546 SignalReadPacket(this, buf, read, rtc::CreatePacketTime(0), 0);
547 } else if (ret == rtc::SR_EOS) {
548 // Remote peer shut down the association with no error.
549 LOG_J(LS_INFO, this) << "DTLS transport closed";
550 set_writable(false);
551 set_dtls_state(DTLS_TRANSPORT_CLOSED);
552 } else if (ret == rtc::SR_ERROR) {
553 // Remote peer shut down the association with an error.
554 LOG_J(LS_INFO, this) << "DTLS transport error, code=" << read_error;
555 set_writable(false);
556 set_dtls_state(DTLS_TRANSPORT_FAILED);
557 }
558 } while (ret == rtc::SR_SUCCESS);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000559 }
560 if (sig & rtc::SE_CLOSE) {
nisseede5da42017-01-12 05:15:36 -0800561 RTC_DCHECK(sig == rtc::SE_CLOSE); // SE_CLOSE should be by itself.
deadbeef2b558672015-10-26 17:23:29 -0700562 set_writable(false);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000563 if (!err) {
zhihuangb2cdd932017-01-19 16:54:25 -0800564 LOG_J(LS_INFO, this) << "DTLS transport closed";
deadbeef2b558672015-10-26 17:23:29 -0700565 set_dtls_state(DTLS_TRANSPORT_CLOSED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000566 } else {
zhihuangb2cdd932017-01-19 16:54:25 -0800567 LOG_J(LS_INFO, this) << "DTLS transport error, code=" << err;
deadbeef2b558672015-10-26 17:23:29 -0700568 set_dtls_state(DTLS_TRANSPORT_FAILED);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000569 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000570 }
571}
572
zhihuangb2cdd932017-01-19 16:54:25 -0800573void DtlsTransport::MaybeStartDtls() {
574 if (dtls_ && ice_transport_->writable()) {
skvladd0309122017-02-02 17:18:37 -0800575 ConfigureHandshakeTimeout();
576
Taylor Brandstetterc8762a82016-08-11 12:01:49 -0700577 if (dtls_->StartSSL()) {
deadbeef367efdc2016-07-13 12:10:17 -0700578 // This should never fail:
579 // Because we are operating in a nonblocking mode and all
580 // incoming packets come in via OnReadPacket(), which rejects
581 // packets in this state, the incoming queue must be empty. We
582 // ignore write errors, thus any errors must be because of
583 // configuration and therefore are our fault.
nisseeb4ca4e2017-01-12 02:24:27 -0800584 RTC_NOTREACHED() << "StartSSL failed.";
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000585 LOG_J(LS_ERROR, this) << "Couldn't start DTLS handshake";
deadbeef2b558672015-10-26 17:23:29 -0700586 set_dtls_state(DTLS_TRANSPORT_FAILED);
deadbeef367efdc2016-07-13 12:10:17 -0700587 return;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000588 }
zhihuangb2cdd932017-01-19 16:54:25 -0800589 LOG_J(LS_INFO, this) << "DtlsTransport: Started DTLS handshake";
deadbeef2b558672015-10-26 17:23:29 -0700590 set_dtls_state(DTLS_TRANSPORT_CONNECTING);
deadbeefe84cd2e2016-05-04 17:16:34 -0700591 // Now that the handshake has started, we can process a cached ClientHello
592 // (if one exists).
593 if (cached_client_hello_.size()) {
594 if (ssl_role_ == rtc::SSL_SERVER) {
595 LOG_J(LS_INFO, this) << "Handling cached DTLS ClientHello packet.";
596 if (!HandleDtlsPacket(cached_client_hello_.data<char>(),
597 cached_client_hello_.size())) {
598 LOG_J(LS_ERROR, this) << "Failed to handle DTLS packet.";
599 }
600 } else {
601 LOG_J(LS_WARNING, this) << "Discarding cached DTLS ClientHello packet "
602 << "because we don't have the server role.";
603 }
604 cached_client_hello_.Clear();
605 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000606 }
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000607}
608
609// Called from OnReadPacket when a DTLS packet is received.
zhihuangb2cdd932017-01-19 16:54:25 -0800610bool DtlsTransport::HandleDtlsPacket(const char* data, size_t size) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000611 // Sanity check we're not passing junk that
612 // just looks like DTLS.
Peter Boström0c4e06b2015-10-07 12:23:21 +0200613 const uint8_t* tmp_data = reinterpret_cast<const uint8_t*>(data);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000614 size_t tmp_size = size;
615 while (tmp_size > 0) {
616 if (tmp_size < kDtlsRecordHeaderLen)
617 return false; // Too short for the header
618
619 size_t record_len = (tmp_data[11] << 8) | (tmp_data[12]);
620 if ((record_len + kDtlsRecordHeaderLen) > tmp_size)
621 return false; // Body too short
622
623 tmp_data += record_len + kDtlsRecordHeaderLen;
624 tmp_size -= record_len + kDtlsRecordHeaderLen;
625 }
626
627 // Looks good. Pass to the SIC which ends up being passed to
628 // the DTLS stack.
629 return downward_->OnPacketReceived(data, size);
630}
631
zhihuangb2cdd932017-01-19 16:54:25 -0800632void DtlsTransport::set_receiving(bool receiving) {
633 if (receiving_ == receiving) {
634 return;
635 }
636 receiving_ = receiving;
637 SignalReceivingState(this);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000638}
639
zhihuangb2cdd932017-01-19 16:54:25 -0800640void DtlsTransport::set_writable(bool writable) {
641 if (writable_ == writable) {
642 return;
643 }
644 LOG_J(LS_VERBOSE, this) << "set_writable from:" << writable_ << " to "
645 << writable;
646 writable_ = writable;
647 if (writable_) {
648 SignalReadyToSend(this);
649 }
650 SignalWritableState(this);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000651}
652
zhihuangb2cdd932017-01-19 16:54:25 -0800653void DtlsTransport::set_dtls_state(DtlsTransportState state) {
654 if (dtls_state_ == state) {
655 return;
656 }
657 LOG_J(LS_VERBOSE, this) << "set_dtls_state from:" << dtls_state_ << " to "
658 << state;
659 dtls_state_ = state;
660 SignalDtlsState(this, state);
Honghai Zhang7fb69db2016-03-14 11:59:18 -0700661}
662
zhihuangb2cdd932017-01-19 16:54:25 -0800663void DtlsTransport::OnDtlsHandshakeError(rtc::SSLHandshakeError error) {
zhihuangd82eee02016-08-26 11:25:05 -0700664 SignalDtlsHandshakeError(error);
665}
666
skvladd0309122017-02-02 17:18:37 -0800667void DtlsTransport::ConfigureHandshakeTimeout() {
668 RTC_DCHECK(dtls_);
669 rtc::Optional<int> rtt = ice_transport_->GetRttEstimate();
670 if (rtt) {
671 // Limit the timeout to a reasonable range in case the ICE RTT takes
672 // extreme values.
673 int initial_timeout = std::max(kMinHandshakeTimeout,
zhihuangca6d3b62017-08-23 18:05:50 -0700674 std::min(kMaxHandshakeTimeout, 2 * (*rtt)));
skvladd0309122017-02-02 17:18:37 -0800675 LOG_J(LS_INFO, this) << "configuring DTLS handshake timeout "
676 << initial_timeout << " based on ICE RTT " << *rtt;
677
678 dtls_->SetInitialRetransmissionTimeout(initial_timeout);
679 } else {
680 LOG_J(LS_INFO, this)
681 << "no RTT estimate - using default DTLS handshake timeout";
682 }
683}
684
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000685} // namespace cricket