| 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/common.h" | 20 #include "webrtc/base/common.h" |
| 20 #include "webrtc/base/logging.h" | 21 #include "webrtc/base/logging.h" |
| 21 #include "webrtc/base/stringencode.h" | 22 #include "webrtc/base/stringencode.h" |
| 22 #include "webrtc/base/timeutils.h" | 23 #include "webrtc/base/timeutils.h" |
| 23 #include "webrtc/media/base/rtputils.h" | 24 #include "webrtc/media/base/rtputils.h" |
| 24 | 25 |
| 25 // Enable this line to turn on SRTP debugging | 26 // Enable this line to turn on SRTP debugging |
| 26 // #define SRTP_DEBUG | 27 // #define SRTP_DEBUG |
| 27 | 28 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 40 #endif // ENABLE_EXTERNAL_AUTH | 41 #endif // ENABLE_EXTERNAL_AUTH |
| 41 #if !defined(NDEBUG) | 42 #if !defined(NDEBUG) |
| 42 extern "C" debug_module_t mod_srtp; | 43 extern "C" debug_module_t mod_srtp; |
| 43 extern "C" debug_module_t mod_auth; | 44 extern "C" debug_module_t mod_auth; |
| 44 extern "C" debug_module_t mod_cipher; | 45 extern "C" debug_module_t mod_cipher; |
| 45 extern "C" debug_module_t mod_stat; | 46 extern "C" debug_module_t mod_stat; |
| 46 extern "C" debug_module_t mod_alloc; | 47 extern "C" debug_module_t mod_alloc; |
| 47 extern "C" debug_module_t mod_aes_icm; | 48 extern "C" debug_module_t mod_aes_icm; |
| 48 extern "C" debug_module_t mod_aes_hmac; | 49 extern "C" debug_module_t mod_aes_hmac; |
| 49 #endif | 50 #endif |
| 50 #else | |
| 51 // SrtpFilter needs that constant. | |
| 52 #define SRTP_MASTER_KEY_LEN 30 | |
| 53 #endif // HAVE_SRTP | 51 #endif // HAVE_SRTP |
| 54 | 52 |
| 55 namespace cricket { | 53 namespace cricket { |
| 56 | 54 |
| 57 const int SRTP_MASTER_KEY_BASE64_LEN = SRTP_MASTER_KEY_LEN * 4 / 3; | |
| 58 const int SRTP_MASTER_KEY_KEY_LEN = 16; | |
| 59 const int SRTP_MASTER_KEY_SALT_LEN = 14; | |
| 60 | |
| 61 #ifndef HAVE_SRTP | 55 #ifndef HAVE_SRTP |
| 62 | 56 |
| 63 // This helper function is used on systems that don't (yet) have SRTP, | 57 // This helper function is used on systems that don't (yet) have SRTP, |
| 64 // to log that the functions that require it won't do anything. | 58 // to log that the functions that require it won't do anything. |
| 65 namespace { | 59 namespace { |
| 66 bool SrtpNotAvailable(const char *func) { | 60 bool SrtpNotAvailable(const char *func) { |
| 67 LOG(LS_ERROR) << func << ": SRTP is not available on your system."; | 61 LOG(LS_ERROR) << func << ": SRTP is not available on your system."; |
| 68 return false; | 62 return false; |
| 69 } | 63 } |
| 70 } // anonymous namespace | 64 } // anonymous namespace |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 // CryptoParams is unchanged. | 389 // CryptoParams is unchanged. |
| 396 if (applied_send_params_.cipher_suite == send_params.cipher_suite && | 390 if (applied_send_params_.cipher_suite == send_params.cipher_suite && |
| 397 applied_send_params_.key_params == send_params.key_params && | 391 applied_send_params_.key_params == send_params.key_params && |
| 398 applied_recv_params_.cipher_suite == recv_params.cipher_suite && | 392 applied_recv_params_.cipher_suite == recv_params.cipher_suite && |
| 399 applied_recv_params_.key_params == recv_params.key_params) { | 393 applied_recv_params_.key_params == recv_params.key_params) { |
| 400 LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op."; | 394 LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op."; |
| 401 | 395 |
| 402 // We do not want to reset the ROC if the keys are the same. So just return. | 396 // We do not want to reset the ROC if the keys are the same. So just return. |
| 403 return true; | 397 return true; |
| 404 } | 398 } |
| 399 |
| 400 int send_suite = rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite); |
| 401 int recv_suite = rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite); |
| 402 if (send_suite == rtc::SRTP_INVALID_CRYPTO_SUITE || |
| 403 recv_suite == rtc::SRTP_INVALID_CRYPTO_SUITE) { |
| 404 LOG(LS_WARNING) << "Unknown crypto suite(s) received:" |
| 405 << " send cipher_suite " << send_params.cipher_suite |
| 406 << " recv cipher_suite " << recv_params.cipher_suite; |
| 407 return false; |
| 408 } |
| 409 |
| 410 int send_key_len, send_salt_len; |
| 411 int recv_key_len, recv_salt_len; |
| 412 if (!rtc::GetSrtpKeyAndSaltLengths(send_suite, &send_key_len, |
| 413 &send_salt_len) || |
| 414 !rtc::GetSrtpKeyAndSaltLengths(recv_suite, &recv_key_len, |
| 415 &recv_salt_len)) { |
| 416 LOG(LS_WARNING) << "Could not get lengths for crypto suite(s):" |
| 417 << " send cipher_suite " << send_params.cipher_suite |
| 418 << " recv cipher_suite " << recv_params.cipher_suite; |
| 419 return false; |
| 420 } |
| 421 |
| 405 // TODO(juberti): Zero these buffers after use. | 422 // TODO(juberti): Zero these buffers after use. |
| 406 bool ret; | 423 bool ret; |
| 407 uint8_t send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN]; | 424 rtc::Buffer send_key(send_key_len + send_salt_len); |
| 408 ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) && | 425 rtc::Buffer recv_key(recv_key_len + recv_salt_len); |
| 409 ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key))); | 426 ret = (ParseKeyParams(send_params.key_params, send_key.data(), |
| 427 send_key.size()) && |
| 428 ParseKeyParams(recv_params.key_params, recv_key.data(), |
| 429 recv_key.size())); |
| 410 if (ret) { | 430 if (ret) { |
| 411 CreateSrtpSessions(); | 431 CreateSrtpSessions(); |
| 412 ret = (send_session_->SetSend( | 432 ret = (send_session_->SetSend( |
| 413 rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite), send_key, | 433 rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite), |
| 414 sizeof(send_key)) && | 434 send_key.data(), send_key.size()) && |
| 415 recv_session_->SetRecv( | 435 recv_session_->SetRecv( |
| 416 rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite), recv_key, | 436 rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite), |
| 417 sizeof(recv_key))); | 437 recv_key.data(), recv_key.size())); |
| 418 } | 438 } |
| 419 if (ret) { | 439 if (ret) { |
| 420 LOG(LS_INFO) << "SRTP activated with negotiated parameters:" | 440 LOG(LS_INFO) << "SRTP activated with negotiated parameters:" |
| 421 << " send cipher_suite " << send_params.cipher_suite | 441 << " send cipher_suite " << send_params.cipher_suite |
| 422 << " recv cipher_suite " << recv_params.cipher_suite; | 442 << " recv cipher_suite " << recv_params.cipher_suite; |
| 423 applied_send_params_ = send_params; | 443 applied_send_params_ = send_params; |
| 424 applied_recv_params_ = recv_params; | 444 applied_recv_params_ = recv_params; |
| 425 } else { | 445 } else { |
| 426 LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters"; | 446 LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters"; |
| 427 } | 447 } |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 << "SRTP session already created"; | 671 << "SRTP session already created"; |
| 652 return false; | 672 return false; |
| 653 } | 673 } |
| 654 | 674 |
| 655 if (!Init()) { | 675 if (!Init()) { |
| 656 return false; | 676 return false; |
| 657 } | 677 } |
| 658 | 678 |
| 659 srtp_policy_t policy; | 679 srtp_policy_t policy; |
| 660 memset(&policy, 0, sizeof(policy)); | 680 memset(&policy, 0, sizeof(policy)); |
| 661 | |
| 662 if (cs == rtc::SRTP_AES128_CM_SHA1_80) { | 681 if (cs == rtc::SRTP_AES128_CM_SHA1_80) { |
| 663 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); | 682 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); |
| 664 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); | 683 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); |
| 665 } else if (cs == rtc::SRTP_AES128_CM_SHA1_32) { | 684 } else if (cs == rtc::SRTP_AES128_CM_SHA1_32) { |
| 666 crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); // rtp is 32, | 685 crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); // rtp is 32, |
| 667 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // rtcp still 80 | 686 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // rtcp still 80 |
| 687 } else if (cs == rtc::SRTP_AEAD_AES_128_GCM) { |
| 688 crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp); |
| 689 crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp); |
| 690 } else if (cs == rtc::SRTP_AEAD_AES_256_GCM) { |
| 691 crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp); |
| 692 crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp); |
| 668 } else { | 693 } else { |
| 669 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported" | 694 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported" |
| 670 << " cipher_suite " << cs; | 695 << " cipher_suite " << cs; |
| 671 return false; | 696 return false; |
| 672 } | 697 } |
| 673 | 698 |
| 674 if (!key || len != SRTP_MASTER_KEY_LEN) { | 699 int expected_key_len; |
| 700 int expected_salt_len; |
| 701 if (!rtc::GetSrtpKeyAndSaltLengths(cs, &expected_key_len, |
| 702 &expected_salt_len)) { |
| 703 // This should never happen. |
| 704 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported" |
| 705 << " cipher_suite without length information" << cs; |
| 706 return false; |
| 707 } |
| 708 |
| 709 if (!key || len != (expected_key_len + expected_salt_len)) { |
| 675 LOG(LS_WARNING) << "Failed to create SRTP session: invalid key"; | 710 LOG(LS_WARNING) << "Failed to create SRTP session: invalid key"; |
| 676 return false; | 711 return false; |
| 677 } | 712 } |
| 678 | 713 |
| 679 policy.ssrc.type = static_cast<ssrc_type_t>(type); | 714 policy.ssrc.type = static_cast<ssrc_type_t>(type); |
| 680 policy.ssrc.value = 0; | 715 policy.ssrc.value = 0; |
| 681 policy.key = const_cast<uint8_t*>(key); | 716 policy.key = const_cast<uint8_t*>(key); |
| 682 // TODO(astor) parse window size from WSH session-param | 717 // TODO(astor) parse window size from WSH session-param |
| 683 policy.window_size = 1024; | 718 policy.window_size = 1024; |
| 684 policy.allow_repeat_tx = 1; | 719 policy.allow_repeat_tx = 1; |
| 685 // If external authentication option is enabled, supply custom auth module | 720 // If external authentication option is enabled, supply custom auth module |
| 686 // id EXTERNAL_HMAC_SHA1 in the policy structure. | 721 // id EXTERNAL_HMAC_SHA1 in the policy structure. |
| 687 // We want to set this option only for rtp packets. | 722 // We want to set this option only for rtp packets. |
| 688 // By default policy structure is initialized to HMAC_SHA1. | 723 // By default policy structure is initialized to HMAC_SHA1. |
| 689 #if defined(ENABLE_EXTERNAL_AUTH) | 724 #if defined(ENABLE_EXTERNAL_AUTH) |
| 690 // Enable external HMAC authentication only for outgoing streams. | 725 // Enable external HMAC authentication only for outgoing streams. |
| 691 if (type == ssrc_any_outbound) { | 726 if (type == ssrc_any_outbound) { |
| 692 policy.rtp.auth_type = EXTERNAL_HMAC_SHA1; | 727 policy.rtp.auth_type = EXTERNAL_HMAC_SHA1; |
| 693 } | 728 } |
| 694 #endif | 729 #endif |
| 695 policy.next = NULL; | 730 policy.next = NULL; |
| 696 | 731 |
| 697 int err = srtp_create(&session_, &policy); | 732 int err = srtp_create(&session_, &policy); |
| 698 if (err != err_status_ok) { | 733 if (err != err_status_ok) { |
| 699 session_ = NULL; | 734 session_ = NULL; |
| 700 LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err; | 735 LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err; |
| 701 return false; | 736 return false; |
| 702 } | 737 } |
| 703 | 738 |
| 704 | |
| 705 rtp_auth_tag_len_ = policy.rtp.auth_tag_len; | 739 rtp_auth_tag_len_ = policy.rtp.auth_tag_len; |
| 706 rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len; | 740 rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len; |
| 707 return true; | 741 return true; |
| 708 } | 742 } |
| 709 | 743 |
| 710 bool SrtpSession::Init() { | 744 bool SrtpSession::Init() { |
| 711 rtc::GlobalLockScope ls(&lock_); | 745 rtc::GlobalLockScope ls(&lock_); |
| 712 | 746 |
| 713 if (!inited_) { | 747 if (!inited_) { |
| 714 int err; | 748 int err; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 SrtpNotAvailable(__FUNCTION__); | 960 SrtpNotAvailable(__FUNCTION__); |
| 927 } | 961 } |
| 928 | 962 |
| 929 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) { | 963 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) { |
| 930 SrtpNotAvailable(__FUNCTION__); | 964 SrtpNotAvailable(__FUNCTION__); |
| 931 } | 965 } |
| 932 | 966 |
| 933 #endif // HAVE_SRTP | 967 #endif // HAVE_SRTP |
| 934 | 968 |
| 935 } // namespace cricket | 969 } // namespace cricket |
| OLD | NEW |