blob: 6fd8be37c242481b9c9789930be43cdda1470f3b [file] [log] [blame]
zstein398c3fd2017-07-19 13:38:02 -07001/*
2 * Copyright 2017 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#include "pc/srtptransport.h"
zstein398c3fd2017-07-19 13:38:02 -070012
13#include <string>
Steve Anton36b29d12017-10-30 09:57:42 -070014#include <vector>
zstein398c3fd2017-07-19 13:38:02 -070015
Karl Wiberg918f50c2018-07-05 11:40:33 +020016#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "media/base/rtputils.h"
18#include "pc/rtptransport.h"
19#include "pc/srtpsession.h"
20#include "rtc_base/asyncpacketsocket.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "rtc_base/copyonwritebuffer.h"
Zhi Huang365381f2018-04-13 16:44:34 -070022#include "rtc_base/numerics/safe_conversions.h"
Artem Titova76af0c2018-07-23 17:38:12 +020023#include "rtc_base/third_party/base64/base64.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/trace_event.h"
Zhi Huange830e682018-03-30 10:48:35 -070025#include "rtc_base/zero_memory.h"
zstein398c3fd2017-07-19 13:38:02 -070026
27namespace webrtc {
28
Zhi Huang2dfc42d2017-12-04 13:38:48 -080029SrtpTransport::SrtpTransport(bool rtcp_mux_enabled)
Zhi Huang365381f2018-04-13 16:44:34 -070030 : RtpTransport(rtcp_mux_enabled) {}
zstein398c3fd2017-07-19 13:38:02 -070031
Zhi Huange830e682018-03-30 10:48:35 -070032RTCError SrtpTransport::SetSrtpSendKey(const cricket::CryptoParams& params) {
33 if (send_params_) {
34 LOG_AND_RETURN_ERROR(
35 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
36 "Setting the SRTP send key twice is currently unsupported.");
37 }
38 if (recv_params_ && recv_params_->cipher_suite != params.cipher_suite) {
39 LOG_AND_RETURN_ERROR(
40 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
41 "The send key and receive key must have the same cipher suite.");
42 }
43
44 send_cipher_suite_ = rtc::SrtpCryptoSuiteFromName(params.cipher_suite);
45 if (*send_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) {
46 return RTCError(RTCErrorType::INVALID_PARAMETER,
47 "Invalid SRTP crypto suite");
48 }
49
50 int send_key_len, send_salt_len;
51 if (!rtc::GetSrtpKeyAndSaltLengths(*send_cipher_suite_, &send_key_len,
52 &send_salt_len)) {
53 return RTCError(RTCErrorType::INVALID_PARAMETER,
54 "Could not get lengths for crypto suite(s):"
55 " send cipher_suite ");
56 }
57
58 send_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(send_key_len + send_salt_len);
59 if (!ParseKeyParams(params.key_params, send_key_.data(), send_key_.size())) {
60 return RTCError(RTCErrorType::INVALID_PARAMETER,
61 "Failed to parse the crypto key params");
62 }
63
64 if (!MaybeSetKeyParams()) {
65 return RTCError(RTCErrorType::INVALID_PARAMETER,
66 "Failed to set the crypto key params");
67 }
68 send_params_ = params;
69 return RTCError::OK();
70}
71
72RTCError SrtpTransport::SetSrtpReceiveKey(const cricket::CryptoParams& params) {
73 if (recv_params_) {
74 LOG_AND_RETURN_ERROR(
75 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
76 "Setting the SRTP send key twice is currently unsupported.");
77 }
78 if (send_params_ && send_params_->cipher_suite != params.cipher_suite) {
79 LOG_AND_RETURN_ERROR(
80 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
81 "The send key and receive key must have the same cipher suite.");
82 }
83
84 recv_cipher_suite_ = rtc::SrtpCryptoSuiteFromName(params.cipher_suite);
85 if (*recv_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) {
86 return RTCError(RTCErrorType::INVALID_PARAMETER,
87 "Invalid SRTP crypto suite");
88 }
89
90 int recv_key_len, recv_salt_len;
91 if (!rtc::GetSrtpKeyAndSaltLengths(*recv_cipher_suite_, &recv_key_len,
92 &recv_salt_len)) {
93 return RTCError(RTCErrorType::INVALID_PARAMETER,
94 "Could not get lengths for crypto suite(s):"
95 " recv cipher_suite ");
96 }
97
98 recv_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(recv_key_len + recv_salt_len);
99 if (!ParseKeyParams(params.key_params, recv_key_.data(), recv_key_.size())) {
100 return RTCError(RTCErrorType::INVALID_PARAMETER,
101 "Failed to parse the crypto key params");
102 }
103
104 if (!MaybeSetKeyParams()) {
105 return RTCError(RTCErrorType::INVALID_PARAMETER,
106 "Failed to set the crypto key params");
107 }
108 recv_params_ = params;
109 return RTCError::OK();
110}
111
Zhi Huangcf990f52017-09-22 12:12:30 -0700112bool SrtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
113 const rtc::PacketOptions& options,
114 int flags) {
Zhi Huange830e682018-03-30 10:48:35 -0700115 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100116 RTC_LOG(LS_ERROR)
Zhi Huangcf990f52017-09-22 12:12:30 -0700117 << "Failed to send the packet because SRTP transport is inactive.";
118 return false;
119 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700120 rtc::PacketOptions updated_options = options;
Zhi Huangcf990f52017-09-22 12:12:30 -0700121 TRACE_EVENT0("webrtc", "SRTP Encode");
122 bool res;
123 uint8_t* data = packet->data();
Zhi Huang365381f2018-04-13 16:44:34 -0700124 int len = rtc::checked_cast<int>(packet->size());
Zhi Huangcf990f52017-09-22 12:12:30 -0700125// If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
126// inside libsrtp for a RTP packet. A external HMAC module will be writing
127// a fake HMAC value. This is ONLY done for a RTP packet.
128// Socket layer will update rtp sendtime extension header if present in
129// packet with current time before updating the HMAC.
130#if !defined(ENABLE_EXTERNAL_AUTH)
Zhi Huang365381f2018-04-13 16:44:34 -0700131 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000132#else
Zhi Huang365381f2018-04-13 16:44:34 -0700133 if (!IsExternalAuthActive()) {
134 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
135 } else {
136 updated_options.packet_time_params.rtp_sendtime_extension_id =
137 rtp_abs_sendtime_extn_id_;
138 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len,
139 &updated_options.packet_time_params.srtp_packet_index);
140 // If protection succeeds, let's get auth params from srtp.
141 if (res) {
142 uint8_t* auth_key = nullptr;
143 int key_len = 0;
144 res = GetRtpAuthParams(
145 &auth_key, &key_len,
146 &updated_options.packet_time_params.srtp_auth_tag_len);
Zhi Huangcf990f52017-09-22 12:12:30 -0700147 if (res) {
Zhi Huang365381f2018-04-13 16:44:34 -0700148 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
149 updated_options.packet_time_params.srtp_auth_key.assign(
150 auth_key, auth_key + key_len);
Zhi Huangcf990f52017-09-22 12:12:30 -0700151 }
152 }
Zhi Huang365381f2018-04-13 16:44:34 -0700153 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700154#endif
Zhi Huang365381f2018-04-13 16:44:34 -0700155 if (!res) {
156 int seq_num = -1;
157 uint32_t ssrc = 0;
158 cricket::GetRtpSeqNum(data, len, &seq_num);
159 cricket::GetRtpSsrc(data, len, &ssrc);
160 RTC_LOG(LS_ERROR) << "Failed to protect RTP packet: size=" << len
161 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
162 return false;
Zhi Huangcf990f52017-09-22 12:12:30 -0700163 }
164
165 // Update the length of the packet now that we've added the auth tag.
166 packet->SetSize(len);
Zhi Huang365381f2018-04-13 16:44:34 -0700167 return SendPacket(/*rtcp=*/false, packet, updated_options, flags);
zstein398c3fd2017-07-19 13:38:02 -0700168}
169
Zhi Huang365381f2018-04-13 16:44:34 -0700170bool SrtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
171 const rtc::PacketOptions& options,
172 int flags) {
173 if (!IsSrtpActive()) {
174 RTC_LOG(LS_ERROR)
175 << "Failed to send the packet because SRTP transport is inactive.";
176 return false;
177 }
178
179 TRACE_EVENT0("webrtc", "SRTP Encode");
180 uint8_t* data = packet->data();
181 int len = rtc::checked_cast<int>(packet->size());
182 if (!ProtectRtcp(data, len, static_cast<int>(packet->capacity()), &len)) {
183 int type = -1;
184 cricket::GetRtcpType(data, len, &type);
185 RTC_LOG(LS_ERROR) << "Failed to protect RTCP packet: size=" << len
186 << ", type=" << type;
187 return false;
188 }
189 // Update the length of the packet now that we've added the auth tag.
190 packet->SetSize(len);
191
192 return SendPacket(/*rtcp=*/true, packet, options, flags);
193}
194
195void SrtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer* packet,
196 const rtc::PacketTime& packet_time) {
Zhi Huange830e682018-03-30 10:48:35 -0700197 if (!IsSrtpActive()) {
Zhi Huang27f3bf52018-03-26 21:37:23 -0700198 RTC_LOG(LS_WARNING)
Zhi Huang365381f2018-04-13 16:44:34 -0700199 << "Inactive SRTP transport received an RTP packet. Drop it.";
Zhi Huang27f3bf52018-03-26 21:37:23 -0700200 return;
201 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700202 TRACE_EVENT0("webrtc", "SRTP Decode");
203 char* data = packet->data<char>();
Zhi Huang365381f2018-04-13 16:44:34 -0700204 int len = rtc::checked_cast<int>(packet->size());
205 if (!UnprotectRtp(data, len, &len)) {
206 int seq_num = -1;
207 uint32_t ssrc = 0;
208 cricket::GetRtpSeqNum(data, len, &seq_num);
209 cricket::GetRtpSsrc(data, len, &ssrc);
210 RTC_LOG(LS_ERROR) << "Failed to unprotect RTP packet: size=" << len
211 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
212 return;
Zhi Huangcf990f52017-09-22 12:12:30 -0700213 }
Zhi Huang27f3bf52018-03-26 21:37:23 -0700214 packet->SetSize(len);
Zhi Huang365381f2018-04-13 16:44:34 -0700215 DemuxPacket(packet, packet_time);
216}
217
218void SrtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
219 const rtc::PacketTime& packet_time) {
220 if (!IsSrtpActive()) {
221 RTC_LOG(LS_WARNING)
222 << "Inactive SRTP transport received an RTCP packet. Drop it.";
223 return;
224 }
225 TRACE_EVENT0("webrtc", "SRTP Decode");
226 char* data = packet->data<char>();
227 int len = rtc::checked_cast<int>(packet->size());
228 if (!UnprotectRtcp(data, len, &len)) {
229 int type = -1;
230 cricket::GetRtcpType(data, len, &type);
231 RTC_LOG(LS_ERROR) << "Failed to unprotect RTCP packet: size=" << len
232 << ", type=" << type;
233 return;
234 }
235 packet->SetSize(len);
236 SignalRtcpPacketReceived(packet, packet_time);
zstein398c3fd2017-07-19 13:38:02 -0700237}
238
Zhi Huang942bc2e2017-11-13 13:26:07 -0800239void SrtpTransport::OnNetworkRouteChanged(
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200240 absl::optional<rtc::NetworkRoute> network_route) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800241 // Only append the SRTP overhead when there is a selected network route.
242 if (network_route) {
243 int srtp_overhead = 0;
Zhi Huange830e682018-03-30 10:48:35 -0700244 if (IsSrtpActive()) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800245 GetSrtpOverhead(&srtp_overhead);
246 }
247 network_route->packet_overhead += srtp_overhead;
248 }
249 SignalNetworkRouteChanged(network_route);
250}
251
Zhi Huang365381f2018-04-13 16:44:34 -0700252void SrtpTransport::OnWritableState(
253 rtc::PacketTransportInternal* packet_transport) {
254 SignalWritableState(IsWritable(/*rtcp=*/true) && IsWritable(/*rtcp=*/true));
255}
256
Zhi Huangcf990f52017-09-22 12:12:30 -0700257bool SrtpTransport::SetRtpParams(int send_cs,
258 const uint8_t* send_key,
259 int send_key_len,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800260 const std::vector<int>& send_extension_ids,
Zhi Huangcf990f52017-09-22 12:12:30 -0700261 int recv_cs,
262 const uint8_t* recv_key,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800263 int recv_key_len,
264 const std::vector<int>& recv_extension_ids) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700265 // If parameters are being set for the first time, we should create new SRTP
266 // sessions and call "SetSend/SetRecv". Otherwise we should call
267 // "UpdateSend"/"UpdateRecv" on the existing sessions, which will internally
268 // call "srtp_update".
269 bool new_sessions = false;
270 if (!send_session_) {
271 RTC_DCHECK(!recv_session_);
272 CreateSrtpSessions();
273 new_sessions = true;
274 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700275 bool ret = new_sessions
Zhi Huangc99b6c72017-11-10 16:44:46 -0800276 ? send_session_->SetSend(send_cs, send_key, send_key_len,
277 send_extension_ids)
278 : send_session_->UpdateSend(send_cs, send_key, send_key_len,
279 send_extension_ids);
Zhi Huangcf990f52017-09-22 12:12:30 -0700280 if (!ret) {
281 ResetParams();
282 return false;
283 }
284
Zhi Huangc99b6c72017-11-10 16:44:46 -0800285 ret = new_sessions ? recv_session_->SetRecv(recv_cs, recv_key, recv_key_len,
286 recv_extension_ids)
287 : recv_session_->UpdateRecv(
288 recv_cs, recv_key, recv_key_len, recv_extension_ids);
Zhi Huangcf990f52017-09-22 12:12:30 -0700289 if (!ret) {
290 ResetParams();
291 return false;
292 }
293
Mirko Bonadei675513b2017-11-09 11:09:25 +0100294 RTC_LOG(LS_INFO) << "SRTP " << (new_sessions ? "activated" : "updated")
Jonas Olsson45cc8902018-02-13 10:37:07 +0100295 << " with negotiated parameters: send cipher_suite "
296 << send_cs << " recv cipher_suite " << recv_cs;
Zhi Huang365381f2018-04-13 16:44:34 -0700297 MaybeUpdateWritableState();
Zhi Huangcf990f52017-09-22 12:12:30 -0700298 return true;
299}
300
301bool SrtpTransport::SetRtcpParams(int send_cs,
302 const uint8_t* send_key,
303 int send_key_len,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800304 const std::vector<int>& send_extension_ids,
Zhi Huangcf990f52017-09-22 12:12:30 -0700305 int recv_cs,
306 const uint8_t* recv_key,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800307 int recv_key_len,
308 const std::vector<int>& recv_extension_ids) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700309 // This can only be called once, but can be safely called after
310 // SetRtpParams
311 if (send_rtcp_session_ || recv_rtcp_session_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100312 RTC_LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700313 return false;
314 }
315
316 send_rtcp_session_.reset(new cricket::SrtpSession());
Zhi Huangc99b6c72017-11-10 16:44:46 -0800317 if (!send_rtcp_session_->SetSend(send_cs, send_key, send_key_len,
318 send_extension_ids)) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700319 return false;
320 }
321
322 recv_rtcp_session_.reset(new cricket::SrtpSession());
Zhi Huangc99b6c72017-11-10 16:44:46 -0800323 if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len,
324 recv_extension_ids)) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700325 return false;
326 }
327
Mirko Bonadei675513b2017-11-09 11:09:25 +0100328 RTC_LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
Jonas Olsson45cc8902018-02-13 10:37:07 +0100329 " send cipher_suite "
330 << send_cs << " recv cipher_suite " << recv_cs;
Zhi Huang365381f2018-04-13 16:44:34 -0700331 MaybeUpdateWritableState();
Zhi Huangcf990f52017-09-22 12:12:30 -0700332 return true;
333}
334
Zhi Huange830e682018-03-30 10:48:35 -0700335bool SrtpTransport::IsSrtpActive() const {
Zhi Huangcf990f52017-09-22 12:12:30 -0700336 return send_session_ && recv_session_;
337}
338
Zhi Huang365381f2018-04-13 16:44:34 -0700339bool SrtpTransport::IsWritable(bool rtcp) const {
340 return IsSrtpActive() && RtpTransport::IsWritable(rtcp);
341}
342
Zhi Huangcf990f52017-09-22 12:12:30 -0700343void SrtpTransport::ResetParams() {
344 send_session_ = nullptr;
345 recv_session_ = nullptr;
346 send_rtcp_session_ = nullptr;
347 recv_rtcp_session_ = nullptr;
Zhi Huang365381f2018-04-13 16:44:34 -0700348 MaybeUpdateWritableState();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100349 RTC_LOG(LS_INFO) << "The params in SRTP transport are reset.";
Zhi Huangcf990f52017-09-22 12:12:30 -0700350}
351
Zhi Huangcf990f52017-09-22 12:12:30 -0700352void SrtpTransport::CreateSrtpSessions() {
353 send_session_.reset(new cricket::SrtpSession());
354 recv_session_.reset(new cricket::SrtpSession());
Zhi Huangcf990f52017-09-22 12:12:30 -0700355 if (external_auth_enabled_) {
356 send_session_->EnableExternalAuth();
357 }
358}
359
360bool SrtpTransport::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700361 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100362 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700363 return false;
364 }
365 RTC_CHECK(send_session_);
366 return send_session_->ProtectRtp(p, in_len, max_len, out_len);
367}
368
369bool SrtpTransport::ProtectRtp(void* p,
370 int in_len,
371 int max_len,
372 int* out_len,
373 int64_t* index) {
Zhi Huange830e682018-03-30 10:48:35 -0700374 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100375 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700376 return false;
377 }
378 RTC_CHECK(send_session_);
379 return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
380}
381
382bool SrtpTransport::ProtectRtcp(void* p,
383 int in_len,
384 int max_len,
385 int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700386 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100387 RTC_LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700388 return false;
389 }
390 if (send_rtcp_session_) {
391 return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
392 } else {
393 RTC_CHECK(send_session_);
394 return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
395 }
396}
397
398bool SrtpTransport::UnprotectRtp(void* p, int in_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700399 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100400 RTC_LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700401 return false;
402 }
403 RTC_CHECK(recv_session_);
404 return recv_session_->UnprotectRtp(p, in_len, out_len);
405}
406
407bool SrtpTransport::UnprotectRtcp(void* p, int in_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700408 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100409 RTC_LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700410 return false;
411 }
412 if (recv_rtcp_session_) {
413 return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
414 } else {
415 RTC_CHECK(recv_session_);
416 return recv_session_->UnprotectRtcp(p, in_len, out_len);
417 }
418}
419
420bool SrtpTransport::GetRtpAuthParams(uint8_t** key,
421 int* key_len,
422 int* tag_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700423 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100424 RTC_LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700425 return false;
426 }
427
428 RTC_CHECK(send_session_);
429 return send_session_->GetRtpAuthParams(key, key_len, tag_len);
430}
431
432bool SrtpTransport::GetSrtpOverhead(int* srtp_overhead) const {
Zhi Huange830e682018-03-30 10:48:35 -0700433 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100434 RTC_LOG(LS_WARNING) << "Failed to GetSrtpOverhead: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700435 return false;
436 }
437
438 RTC_CHECK(send_session_);
439 *srtp_overhead = send_session_->GetSrtpOverhead();
440 return true;
441}
442
443void SrtpTransport::EnableExternalAuth() {
Zhi Huange830e682018-03-30 10:48:35 -0700444 RTC_DCHECK(!IsSrtpActive());
Zhi Huangcf990f52017-09-22 12:12:30 -0700445 external_auth_enabled_ = true;
446}
447
448bool SrtpTransport::IsExternalAuthEnabled() const {
449 return external_auth_enabled_;
450}
451
452bool SrtpTransport::IsExternalAuthActive() const {
Zhi Huange830e682018-03-30 10:48:35 -0700453 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100454 RTC_LOG(LS_WARNING)
455 << "Failed to check IsExternalAuthActive: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700456 return false;
457 }
458
459 RTC_CHECK(send_session_);
460 return send_session_->IsExternalAuthActive();
461}
462
Zhi Huange830e682018-03-30 10:48:35 -0700463bool SrtpTransport::MaybeSetKeyParams() {
464 if (!send_cipher_suite_ || !recv_cipher_suite_) {
465 return true;
466 }
467
468 return SetRtpParams(*send_cipher_suite_, send_key_.data(),
469 static_cast<int>(send_key_.size()), std::vector<int>(),
470 *recv_cipher_suite_, recv_key_.data(),
471 static_cast<int>(recv_key_.size()), std::vector<int>());
472}
473
474bool SrtpTransport::ParseKeyParams(const std::string& key_params,
475 uint8_t* key,
476 size_t len) {
477 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
478
479 // Fail if key-method is wrong.
480 if (key_params.find("inline:") != 0) {
481 return false;
482 }
483
484 // Fail if base64 decode fails, or the key is the wrong size.
485 std::string key_b64(key_params.substr(7)), key_str;
486 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, &key_str,
487 nullptr) ||
488 key_str.size() != len) {
489 return false;
490 }
491
492 memcpy(key, key_str.c_str(), len);
493 // TODO(bugs.webrtc.org/8905): Switch to ZeroOnFreeBuffer for storing
494 // sensitive data.
495 rtc::ExplicitZeroMemory(&key_str[0], key_str.size());
496 return true;
497}
498
Zhi Huang365381f2018-04-13 16:44:34 -0700499void SrtpTransport::MaybeUpdateWritableState() {
500 bool writable = IsWritable(/*rtcp=*/true) && IsWritable(/*rtcp=*/false);
501 // Only fire the signal if the writable state changes.
502 if (writable_ != writable) {
503 writable_ = writable;
504 SignalWritableState(writable_);
505 }
Steve Antondb67ba12018-03-19 17:41:42 -0700506}
507
zstein398c3fd2017-07-19 13:38:02 -0700508} // namespace webrtc