1 /* 2 * libjingle 3 * Copyright 2009 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef TALK_SESSION_MEDIA_SRTPFILTER_H_ 29 #define TALK_SESSION_MEDIA_SRTPFILTER_H_ 30 31 #include <list> 32 #include <map> 33 #include <string> 34 #include <vector> 35 36 #include "talk/base/basictypes.h" 37 #include "talk/base/scoped_ptr.h" 38 #include "talk/base/sigslotrepeater.h" 39 #include "talk/media/base/cryptoparams.h" 40 #include "talk/p2p/base/sessiondescription.h" 41 42 // Forward declaration to avoid pulling in libsrtp headers here 43 struct srtp_event_data_t; 44 struct srtp_ctx_t; 45 typedef srtp_ctx_t* srtp_t; 46 struct srtp_policy_t; 47 48 namespace cricket { 49 50 // Cipher suite to use for SRTP. Typically a 80-bit HMAC will be used, except 51 // in applications (voice) where the additional bandwidth may be significant. 52 // A 80-bit HMAC is always used for SRTCP. 53 // 128-bit AES with 80-bit SHA-1 HMAC. 54 extern const char CS_AES_CM_128_HMAC_SHA1_80[]; 55 // 128-bit AES with 32-bit SHA-1 HMAC. 56 extern const char CS_AES_CM_128_HMAC_SHA1_32[]; 57 // Key is 128 bits and salt is 112 bits == 30 bytes. B64 bloat => 40 bytes. 58 extern const int SRTP_MASTER_KEY_BASE64_LEN; 59 60 // Needed for DTLS-SRTP 61 extern const int SRTP_MASTER_KEY_KEY_LEN; 62 extern const int SRTP_MASTER_KEY_SALT_LEN; 63 64 class SrtpSession; 65 class SrtpStat; 66 67 void EnableSrtpDebugging(); 68 void ShutdownSrtp(); 69 70 // Class to transform SRTP to/from RTP. 71 // Initialize by calling SetSend with the local security params, then call 72 // SetRecv once the remote security params are received. At that point 73 // Protect/UnprotectRt(c)p can be called to encrypt/decrypt data. 74 // TODO: Figure out concurrency policy for SrtpFilter. 75 class SrtpFilter { 76 public: 77 enum Mode { 78 PROTECT, 79 UNPROTECT 80 }; 81 enum Error { 82 ERROR_NONE, 83 ERROR_FAIL, 84 ERROR_AUTH, 85 ERROR_REPLAY, 86 }; 87 88 SrtpFilter(); 89 ~SrtpFilter(); 90 91 // Whether the filter is active (i.e. crypto has been properly negotiated). 92 bool IsActive() const; 93 94 // Indicates which crypto algorithms and keys were contained in the offer. 95 // offer_params should contain a list of available parameters to use, or none, 96 // if crypto is not desired. This must be called before SetAnswer. 97 bool SetOffer(const std::vector<CryptoParams>& offer_params, 98 ContentSource source); 99 // Same as SetAnwer. But multiple calls are allowed to SetProvisionalAnswer 100 // after a call to SetOffer. 101 bool SetProvisionalAnswer(const std::vector<CryptoParams>& answer_params, 102 ContentSource source); 103 // Indicates which crypto algorithms and keys were contained in the answer. 104 // answer_params should contain the negotiated parameters, which may be none, 105 // if crypto was not desired or could not be negotiated (and not required). 106 // This must be called after SetOffer. If crypto negotiation completes 107 // successfully, this will advance the filter to the active state. 108 bool SetAnswer(const std::vector<CryptoParams>& answer_params, 109 ContentSource source); 110 111 // Just set up both sets of keys directly. 112 // Used with DTLS-SRTP. 113 bool SetRtpParams(const std::string& send_cs, 114 const uint8* send_key, int send_key_len, 115 const std::string& recv_cs, 116 const uint8* recv_key, int recv_key_len); 117 bool SetRtcpParams(const std::string& send_cs, 118 const uint8* send_key, int send_key_len, 119 const std::string& recv_cs, 120 const uint8* recv_key, int recv_key_len); 121 122 // Encrypts/signs an individual RTP/RTCP packet, in-place. 123 // If an HMAC is used, this will increase the packet size. 124 bool ProtectRtp(void* data, int in_len, int max_len, int* out_len); 125 bool ProtectRtcp(void* data, int in_len, int max_len, int* out_len); 126 // Decrypts/verifies an invidiual RTP/RTCP packet. 127 // If an HMAC is used, this will decrease the packet size. 128 bool UnprotectRtp(void* data, int in_len, int* out_len); 129 bool UnprotectRtcp(void* data, int in_len, int* out_len); 130 131 // Update the silent threshold (in ms) for signaling errors. 132 void set_signal_silent_time(uint32 signal_silent_time_in_ms); 133 134 sigslot::repeater3<uint32, Mode, Error> SignalSrtpError; 135 136 protected: 137 bool ExpectOffer(ContentSource source); 138 bool StoreParams(const std::vector<CryptoParams>& params, 139 ContentSource source); 140 bool ExpectAnswer(ContentSource source); 141 bool DoSetAnswer(const std::vector<CryptoParams>& answer_params, 142 ContentSource source, 143 bool final); 144 void CreateSrtpSessions(); 145 bool NegotiateParams(const std::vector<CryptoParams>& answer_params, 146 CryptoParams* selected_params); 147 bool ApplyParams(const CryptoParams& send_params, 148 const CryptoParams& recv_params); 149 bool ResetParams(); 150 static bool ParseKeyParams(const std::string& params, uint8* key, int len); 151 152 private: 153 enum State { 154 ST_INIT, // SRTP filter unused. 155 ST_SENTOFFER, // Offer with SRTP parameters sent. 156 ST_RECEIVEDOFFER, // Offer with SRTP parameters received. 157 ST_SENTPRANSWER_NO_CRYPTO, // Sent provisional answer without crypto. 158 // Received provisional answer without crypto. 159 ST_RECEIVEDPRANSWER_NO_CRYPTO, 160 ST_ACTIVE, // Offer and answer set. 161 // SRTP filter is active but new parameters are offered. 162 // When the answer is set, the state transitions to ST_ACTIVE or ST_INIT. 163 ST_SENTUPDATEDOFFER, 164 // SRTP filter is active but new parameters are received. 165 // When the answer is set, the state transitions back to ST_ACTIVE. 166 ST_RECEIVEDUPDATEDOFFER, 167 // SRTP filter is active but the sent answer is only provisional. 168 // When the final answer is set, the state transitions to ST_ACTIVE or 169 // ST_INIT. 170 ST_SENTPRANSWER, 171 // SRTP filter is active but the received answer is only provisional. 172 // When the final answer is set, the state transitions to ST_ACTIVE or 173 // ST_INIT. 174 ST_RECEIVEDPRANSWER 175 }; 176 State state_; 177 uint32 signal_silent_time_in_ms_; 178 std::vector<CryptoParams> offer_params_; 179 talk_base::scoped_ptr<SrtpSession> send_session_; 180 talk_base::scoped_ptr<SrtpSession> recv_session_; 181 talk_base::scoped_ptr<SrtpSession> send_rtcp_session_; 182 talk_base::scoped_ptr<SrtpSession> recv_rtcp_session_; 183 CryptoParams applied_send_params_; 184 CryptoParams applied_recv_params_; 185 }; 186 187 // Class that wraps a libSRTP session. 188 class SrtpSession { 189 public: 190 SrtpSession(); 191 ~SrtpSession(); 192 193 // Configures the session for sending data using the specified 194 // cipher-suite and key. Receiving must be done by a separate session. 195 bool SetSend(const std::string& cs, const uint8* key, int len); 196 // Configures the session for receiving data using the specified 197 // cipher-suite and key. Sending must be done by a separate session. 198 bool SetRecv(const std::string& cs, const uint8* key, int len); 199 200 // Encrypts/signs an individual RTP/RTCP packet, in-place. 201 // If an HMAC is used, this will increase the packet size. 202 bool ProtectRtp(void* data, int in_len, int max_len, int* out_len); 203 bool ProtectRtcp(void* data, int in_len, int max_len, int* out_len); 204 // Decrypts/verifies an invidiual RTP/RTCP packet. 205 // If an HMAC is used, this will decrease the packet size. 206 bool UnprotectRtp(void* data, int in_len, int* out_len); 207 bool UnprotectRtcp(void* data, int in_len, int* out_len); 208 209 // Update the silent threshold (in ms) for signaling errors. 210 void set_signal_silent_time(uint32 signal_silent_time_in_ms); 211 212 // Calls srtp_shutdown if it's initialized. 213 static void Terminate(); 214 215 sigslot::repeater3<uint32, SrtpFilter::Mode, SrtpFilter::Error> 216 SignalSrtpError; 217 218 private: 219 bool SetKey(int type, const std::string& cs, const uint8* key, int len); 220 static bool Init(); 221 void HandleEvent(const srtp_event_data_t* ev); 222 static void HandleEventThunk(srtp_event_data_t* ev); 223 static std::list<SrtpSession*>* sessions(); 224 225 srtp_t session_; 226 int rtp_auth_tag_len_; 227 int rtcp_auth_tag_len_; 228 talk_base::scoped_ptr<SrtpStat> srtp_stat_; 229 static bool inited_; 230 int last_send_seq_num_; 231 DISALLOW_COPY_AND_ASSIGN(SrtpSession); 232 }; 233 234 // Class that collects failures of SRTP. 235 class SrtpStat { 236 public: 237 SrtpStat(); 238 239 // Report RTP protection results to the handler. 240 void AddProtectRtpResult(uint32 ssrc, int result); 241 // Report RTP unprotection results to the handler. 242 void AddUnprotectRtpResult(uint32 ssrc, int result); 243 // Report RTCP protection results to the handler. 244 void AddProtectRtcpResult(int result); 245 // Report RTCP unprotection results to the handler. 246 void AddUnprotectRtcpResult(int result); 247 248 // Get silent time (in ms) for SRTP statistics handler. signal_silent_time()249 uint32 signal_silent_time() const { return signal_silent_time_; } 250 // Set silent time (in ms) for SRTP statistics handler. set_signal_silent_time(uint32 signal_silent_time)251 void set_signal_silent_time(uint32 signal_silent_time) { 252 signal_silent_time_ = signal_silent_time; 253 } 254 255 // Sigslot for reporting errors. 256 sigslot::signal3<uint32, SrtpFilter::Mode, SrtpFilter::Error> 257 SignalSrtpError; 258 259 private: 260 // For each different ssrc and error, we collect statistics separately. 261 struct FailureKey { FailureKeyFailureKey262 FailureKey() 263 : ssrc(0), 264 mode(SrtpFilter::PROTECT), 265 error(SrtpFilter::ERROR_NONE) { 266 } FailureKeyFailureKey267 FailureKey(uint32 in_ssrc, SrtpFilter::Mode in_mode, 268 SrtpFilter::Error in_error) 269 : ssrc(in_ssrc), 270 mode(in_mode), 271 error(in_error) { 272 } 273 bool operator <(const FailureKey& key) const { 274 return 275 (ssrc < key.ssrc) || 276 (ssrc == key.ssrc && mode < key.mode) || 277 (ssrc == key.ssrc && mode == key.mode && error < key.error); 278 } 279 uint32 ssrc; 280 SrtpFilter::Mode mode; 281 SrtpFilter::Error error; 282 }; 283 // For tracing conditions for signaling, currently we only use 284 // last_signal_time. Wrap this as a struct so that later on, if we need any 285 // other improvements, it will be easier. 286 struct FailureStat { FailureStatFailureStat287 FailureStat() 288 : last_signal_time(0) { 289 } FailureStatFailureStat290 explicit FailureStat(uint32 in_last_signal_time) 291 : last_signal_time(in_last_signal_time) { 292 } ResetFailureStat293 void Reset() { 294 last_signal_time = 0; 295 } 296 uint32 last_signal_time; 297 }; 298 299 // Inspect SRTP result and signal error if needed. 300 void HandleSrtpResult(const FailureKey& key); 301 302 std::map<FailureKey, FailureStat> failures_; 303 // Threshold in ms to silent the signaling errors. 304 uint32 signal_silent_time_; 305 306 DISALLOW_COPY_AND_ASSIGN(SrtpStat); 307 }; 308 309 } // namespace cricket 310 311 #endif // TALK_SESSION_MEDIA_SRTPFILTER_H_ 312