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