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