1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2009, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// talk's config.h, generated from mac_config_dot_h for OSX, conflicts with the
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// one included by the libsrtp headers. Don't use it. Instead, we keep HAVE_SRTP
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// and LOGGING defined in config.h.
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#undef HAVE_CONFIG_H
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#ifdef OSX
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// TODO: For the XCode build, we force SRTP (b/2500074)
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#ifndef HAVE_SRTP
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#define HAVE_SRTP 1
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif  // HAVE_SRTP
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// If LOGGING is not defined, define it to 1 (b/3245816)
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#ifndef LOGGING
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#define LOGGING 1
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif  // HAVE_SRTP
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/session/phone/srtpfilter.h"
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <algorithm>
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <cstring>
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/base64.h"
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h"
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Enable this line to turn on SRTP debugging
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// #define SRTP_DEBUG
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef HAVE_SRTP
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#ifdef SRTP_RELATIVE_PATH
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "srtp.h"  // NOLINT
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#else
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "third_party/libsrtp/include/srtp.h"
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif  // SRTP_RELATIVE_PATH
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG
62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochextern "C" debug_module_t mod_srtp;
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// SrtpFilter needs that constant.
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define SRTP_MASTER_KEY_LEN 30
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // HAVE_SRTP
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace cricket {
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string& CS_DEFAULT = CS_AES_CM_128_HMAC_SHA1_80;
72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string CS_AES_CM_128_HMAC_SHA1_80 = "AES_CM_128_HMAC_SHA1_80";
73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst std::string CS_AES_CM_128_HMAC_SHA1_32 = "AES_CM_128_HMAC_SHA1_32";
744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochconst int SRTP_MASTER_KEY_BASE64_LEN = SRTP_MASTER_KEY_LEN * 4 / 3;
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSrtpFilter::SrtpFilter() : state_(ST_INIT) {
77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSrtpFilter::~SrtpFilter() {
80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::IsActive() const {
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return (state_ == ST_ACTIVE);
84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::SetOffer(const std::vector<CryptoParams>& offer_params,
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          ContentSource source) {
88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret = false;
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (state_ == ST_INIT) {
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret = StoreParams(offer_params, source);
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "Invalid state for SRTP offer";
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params,
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                           ContentSource source) {
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret = false;
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if ((state_ == ST_SENTOFFER && source == CS_REMOTE) ||
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL)) {
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // If the answer requests crypto, finalize the parameters and apply them.
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // Otherwise, complete the negotiation of a unencrypted session.
104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!answer_params.empty()) {
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      CryptoParams selected_params;
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ret = NegotiateParams(answer_params, &selected_params);
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (ret) {
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        if (state_ == ST_SENTOFFER) {
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          ret = ApplyParams(selected_params, answer_params[0]);
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        } else {  // ST_RECEIVEDOFFER
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch          ret = ApplyParams(answer_params[0], selected_params);
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        }
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ret = ResetParams();
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "Invalid state for SRTP answer";
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!IsActive()) {
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return send_session_.ProtectRtp(p, in_len, max_len, out_len);
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!IsActive()) {
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active";
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return send_session_.ProtectRtcp(p, in_len, max_len, out_len);
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::UnprotectRtp(void* p, int in_len, int* out_len) {
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!IsActive()) {
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return recv_session_.UnprotectRtp(p, in_len, out_len);
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::UnprotectRtcp(void* p, int in_len, int* out_len) {
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!IsActive()) {
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active";
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return recv_session_.UnprotectRtcp(p, in_len, out_len);
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params,
1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             ContentSource source) {
158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  offer_params_ = params;
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params,
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                 CryptoParams* selected_params) {
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // We're processing an accept. We should have exactly one set of params,
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // unless the offer didn't mention crypto, in which case we shouldn't be here.
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret = (answer_params.size() == 1U && !offer_params_.empty());
168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // We should find a match between the answer params and the offered params.
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    std::vector<CryptoParams>::const_iterator it;
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    for (it = offer_params_.begin(); it != offer_params_.end(); ++it) {
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      if (answer_params[0].Matches(*it)) {
173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        break;
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      }
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (it != offer_params_.end()) {
178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      *selected_params = *it;
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    } else {
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ret = false;
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ret) {
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_WARNING) << "Invalid parameters in SRTP answer";
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::ApplyParams(const CryptoParams& send_params,
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                             const CryptoParams& recv_params) {
192731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO: Zero these buffers after use.
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  bool ret;
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint8 send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN];
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) &&
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch         ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key)));
197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ret = (send_session_.SetSend(send_params.cipher_suite,
199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                 send_key, sizeof(send_key)) &&
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch           recv_session_.SetRecv(recv_params.cipher_suite,
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                 recv_key, sizeof(recv_key)));
202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (ret) {
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    offer_params_.clear();
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    state_ = ST_ACTIVE;
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_INFO) << "SRTP activated with negotiated parameters:"
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                 << " send cipher_suite " << send_params.cipher_suite
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                 << " recv cipher_suite " << recv_params.cipher_suite;
209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters";
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return ret;
213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::ResetParams() {
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  offer_params_.clear();
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  state_ = ST_INIT;
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  LOG(LS_INFO) << "SRTP reset to init state";
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpFilter::ParseKeyParams(const std::string& key_params,
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                uint8* key, int len) {
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2"
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Fail if key-method is wrong.
227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (key_params.find("inline:") != 0) {
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Fail if base64 decode fails, or the key is the wrong size.
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  std::string key_b64(key_params.substr(7)), key_str;
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!talk_base::Base64::Decode(key_b64, talk_base::Base64::DO_STRICT,
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                 &key_str, NULL) ||
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      static_cast<int>(key_str.size()) != len) {
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  memcpy(key, key_str.c_str(), len);
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch///////////////////////////////////////////////////////////////////////////////
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// SrtpSession
245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef HAVE_SRTP
247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::inited_ = false;
249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::list<SrtpSession*> SrtpSession::sessions_;
250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSrtpSession::SrtpSession()
252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : session_(NULL), rtp_auth_tag_len_(0), rtcp_auth_tag_len_(0) {
253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  sessions_.push_back(this);
254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSrtpSession::~SrtpSession() {
257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  sessions_.erase(std::find(sessions_.begin(), sessions_.end(), this));
258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (session_) {
259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    srtp_dealloc(session_);
260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SetKey(ssrc_any_outbound, cs, key, len);
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SetKey(ssrc_any_inbound, cs, key, len);
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) {
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!session_) {
273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session";
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int need_len = in_len + rtp_auth_tag_len_;  // NOLINT
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (max_len < need_len) {
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length "
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    << max_len << " is less than the needed " << need_len;
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *out_len = in_len;
285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int err = srtp_protect(session_, p, out_len);
286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (err != err_status_ok) {
287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_WARNING) << "Failed to protect SRTP packet, err=" << err;
288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) {
294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!session_) {
295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session";
296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int need_len = in_len + sizeof(uint32) + rtcp_auth_tag_len_;  // NOLINT
300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (max_len < need_len) {
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length "
302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    << max_len << " is less than the needed " << need_len;
303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *out_len = in_len;
307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int err = srtp_protect_rtcp(session_, p, out_len);
308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (err != err_status_ok) {
309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err;
310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) {
316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!session_) {
317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session";
318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *out_len = in_len;
322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int err = srtp_unprotect(session_, p, out_len);
323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (err != err_status_ok) {
324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err;
325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) {
331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!session_) {
332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session";
333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  *out_len = in_len;
337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int err = srtp_unprotect_rtcp(session_, p, out_len);
338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (err != err_status_ok) {
339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err;
340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::SetKey(int type, const std::string& cs,
346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                         const uint8* key, int len) {
347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (session_) {
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_ERROR) << "Failed to create SRTP session: "
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                  << "SRTP session already created";
350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!Init()) {
354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  srtp_policy_t policy;
358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  memset(&policy, 0, sizeof(policy));
359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (cs == CS_AES_CM_128_HMAC_SHA1_80) {
361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else if (cs == CS_AES_CM_128_HMAC_SHA1_32) {
364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);   // rtp is 32,
365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);  // rtcp still 80
366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to create SRTP session: unsupported"
368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                    << " cipher_suite " << cs.c_str();
369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!key || len != SRTP_MASTER_KEY_LEN) {
373dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LOG(LS_WARNING) << "Failed to create SRTP session: invalid key";
374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  policy.ssrc.type = static_cast<ssrc_type_t>(type);
378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  policy.ssrc.value = 0;
379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  policy.key = const_cast<uint8*>(key);
380731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO parse window size from WSH session-param
381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  policy.window_size = 1024;
382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  policy.allow_repeat_tx = 1;
383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  policy.next = NULL;
384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  int err = srtp_create(&session_, &policy);
386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (err != err_status_ok) {
387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err;
388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return false;
389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  rtp_auth_tag_len_ = policy.rtp.auth_tag_len;
392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len;
393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::Init() {
397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!inited_) {
398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    int err;
399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef DEBUG_SRTP
400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    debug_on(mod_srtp);
401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif
402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    err = srtp_init();
403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (err != err_status_ok) {
404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_ERROR) << "Failed to init SRTP, err=" << err;
405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    err = srtp_install_event_handler(&SrtpSession::HandleEventThunk);
409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (err != err_status_ok) {
410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(LS_ERROR) << "Failed to install SRTP event handler, err=" << err;
411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return false;
412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    inited_ = true;
415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return true;
418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SrtpSession::HandleEvent(const srtp_event_data_t* ev) {
421dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switch (ev->event) {
422dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case event_ssrc_collision:
423dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(LS_INFO) << "SRTP event: SSRC collision";
424dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
425dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case event_key_soft_limit:
426dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(LS_INFO) << "SRTP event: reached soft key usage limit";
427dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
428dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case event_key_hard_limit:
429dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(LS_INFO) << "SRTP event: reached hard key usage limit";
430dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
431dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    case event_packet_index_limit:
432dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(LS_INFO) << "SRTP event: reached hard packet limit (2^48 packets)";
433dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
434dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    default:
435dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      LOG(LS_INFO) << "SRTP event: unknown " << ev->event;
436dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      break;
437dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SrtpSession::HandleEventThunk(srtp_event_data_t* ev) {
441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (std::list<SrtpSession*>::iterator it = sessions_.begin();
442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch       it != sessions_.end(); ++it) {
443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if ((*it)->session_ == ev->session) {
444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      (*it)->HandleEvent(ev);
445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      break;
446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else   // !HAVE_SRTP
451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace {
453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpNotAvailable(const char *func) {
454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(LS_ERROR) << func << ": SRTP is not available on your system.";
455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return false;
456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}  // anonymous namespace
458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSrtpSession::SrtpSession() {
460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  LOG(WARNING) << "SRTP implementation is missing.";
461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSrtpSession::~SrtpSession() {
464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::SetSend(const std::string& cs, const uint8* key, int len) {
467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SrtpNotAvailable(__FUNCTION__);
468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::SetRecv(const std::string& cs, const uint8* key, int len) {
471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SrtpNotAvailable(__FUNCTION__);
472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
4743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SrtpSession::ProtectRtp(void* data, int in_len, int max_len,
4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                             int* out_len) {
476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SrtpNotAvailable(__FUNCTION__);
477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
4793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SrtpSession::ProtectRtcp(void* data, int in_len, int max_len,
4803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                              int* out_len) {
481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SrtpNotAvailable(__FUNCTION__);
482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::UnprotectRtp(void* data, int in_len, int* out_len) {
485f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SrtpNotAvailable(__FUNCTION__);
486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
487f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SrtpSession::UnprotectRtcp(void* data, int in_len, int* out_len) {
489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return SrtpNotAvailable(__FUNCTION__);
490f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
491f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif  // HAVE_SRTP
493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}  // namespace cricket
494