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/media/base/cryptoparams.h" 37 #include "talk/p2p/base/sessiondescription.h" 38 #include "webrtc/base/basictypes.h" 39 #include "webrtc/base/scoped_ptr.h" 40 #include "webrtc/base/sigslotrepeater.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 // Overloaded version, outputs packet index. 126 bool ProtectRtp(void* data, int in_len, int max_len, int* out_len, 127 int64* index); 128 bool ProtectRtcp(void* data, int in_len, int max_len, int* out_len); 129 // Decrypts/verifies an invidiual RTP/RTCP packet. 130 // If an HMAC is used, this will decrease the packet size. 131 bool UnprotectRtp(void* data, int in_len, int* out_len); 132 bool UnprotectRtcp(void* data, int in_len, int* out_len); 133 134 // Returns rtp auth params from srtp context. 135 bool GetRtpAuthParams(uint8** key, int* key_len, int* tag_len); 136 137 // Update the silent threshold (in ms) for signaling errors. 138 void set_signal_silent_time(uint32 signal_silent_time_in_ms); 139 140 sigslot::repeater3<uint32, Mode, Error> SignalSrtpError; 141 142 protected: 143 bool ExpectOffer(ContentSource source); 144 bool StoreParams(const std::vector<CryptoParams>& params, 145 ContentSource source); 146 bool ExpectAnswer(ContentSource source); 147 bool DoSetAnswer(const std::vector<CryptoParams>& answer_params, 148 ContentSource source, 149 bool final); 150 void CreateSrtpSessions(); 151 bool NegotiateParams(const std::vector<CryptoParams>& answer_params, 152 CryptoParams* selected_params); 153 bool ApplyParams(const CryptoParams& send_params, 154 const CryptoParams& recv_params); 155 bool ResetParams(); 156 static bool ParseKeyParams(const std::string& params, uint8* key, int len); 157 158 private: 159 enum State { 160 ST_INIT, // SRTP filter unused. 161 ST_SENTOFFER, // Offer with SRTP parameters sent. 162 ST_RECEIVEDOFFER, // Offer with SRTP parameters received. 163 ST_SENTPRANSWER_NO_CRYPTO, // Sent provisional answer without crypto. 164 // Received provisional answer without crypto. 165 ST_RECEIVEDPRANSWER_NO_CRYPTO, 166 ST_ACTIVE, // Offer and answer set. 167 // SRTP filter is active but new parameters are offered. 168 // When the answer is set, the state transitions to ST_ACTIVE or ST_INIT. 169 ST_SENTUPDATEDOFFER, 170 // SRTP filter is active but new parameters are received. 171 // When the answer is set, the state transitions back to ST_ACTIVE. 172 ST_RECEIVEDUPDATEDOFFER, 173 // SRTP filter is active but the sent answer is only provisional. 174 // When the final answer is set, the state transitions to ST_ACTIVE or 175 // ST_INIT. 176 ST_SENTPRANSWER, 177 // SRTP filter is active but the received answer is only provisional. 178 // When the final answer is set, the state transitions to ST_ACTIVE or 179 // ST_INIT. 180 ST_RECEIVEDPRANSWER 181 }; 182 State state_; 183 uint32 signal_silent_time_in_ms_; 184 std::vector<CryptoParams> offer_params_; 185 rtc::scoped_ptr<SrtpSession> send_session_; 186 rtc::scoped_ptr<SrtpSession> recv_session_; 187 rtc::scoped_ptr<SrtpSession> send_rtcp_session_; 188 rtc::scoped_ptr<SrtpSession> recv_rtcp_session_; 189 CryptoParams applied_send_params_; 190 CryptoParams applied_recv_params_; 191 }; 192 193 // Class that wraps a libSRTP session. 194 class SrtpSession { 195 public: 196 SrtpSession(); 197 ~SrtpSession(); 198 199 // Configures the session for sending data using the specified 200 // cipher-suite and key. Receiving must be done by a separate session. 201 bool SetSend(const std::string& cs, const uint8* key, int len); 202 // Configures the session for receiving data using the specified 203 // cipher-suite and key. Sending must be done by a separate session. 204 bool SetRecv(const std::string& cs, const uint8* key, int len); 205 206 // Encrypts/signs an individual RTP/RTCP packet, in-place. 207 // If an HMAC is used, this will increase the packet size. 208 bool ProtectRtp(void* data, int in_len, int max_len, int* out_len); 209 // Overloaded version, outputs packet index. 210 bool ProtectRtp(void* data, int in_len, int max_len, int* out_len, 211 int64* index); 212 bool ProtectRtcp(void* data, int in_len, int max_len, int* out_len); 213 // Decrypts/verifies an invidiual RTP/RTCP packet. 214 // If an HMAC is used, this will decrease the packet size. 215 bool UnprotectRtp(void* data, int in_len, int* out_len); 216 bool UnprotectRtcp(void* data, int in_len, int* out_len); 217 218 // Helper method to get authentication params. 219 bool GetRtpAuthParams(uint8** key, int* key_len, int* tag_len); 220 221 // Update the silent threshold (in ms) for signaling errors. 222 void set_signal_silent_time(uint32 signal_silent_time_in_ms); 223 224 // Calls srtp_shutdown if it's initialized. 225 static void Terminate(); 226 227 sigslot::repeater3<uint32, SrtpFilter::Mode, SrtpFilter::Error> 228 SignalSrtpError; 229 230 private: 231 bool SetKey(int type, const std::string& cs, const uint8* key, int len); 232 // Returns send stream current packet index from srtp db. 233 bool GetSendStreamPacketIndex(void* data, int in_len, int64* index); 234 235 static bool Init(); 236 void HandleEvent(const srtp_event_data_t* ev); 237 static void HandleEventThunk(srtp_event_data_t* ev); 238 239 static std::list<SrtpSession*>* sessions(); 240 241 srtp_t session_; 242 int rtp_auth_tag_len_; 243 int rtcp_auth_tag_len_; 244 rtc::scoped_ptr<SrtpStat> srtp_stat_; 245 static bool inited_; 246 int last_send_seq_num_; 247 DISALLOW_COPY_AND_ASSIGN(SrtpSession); 248 }; 249 250 // Class that collects failures of SRTP. 251 class SrtpStat { 252 public: 253 SrtpStat(); 254 255 // Report RTP protection results to the handler. 256 void AddProtectRtpResult(uint32 ssrc, int result); 257 // Report RTP unprotection results to the handler. 258 void AddUnprotectRtpResult(uint32 ssrc, int result); 259 // Report RTCP protection results to the handler. 260 void AddProtectRtcpResult(int result); 261 // Report RTCP unprotection results to the handler. 262 void AddUnprotectRtcpResult(int result); 263 264 // Get silent time (in ms) for SRTP statistics handler. signal_silent_time()265 uint32 signal_silent_time() const { return signal_silent_time_; } 266 // Set silent time (in ms) for SRTP statistics handler. set_signal_silent_time(uint32 signal_silent_time)267 void set_signal_silent_time(uint32 signal_silent_time) { 268 signal_silent_time_ = signal_silent_time; 269 } 270 271 // Sigslot for reporting errors. 272 sigslot::signal3<uint32, SrtpFilter::Mode, SrtpFilter::Error> 273 SignalSrtpError; 274 275 private: 276 // For each different ssrc and error, we collect statistics separately. 277 struct FailureKey { FailureKeyFailureKey278 FailureKey() 279 : ssrc(0), 280 mode(SrtpFilter::PROTECT), 281 error(SrtpFilter::ERROR_NONE) { 282 } FailureKeyFailureKey283 FailureKey(uint32 in_ssrc, SrtpFilter::Mode in_mode, 284 SrtpFilter::Error in_error) 285 : ssrc(in_ssrc), 286 mode(in_mode), 287 error(in_error) { 288 } 289 bool operator <(const FailureKey& key) const { 290 return 291 (ssrc < key.ssrc) || 292 (ssrc == key.ssrc && mode < key.mode) || 293 (ssrc == key.ssrc && mode == key.mode && error < key.error); 294 } 295 uint32 ssrc; 296 SrtpFilter::Mode mode; 297 SrtpFilter::Error error; 298 }; 299 // For tracing conditions for signaling, currently we only use 300 // last_signal_time. Wrap this as a struct so that later on, if we need any 301 // other improvements, it will be easier. 302 struct FailureStat { FailureStatFailureStat303 FailureStat() 304 : last_signal_time(0) { 305 } FailureStatFailureStat306 explicit FailureStat(uint32 in_last_signal_time) 307 : last_signal_time(in_last_signal_time) { 308 } ResetFailureStat309 void Reset() { 310 last_signal_time = 0; 311 } 312 uint32 last_signal_time; 313 }; 314 315 // Inspect SRTP result and signal error if needed. 316 void HandleSrtpResult(const FailureKey& key); 317 318 std::map<FailureKey, FailureStat> failures_; 319 // Threshold in ms to silent the signaling errors. 320 uint32 signal_silent_time_; 321 322 DISALLOW_COPY_AND_ASSIGN(SrtpStat); 323 }; 324 325 } // namespace cricket 326 327 #endif // TALK_SESSION_MEDIA_SRTPFILTER_H_ 328