Home | History | Annotate | Download | only in phone
      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 // talk's config.h, generated from mac_config_dot_h for OSX, conflicts with the
     29 // one included by the libsrtp headers. Don't use it. Instead, we keep HAVE_SRTP
     30 // and LOGGING defined in config.h.
     31 #undef HAVE_CONFIG_H
     32 
     33 #ifdef OSX
     34 // TODO: For the XCode build, we force SRTP (b/2500074)
     35 #ifndef HAVE_SRTP
     36 #define HAVE_SRTP 1
     37 #endif  // HAVE_SRTP
     38 // If LOGGING is not defined, define it to 1 (b/3245816)
     39 #ifndef LOGGING
     40 #define LOGGING 1
     41 #endif  // HAVE_SRTP
     42 #endif
     43 
     44 #include "talk/session/phone/srtpfilter.h"
     45 
     46 #include <algorithm>
     47 #include <cstring>
     48 
     49 #include "talk/base/base64.h"
     50 #include "talk/base/logging.h"
     51 
     52 // Enable this line to turn on SRTP debugging
     53 // #define SRTP_DEBUG
     54 
     55 #ifdef HAVE_SRTP
     56 #ifdef SRTP_RELATIVE_PATH
     57 #include "srtp.h"  // NOLINT
     58 #else
     59 #include "third_party/libsrtp/include/srtp.h"
     60 #endif  // SRTP_RELATIVE_PATH
     61 #ifdef _DEBUG
     62 extern "C" debug_module_t mod_srtp;
     63 #endif
     64 #else
     65 // SrtpFilter needs that constant.
     66 #define SRTP_MASTER_KEY_LEN 30
     67 #endif  // HAVE_SRTP
     68 
     69 namespace cricket {
     70 
     71 const std::string& CS_DEFAULT = CS_AES_CM_128_HMAC_SHA1_80;
     72 const std::string CS_AES_CM_128_HMAC_SHA1_80 = "AES_CM_128_HMAC_SHA1_80";
     73 const std::string CS_AES_CM_128_HMAC_SHA1_32 = "AES_CM_128_HMAC_SHA1_32";
     74 const int SRTP_MASTER_KEY_BASE64_LEN = SRTP_MASTER_KEY_LEN * 4 / 3;
     75 
     76 SrtpFilter::SrtpFilter() : state_(ST_INIT) {
     77 }
     78 
     79 SrtpFilter::~SrtpFilter() {
     80 }
     81 
     82 bool SrtpFilter::IsActive() const {
     83   return (state_ == ST_ACTIVE);
     84 }
     85 
     86 bool SrtpFilter::SetOffer(const std::vector<CryptoParams>& offer_params,
     87                           ContentSource source) {
     88   bool ret = false;
     89   if (state_ == ST_INIT) {
     90     ret = StoreParams(offer_params, source);
     91   } else {
     92     LOG(LS_ERROR) << "Invalid state for SRTP offer";
     93   }
     94   return ret;
     95 }
     96 
     97 bool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params,
     98                            ContentSource source) {
     99   bool ret = false;
    100   if ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
    101       (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL)) {
    102     // If the answer requests crypto, finalize the parameters and apply them.
    103     // Otherwise, complete the negotiation of a unencrypted session.
    104     if (!answer_params.empty()) {
    105       CryptoParams selected_params;
    106       ret = NegotiateParams(answer_params, &selected_params);
    107       if (ret) {
    108         if (state_ == ST_SENTOFFER) {
    109           ret = ApplyParams(selected_params, answer_params[0]);
    110         } else {  // ST_RECEIVEDOFFER
    111           ret = ApplyParams(answer_params[0], selected_params);
    112         }
    113       }
    114     } else {
    115       ret = ResetParams();
    116     }
    117   } else {
    118     LOG(LS_ERROR) << "Invalid state for SRTP answer";
    119   }
    120   return ret;
    121 }
    122 
    123 bool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
    124   if (!IsActive()) {
    125     LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
    126     return false;
    127   }
    128   return send_session_.ProtectRtp(p, in_len, max_len, out_len);
    129 }
    130 
    131 bool SrtpFilter::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
    132   if (!IsActive()) {
    133     LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
    134     return false;
    135   }
    136   return send_session_.ProtectRtcp(p, in_len, max_len, out_len);
    137 }
    138 
    139 bool SrtpFilter::UnprotectRtp(void* p, int in_len, int* out_len) {
    140   if (!IsActive()) {
    141     LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
    142     return false;
    143   }
    144   return recv_session_.UnprotectRtp(p, in_len, out_len);
    145 }
    146 
    147 bool SrtpFilter::UnprotectRtcp(void* p, int in_len, int* out_len) {
    148   if (!IsActive()) {
    149     LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
    150     return false;
    151   }
    152   return recv_session_.UnprotectRtcp(p, in_len, out_len);
    153 }
    154 
    155 
    156 bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params,
    157                              ContentSource source) {
    158   offer_params_ = params;
    159   state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
    160   return true;
    161 }
    162 
    163 bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params,
    164                                  CryptoParams* selected_params) {
    165   // We're processing an accept. We should have exactly one set of params,
    166   // unless the offer didn't mention crypto, in which case we shouldn't be here.
    167   bool ret = (answer_params.size() == 1U && !offer_params_.empty());
    168   if (ret) {
    169     // We should find a match between the answer params and the offered params.
    170     std::vector<CryptoParams>::const_iterator it;
    171     for (it = offer_params_.begin(); it != offer_params_.end(); ++it) {
    172       if (answer_params[0].Matches(*it)) {
    173         break;
    174       }
    175     }
    176 
    177     if (it != offer_params_.end()) {
    178       *selected_params = *it;
    179     } else {
    180       ret = false;
    181     }
    182   }
    183 
    184   if (!ret) {
    185     LOG(LS_WARNING) << "Invalid parameters in SRTP answer";
    186   }
    187   return ret;
    188 }
    189 
    190 bool SrtpFilter::ApplyParams(const CryptoParams& send_params,
    191                              const CryptoParams& recv_params) {
    192   // TODO: Zero these buffers after use.
    193   bool ret;
    194   uint8 send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN];
    195   ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) &&
    196          ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key)));
    197   if (ret) {
    198     ret = (send_session_.SetSend(send_params.cipher_suite,
    199                                  send_key, sizeof(send_key)) &&
    200            recv_session_.SetRecv(recv_params.cipher_suite,
    201                                  recv_key, sizeof(recv_key)));
    202   }
    203   if (ret) {
    204     offer_params_.clear();
    205     state_ = ST_ACTIVE;
    206     LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
    207                  << " send cipher_suite " << send_params.cipher_suite
    208                  << " recv cipher_suite " << recv_params.cipher_suite;
    209   } else {
    210     LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters";
    211   }
    212   return ret;
    213 }
    214 
    215 bool SrtpFilter::ResetParams() {
    216   offer_params_.clear();
    217   state_ = ST_INIT;
    218   LOG(LS_INFO) << "SRTP reset to init state";
    219   return true;
    220 }
    221 
    222 bool SrtpFilter::ParseKeyParams(const std::string& key_params,
    223                                 uint8* key, int len) {
    224   // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
    225 
    226   // Fail if key-method is wrong.
    227   if (key_params.find("inline:") != 0) {
    228     return false;
    229   }
    230 
    231   // Fail if base64 decode fails, or the key is the wrong size.
    232   std::string key_b64(key_params.substr(7)), key_str;
    233   if (!talk_base::Base64::Decode(key_b64, talk_base::Base64::DO_STRICT,
    234                                  &key_str, NULL) ||
    235       static_cast<int>(key_str.size()) != len) {
    236     return false;
    237   }
    238 
    239   memcpy(key, key_str.c_str(), len);
    240   return true;
    241 }
    242 
    243 ///////////////////////////////////////////////////////////////////////////////
    244 // SrtpSession
    245 
    246 #ifdef HAVE_SRTP
    247 
    248 bool SrtpSession::inited_ = false;
    249 std::list<SrtpSession*> SrtpSession::sessions_;
    250 
    251 SrtpSession::SrtpSession()
    252     : session_(NULL), rtp_auth_tag_len_(0), rtcp_auth_tag_len_(0) {
    253   sessions_.push_back(this);
    254 }
    255 
    256 SrtpSession::~SrtpSession() {
    257   sessions_.erase(std::find(sessions_.begin(), sessions_.end(), this));
    258   if (session_) {
    259     srtp_dealloc(session_);
    260   }
    261 }
    262 
    263 bool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
    264   return SetKey(ssrc_any_outbound, cs, key, len);
    265 }
    266 
    267 bool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
    268   return SetKey(ssrc_any_inbound, cs, key, len);
    269 }
    270 
    271 bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
    272   if (!session_) {
    273     LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session";
    274     return false;
    275   }
    276 
    277   int need_len = in_len + rtp_auth_tag_len_;  // NOLINT
    278   if (max_len < need_len) {
    279     LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length "
    280                     << max_len << " is less than the needed " << need_len;
    281     return false;
    282   }
    283 
    284   *out_len = in_len;
    285   int err = srtp_protect(session_, p, out_len);
    286   if (err != err_status_ok) {
    287     LOG(LS_WARNING) << "Failed to protect SRTP packet, err=" << err;
    288     return false;
    289   }
    290   return true;
    291 }
    292 
    293 bool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
    294   if (!session_) {
    295     LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session";
    296     return false;
    297   }
    298 
    299   int need_len = in_len + sizeof(uint32) + rtcp_auth_tag_len_;  // NOLINT
    300   if (max_len < need_len) {
    301     LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length "
    302                     << max_len << " is less than the needed " << need_len;
    303     return false;
    304   }
    305 
    306   *out_len = in_len;
    307   int err = srtp_protect_rtcp(session_, p, out_len);
    308   if (err != err_status_ok) {
    309     LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err;
    310     return false;
    311   }
    312   return true;
    313 }
    314 
    315 bool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) {
    316   if (!session_) {
    317     LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session";
    318     return false;
    319   }
    320 
    321   *out_len = in_len;
    322   int err = srtp_unprotect(session_, p, out_len);
    323   if (err != err_status_ok) {
    324     LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err;
    325     return false;
    326   }
    327   return true;
    328 }
    329 
    330 bool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) {
    331   if (!session_) {
    332     LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session";
    333     return false;
    334   }
    335 
    336   *out_len = in_len;
    337   int err = srtp_unprotect_rtcp(session_, p, out_len);
    338   if (err != err_status_ok) {
    339     LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err;
    340     return false;
    341   }
    342   return true;
    343 }
    344 
    345 bool SrtpSession::SetKey(int type, const std::string& cs,
    346                          const uint8* key, int len) {
    347   if (session_) {
    348     LOG(LS_ERROR) << "Failed to create SRTP session: "
    349                   << "SRTP session already created";
    350     return false;
    351   }
    352 
    353   if (!Init()) {
    354     return false;
    355   }
    356 
    357   srtp_policy_t policy;
    358   memset(&policy, 0, sizeof(policy));
    359 
    360   if (cs == CS_AES_CM_128_HMAC_SHA1_80) {
    361     crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
    362     crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
    363   } else if (cs == CS_AES_CM_128_HMAC_SHA1_32) {
    364     crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);   // rtp is 32,
    365     crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);  // rtcp still 80
    366   } else {
    367     LOG(LS_WARNING) << "Failed to create SRTP session: unsupported"
    368                     << " cipher_suite " << cs.c_str();
    369     return false;
    370   }
    371 
    372   if (!key || len != SRTP_MASTER_KEY_LEN) {
    373     LOG(LS_WARNING) << "Failed to create SRTP session: invalid key";
    374     return false;
    375   }
    376 
    377   policy.ssrc.type = static_cast<ssrc_type_t>(type);
    378   policy.ssrc.value = 0;
    379   policy.key = const_cast<uint8*>(key);
    380   // TODO parse window size from WSH session-param
    381   policy.window_size = 1024;
    382   policy.allow_repeat_tx = 1;
    383   policy.next = NULL;
    384 
    385   int err = srtp_create(&session_, &policy);
    386   if (err != err_status_ok) {
    387     LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err;
    388     return false;
    389   }
    390 
    391   rtp_auth_tag_len_ = policy.rtp.auth_tag_len;
    392   rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len;
    393   return true;
    394 }
    395 
    396 bool SrtpSession::Init() {
    397   if (!inited_) {
    398     int err;
    399 #ifdef DEBUG_SRTP
    400     debug_on(mod_srtp);
    401 #endif
    402     err = srtp_init();
    403     if (err != err_status_ok) {
    404       LOG(LS_ERROR) << "Failed to init SRTP, err=" << err;
    405       return false;
    406     }
    407 
    408     err = srtp_install_event_handler(&SrtpSession::HandleEventThunk);
    409     if (err != err_status_ok) {
    410       LOG(LS_ERROR) << "Failed to install SRTP event handler, err=" << err;
    411       return false;
    412     }
    413 
    414     inited_ = true;
    415   }
    416 
    417   return true;
    418 }
    419 
    420 void SrtpSession::HandleEvent(const srtp_event_data_t* ev) {
    421   switch (ev->event) {
    422     case event_ssrc_collision:
    423       LOG(LS_INFO) << "SRTP event: SSRC collision";
    424       break;
    425     case event_key_soft_limit:
    426       LOG(LS_INFO) << "SRTP event: reached soft key usage limit";
    427       break;
    428     case event_key_hard_limit:
    429       LOG(LS_INFO) << "SRTP event: reached hard key usage limit";
    430       break;
    431     case event_packet_index_limit:
    432       LOG(LS_INFO) << "SRTP event: reached hard packet limit (2^48 packets)";
    433       break;
    434     default:
    435       LOG(LS_INFO) << "SRTP event: unknown " << ev->event;
    436       break;
    437   }
    438 }
    439 
    440 void SrtpSession::HandleEventThunk(srtp_event_data_t* ev) {
    441   for (std::list<SrtpSession*>::iterator it = sessions_.begin();
    442        it != sessions_.end(); ++it) {
    443     if ((*it)->session_ == ev->session) {
    444       (*it)->HandleEvent(ev);
    445       break;
    446     }
    447   }
    448 }
    449 
    450 #else   // !HAVE_SRTP
    451 
    452 namespace {
    453 bool SrtpNotAvailable(const char *func) {
    454   LOG(LS_ERROR) << func << ": SRTP is not available on your system.";
    455   return false;
    456 }
    457 }  // anonymous namespace
    458 
    459 SrtpSession::SrtpSession() {
    460   LOG(WARNING) << "SRTP implementation is missing.";
    461 }
    462 
    463 SrtpSession::~SrtpSession() {
    464 }
    465 
    466 bool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
    467   return SrtpNotAvailable(__FUNCTION__);
    468 }
    469 
    470 bool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
    471   return SrtpNotAvailable(__FUNCTION__);
    472 }
    473 
    474 bool SrtpSession::ProtectRtp(void* data, int in_len, int max_len,
    475                              int* out_len) {
    476   return SrtpNotAvailable(__FUNCTION__);
    477 }
    478 
    479 bool SrtpSession::ProtectRtcp(void* data, int in_len, int max_len,
    480                               int* out_len) {
    481   return SrtpNotAvailable(__FUNCTION__);
    482 }
    483 
    484 bool SrtpSession::UnprotectRtp(void* data, int in_len, int* out_len) {
    485   return SrtpNotAvailable(__FUNCTION__);
    486 }
    487 
    488 bool SrtpSession::UnprotectRtcp(void* data, int in_len, int* out_len) {
    489   return SrtpNotAvailable(__FUNCTION__);
    490 }
    491 
    492 #endif  // HAVE_SRTP
    493 }  // namespace cricket
    494