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