• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "talk/media/base/rtputils.h"
37 #include "webrtc/base/base64.h"
38 #include "webrtc/base/byteorder.h"
39 #include "webrtc/base/common.h"
40 #include "webrtc/base/logging.h"
41 #include "webrtc/base/stringencode.h"
42 #include "webrtc/base/timeutils.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 {
SrtpNotAvailable(const char * func)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 
EnableSrtpDebugging()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.
ShutdownSrtp()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 
SrtpFilter()117 SrtpFilter::SrtpFilter()
118     : state_(ST_INIT),
119       signal_silent_time_in_ms_(0) {
120 }
121 
~SrtpFilter()122 SrtpFilter::~SrtpFilter() {
123 }
124 
IsActive() const125 bool SrtpFilter::IsActive() const {
126   return state_ >= ST_ACTIVE;
127 }
128 
SetOffer(const std::vector<CryptoParams> & offer_params,ContentSource source)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 
SetAnswer(const std::vector<CryptoParams> & answer_params,ContentSource source)138 bool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params,
139                            ContentSource source) {
140   return DoSetAnswer(answer_params, source, true);
141 }
142 
SetProvisionalAnswer(const std::vector<CryptoParams> & answer_params,ContentSource source)143 bool SrtpFilter::SetProvisionalAnswer(
144     const std::vector<CryptoParams>& answer_params,
145     ContentSource source) {
146   return DoSetAnswer(answer_params, source, false);
147 }
148 
SetRtpParams(int send_cs,const uint8_t * send_key,int send_key_len,int recv_cs,const uint8_t * recv_key,int recv_key_len)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
SetRtcpParams(int send_cs,const uint8_t * send_key,int send_key_len,int recv_cs,const uint8_t * recv_key,int recv_key_len)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 
ProtectRtp(void * p,int in_len,int max_len,int * out_len)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 
ProtectRtp(void * p,int in_len,int max_len,int * out_len,int64_t * index)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 
ProtectRtcp(void * p,int in_len,int max_len,int * out_len)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 
UnprotectRtp(void * p,int in_len,int * out_len)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 
UnprotectRtcp(void * p,int in_len,int * out_len)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 
GetRtpAuthParams(uint8_t ** key,int * key_len,int * tag_len)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 
set_signal_silent_time(uint32_t signal_silent_time_in_ms)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 
ExpectOffer(ContentSource source)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 
StoreParams(const std::vector<CryptoParams> & params,ContentSource source)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 
ExpectAnswer(ContentSource source)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 
DoSetAnswer(const std::vector<CryptoParams> & answer_params,ContentSource source,bool final)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 
CreateSrtpSessions()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 
NegotiateParams(const std::vector<CryptoParams> & answer_params,CryptoParams * selected_params)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 
ApplyParams(const CryptoParams & send_params,const CryptoParams & recv_params)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 
ResetParams()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 
ParseKeyParams(const std::string & key_params,uint8_t * key,int len)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 
SrtpSession()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 
~SrtpSession()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 
SetSend(int cs,const uint8_t * key,int len)516 bool SrtpSession::SetSend(int cs, const uint8_t* key, int len) {
517   return SetKey(ssrc_any_outbound, cs, key, len);
518 }
519 
SetRecv(int cs,const uint8_t * key,int len)520 bool SrtpSession::SetRecv(int cs, const uint8_t* key, int len) {
521   return SetKey(ssrc_any_inbound, cs, key, len);
522 }
523 
ProtectRtp(void * p,int in_len,int max_len,int * out_len)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 
ProtectRtp(void * p,int in_len,int max_len,int * out_len,int64_t * index)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 
ProtectRtcp(void * p,int in_len,int max_len,int * out_len)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 
UnprotectRtp(void * p,int in_len,int * out_len)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 
UnprotectRtcp(void * p,int in_len,int * out_len)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 
GetRtpAuthParams(uint8_t ** key,int * key_len,int * tag_len)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 
GetSendStreamPacketIndex(void * p,int in_len,int64_t * index)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 
set_signal_silent_time(uint32_t signal_silent_time_in_ms)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 
SetKey(int type,int cs,const uint8_t * key,int len)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 
Init()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 
Terminate()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 
HandleEvent(const srtp_event_data_t * ev)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 
HandleEventThunk(srtp_event_data_t * ev)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 
sessions()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 
SrtpSession()812 SrtpSession::SrtpSession() {
813   LOG(WARNING) << "SRTP implementation is missing.";
814 }
815 
~SrtpSession()816 SrtpSession::~SrtpSession() {
817 }
818 
SetSend(const std::string & cs,const uint8_t * key,int len)819 bool SrtpSession::SetSend(const std::string& cs, const uint8_t* key, int len) {
820   return SrtpNotAvailable(__FUNCTION__);
821 }
822 
SetRecv(const std::string & cs,const uint8_t * key,int len)823 bool SrtpSession::SetRecv(const std::string& cs, const uint8_t* key, int len) {
824   return SrtpNotAvailable(__FUNCTION__);
825 }
826 
ProtectRtp(void * data,int in_len,int max_len,int * out_len)827 bool SrtpSession::ProtectRtp(void* data, int in_len, int max_len,
828                              int* out_len) {
829   return SrtpNotAvailable(__FUNCTION__);
830 }
831 
ProtectRtcp(void * data,int in_len,int max_len,int * out_len)832 bool SrtpSession::ProtectRtcp(void* data, int in_len, int max_len,
833                               int* out_len) {
834   return SrtpNotAvailable(__FUNCTION__);
835 }
836 
UnprotectRtp(void * data,int in_len,int * out_len)837 bool SrtpSession::UnprotectRtp(void* data, int in_len, int* out_len) {
838   return SrtpNotAvailable(__FUNCTION__);
839 }
840 
UnprotectRtcp(void * data,int in_len,int * out_len)841 bool SrtpSession::UnprotectRtcp(void* data, int in_len, int* out_len) {
842   return SrtpNotAvailable(__FUNCTION__);
843 }
844 
set_signal_silent_time(uint32_t signal_silent_time)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 
SrtpStat()856 SrtpStat::SrtpStat()
857     : signal_silent_time_(1000) {
858 }
859 
AddProtectRtpResult(uint32_t ssrc,int result)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 
AddUnprotectRtpResult(uint32_t ssrc,int result)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 
AddProtectRtcpResult(int result)898 void SrtpStat::AddProtectRtcpResult(int result) {
899   AddProtectRtpResult(0U, result);
900 }
901 
AddUnprotectRtcpResult(int result)902 void SrtpStat::AddUnprotectRtcpResult(int result) {
903   AddUnprotectRtpResult(0U, result);
904 }
905 
HandleSrtpResult(const SrtpStat::FailureKey & key)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 
SrtpStat()927 SrtpStat::SrtpStat()
928     : signal_silent_time_(1000) {
929   LOG(WARNING) << "SRTP implementation is missing.";
930 }
931 
AddProtectRtpResult(uint32_t ssrc,int result)932 void SrtpStat::AddProtectRtpResult(uint32_t ssrc, int result) {
933   SrtpNotAvailable(__FUNCTION__);
934 }
935 
AddUnprotectRtpResult(uint32_t ssrc,int result)936 void SrtpStat::AddUnprotectRtpResult(uint32_t ssrc, int result) {
937   SrtpNotAvailable(__FUNCTION__);
938 }
939 
AddProtectRtcpResult(int result)940 void SrtpStat::AddProtectRtcpResult(int result) {
941   SrtpNotAvailable(__FUNCTION__);
942 }
943 
AddUnprotectRtcpResult(int result)944 void SrtpStat::AddUnprotectRtcpResult(int result) {
945   SrtpNotAvailable(__FUNCTION__);
946 }
947 
HandleSrtpResult(const SrtpStat::FailureKey & key)948 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
949   SrtpNotAvailable(__FUNCTION__);
950 }
951 
952 #endif  // HAVE_SRTP
953 
954 }  // namespace cricket
955