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