• 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/logging.h"
39 #include "webrtc/base/stringencode.h"
40 #include "webrtc/base/timeutils.h"
41 
42 // Enable this line to turn on SRTP debugging
43 // #define SRTP_DEBUG
44 
45 #ifdef HAVE_SRTP
46 #ifdef SRTP_RELATIVE_PATH
47 #include "srtp.h"  // NOLINT
48 extern "C" srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
49 #include "srtp_priv.h"  // NOLINT
50 #else
51 #include "third_party/libsrtp/include/srtp.h"
52 extern "C" srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
53 #include "third_party/libsrtp/include/srtp_priv.h"
54 #endif  // SRTP_RELATIVE_PATH
55 #ifdef  ENABLE_EXTERNAL_AUTH
56 #include "talk/session/media/externalhmac.h"
57 #endif  // ENABLE_EXTERNAL_AUTH
58 #ifdef _DEBUG
59 extern "C" debug_module_t mod_srtp;
60 extern "C" debug_module_t mod_auth;
61 extern "C" debug_module_t mod_cipher;
62 extern "C" debug_module_t mod_stat;
63 extern "C" debug_module_t mod_alloc;
64 extern "C" debug_module_t mod_aes_icm;
65 extern "C" debug_module_t mod_aes_hmac;
66 #endif
67 #else
68 // SrtpFilter needs that constant.
69 #define SRTP_MASTER_KEY_LEN 30
70 #endif  // HAVE_SRTP
71 
72 namespace cricket {
73 
74 const char CS_AES_CM_128_HMAC_SHA1_80[] = "AES_CM_128_HMAC_SHA1_80";
75 const char CS_AES_CM_128_HMAC_SHA1_32[] = "AES_CM_128_HMAC_SHA1_32";
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 #ifdef _DEBUG
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(const std::string & send_cs,const uint8 * send_key,int send_key_len,const std::string & recv_cs,const uint8 * recv_key,int recv_key_len)149 bool SrtpFilter::SetRtpParams(const std::string& send_cs,
150                               const uint8* send_key, int send_key_len,
151                               const std::string& recv_cs,
152                               const uint8* recv_key, int recv_key_len) {
153   if (state_ == ST_ACTIVE) {
154     LOG(LS_ERROR) << "Tried to set SRTP Params when filter already active";
155     return false;
156   }
157   CreateSrtpSessions();
158   if (!send_session_->SetSend(send_cs, send_key, send_key_len))
159     return false;
160 
161   if (!recv_session_->SetRecv(recv_cs, recv_key, recv_key_len))
162     return false;
163 
164   state_ = ST_ACTIVE;
165 
166   LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
167                << " send cipher_suite " << send_cs
168                << " recv cipher_suite " << recv_cs;
169   return true;
170 }
171 
172 // This function is provided separately because DTLS-SRTP behaves
173 // differently in RTP/RTCP mux and non-mux modes.
174 //
175 // - In the non-muxed case, RTP and RTCP are keyed with different
176 //   keys (from different DTLS handshakes), and so we need a new
177 //   SrtpSession.
178 // - In the muxed case, they are keyed with the same keys, so
179 //   this function is not needed
SetRtcpParams(const std::string & send_cs,const uint8 * send_key,int send_key_len,const std::string & recv_cs,const uint8 * recv_key,int recv_key_len)180 bool SrtpFilter::SetRtcpParams(const std::string& send_cs,
181                                const uint8* send_key, int send_key_len,
182                                const std::string& recv_cs,
183                                const uint8* recv_key, int recv_key_len) {
184   // This can only be called once, but can be safely called after
185   // SetRtpParams
186   if (send_rtcp_session_ || recv_rtcp_session_) {
187     LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active";
188     return false;
189   }
190 
191   send_rtcp_session_.reset(new SrtpSession());
192   SignalSrtpError.repeat(send_rtcp_session_->SignalSrtpError);
193   send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_);
194   if (!send_rtcp_session_->SetRecv(send_cs, send_key, send_key_len))
195     return false;
196 
197   recv_rtcp_session_.reset(new SrtpSession());
198   SignalSrtpError.repeat(recv_rtcp_session_->SignalSrtpError);
199   recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_);
200   if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len))
201     return false;
202 
203   LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
204                << " send cipher_suite " << send_cs
205                << " recv cipher_suite " << recv_cs;
206 
207   return true;
208 }
209 
ProtectRtp(void * p,int in_len,int max_len,int * out_len)210 bool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
211   if (!IsActive()) {
212     LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
213     return false;
214   }
215   return send_session_->ProtectRtp(p, in_len, max_len, out_len);
216 }
217 
ProtectRtp(void * p,int in_len,int max_len,int * out_len,int64 * index)218 bool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len,
219                             int64* index) {
220   if (!IsActive()) {
221     LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
222     return false;
223   }
224 
225   return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
226 }
227 
ProtectRtcp(void * p,int in_len,int max_len,int * out_len)228 bool SrtpFilter::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
229   if (!IsActive()) {
230     LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
231     return false;
232   }
233   if (send_rtcp_session_) {
234     return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
235   } else {
236     return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
237   }
238 }
239 
UnprotectRtp(void * p,int in_len,int * out_len)240 bool SrtpFilter::UnprotectRtp(void* p, int in_len, int* out_len) {
241   if (!IsActive()) {
242     LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
243     return false;
244   }
245   return recv_session_->UnprotectRtp(p, in_len, out_len);
246 }
247 
UnprotectRtcp(void * p,int in_len,int * out_len)248 bool SrtpFilter::UnprotectRtcp(void* p, int in_len, int* out_len) {
249   if (!IsActive()) {
250     LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
251     return false;
252   }
253   if (recv_rtcp_session_) {
254     return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
255   } else {
256     return recv_session_->UnprotectRtcp(p, in_len, out_len);
257   }
258 }
259 
GetRtpAuthParams(uint8 ** key,int * key_len,int * tag_len)260 bool SrtpFilter::GetRtpAuthParams(uint8** key, int* key_len, int* tag_len) {
261   if (!IsActive()) {
262     LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active";
263     return false;
264   }
265 
266   return send_session_->GetRtpAuthParams(key, key_len, tag_len);
267 }
268 
set_signal_silent_time(uint32 signal_silent_time_in_ms)269 void SrtpFilter::set_signal_silent_time(uint32 signal_silent_time_in_ms) {
270   signal_silent_time_in_ms_ = signal_silent_time_in_ms;
271   if (state_ == ST_ACTIVE) {
272     send_session_->set_signal_silent_time(signal_silent_time_in_ms);
273     recv_session_->set_signal_silent_time(signal_silent_time_in_ms);
274     if (send_rtcp_session_)
275       send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms);
276     if (recv_rtcp_session_)
277       recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms);
278   }
279 }
280 
ExpectOffer(ContentSource source)281 bool SrtpFilter::ExpectOffer(ContentSource source) {
282   return ((state_ == ST_INIT) ||
283           (state_ == ST_ACTIVE) ||
284           (state_  == ST_SENTOFFER && source == CS_LOCAL) ||
285           (state_  == ST_SENTUPDATEDOFFER && source == CS_LOCAL) ||
286           (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) ||
287           (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE));
288 }
289 
StoreParams(const std::vector<CryptoParams> & params,ContentSource source)290 bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params,
291                              ContentSource source) {
292   offer_params_ = params;
293   if (state_ == ST_INIT) {
294     state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
295   } else {  // state >= ST_ACTIVE
296     state_ =
297         (source == CS_LOCAL) ? ST_SENTUPDATEDOFFER : ST_RECEIVEDUPDATEDOFFER;
298   }
299   return true;
300 }
301 
ExpectAnswer(ContentSource source)302 bool SrtpFilter::ExpectAnswer(ContentSource source) {
303   return ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
304           (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL) ||
305           (state_ == ST_SENTUPDATEDOFFER && source == CS_REMOTE) ||
306           (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_LOCAL) ||
307           (state_ == ST_SENTPRANSWER_NO_CRYPTO && source == CS_LOCAL) ||
308           (state_ == ST_SENTPRANSWER && source == CS_LOCAL) ||
309           (state_ == ST_RECEIVEDPRANSWER_NO_CRYPTO && source == CS_REMOTE) ||
310           (state_ == ST_RECEIVEDPRANSWER && source == CS_REMOTE));
311 }
312 
DoSetAnswer(const std::vector<CryptoParams> & answer_params,ContentSource source,bool final)313 bool SrtpFilter::DoSetAnswer(const std::vector<CryptoParams>& answer_params,
314                              ContentSource source,
315                              bool final) {
316   if (!ExpectAnswer(source)) {
317     LOG(LS_ERROR) << "Invalid state for SRTP answer";
318     return false;
319   }
320 
321   // If the answer doesn't requests crypto complete the negotiation of an
322   // unencrypted session.
323   // Otherwise, finalize the parameters and apply them.
324   if (answer_params.empty()) {
325     if (final) {
326       return ResetParams();
327     } else {
328       // Need to wait for the final answer to decide if
329       // we should go to Active state.
330       state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO :
331                                       ST_RECEIVEDPRANSWER_NO_CRYPTO;
332       return true;
333     }
334   }
335   CryptoParams selected_params;
336   if (!NegotiateParams(answer_params, &selected_params))
337     return false;
338   const CryptoParams& send_params =
339       (source == CS_REMOTE) ? selected_params : answer_params[0];
340   const CryptoParams& recv_params =
341       (source == CS_REMOTE) ? answer_params[0] : selected_params;
342   if (!ApplyParams(send_params, recv_params)) {
343     return false;
344   }
345 
346   if (final) {
347     offer_params_.clear();
348     state_ = ST_ACTIVE;
349   } else {
350     state_ =
351         (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER;
352   }
353   return true;
354 }
355 
CreateSrtpSessions()356 void SrtpFilter::CreateSrtpSessions() {
357   send_session_.reset(new SrtpSession());
358   applied_send_params_ = CryptoParams();
359   recv_session_.reset(new SrtpSession());
360   applied_recv_params_ = CryptoParams();
361 
362   SignalSrtpError.repeat(send_session_->SignalSrtpError);
363   SignalSrtpError.repeat(recv_session_->SignalSrtpError);
364 
365   send_session_->set_signal_silent_time(signal_silent_time_in_ms_);
366   recv_session_->set_signal_silent_time(signal_silent_time_in_ms_);
367 }
368 
NegotiateParams(const std::vector<CryptoParams> & answer_params,CryptoParams * selected_params)369 bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params,
370                                  CryptoParams* selected_params) {
371   // We're processing an accept. We should have exactly one set of params,
372   // unless the offer didn't mention crypto, in which case we shouldn't be here.
373   bool ret = (answer_params.size() == 1U && !offer_params_.empty());
374   if (ret) {
375     // We should find a match between the answer params and the offered params.
376     std::vector<CryptoParams>::const_iterator it;
377     for (it = offer_params_.begin(); it != offer_params_.end(); ++it) {
378       if (answer_params[0].Matches(*it)) {
379         break;
380       }
381     }
382 
383     if (it != offer_params_.end()) {
384       *selected_params = *it;
385     } else {
386       ret = false;
387     }
388   }
389 
390   if (!ret) {
391     LOG(LS_WARNING) << "Invalid parameters in SRTP answer";
392   }
393   return ret;
394 }
395 
ApplyParams(const CryptoParams & send_params,const CryptoParams & recv_params)396 bool SrtpFilter::ApplyParams(const CryptoParams& send_params,
397                              const CryptoParams& recv_params) {
398   // TODO(jiayl): Split this method to apply send and receive CryptoParams
399   // independently, so that we can skip one method when either send or receive
400   // CryptoParams is unchanged.
401   if (applied_send_params_.cipher_suite == send_params.cipher_suite &&
402       applied_send_params_.key_params == send_params.key_params &&
403       applied_recv_params_.cipher_suite == recv_params.cipher_suite &&
404       applied_recv_params_.key_params == recv_params.key_params) {
405     LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op.";
406 
407     // We do not want to reset the ROC if the keys are the same. So just return.
408     return true;
409   }
410   // TODO(juberti): Zero these buffers after use.
411   bool ret;
412   uint8 send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN];
413   ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) &&
414          ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key)));
415   if (ret) {
416     CreateSrtpSessions();
417     ret = (send_session_->SetSend(send_params.cipher_suite,
418                                   send_key, sizeof(send_key)) &&
419            recv_session_->SetRecv(recv_params.cipher_suite,
420                                   recv_key, sizeof(recv_key)));
421   }
422   if (ret) {
423     LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
424                  << " send cipher_suite " << send_params.cipher_suite
425                  << " recv cipher_suite " << recv_params.cipher_suite;
426     applied_send_params_ = send_params;
427     applied_recv_params_ = recv_params;
428   } else {
429     LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters";
430   }
431   return ret;
432 }
433 
ResetParams()434 bool SrtpFilter::ResetParams() {
435   offer_params_.clear();
436   state_ = ST_INIT;
437   LOG(LS_INFO) << "SRTP reset to init state";
438   return true;
439 }
440 
ParseKeyParams(const std::string & key_params,uint8 * key,int len)441 bool SrtpFilter::ParseKeyParams(const std::string& key_params,
442                                 uint8* key, int len) {
443   // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
444 
445   // Fail if key-method is wrong.
446   if (key_params.find("inline:") != 0) {
447     return false;
448   }
449 
450   // Fail if base64 decode fails, or the key is the wrong size.
451   std::string key_b64(key_params.substr(7)), key_str;
452   if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT,
453                                  &key_str, NULL) ||
454       static_cast<int>(key_str.size()) != len) {
455     return false;
456   }
457 
458   memcpy(key, key_str.c_str(), len);
459   return true;
460 }
461 
462 ///////////////////////////////////////////////////////////////////////////////
463 // SrtpSession
464 
465 #ifdef HAVE_SRTP
466 
467 bool SrtpSession::inited_ = false;
468 
SrtpSession()469 SrtpSession::SrtpSession()
470     : session_(NULL),
471       rtp_auth_tag_len_(0),
472       rtcp_auth_tag_len_(0),
473       srtp_stat_(new SrtpStat()),
474       last_send_seq_num_(-1) {
475   sessions()->push_back(this);
476   SignalSrtpError.repeat(srtp_stat_->SignalSrtpError);
477 }
478 
~SrtpSession()479 SrtpSession::~SrtpSession() {
480   sessions()->erase(std::find(sessions()->begin(), sessions()->end(), this));
481   if (session_) {
482     srtp_dealloc(session_);
483   }
484 }
485 
SetSend(const std::string & cs,const uint8 * key,int len)486 bool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
487   return SetKey(ssrc_any_outbound, cs, key, len);
488 }
489 
SetRecv(const std::string & cs,const uint8 * key,int len)490 bool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
491   return SetKey(ssrc_any_inbound, cs, key, len);
492 }
493 
ProtectRtp(void * p,int in_len,int max_len,int * out_len)494 bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
495   if (!session_) {
496     LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session";
497     return false;
498   }
499 
500   int need_len = in_len + rtp_auth_tag_len_;  // NOLINT
501   if (max_len < need_len) {
502     LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length "
503                     << max_len << " is less than the needed " << need_len;
504     return false;
505   }
506 
507   *out_len = in_len;
508   int err = srtp_protect(session_, p, out_len);
509   uint32 ssrc;
510   if (GetRtpSsrc(p, in_len, &ssrc)) {
511     srtp_stat_->AddProtectRtpResult(ssrc, err);
512   }
513   int seq_num;
514   GetRtpSeqNum(p, in_len, &seq_num);
515   if (err != err_status_ok) {
516     LOG(LS_WARNING) << "Failed to protect SRTP packet, seqnum="
517                     << seq_num << ", err=" << err << ", last seqnum="
518                     << last_send_seq_num_;
519     return false;
520   }
521   last_send_seq_num_ = seq_num;
522   return true;
523 }
524 
ProtectRtp(void * p,int in_len,int max_len,int * out_len,int64 * index)525 bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len,
526                              int64* index) {
527   if (!ProtectRtp(p, in_len, max_len, out_len)) {
528     return false;
529   }
530   return (index) ? GetSendStreamPacketIndex(p, in_len, index) : true;
531 }
532 
ProtectRtcp(void * p,int in_len,int max_len,int * out_len)533 bool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
534   if (!session_) {
535     LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session";
536     return false;
537   }
538 
539   int need_len = in_len + sizeof(uint32) + rtcp_auth_tag_len_;  // NOLINT
540   if (max_len < need_len) {
541     LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length "
542                     << max_len << " is less than the needed " << need_len;
543     return false;
544   }
545 
546   *out_len = in_len;
547   int err = srtp_protect_rtcp(session_, p, out_len);
548   srtp_stat_->AddProtectRtcpResult(err);
549   if (err != err_status_ok) {
550     LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err;
551     return false;
552   }
553   return true;
554 }
555 
UnprotectRtp(void * p,int in_len,int * out_len)556 bool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) {
557   if (!session_) {
558     LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session";
559     return false;
560   }
561 
562   *out_len = in_len;
563   int err = srtp_unprotect(session_, p, out_len);
564   uint32 ssrc;
565   if (GetRtpSsrc(p, in_len, &ssrc)) {
566     srtp_stat_->AddUnprotectRtpResult(ssrc, err);
567   }
568   if (err != err_status_ok) {
569     LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err;
570     return false;
571   }
572   return true;
573 }
574 
UnprotectRtcp(void * p,int in_len,int * out_len)575 bool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) {
576   if (!session_) {
577     LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session";
578     return false;
579   }
580 
581   *out_len = in_len;
582   int err = srtp_unprotect_rtcp(session_, p, out_len);
583   srtp_stat_->AddUnprotectRtcpResult(err);
584   if (err != err_status_ok) {
585     LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err;
586     return false;
587   }
588   return true;
589 }
590 
GetRtpAuthParams(uint8 ** key,int * key_len,int * tag_len)591 bool SrtpSession::GetRtpAuthParams(uint8** key, int* key_len,
592                                    int* tag_len) {
593 #if defined(ENABLE_EXTERNAL_AUTH)
594   external_hmac_ctx_t* external_hmac = NULL;
595   // stream_template will be the reference context for other streams.
596   // Let's use it for getting the keys.
597   srtp_stream_ctx_t* srtp_context = session_->stream_template;
598   if (srtp_context && srtp_context->rtp_auth) {
599     external_hmac = reinterpret_cast<external_hmac_ctx_t*>(
600         srtp_context->rtp_auth->state);
601   }
602 
603   if (!external_hmac) {
604     LOG(LS_ERROR) << "Failed to get auth keys from libsrtp!.";
605     return false;
606   }
607 
608   *key = external_hmac->key;
609   *key_len = external_hmac->key_length;
610   *tag_len = rtp_auth_tag_len_;
611   return true;
612 #else
613   return false;
614 #endif
615 }
616 
GetSendStreamPacketIndex(void * p,int in_len,int64 * index)617 bool SrtpSession::GetSendStreamPacketIndex(void* p, int in_len, int64* index) {
618   srtp_hdr_t* hdr = reinterpret_cast<srtp_hdr_t*>(p);
619   srtp_stream_ctx_t* stream = srtp_get_stream(session_, hdr->ssrc);
620   if (stream == NULL)
621     return false;
622 
623   // Shift packet index, put into network byte order
624   *index = be64_to_cpu(rdbx_get_packet_index(&stream->rtp_rdbx) << 16);
625   return true;
626 }
627 
set_signal_silent_time(uint32 signal_silent_time_in_ms)628 void SrtpSession::set_signal_silent_time(uint32 signal_silent_time_in_ms) {
629   srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms);
630 }
631 
SetKey(int type,const std::string & cs,const uint8 * key,int len)632 bool SrtpSession::SetKey(int type, const std::string& cs,
633                          const uint8* key, int len) {
634   if (session_) {
635     LOG(LS_ERROR) << "Failed to create SRTP session: "
636                   << "SRTP session already created";
637     return false;
638   }
639 
640   if (!Init()) {
641     return false;
642   }
643 
644   srtp_policy_t policy;
645   memset(&policy, 0, sizeof(policy));
646 
647   if (cs == CS_AES_CM_128_HMAC_SHA1_80) {
648     crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
649     crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
650   } else if (cs == CS_AES_CM_128_HMAC_SHA1_32) {
651     crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);   // rtp is 32,
652     crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);  // rtcp still 80
653   } else {
654     LOG(LS_WARNING) << "Failed to create SRTP session: unsupported"
655                     << " cipher_suite " << cs.c_str();
656     return false;
657   }
658 
659   if (!key || len != SRTP_MASTER_KEY_LEN) {
660     LOG(LS_WARNING) << "Failed to create SRTP session: invalid key";
661     return false;
662   }
663 
664   policy.ssrc.type = static_cast<ssrc_type_t>(type);
665   policy.ssrc.value = 0;
666   policy.key = const_cast<uint8*>(key);
667   // TODO(astor) parse window size from WSH session-param
668   policy.window_size = 1024;
669   policy.allow_repeat_tx = 1;
670   // If external authentication option is enabled, supply custom auth module
671   // id EXTERNAL_HMAC_SHA1 in the policy structure.
672   // We want to set this option only for rtp packets.
673   // By default policy structure is initialized to HMAC_SHA1.
674 #if defined(ENABLE_EXTERNAL_AUTH)
675   // Enable external HMAC authentication only for outgoing streams.
676   if (type == ssrc_any_outbound) {
677     policy.rtp.auth_type = EXTERNAL_HMAC_SHA1;
678   }
679 #endif
680   policy.next = NULL;
681 
682   int err = srtp_create(&session_, &policy);
683   if (err != err_status_ok) {
684     LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err;
685     return false;
686   }
687 
688 
689   rtp_auth_tag_len_ = policy.rtp.auth_tag_len;
690   rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len;
691   return true;
692 }
693 
Init()694 bool SrtpSession::Init() {
695   if (!inited_) {
696     int err;
697     err = srtp_init();
698     if (err != err_status_ok) {
699       LOG(LS_ERROR) << "Failed to init SRTP, err=" << err;
700       return false;
701     }
702 
703     err = srtp_install_event_handler(&SrtpSession::HandleEventThunk);
704     if (err != err_status_ok) {
705       LOG(LS_ERROR) << "Failed to install SRTP event handler, err=" << err;
706       return false;
707     }
708 #if defined(ENABLE_EXTERNAL_AUTH)
709     err = external_crypto_init();
710     if (err != err_status_ok) {
711       LOG(LS_ERROR) << "Failed to initialize fake auth, err=" << err;
712       return false;
713     }
714 #endif
715     inited_ = true;
716   }
717 
718   return true;
719 }
720 
Terminate()721 void SrtpSession::Terminate() {
722   if (inited_) {
723     int err = srtp_shutdown();
724     if (err) {
725       LOG(LS_ERROR) << "srtp_shutdown failed. err=" << err;
726       return;
727     }
728     inited_ = false;
729   }
730 }
731 
HandleEvent(const srtp_event_data_t * ev)732 void SrtpSession::HandleEvent(const srtp_event_data_t* ev) {
733   switch (ev->event) {
734     case event_ssrc_collision:
735       LOG(LS_INFO) << "SRTP event: SSRC collision";
736       break;
737     case event_key_soft_limit:
738       LOG(LS_INFO) << "SRTP event: reached soft key usage limit";
739       break;
740     case event_key_hard_limit:
741       LOG(LS_INFO) << "SRTP event: reached hard key usage limit";
742       break;
743     case event_packet_index_limit:
744       LOG(LS_INFO) << "SRTP event: reached hard packet limit (2^48 packets)";
745       break;
746     default:
747       LOG(LS_INFO) << "SRTP event: unknown " << ev->event;
748       break;
749   }
750 }
751 
HandleEventThunk(srtp_event_data_t * ev)752 void SrtpSession::HandleEventThunk(srtp_event_data_t* ev) {
753   for (std::list<SrtpSession*>::iterator it = sessions()->begin();
754        it != sessions()->end(); ++it) {
755     if ((*it)->session_ == ev->session) {
756       (*it)->HandleEvent(ev);
757       break;
758     }
759   }
760 }
761 
sessions()762 std::list<SrtpSession*>* SrtpSession::sessions() {
763   LIBJINGLE_DEFINE_STATIC_LOCAL(std::list<SrtpSession*>, sessions, ());
764   return &sessions;
765 }
766 
767 #else   // !HAVE_SRTP
768 
769 // On some systems, SRTP is not (yet) available.
770 
SrtpSession()771 SrtpSession::SrtpSession() {
772   LOG(WARNING) << "SRTP implementation is missing.";
773 }
774 
~SrtpSession()775 SrtpSession::~SrtpSession() {
776 }
777 
SetSend(const std::string & cs,const uint8 * key,int len)778 bool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
779   return SrtpNotAvailable(__FUNCTION__);
780 }
781 
SetRecv(const std::string & cs,const uint8 * key,int len)782 bool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
783   return SrtpNotAvailable(__FUNCTION__);
784 }
785 
ProtectRtp(void * data,int in_len,int max_len,int * out_len)786 bool SrtpSession::ProtectRtp(void* data, int in_len, int max_len,
787                              int* out_len) {
788   return SrtpNotAvailable(__FUNCTION__);
789 }
790 
ProtectRtcp(void * data,int in_len,int max_len,int * out_len)791 bool SrtpSession::ProtectRtcp(void* data, int in_len, int max_len,
792                               int* out_len) {
793   return SrtpNotAvailable(__FUNCTION__);
794 }
795 
UnprotectRtp(void * data,int in_len,int * out_len)796 bool SrtpSession::UnprotectRtp(void* data, int in_len, int* out_len) {
797   return SrtpNotAvailable(__FUNCTION__);
798 }
799 
UnprotectRtcp(void * data,int in_len,int * out_len)800 bool SrtpSession::UnprotectRtcp(void* data, int in_len, int* out_len) {
801   return SrtpNotAvailable(__FUNCTION__);
802 }
803 
set_signal_silent_time(uint32 signal_silent_time)804 void SrtpSession::set_signal_silent_time(uint32 signal_silent_time) {
805   // Do nothing.
806 }
807 
808 #endif  // HAVE_SRTP
809 
810 ///////////////////////////////////////////////////////////////////////////////
811 // SrtpStat
812 
813 #ifdef HAVE_SRTP
814 
SrtpStat()815 SrtpStat::SrtpStat()
816     : signal_silent_time_(1000) {
817 }
818 
AddProtectRtpResult(uint32 ssrc,int result)819 void SrtpStat::AddProtectRtpResult(uint32 ssrc, int result) {
820   FailureKey key;
821   key.ssrc = ssrc;
822   key.mode = SrtpFilter::PROTECT;
823   switch (result) {
824     case err_status_ok:
825       key.error = SrtpFilter::ERROR_NONE;
826       break;
827     case err_status_auth_fail:
828       key.error = SrtpFilter::ERROR_AUTH;
829       break;
830     default:
831       key.error = SrtpFilter::ERROR_FAIL;
832   }
833   HandleSrtpResult(key);
834 }
835 
AddUnprotectRtpResult(uint32 ssrc,int result)836 void SrtpStat::AddUnprotectRtpResult(uint32 ssrc, int result) {
837   FailureKey key;
838   key.ssrc = ssrc;
839   key.mode = SrtpFilter::UNPROTECT;
840   switch (result) {
841     case err_status_ok:
842       key.error = SrtpFilter::ERROR_NONE;
843       break;
844     case err_status_auth_fail:
845       key.error = SrtpFilter::ERROR_AUTH;
846       break;
847     case err_status_replay_fail:
848     case err_status_replay_old:
849       key.error = SrtpFilter::ERROR_REPLAY;
850       break;
851     default:
852       key.error = SrtpFilter::ERROR_FAIL;
853   }
854   HandleSrtpResult(key);
855 }
856 
AddProtectRtcpResult(int result)857 void SrtpStat::AddProtectRtcpResult(int result) {
858   AddProtectRtpResult(0U, result);
859 }
860 
AddUnprotectRtcpResult(int result)861 void SrtpStat::AddUnprotectRtcpResult(int result) {
862   AddUnprotectRtpResult(0U, result);
863 }
864 
HandleSrtpResult(const SrtpStat::FailureKey & key)865 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
866   // Handle some cases where error should be signalled right away. For other
867   // errors, trigger error for the first time seeing it.  After that, silent
868   // the same error for a certain amount of time (default 1 sec).
869   if (key.error != SrtpFilter::ERROR_NONE) {
870     // For errors, signal first time and wait for 1 sec.
871     FailureStat* stat = &(failures_[key]);
872     uint32 current_time = rtc::Time();
873     if (stat->last_signal_time == 0 ||
874         rtc::TimeDiff(current_time, stat->last_signal_time) >
875         static_cast<int>(signal_silent_time_)) {
876       SignalSrtpError(key.ssrc, key.mode, key.error);
877       stat->last_signal_time = current_time;
878     }
879   }
880 }
881 
882 #else   // !HAVE_SRTP
883 
884 // On some systems, SRTP is not (yet) available.
885 
SrtpStat()886 SrtpStat::SrtpStat()
887     : signal_silent_time_(1000) {
888   LOG(WARNING) << "SRTP implementation is missing.";
889 }
890 
AddProtectRtpResult(uint32 ssrc,int result)891 void SrtpStat::AddProtectRtpResult(uint32 ssrc, int result) {
892   SrtpNotAvailable(__FUNCTION__);
893 }
894 
AddUnprotectRtpResult(uint32 ssrc,int result)895 void SrtpStat::AddUnprotectRtpResult(uint32 ssrc, int result) {
896   SrtpNotAvailable(__FUNCTION__);
897 }
898 
AddProtectRtcpResult(int result)899 void SrtpStat::AddProtectRtcpResult(int result) {
900   SrtpNotAvailable(__FUNCTION__);
901 }
902 
AddUnprotectRtcpResult(int result)903 void SrtpStat::AddUnprotectRtcpResult(int result) {
904   SrtpNotAvailable(__FUNCTION__);
905 }
906 
HandleSrtpResult(const SrtpStat::FailureKey & key)907 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
908   SrtpNotAvailable(__FUNCTION__);
909 }
910 
911 #endif  // HAVE_SRTP
912 
913 }  // namespace cricket
914