| OLD | NEW |
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2009 Google Inc. | 3 * Copyright 2009 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 return true; | 474 return true; |
| 475 } | 475 } |
| 476 | 476 |
| 477 /////////////////////////////////////////////////////////////////////////////// | 477 /////////////////////////////////////////////////////////////////////////////// |
| 478 // SrtpSession | 478 // SrtpSession |
| 479 | 479 |
| 480 #ifdef HAVE_SRTP | 480 #ifdef HAVE_SRTP |
| 481 | 481 |
| 482 bool SrtpSession::inited_ = false; | 482 bool SrtpSession::inited_ = false; |
| 483 | 483 |
| 484 // This lock protects SrtpSession::inited_ and SrtpSession::sessions_. | 484 // This lock protects SrtpSession::inited_. |
| 485 rtc::GlobalLockPod SrtpSession::lock_; | 485 rtc::GlobalLockPod SrtpSession::lock_; |
| 486 | 486 |
| 487 SrtpSession::SrtpSession() | 487 SrtpSession::SrtpSession() |
| 488 : session_(NULL), | 488 : session_(NULL), |
| 489 rtp_auth_tag_len_(0), | 489 rtp_auth_tag_len_(0), |
| 490 rtcp_auth_tag_len_(0), | 490 rtcp_auth_tag_len_(0), |
| 491 srtp_stat_(new SrtpStat()), | 491 srtp_stat_(new SrtpStat()), |
| 492 last_send_seq_num_(-1) { | 492 last_send_seq_num_(-1) { |
| 493 { | |
| 494 rtc::GlobalLockScope ls(&lock_); | |
| 495 sessions()->push_back(this); | |
| 496 } | |
| 497 SignalSrtpError.repeat(srtp_stat_->SignalSrtpError); | 493 SignalSrtpError.repeat(srtp_stat_->SignalSrtpError); |
| 498 } | 494 } |
| 499 | 495 |
| 500 SrtpSession::~SrtpSession() { | 496 SrtpSession::~SrtpSession() { |
| 501 { | 497 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 502 rtc::GlobalLockScope ls(&lock_); | |
| 503 sessions()->erase(std::find(sessions()->begin(), sessions()->end(), this)); | |
| 504 } | |
| 505 if (session_) { | 498 if (session_) { |
| 499 session_->user_data = nullptr; |
| 506 srtp_dealloc(session_); | 500 srtp_dealloc(session_); |
| 507 } | 501 } |
| 508 } | 502 } |
| 509 | 503 |
| 510 bool SrtpSession::SetSend(const std::string& cs, const uint8_t* key, int len) { | 504 bool SrtpSession::SetSend(const std::string& cs, const uint8_t* key, int len) { |
| 511 return SetKey(ssrc_any_outbound, cs, key, len); | 505 return SetKey(ssrc_any_outbound, cs, key, len); |
| 512 } | 506 } |
| 513 | 507 |
| 514 bool SrtpSession::SetRecv(const std::string& cs, const uint8_t* key, int len) { | 508 bool SrtpSession::SetRecv(const std::string& cs, const uint8_t* key, int len) { |
| 515 return SetKey(ssrc_any_inbound, cs, key, len); | 509 return SetKey(ssrc_any_inbound, cs, key, len); |
| 516 } | 510 } |
| 517 | 511 |
| 518 bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) { | 512 bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) { |
| 513 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 519 if (!session_) { | 514 if (!session_) { |
| 520 LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session"; | 515 LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session"; |
| 521 return false; | 516 return false; |
| 522 } | 517 } |
| 523 | 518 |
| 524 int need_len = in_len + rtp_auth_tag_len_; // NOLINT | 519 int need_len = in_len + rtp_auth_tag_len_; // NOLINT |
| 525 if (max_len < need_len) { | 520 if (max_len < need_len) { |
| 526 LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length " | 521 LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length " |
| 527 << max_len << " is less than the needed " << need_len; | 522 << max_len << " is less than the needed " << need_len; |
| 528 return false; | 523 return false; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 551 int max_len, | 546 int max_len, |
| 552 int* out_len, | 547 int* out_len, |
| 553 int64_t* index) { | 548 int64_t* index) { |
| 554 if (!ProtectRtp(p, in_len, max_len, out_len)) { | 549 if (!ProtectRtp(p, in_len, max_len, out_len)) { |
| 555 return false; | 550 return false; |
| 556 } | 551 } |
| 557 return (index) ? GetSendStreamPacketIndex(p, in_len, index) : true; | 552 return (index) ? GetSendStreamPacketIndex(p, in_len, index) : true; |
| 558 } | 553 } |
| 559 | 554 |
| 560 bool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) { | 555 bool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) { |
| 556 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 561 if (!session_) { | 557 if (!session_) { |
| 562 LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session"; | 558 LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session"; |
| 563 return false; | 559 return false; |
| 564 } | 560 } |
| 565 | 561 |
| 566 int need_len = in_len + sizeof(uint32_t) + rtcp_auth_tag_len_; // NOLINT | 562 int need_len = in_len + sizeof(uint32_t) + rtcp_auth_tag_len_; // NOLINT |
| 567 if (max_len < need_len) { | 563 if (max_len < need_len) { |
| 568 LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length " | 564 LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length " |
| 569 << max_len << " is less than the needed " << need_len; | 565 << max_len << " is less than the needed " << need_len; |
| 570 return false; | 566 return false; |
| 571 } | 567 } |
| 572 | 568 |
| 573 *out_len = in_len; | 569 *out_len = in_len; |
| 574 int err = srtp_protect_rtcp(session_, p, out_len); | 570 int err = srtp_protect_rtcp(session_, p, out_len); |
| 575 srtp_stat_->AddProtectRtcpResult(err); | 571 srtp_stat_->AddProtectRtcpResult(err); |
| 576 if (err != err_status_ok) { | 572 if (err != err_status_ok) { |
| 577 LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err; | 573 LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err; |
| 578 return false; | 574 return false; |
| 579 } | 575 } |
| 580 return true; | 576 return true; |
| 581 } | 577 } |
| 582 | 578 |
| 583 bool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) { | 579 bool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) { |
| 580 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 584 if (!session_) { | 581 if (!session_) { |
| 585 LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session"; | 582 LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session"; |
| 586 return false; | 583 return false; |
| 587 } | 584 } |
| 588 | 585 |
| 589 *out_len = in_len; | 586 *out_len = in_len; |
| 590 int err = srtp_unprotect(session_, p, out_len); | 587 int err = srtp_unprotect(session_, p, out_len); |
| 591 uint32_t ssrc; | 588 uint32_t ssrc; |
| 592 if (GetRtpSsrc(p, in_len, &ssrc)) { | 589 if (GetRtpSsrc(p, in_len, &ssrc)) { |
| 593 srtp_stat_->AddUnprotectRtpResult(ssrc, err); | 590 srtp_stat_->AddUnprotectRtpResult(ssrc, err); |
| 594 } | 591 } |
| 595 if (err != err_status_ok) { | 592 if (err != err_status_ok) { |
| 596 LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err; | 593 LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err; |
| 597 return false; | 594 return false; |
| 598 } | 595 } |
| 599 return true; | 596 return true; |
| 600 } | 597 } |
| 601 | 598 |
| 602 bool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) { | 599 bool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) { |
| 600 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 603 if (!session_) { | 601 if (!session_) { |
| 604 LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session"; | 602 LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session"; |
| 605 return false; | 603 return false; |
| 606 } | 604 } |
| 607 | 605 |
| 608 *out_len = in_len; | 606 *out_len = in_len; |
| 609 int err = srtp_unprotect_rtcp(session_, p, out_len); | 607 int err = srtp_unprotect_rtcp(session_, p, out_len); |
| 610 srtp_stat_->AddUnprotectRtcpResult(err); | 608 srtp_stat_->AddUnprotectRtcpResult(err); |
| 611 if (err != err_status_ok) { | 609 if (err != err_status_ok) { |
| 612 LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err; | 610 LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err; |
| 613 return false; | 611 return false; |
| 614 } | 612 } |
| 615 return true; | 613 return true; |
| 616 } | 614 } |
| 617 | 615 |
| 618 bool SrtpSession::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) { | 616 bool SrtpSession::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) { |
| 619 #if defined(ENABLE_EXTERNAL_AUTH) | 617 #if defined(ENABLE_EXTERNAL_AUTH) |
| 618 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 620 ExternalHmacContext* external_hmac = NULL; | 619 ExternalHmacContext* external_hmac = NULL; |
| 621 // stream_template will be the reference context for other streams. | 620 // stream_template will be the reference context for other streams. |
| 622 // Let's use it for getting the keys. | 621 // Let's use it for getting the keys. |
| 623 srtp_stream_ctx_t* srtp_context = session_->stream_template; | 622 srtp_stream_ctx_t* srtp_context = session_->stream_template; |
| 624 if (srtp_context && srtp_context->rtp_auth) { | 623 if (srtp_context && srtp_context->rtp_auth) { |
| 625 external_hmac = reinterpret_cast<ExternalHmacContext*>( | 624 external_hmac = reinterpret_cast<ExternalHmacContext*>( |
| 626 srtp_context->rtp_auth->state); | 625 srtp_context->rtp_auth->state); |
| 627 } | 626 } |
| 628 | 627 |
| 629 if (!external_hmac) { | 628 if (!external_hmac) { |
| 630 LOG(LS_ERROR) << "Failed to get auth keys from libsrtp!."; | 629 LOG(LS_ERROR) << "Failed to get auth keys from libsrtp!."; |
| 631 return false; | 630 return false; |
| 632 } | 631 } |
| 633 | 632 |
| 634 *key = external_hmac->key; | 633 *key = external_hmac->key; |
| 635 *key_len = external_hmac->key_length; | 634 *key_len = external_hmac->key_length; |
| 636 *tag_len = rtp_auth_tag_len_; | 635 *tag_len = rtp_auth_tag_len_; |
| 637 return true; | 636 return true; |
| 638 #else | 637 #else |
| 639 return false; | 638 return false; |
| 640 #endif | 639 #endif |
| 641 } | 640 } |
| 642 | 641 |
| 643 bool SrtpSession::GetSendStreamPacketIndex(void* p, | 642 bool SrtpSession::GetSendStreamPacketIndex(void* p, |
| 644 int in_len, | 643 int in_len, |
| 645 int64_t* index) { | 644 int64_t* index) { |
| 645 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 646 srtp_hdr_t* hdr = reinterpret_cast<srtp_hdr_t*>(p); | 646 srtp_hdr_t* hdr = reinterpret_cast<srtp_hdr_t*>(p); |
| 647 srtp_stream_ctx_t* stream = srtp_get_stream(session_, hdr->ssrc); | 647 srtp_stream_ctx_t* stream = srtp_get_stream(session_, hdr->ssrc); |
| 648 if (stream == NULL) | 648 if (stream == NULL) |
| 649 return false; | 649 return false; |
| 650 | 650 |
| 651 // Shift packet index, put into network byte order | 651 // Shift packet index, put into network byte order |
| 652 *index = static_cast<int64_t>( | 652 *index = static_cast<int64_t>( |
| 653 rtc::NetworkToHost64(rdbx_get_packet_index(&stream->rtp_rdbx) << 16)); | 653 rtc::NetworkToHost64(rdbx_get_packet_index(&stream->rtp_rdbx) << 16)); |
| 654 return true; | 654 return true; |
| 655 } | 655 } |
| 656 | 656 |
| 657 void SrtpSession::set_signal_silent_time(uint32_t signal_silent_time_in_ms) { | 657 void SrtpSession::set_signal_silent_time(uint32_t signal_silent_time_in_ms) { |
| 658 srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms); | 658 srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms); |
| 659 } | 659 } |
| 660 | 660 |
| 661 bool SrtpSession::SetKey(int type, | 661 bool SrtpSession::SetKey(int type, |
| 662 const std::string& cs, | 662 const std::string& cs, |
| 663 const uint8_t* key, | 663 const uint8_t* key, |
| 664 int len) { | 664 int len) { |
| 665 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 665 if (session_) { | 666 if (session_) { |
| 666 LOG(LS_ERROR) << "Failed to create SRTP session: " | 667 LOG(LS_ERROR) << "Failed to create SRTP session: " |
| 667 << "SRTP session already created"; | 668 << "SRTP session already created"; |
| 668 return false; | 669 return false; |
| 669 } | 670 } |
| 670 | 671 |
| 671 if (!Init()) { | 672 if (!Init()) { |
| 672 return false; | 673 return false; |
| 673 } | 674 } |
| 674 | 675 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 710 #endif | 711 #endif |
| 711 policy.next = NULL; | 712 policy.next = NULL; |
| 712 | 713 |
| 713 int err = srtp_create(&session_, &policy); | 714 int err = srtp_create(&session_, &policy); |
| 714 if (err != err_status_ok) { | 715 if (err != err_status_ok) { |
| 715 session_ = NULL; | 716 session_ = NULL; |
| 716 LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err; | 717 LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err; |
| 717 return false; | 718 return false; |
| 718 } | 719 } |
| 719 | 720 |
| 720 | 721 session_->user_data = this; |
| 721 rtp_auth_tag_len_ = policy.rtp.auth_tag_len; | 722 rtp_auth_tag_len_ = policy.rtp.auth_tag_len; |
| 722 rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len; | 723 rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len; |
| 723 return true; | 724 return true; |
| 724 } | 725 } |
| 725 | 726 |
| 726 bool SrtpSession::Init() { | 727 bool SrtpSession::Init() { |
| 727 rtc::GlobalLockScope ls(&lock_); | 728 rtc::GlobalLockScope ls(&lock_); |
| 728 | 729 |
| 729 if (!inited_) { | 730 if (!inited_) { |
| 730 int err; | 731 int err; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 759 int err = srtp_shutdown(); | 760 int err = srtp_shutdown(); |
| 760 if (err) { | 761 if (err) { |
| 761 LOG(LS_ERROR) << "srtp_shutdown failed. err=" << err; | 762 LOG(LS_ERROR) << "srtp_shutdown failed. err=" << err; |
| 762 return; | 763 return; |
| 763 } | 764 } |
| 764 inited_ = false; | 765 inited_ = false; |
| 765 } | 766 } |
| 766 } | 767 } |
| 767 | 768 |
| 768 void SrtpSession::HandleEvent(const srtp_event_data_t* ev) { | 769 void SrtpSession::HandleEvent(const srtp_event_data_t* ev) { |
| 770 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 769 switch (ev->event) { | 771 switch (ev->event) { |
| 770 case event_ssrc_collision: | 772 case event_ssrc_collision: |
| 771 LOG(LS_INFO) << "SRTP event: SSRC collision"; | 773 LOG(LS_INFO) << "SRTP event: SSRC collision"; |
| 772 break; | 774 break; |
| 773 case event_key_soft_limit: | 775 case event_key_soft_limit: |
| 774 LOG(LS_INFO) << "SRTP event: reached soft key usage limit"; | 776 LOG(LS_INFO) << "SRTP event: reached soft key usage limit"; |
| 775 break; | 777 break; |
| 776 case event_key_hard_limit: | 778 case event_key_hard_limit: |
| 777 LOG(LS_INFO) << "SRTP event: reached hard key usage limit"; | 779 LOG(LS_INFO) << "SRTP event: reached hard key usage limit"; |
| 778 break; | 780 break; |
| 779 case event_packet_index_limit: | 781 case event_packet_index_limit: |
| 780 LOG(LS_INFO) << "SRTP event: reached hard packet limit (2^48 packets)"; | 782 LOG(LS_INFO) << "SRTP event: reached hard packet limit (2^48 packets)"; |
| 781 break; | 783 break; |
| 782 default: | 784 default: |
| 783 LOG(LS_INFO) << "SRTP event: unknown " << ev->event; | 785 LOG(LS_INFO) << "SRTP event: unknown " << ev->event; |
| 784 break; | 786 break; |
| 785 } | 787 } |
| 786 } | 788 } |
| 787 | 789 |
| 788 void SrtpSession::HandleEventThunk(srtp_event_data_t* ev) { | 790 void SrtpSession::HandleEventThunk(srtp_event_data_t* ev) { |
| 789 rtc::GlobalLockScope ls(&lock_); | 791 // Callback will be executed from same thread that calls the "srtp_protect" |
| 790 | 792 // and "srtp_unprotect" functions. |
| 791 for (std::list<SrtpSession*>::iterator it = sessions()->begin(); | 793 SrtpSession* session = static_cast<SrtpSession*>(ev->session->user_data); |
| 792 it != sessions()->end(); ++it) { | 794 if (session) { |
| 793 if ((*it)->session_ == ev->session) { | 795 session->HandleEvent(ev); |
| 794 (*it)->HandleEvent(ev); | |
| 795 break; | |
| 796 } | |
| 797 } | 796 } |
| 798 } | 797 } |
| 799 | 798 |
| 800 std::list<SrtpSession*>* SrtpSession::sessions() { | |
| 801 RTC_DEFINE_STATIC_LOCAL(std::list<SrtpSession*>, sessions, ()); | |
| 802 return &sessions; | |
| 803 } | |
| 804 | |
| 805 #else // !HAVE_SRTP | 799 #else // !HAVE_SRTP |
| 806 | 800 |
| 807 // On some systems, SRTP is not (yet) available. | 801 // On some systems, SRTP is not (yet) available. |
| 808 | 802 |
| 809 SrtpSession::SrtpSession() { | 803 SrtpSession::SrtpSession() { |
| 810 LOG(WARNING) << "SRTP implementation is missing."; | 804 LOG(WARNING) << "SRTP implementation is missing."; |
| 811 } | 805 } |
| 812 | 806 |
| 813 SrtpSession::~SrtpSession() { | 807 SrtpSession::~SrtpSession() { |
| 814 } | 808 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 SrtpNotAvailable(__FUNCTION__); | 936 SrtpNotAvailable(__FUNCTION__); |
| 943 } | 937 } |
| 944 | 938 |
| 945 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) { | 939 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) { |
| 946 SrtpNotAvailable(__FUNCTION__); | 940 SrtpNotAvailable(__FUNCTION__); |
| 947 } | 941 } |
| 948 | 942 |
| 949 #endif // HAVE_SRTP | 943 #endif // HAVE_SRTP |
| 950 | 944 |
| 951 } // namespace cricket | 945 } // namespace cricket |
| OLD | NEW |