blob: 7d1aaf2d6528870af7d2a0ae9d29394e65de3690 [file] [log] [blame]
zstein4dde3df2017-07-07 21:26:251/*
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 17:11:0011#include "pc/srtp_session.h"
zstein4dde3df2017-07-07 21:26:2512
Harald Alvestrandc24a2182022-02-23 13:44:5913#include <string.h>
14
Philipp Hancke397c40e2020-12-04 11:11:2715#include <iomanip>
Harald Alvestrandc24a2182022-02-23 13:44:5916#include <string>
Philipp Hancke397c40e2020-12-04 11:11:2717
Danil Chapovalov5740f3e2019-10-10 09:12:1518#include "absl/base/attributes.h"
Harald Alvestrandc24a2182022-02-23 13:44:5919#include "absl/base/const_init.h"
Ali Tofighfd6a4d62022-03-31 08:36:4820#include "absl/strings/string_view.h"
Danil Chapovalov99a71f42021-07-19 13:20:4621#include "api/array_view.h"
Jonas Orelande62c2f22022-03-29 09:04:4822#include "api/field_trials_view.h"
Danil Chapovalov99a71f42021-07-19 13:20:4623#include "modules/rtp_rtcp/source/rtp_util.h"
Steve Anton10542f22019-01-11 17:11:0024#include "pc/external_hmac.h"
Harald Alvestrandc24a2182022-02-23 13:44:5925#include "rtc_base/byte_order.h"
26#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3127#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 17:11:0028#include "rtc_base/ssl_stream_adapter.h"
Philipp Hancke397c40e2020-12-04 11:11:2729#include "rtc_base/string_encode.h"
Niels Möller2d6c4d02022-04-05 14:14:2130#include "rtc_base/thread_annotations.h"
Philipp Hancke397c40e2020-12-04 11:11:2731#include "rtc_base/time_utils.h"
Zhi Huang0a5fdbb2018-06-14 17:40:1932#include "system_wrappers/include/metrics.h"
Taylor Brandstetterb140b9f2017-10-13 00:24:1633#include "third_party/libsrtp/include/srtp.h"
34#include "third_party/libsrtp/include/srtp_priv.h"
zstein4dde3df2017-07-07 21:26:2535
36namespace cricket {
37
Niels Möller2d6c4d02022-04-05 14:14:2138namespace {
39class LibSrtpInitializer {
40 public:
41 // Returns singleton instance of this class. Instance created on first use,
42 // and never destroyed.
43 static LibSrtpInitializer& Get() {
44 static LibSrtpInitializer* const instance = new LibSrtpInitializer();
45 return *instance;
46 }
47 void ProhibitLibsrtpInitialization();
48
49 // These methods are responsible for initializing libsrtp (if the usage count
50 // is incremented from 0 to 1) or deinitializing it (when decremented from 1
51 // to 0).
52 //
53 // Returns true if successful (will always be successful if already inited).
54 bool IncrementLibsrtpUsageCountAndMaybeInit(
55 srtp_event_handler_func_t* handler);
56 void DecrementLibsrtpUsageCountAndMaybeDeinit();
57
58 private:
59 LibSrtpInitializer() = default;
60
61 webrtc::Mutex mutex_;
62 int usage_count_ RTC_GUARDED_BY(mutex_) = 0;
63};
64
65void LibSrtpInitializer::ProhibitLibsrtpInitialization() {
66 webrtc::MutexLock lock(&mutex_);
67 ++usage_count_;
68}
69
70bool LibSrtpInitializer::IncrementLibsrtpUsageCountAndMaybeInit(
71 srtp_event_handler_func_t* handler) {
72 webrtc::MutexLock lock(&mutex_);
73
74 RTC_DCHECK_GE(usage_count_, 0);
75 if (usage_count_ == 0) {
76 int err;
77 err = srtp_init();
78 if (err != srtp_err_status_ok) {
79 RTC_LOG(LS_ERROR) << "Failed to init SRTP, err=" << err;
80 return false;
81 }
82
83 err = srtp_install_event_handler(handler);
84 if (err != srtp_err_status_ok) {
85 RTC_LOG(LS_ERROR) << "Failed to install SRTP event handler, err=" << err;
86 return false;
87 }
88
89 err = external_crypto_init();
90 if (err != srtp_err_status_ok) {
91 RTC_LOG(LS_ERROR) << "Failed to initialize fake auth, err=" << err;
92 return false;
93 }
94 }
95 ++usage_count_;
96 return true;
97}
98
99void LibSrtpInitializer::DecrementLibsrtpUsageCountAndMaybeDeinit() {
100 webrtc::MutexLock lock(&mutex_);
101
102 RTC_DCHECK_GE(usage_count_, 1);
103 if (--usage_count_ == 0) {
104 int err = srtp_shutdown();
105 if (err) {
106 RTC_LOG(LS_ERROR) << "srtp_shutdown failed. err=" << err;
107 }
108 }
109}
110
111} // namespace
112
Danil Chapovalov99a71f42021-07-19 13:20:46113using ::webrtc::ParseRtpSequenceNumber;
114
Zhi Huang0a5fdbb2018-06-14 17:40:19115// One more than the maximum libsrtp error code. Required by
116// RTC_HISTOGRAM_ENUMERATION. Keep this in sync with srtp_error_status_t defined
117// in srtp.h.
118constexpr int kSrtpErrorCodeBoundary = 28;
119
Jonas Orelanded99dae2022-03-09 08:28:10120SrtpSession::SrtpSession() {}
121
Jonas Orelande62c2f22022-03-29 09:04:48122SrtpSession::SrtpSession(const webrtc::FieldTrialsView& field_trials) {
Jonas Orelanded99dae2022-03-09 08:28:10123 dump_plain_rtp_ = field_trials.IsEnabled("WebRTC-Debugging-RtpDump");
Philipp Hancke397c40e2020-12-04 11:11:27124}
zstein4dde3df2017-07-07 21:26:25125
126SrtpSession::~SrtpSession() {
127 if (session_) {
128 srtp_set_user_data(session_, nullptr);
129 srtp_dealloc(session_);
130 }
Taylor Brandstetterb140b9f2017-10-13 00:24:16131 if (inited_) {
Niels Möller2d6c4d02022-04-05 14:14:21132 LibSrtpInitializer::Get().DecrementLibsrtpUsageCountAndMaybeDeinit();
Taylor Brandstetterb140b9f2017-10-13 00:24:16133 }
zstein4dde3df2017-07-07 21:26:25134}
135
Zhi Huangc99b6c72017-11-11 00:44:46136bool SrtpSession::SetSend(int cs,
137 const uint8_t* key,
138 size_t len,
139 const std::vector<int>& extension_ids) {
140 return SetKey(ssrc_any_outbound, cs, key, len, extension_ids);
zstein4dde3df2017-07-07 21:26:25141}
142
Zhi Huangc99b6c72017-11-11 00:44:46143bool SrtpSession::UpdateSend(int cs,
144 const uint8_t* key,
145 size_t len,
146 const std::vector<int>& extension_ids) {
147 return UpdateKey(ssrc_any_outbound, cs, key, len, extension_ids);
zstein4dde3df2017-07-07 21:26:25148}
149
Zhi Huangc99b6c72017-11-11 00:44:46150bool SrtpSession::SetRecv(int cs,
151 const uint8_t* key,
152 size_t len,
153 const std::vector<int>& extension_ids) {
154 return SetKey(ssrc_any_inbound, cs, key, len, extension_ids);
zstein4dde3df2017-07-07 21:26:25155}
156
Zhi Huangc99b6c72017-11-11 00:44:46157bool SrtpSession::UpdateRecv(int cs,
158 const uint8_t* key,
159 size_t len,
160 const std::vector<int>& extension_ids) {
161 return UpdateKey(ssrc_any_inbound, cs, key, len, extension_ids);
zstein4dde3df2017-07-07 21:26:25162}
163
164bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
Sebastian Janssonc01367d2019-04-08 13:20:44165 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25166 if (!session_) {
Mirko Bonadei675513b2017-11-09 10:09:25167 RTC_LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session";
zstein4dde3df2017-07-07 21:26:25168 return false;
169 }
170
Philipp Hanckebe66d952021-03-01 13:56:22171 // Note: the need_len differs from the libsrtp recommendatіon to ensure
172 // SRTP_MAX_TRAILER_LEN bytes of free space after the data. WebRTC
173 // never includes a MKI, therefore the amount of bytes added by the
174 // srtp_protect call is known in advance and depends on the cipher suite.
zstein4dde3df2017-07-07 21:26:25175 int need_len = in_len + rtp_auth_tag_len_; // NOLINT
176 if (max_len < need_len) {
Mirko Bonadei675513b2017-11-09 10:09:25177 RTC_LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length "
178 << max_len << " is less than the needed " << need_len;
zstein4dde3df2017-07-07 21:26:25179 return false;
180 }
Philipp Hancke397c40e2020-12-04 11:11:27181 if (dump_plain_rtp_) {
182 DumpPacket(p, in_len, /*outbound=*/true);
183 }
zstein4dde3df2017-07-07 21:26:25184
185 *out_len = in_len;
186 int err = srtp_protect(session_, p, out_len);
Danil Chapovalov99a71f42021-07-19 13:20:46187 int seq_num = ParseRtpSequenceNumber(
188 rtc::MakeArrayView(reinterpret_cast<const uint8_t*>(p), in_len));
zstein4dde3df2017-07-07 21:26:25189 if (err != srtp_err_status_ok) {
Mirko Bonadei675513b2017-11-09 10:09:25190 RTC_LOG(LS_WARNING) << "Failed to protect SRTP packet, seqnum=" << seq_num
191 << ", err=" << err
192 << ", last seqnum=" << last_send_seq_num_;
zstein4dde3df2017-07-07 21:26:25193 return false;
194 }
195 last_send_seq_num_ = seq_num;
196 return true;
197}
198
199bool SrtpSession::ProtectRtp(void* p,
200 int in_len,
201 int max_len,
202 int* out_len,
203 int64_t* index) {
204 if (!ProtectRtp(p, in_len, max_len, out_len)) {
205 return false;
206 }
207 return (index) ? GetSendStreamPacketIndex(p, in_len, index) : true;
208}
209
210bool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
Sebastian Janssonc01367d2019-04-08 13:20:44211 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25212 if (!session_) {
Mirko Bonadei675513b2017-11-09 10:09:25213 RTC_LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session";
zstein4dde3df2017-07-07 21:26:25214 return false;
215 }
216
Philipp Hanckebe66d952021-03-01 13:56:22217 // Note: the need_len differs from the libsrtp recommendatіon to ensure
218 // SRTP_MAX_TRAILER_LEN bytes of free space after the data. WebRTC
219 // never includes a MKI, therefore the amount of bytes added by the
220 // srtp_protect_rtp call is known in advance and depends on the cipher suite.
zstein4dde3df2017-07-07 21:26:25221 int need_len = in_len + sizeof(uint32_t) + rtcp_auth_tag_len_; // NOLINT
222 if (max_len < need_len) {
Mirko Bonadei675513b2017-11-09 10:09:25223 RTC_LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length "
224 << max_len << " is less than the needed " << need_len;
zstein4dde3df2017-07-07 21:26:25225 return false;
226 }
Philipp Hancke397c40e2020-12-04 11:11:27227 if (dump_plain_rtp_) {
228 DumpPacket(p, in_len, /*outbound=*/true);
229 }
zstein4dde3df2017-07-07 21:26:25230
231 *out_len = in_len;
232 int err = srtp_protect_rtcp(session_, p, out_len);
233 if (err != srtp_err_status_ok) {
Mirko Bonadei675513b2017-11-09 10:09:25234 RTC_LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err;
zstein4dde3df2017-07-07 21:26:25235 return false;
236 }
237 return true;
238}
239
240bool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) {
Sebastian Janssonc01367d2019-04-08 13:20:44241 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25242 if (!session_) {
Mirko Bonadei675513b2017-11-09 10:09:25243 RTC_LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session";
zstein4dde3df2017-07-07 21:26:25244 return false;
245 }
246
247 *out_len = in_len;
248 int err = srtp_unprotect(session_, p, out_len);
249 if (err != srtp_err_status_ok) {
erikvarga@webrtc.orgd76a0fc2018-10-09 10:31:28250 // Limit the error logging to avoid excessive logs when there are lots of
251 // bad packets.
252 const int kFailureLogThrottleCount = 100;
253 if (decryption_failure_count_ % kFailureLogThrottleCount == 0) {
254 RTC_LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err
255 << ", previous failure count: "
256 << decryption_failure_count_;
257 }
258 ++decryption_failure_count_;
Qingsi Wang7fc821d2018-07-12 19:54:53259 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.SrtpUnprotectError",
Zhi Huang0a5fdbb2018-06-14 17:40:19260 static_cast<int>(err), kSrtpErrorCodeBoundary);
zstein4dde3df2017-07-07 21:26:25261 return false;
262 }
Philipp Hancke397c40e2020-12-04 11:11:27263 if (dump_plain_rtp_) {
264 DumpPacket(p, *out_len, /*outbound=*/false);
265 }
zstein4dde3df2017-07-07 21:26:25266 return true;
267}
268
269bool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) {
Sebastian Janssonc01367d2019-04-08 13:20:44270 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25271 if (!session_) {
Mirko Bonadei675513b2017-11-09 10:09:25272 RTC_LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session";
zstein4dde3df2017-07-07 21:26:25273 return false;
274 }
275
276 *out_len = in_len;
277 int err = srtp_unprotect_rtcp(session_, p, out_len);
278 if (err != srtp_err_status_ok) {
Mirko Bonadei675513b2017-11-09 10:09:25279 RTC_LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err;
Qingsi Wang7fc821d2018-07-12 19:54:53280 RTC_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.SrtcpUnprotectError",
Zhi Huang0a5fdbb2018-06-14 17:40:19281 static_cast<int>(err), kSrtpErrorCodeBoundary);
zstein4dde3df2017-07-07 21:26:25282 return false;
283 }
Philipp Hancke397c40e2020-12-04 11:11:27284 if (dump_plain_rtp_) {
285 DumpPacket(p, *out_len, /*outbound=*/false);
286 }
zstein4dde3df2017-07-07 21:26:25287 return true;
288}
289
290bool SrtpSession::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) {
Sebastian Janssonc01367d2019-04-08 13:20:44291 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25292 RTC_DCHECK(IsExternalAuthActive());
293 if (!IsExternalAuthActive()) {
294 return false;
295 }
296
297 ExternalHmacContext* external_hmac = nullptr;
298 // stream_template will be the reference context for other streams.
299 // Let's use it for getting the keys.
300 srtp_stream_ctx_t* srtp_context = session_->stream_template;
zstein4dde3df2017-07-07 21:26:25301 if (srtp_context && srtp_context->session_keys &&
302 srtp_context->session_keys->rtp_auth) {
303 external_hmac = reinterpret_cast<ExternalHmacContext*>(
304 srtp_context->session_keys->rtp_auth->state);
305 }
zstein4dde3df2017-07-07 21:26:25306
307 if (!external_hmac) {
Mirko Bonadei675513b2017-11-09 10:09:25308 RTC_LOG(LS_ERROR) << "Failed to get auth keys from libsrtp!.";
zstein4dde3df2017-07-07 21:26:25309 return false;
310 }
311
312 *key = external_hmac->key;
313 *key_len = external_hmac->key_length;
314 *tag_len = rtp_auth_tag_len_;
315 return true;
316}
317
318int SrtpSession::GetSrtpOverhead() const {
319 return rtp_auth_tag_len_;
320}
321
322void SrtpSession::EnableExternalAuth() {
323 RTC_DCHECK(!session_);
324 external_auth_enabled_ = true;
325}
326
327bool SrtpSession::IsExternalAuthEnabled() const {
328 return external_auth_enabled_;
329}
330
331bool SrtpSession::IsExternalAuthActive() const {
332 return external_auth_active_;
333}
334
335bool SrtpSession::GetSendStreamPacketIndex(void* p,
336 int in_len,
337 int64_t* index) {
Sebastian Janssonc01367d2019-04-08 13:20:44338 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25339 srtp_hdr_t* hdr = reinterpret_cast<srtp_hdr_t*>(p);
340 srtp_stream_ctx_t* stream = srtp_get_stream(session_, hdr->ssrc);
341 if (!stream) {
342 return false;
343 }
344
345 // Shift packet index, put into network byte order
346 *index = static_cast<int64_t>(rtc::NetworkToHost64(
347 srtp_rdbx_get_packet_index(&stream->rtp_rdbx) << 16));
348 return true;
349}
350
Zhi Huangc99b6c72017-11-11 00:44:46351bool SrtpSession::DoSetKey(int type,
352 int cs,
353 const uint8_t* key,
354 size_t len,
355 const std::vector<int>& extension_ids) {
Sebastian Janssonc01367d2019-04-08 13:20:44356 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25357
358 srtp_policy_t policy;
359 memset(&policy, 0, sizeof(policy));
Philipp Hanckea113d232021-02-22 14:01:42360 if (!(srtp_crypto_policy_set_from_profile_for_rtp(
361 &policy.rtp, (srtp_profile_t)cs) == srtp_err_status_ok &&
362 srtp_crypto_policy_set_from_profile_for_rtcp(
363 &policy.rtcp, (srtp_profile_t)cs) == srtp_err_status_ok)) {
364 RTC_LOG(LS_ERROR) << "Failed to " << (session_ ? "update" : "create")
365 << " SRTP session: unsupported cipher_suite " << cs;
zstein4dde3df2017-07-07 21:26:25366 return false;
367 }
368
Philipp Hancke10032192021-04-08 14:02:40369 if (!key || len != static_cast<size_t>(policy.rtp.cipher_key_len)) {
370 RTC_LOG(LS_ERROR) << "Failed to " << (session_ ? "update" : "create")
371 << " SRTP session: invalid key";
zstein4dde3df2017-07-07 21:26:25372 return false;
373 }
374
375 policy.ssrc.type = static_cast<srtp_ssrc_type_t>(type);
376 policy.ssrc.value = 0;
377 policy.key = const_cast<uint8_t*>(key);
378 // TODO(astor) parse window size from WSH session-param
379 policy.window_size = 1024;
380 policy.allow_repeat_tx = 1;
381 // If external authentication option is enabled, supply custom auth module
382 // id EXTERNAL_HMAC_SHA1 in the policy structure.
383 // We want to set this option only for rtp packets.
384 // By default policy structure is initialized to HMAC_SHA1.
385 // Enable external HMAC authentication only for outgoing streams and only
386 // for cipher suites that support it (i.e. only non-GCM cipher suites).
387 if (type == ssrc_any_outbound && IsExternalAuthEnabled() &&
388 !rtc::IsGcmCryptoSuite(cs)) {
389 policy.rtp.auth_type = EXTERNAL_HMAC_SHA1;
390 }
Zhi Huangc99b6c72017-11-11 00:44:46391 if (!extension_ids.empty()) {
392 policy.enc_xtn_hdr = const_cast<int*>(&extension_ids[0]);
393 policy.enc_xtn_hdr_count = static_cast<int>(extension_ids.size());
zstein4dde3df2017-07-07 21:26:25394 }
395 policy.next = nullptr;
396
397 if (!session_) {
398 int err = srtp_create(&session_, &policy);
399 if (err != srtp_err_status_ok) {
400 session_ = nullptr;
Mirko Bonadei675513b2017-11-09 10:09:25401 RTC_LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err;
zstein4dde3df2017-07-07 21:26:25402 return false;
403 }
404 srtp_set_user_data(session_, this);
405 } else {
406 int err = srtp_update(session_, &policy);
407 if (err != srtp_err_status_ok) {
Mirko Bonadei675513b2017-11-09 10:09:25408 RTC_LOG(LS_ERROR) << "Failed to update SRTP session, err=" << err;
zstein4dde3df2017-07-07 21:26:25409 return false;
410 }
411 }
412
413 rtp_auth_tag_len_ = policy.rtp.auth_tag_len;
414 rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len;
415 external_auth_active_ = (policy.rtp.auth_type == EXTERNAL_HMAC_SHA1);
416 return true;
417}
418
Zhi Huangc99b6c72017-11-11 00:44:46419bool SrtpSession::SetKey(int type,
420 int cs,
421 const uint8_t* key,
422 size_t len,
423 const std::vector<int>& extension_ids) {
Sebastian Janssonc01367d2019-04-08 13:20:44424 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25425 if (session_) {
Mirko Bonadei675513b2017-11-09 10:09:25426 RTC_LOG(LS_ERROR) << "Failed to create SRTP session: "
Jonas Olsson45cc8902018-02-13 09:37:07427 "SRTP session already created";
zstein4dde3df2017-07-07 21:26:25428 return false;
429 }
430
Taylor Brandstetterb140b9f2017-10-13 00:24:16431 // This is the first time we need to actually interact with libsrtp, so
432 // initialize it if needed.
Niels Möller2d6c4d02022-04-05 14:14:21433 if (LibSrtpInitializer::Get().IncrementLibsrtpUsageCountAndMaybeInit(
434 &SrtpSession::HandleEventThunk)) {
Taylor Brandstetterb140b9f2017-10-13 00:24:16435 inited_ = true;
436 } else {
zstein4dde3df2017-07-07 21:26:25437 return false;
438 }
439
Zhi Huangc99b6c72017-11-11 00:44:46440 return DoSetKey(type, cs, key, len, extension_ids);
zstein4dde3df2017-07-07 21:26:25441}
442
Zhi Huangc99b6c72017-11-11 00:44:46443bool SrtpSession::UpdateKey(int type,
444 int cs,
445 const uint8_t* key,
446 size_t len,
447 const std::vector<int>& extension_ids) {
Sebastian Janssonc01367d2019-04-08 13:20:44448 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25449 if (!session_) {
Mirko Bonadei675513b2017-11-09 10:09:25450 RTC_LOG(LS_ERROR) << "Failed to update non-existing SRTP session";
zstein4dde3df2017-07-07 21:26:25451 return false;
452 }
453
Zhi Huangc99b6c72017-11-11 00:44:46454 return DoSetKey(type, cs, key, len, extension_ids);
zstein4dde3df2017-07-07 21:26:25455}
456
Sebastian Jansson22619b32019-12-12 12:15:54457void ProhibitLibsrtpInitialization() {
Niels Möller2d6c4d02022-04-05 14:14:21458 LibSrtpInitializer::Get().ProhibitLibsrtpInitialization();
zstein4dde3df2017-07-07 21:26:25459}
460
461void SrtpSession::HandleEvent(const srtp_event_data_t* ev) {
Sebastian Janssonc01367d2019-04-08 13:20:44462 RTC_DCHECK(thread_checker_.IsCurrent());
zstein4dde3df2017-07-07 21:26:25463 switch (ev->event) {
464 case event_ssrc_collision:
Mirko Bonadei675513b2017-11-09 10:09:25465 RTC_LOG(LS_INFO) << "SRTP event: SSRC collision";
zstein4dde3df2017-07-07 21:26:25466 break;
467 case event_key_soft_limit:
Mirko Bonadei675513b2017-11-09 10:09:25468 RTC_LOG(LS_INFO) << "SRTP event: reached soft key usage limit";
zstein4dde3df2017-07-07 21:26:25469 break;
470 case event_key_hard_limit:
Mirko Bonadei675513b2017-11-09 10:09:25471 RTC_LOG(LS_INFO) << "SRTP event: reached hard key usage limit";
zstein4dde3df2017-07-07 21:26:25472 break;
473 case event_packet_index_limit:
Mirko Bonadei675513b2017-11-09 10:09:25474 RTC_LOG(LS_INFO)
475 << "SRTP event: reached hard packet limit (2^48 packets)";
zstein4dde3df2017-07-07 21:26:25476 break;
477 default:
Mirko Bonadei675513b2017-11-09 10:09:25478 RTC_LOG(LS_INFO) << "SRTP event: unknown " << ev->event;
zstein4dde3df2017-07-07 21:26:25479 break;
480 }
481}
482
483void SrtpSession::HandleEventThunk(srtp_event_data_t* ev) {
484 // Callback will be executed from same thread that calls the "srtp_protect"
485 // and "srtp_unprotect" functions.
486 SrtpSession* session =
487 static_cast<SrtpSession*>(srtp_get_user_data(ev->session));
488 if (session) {
489 session->HandleEvent(ev);
490 }
491}
492
Philipp Hancke397c40e2020-12-04 11:11:27493// Logs the unencrypted packet in text2pcap format. This can then be
494// extracted by searching for RTP_DUMP
495// grep RTP_DUMP chrome_debug.log > in.txt
496// and converted to pcap using
497// text2pcap -D -u 1000,2000 -t %H:%M:%S. in.txt out.pcap
498// The resulting file can be replayed using the WebRTC video_replay tool and
499// be inspected in Wireshark using the RTP, VP8 and H264 dissectors.
500void SrtpSession::DumpPacket(const void* buf, int len, bool outbound) {
501 int64_t time_of_day = rtc::TimeUTCMillis() % (24 * 3600 * 1000);
502 int64_t hours = time_of_day / (3600 * 1000);
503 int64_t minutes = (time_of_day / (60 * 1000)) % 60;
504 int64_t seconds = (time_of_day / 1000) % 60;
505 int64_t millis = time_of_day % 1000;
Ali Tofighfd6a4d62022-03-31 08:36:48506 RTC_LOG(LS_VERBOSE) << "\n"
507 << (outbound ? "O" : "I") << " " << std::setfill('0')
508 << std::setw(2) << hours << ":" << std::setfill('0')
509 << std::setw(2) << minutes << ":" << std::setfill('0')
510 << std::setw(2) << seconds << "." << std::setfill('0')
511 << std::setw(3) << millis << " "
512 << "000000 "
513 << rtc::hex_encode_with_delimiter(
514 absl::string_view((const char*)buf, len), ' ')
515 << " # RTP_DUMP";
Philipp Hancke397c40e2020-12-04 11:11:27516}
517
zstein4dde3df2017-07-07 21:26:25518} // namespace cricket