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 "webrtc/p2p/base/sessiondescription.h" 38 #include "webrtc/base/basictypes.h" 39 #include "webrtc/base/criticalsection.h" 40 #include "webrtc/base/scoped_ptr.h" 41 #include "webrtc/base/sigslotrepeater.h" 42 #include "webrtc/base/sslstreamadapter.h" 43 44 // Forward declaration to avoid pulling in libsrtp headers here 45 struct srtp_event_data_t; 46 struct srtp_ctx_t; 47 struct srtp_policy_t; 48 49 namespace cricket { 50 51 // Key is 128 bits and salt is 112 bits == 30 bytes. B64 bloat => 40 bytes. 52 extern const int SRTP_MASTER_KEY_BASE64_LEN; 53 54 // Needed for DTLS-SRTP 55 extern const int SRTP_MASTER_KEY_KEY_LEN; 56 extern const int SRTP_MASTER_KEY_SALT_LEN; 57 58 class SrtpSession; 59 class SrtpStat; 60 61 void EnableSrtpDebugging(); 62 void ShutdownSrtp(); 63 64 // Class to transform SRTP to/from RTP. 65 // Initialize by calling SetSend with the local security params, then call 66 // SetRecv once the remote security params are received. At that point 67 // Protect/UnprotectRt(c)p can be called to encrypt/decrypt data. 68 // TODO: Figure out concurrency policy for SrtpFilter. 69 class SrtpFilter { 70 public: 71 enum Mode { 72 PROTECT, 73 UNPROTECT 74 }; 75 enum Error { 76 ERROR_NONE, 77 ERROR_FAIL, 78 ERROR_AUTH, 79 ERROR_REPLAY, 80 }; 81 82 SrtpFilter(); 83 ~SrtpFilter(); 84 85 // Whether the filter is active (i.e. crypto has been properly negotiated). 86 bool IsActive() const; 87 88 // Indicates which crypto algorithms and keys were contained in the offer. 89 // offer_params should contain a list of available parameters to use, or none, 90 // if crypto is not desired. This must be called before SetAnswer. 91 bool SetOffer(const std::vector<CryptoParams>& offer_params, 92 ContentSource source); 93 // Same as SetAnwer. But multiple calls are allowed to SetProvisionalAnswer 94 // after a call to SetOffer. 95 bool SetProvisionalAnswer(const std::vector<CryptoParams>& answer_params, 96 ContentSource source); 97 // Indicates which crypto algorithms and keys were contained in the answer. 98 // answer_params should contain the negotiated parameters, which may be none, 99 // if crypto was not desired or could not be negotiated (and not required). 100 // This must be called after SetOffer. If crypto negotiation completes 101 // successfully, this will advance the filter to the active state. 102 bool SetAnswer(const std::vector<CryptoParams>& answer_params, 103 ContentSource source); 104 105 // Just set up both sets of keys directly. 106 // Used with DTLS-SRTP. 107 bool SetRtpParams(int send_cs, 108 const uint8_t* send_key, 109 int send_key_len, 110 int recv_cs, 111 const uint8_t* recv_key, 112 int recv_key_len); 113 bool SetRtcpParams(int send_cs, 114 const uint8_t* send_key, 115 int send_key_len, 116 int recv_cs, 117 const uint8_t* recv_key, 118 int recv_key_len); 119 120 // Encrypts/signs an individual RTP/RTCP packet, in-place. 121 // If an HMAC is used, this will increase the packet size. 122 bool ProtectRtp(void* data, int in_len, int max_len, int* out_len); 123 // Overloaded version, outputs packet index. 124 bool ProtectRtp(void* data, 125 int in_len, 126 int max_len, 127 int* out_len, 128 int64_t* index); 129 bool ProtectRtcp(void* data, int in_len, int max_len, int* out_len); 130 // Decrypts/verifies an invidiual RTP/RTCP packet. 131 // If an HMAC is used, this will decrease the packet size. 132 bool UnprotectRtp(void* data, int in_len, int* out_len); 133 bool UnprotectRtcp(void* data, int in_len, int* out_len); 134 135 // Returns rtp auth params from srtp context. 136 bool GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len); 137 138 // Update the silent threshold (in ms) for signaling errors. 139 void set_signal_silent_time(uint32_t signal_silent_time_in_ms); 140 141 bool ResetParams(); 142 143 sigslot::repeater3<uint32_t, Mode, Error> SignalSrtpError; 144 145 protected: 146 bool ExpectOffer(ContentSource source); 147 bool StoreParams(const std::vector<CryptoParams>& params, 148 ContentSource source); 149 bool ExpectAnswer(ContentSource source); 150 bool DoSetAnswer(const std::vector<CryptoParams>& answer_params, 151 ContentSource source, 152 bool final); 153 void CreateSrtpSessions(); 154 bool NegotiateParams(const std::vector<CryptoParams>& answer_params, 155 CryptoParams* selected_params); 156 bool ApplyParams(const CryptoParams& send_params, 157 const CryptoParams& recv_params); 158 static bool ParseKeyParams(const std::string& params, uint8_t* key, int len); 159 160 private: 161 enum State { 162 ST_INIT, // SRTP filter unused. 163 ST_SENTOFFER, // Offer with SRTP parameters sent. 164 ST_RECEIVEDOFFER, // Offer with SRTP parameters received. 165 ST_SENTPRANSWER_NO_CRYPTO, // Sent provisional answer without crypto. 166 // Received provisional answer without crypto. 167 ST_RECEIVEDPRANSWER_NO_CRYPTO, 168 ST_ACTIVE, // Offer and answer set. 169 // SRTP filter is active but new parameters are offered. 170 // When the answer is set, the state transitions to ST_ACTIVE or ST_INIT. 171 ST_SENTUPDATEDOFFER, 172 // SRTP filter is active but new parameters are received. 173 // When the answer is set, the state transitions back to ST_ACTIVE. 174 ST_RECEIVEDUPDATEDOFFER, 175 // SRTP filter is active but the sent answer is only provisional. 176 // When the final answer is set, the state transitions to ST_ACTIVE or 177 // ST_INIT. 178 ST_SENTPRANSWER, 179 // SRTP filter is active but the received answer is only provisional. 180 // When the final answer is set, the state transitions to ST_ACTIVE or 181 // ST_INIT. 182 ST_RECEIVEDPRANSWER 183 }; 184 State state_; 185 uint32_t signal_silent_time_in_ms_; 186 std::vector<CryptoParams> offer_params_; 187 rtc::scoped_ptr<SrtpSession> send_session_; 188 rtc::scoped_ptr<SrtpSession> recv_session_; 189 rtc::scoped_ptr<SrtpSession> send_rtcp_session_; 190 rtc::scoped_ptr<SrtpSession> recv_rtcp_session_; 191 CryptoParams applied_send_params_; 192 CryptoParams applied_recv_params_; 193 }; 194 195 // Class that wraps a libSRTP session. 196 class SrtpSession { 197 public: 198 SrtpSession(); 199 ~SrtpSession(); 200 201 // Configures the session for sending data using the specified 202 // cipher-suite and key. Receiving must be done by a separate session. 203 bool SetSend(int cs, const uint8_t* key, int len); 204 // Configures the session for receiving data using the specified 205 // cipher-suite and key. Sending must be done by a separate session. 206 bool SetRecv(int cs, const uint8_t* key, int len); 207 208 // Encrypts/signs an individual RTP/RTCP packet, in-place. 209 // If an HMAC is used, this will increase the packet size. 210 bool ProtectRtp(void* data, int in_len, int max_len, int* out_len); 211 // Overloaded version, outputs packet index. 212 bool ProtectRtp(void* data, 213 int in_len, 214 int max_len, 215 int* out_len, 216 int64_t* index); 217 bool ProtectRtcp(void* data, int in_len, int max_len, int* out_len); 218 // Decrypts/verifies an invidiual RTP/RTCP packet. 219 // If an HMAC is used, this will decrease the packet size. 220 bool UnprotectRtp(void* data, int in_len, int* out_len); 221 bool UnprotectRtcp(void* data, int in_len, int* out_len); 222 223 // Helper method to get authentication params. 224 bool GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len); 225 226 // Update the silent threshold (in ms) for signaling errors. 227 void set_signal_silent_time(uint32_t signal_silent_time_in_ms); 228 229 // Calls srtp_shutdown if it's initialized. 230 static void Terminate(); 231 232 sigslot::repeater3<uint32_t, SrtpFilter::Mode, SrtpFilter::Error> 233 SignalSrtpError; 234 235 private: 236 bool SetKey(int type, int cs, const uint8_t* key, int len); 237 // Returns send stream current packet index from srtp db. 238 bool GetSendStreamPacketIndex(void* data, int in_len, int64_t* index); 239 240 static bool Init(); 241 void HandleEvent(const srtp_event_data_t* ev); 242 static void HandleEventThunk(srtp_event_data_t* ev); 243 244 static std::list<SrtpSession*>* sessions(); 245 246 srtp_ctx_t* session_; 247 int rtp_auth_tag_len_; 248 int rtcp_auth_tag_len_; 249 rtc::scoped_ptr<SrtpStat> srtp_stat_; 250 static bool inited_; 251 static rtc::GlobalLockPod lock_; 252 int last_send_seq_num_; 253 RTC_DISALLOW_COPY_AND_ASSIGN(SrtpSession); 254 }; 255 256 // Class that collects failures of SRTP. 257 class SrtpStat { 258 public: 259 SrtpStat(); 260 261 // Report RTP protection results to the handler. 262 void AddProtectRtpResult(uint32_t ssrc, int result); 263 // Report RTP unprotection results to the handler. 264 void AddUnprotectRtpResult(uint32_t ssrc, int result); 265 // Report RTCP protection results to the handler. 266 void AddProtectRtcpResult(int result); 267 // Report RTCP unprotection results to the handler. 268 void AddUnprotectRtcpResult(int result); 269 270 // Get silent time (in ms) for SRTP statistics handler. 271 uint32_t signal_silent_time() const { return signal_silent_time_; } 272 // Set silent time (in ms) for SRTP statistics handler. 273 void set_signal_silent_time(uint32_t signal_silent_time) { 274 signal_silent_time_ = signal_silent_time; 275 } 276 277 // Sigslot for reporting errors. 278 sigslot::signal3<uint32_t, SrtpFilter::Mode, SrtpFilter::Error> 279 SignalSrtpError; 280 281 private: 282 // For each different ssrc and error, we collect statistics separately. 283 struct FailureKey { 284 FailureKey() 285 : ssrc(0), 286 mode(SrtpFilter::PROTECT), 287 error(SrtpFilter::ERROR_NONE) { 288 } 289 FailureKey(uint32_t in_ssrc, 290 SrtpFilter::Mode in_mode, 291 SrtpFilter::Error in_error) 292 : ssrc(in_ssrc), mode(in_mode), error(in_error) {} 293 bool operator <(const FailureKey& key) const { 294 return 295 (ssrc < key.ssrc) || 296 (ssrc == key.ssrc && mode < key.mode) || 297 (ssrc == key.ssrc && mode == key.mode && error < key.error); 298 } 299 uint32_t ssrc; 300 SrtpFilter::Mode mode; 301 SrtpFilter::Error error; 302 }; 303 // For tracing conditions for signaling, currently we only use 304 // last_signal_time. Wrap this as a struct so that later on, if we need any 305 // other improvements, it will be easier. 306 struct FailureStat { 307 FailureStat() 308 : last_signal_time(0) { 309 } 310 explicit FailureStat(uint32_t in_last_signal_time) 311 : last_signal_time(in_last_signal_time) {} 312 void Reset() { 313 last_signal_time = 0; 314 } 315 uint32_t last_signal_time; 316 }; 317 318 // Inspect SRTP result and signal error if needed. 319 void HandleSrtpResult(const FailureKey& key); 320 321 std::map<FailureKey, FailureStat> failures_; 322 // Threshold in ms to silent the signaling errors. 323 uint32_t signal_silent_time_; 324 325 RTC_DISALLOW_COPY_AND_ASSIGN(SrtpStat); 326 }; 327 328 } // namespace cricket 329 330 #endif // TALK_SESSION_MEDIA_SRTPFILTER_H_ 331