blob: 3e7b154fc0c46fa57b7b6fee157e63dcaa666673 [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"
22#include "rtc_base/ptr_util.h"
23#include "rtc_base/trace_event.h"
Zhi Huange830e682018-03-30 10:48:35 -070024#include "rtc_base/zero_memory.h"
zstein398c3fd2017-07-19 13:38:02 -070025
26namespace webrtc {
27
Zhi Huang2dfc42d2017-12-04 13:38:48 -080028SrtpTransport::SrtpTransport(bool rtcp_mux_enabled)
Zhi Huang95e7dbb2018-03-29 00:08:03 +000029 : RtpTransportInternalAdapter(new RtpTransport(rtcp_mux_enabled)) {
30 // Own the raw pointer |transport| from the base class.
Zhi Huange830e682018-03-30 10:48:35 -070031 rtp_transport_.reset(static_cast<RtpTransport*>(transport_));
Zhi Huang95e7dbb2018-03-29 00:08:03 +000032 RTC_DCHECK(rtp_transport_);
33 ConnectToRtpTransport();
34}
35
Zhi Huange830e682018-03-30 10:48:35 -070036SrtpTransport::SrtpTransport(std::unique_ptr<RtpTransport> rtp_transport)
Zhi Huang95e7dbb2018-03-29 00:08:03 +000037 : RtpTransportInternalAdapter(rtp_transport.get()),
38 rtp_transport_(std::move(rtp_transport)) {
39 RTC_DCHECK(rtp_transport_);
40 ConnectToRtpTransport();
41}
42
43void SrtpTransport::ConnectToRtpTransport() {
44 rtp_transport_->SignalPacketReceived.connect(
45 this, &SrtpTransport::OnPacketReceived);
46 rtp_transport_->SignalReadyToSend.connect(this,
47 &SrtpTransport::OnReadyToSend);
48 rtp_transport_->SignalNetworkRouteChanged.connect(
49 this, &SrtpTransport::OnNetworkRouteChanged);
50 rtp_transport_->SignalWritableState.connect(this,
51 &SrtpTransport::OnWritableState);
52 rtp_transport_->SignalSentPacket.connect(this, &SrtpTransport::OnSentPacket);
53}
zstein398c3fd2017-07-19 13:38:02 -070054
Zhi Huange830e682018-03-30 10:48:35 -070055RTCError SrtpTransport::SetSrtpSendKey(const cricket::CryptoParams& params) {
56 if (send_params_) {
57 LOG_AND_RETURN_ERROR(
58 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
59 "Setting the SRTP send key twice is currently unsupported.");
60 }
61 if (recv_params_ && recv_params_->cipher_suite != params.cipher_suite) {
62 LOG_AND_RETURN_ERROR(
63 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
64 "The send key and receive key must have the same cipher suite.");
65 }
66
67 send_cipher_suite_ = rtc::SrtpCryptoSuiteFromName(params.cipher_suite);
68 if (*send_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) {
69 return RTCError(RTCErrorType::INVALID_PARAMETER,
70 "Invalid SRTP crypto suite");
71 }
72
73 int send_key_len, send_salt_len;
74 if (!rtc::GetSrtpKeyAndSaltLengths(*send_cipher_suite_, &send_key_len,
75 &send_salt_len)) {
76 return RTCError(RTCErrorType::INVALID_PARAMETER,
77 "Could not get lengths for crypto suite(s):"
78 " send cipher_suite ");
79 }
80
81 send_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(send_key_len + send_salt_len);
82 if (!ParseKeyParams(params.key_params, send_key_.data(), send_key_.size())) {
83 return RTCError(RTCErrorType::INVALID_PARAMETER,
84 "Failed to parse the crypto key params");
85 }
86
87 if (!MaybeSetKeyParams()) {
88 return RTCError(RTCErrorType::INVALID_PARAMETER,
89 "Failed to set the crypto key params");
90 }
91 send_params_ = params;
92 return RTCError::OK();
93}
94
95RTCError SrtpTransport::SetSrtpReceiveKey(const cricket::CryptoParams& params) {
96 if (recv_params_) {
97 LOG_AND_RETURN_ERROR(
98 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
99 "Setting the SRTP send key twice is currently unsupported.");
100 }
101 if (send_params_ && send_params_->cipher_suite != params.cipher_suite) {
102 LOG_AND_RETURN_ERROR(
103 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
104 "The send key and receive key must have the same cipher suite.");
105 }
106
107 recv_cipher_suite_ = rtc::SrtpCryptoSuiteFromName(params.cipher_suite);
108 if (*recv_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) {
109 return RTCError(RTCErrorType::INVALID_PARAMETER,
110 "Invalid SRTP crypto suite");
111 }
112
113 int recv_key_len, recv_salt_len;
114 if (!rtc::GetSrtpKeyAndSaltLengths(*recv_cipher_suite_, &recv_key_len,
115 &recv_salt_len)) {
116 return RTCError(RTCErrorType::INVALID_PARAMETER,
117 "Could not get lengths for crypto suite(s):"
118 " recv cipher_suite ");
119 }
120
121 recv_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(recv_key_len + recv_salt_len);
122 if (!ParseKeyParams(params.key_params, recv_key_.data(), recv_key_.size())) {
123 return RTCError(RTCErrorType::INVALID_PARAMETER,
124 "Failed to parse the crypto key params");
125 }
126
127 if (!MaybeSetKeyParams()) {
128 return RTCError(RTCErrorType::INVALID_PARAMETER,
129 "Failed to set the crypto key params");
130 }
131 recv_params_ = params;
132 return RTCError::OK();
133}
134
Zhi Huangcf990f52017-09-22 12:12:30 -0700135bool SrtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
136 const rtc::PacketOptions& options,
137 int flags) {
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000138 return SendPacket(false, packet, options, flags);
139}
140
141bool SrtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
142 const rtc::PacketOptions& options,
143 int flags) {
144 return SendPacket(true, packet, options, flags);
145}
146
147bool SrtpTransport::SendPacket(bool rtcp,
148 rtc::CopyOnWriteBuffer* packet,
149 const rtc::PacketOptions& options,
150 int flags) {
Zhi Huange830e682018-03-30 10:48:35 -0700151 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100152 RTC_LOG(LS_ERROR)
Zhi Huangcf990f52017-09-22 12:12:30 -0700153 << "Failed to send the packet because SRTP transport is inactive.";
154 return false;
155 }
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000156
Zhi Huangcf990f52017-09-22 12:12:30 -0700157 rtc::PacketOptions updated_options = options;
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000158 rtc::CopyOnWriteBuffer cp = *packet;
Zhi Huangcf990f52017-09-22 12:12:30 -0700159 TRACE_EVENT0("webrtc", "SRTP Encode");
160 bool res;
161 uint8_t* data = packet->data();
162 int len = static_cast<int>(packet->size());
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000163 if (!rtcp) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700164// If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
165// inside libsrtp for a RTP packet. A external HMAC module will be writing
166// a fake HMAC value. This is ONLY done for a RTP packet.
167// Socket layer will update rtp sendtime extension header if present in
168// packet with current time before updating the HMAC.
169#if !defined(ENABLE_EXTERNAL_AUTH)
Zhi Huang27f3bf52018-03-26 21:37:23 -0700170 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000171#else
172 if (!IsExternalAuthActive()) {
173 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
174 } else {
175 updated_options.packet_time_params.rtp_sendtime_extension_id =
176 rtp_abs_sendtime_extn_id_;
177 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len,
178 &updated_options.packet_time_params.srtp_packet_index);
179 // If protection succeeds, let's get auth params from srtp.
Zhi Huangcf990f52017-09-22 12:12:30 -0700180 if (res) {
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000181 uint8_t* auth_key = NULL;
182 int key_len;
183 res = GetRtpAuthParams(
184 &auth_key, &key_len,
185 &updated_options.packet_time_params.srtp_auth_tag_len);
186 if (res) {
187 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
188 updated_options.packet_time_params.srtp_auth_key.assign(
189 auth_key, auth_key + key_len);
190 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700191 }
192 }
193#endif
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000194 if (!res) {
195 int seq_num = -1;
196 uint32_t ssrc = 0;
197 cricket::GetRtpSeqNum(data, len, &seq_num);
198 cricket::GetRtpSsrc(data, len, &ssrc);
199 RTC_LOG(LS_ERROR) << "Failed to protect RTP packet: size=" << len
200 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
201 return false;
202 }
203 } else {
204 res = ProtectRtcp(data, len, static_cast<int>(packet->capacity()), &len);
205 if (!res) {
206 int type = -1;
207 cricket::GetRtcpType(data, len, &type);
208 RTC_LOG(LS_ERROR) << "Failed to protect RTCP packet: size=" << len
209 << ", type=" << type;
210 return false;
211 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700212 }
213
214 // Update the length of the packet now that we've added the auth tag.
215 packet->SetSize(len);
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000216 return rtcp ? rtp_transport_->SendRtcpPacket(packet, updated_options, flags)
217 : rtp_transport_->SendRtpPacket(packet, updated_options, flags);
zstein398c3fd2017-07-19 13:38:02 -0700218}
219
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000220void SrtpTransport::OnPacketReceived(bool rtcp,
221 rtc::CopyOnWriteBuffer* packet,
222 const rtc::PacketTime& packet_time) {
Zhi Huange830e682018-03-30 10:48:35 -0700223 if (!IsSrtpActive()) {
Zhi Huang27f3bf52018-03-26 21:37:23 -0700224 RTC_LOG(LS_WARNING)
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000225 << "Inactive SRTP transport received a packet. Drop it.";
Zhi Huang27f3bf52018-03-26 21:37:23 -0700226 return;
227 }
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000228
Zhi Huangcf990f52017-09-22 12:12:30 -0700229 TRACE_EVENT0("webrtc", "SRTP Decode");
230 char* data = packet->data<char>();
231 int len = static_cast<int>(packet->size());
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000232 bool res;
233 if (!rtcp) {
234 res = UnprotectRtp(data, len, &len);
235 if (!res) {
236 int seq_num = -1;
237 uint32_t ssrc = 0;
238 cricket::GetRtpSeqNum(data, len, &seq_num);
239 cricket::GetRtpSsrc(data, len, &ssrc);
240 RTC_LOG(LS_ERROR) << "Failed to unprotect RTP packet: size=" << len
241 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
242 return;
243 }
244 } else {
245 res = UnprotectRtcp(data, len, &len);
246 if (!res) {
247 int type = -1;
248 cricket::GetRtcpType(data, len, &type);
249 RTC_LOG(LS_ERROR) << "Failed to unprotect RTCP packet: size=" << len
250 << ", type=" << type;
251 return;
252 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700253 }
Zhi Huang27f3bf52018-03-26 21:37:23 -0700254
Zhi Huang27f3bf52018-03-26 21:37:23 -0700255 packet->SetSize(len);
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000256 SignalPacketReceived(rtcp, packet, packet_time);
zstein398c3fd2017-07-19 13:38:02 -0700257}
258
Zhi Huang942bc2e2017-11-13 13:26:07 -0800259void SrtpTransport::OnNetworkRouteChanged(
Zhi Huang942bc2e2017-11-13 13:26:07 -0800260 rtc::Optional<rtc::NetworkRoute> network_route) {
261 // Only append the SRTP overhead when there is a selected network route.
262 if (network_route) {
263 int srtp_overhead = 0;
Zhi Huange830e682018-03-30 10:48:35 -0700264 if (IsSrtpActive()) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800265 GetSrtpOverhead(&srtp_overhead);
266 }
267 network_route->packet_overhead += srtp_overhead;
268 }
269 SignalNetworkRouteChanged(network_route);
270}
271
Zhi Huangcf990f52017-09-22 12:12:30 -0700272bool SrtpTransport::SetRtpParams(int send_cs,
273 const uint8_t* send_key,
274 int send_key_len,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800275 const std::vector<int>& send_extension_ids,
Zhi Huangcf990f52017-09-22 12:12:30 -0700276 int recv_cs,
277 const uint8_t* recv_key,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800278 int recv_key_len,
279 const std::vector<int>& recv_extension_ids) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700280 // If parameters are being set for the first time, we should create new SRTP
281 // sessions and call "SetSend/SetRecv". Otherwise we should call
282 // "UpdateSend"/"UpdateRecv" on the existing sessions, which will internally
283 // call "srtp_update".
284 bool new_sessions = false;
285 if (!send_session_) {
286 RTC_DCHECK(!recv_session_);
287 CreateSrtpSessions();
288 new_sessions = true;
289 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700290 bool ret = new_sessions
Zhi Huangc99b6c72017-11-10 16:44:46 -0800291 ? send_session_->SetSend(send_cs, send_key, send_key_len,
292 send_extension_ids)
293 : send_session_->UpdateSend(send_cs, send_key, send_key_len,
294 send_extension_ids);
Zhi Huangcf990f52017-09-22 12:12:30 -0700295 if (!ret) {
296 ResetParams();
297 return false;
298 }
299
Zhi Huangc99b6c72017-11-10 16:44:46 -0800300 ret = new_sessions ? recv_session_->SetRecv(recv_cs, recv_key, recv_key_len,
301 recv_extension_ids)
302 : recv_session_->UpdateRecv(
303 recv_cs, recv_key, recv_key_len, recv_extension_ids);
Zhi Huangcf990f52017-09-22 12:12:30 -0700304 if (!ret) {
305 ResetParams();
306 return false;
307 }
308
Mirko Bonadei675513b2017-11-09 11:09:25 +0100309 RTC_LOG(LS_INFO) << "SRTP " << (new_sessions ? "activated" : "updated")
Jonas Olsson45cc8902018-02-13 10:37:07 +0100310 << " with negotiated parameters: send cipher_suite "
311 << send_cs << " recv cipher_suite " << recv_cs;
Zhi Huangcf990f52017-09-22 12:12:30 -0700312 return true;
313}
314
315bool SrtpTransport::SetRtcpParams(int send_cs,
316 const uint8_t* send_key,
317 int send_key_len,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800318 const std::vector<int>& send_extension_ids,
Zhi Huangcf990f52017-09-22 12:12:30 -0700319 int recv_cs,
320 const uint8_t* recv_key,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800321 int recv_key_len,
322 const std::vector<int>& recv_extension_ids) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700323 // This can only be called once, but can be safely called after
324 // SetRtpParams
325 if (send_rtcp_session_ || recv_rtcp_session_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100326 RTC_LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700327 return false;
328 }
329
330 send_rtcp_session_.reset(new cricket::SrtpSession());
Zhi Huangc99b6c72017-11-10 16:44:46 -0800331 if (!send_rtcp_session_->SetSend(send_cs, send_key, send_key_len,
332 send_extension_ids)) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700333 return false;
334 }
335
336 recv_rtcp_session_.reset(new cricket::SrtpSession());
Zhi Huangc99b6c72017-11-10 16:44:46 -0800337 if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len,
338 recv_extension_ids)) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700339 return false;
340 }
341
Steve Antondb67ba12018-03-19 17:41:42 -0700342 if (metrics_observer_) {
343 send_rtcp_session_->SetMetricsObserver(metrics_observer_);
344 recv_rtcp_session_->SetMetricsObserver(metrics_observer_);
345 }
346
Mirko Bonadei675513b2017-11-09 11:09:25 +0100347 RTC_LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
Jonas Olsson45cc8902018-02-13 10:37:07 +0100348 " send cipher_suite "
349 << send_cs << " recv cipher_suite " << recv_cs;
Zhi Huangcf990f52017-09-22 12:12:30 -0700350
351 return true;
352}
353
Zhi Huange830e682018-03-30 10:48:35 -0700354bool SrtpTransport::IsSrtpActive() const {
Zhi Huangcf990f52017-09-22 12:12:30 -0700355 return send_session_ && recv_session_;
356}
357
358void SrtpTransport::ResetParams() {
359 send_session_ = nullptr;
360 recv_session_ = nullptr;
361 send_rtcp_session_ = nullptr;
362 recv_rtcp_session_ = nullptr;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100363 RTC_LOG(LS_INFO) << "The params in SRTP transport are reset.";
Zhi Huangcf990f52017-09-22 12:12:30 -0700364}
365
Zhi Huangcf990f52017-09-22 12:12:30 -0700366void SrtpTransport::CreateSrtpSessions() {
367 send_session_.reset(new cricket::SrtpSession());
368 recv_session_.reset(new cricket::SrtpSession());
Steve Antondb67ba12018-03-19 17:41:42 -0700369 if (metrics_observer_) {
370 send_session_->SetMetricsObserver(metrics_observer_);
371 recv_session_->SetMetricsObserver(metrics_observer_);
372 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700373
374 if (external_auth_enabled_) {
375 send_session_->EnableExternalAuth();
376 }
377}
378
379bool SrtpTransport::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700380 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100381 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700382 return false;
383 }
384 RTC_CHECK(send_session_);
385 return send_session_->ProtectRtp(p, in_len, max_len, out_len);
386}
387
388bool SrtpTransport::ProtectRtp(void* p,
389 int in_len,
390 int max_len,
391 int* out_len,
392 int64_t* index) {
Zhi Huange830e682018-03-30 10:48:35 -0700393 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100394 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700395 return false;
396 }
397 RTC_CHECK(send_session_);
398 return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
399}
400
401bool SrtpTransport::ProtectRtcp(void* p,
402 int in_len,
403 int max_len,
404 int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700405 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100406 RTC_LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700407 return false;
408 }
409 if (send_rtcp_session_) {
410 return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
411 } else {
412 RTC_CHECK(send_session_);
413 return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
414 }
415}
416
417bool SrtpTransport::UnprotectRtp(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 UnprotectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700420 return false;
421 }
422 RTC_CHECK(recv_session_);
423 return recv_session_->UnprotectRtp(p, in_len, out_len);
424}
425
426bool SrtpTransport::UnprotectRtcp(void* p, int in_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700427 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100428 RTC_LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700429 return false;
430 }
431 if (recv_rtcp_session_) {
432 return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
433 } else {
434 RTC_CHECK(recv_session_);
435 return recv_session_->UnprotectRtcp(p, in_len, out_len);
436 }
437}
438
439bool SrtpTransport::GetRtpAuthParams(uint8_t** key,
440 int* key_len,
441 int* tag_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700442 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100443 RTC_LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700444 return false;
445 }
446
447 RTC_CHECK(send_session_);
448 return send_session_->GetRtpAuthParams(key, key_len, tag_len);
449}
450
451bool SrtpTransport::GetSrtpOverhead(int* srtp_overhead) const {
Zhi Huange830e682018-03-30 10:48:35 -0700452 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100453 RTC_LOG(LS_WARNING) << "Failed to GetSrtpOverhead: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700454 return false;
455 }
456
457 RTC_CHECK(send_session_);
458 *srtp_overhead = send_session_->GetSrtpOverhead();
459 return true;
460}
461
462void SrtpTransport::EnableExternalAuth() {
Zhi Huange830e682018-03-30 10:48:35 -0700463 RTC_DCHECK(!IsSrtpActive());
Zhi Huangcf990f52017-09-22 12:12:30 -0700464 external_auth_enabled_ = true;
465}
466
467bool SrtpTransport::IsExternalAuthEnabled() const {
468 return external_auth_enabled_;
469}
470
471bool SrtpTransport::IsExternalAuthActive() const {
Zhi Huange830e682018-03-30 10:48:35 -0700472 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100473 RTC_LOG(LS_WARNING)
474 << "Failed to check IsExternalAuthActive: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700475 return false;
476 }
477
478 RTC_CHECK(send_session_);
479 return send_session_->IsExternalAuthActive();
480}
481
Zhi Huange830e682018-03-30 10:48:35 -0700482bool SrtpTransport::MaybeSetKeyParams() {
483 if (!send_cipher_suite_ || !recv_cipher_suite_) {
484 return true;
485 }
486
487 return SetRtpParams(*send_cipher_suite_, send_key_.data(),
488 static_cast<int>(send_key_.size()), std::vector<int>(),
489 *recv_cipher_suite_, recv_key_.data(),
490 static_cast<int>(recv_key_.size()), std::vector<int>());
491}
492
493bool SrtpTransport::ParseKeyParams(const std::string& key_params,
494 uint8_t* key,
495 size_t len) {
496 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
497
498 // Fail if key-method is wrong.
499 if (key_params.find("inline:") != 0) {
500 return false;
501 }
502
503 // Fail if base64 decode fails, or the key is the wrong size.
504 std::string key_b64(key_params.substr(7)), key_str;
505 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, &key_str,
506 nullptr) ||
507 key_str.size() != len) {
508 return false;
509 }
510
511 memcpy(key, key_str.c_str(), len);
512 // TODO(bugs.webrtc.org/8905): Switch to ZeroOnFreeBuffer for storing
513 // sensitive data.
514 rtc::ExplicitZeroMemory(&key_str[0], key_str.size());
515 return true;
516}
517
Steve Antondb67ba12018-03-19 17:41:42 -0700518void SrtpTransport::SetMetricsObserver(
519 rtc::scoped_refptr<MetricsObserverInterface> metrics_observer) {
520 metrics_observer_ = metrics_observer;
521 if (send_session_) {
522 send_session_->SetMetricsObserver(metrics_observer_);
523 }
524 if (recv_session_) {
525 recv_session_->SetMetricsObserver(metrics_observer_);
526 }
527 if (send_rtcp_session_) {
528 send_rtcp_session_->SetMetricsObserver(metrics_observer_);
529 }
530 if (recv_rtcp_session_) {
531 recv_rtcp_session_->SetMetricsObserver(metrics_observer_);
532 }
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000533 rtp_transport_->SetMetricsObserver(metrics_observer);
Steve Antondb67ba12018-03-19 17:41:42 -0700534}
535
zstein398c3fd2017-07-19 13:38:02 -0700536} // namespace webrtc