128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/*
228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * libjingle
328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * Copyright 2009 Google Inc.
428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *
528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *
828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *     this list of conditions and the following disclaimer.
1028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
1128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
1228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *     and/or other materials provided with the distribution.
1328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
1428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *     derived from this software without specific prior written permission.
1528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *
1628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
1728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
1928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org */
2728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
2828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#undef HAVE_CONFIG_H
2928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
3028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/session/media/srtpfilter.h"
3128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
32371243dfa3467c7be7217da4b537cc33d2bd45a6pbos@webrtc.org#include <string.h>
33371243dfa3467c7be7217da4b537cc33d2bd45a6pbos@webrtc.org
3428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <algorithm>
3528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
36a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "talk/media/base/rtputils.h"
37d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/base64.h"
384b3c0d6f34c379c2a06f654b62403876b20180c6Jiayang Liu#include "webrtc/base/byteorder.h"
399478437fdea4eb31b92ffe0c10368fe5bc9b9e16Karl Wiberg#include "webrtc/base/common.h"
40d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/logging.h"
41d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/stringencode.h"
42d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/timeutils.h"
4328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Enable this line to turn on SRTP debugging
4528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// #define SRTP_DEBUG
4628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
4728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifdef HAVE_SRTP
48a197a5eed68ad29e42cde83052abdc55efbcd65fjiayl@webrtc.orgextern "C" {
4928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifdef SRTP_RELATIVE_PATH
5028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "srtp.h"  // NOLINT
51a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#include "srtp_priv.h"  // NOLINT
5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#else
53a197a5eed68ad29e42cde83052abdc55efbcd65fjiayl@webrtc.org#include "third_party/libsrtp/srtp/include/srtp.h"
54a197a5eed68ad29e42cde83052abdc55efbcd65fjiayl@webrtc.org#include "third_party/libsrtp/srtp/include/srtp_priv.h"
5528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif  // SRTP_RELATIVE_PATH
56a197a5eed68ad29e42cde83052abdc55efbcd65fjiayl@webrtc.org}
57a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#ifdef  ENABLE_EXTERNAL_AUTH
58d43aa9de7a4a2b793e5ec59c86fb0b81e4052bb0henrike@webrtc.org#include "talk/session/media/externalhmac.h"
59a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#endif  // ENABLE_EXTERNAL_AUTH
60ff134ebd3d35ae2edd6eaa63b0a19cb16cc256b7tfarina#if !defined(NDEBUG)
6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgextern "C" debug_module_t mod_srtp;
6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgextern "C" debug_module_t mod_auth;
6328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgextern "C" debug_module_t mod_cipher;
6428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgextern "C" debug_module_t mod_stat;
6528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgextern "C" debug_module_t mod_alloc;
6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgextern "C" debug_module_t mod_aes_icm;
6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgextern "C" debug_module_t mod_aes_hmac;
6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif
6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#else
7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// SrtpFilter needs that constant.
7128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#define SRTP_MASTER_KEY_LEN 30
7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif  // HAVE_SRTP
7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace cricket {
7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgconst int SRTP_MASTER_KEY_BASE64_LEN = SRTP_MASTER_KEY_LEN * 4 / 3;
7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgconst int SRTP_MASTER_KEY_KEY_LEN = 16;
7828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgconst int SRTP_MASTER_KEY_SALT_LEN = 14;
7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifndef HAVE_SRTP
8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// This helper function is used on systems that don't (yet) have SRTP,
8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// to log that the functions that require it won't do anything.
8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace {
8528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpNotAvailable(const char *func) {
8628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(LS_ERROR) << func << ": SRTP is not available on your system.";
8728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return false;
8828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
8928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}  // anonymous namespace
9028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
9128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif  // !HAVE_SRTP
9228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
9328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid EnableSrtpDebugging() {
9428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifdef HAVE_SRTP
95ff134ebd3d35ae2edd6eaa63b0a19cb16cc256b7tfarina#if !defined(NDEBUG)
9628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  debug_on(mod_srtp);
9728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  debug_on(mod_auth);
9828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  debug_on(mod_cipher);
9928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  debug_on(mod_stat);
10028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  debug_on(mod_alloc);
10128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  debug_on(mod_aes_icm);
10228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // debug_on(mod_aes_cbc);
10328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // debug_on(mod_hmac);
10428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif
10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif  // HAVE_SRTP
10628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
10728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
1089dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org// NOTE: This is called from ChannelManager D'tor.
1099dba52562725dbaced0d671982201ede753d72e8wu@webrtc.orgvoid ShutdownSrtp() {
1109dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org#ifdef HAVE_SRTP
1119dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org  // If srtp_dealloc is not executed then this will clear all existing sessions.
1129dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org  // This should be called when application is shutting down.
1139dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org  SrtpSession::Terminate();
1149dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org#endif
1159dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org}
1169dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org
11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSrtpFilter::SrtpFilter()
11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    : state_(ST_INIT),
11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      signal_silent_time_in_ms_(0) {
12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSrtpFilter::~SrtpFilter() {
12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::IsActive() const {
12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return state_ >= ST_ACTIVE;
12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
12828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::SetOffer(const std::vector<CryptoParams>& offer_params,
13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                          ContentSource source) {
13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!ExpectOffer(source)) {
13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     LOG(LS_ERROR) << "Wrong state to update SRTP offer";
13328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     return false;
13428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
13528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return StoreParams(offer_params, source);
13628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
13728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params,
13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                           ContentSource source) {
14028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return DoSetAnswer(answer_params, source, true);
14128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
14228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
14328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::SetProvisionalAnswer(
14428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    const std::vector<CryptoParams>& answer_params,
14528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    ContentSource source) {
14628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return DoSetAnswer(answer_params, source, false);
14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
149521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shiehbool SrtpFilter::SetRtpParams(int send_cs,
1500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                              const uint8_t* send_key,
1510c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                              int send_key_len,
152521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh                              int recv_cs,
1530c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                              const uint8_t* recv_key,
1540c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                              int recv_key_len) {
1552e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org  if (IsActive()) {
15628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Tried to set SRTP Params when filter already active";
15728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
15828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  CreateSrtpSessions();
16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!send_session_->SetSend(send_cs, send_key, send_key_len))
16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!recv_session_->SetRecv(recv_cs, recv_key, recv_key_len))
16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
16628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  state_ = ST_ACTIVE;
16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org               << " send cipher_suite " << send_cs
17028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org               << " recv cipher_suite " << recv_cs;
17128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
17228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
17428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// This function is provided separately because DTLS-SRTP behaves
17528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// differently in RTP/RTCP mux and non-mux modes.
17628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org//
17728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// - In the non-muxed case, RTP and RTCP are keyed with different
17828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org//   keys (from different DTLS handshakes), and so we need a new
17928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org//   SrtpSession.
18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// - In the muxed case, they are keyed with the same keys, so
18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org//   this function is not needed
182521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shiehbool SrtpFilter::SetRtcpParams(int send_cs,
1830c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                               const uint8_t* send_key,
1840c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                               int send_key_len,
185521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh                               int recv_cs,
1860c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                               const uint8_t* recv_key,
1870c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                               int recv_key_len) {
18828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // This can only be called once, but can be safely called after
18928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // SetRtpParams
19028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (send_rtcp_session_ || recv_rtcp_session_) {
19128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active";
19228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
19328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  send_rtcp_session_.reset(new SrtpSession());
19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SignalSrtpError.repeat(send_rtcp_session_->SignalSrtpError);
19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_);
19828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!send_rtcp_session_->SetRecv(send_cs, send_key, send_key_len))
19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
20028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  recv_rtcp_session_.reset(new SrtpSession());
20228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SignalSrtpError.repeat(recv_rtcp_session_->SignalSrtpError);
20328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_);
20428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len))
20528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
20628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
20728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(LS_INFO) << "SRTCP activated with negotiated parameters:"
20828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org               << " send cipher_suite " << send_cs
20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org               << " recv cipher_suite " << recv_cs;
21028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
21128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
21228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
21528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!IsActive()) {
21628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
2192e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org  ASSERT(send_session_ != NULL);
22028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return send_session_->ProtectRtp(p, in_len, max_len, out_len);
22128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
22228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
2230c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SrtpFilter::ProtectRtp(void* p,
2240c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                            int in_len,
2250c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                            int max_len,
2260c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                            int* out_len,
2270c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                            int64_t* index) {
228a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  if (!IsActive()) {
229a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
230a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    return false;
231a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  }
2322e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org  ASSERT(send_session_ != NULL);
233a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
234a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org}
235a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org
23628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
23728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!IsActive()) {
23828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
23928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
24028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
24128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (send_rtcp_session_) {
24228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
24328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  } else {
2442e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org    ASSERT(send_session_ != NULL);
24528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
24628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
24728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::UnprotectRtp(void* p, int in_len, int* out_len) {
25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!IsActive()) {
25128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
25328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
2542e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org  ASSERT(recv_session_ != NULL);
25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return recv_session_->UnprotectRtp(p, in_len, out_len);
25628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::UnprotectRtcp(void* p, int in_len, int* out_len) {
25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!IsActive()) {
26028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
26128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
26228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
26328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (recv_rtcp_session_) {
26428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
26528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  } else {
2662e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org    ASSERT(recv_session_ != NULL);
26728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return recv_session_->UnprotectRtcp(p, in_len, out_len);
26828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
26928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
27028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
2710c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SrtpFilter::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) {
272a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  if (!IsActive()) {
273a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active";
274a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    return false;
275a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  }
276a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org
2772e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org  ASSERT(send_session_ != NULL);
278a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  return send_session_->GetRtpAuthParams(key, key_len, tag_len);
279a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org}
280a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org
2810c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmvoid SrtpFilter::set_signal_silent_time(uint32_t signal_silent_time_in_ms) {
28228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  signal_silent_time_in_ms_ = signal_silent_time_in_ms;
2832e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org  if (IsActive()) {
2842e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org    ASSERT(send_session_ != NULL);
28528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    send_session_->set_signal_silent_time(signal_silent_time_in_ms);
2862e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org    ASSERT(recv_session_ != NULL);
28728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    recv_session_->set_signal_silent_time(signal_silent_time_in_ms);
28828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (send_rtcp_session_)
28928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms);
29028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (recv_rtcp_session_)
29128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms);
29228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
29328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
29428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
29528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::ExpectOffer(ContentSource source) {
29628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return ((state_ == ST_INIT) ||
29728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_ACTIVE) ||
29828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_  == ST_SENTOFFER && source == CS_LOCAL) ||
29928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_  == ST_SENTUPDATEDOFFER && source == CS_LOCAL) ||
30028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) ||
30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE));
30228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
30328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
30428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params,
30528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                             ContentSource source) {
30628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  offer_params_ = params;
30728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (state_ == ST_INIT) {
30828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
3092e7ee4b28bbdf92bdf804b600ae33679d1799788pthatcher@webrtc.org  } else if (state_ == ST_ACTIVE) {
31028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    state_ =
31128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        (source == CS_LOCAL) ? ST_SENTUPDATEDOFFER : ST_RECEIVEDUPDATEDOFFER;
31228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
31328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
31428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
31528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
31628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::ExpectAnswer(ContentSource source) {
31728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
31828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL) ||
31928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_SENTUPDATEDOFFER && source == CS_REMOTE) ||
32028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_LOCAL) ||
32128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_SENTPRANSWER_NO_CRYPTO && source == CS_LOCAL) ||
32228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_SENTPRANSWER && source == CS_LOCAL) ||
32328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_RECEIVEDPRANSWER_NO_CRYPTO && source == CS_REMOTE) ||
32428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          (state_ == ST_RECEIVEDPRANSWER && source == CS_REMOTE));
32528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
32628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
32728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::DoSetAnswer(const std::vector<CryptoParams>& answer_params,
32828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                             ContentSource source,
32928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                             bool final) {
33028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!ExpectAnswer(source)) {
33128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Invalid state for SRTP answer";
33228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
33328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
33428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
33528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // If the answer doesn't requests crypto complete the negotiation of an
33628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // unencrypted session.
33728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Otherwise, finalize the parameters and apply them.
33828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (answer_params.empty()) {
33928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (final) {
34028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      return ResetParams();
34128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    } else {
34228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      // Need to wait for the final answer to decide if
34328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      // we should go to Active state.
34428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO :
34528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                                      ST_RECEIVEDPRANSWER_NO_CRYPTO;
34628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      return true;
34728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
34828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
34928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  CryptoParams selected_params;
35028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!NegotiateParams(answer_params, &selected_params))
35128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
35228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  const CryptoParams& send_params =
35328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      (source == CS_REMOTE) ? selected_params : answer_params[0];
35428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  const CryptoParams& recv_params =
35528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      (source == CS_REMOTE) ? answer_params[0] : selected_params;
35628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!ApplyParams(send_params, recv_params)) {
35728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
35828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
35928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
36028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (final) {
36128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    offer_params_.clear();
36228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    state_ = ST_ACTIVE;
36328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  } else {
36428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    state_ =
36528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER;
36628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
36728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
36828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
36928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
37028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SrtpFilter::CreateSrtpSessions() {
37128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  send_session_.reset(new SrtpSession());
37228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  applied_send_params_ = CryptoParams();
37328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  recv_session_.reset(new SrtpSession());
37428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  applied_recv_params_ = CryptoParams();
37528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
37628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SignalSrtpError.repeat(send_session_->SignalSrtpError);
37728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SignalSrtpError.repeat(recv_session_->SignalSrtpError);
37828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
37928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  send_session_->set_signal_silent_time(signal_silent_time_in_ms_);
38028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  recv_session_->set_signal_silent_time(signal_silent_time_in_ms_);
38128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
38228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
38328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params,
38428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                                 CryptoParams* selected_params) {
38528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // We're processing an accept. We should have exactly one set of params,
38628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // unless the offer didn't mention crypto, in which case we shouldn't be here.
38728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  bool ret = (answer_params.size() == 1U && !offer_params_.empty());
38828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (ret) {
38928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    // We should find a match between the answer params and the offered params.
39028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    std::vector<CryptoParams>::const_iterator it;
39128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    for (it = offer_params_.begin(); it != offer_params_.end(); ++it) {
39228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      if (answer_params[0].Matches(*it)) {
39328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        break;
39428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      }
39528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
39628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
39728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (it != offer_params_.end()) {
39828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      *selected_params = *it;
39928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    } else {
40028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      ret = false;
40128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
40228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
40328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
40428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!ret) {
40528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Invalid parameters in SRTP answer";
40628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
40728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return ret;
40828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
40928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
41028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::ApplyParams(const CryptoParams& send_params,
41128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                             const CryptoParams& recv_params) {
41228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // TODO(jiayl): Split this method to apply send and receive CryptoParams
41328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // independently, so that we can skip one method when either send or receive
41428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // CryptoParams is unchanged.
41528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (applied_send_params_.cipher_suite == send_params.cipher_suite &&
41628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      applied_send_params_.key_params == send_params.key_params &&
41728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      applied_recv_params_.cipher_suite == recv_params.cipher_suite &&
41828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      applied_recv_params_.key_params == recv_params.key_params) {
41928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op.";
42028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
42128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    // We do not want to reset the ROC if the keys are the same. So just return.
42228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return true;
42328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
42428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // TODO(juberti): Zero these buffers after use.
42528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  bool ret;
4260c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN];
42728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) &&
42828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org         ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key)));
42928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (ret) {
43028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    CreateSrtpSessions();
431521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh    ret = (send_session_->SetSend(
432521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh               rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite), send_key,
433521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh               sizeof(send_key)) &&
434521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh           recv_session_->SetRecv(
435521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh               rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite), recv_key,
436521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh               sizeof(recv_key)));
43728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
43828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (ret) {
43928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
44028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                 << " send cipher_suite " << send_params.cipher_suite
44128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                 << " recv cipher_suite " << recv_params.cipher_suite;
44228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    applied_send_params_ = send_params;
44328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    applied_recv_params_ = recv_params;
44428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  } else {
44528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters";
44628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
44728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return ret;
44828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
44928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
45028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::ResetParams() {
45128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  offer_params_.clear();
45228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  state_ = ST_INIT;
45377fa59d78923815ef7403bd738784e9c0be24c54guoweis  send_session_ = nullptr;
45477fa59d78923815ef7403bd738784e9c0be24c54guoweis  recv_session_ = nullptr;
45577fa59d78923815ef7403bd738784e9c0be24c54guoweis  send_rtcp_session_ = nullptr;
45677fa59d78923815ef7403bd738784e9c0be24c54guoweis  recv_rtcp_session_ = nullptr;
45728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(LS_INFO) << "SRTP reset to init state";
45828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
45928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
46028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
46128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpFilter::ParseKeyParams(const std::string& key_params,
4620c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                uint8_t* key,
4630c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                int len) {
46428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
46528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
46628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Fail if key-method is wrong.
46728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (key_params.find("inline:") != 0) {
46828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
46928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
47028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
47128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Fail if base64 decode fails, or the key is the wrong size.
47228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  std::string key_b64(key_params.substr(7)), key_str;
473d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT,
47428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                                 &key_str, NULL) ||
47528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      static_cast<int>(key_str.size()) != len) {
47628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
47728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
47828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
47928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  memcpy(key, key_str.c_str(), len);
48028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
48128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
48228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
48328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
48428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// SrtpSession
48528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
48628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifdef HAVE_SRTP
48728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
48828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::inited_ = false;
489e70028e43fded41310d41cc93b90f2e689c04725Joachim Bauch
490cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund// This lock protects SrtpSession::inited_ and SrtpSession::sessions_.
49146ad5426b025eddac8e9232014d347e73d27180epbosrtc::GlobalLockPod SrtpSession::lock_;
49228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
49328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSrtpSession::SrtpSession()
49428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    : session_(NULL),
49528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      rtp_auth_tag_len_(0),
49628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      rtcp_auth_tag_len_(0),
49728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      srtp_stat_(new SrtpStat()),
49828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      last_send_seq_num_(-1) {
499cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund  {
500cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund    rtc::GlobalLockScope ls(&lock_);
501cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund    sessions()->push_back(this);
502cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund  }
50328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SignalSrtpError.repeat(srtp_stat_->SignalSrtpError);
50428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
50528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
50628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSrtpSession::~SrtpSession() {
507cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund  {
508cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund    rtc::GlobalLockScope ls(&lock_);
509cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund    sessions()->erase(std::find(sessions()->begin(), sessions()->end(), this));
510cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund  }
51128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (session_) {
51228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    srtp_dealloc(session_);
51328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
51428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
51528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
516521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shiehbool SrtpSession::SetSend(int cs, const uint8_t* key, int len) {
51728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return SetKey(ssrc_any_outbound, cs, key, len);
51828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
51928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
520521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shiehbool SrtpSession::SetRecv(int cs, const uint8_t* key, int len) {
52128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return SetKey(ssrc_any_inbound, cs, key, len);
52228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
52328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
52428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
52528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!session_) {
52628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session";
52728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
52828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
52928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
53028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int need_len = in_len + rtp_auth_tag_len_;  // NOLINT
53128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (max_len < need_len) {
53228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length "
53328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                    << max_len << " is less than the needed " << need_len;
53428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
53528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
53628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
53728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  *out_len = in_len;
53828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int err = srtp_protect(session_, p, out_len);
5390c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t ssrc;
54028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (GetRtpSsrc(p, in_len, &ssrc)) {
54128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    srtp_stat_->AddProtectRtpResult(ssrc, err);
54228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
54328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int seq_num;
54428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GetRtpSeqNum(p, in_len, &seq_num);
54528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (err != err_status_ok) {
54628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTP packet, seqnum="
54728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                    << seq_num << ", err=" << err << ", last seqnum="
54828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                    << last_send_seq_num_;
54928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
55028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
55128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  last_send_seq_num_ = seq_num;
55228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
55328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
55428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
5550c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SrtpSession::ProtectRtp(void* p,
5560c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                             int in_len,
5570c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                             int max_len,
5580c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                             int* out_len,
5590c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                             int64_t* index) {
560a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  if (!ProtectRtp(p, in_len, max_len, out_len)) {
561a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    return false;
562a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  }
563a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  return (index) ? GetSendStreamPacketIndex(p, in_len, index) : true;
564a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org}
565a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org
56628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
56728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!session_) {
56828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session";
56928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
57028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
57128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
5720c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  int need_len = in_len + sizeof(uint32_t) + rtcp_auth_tag_len_;  // NOLINT
57328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (max_len < need_len) {
57428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length "
57528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                    << max_len << " is less than the needed " << need_len;
57628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
57728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
57828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
57928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  *out_len = in_len;
58028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int err = srtp_protect_rtcp(session_, p, out_len);
58128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  srtp_stat_->AddProtectRtcpResult(err);
58228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (err != err_status_ok) {
58328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err;
58428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
58528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
58628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
58728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
58828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
58928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) {
59028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!session_) {
59128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session";
59228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
59328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
59428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
59528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  *out_len = in_len;
59628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int err = srtp_unprotect(session_, p, out_len);
5970c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t ssrc;
59828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (GetRtpSsrc(p, in_len, &ssrc)) {
59928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    srtp_stat_->AddUnprotectRtpResult(ssrc, err);
60028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
60128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (err != err_status_ok) {
60228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err;
60328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
60428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
60528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
60628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
60728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
60828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) {
60928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!session_) {
61028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session";
61128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
61228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
61328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
61428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  *out_len = in_len;
61528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int err = srtp_unprotect_rtcp(session_, p, out_len);
61628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  srtp_stat_->AddUnprotectRtcpResult(err);
61728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (err != err_status_ok) {
61828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err;
61928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
62028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
62128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
62228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
62328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
6240c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SrtpSession::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) {
625a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#if defined(ENABLE_EXTERNAL_AUTH)
626a9cf079248e1274b2ddf36ab1dc179a2b6eb9debpbos@webrtc.org  ExternalHmacContext* external_hmac = NULL;
627a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  // stream_template will be the reference context for other streams.
628a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  // Let's use it for getting the keys.
629a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  srtp_stream_ctx_t* srtp_context = session_->stream_template;
630a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  if (srtp_context && srtp_context->rtp_auth) {
631a9cf079248e1274b2ddf36ab1dc179a2b6eb9debpbos@webrtc.org    external_hmac = reinterpret_cast<ExternalHmacContext*>(
632a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org        srtp_context->rtp_auth->state);
633a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  }
634a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org
635a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  if (!external_hmac) {
636a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    LOG(LS_ERROR) << "Failed to get auth keys from libsrtp!.";
637a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    return false;
638a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  }
639a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org
640a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  *key = external_hmac->key;
641a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  *key_len = external_hmac->key_length;
642a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  *tag_len = rtp_auth_tag_len_;
643a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  return true;
644a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#else
645a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  return false;
646a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#endif
647a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org}
648a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org
6490c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SrtpSession::GetSendStreamPacketIndex(void* p,
6500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                           int in_len,
6510c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                           int64_t* index) {
652a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  srtp_hdr_t* hdr = reinterpret_cast<srtp_hdr_t*>(p);
653a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  srtp_stream_ctx_t* stream = srtp_get_stream(session_, hdr->ssrc);
654a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  if (stream == NULL)
655a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    return false;
656a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org
65705376341549062f82114c96bc8d95435c00c0479henrike@webrtc.org  // Shift packet index, put into network byte order
6580c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  *index = static_cast<int64_t>(
6594b3c0d6f34c379c2a06f654b62403876b20180c6Jiayang Liu      rtc::NetworkToHost64(rdbx_get_packet_index(&stream->rtp_rdbx) << 16));
660a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  return true;
661a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org}
662a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org
6630c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmvoid SrtpSession::set_signal_silent_time(uint32_t signal_silent_time_in_ms) {
66428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms);
66528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
66628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
667521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shiehbool SrtpSession::SetKey(int type, int cs, const uint8_t* key, int len) {
66828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (session_) {
66928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Failed to create SRTP session: "
67028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                  << "SRTP session already created";
67128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
67228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
67328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
67428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!Init()) {
67528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
67628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
67728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
67828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  srtp_policy_t policy;
67928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  memset(&policy, 0, sizeof(policy));
68028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
681521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh  if (cs == rtc::SRTP_AES128_CM_SHA1_80) {
68228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
68328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
684521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh  } else if (cs == rtc::SRTP_AES128_CM_SHA1_32) {
68528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);   // rtp is 32,
68628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);  // rtcp still 80
68728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  } else {
68828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to create SRTP session: unsupported"
689521ed7bf022c4e30574d7970c2be5be46567f4cdGuo-wei Shieh                    << " cipher_suite " << cs;
69028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
69128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
69228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
69328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!key || len != SRTP_MASTER_KEY_LEN) {
69428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to create SRTP session: invalid key";
69528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
69628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
69728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
69828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  policy.ssrc.type = static_cast<ssrc_type_t>(type);
69928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  policy.ssrc.value = 0;
7000c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  policy.key = const_cast<uint8_t*>(key);
70128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // TODO(astor) parse window size from WSH session-param
70228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  policy.window_size = 1024;
70328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  policy.allow_repeat_tx = 1;
704a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  // If external authentication option is enabled, supply custom auth module
705a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  // id EXTERNAL_HMAC_SHA1 in the policy structure.
706a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  // We want to set this option only for rtp packets.
707a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org  // By default policy structure is initialized to HMAC_SHA1.
708a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#if defined(ENABLE_EXTERNAL_AUTH)
70905376341549062f82114c96bc8d95435c00c0479henrike@webrtc.org  // Enable external HMAC authentication only for outgoing streams.
71005376341549062f82114c96bc8d95435c00c0479henrike@webrtc.org  if (type == ssrc_any_outbound) {
71105376341549062f82114c96bc8d95435c00c0479henrike@webrtc.org    policy.rtp.auth_type = EXTERNAL_HMAC_SHA1;
71205376341549062f82114c96bc8d95435c00c0479henrike@webrtc.org  }
713a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#endif
71428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  policy.next = NULL;
71528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
71628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int err = srtp_create(&session_, &policy);
71728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (err != err_status_ok) {
718fec2c6d7eb58574b32eaa26222d3fb903b738cfaJoachim Bauch    session_ = NULL;
71928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err;
72028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
72128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
72228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
723cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund
72428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  rtp_auth_tag_len_ = policy.rtp.auth_tag_len;
72528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len;
72628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
72728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
72828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
72928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::Init() {
730fec2c6d7eb58574b32eaa26222d3fb903b738cfaJoachim Bauch  rtc::GlobalLockScope ls(&lock_);
731fec2c6d7eb58574b32eaa26222d3fb903b738cfaJoachim Bauch
73228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!inited_) {
73328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    int err;
73428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    err = srtp_init();
73528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (err != err_status_ok) {
73628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      LOG(LS_ERROR) << "Failed to init SRTP, err=" << err;
73728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      return false;
73828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
73928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
74028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    err = srtp_install_event_handler(&SrtpSession::HandleEventThunk);
74128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (err != err_status_ok) {
74228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      LOG(LS_ERROR) << "Failed to install SRTP event handler, err=" << err;
74328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      return false;
74428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
745a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#if defined(ENABLE_EXTERNAL_AUTH)
746a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    err = external_crypto_init();
747a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    if (err != err_status_ok) {
748a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org      LOG(LS_ERROR) << "Failed to initialize fake auth, err=" << err;
749a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org      return false;
750a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org    }
751a7b981843f35bb6c26cf3bc95b5a00a0b9f50a93henrike@webrtc.org#endif
75228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    inited_ = true;
75328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
75428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
75528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
75628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
75728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
7589dba52562725dbaced0d671982201ede753d72e8wu@webrtc.orgvoid SrtpSession::Terminate() {
759fec2c6d7eb58574b32eaa26222d3fb903b738cfaJoachim Bauch  rtc::GlobalLockScope ls(&lock_);
760fec2c6d7eb58574b32eaa26222d3fb903b738cfaJoachim Bauch
7619dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org  if (inited_) {
7629dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org    int err = srtp_shutdown();
7639dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org    if (err) {
7649dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org      LOG(LS_ERROR) << "srtp_shutdown failed. err=" << err;
7659dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org      return;
7669dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org    }
7679dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org    inited_ = false;
7689dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org  }
7699dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org}
7709dba52562725dbaced0d671982201ede753d72e8wu@webrtc.org
77128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SrtpSession::HandleEvent(const srtp_event_data_t* ev) {
77228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  switch (ev->event) {
77328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case event_ssrc_collision:
77428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: SSRC collision";
77528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
77628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case event_key_soft_limit:
77728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: reached soft key usage limit";
77828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
77928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case event_key_hard_limit:
78028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: reached hard key usage limit";
78128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
78228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case event_packet_index_limit:
78328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: reached hard packet limit (2^48 packets)";
78428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
78528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    default:
78628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      LOG(LS_INFO) << "SRTP event: unknown " << ev->event;
78728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
78828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
78928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
79028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
79128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SrtpSession::HandleEventThunk(srtp_event_data_t* ev) {
792cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund  rtc::GlobalLockScope ls(&lock_);
793cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund
794cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund  for (std::list<SrtpSession*>::iterator it = sessions()->begin();
795cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund       it != sessions()->end(); ++it) {
796cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund    if ((*it)->session_ == ev->session) {
797cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund      (*it)->HandleEvent(ev);
798cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund      break;
799cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund    }
80028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
80128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
80228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
803cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglundstd::list<SrtpSession*>* SrtpSession::sessions() {
804cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund  RTC_DEFINE_STATIC_LOCAL(std::list<SrtpSession*>, sessions, ());
805cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund  return &sessions;
806cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund}
807cbe9f51cf85a5aeb20a5134dad56cd2b527c098dphoglund
80828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#else   // !HAVE_SRTP
80928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
81028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// On some systems, SRTP is not (yet) available.
81128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
81228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSrtpSession::SrtpSession() {
81328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(WARNING) << "SRTP implementation is missing.";
81428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
81528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
81628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSrtpSession::~SrtpSession() {
81728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
81828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
8190c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SrtpSession::SetSend(const std::string& cs, const uint8_t* key, int len) {
82028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
82128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
82228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
8230c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool SrtpSession::SetRecv(const std::string& cs, const uint8_t* key, int len) {
82428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
82528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
82628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
82728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::ProtectRtp(void* data, int in_len, int max_len,
82828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                             int* out_len) {
82928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
83028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
83128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
83228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::ProtectRtcp(void* data, int in_len, int max_len,
83328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                              int* out_len) {
83428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
83528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
83628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
83728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::UnprotectRtp(void* data, int in_len, int* out_len) {
83828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
83928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
84028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
84128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool SrtpSession::UnprotectRtcp(void* data, int in_len, int* out_len) {
84228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return SrtpNotAvailable(__FUNCTION__);
84328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
84428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
8450c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmvoid SrtpSession::set_signal_silent_time(uint32_t signal_silent_time) {
84628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Do nothing.
84728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
84828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
84928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif  // HAVE_SRTP
85028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
85128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////////
85228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// SrtpStat
85328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
85428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifdef HAVE_SRTP
85528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
85628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSrtpStat::SrtpStat()
85728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    : signal_silent_time_(1000) {
85828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
85928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
8600c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmvoid SrtpStat::AddProtectRtpResult(uint32_t ssrc, int result) {
86128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  FailureKey key;
86228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  key.ssrc = ssrc;
86328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  key.mode = SrtpFilter::PROTECT;
86428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  switch (result) {
86528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case err_status_ok:
86628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      key.error = SrtpFilter::ERROR_NONE;
86728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
86828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case err_status_auth_fail:
86928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      key.error = SrtpFilter::ERROR_AUTH;
87028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
87128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    default:
87228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      key.error = SrtpFilter::ERROR_FAIL;
87328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
87428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  HandleSrtpResult(key);
87528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
87628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
8770c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmvoid SrtpStat::AddUnprotectRtpResult(uint32_t ssrc, int result) {
87828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  FailureKey key;
87928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  key.ssrc = ssrc;
88028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  key.mode = SrtpFilter::UNPROTECT;
88128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  switch (result) {
88228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case err_status_ok:
88328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      key.error = SrtpFilter::ERROR_NONE;
88428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
88528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case err_status_auth_fail:
88628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      key.error = SrtpFilter::ERROR_AUTH;
88728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
88828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case err_status_replay_fail:
88928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    case err_status_replay_old:
89028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      key.error = SrtpFilter::ERROR_REPLAY;
89128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      break;
89228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    default:
89328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      key.error = SrtpFilter::ERROR_FAIL;
89428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
89528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  HandleSrtpResult(key);
89628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
89728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
89828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SrtpStat::AddProtectRtcpResult(int result) {
89928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  AddProtectRtpResult(0U, result);
90028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
90128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
90228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SrtpStat::AddUnprotectRtcpResult(int result) {
90328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  AddUnprotectRtpResult(0U, result);
90428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
90528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
90628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
90728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Handle some cases where error should be signalled right away. For other
90828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // errors, trigger error for the first time seeing it.  After that, silent
90928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // the same error for a certain amount of time (default 1 sec).
91028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (key.error != SrtpFilter::ERROR_NONE) {
91128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    // For errors, signal first time and wait for 1 sec.
91228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    FailureStat* stat = &(failures_[key]);
9130c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint32_t current_time = rtc::Time();
91428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (stat->last_signal_time == 0 ||
915d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org        rtc::TimeDiff(current_time, stat->last_signal_time) >
91628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        static_cast<int>(signal_silent_time_)) {
91728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      SignalSrtpError(key.ssrc, key.mode, key.error);
91828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      stat->last_signal_time = current_time;
91928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
92028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
92128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
92228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
92328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#else   // !HAVE_SRTP
92428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
92528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// On some systems, SRTP is not (yet) available.
92628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
92728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgSrtpStat::SrtpStat()
92828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    : signal_silent_time_(1000) {
92928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(WARNING) << "SRTP implementation is missing.";
93028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
93128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
9320c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmvoid SrtpStat::AddProtectRtpResult(uint32_t ssrc, int result) {
93328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
93428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
93528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
9360c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmvoid SrtpStat::AddUnprotectRtpResult(uint32_t ssrc, int result) {
93728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
93828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
93928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
94028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SrtpStat::AddProtectRtcpResult(int result) {
94128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
94228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
94328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
94428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SrtpStat::AddUnprotectRtcpResult(int result) {
94528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
94628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
94728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
94828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) {
94928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SrtpNotAvailable(__FUNCTION__);
95028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
95128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
95228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif  // HAVE_SRTP
95328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
95428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}  // namespace cricket
955