10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2009 Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#undef HAVE_CONFIG_H
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/session/media/srtpfilter.h"
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
32b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org#include <string.h>
33b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <algorithm>
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
36cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/rtputils.h"
372a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/base64.h"
382a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/logging.h"
392a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/stringencode.h"
402a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/timeutils.h"
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Enable this line to turn on SRTP debugging
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// #define SRTP_DEBUG
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_SRTP
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef SRTP_RELATIVE_PATH
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "srtp.h"  // NOLINT
48e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.orgextern "C" srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
49e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#include "srtp_priv.h"  // NOLINT
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "third_party/libsrtp/include/srtp.h"
52e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.orgextern "C" srtp_stream_t srtp_get_stream(srtp_t srtp, uint32_t ssrc);
53e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#include "third_party/libsrtp/include/srtp_priv.h"
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif  // SRTP_RELATIVE_PATH
55e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#ifdef  ENABLE_EXTERNAL_AUTH
5678afd903598b85bd36e67ca5a4cf8e631cef6eaehenrike@webrtc.org#include "talk/session/media/externalhmac.h"
57e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#endif  // ENABLE_EXTERNAL_AUTH
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef _DEBUG
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgextern "C" debug_module_t mod_srtp;
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgextern "C" debug_module_t mod_auth;
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgextern "C" debug_module_t mod_cipher;
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgextern "C" debug_module_t mod_stat;
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgextern "C" debug_module_t mod_alloc;
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgextern "C" debug_module_t mod_aes_icm;
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgextern "C" debug_module_t mod_aes_hmac;
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// SrtpFilter needs that constant.
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define SRTP_MASTER_KEY_LEN 30
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif  // HAVE_SRTP
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char CS_AES_CM_128_HMAC_SHA1_80[] = "AES_CM_128_HMAC_SHA1_80";
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char CS_AES_CM_128_HMAC_SHA1_32[] = "AES_CM_128_HMAC_SHA1_32";
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int SRTP_MASTER_KEY_BASE64_LEN = SRTP_MASTER_KEY_LEN * 4 / 3;
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int SRTP_MASTER_KEY_KEY_LEN = 16;
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int SRTP_MASTER_KEY_SALT_LEN = 14;
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifndef HAVE_SRTP
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This helper function is used on systems that don't (yet) have SRTP,
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// to log that the functions that require it won't do anything.
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace {
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpNotAvailable(const char *func) {
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_ERROR) << func << ": SRTP is not available on your system.";
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // anonymous namespace
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif  // !HAVE_SRTP
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid EnableSrtpDebugging() {
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_SRTP
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef _DEBUG
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  debug_on(mod_srtp);
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  debug_on(mod_auth);
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  debug_on(mod_cipher);
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  debug_on(mod_stat);
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  debug_on(mod_alloc);
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  debug_on(mod_aes_icm);
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // debug_on(mod_aes_cbc);
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // debug_on(mod_hmac);
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif  // HAVE_SRTP
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
108f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org// NOTE: This is called from ChannelManager D'tor.
109f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgvoid ShutdownSrtp() {
110f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org#ifdef HAVE_SRTP
111f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // If srtp_dealloc is not executed then this will clear all existing sessions.
112f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  // This should be called when application is shutting down.
113f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  SrtpSession::Terminate();
114f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org#endif
115f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org}
116f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSrtpFilter::SrtpFilter()
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : state_(ST_INIT),
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      signal_silent_time_in_ms_(0) {
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSrtpFilter::~SrtpFilter() {
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::IsActive() const {
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return state_ >= ST_ACTIVE;
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::SetOffer(const std::vector<CryptoParams>& offer_params,
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          ContentSource source) {
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ExpectOffer(source)) {
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org     LOG(LS_ERROR) << "Wrong state to update SRTP offer";
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org     return false;
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return StoreParams(offer_params, source);
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params,
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           ContentSource source) {
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return DoSetAnswer(answer_params, source, true);
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::SetProvisionalAnswer(
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::vector<CryptoParams>& answer_params,
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ContentSource source) {
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return DoSetAnswer(answer_params, source, false);
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::SetRtpParams(const std::string& send_cs,
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              const uint8* send_key, int send_key_len,
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              const std::string& recv_cs,
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              const uint8* recv_key, int recv_key_len) {
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (state_ == ST_ACTIVE) {
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "Tried to set SRTP Params when filter already active";
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CreateSrtpSessions();
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!send_session_->SetSend(send_cs, send_key, send_key_len))
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!recv_session_->SetRecv(recv_cs, recv_key, recv_key_len))
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  state_ = ST_ACTIVE;
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << " send cipher_suite " << send_cs
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << " recv cipher_suite " << recv_cs;
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This function is provided separately because DTLS-SRTP behaves
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// differently in RTP/RTCP mux and non-mux modes.
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// - In the non-muxed case, RTP and RTCP are keyed with different
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//   keys (from different DTLS handshakes), and so we need a new
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//   SrtpSession.
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// - In the muxed case, they are keyed with the same keys, so
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org//   this function is not needed
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::SetRtcpParams(const std::string& send_cs,
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const uint8* send_key, int send_key_len,
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const std::string& recv_cs,
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const uint8* recv_key, int recv_key_len) {
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // This can only be called once, but can be safely called after
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // SetRtpParams
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (send_rtcp_session_ || recv_rtcp_session_) {
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active";
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  send_rtcp_session_.reset(new SrtpSession());
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalSrtpError.repeat(send_rtcp_session_->SignalSrtpError);
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_);
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!send_rtcp_session_->SetRecv(send_cs, send_key, send_key_len))
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  recv_rtcp_session_.reset(new SrtpSession());
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalSrtpError.repeat(recv_rtcp_session_->SignalSrtpError);
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_);
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len))
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << " send cipher_suite " << send_cs
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               << " recv cipher_suite " << recv_cs;
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!IsActive()) {
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return send_session_->ProtectRtp(p, in_len, max_len, out_len);
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
218e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.orgbool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len,
219e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org                            int64* index) {
220e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  if (!IsActive()) {
221e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
222e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    return false;
223e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  }
224e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
225e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
226e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org}
227e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!IsActive()) {
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (send_rtcp_session_) {
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::UnprotectRtp(void* p, int in_len, int* out_len) {
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!IsActive()) {
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return recv_session_->UnprotectRtp(p, in_len, out_len);
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::UnprotectRtcp(void* p, int in_len, int* out_len) {
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!IsActive()) {
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (recv_rtcp_session_) {
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return recv_session_->UnprotectRtcp(p, in_len, out_len);
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
260e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.orgbool SrtpFilter::GetRtpAuthParams(uint8** key, int* key_len, int* tag_len) {
261e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  if (!IsActive()) {
262e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active";
263e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    return false;
264e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  }
265e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
266e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  return send_session_->GetRtpAuthParams(key, key_len, tag_len);
267e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org}
268e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpFilter::set_signal_silent_time(uint32 signal_silent_time_in_ms) {
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  signal_silent_time_in_ms_ = signal_silent_time_in_ms;
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (state_ == ST_ACTIVE) {
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    send_session_->set_signal_silent_time(signal_silent_time_in_ms);
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    recv_session_->set_signal_silent_time(signal_silent_time_in_ms);
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (send_rtcp_session_)
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms);
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (recv_rtcp_session_)
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms);
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::ExpectOffer(ContentSource source) {
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ((state_ == ST_INIT) ||
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_ACTIVE) ||
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_  == ST_SENTOFFER && source == CS_LOCAL) ||
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_  == ST_SENTUPDATEDOFFER && source == CS_LOCAL) ||
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) ||
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE));
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params,
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             ContentSource source) {
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  offer_params_ = params;
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (state_ == ST_INIT) {
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {  // state >= ST_ACTIVE
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    state_ =
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        (source == CS_LOCAL) ? ST_SENTUPDATEDOFFER : ST_RECEIVEDUPDATEDOFFER;
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::ExpectAnswer(ContentSource source) {
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL) ||
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_SENTUPDATEDOFFER && source == CS_REMOTE) ||
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_LOCAL) ||
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_SENTPRANSWER_NO_CRYPTO && source == CS_LOCAL) ||
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_SENTPRANSWER && source == CS_LOCAL) ||
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_RECEIVEDPRANSWER_NO_CRYPTO && source == CS_REMOTE) ||
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (state_ == ST_RECEIVEDPRANSWER && source == CS_REMOTE));
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::DoSetAnswer(const std::vector<CryptoParams>& answer_params,
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             ContentSource source,
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             bool final) {
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ExpectAnswer(source)) {
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "Invalid state for SRTP answer";
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If the answer doesn't requests crypto complete the negotiation of an
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // unencrypted session.
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Otherwise, finalize the parameters and apply them.
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (answer_params.empty()) {
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (final) {
3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return ResetParams();
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Need to wait for the final answer to decide if
3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // we should go to Active state.
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO :
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      ST_RECEIVEDPRANSWER_NO_CRYPTO;
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return true;
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CryptoParams selected_params;
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!NegotiateParams(answer_params, &selected_params))
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const CryptoParams& send_params =
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (source == CS_REMOTE) ? selected_params : answer_params[0];
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const CryptoParams& recv_params =
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (source == CS_REMOTE) ? answer_params[0] : selected_params;
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ApplyParams(send_params, recv_params)) {
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (final) {
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    offer_params_.clear();
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    state_ = ST_ACTIVE;
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    state_ =
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER;
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpFilter::CreateSrtpSessions() {
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  send_session_.reset(new SrtpSession());
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  applied_send_params_ = CryptoParams();
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  recv_session_.reset(new SrtpSession());
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  applied_recv_params_ = CryptoParams();
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalSrtpError.repeat(send_session_->SignalSrtpError);
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalSrtpError.repeat(recv_session_->SignalSrtpError);
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  send_session_->set_signal_silent_time(signal_silent_time_in_ms_);
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  recv_session_->set_signal_silent_time(signal_silent_time_in_ms_);
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params,
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                 CryptoParams* selected_params) {
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We're processing an accept. We should have exactly one set of params,
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // unless the offer didn't mention crypto, in which case we shouldn't be here.
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool ret = (answer_params.size() == 1U && !offer_params_.empty());
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (ret) {
3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // We should find a match between the answer params and the offered params.
3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::vector<CryptoParams>::const_iterator it;
3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (it = offer_params_.begin(); it != offer_params_.end(); ++it) {
3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (answer_params[0].Matches(*it)) {
3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        break;
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (it != offer_params_.end()) {
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *selected_params = *it;
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ret = false;
3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ret) {
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Invalid parameters in SRTP answer";
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ret;
3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::ApplyParams(const CryptoParams& send_params,
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             const CryptoParams& recv_params) {
3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(jiayl): Split this method to apply send and receive CryptoParams
3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // independently, so that we can skip one method when either send or receive
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // CryptoParams is unchanged.
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (applied_send_params_.cipher_suite == send_params.cipher_suite &&
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      applied_send_params_.key_params == send_params.key_params &&
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      applied_recv_params_.cipher_suite == recv_params.cipher_suite &&
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      applied_recv_params_.key_params == recv_params.key_params) {
4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op.";
4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // We do not want to reset the ROC if the keys are the same. So just return.
4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(juberti): Zero these buffers after use.
4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool ret;
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint8 send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN];
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) &&
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key)));
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (ret) {
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    CreateSrtpSessions();
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ret = (send_session_->SetSend(send_params.cipher_suite,
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  send_key, sizeof(send_key)) &&
4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org           recv_session_->SetRecv(recv_params.cipher_suite,
4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  recv_key, sizeof(recv_key)));
4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (ret) {
4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << " send cipher_suite " << send_params.cipher_suite
4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << " recv cipher_suite " << recv_params.cipher_suite;
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    applied_send_params_ = send_params;
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    applied_recv_params_ = recv_params;
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters";
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ret;
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::ResetParams() {
4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  offer_params_.clear();
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  state_ = ST_INIT;
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "SRTP reset to init state";
4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpFilter::ParseKeyParams(const std::string& key_params,
4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                uint8* key, int len) {
4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Fail if key-method is wrong.
4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (key_params.find("inline:") != 0) {
4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Fail if base64 decode fails, or the key is the wrong size.
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string key_b64(key_params.substr(7)), key_str;
4522a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT,
4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                 &key_str, NULL) ||
4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      static_cast<int>(key_str.size()) != len) {
4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  memcpy(key, key_str.c_str(), len);
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// SrtpSession
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_SRTP
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::inited_ = false;
4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSrtpSession::SrtpSession()
4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : session_(NULL),
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      rtp_auth_tag_len_(0),
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      rtcp_auth_tag_len_(0),
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      srtp_stat_(new SrtpStat()),
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      last_send_seq_num_(-1) {
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  sessions()->push_back(this);
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SignalSrtpError.repeat(srtp_stat_->SignalSrtpError);
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSrtpSession::~SrtpSession() {
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  sessions()->erase(std::find(sessions()->begin(), sessions()->end(), this));
4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (session_) {
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    srtp_dealloc(session_);
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SetKey(ssrc_any_outbound, cs, key, len);
4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SetKey(ssrc_any_inbound, cs, key, len);
4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!session_) {
4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session";
4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int need_len = in_len + rtp_auth_tag_len_;  // NOLINT
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (max_len < need_len) {
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length "
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << max_len << " is less than the needed " << need_len;
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *out_len = in_len;
5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int err = srtp_protect(session_, p, out_len);
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 ssrc;
5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (GetRtpSsrc(p, in_len, &ssrc)) {
5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    srtp_stat_->AddProtectRtpResult(ssrc, err);
5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int seq_num;
5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  GetRtpSeqNum(p, in_len, &seq_num);
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (err != err_status_ok) {
5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTP packet, seqnum="
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << seq_num << ", err=" << err << ", last seqnum="
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << last_send_seq_num_;
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  last_send_seq_num_ = seq_num;
5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
525e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.orgbool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len,
526e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org                             int64* index) {
527e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  if (!ProtectRtp(p, in_len, max_len, out_len)) {
528e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    return false;
529e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  }
530e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  return (index) ? GetSendStreamPacketIndex(p, in_len, index) : true;
531e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org}
532e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!session_) {
5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session";
5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int need_len = in_len + sizeof(uint32) + rtcp_auth_tag_len_;  // NOLINT
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (max_len < need_len) {
5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length "
5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << max_len << " is less than the needed " << need_len;
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *out_len = in_len;
5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int err = srtp_protect_rtcp(session_, p, out_len);
5480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  srtp_stat_->AddProtectRtcpResult(err);
5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (err != err_status_ok) {
5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err;
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) {
5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!session_) {
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session";
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *out_len = in_len;
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int err = srtp_unprotect(session_, p, out_len);
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 ssrc;
5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (GetRtpSsrc(p, in_len, &ssrc)) {
5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    srtp_stat_->AddUnprotectRtpResult(ssrc, err);
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (err != err_status_ok) {
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err;
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) {
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!session_) {
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session";
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *out_len = in_len;
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int err = srtp_unprotect_rtcp(session_, p, out_len);
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  srtp_stat_->AddUnprotectRtcpResult(err);
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (err != err_status_ok) {
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err;
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
591e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.orgbool SrtpSession::GetRtpAuthParams(uint8** key, int* key_len,
592e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org                                   int* tag_len) {
593e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#if defined(ENABLE_EXTERNAL_AUTH)
594e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  external_hmac_ctx_t* external_hmac = NULL;
595e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // stream_template will be the reference context for other streams.
596e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // Let's use it for getting the keys.
597e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  srtp_stream_ctx_t* srtp_context = session_->stream_template;
598e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  if (srtp_context && srtp_context->rtp_auth) {
599e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    external_hmac = reinterpret_cast<external_hmac_ctx_t*>(
600e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org        srtp_context->rtp_auth->state);
601e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  }
602e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
603e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  if (!external_hmac) {
604e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    LOG(LS_ERROR) << "Failed to get auth keys from libsrtp!.";
605e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    return false;
606e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  }
607e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
608e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  *key = external_hmac->key;
609e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  *key_len = external_hmac->key_length;
610e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  *tag_len = rtp_auth_tag_len_;
611e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  return true;
612e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#else
613e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  return false;
614e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#endif
615e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org}
616e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
617e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.orgbool SrtpSession::GetSendStreamPacketIndex(void* p, int in_len, int64* index) {
618e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  srtp_hdr_t* hdr = reinterpret_cast<srtp_hdr_t*>(p);
619e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  srtp_stream_ctx_t* stream = srtp_get_stream(session_, hdr->ssrc);
620e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  if (stream == NULL)
621e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    return false;
622e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
623b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  // Shift packet index, put into network byte order
624b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  *index = be64_to_cpu(rdbx_get_packet_index(&stream->rtp_rdbx) << 16);
625e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  return true;
626e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org}
627e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpSession::set_signal_silent_time(uint32 signal_silent_time_in_ms) {
6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms);
6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::SetKey(int type, const std::string& cs,
6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const uint8* key, int len) {
6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (session_) {
6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "Failed to create SRTP session: "
6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << "SRTP session already created";
6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!Init()) {
6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  srtp_policy_t policy;
6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  memset(&policy, 0, sizeof(policy));
6460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (cs == CS_AES_CM_128_HMAC_SHA1_80) {
6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
6500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (cs == CS_AES_CM_128_HMAC_SHA1_32) {
6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);   // rtp is 32,
6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);  // rtcp still 80
6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to create SRTP session: unsupported"
6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " cipher_suite " << cs.c_str();
6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!key || len != SRTP_MASTER_KEY_LEN) {
6600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to create SRTP session: invalid key";
6610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  policy.ssrc.type = static_cast<ssrc_type_t>(type);
6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  policy.ssrc.value = 0;
6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  policy.key = const_cast<uint8*>(key);
6670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(astor) parse window size from WSH session-param
6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  policy.window_size = 1024;
6690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  policy.allow_repeat_tx = 1;
670e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // If external authentication option is enabled, supply custom auth module
671e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // id EXTERNAL_HMAC_SHA1 in the policy structure.
672e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // We want to set this option only for rtp packets.
673e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org  // By default policy structure is initialized to HMAC_SHA1.
674e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#if defined(ENABLE_EXTERNAL_AUTH)
675b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  // Enable external HMAC authentication only for outgoing streams.
676b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  if (type == ssrc_any_outbound) {
677b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org    policy.rtp.auth_type = EXTERNAL_HMAC_SHA1;
678b1ad2cd39fca8ea62e7dc512e788a414b328db7dhenrike@webrtc.org  }
679e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#endif
6800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  policy.next = NULL;
6810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int err = srtp_create(&session_, &policy);
6830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (err != err_status_ok) {
6840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err;
6850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
688e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org
6890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  rtp_auth_tag_len_ = policy.rtp.auth_tag_len;
6900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len;
6910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
6920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::Init() {
6950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!inited_) {
6960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int err;
6970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    err = srtp_init();
6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (err != err_status_ok) {
6990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_ERROR) << "Failed to init SRTP, err=" << err;
7000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    err = srtp_install_event_handler(&SrtpSession::HandleEventThunk);
7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (err != err_status_ok) {
7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_ERROR) << "Failed to install SRTP event handler, err=" << err;
7060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
708e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#if defined(ENABLE_EXTERNAL_AUTH)
709e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    err = external_crypto_init();
710e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    if (err != err_status_ok) {
711e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org      LOG(LS_ERROR) << "Failed to initialize fake auth, err=" << err;
712e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org      return false;
713e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org    }
714e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org#endif
7150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    inited_ = true;
7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
721f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.orgvoid SrtpSession::Terminate() {
722f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  if (inited_) {
723f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    int err = srtp_shutdown();
724f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    if (err) {
725f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      LOG(LS_ERROR) << "srtp_shutdown failed. err=" << err;
726f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org      return;
727f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    }
728f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org    inited_ = false;
729f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org  }
730f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org}
731f99f1011aa4cd22bd86ba2e4f7d239ea1b766ec8wu@webrtc.org
7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpSession::HandleEvent(const srtp_event_data_t* ev) {
7330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (ev->event) {
7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case event_ssrc_collision:
7350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: SSRC collision";
7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
7370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case event_key_soft_limit:
7380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: reached soft key usage limit";
7390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
7400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case event_key_hard_limit:
7410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: reached hard key usage limit";
7420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
7430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case event_packet_index_limit:
7440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: reached hard packet limit (2^48 packets)";
7450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
7460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
7470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: unknown " << ev->event;
7480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
7490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpSession::HandleEventThunk(srtp_event_data_t* ev) {
7530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::list<SrtpSession*>::iterator it = sessions()->begin();
7540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != sessions()->end(); ++it) {
7550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((*it)->session_ == ev->session) {
7560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (*it)->HandleEvent(ev);
7570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
7580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::list<SrtpSession*>* SrtpSession::sessions() {
7630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LIBJINGLE_DEFINE_STATIC_LOCAL(std::list<SrtpSession*>, sessions, ());
7640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return &sessions;
7650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else   // !HAVE_SRTP
7680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// On some systems, SRTP is not (yet) available.
7700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSrtpSession::SrtpSession() {
7720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(WARNING) << "SRTP implementation is missing.";
7730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSrtpSession::~SrtpSession() {
7760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
7790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
7800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
7830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
7840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::ProtectRtp(void* data, int in_len, int max_len,
7870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             int* out_len) {
7880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
7890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::ProtectRtcp(void* data, int in_len, int max_len,
7920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              int* out_len) {
7930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
7940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::UnprotectRtp(void* data, int in_len, int* out_len) {
7970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
7980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool SrtpSession::UnprotectRtcp(void* data, int in_len, int* out_len) {
8010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
8020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpSession::set_signal_silent_time(uint32 signal_silent_time) {
8050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Do nothing.
8060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif  // HAVE_SRTP
8090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
8110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// SrtpStat
8120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef HAVE_SRTP
8140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSrtpStat::SrtpStat()
8160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : signal_silent_time_(1000) {
8170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::AddProtectRtpResult(uint32 ssrc, int result) {
8200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  FailureKey key;
8210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  key.ssrc = ssrc;
8220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  key.mode = SrtpFilter::PROTECT;
8230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (result) {
8240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case err_status_ok:
8250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      key.error = SrtpFilter::ERROR_NONE;
8260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
8270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case err_status_auth_fail:
8280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      key.error = SrtpFilter::ERROR_AUTH;
8290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
8300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
8310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      key.error = SrtpFilter::ERROR_FAIL;
8320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  HandleSrtpResult(key);
8340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::AddUnprotectRtpResult(uint32 ssrc, int result) {
8370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  FailureKey key;
8380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  key.ssrc = ssrc;
8390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  key.mode = SrtpFilter::UNPROTECT;
8400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (result) {
8410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case err_status_ok:
8420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      key.error = SrtpFilter::ERROR_NONE;
8430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
8440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case err_status_auth_fail:
8450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      key.error = SrtpFilter::ERROR_AUTH;
8460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
8470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case err_status_replay_fail:
8480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case err_status_replay_old:
8490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      key.error = SrtpFilter::ERROR_REPLAY;
8500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
8510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
8520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      key.error = SrtpFilter::ERROR_FAIL;
8530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  HandleSrtpResult(key);
8550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::AddProtectRtcpResult(int result) {
8580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AddProtectRtpResult(0U, result);
8590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::AddUnprotectRtcpResult(int result) {
8620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AddUnprotectRtpResult(0U, result);
8630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
8660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Handle some cases where error should be signalled right away. For other
8670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // errors, trigger error for the first time seeing it.  After that, silent
8680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // the same error for a certain amount of time (default 1 sec).
8690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (key.error != SrtpFilter::ERROR_NONE) {
8700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // For errors, signal first time and wait for 1 sec.
8710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    FailureStat* stat = &(failures_[key]);
8722a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    uint32 current_time = rtc::Time();
8730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (stat->last_signal_time == 0 ||
8742a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        rtc::TimeDiff(current_time, stat->last_signal_time) >
8750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        static_cast<int>(signal_silent_time_)) {
8760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      SignalSrtpError(key.ssrc, key.mode, key.error);
8770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      stat->last_signal_time = current_time;
8780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else   // !HAVE_SRTP
8830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// On some systems, SRTP is not (yet) available.
8850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgSrtpStat::SrtpStat()
8870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : signal_silent_time_(1000) {
8880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(WARNING) << "SRTP implementation is missing.";
8890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::AddProtectRtpResult(uint32 ssrc, int result) {
8920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
8930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::AddUnprotectRtpResult(uint32 ssrc, int result) {
8960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
8970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::AddProtectRtcpResult(int result) {
9000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
9010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::AddUnprotectRtcpResult(int result) {
9040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
9050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
9080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
9090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif  // HAVE_SRTP
9120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
914