blob: 8f9de671466230900830a8d718508e6c6fa3f58d [file] [log] [blame]
zstein398c3fd2017-07-19 20:38:021/*
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 04:47:3111#include "pc/srtptransport.h"
zstein398c3fd2017-07-19 20:38:0212
13#include <string>
Steve Anton36b29d12017-10-30 16:57:4214#include <vector>
zstein398c3fd2017-07-19 20:38:0215
Karl Wiberg918f50c2018-07-05 09:40:3316#include "absl/memory/memory.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3117#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 04:47:3121#include "rtc_base/copyonwritebuffer.h"
Zhi Huang365381f2018-04-13 23:44:3422#include "rtc_base/numerics/safe_conversions.h"
Artem Titova76af0c2018-07-23 15:38:1223#include "rtc_base/third_party/base64/base64.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3124#include "rtc_base/trace_event.h"
Zhi Huange830e682018-03-30 17:48:3525#include "rtc_base/zero_memory.h"
zstein398c3fd2017-07-19 20:38:0226
27namespace webrtc {
28
Zhi Huang2dfc42d2017-12-04 21:38:4829SrtpTransport::SrtpTransport(bool rtcp_mux_enabled)
Zhi Huang365381f2018-04-13 23:44:3430 : RtpTransport(rtcp_mux_enabled) {}
zstein398c3fd2017-07-19 20:38:0231
Zhi Huange830e682018-03-30 17:48:3532RTCError 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 19:12:30112bool SrtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
113 const rtc::PacketOptions& options,
114 int flags) {
Zhi Huange830e682018-03-30 17:48:35115 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 10:09:25116 RTC_LOG(LS_ERROR)
Zhi Huangcf990f52017-09-22 19:12:30117 << "Failed to send the packet because SRTP transport is inactive.";
118 return false;
119 }
Zhi Huangcf990f52017-09-22 19:12:30120 rtc::PacketOptions updated_options = options;
Zhi Huangcf990f52017-09-22 19:12:30121 TRACE_EVENT0("webrtc", "SRTP Encode");
122 bool res;
123 uint8_t* data = packet->data();
Zhi Huang365381f2018-04-13 23:44:34124 int len = rtc::checked_cast<int>(packet->size());
Zhi Huangcf990f52017-09-22 19:12:30125// 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 23:44:34131 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
Zhi Huang95e7dbb2018-03-29 00:08:03132#else
Zhi Huang365381f2018-04-13 23:44:34133 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 19:12:30147 if (res) {
Zhi Huang365381f2018-04-13 23:44:34148 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 19:12:30151 }
152 }
Zhi Huang365381f2018-04-13 23:44:34153 }
Zhi Huangcf990f52017-09-22 19:12:30154#endif
Zhi Huang365381f2018-04-13 23:44:34155 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 19:12:30163 }
164
165 // Update the length of the packet now that we've added the auth tag.
166 packet->SetSize(len);
Zhi Huang365381f2018-04-13 23:44:34167 return SendPacket(/*rtcp=*/false, packet, updated_options, flags);
zstein398c3fd2017-07-19 20:38:02168}
169
Zhi Huang365381f2018-04-13 23:44:34170bool 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 17:48:35197 if (!IsSrtpActive()) {
Zhi Huang27f3bf52018-03-27 04:37:23198 RTC_LOG(LS_WARNING)
Zhi Huang365381f2018-04-13 23:44:34199 << "Inactive SRTP transport received an RTP packet. Drop it.";
Zhi Huang27f3bf52018-03-27 04:37:23200 return;
201 }
Zhi Huangcf990f52017-09-22 19:12:30202 TRACE_EVENT0("webrtc", "SRTP Decode");
203 char* data = packet->data<char>();
Zhi Huang365381f2018-04-13 23:44:34204 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);
erikvarga@webrtc.orgd76a0fc2018-10-09 10:31:28210
211 // Limit the error logging to avoid excessive logs when there are lots of
212 // bad packets.
213 const int kFailureLogThrottleCount = 100;
214 if (decryption_failure_count_ % kFailureLogThrottleCount == 0) {
215 RTC_LOG(LS_ERROR) << "Failed to unprotect RTP packet: size=" << len
216 << ", seqnum=" << seq_num << ", SSRC=" << ssrc
217 << ", previous failure count: "
218 << decryption_failure_count_;
219 }
220 ++decryption_failure_count_;
Zhi Huang365381f2018-04-13 23:44:34221 return;
Zhi Huangcf990f52017-09-22 19:12:30222 }
Zhi Huang27f3bf52018-03-27 04:37:23223 packet->SetSize(len);
Zhi Huang365381f2018-04-13 23:44:34224 DemuxPacket(packet, packet_time);
225}
226
227void SrtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet,
228 const rtc::PacketTime& packet_time) {
229 if (!IsSrtpActive()) {
230 RTC_LOG(LS_WARNING)
231 << "Inactive SRTP transport received an RTCP packet. Drop it.";
232 return;
233 }
234 TRACE_EVENT0("webrtc", "SRTP Decode");
235 char* data = packet->data<char>();
236 int len = rtc::checked_cast<int>(packet->size());
237 if (!UnprotectRtcp(data, len, &len)) {
238 int type = -1;
239 cricket::GetRtcpType(data, len, &type);
240 RTC_LOG(LS_ERROR) << "Failed to unprotect RTCP packet: size=" << len
241 << ", type=" << type;
242 return;
243 }
244 packet->SetSize(len);
245 SignalRtcpPacketReceived(packet, packet_time);
zstein398c3fd2017-07-19 20:38:02246}
247
Zhi Huang942bc2e2017-11-13 21:26:07248void SrtpTransport::OnNetworkRouteChanged(
Danil Chapovalov66cadcc2018-06-19 14:47:43249 absl::optional<rtc::NetworkRoute> network_route) {
Zhi Huang942bc2e2017-11-13 21:26:07250 // Only append the SRTP overhead when there is a selected network route.
251 if (network_route) {
252 int srtp_overhead = 0;
Zhi Huange830e682018-03-30 17:48:35253 if (IsSrtpActive()) {
Zhi Huang942bc2e2017-11-13 21:26:07254 GetSrtpOverhead(&srtp_overhead);
255 }
256 network_route->packet_overhead += srtp_overhead;
257 }
258 SignalNetworkRouteChanged(network_route);
259}
260
Zhi Huang365381f2018-04-13 23:44:34261void SrtpTransport::OnWritableState(
262 rtc::PacketTransportInternal* packet_transport) {
263 SignalWritableState(IsWritable(/*rtcp=*/true) && IsWritable(/*rtcp=*/true));
264}
265
Zhi Huangcf990f52017-09-22 19:12:30266bool SrtpTransport::SetRtpParams(int send_cs,
267 const uint8_t* send_key,
268 int send_key_len,
Zhi Huangc99b6c72017-11-11 00:44:46269 const std::vector<int>& send_extension_ids,
Zhi Huangcf990f52017-09-22 19:12:30270 int recv_cs,
271 const uint8_t* recv_key,
Zhi Huangc99b6c72017-11-11 00:44:46272 int recv_key_len,
273 const std::vector<int>& recv_extension_ids) {
Zhi Huangcf990f52017-09-22 19:12:30274 // If parameters are being set for the first time, we should create new SRTP
275 // sessions and call "SetSend/SetRecv". Otherwise we should call
276 // "UpdateSend"/"UpdateRecv" on the existing sessions, which will internally
277 // call "srtp_update".
278 bool new_sessions = false;
279 if (!send_session_) {
280 RTC_DCHECK(!recv_session_);
281 CreateSrtpSessions();
282 new_sessions = true;
283 }
Zhi Huangcf990f52017-09-22 19:12:30284 bool ret = new_sessions
Zhi Huangc99b6c72017-11-11 00:44:46285 ? send_session_->SetSend(send_cs, send_key, send_key_len,
286 send_extension_ids)
287 : send_session_->UpdateSend(send_cs, send_key, send_key_len,
288 send_extension_ids);
Zhi Huangcf990f52017-09-22 19:12:30289 if (!ret) {
290 ResetParams();
291 return false;
292 }
293
Zhi Huangc99b6c72017-11-11 00:44:46294 ret = new_sessions ? recv_session_->SetRecv(recv_cs, recv_key, recv_key_len,
295 recv_extension_ids)
296 : recv_session_->UpdateRecv(
297 recv_cs, recv_key, recv_key_len, recv_extension_ids);
Zhi Huangcf990f52017-09-22 19:12:30298 if (!ret) {
299 ResetParams();
300 return false;
301 }
302
Mirko Bonadei675513b2017-11-09 10:09:25303 RTC_LOG(LS_INFO) << "SRTP " << (new_sessions ? "activated" : "updated")
Jonas Olsson45cc8902018-02-13 09:37:07304 << " with negotiated parameters: send cipher_suite "
305 << send_cs << " recv cipher_suite " << recv_cs;
Zhi Huang365381f2018-04-13 23:44:34306 MaybeUpdateWritableState();
Zhi Huangcf990f52017-09-22 19:12:30307 return true;
308}
309
310bool SrtpTransport::SetRtcpParams(int send_cs,
311 const uint8_t* send_key,
312 int send_key_len,
Zhi Huangc99b6c72017-11-11 00:44:46313 const std::vector<int>& send_extension_ids,
Zhi Huangcf990f52017-09-22 19:12:30314 int recv_cs,
315 const uint8_t* recv_key,
Zhi Huangc99b6c72017-11-11 00:44:46316 int recv_key_len,
317 const std::vector<int>& recv_extension_ids) {
Zhi Huangcf990f52017-09-22 19:12:30318 // This can only be called once, but can be safely called after
319 // SetRtpParams
320 if (send_rtcp_session_ || recv_rtcp_session_) {
Mirko Bonadei675513b2017-11-09 10:09:25321 RTC_LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active";
Zhi Huangcf990f52017-09-22 19:12:30322 return false;
323 }
324
325 send_rtcp_session_.reset(new cricket::SrtpSession());
Zhi Huangc99b6c72017-11-11 00:44:46326 if (!send_rtcp_session_->SetSend(send_cs, send_key, send_key_len,
327 send_extension_ids)) {
Zhi Huangcf990f52017-09-22 19:12:30328 return false;
329 }
330
331 recv_rtcp_session_.reset(new cricket::SrtpSession());
Zhi Huangc99b6c72017-11-11 00:44:46332 if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len,
333 recv_extension_ids)) {
Zhi Huangcf990f52017-09-22 19:12:30334 return false;
335 }
336
Mirko Bonadei675513b2017-11-09 10:09:25337 RTC_LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
Jonas Olsson45cc8902018-02-13 09:37:07338 " send cipher_suite "
339 << send_cs << " recv cipher_suite " << recv_cs;
Zhi Huang365381f2018-04-13 23:44:34340 MaybeUpdateWritableState();
Zhi Huangcf990f52017-09-22 19:12:30341 return true;
342}
343
Zhi Huange830e682018-03-30 17:48:35344bool SrtpTransport::IsSrtpActive() const {
Zhi Huangcf990f52017-09-22 19:12:30345 return send_session_ && recv_session_;
346}
347
Zhi Huang365381f2018-04-13 23:44:34348bool SrtpTransport::IsWritable(bool rtcp) const {
349 return IsSrtpActive() && RtpTransport::IsWritable(rtcp);
350}
351
Zhi Huangcf990f52017-09-22 19:12:30352void SrtpTransport::ResetParams() {
353 send_session_ = nullptr;
354 recv_session_ = nullptr;
355 send_rtcp_session_ = nullptr;
356 recv_rtcp_session_ = nullptr;
Zhi Huang365381f2018-04-13 23:44:34357 MaybeUpdateWritableState();
Mirko Bonadei675513b2017-11-09 10:09:25358 RTC_LOG(LS_INFO) << "The params in SRTP transport are reset.";
Zhi Huangcf990f52017-09-22 19:12:30359}
360
Zhi Huangcf990f52017-09-22 19:12:30361void SrtpTransport::CreateSrtpSessions() {
362 send_session_.reset(new cricket::SrtpSession());
363 recv_session_.reset(new cricket::SrtpSession());
Zhi Huangcf990f52017-09-22 19:12:30364 if (external_auth_enabled_) {
365 send_session_->EnableExternalAuth();
366 }
367}
368
369bool SrtpTransport::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
Zhi Huange830e682018-03-30 17:48:35370 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 10:09:25371 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 19:12:30372 return false;
373 }
374 RTC_CHECK(send_session_);
375 return send_session_->ProtectRtp(p, in_len, max_len, out_len);
376}
377
378bool SrtpTransport::ProtectRtp(void* p,
379 int in_len,
380 int max_len,
381 int* out_len,
382 int64_t* index) {
Zhi Huange830e682018-03-30 17:48:35383 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 10:09:25384 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 19:12:30385 return false;
386 }
387 RTC_CHECK(send_session_);
388 return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
389}
390
391bool SrtpTransport::ProtectRtcp(void* p,
392 int in_len,
393 int max_len,
394 int* out_len) {
Zhi Huange830e682018-03-30 17:48:35395 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 10:09:25396 RTC_LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 19:12:30397 return false;
398 }
399 if (send_rtcp_session_) {
400 return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
401 } else {
402 RTC_CHECK(send_session_);
403 return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
404 }
405}
406
407bool SrtpTransport::UnprotectRtp(void* p, int in_len, int* out_len) {
Zhi Huange830e682018-03-30 17:48:35408 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 10:09:25409 RTC_LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 19:12:30410 return false;
411 }
412 RTC_CHECK(recv_session_);
413 return recv_session_->UnprotectRtp(p, in_len, out_len);
414}
415
416bool SrtpTransport::UnprotectRtcp(void* p, int in_len, int* out_len) {
Zhi Huange830e682018-03-30 17:48:35417 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 10:09:25418 RTC_LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 19:12:30419 return false;
420 }
421 if (recv_rtcp_session_) {
422 return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
423 } else {
424 RTC_CHECK(recv_session_);
425 return recv_session_->UnprotectRtcp(p, in_len, out_len);
426 }
427}
428
429bool SrtpTransport::GetRtpAuthParams(uint8_t** key,
430 int* key_len,
431 int* tag_len) {
Zhi Huange830e682018-03-30 17:48:35432 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 10:09:25433 RTC_LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active";
Zhi Huangcf990f52017-09-22 19:12:30434 return false;
435 }
436
437 RTC_CHECK(send_session_);
438 return send_session_->GetRtpAuthParams(key, key_len, tag_len);
439}
440
441bool SrtpTransport::GetSrtpOverhead(int* srtp_overhead) const {
Zhi Huange830e682018-03-30 17:48:35442 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 10:09:25443 RTC_LOG(LS_WARNING) << "Failed to GetSrtpOverhead: SRTP not active";
Zhi Huangcf990f52017-09-22 19:12:30444 return false;
445 }
446
447 RTC_CHECK(send_session_);
448 *srtp_overhead = send_session_->GetSrtpOverhead();
449 return true;
450}
451
452void SrtpTransport::EnableExternalAuth() {
Zhi Huange830e682018-03-30 17:48:35453 RTC_DCHECK(!IsSrtpActive());
Zhi Huangcf990f52017-09-22 19:12:30454 external_auth_enabled_ = true;
455}
456
457bool SrtpTransport::IsExternalAuthEnabled() const {
458 return external_auth_enabled_;
459}
460
461bool SrtpTransport::IsExternalAuthActive() const {
Zhi Huange830e682018-03-30 17:48:35462 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 10:09:25463 RTC_LOG(LS_WARNING)
464 << "Failed to check IsExternalAuthActive: SRTP not active";
Zhi Huangcf990f52017-09-22 19:12:30465 return false;
466 }
467
468 RTC_CHECK(send_session_);
469 return send_session_->IsExternalAuthActive();
470}
471
Zhi Huange830e682018-03-30 17:48:35472bool SrtpTransport::MaybeSetKeyParams() {
473 if (!send_cipher_suite_ || !recv_cipher_suite_) {
474 return true;
475 }
476
477 return SetRtpParams(*send_cipher_suite_, send_key_.data(),
478 static_cast<int>(send_key_.size()), std::vector<int>(),
479 *recv_cipher_suite_, recv_key_.data(),
480 static_cast<int>(recv_key_.size()), std::vector<int>());
481}
482
483bool SrtpTransport::ParseKeyParams(const std::string& key_params,
484 uint8_t* key,
485 size_t len) {
486 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
487
488 // Fail if key-method is wrong.
489 if (key_params.find("inline:") != 0) {
490 return false;
491 }
492
493 // Fail if base64 decode fails, or the key is the wrong size.
494 std::string key_b64(key_params.substr(7)), key_str;
495 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, &key_str,
496 nullptr) ||
497 key_str.size() != len) {
498 return false;
499 }
500
501 memcpy(key, key_str.c_str(), len);
502 // TODO(bugs.webrtc.org/8905): Switch to ZeroOnFreeBuffer for storing
503 // sensitive data.
504 rtc::ExplicitZeroMemory(&key_str[0], key_str.size());
505 return true;
506}
507
Zhi Huang365381f2018-04-13 23:44:34508void SrtpTransport::MaybeUpdateWritableState() {
509 bool writable = IsWritable(/*rtcp=*/true) && IsWritable(/*rtcp=*/false);
510 // Only fire the signal if the writable state changes.
511 if (writable_ != writable) {
512 writable_ = writable;
513 SignalWritableState(writable_);
514 }
Steve Antondb67ba12018-03-20 00:41:42515}
516
zstein398c3fd2017-07-19 20:38:02517} // namespace webrtc