blob: 6306d5006b4caac2546b265871b33bc27a2c3645 [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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/srtp_transport.h"
zstein398c3fd2017-07-19 13:38:02 -070012
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <stdint.h>
14#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020015
zstein398c3fd2017-07-19 13:38:02 -070016#include <string>
Amit Hilbuchedd20542019-03-18 12:33:43 -070017#include <utility>
Steve Anton36b29d12017-10-30 09:57:42 -070018#include <vector>
zstein398c3fd2017-07-19 13:38:02 -070019
Steve Anton10542f22019-01-11 09:11:00 -080020#include "media/base/rtp_utils.h"
21#include "pc/rtp_transport.h"
22#include "pc/srtp_session.h"
23#include "rtc_base/async_packet_socket.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080025#include "rtc_base/copy_on_write_buffer.h"
Yves Gerey3e707812018-11-28 16:47:49 +010026#include "rtc_base/logging.h"
Zhi Huang365381f2018-04-13 16:44:34 -070027#include "rtc_base/numerics/safe_conversions.h"
Steve Anton10542f22019-01-11 09:11:00 -080028#include "rtc_base/ssl_stream_adapter.h"
Artem Titova76af0c2018-07-23 17:38:12 +020029#include "rtc_base/third_party/base64/base64.h"
Yves Gerey3e707812018-11-28 16:47:49 +010030#include "rtc_base/third_party/sigslot/sigslot.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020031#include "rtc_base/trace_event.h"
Zhi Huange830e682018-03-30 10:48:35 -070032#include "rtc_base/zero_memory.h"
zstein398c3fd2017-07-19 13:38:02 -070033
34namespace webrtc {
35
Zhi Huang2dfc42d2017-12-04 13:38:48 -080036SrtpTransport::SrtpTransport(bool rtcp_mux_enabled)
Zhi Huang365381f2018-04-13 16:44:34 -070037 : RtpTransport(rtcp_mux_enabled) {}
zstein398c3fd2017-07-19 13:38:02 -070038
Zhi Huange830e682018-03-30 10:48:35 -070039RTCError SrtpTransport::SetSrtpSendKey(const cricket::CryptoParams& params) {
40 if (send_params_) {
41 LOG_AND_RETURN_ERROR(
42 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
43 "Setting the SRTP send key twice is currently unsupported.");
44 }
45 if (recv_params_ && recv_params_->cipher_suite != params.cipher_suite) {
46 LOG_AND_RETURN_ERROR(
47 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
48 "The send key and receive key must have the same cipher suite.");
49 }
50
51 send_cipher_suite_ = rtc::SrtpCryptoSuiteFromName(params.cipher_suite);
52 if (*send_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) {
53 return RTCError(RTCErrorType::INVALID_PARAMETER,
54 "Invalid SRTP crypto suite");
55 }
56
57 int send_key_len, send_salt_len;
58 if (!rtc::GetSrtpKeyAndSaltLengths(*send_cipher_suite_, &send_key_len,
59 &send_salt_len)) {
60 return RTCError(RTCErrorType::INVALID_PARAMETER,
61 "Could not get lengths for crypto suite(s):"
62 " send cipher_suite ");
63 }
64
65 send_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(send_key_len + send_salt_len);
66 if (!ParseKeyParams(params.key_params, send_key_.data(), send_key_.size())) {
67 return RTCError(RTCErrorType::INVALID_PARAMETER,
68 "Failed to parse the crypto key params");
69 }
70
71 if (!MaybeSetKeyParams()) {
72 return RTCError(RTCErrorType::INVALID_PARAMETER,
73 "Failed to set the crypto key params");
74 }
75 send_params_ = params;
76 return RTCError::OK();
77}
78
79RTCError SrtpTransport::SetSrtpReceiveKey(const cricket::CryptoParams& params) {
80 if (recv_params_) {
81 LOG_AND_RETURN_ERROR(
82 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
83 "Setting the SRTP send key twice is currently unsupported.");
84 }
85 if (send_params_ && send_params_->cipher_suite != params.cipher_suite) {
86 LOG_AND_RETURN_ERROR(
87 webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
88 "The send key and receive key must have the same cipher suite.");
89 }
90
91 recv_cipher_suite_ = rtc::SrtpCryptoSuiteFromName(params.cipher_suite);
92 if (*recv_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) {
93 return RTCError(RTCErrorType::INVALID_PARAMETER,
94 "Invalid SRTP crypto suite");
95 }
96
97 int recv_key_len, recv_salt_len;
98 if (!rtc::GetSrtpKeyAndSaltLengths(*recv_cipher_suite_, &recv_key_len,
99 &recv_salt_len)) {
100 return RTCError(RTCErrorType::INVALID_PARAMETER,
101 "Could not get lengths for crypto suite(s):"
102 " recv cipher_suite ");
103 }
104
105 recv_key_ = rtc::ZeroOnFreeBuffer<uint8_t>(recv_key_len + recv_salt_len);
106 if (!ParseKeyParams(params.key_params, recv_key_.data(), recv_key_.size())) {
107 return RTCError(RTCErrorType::INVALID_PARAMETER,
108 "Failed to parse the crypto key params");
109 }
110
111 if (!MaybeSetKeyParams()) {
112 return RTCError(RTCErrorType::INVALID_PARAMETER,
113 "Failed to set the crypto key params");
114 }
115 recv_params_ = params;
116 return RTCError::OK();
117}
118
Zhi Huangcf990f52017-09-22 12:12:30 -0700119bool SrtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet,
120 const rtc::PacketOptions& options,
121 int flags) {
Zhi Huange830e682018-03-30 10:48:35 -0700122 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100123 RTC_LOG(LS_ERROR)
Zhi Huangcf990f52017-09-22 12:12:30 -0700124 << "Failed to send the packet because SRTP transport is inactive.";
125 return false;
126 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700127 rtc::PacketOptions updated_options = options;
Zhi Huangcf990f52017-09-22 12:12:30 -0700128 TRACE_EVENT0("webrtc", "SRTP Encode");
129 bool res;
130 uint8_t* data = packet->data();
Zhi Huang365381f2018-04-13 16:44:34 -0700131 int len = rtc::checked_cast<int>(packet->size());
Zhi Huangcf990f52017-09-22 12:12:30 -0700132// If ENABLE_EXTERNAL_AUTH flag is on then packet authentication is not done
133// inside libsrtp for a RTP packet. A external HMAC module will be writing
134// a fake HMAC value. This is ONLY done for a RTP packet.
135// Socket layer will update rtp sendtime extension header if present in
136// packet with current time before updating the HMAC.
137#if !defined(ENABLE_EXTERNAL_AUTH)
Zhi Huang365381f2018-04-13 16:44:34 -0700138 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
Zhi Huang95e7dbb2018-03-29 00:08:03 +0000139#else
Zhi Huang365381f2018-04-13 16:44:34 -0700140 if (!IsExternalAuthActive()) {
141 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len);
142 } else {
143 updated_options.packet_time_params.rtp_sendtime_extension_id =
144 rtp_abs_sendtime_extn_id_;
145 res = ProtectRtp(data, len, static_cast<int>(packet->capacity()), &len,
146 &updated_options.packet_time_params.srtp_packet_index);
147 // If protection succeeds, let's get auth params from srtp.
148 if (res) {
149 uint8_t* auth_key = nullptr;
150 int key_len = 0;
151 res = GetRtpAuthParams(
152 &auth_key, &key_len,
153 &updated_options.packet_time_params.srtp_auth_tag_len);
Zhi Huangcf990f52017-09-22 12:12:30 -0700154 if (res) {
Zhi Huang365381f2018-04-13 16:44:34 -0700155 updated_options.packet_time_params.srtp_auth_key.resize(key_len);
156 updated_options.packet_time_params.srtp_auth_key.assign(
157 auth_key, auth_key + key_len);
Zhi Huangcf990f52017-09-22 12:12:30 -0700158 }
159 }
Zhi Huang365381f2018-04-13 16:44:34 -0700160 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700161#endif
Zhi Huang365381f2018-04-13 16:44:34 -0700162 if (!res) {
163 int seq_num = -1;
164 uint32_t ssrc = 0;
165 cricket::GetRtpSeqNum(data, len, &seq_num);
166 cricket::GetRtpSsrc(data, len, &ssrc);
167 RTC_LOG(LS_ERROR) << "Failed to protect RTP packet: size=" << len
168 << ", seqnum=" << seq_num << ", SSRC=" << ssrc;
169 return false;
Zhi Huangcf990f52017-09-22 12:12:30 -0700170 }
171
172 // Update the length of the packet now that we've added the auth tag.
173 packet->SetSize(len);
Zhi Huang365381f2018-04-13 16:44:34 -0700174 return SendPacket(/*rtcp=*/false, packet, updated_options, flags);
zstein398c3fd2017-07-19 13:38:02 -0700175}
176
Zhi Huang365381f2018-04-13 16:44:34 -0700177bool SrtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet,
178 const rtc::PacketOptions& options,
179 int flags) {
180 if (!IsSrtpActive()) {
181 RTC_LOG(LS_ERROR)
182 << "Failed to send the packet because SRTP transport is inactive.";
183 return false;
184 }
185
186 TRACE_EVENT0("webrtc", "SRTP Encode");
187 uint8_t* data = packet->data();
188 int len = rtc::checked_cast<int>(packet->size());
189 if (!ProtectRtcp(data, len, static_cast<int>(packet->capacity()), &len)) {
190 int type = -1;
191 cricket::GetRtcpType(data, len, &type);
192 RTC_LOG(LS_ERROR) << "Failed to protect RTCP packet: size=" << len
193 << ", type=" << type;
194 return false;
195 }
196 // Update the length of the packet now that we've added the auth tag.
197 packet->SetSize(len);
198
199 return SendPacket(/*rtcp=*/true, packet, options, flags);
200}
201
Amit Hilbuchedd20542019-03-18 12:33:43 -0700202void SrtpTransport::OnRtpPacketReceived(rtc::CopyOnWriteBuffer packet,
Niels Möllere6933812018-11-05 13:01:41 +0100203 int64_t packet_time_us) {
Zhi Huange830e682018-03-30 10:48:35 -0700204 if (!IsSrtpActive()) {
Zhi Huang27f3bf52018-03-26 21:37:23 -0700205 RTC_LOG(LS_WARNING)
Zhi Huang365381f2018-04-13 16:44:34 -0700206 << "Inactive SRTP transport received an RTP packet. Drop it.";
Zhi Huang27f3bf52018-03-26 21:37:23 -0700207 return;
208 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700209 TRACE_EVENT0("webrtc", "SRTP Decode");
Amit Hilbuchedd20542019-03-18 12:33:43 -0700210 char* data = packet.data<char>();
211 int len = rtc::checked_cast<int>(packet.size());
Zhi Huang365381f2018-04-13 16:44:34 -0700212 if (!UnprotectRtp(data, len, &len)) {
213 int seq_num = -1;
214 uint32_t ssrc = 0;
215 cricket::GetRtpSeqNum(data, len, &seq_num);
216 cricket::GetRtpSsrc(data, len, &ssrc);
erikvarga@webrtc.orgd76a0fc2018-10-09 12:31:28 +0200217
218 // Limit the error logging to avoid excessive logs when there are lots of
219 // bad packets.
220 const int kFailureLogThrottleCount = 100;
221 if (decryption_failure_count_ % kFailureLogThrottleCount == 0) {
222 RTC_LOG(LS_ERROR) << "Failed to unprotect RTP packet: size=" << len
223 << ", seqnum=" << seq_num << ", SSRC=" << ssrc
224 << ", previous failure count: "
225 << decryption_failure_count_;
226 }
227 ++decryption_failure_count_;
Zhi Huang365381f2018-04-13 16:44:34 -0700228 return;
Zhi Huangcf990f52017-09-22 12:12:30 -0700229 }
Amit Hilbuchedd20542019-03-18 12:33:43 -0700230 packet.SetSize(len);
231 DemuxPacket(std::move(packet), packet_time_us);
Zhi Huang365381f2018-04-13 16:44:34 -0700232}
233
Amit Hilbuchedd20542019-03-18 12:33:43 -0700234void SrtpTransport::OnRtcpPacketReceived(rtc::CopyOnWriteBuffer packet,
Niels Möllere6933812018-11-05 13:01:41 +0100235 int64_t packet_time_us) {
Zhi Huang365381f2018-04-13 16:44:34 -0700236 if (!IsSrtpActive()) {
237 RTC_LOG(LS_WARNING)
238 << "Inactive SRTP transport received an RTCP packet. Drop it.";
239 return;
240 }
241 TRACE_EVENT0("webrtc", "SRTP Decode");
Amit Hilbuchedd20542019-03-18 12:33:43 -0700242 char* data = packet.data<char>();
243 int len = rtc::checked_cast<int>(packet.size());
Zhi Huang365381f2018-04-13 16:44:34 -0700244 if (!UnprotectRtcp(data, len, &len)) {
245 int type = -1;
246 cricket::GetRtcpType(data, len, &type);
247 RTC_LOG(LS_ERROR) << "Failed to unprotect RTCP packet: size=" << len
248 << ", type=" << type;
249 return;
250 }
Amit Hilbuchedd20542019-03-18 12:33:43 -0700251 packet.SetSize(len);
252 SignalRtcpPacketReceived(&packet, packet_time_us);
zstein398c3fd2017-07-19 13:38:02 -0700253}
254
Zhi Huang942bc2e2017-11-13 13:26:07 -0800255void SrtpTransport::OnNetworkRouteChanged(
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200256 absl::optional<rtc::NetworkRoute> network_route) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800257 // Only append the SRTP overhead when there is a selected network route.
258 if (network_route) {
259 int srtp_overhead = 0;
Zhi Huange830e682018-03-30 10:48:35 -0700260 if (IsSrtpActive()) {
Zhi Huang942bc2e2017-11-13 13:26:07 -0800261 GetSrtpOverhead(&srtp_overhead);
262 }
263 network_route->packet_overhead += srtp_overhead;
264 }
265 SignalNetworkRouteChanged(network_route);
266}
267
Zhi Huang365381f2018-04-13 16:44:34 -0700268void SrtpTransport::OnWritableState(
269 rtc::PacketTransportInternal* packet_transport) {
270 SignalWritableState(IsWritable(/*rtcp=*/true) && IsWritable(/*rtcp=*/true));
271}
272
Zhi Huangcf990f52017-09-22 12:12:30 -0700273bool SrtpTransport::SetRtpParams(int send_cs,
274 const uint8_t* send_key,
275 int send_key_len,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800276 const std::vector<int>& send_extension_ids,
Zhi Huangcf990f52017-09-22 12:12:30 -0700277 int recv_cs,
278 const uint8_t* recv_key,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800279 int recv_key_len,
280 const std::vector<int>& recv_extension_ids) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700281 // If parameters are being set for the first time, we should create new SRTP
282 // sessions and call "SetSend/SetRecv". Otherwise we should call
283 // "UpdateSend"/"UpdateRecv" on the existing sessions, which will internally
284 // call "srtp_update".
285 bool new_sessions = false;
286 if (!send_session_) {
287 RTC_DCHECK(!recv_session_);
288 CreateSrtpSessions();
289 new_sessions = true;
290 }
Zhi Huangcf990f52017-09-22 12:12:30 -0700291 bool ret = new_sessions
Zhi Huangc99b6c72017-11-10 16:44:46 -0800292 ? send_session_->SetSend(send_cs, send_key, send_key_len,
293 send_extension_ids)
294 : send_session_->UpdateSend(send_cs, send_key, send_key_len,
295 send_extension_ids);
Zhi Huangcf990f52017-09-22 12:12:30 -0700296 if (!ret) {
297 ResetParams();
298 return false;
299 }
300
Zhi Huangc99b6c72017-11-10 16:44:46 -0800301 ret = new_sessions ? recv_session_->SetRecv(recv_cs, recv_key, recv_key_len,
302 recv_extension_ids)
303 : recv_session_->UpdateRecv(
304 recv_cs, recv_key, recv_key_len, recv_extension_ids);
Zhi Huangcf990f52017-09-22 12:12:30 -0700305 if (!ret) {
306 ResetParams();
307 return false;
308 }
309
Mirko Bonadei675513b2017-11-09 11:09:25 +0100310 RTC_LOG(LS_INFO) << "SRTP " << (new_sessions ? "activated" : "updated")
Jonas Olsson45cc8902018-02-13 10:37:07 +0100311 << " with negotiated parameters: send cipher_suite "
312 << send_cs << " recv cipher_suite " << recv_cs;
Zhi Huang365381f2018-04-13 16:44:34 -0700313 MaybeUpdateWritableState();
Zhi Huangcf990f52017-09-22 12:12:30 -0700314 return true;
315}
316
317bool SrtpTransport::SetRtcpParams(int send_cs,
318 const uint8_t* send_key,
319 int send_key_len,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800320 const std::vector<int>& send_extension_ids,
Zhi Huangcf990f52017-09-22 12:12:30 -0700321 int recv_cs,
322 const uint8_t* recv_key,
Zhi Huangc99b6c72017-11-10 16:44:46 -0800323 int recv_key_len,
324 const std::vector<int>& recv_extension_ids) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700325 // This can only be called once, but can be safely called after
326 // SetRtpParams
327 if (send_rtcp_session_ || recv_rtcp_session_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100328 RTC_LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700329 return false;
330 }
331
332 send_rtcp_session_.reset(new cricket::SrtpSession());
Zhi Huangc99b6c72017-11-10 16:44:46 -0800333 if (!send_rtcp_session_->SetSend(send_cs, send_key, send_key_len,
334 send_extension_ids)) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700335 return false;
336 }
337
338 recv_rtcp_session_.reset(new cricket::SrtpSession());
Zhi Huangc99b6c72017-11-10 16:44:46 -0800339 if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len,
340 recv_extension_ids)) {
Zhi Huangcf990f52017-09-22 12:12:30 -0700341 return false;
342 }
343
Mirko Bonadei675513b2017-11-09 11:09:25 +0100344 RTC_LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
Jonas Olsson45cc8902018-02-13 10:37:07 +0100345 " send cipher_suite "
346 << send_cs << " recv cipher_suite " << recv_cs;
Zhi Huang365381f2018-04-13 16:44:34 -0700347 MaybeUpdateWritableState();
Zhi Huangcf990f52017-09-22 12:12:30 -0700348 return true;
349}
350
Zhi Huange830e682018-03-30 10:48:35 -0700351bool SrtpTransport::IsSrtpActive() const {
Zhi Huangcf990f52017-09-22 12:12:30 -0700352 return send_session_ && recv_session_;
353}
354
Zhi Huang365381f2018-04-13 16:44:34 -0700355bool SrtpTransport::IsWritable(bool rtcp) const {
356 return IsSrtpActive() && RtpTransport::IsWritable(rtcp);
357}
358
Zhi Huangcf990f52017-09-22 12:12:30 -0700359void SrtpTransport::ResetParams() {
360 send_session_ = nullptr;
361 recv_session_ = nullptr;
362 send_rtcp_session_ = nullptr;
363 recv_rtcp_session_ = nullptr;
Zhi Huang365381f2018-04-13 16:44:34 -0700364 MaybeUpdateWritableState();
Mirko Bonadei675513b2017-11-09 11:09:25 +0100365 RTC_LOG(LS_INFO) << "The params in SRTP transport are reset.";
Zhi Huangcf990f52017-09-22 12:12:30 -0700366}
367
Zhi Huangcf990f52017-09-22 12:12:30 -0700368void SrtpTransport::CreateSrtpSessions() {
369 send_session_.reset(new cricket::SrtpSession());
370 recv_session_.reset(new cricket::SrtpSession());
Zhi Huangcf990f52017-09-22 12:12:30 -0700371 if (external_auth_enabled_) {
372 send_session_->EnableExternalAuth();
373 }
374}
375
376bool SrtpTransport::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700377 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100378 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700379 return false;
380 }
381 RTC_CHECK(send_session_);
382 return send_session_->ProtectRtp(p, in_len, max_len, out_len);
383}
384
385bool SrtpTransport::ProtectRtp(void* p,
386 int in_len,
387 int max_len,
388 int* out_len,
389 int64_t* index) {
Zhi Huange830e682018-03-30 10:48:35 -0700390 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100391 RTC_LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700392 return false;
393 }
394 RTC_CHECK(send_session_);
395 return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
396}
397
398bool SrtpTransport::ProtectRtcp(void* p,
399 int in_len,
400 int max_len,
401 int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700402 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100403 RTC_LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700404 return false;
405 }
406 if (send_rtcp_session_) {
407 return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
408 } else {
409 RTC_CHECK(send_session_);
410 return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
411 }
412}
413
414bool SrtpTransport::UnprotectRtp(void* p, int in_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700415 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100416 RTC_LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700417 return false;
418 }
419 RTC_CHECK(recv_session_);
420 return recv_session_->UnprotectRtp(p, in_len, out_len);
421}
422
423bool SrtpTransport::UnprotectRtcp(void* p, int in_len, int* out_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700424 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100425 RTC_LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700426 return false;
427 }
428 if (recv_rtcp_session_) {
429 return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
430 } else {
431 RTC_CHECK(recv_session_);
432 return recv_session_->UnprotectRtcp(p, in_len, out_len);
433 }
434}
435
436bool SrtpTransport::GetRtpAuthParams(uint8_t** key,
437 int* key_len,
438 int* tag_len) {
Zhi Huange830e682018-03-30 10:48:35 -0700439 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100440 RTC_LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700441 return false;
442 }
443
444 RTC_CHECK(send_session_);
445 return send_session_->GetRtpAuthParams(key, key_len, tag_len);
446}
447
448bool SrtpTransport::GetSrtpOverhead(int* srtp_overhead) const {
Zhi Huange830e682018-03-30 10:48:35 -0700449 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100450 RTC_LOG(LS_WARNING) << "Failed to GetSrtpOverhead: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700451 return false;
452 }
453
454 RTC_CHECK(send_session_);
455 *srtp_overhead = send_session_->GetSrtpOverhead();
456 return true;
457}
458
459void SrtpTransport::EnableExternalAuth() {
Zhi Huange830e682018-03-30 10:48:35 -0700460 RTC_DCHECK(!IsSrtpActive());
Zhi Huangcf990f52017-09-22 12:12:30 -0700461 external_auth_enabled_ = true;
462}
463
464bool SrtpTransport::IsExternalAuthEnabled() const {
465 return external_auth_enabled_;
466}
467
468bool SrtpTransport::IsExternalAuthActive() const {
Zhi Huange830e682018-03-30 10:48:35 -0700469 if (!IsSrtpActive()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100470 RTC_LOG(LS_WARNING)
471 << "Failed to check IsExternalAuthActive: SRTP not active";
Zhi Huangcf990f52017-09-22 12:12:30 -0700472 return false;
473 }
474
475 RTC_CHECK(send_session_);
476 return send_session_->IsExternalAuthActive();
477}
478
Zhi Huange830e682018-03-30 10:48:35 -0700479bool SrtpTransport::MaybeSetKeyParams() {
480 if (!send_cipher_suite_ || !recv_cipher_suite_) {
481 return true;
482 }
483
484 return SetRtpParams(*send_cipher_suite_, send_key_.data(),
485 static_cast<int>(send_key_.size()), std::vector<int>(),
486 *recv_cipher_suite_, recv_key_.data(),
487 static_cast<int>(recv_key_.size()), std::vector<int>());
488}
489
490bool SrtpTransport::ParseKeyParams(const std::string& key_params,
491 uint8_t* key,
492 size_t len) {
493 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
494
495 // Fail if key-method is wrong.
496 if (key_params.find("inline:") != 0) {
497 return false;
498 }
499
500 // Fail if base64 decode fails, or the key is the wrong size.
501 std::string key_b64(key_params.substr(7)), key_str;
502 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, &key_str,
503 nullptr) ||
504 key_str.size() != len) {
505 return false;
506 }
507
508 memcpy(key, key_str.c_str(), len);
509 // TODO(bugs.webrtc.org/8905): Switch to ZeroOnFreeBuffer for storing
510 // sensitive data.
511 rtc::ExplicitZeroMemory(&key_str[0], key_str.size());
512 return true;
513}
514
Zhi Huang365381f2018-04-13 16:44:34 -0700515void SrtpTransport::MaybeUpdateWritableState() {
516 bool writable = IsWritable(/*rtcp=*/true) && IsWritable(/*rtcp=*/false);
517 // Only fire the signal if the writable state changes.
518 if (writable_ != writable) {
519 writable_ = writable;
520 SignalWritableState(writable_);
521 }
Steve Antondb67ba12018-03-19 17:41:42 -0700522}
523
zstein398c3fd2017-07-19 13:38:02 -0700524} // namespace webrtc