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