Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: talk/session/media/srtpfilter.cc

Issue 1691463002: Move talk/session/media -> webrtc/pc (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Last rebase Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « talk/session/media/srtpfilter.h ('k') | talk/session/media/srtpfilter_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * libjingle
3 * Copyright 2009 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #undef HAVE_CONFIG_H
29
30 #include "talk/session/media/srtpfilter.h"
31
32 #include <string.h>
33
34 #include <algorithm>
35
36 #include "webrtc/base/base64.h"
37 #include "webrtc/base/byteorder.h"
38 #include "webrtc/base/common.h"
39 #include "webrtc/base/logging.h"
40 #include "webrtc/base/stringencode.h"
41 #include "webrtc/base/timeutils.h"
42 #include "webrtc/media/base/rtputils.h"
43
44 // Enable this line to turn on SRTP debugging
45 // #define SRTP_DEBUG
46
47 #ifdef HAVE_SRTP
48 extern "C" {
49 #ifdef SRTP_RELATIVE_PATH
50 #include "srtp.h" // NOLINT
51 #include "srtp_priv.h" // NOLINT
52 #else
53 #include "third_party/libsrtp/srtp/include/srtp.h"
54 #include "third_party/libsrtp/srtp/include/srtp_priv.h"
55 #endif // SRTP_RELATIVE_PATH
56 }
57 #ifdef ENABLE_EXTERNAL_AUTH
58 #include "talk/session/media/externalhmac.h"
59 #endif // ENABLE_EXTERNAL_AUTH
60 #if !defined(NDEBUG)
61 extern "C" debug_module_t mod_srtp;
62 extern "C" debug_module_t mod_auth;
63 extern "C" debug_module_t mod_cipher;
64 extern "C" debug_module_t mod_stat;
65 extern "C" debug_module_t mod_alloc;
66 extern "C" debug_module_t mod_aes_icm;
67 extern "C" debug_module_t mod_aes_hmac;
68 #endif
69 #else
70 // SrtpFilter needs that constant.
71 #define SRTP_MASTER_KEY_LEN 30
72 #endif // HAVE_SRTP
73
74 namespace cricket {
75
76 const int SRTP_MASTER_KEY_BASE64_LEN = SRTP_MASTER_KEY_LEN * 4 / 3;
77 const int SRTP_MASTER_KEY_KEY_LEN = 16;
78 const int SRTP_MASTER_KEY_SALT_LEN = 14;
79
80 #ifndef HAVE_SRTP
81
82 // This helper function is used on systems that don't (yet) have SRTP,
83 // to log that the functions that require it won't do anything.
84 namespace {
85 bool SrtpNotAvailable(const char *func) {
86 LOG(LS_ERROR) << func << ": SRTP is not available on your system.";
87 return false;
88 }
89 } // anonymous namespace
90
91 #endif // !HAVE_SRTP
92
93 void EnableSrtpDebugging() {
94 #ifdef HAVE_SRTP
95 #if !defined(NDEBUG)
96 debug_on(mod_srtp);
97 debug_on(mod_auth);
98 debug_on(mod_cipher);
99 debug_on(mod_stat);
100 debug_on(mod_alloc);
101 debug_on(mod_aes_icm);
102 // debug_on(mod_aes_cbc);
103 // debug_on(mod_hmac);
104 #endif
105 #endif // HAVE_SRTP
106 }
107
108 // NOTE: This is called from ChannelManager D'tor.
109 void ShutdownSrtp() {
110 #ifdef HAVE_SRTP
111 // If srtp_dealloc is not executed then this will clear all existing sessions.
112 // This should be called when application is shutting down.
113 SrtpSession::Terminate();
114 #endif
115 }
116
117 SrtpFilter::SrtpFilter()
118 : state_(ST_INIT),
119 signal_silent_time_in_ms_(0) {
120 }
121
122 SrtpFilter::~SrtpFilter() {
123 }
124
125 bool SrtpFilter::IsActive() const {
126 return state_ >= ST_ACTIVE;
127 }
128
129 bool SrtpFilter::SetOffer(const std::vector<CryptoParams>& offer_params,
130 ContentSource source) {
131 if (!ExpectOffer(source)) {
132 LOG(LS_ERROR) << "Wrong state to update SRTP offer";
133 return false;
134 }
135 return StoreParams(offer_params, source);
136 }
137
138 bool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params,
139 ContentSource source) {
140 return DoSetAnswer(answer_params, source, true);
141 }
142
143 bool SrtpFilter::SetProvisionalAnswer(
144 const std::vector<CryptoParams>& answer_params,
145 ContentSource source) {
146 return DoSetAnswer(answer_params, source, false);
147 }
148
149 bool SrtpFilter::SetRtpParams(int send_cs,
150 const uint8_t* send_key,
151 int send_key_len,
152 int recv_cs,
153 const uint8_t* recv_key,
154 int recv_key_len) {
155 if (IsActive()) {
156 LOG(LS_ERROR) << "Tried to set SRTP Params when filter already active";
157 return false;
158 }
159 CreateSrtpSessions();
160 if (!send_session_->SetSend(send_cs, send_key, send_key_len))
161 return false;
162
163 if (!recv_session_->SetRecv(recv_cs, recv_key, recv_key_len))
164 return false;
165
166 state_ = ST_ACTIVE;
167
168 LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
169 << " send cipher_suite " << send_cs
170 << " recv cipher_suite " << recv_cs;
171 return true;
172 }
173
174 // This function is provided separately because DTLS-SRTP behaves
175 // differently in RTP/RTCP mux and non-mux modes.
176 //
177 // - In the non-muxed case, RTP and RTCP are keyed with different
178 // keys (from different DTLS handshakes), and so we need a new
179 // SrtpSession.
180 // - In the muxed case, they are keyed with the same keys, so
181 // this function is not needed
182 bool SrtpFilter::SetRtcpParams(int send_cs,
183 const uint8_t* send_key,
184 int send_key_len,
185 int recv_cs,
186 const uint8_t* recv_key,
187 int recv_key_len) {
188 // This can only be called once, but can be safely called after
189 // SetRtpParams
190 if (send_rtcp_session_ || recv_rtcp_session_) {
191 LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active";
192 return false;
193 }
194
195 send_rtcp_session_.reset(new SrtpSession());
196 SignalSrtpError.repeat(send_rtcp_session_->SignalSrtpError);
197 send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_);
198 if (!send_rtcp_session_->SetRecv(send_cs, send_key, send_key_len))
199 return false;
200
201 recv_rtcp_session_.reset(new SrtpSession());
202 SignalSrtpError.repeat(recv_rtcp_session_->SignalSrtpError);
203 recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_);
204 if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len))
205 return false;
206
207 LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
208 << " send cipher_suite " << send_cs
209 << " recv cipher_suite " << recv_cs;
210
211 return true;
212 }
213
214 bool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
215 if (!IsActive()) {
216 LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
217 return false;
218 }
219 ASSERT(send_session_ != NULL);
220 return send_session_->ProtectRtp(p, in_len, max_len, out_len);
221 }
222
223 bool SrtpFilter::ProtectRtp(void* p,
224 int in_len,
225 int max_len,
226 int* out_len,
227 int64_t* index) {
228 if (!IsActive()) {
229 LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
230 return false;
231 }
232 ASSERT(send_session_ != NULL);
233 return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
234 }
235
236 bool SrtpFilter::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
237 if (!IsActive()) {
238 LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
239 return false;
240 }
241 if (send_rtcp_session_) {
242 return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
243 } else {
244 ASSERT(send_session_ != NULL);
245 return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
246 }
247 }
248
249 bool SrtpFilter::UnprotectRtp(void* p, int in_len, int* out_len) {
250 if (!IsActive()) {
251 LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
252 return false;
253 }
254 ASSERT(recv_session_ != NULL);
255 return recv_session_->UnprotectRtp(p, in_len, out_len);
256 }
257
258 bool SrtpFilter::UnprotectRtcp(void* p, int in_len, int* out_len) {
259 if (!IsActive()) {
260 LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
261 return false;
262 }
263 if (recv_rtcp_session_) {
264 return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
265 } else {
266 ASSERT(recv_session_ != NULL);
267 return recv_session_->UnprotectRtcp(p, in_len, out_len);
268 }
269 }
270
271 bool SrtpFilter::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) {
272 if (!IsActive()) {
273 LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active";
274 return false;
275 }
276
277 ASSERT(send_session_ != NULL);
278 return send_session_->GetRtpAuthParams(key, key_len, tag_len);
279 }
280
281 void SrtpFilter::set_signal_silent_time(uint32_t signal_silent_time_in_ms) {
282 signal_silent_time_in_ms_ = signal_silent_time_in_ms;
283 if (IsActive()) {
284 ASSERT(send_session_ != NULL);
285 send_session_->set_signal_silent_time(signal_silent_time_in_ms);
286 ASSERT(recv_session_ != NULL);
287 recv_session_->set_signal_silent_time(signal_silent_time_in_ms);
288 if (send_rtcp_session_)
289 send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms);
290 if (recv_rtcp_session_)
291 recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms);
292 }
293 }
294
295 bool SrtpFilter::ExpectOffer(ContentSource source) {
296 return ((state_ == ST_INIT) ||
297 (state_ == ST_ACTIVE) ||
298 (state_ == ST_SENTOFFER && source == CS_LOCAL) ||
299 (state_ == ST_SENTUPDATEDOFFER && source == CS_LOCAL) ||
300 (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) ||
301 (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE));
302 }
303
304 bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params,
305 ContentSource source) {
306 offer_params_ = params;
307 if (state_ == ST_INIT) {
308 state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
309 } else if (state_ == ST_ACTIVE) {
310 state_ =
311 (source == CS_LOCAL) ? ST_SENTUPDATEDOFFER : ST_RECEIVEDUPDATEDOFFER;
312 }
313 return true;
314 }
315
316 bool SrtpFilter::ExpectAnswer(ContentSource source) {
317 return ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
318 (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL) ||
319 (state_ == ST_SENTUPDATEDOFFER && source == CS_REMOTE) ||
320 (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_LOCAL) ||
321 (state_ == ST_SENTPRANSWER_NO_CRYPTO && source == CS_LOCAL) ||
322 (state_ == ST_SENTPRANSWER && source == CS_LOCAL) ||
323 (state_ == ST_RECEIVEDPRANSWER_NO_CRYPTO && source == CS_REMOTE) ||
324 (state_ == ST_RECEIVEDPRANSWER && source == CS_REMOTE));
325 }
326
327 bool SrtpFilter::DoSetAnswer(const std::vector<CryptoParams>& answer_params,
328 ContentSource source,
329 bool final) {
330 if (!ExpectAnswer(source)) {
331 LOG(LS_ERROR) << "Invalid state for SRTP answer";
332 return false;
333 }
334
335 // If the answer doesn't requests crypto complete the negotiation of an
336 // unencrypted session.
337 // Otherwise, finalize the parameters and apply them.
338 if (answer_params.empty()) {
339 if (final) {
340 return ResetParams();
341 } else {
342 // Need to wait for the final answer to decide if
343 // we should go to Active state.
344 state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO :
345 ST_RECEIVEDPRANSWER_NO_CRYPTO;
346 return true;
347 }
348 }
349 CryptoParams selected_params;
350 if (!NegotiateParams(answer_params, &selected_params))
351 return false;
352 const CryptoParams& send_params =
353 (source == CS_REMOTE) ? selected_params : answer_params[0];
354 const CryptoParams& recv_params =
355 (source == CS_REMOTE) ? answer_params[0] : selected_params;
356 if (!ApplyParams(send_params, recv_params)) {
357 return false;
358 }
359
360 if (final) {
361 offer_params_.clear();
362 state_ = ST_ACTIVE;
363 } else {
364 state_ =
365 (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER;
366 }
367 return true;
368 }
369
370 void SrtpFilter::CreateSrtpSessions() {
371 send_session_.reset(new SrtpSession());
372 applied_send_params_ = CryptoParams();
373 recv_session_.reset(new SrtpSession());
374 applied_recv_params_ = CryptoParams();
375
376 SignalSrtpError.repeat(send_session_->SignalSrtpError);
377 SignalSrtpError.repeat(recv_session_->SignalSrtpError);
378
379 send_session_->set_signal_silent_time(signal_silent_time_in_ms_);
380 recv_session_->set_signal_silent_time(signal_silent_time_in_ms_);
381 }
382
383 bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params,
384 CryptoParams* selected_params) {
385 // We're processing an accept. We should have exactly one set of params,
386 // unless the offer didn't mention crypto, in which case we shouldn't be here.
387 bool ret = (answer_params.size() == 1U && !offer_params_.empty());
388 if (ret) {
389 // We should find a match between the answer params and the offered params.
390 std::vector<CryptoParams>::const_iterator it;
391 for (it = offer_params_.begin(); it != offer_params_.end(); ++it) {
392 if (answer_params[0].Matches(*it)) {
393 break;
394 }
395 }
396
397 if (it != offer_params_.end()) {
398 *selected_params = *it;
399 } else {
400 ret = false;
401 }
402 }
403
404 if (!ret) {
405 LOG(LS_WARNING) << "Invalid parameters in SRTP answer";
406 }
407 return ret;
408 }
409
410 bool SrtpFilter::ApplyParams(const CryptoParams& send_params,
411 const CryptoParams& recv_params) {
412 // TODO(jiayl): Split this method to apply send and receive CryptoParams
413 // independently, so that we can skip one method when either send or receive
414 // CryptoParams is unchanged.
415 if (applied_send_params_.cipher_suite == send_params.cipher_suite &&
416 applied_send_params_.key_params == send_params.key_params &&
417 applied_recv_params_.cipher_suite == recv_params.cipher_suite &&
418 applied_recv_params_.key_params == recv_params.key_params) {
419 LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op.";
420
421 // We do not want to reset the ROC if the keys are the same. So just return.
422 return true;
423 }
424 // TODO(juberti): Zero these buffers after use.
425 bool ret;
426 uint8_t send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN];
427 ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) &&
428 ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key)));
429 if (ret) {
430 CreateSrtpSessions();
431 ret = (send_session_->SetSend(
432 rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite), send_key,
433 sizeof(send_key)) &&
434 recv_session_->SetRecv(
435 rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite), recv_key,
436 sizeof(recv_key)));
437 }
438 if (ret) {
439 LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
440 << " send cipher_suite " << send_params.cipher_suite
441 << " recv cipher_suite " << recv_params.cipher_suite;
442 applied_send_params_ = send_params;
443 applied_recv_params_ = recv_params;
444 } else {
445 LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters";
446 }
447 return ret;
448 }
449
450 bool SrtpFilter::ResetParams() {
451 offer_params_.clear();
452 state_ = ST_INIT;
453 send_session_ = nullptr;
454 recv_session_ = nullptr;
455 send_rtcp_session_ = nullptr;
456 recv_rtcp_session_ = nullptr;
457 LOG(LS_INFO) << "SRTP reset to init state";
458 return true;
459 }
460
461 bool SrtpFilter::ParseKeyParams(const std::string& key_params,
462 uint8_t* key,
463 int len) {
464 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
465
466 // Fail if key-method is wrong.
467 if (key_params.find("inline:") != 0) {
468 return false;
469 }
470
471 // Fail if base64 decode fails, or the key is the wrong size.
472 std::string key_b64(key_params.substr(7)), key_str;
473 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT,
474 &key_str, NULL) ||
475 static_cast<int>(key_str.size()) != len) {
476 return false;
477 }
478
479 memcpy(key, key_str.c_str(), len);
480 return true;
481 }
482
483 ///////////////////////////////////////////////////////////////////////////////
484 // SrtpSession
485
486 #ifdef HAVE_SRTP
487
488 bool SrtpSession::inited_ = false;
489
490 // This lock protects SrtpSession::inited_ and SrtpSession::sessions_.
491 rtc::GlobalLockPod SrtpSession::lock_;
492
493 SrtpSession::SrtpSession()
494 : session_(NULL),
495 rtp_auth_tag_len_(0),
496 rtcp_auth_tag_len_(0),
497 srtp_stat_(new SrtpStat()),
498 last_send_seq_num_(-1) {
499 {
500 rtc::GlobalLockScope ls(&lock_);
501 sessions()->push_back(this);
502 }
503 SignalSrtpError.repeat(srtp_stat_->SignalSrtpError);
504 }
505
506 SrtpSession::~SrtpSession() {
507 {
508 rtc::GlobalLockScope ls(&lock_);
509 sessions()->erase(std::find(sessions()->begin(), sessions()->end(), this));
510 }
511 if (session_) {
512 srtp_dealloc(session_);
513 }
514 }
515
516 bool SrtpSession::SetSend(int cs, const uint8_t* key, int len) {
517 return SetKey(ssrc_any_outbound, cs, key, len);
518 }
519
520 bool SrtpSession::SetRecv(int cs, const uint8_t* key, int len) {
521 return SetKey(ssrc_any_inbound, cs, key, len);
522 }
523
524 bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
525 if (!session_) {
526 LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session";
527 return false;
528 }
529
530 int need_len = in_len + rtp_auth_tag_len_; // NOLINT
531 if (max_len < need_len) {
532 LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length "
533 << max_len << " is less than the needed " << need_len;
534 return false;
535 }
536
537 *out_len = in_len;
538 int err = srtp_protect(session_, p, out_len);
539 uint32_t ssrc;
540 if (GetRtpSsrc(p, in_len, &ssrc)) {
541 srtp_stat_->AddProtectRtpResult(ssrc, err);
542 }
543 int seq_num;
544 GetRtpSeqNum(p, in_len, &seq_num);
545 if (err != err_status_ok) {
546 LOG(LS_WARNING) << "Failed to protect SRTP packet, seqnum="
547 << seq_num << ", err=" << err << ", last seqnum="
548 << last_send_seq_num_;
549 return false;
550 }
551 last_send_seq_num_ = seq_num;
552 return true;
553 }
554
555 bool SrtpSession::ProtectRtp(void* p,
556 int in_len,
557 int max_len,
558 int* out_len,
559 int64_t* index) {
560 if (!ProtectRtp(p, in_len, max_len, out_len)) {
561 return false;
562 }
563 return (index) ? GetSendStreamPacketIndex(p, in_len, index) : true;
564 }
565
566 bool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
567 if (!session_) {
568 LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session";
569 return false;
570 }
571
572 int need_len = in_len + sizeof(uint32_t) + rtcp_auth_tag_len_; // NOLINT
573 if (max_len < need_len) {
574 LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length "
575 << max_len << " is less than the needed " << need_len;
576 return false;
577 }
578
579 *out_len = in_len;
580 int err = srtp_protect_rtcp(session_, p, out_len);
581 srtp_stat_->AddProtectRtcpResult(err);
582 if (err != err_status_ok) {
583 LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err;
584 return false;
585 }
586 return true;
587 }
588
589 bool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) {
590 if (!session_) {
591 LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session";
592 return false;
593 }
594
595 *out_len = in_len;
596 int err = srtp_unprotect(session_, p, out_len);
597 uint32_t ssrc;
598 if (GetRtpSsrc(p, in_len, &ssrc)) {
599 srtp_stat_->AddUnprotectRtpResult(ssrc, err);
600 }
601 if (err != err_status_ok) {
602 LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err;
603 return false;
604 }
605 return true;
606 }
607
608 bool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) {
609 if (!session_) {
610 LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session";
611 return false;
612 }
613
614 *out_len = in_len;
615 int err = srtp_unprotect_rtcp(session_, p, out_len);
616 srtp_stat_->AddUnprotectRtcpResult(err);
617 if (err != err_status_ok) {
618 LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err;
619 return false;
620 }
621 return true;
622 }
623
624 bool SrtpSession::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) {
625 #if defined(ENABLE_EXTERNAL_AUTH)
626 ExternalHmacContext* external_hmac = NULL;
627 // stream_template will be the reference context for other streams.
628 // Let's use it for getting the keys.
629 srtp_stream_ctx_t* srtp_context = session_->stream_template;
630 if (srtp_context && srtp_context->rtp_auth) {
631 external_hmac = reinterpret_cast<ExternalHmacContext*>(
632 srtp_context->rtp_auth->state);
633 }
634
635 if (!external_hmac) {
636 LOG(LS_ERROR) << "Failed to get auth keys from libsrtp!.";
637 return false;
638 }
639
640 *key = external_hmac->key;
641 *key_len = external_hmac->key_length;
642 *tag_len = rtp_auth_tag_len_;
643 return true;
644 #else
645 return false;
646 #endif
647 }
648
649 bool SrtpSession::GetSendStreamPacketIndex(void* p,
650 int in_len,
651 int64_t* index) {
652 srtp_hdr_t* hdr = reinterpret_cast<srtp_hdr_t*>(p);
653 srtp_stream_ctx_t* stream = srtp_get_stream(session_, hdr->ssrc);
654 if (stream == NULL)
655 return false;
656
657 // Shift packet index, put into network byte order
658 *index = static_cast<int64_t>(
659 rtc::NetworkToHost64(rdbx_get_packet_index(&stream->rtp_rdbx) << 16));
660 return true;
661 }
662
663 void SrtpSession::set_signal_silent_time(uint32_t signal_silent_time_in_ms) {
664 srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms);
665 }
666
667 bool SrtpSession::SetKey(int type, int cs, const uint8_t* key, int len) {
668 if (session_) {
669 LOG(LS_ERROR) << "Failed to create SRTP session: "
670 << "SRTP session already created";
671 return false;
672 }
673
674 if (!Init()) {
675 return false;
676 }
677
678 srtp_policy_t policy;
679 memset(&policy, 0, sizeof(policy));
680
681 if (cs == rtc::SRTP_AES128_CM_SHA1_80) {
682 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
683 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
684 } else if (cs == rtc::SRTP_AES128_CM_SHA1_32) {
685 crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); // rtp is 32,
686 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // rtcp still 80
687 } else {
688 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported"
689 << " cipher_suite " << cs;
690 return false;
691 }
692
693 if (!key || len != SRTP_MASTER_KEY_LEN) {
694 LOG(LS_WARNING) << "Failed to create SRTP session: invalid key";
695 return false;
696 }
697
698 policy.ssrc.type = static_cast<ssrc_type_t>(type);
699 policy.ssrc.value = 0;
700 policy.key = const_cast<uint8_t*>(key);
701 // TODO(astor) parse window size from WSH session-param
702 policy.window_size = 1024;
703 policy.allow_repeat_tx = 1;
704 // If external authentication option is enabled, supply custom auth module
705 // id EXTERNAL_HMAC_SHA1 in the policy structure.
706 // We want to set this option only for rtp packets.
707 // By default policy structure is initialized to HMAC_SHA1.
708 #if defined(ENABLE_EXTERNAL_AUTH)
709 // Enable external HMAC authentication only for outgoing streams.
710 if (type == ssrc_any_outbound) {
711 policy.rtp.auth_type = EXTERNAL_HMAC_SHA1;
712 }
713 #endif
714 policy.next = NULL;
715
716 int err = srtp_create(&session_, &policy);
717 if (err != err_status_ok) {
718 session_ = NULL;
719 LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err;
720 return false;
721 }
722
723
724 rtp_auth_tag_len_ = policy.rtp.auth_tag_len;
725 rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len;
726 return true;
727 }
728
729 bool SrtpSession::Init() {
730 rtc::GlobalLockScope ls(&lock_);
731
732 if (!inited_) {
733 int err;
734 err = srtp_init();
735 if (err != err_status_ok) {
736 LOG(LS_ERROR) << "Failed to init SRTP, err=" << err;
737 return false;
738 }
739
740 err = srtp_install_event_handler(&SrtpSession::HandleEventThunk);
741 if (err != err_status_ok) {
742 LOG(LS_ERROR) << "Failed to install SRTP event handler, err=" << err;
743 return false;
744 }
745 #if defined(ENABLE_EXTERNAL_AUTH)
746 err = external_crypto_init();
747 if (err != err_status_ok) {
748 LOG(LS_ERROR) << "Failed to initialize fake auth, err=" << err;
749 return false;
750 }
751 #endif
752 inited_ = true;
753 }
754
755 return true;
756 }
757
758 void SrtpSession::Terminate() {
759 rtc::GlobalLockScope ls(&lock_);
760
761 if (inited_) {
762 int err = srtp_shutdown();
763 if (err) {
764 LOG(LS_ERROR) << "srtp_shutdown failed. err=" << err;
765 return;
766 }
767 inited_ = false;
768 }
769 }
770
771 void SrtpSession::HandleEvent(const srtp_event_data_t* ev) {
772 switch (ev->event) {
773 case event_ssrc_collision:
774 LOG(LS_INFO) << "SRTP event: SSRC collision";
775 break;
776 case event_key_soft_limit:
777 LOG(LS_INFO) << "SRTP event: reached soft key usage limit";
778 break;
779 case event_key_hard_limit:
780 LOG(LS_INFO) << "SRTP event: reached hard key usage limit";
781 break;
782 case event_packet_index_limit:
783 LOG(LS_INFO) << "SRTP event: reached hard packet limit (2^48 packets)";
784 break;
785 default:
786 LOG(LS_INFO) << "SRTP event: unknown " << ev->event;
787 break;
788 }
789 }
790
791 void SrtpSession::HandleEventThunk(srtp_event_data_t* ev) {
792 rtc::GlobalLockScope ls(&lock_);
793
794 for (std::list<SrtpSession*>::iterator it = sessions()->begin();
795 it != sessions()->end(); ++it) {
796 if ((*it)->session_ == ev->session) {
797 (*it)->HandleEvent(ev);
798 break;
799 }
800 }
801 }
802
803 std::list<SrtpSession*>* SrtpSession::sessions() {
804 RTC_DEFINE_STATIC_LOCAL(std::list<SrtpSession*>, sessions, ());
805 return &sessions;
806 }
807
808 #else // !HAVE_SRTP
809
810 // On some systems, SRTP is not (yet) available.
811
812 SrtpSession::SrtpSession() {
813 LOG(WARNING) << "SRTP implementation is missing.";
814 }
815
816 SrtpSession::~SrtpSession() {
817 }
818
819 bool SrtpSession::SetSend(const std::string& cs, const uint8_t* key, int len) {
820 return SrtpNotAvailable(__FUNCTION__);
821 }
822
823 bool SrtpSession::SetRecv(const std::string& cs, const uint8_t* key, int len) {
824 return SrtpNotAvailable(__FUNCTION__);
825 }
826
827 bool SrtpSession::ProtectRtp(void* data, int in_len, int max_len,
828 int* out_len) {
829 return SrtpNotAvailable(__FUNCTION__);
830 }
831
832 bool SrtpSession::ProtectRtcp(void* data, int in_len, int max_len,
833 int* out_len) {
834 return SrtpNotAvailable(__FUNCTION__);
835 }
836
837 bool SrtpSession::UnprotectRtp(void* data, int in_len, int* out_len) {
838 return SrtpNotAvailable(__FUNCTION__);
839 }
840
841 bool SrtpSession::UnprotectRtcp(void* data, int in_len, int* out_len) {
842 return SrtpNotAvailable(__FUNCTION__);
843 }
844
845 void SrtpSession::set_signal_silent_time(uint32_t signal_silent_time) {
846 // Do nothing.
847 }
848
849 #endif // HAVE_SRTP
850
851 ///////////////////////////////////////////////////////////////////////////////
852 // SrtpStat
853
854 #ifdef HAVE_SRTP
855
856 SrtpStat::SrtpStat()
857 : signal_silent_time_(1000) {
858 }
859
860 void SrtpStat::AddProtectRtpResult(uint32_t ssrc, int result) {
861 FailureKey key;
862 key.ssrc = ssrc;
863 key.mode = SrtpFilter::PROTECT;
864 switch (result) {
865 case err_status_ok:
866 key.error = SrtpFilter::ERROR_NONE;
867 break;
868 case err_status_auth_fail:
869 key.error = SrtpFilter::ERROR_AUTH;
870 break;
871 default:
872 key.error = SrtpFilter::ERROR_FAIL;
873 }
874 HandleSrtpResult(key);
875 }
876
877 void SrtpStat::AddUnprotectRtpResult(uint32_t ssrc, int result) {
878 FailureKey key;
879 key.ssrc = ssrc;
880 key.mode = SrtpFilter::UNPROTECT;
881 switch (result) {
882 case err_status_ok:
883 key.error = SrtpFilter::ERROR_NONE;
884 break;
885 case err_status_auth_fail:
886 key.error = SrtpFilter::ERROR_AUTH;
887 break;
888 case err_status_replay_fail:
889 case err_status_replay_old:
890 key.error = SrtpFilter::ERROR_REPLAY;
891 break;
892 default:
893 key.error = SrtpFilter::ERROR_FAIL;
894 }
895 HandleSrtpResult(key);
896 }
897
898 void SrtpStat::AddProtectRtcpResult(int result) {
899 AddProtectRtpResult(0U, result);
900 }
901
902 void SrtpStat::AddUnprotectRtcpResult(int result) {
903 AddUnprotectRtpResult(0U, result);
904 }
905
906 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
907 // Handle some cases where error should be signalled right away. For other
908 // errors, trigger error for the first time seeing it. After that, silent
909 // the same error for a certain amount of time (default 1 sec).
910 if (key.error != SrtpFilter::ERROR_NONE) {
911 // For errors, signal first time and wait for 1 sec.
912 FailureStat* stat = &(failures_[key]);
913 uint32_t current_time = rtc::Time();
914 if (stat->last_signal_time == 0 ||
915 rtc::TimeDiff(current_time, stat->last_signal_time) >
916 static_cast<int>(signal_silent_time_)) {
917 SignalSrtpError(key.ssrc, key.mode, key.error);
918 stat->last_signal_time = current_time;
919 }
920 }
921 }
922
923 #else // !HAVE_SRTP
924
925 // On some systems, SRTP is not (yet) available.
926
927 SrtpStat::SrtpStat()
928 : signal_silent_time_(1000) {
929 LOG(WARNING) << "SRTP implementation is missing.";
930 }
931
932 void SrtpStat::AddProtectRtpResult(uint32_t ssrc, int result) {
933 SrtpNotAvailable(__FUNCTION__);
934 }
935
936 void SrtpStat::AddUnprotectRtpResult(uint32_t ssrc, int result) {
937 SrtpNotAvailable(__FUNCTION__);
938 }
939
940 void SrtpStat::AddProtectRtcpResult(int result) {
941 SrtpNotAvailable(__FUNCTION__);
942 }
943
944 void SrtpStat::AddUnprotectRtcpResult(int result) {
945 SrtpNotAvailable(__FUNCTION__);
946 }
947
948 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
949 SrtpNotAvailable(__FUNCTION__);
950 }
951
952 #endif // HAVE_SRTP
953
954 } // namespace cricket
OLDNEW
« no previous file with comments | « talk/session/media/srtpfilter.h ('k') | talk/session/media/srtpfilter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698