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 |