Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(263)

Side by Side Diff: webrtc/pc/srtpfilter.cc

Issue 1528843005: Add support for GCM cipher suites from RFC 7714. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Disable GCM if ENABLE_EXTERNAL_AUTH is defined. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/pc/srtpfilter.h ('k') | webrtc/pc/srtpfilter_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 #if !defined(ENABLE_EXTERNAL_AUTH)
689 // TODO(jbauch): Re-enable once https://crbug.com/628400 is resolved.
690 } else if (cs == rtc::SRTP_AEAD_AES_128_GCM) {
691 crypto_policy_set_aes_gcm_128_16_auth(&policy.rtp);
692 crypto_policy_set_aes_gcm_128_16_auth(&policy.rtcp);
693 } else if (cs == rtc::SRTP_AEAD_AES_256_GCM) {
694 crypto_policy_set_aes_gcm_256_16_auth(&policy.rtp);
695 crypto_policy_set_aes_gcm_256_16_auth(&policy.rtcp);
696 #endif // ENABLE_EXTERNAL_AUTH
670 } else { 697 } else {
671 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported" 698 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported"
672 << " cipher_suite " << cs; 699 << " cipher_suite " << cs;
673 return false; 700 return false;
674 } 701 }
675 702
676 if (!key || len != SRTP_MASTER_KEY_LEN) { 703 int expected_key_len;
704 int expected_salt_len;
705 if (!rtc::GetSrtpKeyAndSaltLengths(cs, &expected_key_len,
706 &expected_salt_len)) {
707 // This should never happen.
708 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported"
709 << " cipher_suite without length information" << cs;
710 return false;
711 }
712
713 if (!key ||
714 len != static_cast<size_t>(expected_key_len + expected_salt_len)) {
677 LOG(LS_WARNING) << "Failed to create SRTP session: invalid key"; 715 LOG(LS_WARNING) << "Failed to create SRTP session: invalid key";
678 return false; 716 return false;
679 } 717 }
680 718
681 policy.ssrc.type = static_cast<ssrc_type_t>(type); 719 policy.ssrc.type = static_cast<ssrc_type_t>(type);
682 policy.ssrc.value = 0; 720 policy.ssrc.value = 0;
683 policy.key = const_cast<uint8_t*>(key); 721 policy.key = const_cast<uint8_t*>(key);
684 // TODO(astor) parse window size from WSH session-param 722 // TODO(astor) parse window size from WSH session-param
685 policy.window_size = 1024; 723 policy.window_size = 1024;
686 policy.allow_repeat_tx = 1; 724 policy.allow_repeat_tx = 1;
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 SrtpNotAvailable(__FUNCTION__); 960 SrtpNotAvailable(__FUNCTION__);
923 } 961 }
924 962
925 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) { 963 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
926 SrtpNotAvailable(__FUNCTION__); 964 SrtpNotAvailable(__FUNCTION__);
927 } 965 }
928 966
929 #endif // HAVE_SRTP 967 #endif // HAVE_SRTP
930 968
931 } // namespace cricket 969 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/pc/srtpfilter.h ('k') | webrtc/pc/srtpfilter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698