blob: a1c1a8a3b6dbcbfe80ccd034d86cce00c09ef384 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "media/base/rtputils.h"
17#include "pc/rtptransport.h"
18#include "pc/srtpsession.h"
19#include "rtc_base/asyncpacketsocket.h"
Zhi Huangcf990f52017-09-22 12:12:30 -070020#include "rtc_base/base64.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"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "rtc_base/ptr_util.h"
24#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
Steve Antondb67ba12018-03-19 17:41:42 -0700328 if (metrics_observer_) {
329 send_rtcp_session_->SetMetricsObserver(metrics_observer_);
330 recv_rtcp_session_->SetMetricsObserver(metrics_observer_);
331 }
332
Mirko Bonadei675513b2017-11-09 11:09:25 +0100333 RTC_LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
Jonas Olsson45cc8902018-02-13 10:37:07 +0100334 " send cipher_suite "
335 << send_cs << " recv cipher_suite " << recv_cs;
Zhi Huang365381f2018-04-13 16:44:34 -0700336 MaybeUpdateWritableState();
Zhi Huangcf990f52017-09-22 12:12:30 -0700337 return true;
338}
339
Zhi Huange830e682018-03-30 10:48:35 -0700340bool SrtpTransport::IsSrtpActive() const {
Zhi Huangcf990f52017-09-22 12:12:30 -0700341 return send_session_ && recv_session_;
342}
343
Zhi Huang365381f2018-04-13 16:44:34 -0700344bool SrtpTransport::IsWritable(bool rtcp) const {
345 return IsSrtpActive() && RtpTransport::IsWritable(rtcp);
346}
347
Zhi Huangcf990f52017-09-22 12:12:30 -0700348void SrtpTransport::ResetParams() {
349 send_session_ = nullptr;
350 recv_session_ = nullptr;
351 send_rtcp_session_ = nullptr;
352 recv_rtcp_session_ = nullptr;
Zhi Huang365381f2018-04-13 16:44:34 -0700353 MaybeUpdateWritableState();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100354 RTC_LOG(LS_INFO) << "The params in SRTP transport are reset.";
Zhi Huangcf990f52017-09-22 12:12:30 -0700355}
356
Zhi Huangcf990f52017-09-22 12:12:30 -0700357void SrtpTransport::CreateSrtpSessions() {
358 send_session_.reset(new cricket::SrtpSession());
359 recv_session_.reset(new cricket::SrtpSession());
Steve Antondb67ba12018-03-19 17:41:42 -0700360 if (metrics_observer_) {
361 send_session_->SetMetricsObserver(metrics_observer_);
362 recv_session_->SetMetricsObserver(metrics_observer_);
363 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700364
365 if (external_auth_enabled_) {
366 send_session_->EnableExternalAuth();
367 }
368}
369
370bool SrtpTransport::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700371 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100372 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700373 return false;
374 }
375 RTC_CHECK(send_session_);
376 return send_session_->ProtectRtp(p, in_len, max_len, out_len);
377}
378
379bool SrtpTransport::ProtectRtp(void* p,
380 int in_len,
381 int max_len,
382 int* out_len,
383 int64_t* index) {
Zhi Huange830e682018-03-30 10:48:35 -0700384 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100385 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700386 return false;
387 }
388 RTC_CHECK(send_session_);
389 return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
390}
391
392bool SrtpTransport::ProtectRtcp(void* p,
393 int in_len,
394 int max_len,
395 int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700396 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100397 RTC_LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700398 return false;
399 }
400 if (send_rtcp_session_) {
401 return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
402 } else {
403 RTC_CHECK(send_session_);
404 return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
405 }
406}
407
408bool SrtpTransport::UnprotectRtp(void* p, int in_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700409 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100410 RTC_LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700411 return false;
412 }
413 RTC_CHECK(recv_session_);
414 return recv_session_->UnprotectRtp(p, in_len, out_len);
415}
416
417bool SrtpTransport::UnprotectRtcp(void* p, int in_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700418 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100419 RTC_LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700420 return false;
421 }
422 if (recv_rtcp_session_) {
423 return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
424 } else {
425 RTC_CHECK(recv_session_);
426 return recv_session_->UnprotectRtcp(p, in_len, out_len);
427 }
428}
429
430bool SrtpTransport::GetRtpAuthParams(uint8_t** key,
431 int* key_len,
432 int* tag_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700433 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100434 RTC_LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700435 return false;
436 }
437
438 RTC_CHECK(send_session_);
439 return send_session_->GetRtpAuthParams(key, key_len, tag_len);
440}
441
442bool SrtpTransport::GetSrtpOverhead(int* srtp_overhead) const {
Zhi Huange830e682018-03-30 10:48:35 -0700443 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100444 RTC_LOG(LS_WARNING) << "Failed to GetSrtpOverhead: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700445 return false;
446 }
447
448 RTC_CHECK(send_session_);
449 *srtp_overhead = send_session_->GetSrtpOverhead();
450 return true;
451}
452
453void SrtpTransport::EnableExternalAuth() {
Zhi Huange830e682018-03-30 10:48:35 -0700454 RTC_DCHECK(!IsSrtpActive());
Zhi Huangcf990f52017-09-22 12:12:30 -0700455 external_auth_enabled_ = true;
456}
457
458bool SrtpTransport::IsExternalAuthEnabled() const {
459 return external_auth_enabled_;
460}
461
462bool SrtpTransport::IsExternalAuthActive() const {
Zhi Huange830e682018-03-30 10:48:35 -0700463 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100464 RTC_LOG(LS_WARNING)
465 << "Failed to check IsExternalAuthActive: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700466 return false;
467 }
468
469 RTC_CHECK(send_session_);
470 return send_session_->IsExternalAuthActive();
471}
472
Zhi Huange830e682018-03-30 10:48:35 -0700473bool SrtpTransport::MaybeSetKeyParams() {
474 if (!send_cipher_suite_ || !recv_cipher_suite_) {
475 return true;
476 }
477
478 return SetRtpParams(*send_cipher_suite_, send_key_.data(),
479 static_cast<int>(send_key_.size()), std::vector<int>(),
480 *recv_cipher_suite_, recv_key_.data(),
481 static_cast<int>(recv_key_.size()), std::vector<int>());
482}
483
484bool SrtpTransport::ParseKeyParams(const std::string& key_params,
485 uint8_t* key,
486 size_t len) {
487 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
488
489 // Fail if key-method is wrong.
490 if (key_params.find("inline:") != 0) {
491 return false;
492 }
493
494 // Fail if base64 decode fails, or the key is the wrong size.
495 std::string key_b64(key_params.substr(7)), key_str;
496 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, &key_str,
497 nullptr) ||
498 key_str.size() != len) {
499 return false;
500 }
501
502 memcpy(key, key_str.c_str(), len);
503 // TODO(bugs.webrtc.org/8905): Switch to ZeroOnFreeBuffer for storing
504 // sensitive data.
505 rtc::ExplicitZeroMemory(&key_str[0], key_str.size());
506 return true;
507}
508
Steve Antondb67ba12018-03-19 17:41:42 -0700509void SrtpTransport::SetMetricsObserver(
510 rtc::scoped_refptr<MetricsObserverInterface> metrics_observer) {
511 metrics_observer_ = metrics_observer;
512 if (send_session_) {
513 send_session_->SetMetricsObserver(metrics_observer_);
514 }
515 if (recv_session_) {
516 recv_session_->SetMetricsObserver(metrics_observer_);
517 }
518 if (send_rtcp_session_) {
519 send_rtcp_session_->SetMetricsObserver(metrics_observer_);
520 }
521 if (recv_rtcp_session_) {
522 recv_rtcp_session_->SetMetricsObserver(metrics_observer_);
523 }
Zhi Huang365381f2018-04-13 16:44:34 -0700524}
525
526void SrtpTransport::MaybeUpdateWritableState() {
527 bool writable = IsWritable(/*rtcp=*/true) && IsWritable(/*rtcp=*/false);
528 // Only fire the signal if the writable state changes.
529 if (writable_ != writable) {
530 writable_ = writable;
531 SignalWritableState(writable_);
532 }
Steve Antondb67ba12018-03-19 17:41:42 -0700533}
534
zstein398c3fd2017-07-19 13:38:02 -0700535} // namespace webrtc