Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2009 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2009 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/pc/srtpfilter.h" | 11 #include "webrtc/pc/srtpfilter.h" |
| 12 | 12 |
| 13 #include <string.h> | 13 #include <string.h> |
| 14 | 14 |
| 15 #include <algorithm> | 15 #include <algorithm> |
| 16 | 16 |
| 17 #include "webrtc/base/base64.h" | 17 #include "webrtc/base/base64.h" |
| 18 #include "webrtc/base/buffer.h" | |
| 18 #include "webrtc/base/byteorder.h" | 19 #include "webrtc/base/byteorder.h" |
| 19 #include "webrtc/base/checks.h" | 20 #include "webrtc/base/checks.h" |
| 20 #include "webrtc/base/common.h" | 21 #include "webrtc/base/common.h" |
| 21 #include "webrtc/base/logging.h" | 22 #include "webrtc/base/logging.h" |
| 22 #include "webrtc/base/stringencode.h" | 23 #include "webrtc/base/stringencode.h" |
| 23 #include "webrtc/base/timeutils.h" | 24 #include "webrtc/base/timeutils.h" |
| 24 #include "webrtc/media/base/rtputils.h" | 25 #include "webrtc/media/base/rtputils.h" |
| 25 | 26 |
| 26 // Enable this line to turn on SRTP debugging | 27 // Enable this line to turn on SRTP debugging |
| 27 // #define SRTP_DEBUG | 28 // #define SRTP_DEBUG |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 41 #endif // ENABLE_EXTERNAL_AUTH | 42 #endif // ENABLE_EXTERNAL_AUTH |
| 42 #if !defined(NDEBUG) | 43 #if !defined(NDEBUG) |
| 43 extern "C" debug_module_t mod_srtp; | 44 extern "C" debug_module_t mod_srtp; |
| 44 extern "C" debug_module_t mod_auth; | 45 extern "C" debug_module_t mod_auth; |
| 45 extern "C" debug_module_t mod_cipher; | 46 extern "C" debug_module_t mod_cipher; |
| 46 extern "C" debug_module_t mod_stat; | 47 extern "C" debug_module_t mod_stat; |
| 47 extern "C" debug_module_t mod_alloc; | 48 extern "C" debug_module_t mod_alloc; |
| 48 extern "C" debug_module_t mod_aes_icm; | 49 extern "C" debug_module_t mod_aes_icm; |
| 49 extern "C" debug_module_t mod_aes_hmac; | 50 extern "C" debug_module_t mod_aes_hmac; |
| 50 #endif | 51 #endif |
| 51 #else | |
| 52 // SrtpFilter needs that constant. | |
| 53 #define SRTP_MASTER_KEY_LEN 30 | |
| 54 #endif // HAVE_SRTP | 52 #endif // HAVE_SRTP |
| 55 | 53 |
| 56 namespace cricket { | 54 namespace cricket { |
| 57 | 55 |
| 58 const int SRTP_MASTER_KEY_BASE64_LEN = SRTP_MASTER_KEY_LEN * 4 / 3; | |
| 59 const int SRTP_MASTER_KEY_KEY_LEN = 16; | |
| 60 const int SRTP_MASTER_KEY_SALT_LEN = 14; | |
| 61 | |
| 62 #ifndef HAVE_SRTP | 56 #ifndef HAVE_SRTP |
| 63 | 57 |
| 64 // This helper function is used on systems that don't (yet) have SRTP, | 58 // This helper function is used on systems that don't (yet) have SRTP, |
| 65 // to log that the functions that require it won't do anything. | 59 // to log that the functions that require it won't do anything. |
| 66 namespace { | 60 namespace { |
| 67 bool SrtpNotAvailable(const char *func) { | 61 bool SrtpNotAvailable(const char *func) { |
| 68 LOG(LS_ERROR) << func << ": SRTP is not available on your system."; | 62 LOG(LS_ERROR) << func << ": SRTP is not available on your system."; |
| 69 return false; | 63 return false; |
| 70 } | 64 } |
| 71 } // anonymous namespace | 65 } // anonymous namespace |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 // CryptoParams is unchanged. | 390 // CryptoParams is unchanged. |
| 397 if (applied_send_params_.cipher_suite == send_params.cipher_suite && | 391 if (applied_send_params_.cipher_suite == send_params.cipher_suite && |
| 398 applied_send_params_.key_params == send_params.key_params && | 392 applied_send_params_.key_params == send_params.key_params && |
| 399 applied_recv_params_.cipher_suite == recv_params.cipher_suite && | 393 applied_recv_params_.cipher_suite == recv_params.cipher_suite && |
| 400 applied_recv_params_.key_params == recv_params.key_params) { | 394 applied_recv_params_.key_params == recv_params.key_params) { |
| 401 LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op."; | 395 LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op."; |
| 402 | 396 |
| 403 // We do not want to reset the ROC if the keys are the same. So just return. | 397 // We do not want to reset the ROC if the keys are the same. So just return. |
| 404 return true; | 398 return true; |
| 405 } | 399 } |
| 400 | |
| 401 int send_suite = rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite); | |
| 402 int recv_suite = rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite); | |
| 403 if (send_suite == rtc::SRTP_INVALID_CRYPTO_SUITE || | |
| 404 recv_suite == rtc::SRTP_INVALID_CRYPTO_SUITE) { | |
| 405 LOG(LS_WARNING) << "Unknown crypto suite(s) received:" | |
| 406 << " send cipher_suite " << send_params.cipher_suite | |
| 407 << " recv cipher_suite " << recv_params.cipher_suite; | |
| 408 return false; | |
| 409 } | |
| 410 | |
| 411 int send_key_len, send_salt_len; | |
| 412 int recv_key_len, recv_salt_len; | |
| 413 if (!rtc::GetSrtpKeyAndSaltLengths(send_suite, &send_key_len, | |
| 414 &send_salt_len) || | |
| 415 !rtc::GetSrtpKeyAndSaltLengths(recv_suite, &recv_key_len, | |
| 416 &recv_salt_len)) { | |
| 417 LOG(LS_WARNING) << "Could not get lengths for crypto suite(s):" | |
| 418 << " send cipher_suite " << send_params.cipher_suite | |
| 419 << " recv cipher_suite " << recv_params.cipher_suite; | |
| 420 return false; | |
| 421 } | |
| 422 | |
| 406 // TODO(juberti): Zero these buffers after use. | 423 // TODO(juberti): Zero these buffers after use. |
| 407 bool ret; | 424 bool ret; |
| 408 uint8_t send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN]; | 425 rtc::Buffer send_key(send_key_len + send_salt_len); |
| 409 ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) && | 426 rtc::Buffer recv_key(recv_key_len + recv_salt_len); |
| 410 ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key))); | 427 ret = (ParseKeyParams(send_params.key_params, send_key.data(), |
| 428 send_key.size()) && | |
| 429 ParseKeyParams(recv_params.key_params, recv_key.data(), | |
| 430 recv_key.size())); | |
| 411 if (ret) { | 431 if (ret) { |
| 412 CreateSrtpSessions(); | 432 CreateSrtpSessions(); |
| 413 ret = (send_session_->SetSend( | 433 ret = (send_session_->SetSend( |
| 414 rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite), send_key, | 434 rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite), |
| 415 sizeof(send_key)) && | 435 send_key.data(), send_key.size()) && |
| 416 recv_session_->SetRecv( | 436 recv_session_->SetRecv( |
| 417 rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite), recv_key, | 437 rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite), |
| 418 sizeof(recv_key))); | 438 recv_key.data(), recv_key.size())); |
| 419 } | 439 } |
| 420 if (ret) { | 440 if (ret) { |
| 421 LOG(LS_INFO) << "SRTP activated with negotiated parameters:" | 441 LOG(LS_INFO) << "SRTP activated with negotiated parameters:" |
| 422 << " send cipher_suite " << send_params.cipher_suite | 442 << " send cipher_suite " << send_params.cipher_suite |
| 423 << " recv cipher_suite " << recv_params.cipher_suite; | 443 << " recv cipher_suite " << recv_params.cipher_suite; |
| 424 applied_send_params_ = send_params; | 444 applied_send_params_ = send_params; |
| 425 applied_recv_params_ = recv_params; | 445 applied_recv_params_ = recv_params; |
| 426 } else { | 446 } else { |
| 427 LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters"; | 447 LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters"; |
| 428 } | 448 } |
| 429 return ret; | 449 return ret; |
| 430 } | 450 } |
| 431 | 451 |
| 432 bool SrtpFilter::ResetParams() { | 452 bool SrtpFilter::ResetParams() { |
| 433 offer_params_.clear(); | 453 offer_params_.clear(); |
| 434 state_ = ST_INIT; | 454 state_ = ST_INIT; |
| 435 send_session_ = nullptr; | 455 send_session_ = nullptr; |
| 436 recv_session_ = nullptr; | 456 recv_session_ = nullptr; |
| 437 send_rtcp_session_ = nullptr; | 457 send_rtcp_session_ = nullptr; |
| 438 recv_rtcp_session_ = nullptr; | 458 recv_rtcp_session_ = nullptr; |
| 439 LOG(LS_INFO) << "SRTP reset to init state"; | 459 LOG(LS_INFO) << "SRTP reset to init state"; |
| 440 return true; | 460 return true; |
| 441 } | 461 } |
| 442 | 462 |
| 443 bool SrtpFilter::ParseKeyParams(const std::string& key_params, | 463 bool SrtpFilter::ParseKeyParams(const std::string& key_params, |
| 444 uint8_t* key, | 464 uint8_t* key, |
| 445 int len) { | 465 size_t len) { |
| 446 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2" | 466 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2" |
| 447 | 467 |
| 448 // Fail if key-method is wrong. | 468 // Fail if key-method is wrong. |
| 449 if (key_params.find("inline:") != 0) { | 469 if (key_params.find("inline:") != 0) { |
| 450 return false; | 470 return false; |
| 451 } | 471 } |
| 452 | 472 |
| 453 // Fail if base64 decode fails, or the key is the wrong size. | 473 // Fail if base64 decode fails, or the key is the wrong size. |
| 454 std::string key_b64(key_params.substr(7)), key_str; | 474 std::string key_b64(key_params.substr(7)), key_str; |
| 455 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, | 475 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, |
| 456 &key_str, nullptr) || | 476 &key_str, nullptr) || key_str.size() != len) { |
| 457 static_cast<int>(key_str.size()) != len) { | |
| 458 return false; | 477 return false; |
| 459 } | 478 } |
| 460 | 479 |
| 461 memcpy(key, key_str.c_str(), len); | 480 memcpy(key, key_str.c_str(), len); |
| 462 return true; | 481 return true; |
| 463 } | 482 } |
| 464 | 483 |
| 465 /////////////////////////////////////////////////////////////////////////////// | 484 /////////////////////////////////////////////////////////////////////////////// |
| 466 // SrtpSession | 485 // SrtpSession |
| 467 | 486 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 481 SignalSrtpError.repeat(srtp_stat_->SignalSrtpError); | 500 SignalSrtpError.repeat(srtp_stat_->SignalSrtpError); |
| 482 } | 501 } |
| 483 | 502 |
| 484 SrtpSession::~SrtpSession() { | 503 SrtpSession::~SrtpSession() { |
| 485 if (session_) { | 504 if (session_) { |
| 486 srtp_set_user_data(session_, nullptr); | 505 srtp_set_user_data(session_, nullptr); |
| 487 srtp_dealloc(session_); | 506 srtp_dealloc(session_); |
| 488 } | 507 } |
| 489 } | 508 } |
| 490 | 509 |
| 491 bool SrtpSession::SetSend(int cs, const uint8_t* key, int len) { | 510 bool SrtpSession::SetSend(int cs, const uint8_t* key, size_t len) { |
| 492 return SetKey(ssrc_any_outbound, cs, key, len); | 511 return SetKey(ssrc_any_outbound, cs, key, len); |
| 493 } | 512 } |
| 494 | 513 |
| 495 bool SrtpSession::SetRecv(int cs, const uint8_t* key, int len) { | 514 bool SrtpSession::SetRecv(int cs, const uint8_t* key, size_t len) { |
| 496 return SetKey(ssrc_any_inbound, cs, key, len); | 515 return SetKey(ssrc_any_inbound, cs, key, len); |
| 497 } | 516 } |
| 498 | 517 |
| 499 bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) { | 518 bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) { |
| 500 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 519 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 501 if (!session_) { | 520 if (!session_) { |
| 502 LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session"; | 521 LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session"; |
| 503 return false; | 522 return false; |
| 504 } | 523 } |
| 505 | 524 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 639 // Shift packet index, put into network byte order | 658 // Shift packet index, put into network byte order |
| 640 *index = static_cast<int64_t>( | 659 *index = static_cast<int64_t>( |
| 641 rtc::NetworkToHost64(rdbx_get_packet_index(&stream->rtp_rdbx) << 16)); | 660 rtc::NetworkToHost64(rdbx_get_packet_index(&stream->rtp_rdbx) << 16)); |
| 642 return true; | 661 return true; |
| 643 } | 662 } |
| 644 | 663 |
| 645 void SrtpSession::set_signal_silent_time(int signal_silent_time_in_ms) { | 664 void SrtpSession::set_signal_silent_time(int signal_silent_time_in_ms) { |
| 646 srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms); | 665 srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms); |
| 647 } | 666 } |
| 648 | 667 |
| 649 bool SrtpSession::SetKey(int type, int cs, const uint8_t* key, int len) { | 668 bool SrtpSession::SetKey(int type, int cs, const uint8_t* key, size_t len) { |
| 650 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 669 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 651 if (session_) { | 670 if (session_) { |
| 652 LOG(LS_ERROR) << "Failed to create SRTP session: " | 671 LOG(LS_ERROR) << "Failed to create SRTP session: " |
| 653 << "SRTP session already created"; | 672 << "SRTP session already created"; |
| 654 return false; | 673 return false; |
| 655 } | 674 } |
| 656 | 675 |
| 657 if (!Init()) { | 676 if (!Init()) { |
| 658 return false; | 677 return false; |
| 659 } | 678 } |
| 660 | 679 |
| 661 srtp_policy_t policy; | 680 srtp_policy_t policy; |
| 662 memset(&policy, 0, sizeof(policy)); | 681 memset(&policy, 0, sizeof(policy)); |
| 663 | |
| 664 if (cs == rtc::SRTP_AES128_CM_SHA1_80) { | 682 if (cs == rtc::SRTP_AES128_CM_SHA1_80) { |
| 665 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); | 683 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); |
| 666 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); | 684 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); |
| 667 } else if (cs == rtc::SRTP_AES128_CM_SHA1_32) { | 685 } else if (cs == rtc::SRTP_AES128_CM_SHA1_32) { |
| 668 crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); // rtp is 32, | 686 crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); // rtp is 32, |
| 669 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // rtcp still 80 | 687 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // rtcp still 80 |
| 688 } else if (cs == rtc::SRTP_AEAD_AES_128_GCM) { | |
| 689 crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); | |
| 690 crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); | |
| 691 } else if (cs == rtc::SRTP_AEAD_AES_256_GCM) { | |
| 692 crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp); | |
| 693 crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp); | |
| 670 } else { | 694 } else { |
| 671 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported" | 695 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported" |
| 672 << " cipher_suite " << cs; | 696 << " cipher_suite " << cs; |
| 673 return false; | 697 return false; |
| 674 } | 698 } |
| 675 | 699 |
| 676 if (!key || len != SRTP_MASTER_KEY_LEN) { | 700 int expected_key_len; |
| 701 int expected_salt_len; | |
| 702 if (!rtc::GetSrtpKeyAndSaltLengths(cs, &expected_key_len, | |
| 703 &expected_salt_len)) { | |
| 704 // This should never happen. | |
| 705 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported" | |
| 706 << " cipher_suite without length information" << cs; | |
| 707 return false; | |
| 708 } | |
| 709 | |
| 710 if (!key || | |
| 711 len != static_cast<size_t>(expected_key_len + expected_salt_len)) { | |
| 677 LOG(LS_WARNING) << "Failed to create SRTP session: invalid key"; | 712 LOG(LS_WARNING) << "Failed to create SRTP session: invalid key"; |
| 678 return false; | 713 return false; |
| 679 } | 714 } |
| 680 | 715 |
| 681 policy.ssrc.type = static_cast<ssrc_type_t>(type); | 716 policy.ssrc.type = static_cast<ssrc_type_t>(type); |
| 682 policy.ssrc.value = 0; | 717 policy.ssrc.value = 0; |
| 683 policy.key = const_cast<uint8_t*>(key); | 718 policy.key = const_cast<uint8_t*>(key); |
| 684 // TODO(astor) parse window size from WSH session-param | 719 // TODO(astor) parse window size from WSH session-param |
| 685 policy.window_size = 1024; | 720 policy.window_size = 1024; |
| 686 policy.allow_repeat_tx = 1; | 721 policy.allow_repeat_tx = 1; |
| 687 // If external authentication option is enabled, supply custom auth module | 722 // If external authentication option is enabled, supply custom auth module |
| 688 // id EXTERNAL_HMAC_SHA1 in the policy structure. | 723 // id EXTERNAL_HMAC_SHA1 in the policy structure. |
| 689 // We want to set this option only for rtp packets. | 724 // We want to set this option only for rtp packets. |
| 690 // By default policy structure is initialized to HMAC_SHA1. | 725 // By default policy structure is initialized to HMAC_SHA1. |
| 691 #if defined(ENABLE_EXTERNAL_AUTH) | 726 #if defined(ENABLE_EXTERNAL_AUTH) |
| 692 // Enable external HMAC authentication only for outgoing streams. | 727 // Enable external HMAC authentication only for outgoing streams. |
| 693 if (type == ssrc_any_outbound) { | 728 if (type == ssrc_any_outbound) { |
| 694 policy.rtp.auth_type = EXTERNAL_HMAC_SHA1; | 729 policy.rtp.auth_type = EXTERNAL_HMAC_SHA1; |
|
mattdr-at-webrtc.org
2016/07/14 20:39:51
I had to read code near here for some other purpos
mattdr-at-webrtc.org
2016/07/14 20:43:22
... and should this have come up in testing?
note
| |
| 695 } | 730 } |
| 696 #endif | 731 #endif |
| 697 policy.next = nullptr; | 732 policy.next = nullptr; |
| 698 | 733 |
| 699 int err = srtp_create(&session_, &policy); | 734 int err = srtp_create(&session_, &policy); |
| 700 if (err != err_status_ok) { | 735 if (err != err_status_ok) { |
| 701 session_ = nullptr; | 736 session_ = nullptr; |
| 702 LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err; | 737 LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err; |
| 703 return false; | 738 return false; |
| 704 } | 739 } |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 922 SrtpNotAvailable(__FUNCTION__); | 957 SrtpNotAvailable(__FUNCTION__); |
| 923 } | 958 } |
| 924 | 959 |
| 925 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) { | 960 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) { |
| 926 SrtpNotAvailable(__FUNCTION__); | 961 SrtpNotAvailable(__FUNCTION__); |
| 927 } | 962 } |
| 928 | 963 |
| 929 #endif // HAVE_SRTP | 964 #endif // HAVE_SRTP |
| 930 | 965 |
| 931 } // namespace cricket | 966 } // namespace cricket |
| OLD | NEW |