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