OLD | NEW |
| (Empty) |
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 #undef HAVE_CONFIG_H | |
29 | |
30 #include "talk/session/media/srtpfilter.h" | |
31 | |
32 #include <string.h> | |
33 | |
34 #include <algorithm> | |
35 | |
36 #include "webrtc/base/base64.h" | |
37 #include "webrtc/base/byteorder.h" | |
38 #include "webrtc/base/common.h" | |
39 #include "webrtc/base/logging.h" | |
40 #include "webrtc/base/stringencode.h" | |
41 #include "webrtc/base/timeutils.h" | |
42 #include "webrtc/media/base/rtputils.h" | |
43 | |
44 // Enable this line to turn on SRTP debugging | |
45 // #define SRTP_DEBUG | |
46 | |
47 #ifdef HAVE_SRTP | |
48 extern "C" { | |
49 #ifdef SRTP_RELATIVE_PATH | |
50 #include "srtp.h" // NOLINT | |
51 #include "srtp_priv.h" // NOLINT | |
52 #else | |
53 #include "third_party/libsrtp/srtp/include/srtp.h" | |
54 #include "third_party/libsrtp/srtp/include/srtp_priv.h" | |
55 #endif // SRTP_RELATIVE_PATH | |
56 } | |
57 #ifdef ENABLE_EXTERNAL_AUTH | |
58 #include "talk/session/media/externalhmac.h" | |
59 #endif // ENABLE_EXTERNAL_AUTH | |
60 #if !defined(NDEBUG) | |
61 extern "C" debug_module_t mod_srtp; | |
62 extern "C" debug_module_t mod_auth; | |
63 extern "C" debug_module_t mod_cipher; | |
64 extern "C" debug_module_t mod_stat; | |
65 extern "C" debug_module_t mod_alloc; | |
66 extern "C" debug_module_t mod_aes_icm; | |
67 extern "C" debug_module_t mod_aes_hmac; | |
68 #endif | |
69 #else | |
70 // SrtpFilter needs that constant. | |
71 #define SRTP_MASTER_KEY_LEN 30 | |
72 #endif // HAVE_SRTP | |
73 | |
74 namespace cricket { | |
75 | |
76 const int SRTP_MASTER_KEY_BASE64_LEN = SRTP_MASTER_KEY_LEN * 4 / 3; | |
77 const int SRTP_MASTER_KEY_KEY_LEN = 16; | |
78 const int SRTP_MASTER_KEY_SALT_LEN = 14; | |
79 | |
80 #ifndef HAVE_SRTP | |
81 | |
82 // This helper function is used on systems that don't (yet) have SRTP, | |
83 // to log that the functions that require it won't do anything. | |
84 namespace { | |
85 bool SrtpNotAvailable(const char *func) { | |
86 LOG(LS_ERROR) << func << ": SRTP is not available on your system."; | |
87 return false; | |
88 } | |
89 } // anonymous namespace | |
90 | |
91 #endif // !HAVE_SRTP | |
92 | |
93 void EnableSrtpDebugging() { | |
94 #ifdef HAVE_SRTP | |
95 #if !defined(NDEBUG) | |
96 debug_on(mod_srtp); | |
97 debug_on(mod_auth); | |
98 debug_on(mod_cipher); | |
99 debug_on(mod_stat); | |
100 debug_on(mod_alloc); | |
101 debug_on(mod_aes_icm); | |
102 // debug_on(mod_aes_cbc); | |
103 // debug_on(mod_hmac); | |
104 #endif | |
105 #endif // HAVE_SRTP | |
106 } | |
107 | |
108 // NOTE: This is called from ChannelManager D'tor. | |
109 void ShutdownSrtp() { | |
110 #ifdef HAVE_SRTP | |
111 // If srtp_dealloc is not executed then this will clear all existing sessions. | |
112 // This should be called when application is shutting down. | |
113 SrtpSession::Terminate(); | |
114 #endif | |
115 } | |
116 | |
117 SrtpFilter::SrtpFilter() | |
118 : state_(ST_INIT), | |
119 signal_silent_time_in_ms_(0) { | |
120 } | |
121 | |
122 SrtpFilter::~SrtpFilter() { | |
123 } | |
124 | |
125 bool SrtpFilter::IsActive() const { | |
126 return state_ >= ST_ACTIVE; | |
127 } | |
128 | |
129 bool SrtpFilter::SetOffer(const std::vector<CryptoParams>& offer_params, | |
130 ContentSource source) { | |
131 if (!ExpectOffer(source)) { | |
132 LOG(LS_ERROR) << "Wrong state to update SRTP offer"; | |
133 return false; | |
134 } | |
135 return StoreParams(offer_params, source); | |
136 } | |
137 | |
138 bool SrtpFilter::SetAnswer(const std::vector<CryptoParams>& answer_params, | |
139 ContentSource source) { | |
140 return DoSetAnswer(answer_params, source, true); | |
141 } | |
142 | |
143 bool SrtpFilter::SetProvisionalAnswer( | |
144 const std::vector<CryptoParams>& answer_params, | |
145 ContentSource source) { | |
146 return DoSetAnswer(answer_params, source, false); | |
147 } | |
148 | |
149 bool SrtpFilter::SetRtpParams(int send_cs, | |
150 const uint8_t* send_key, | |
151 int send_key_len, | |
152 int recv_cs, | |
153 const uint8_t* recv_key, | |
154 int recv_key_len) { | |
155 if (IsActive()) { | |
156 LOG(LS_ERROR) << "Tried to set SRTP Params when filter already active"; | |
157 return false; | |
158 } | |
159 CreateSrtpSessions(); | |
160 if (!send_session_->SetSend(send_cs, send_key, send_key_len)) | |
161 return false; | |
162 | |
163 if (!recv_session_->SetRecv(recv_cs, recv_key, recv_key_len)) | |
164 return false; | |
165 | |
166 state_ = ST_ACTIVE; | |
167 | |
168 LOG(LS_INFO) << "SRTP activated with negotiated parameters:" | |
169 << " send cipher_suite " << send_cs | |
170 << " recv cipher_suite " << recv_cs; | |
171 return true; | |
172 } | |
173 | |
174 // This function is provided separately because DTLS-SRTP behaves | |
175 // differently in RTP/RTCP mux and non-mux modes. | |
176 // | |
177 // - In the non-muxed case, RTP and RTCP are keyed with different | |
178 // keys (from different DTLS handshakes), and so we need a new | |
179 // SrtpSession. | |
180 // - In the muxed case, they are keyed with the same keys, so | |
181 // this function is not needed | |
182 bool SrtpFilter::SetRtcpParams(int send_cs, | |
183 const uint8_t* send_key, | |
184 int send_key_len, | |
185 int recv_cs, | |
186 const uint8_t* recv_key, | |
187 int recv_key_len) { | |
188 // This can only be called once, but can be safely called after | |
189 // SetRtpParams | |
190 if (send_rtcp_session_ || recv_rtcp_session_) { | |
191 LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active"; | |
192 return false; | |
193 } | |
194 | |
195 send_rtcp_session_.reset(new SrtpSession()); | |
196 SignalSrtpError.repeat(send_rtcp_session_->SignalSrtpError); | |
197 send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_); | |
198 if (!send_rtcp_session_->SetRecv(send_cs, send_key, send_key_len)) | |
199 return false; | |
200 | |
201 recv_rtcp_session_.reset(new SrtpSession()); | |
202 SignalSrtpError.repeat(recv_rtcp_session_->SignalSrtpError); | |
203 recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms_); | |
204 if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len)) | |
205 return false; | |
206 | |
207 LOG(LS_INFO) << "SRTCP activated with negotiated parameters:" | |
208 << " send cipher_suite " << send_cs | |
209 << " recv cipher_suite " << recv_cs; | |
210 | |
211 return true; | |
212 } | |
213 | |
214 bool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len) { | |
215 if (!IsActive()) { | |
216 LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active"; | |
217 return false; | |
218 } | |
219 ASSERT(send_session_ != NULL); | |
220 return send_session_->ProtectRtp(p, in_len, max_len, out_len); | |
221 } | |
222 | |
223 bool SrtpFilter::ProtectRtp(void* p, | |
224 int in_len, | |
225 int max_len, | |
226 int* out_len, | |
227 int64_t* index) { | |
228 if (!IsActive()) { | |
229 LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active"; | |
230 return false; | |
231 } | |
232 ASSERT(send_session_ != NULL); | |
233 return send_session_->ProtectRtp(p, in_len, max_len, out_len, index); | |
234 } | |
235 | |
236 bool SrtpFilter::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) { | |
237 if (!IsActive()) { | |
238 LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active"; | |
239 return false; | |
240 } | |
241 if (send_rtcp_session_) { | |
242 return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len); | |
243 } else { | |
244 ASSERT(send_session_ != NULL); | |
245 return send_session_->ProtectRtcp(p, in_len, max_len, out_len); | |
246 } | |
247 } | |
248 | |
249 bool SrtpFilter::UnprotectRtp(void* p, int in_len, int* out_len) { | |
250 if (!IsActive()) { | |
251 LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active"; | |
252 return false; | |
253 } | |
254 ASSERT(recv_session_ != NULL); | |
255 return recv_session_->UnprotectRtp(p, in_len, out_len); | |
256 } | |
257 | |
258 bool SrtpFilter::UnprotectRtcp(void* p, int in_len, int* out_len) { | |
259 if (!IsActive()) { | |
260 LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active"; | |
261 return false; | |
262 } | |
263 if (recv_rtcp_session_) { | |
264 return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len); | |
265 } else { | |
266 ASSERT(recv_session_ != NULL); | |
267 return recv_session_->UnprotectRtcp(p, in_len, out_len); | |
268 } | |
269 } | |
270 | |
271 bool SrtpFilter::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) { | |
272 if (!IsActive()) { | |
273 LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active"; | |
274 return false; | |
275 } | |
276 | |
277 ASSERT(send_session_ != NULL); | |
278 return send_session_->GetRtpAuthParams(key, key_len, tag_len); | |
279 } | |
280 | |
281 void SrtpFilter::set_signal_silent_time(uint32_t signal_silent_time_in_ms) { | |
282 signal_silent_time_in_ms_ = signal_silent_time_in_ms; | |
283 if (IsActive()) { | |
284 ASSERT(send_session_ != NULL); | |
285 send_session_->set_signal_silent_time(signal_silent_time_in_ms); | |
286 ASSERT(recv_session_ != NULL); | |
287 recv_session_->set_signal_silent_time(signal_silent_time_in_ms); | |
288 if (send_rtcp_session_) | |
289 send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms); | |
290 if (recv_rtcp_session_) | |
291 recv_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms); | |
292 } | |
293 } | |
294 | |
295 bool SrtpFilter::ExpectOffer(ContentSource source) { | |
296 return ((state_ == ST_INIT) || | |
297 (state_ == ST_ACTIVE) || | |
298 (state_ == ST_SENTOFFER && source == CS_LOCAL) || | |
299 (state_ == ST_SENTUPDATEDOFFER && source == CS_LOCAL) || | |
300 (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) || | |
301 (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE)); | |
302 } | |
303 | |
304 bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params, | |
305 ContentSource source) { | |
306 offer_params_ = params; | |
307 if (state_ == ST_INIT) { | |
308 state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER; | |
309 } else if (state_ == ST_ACTIVE) { | |
310 state_ = | |
311 (source == CS_LOCAL) ? ST_SENTUPDATEDOFFER : ST_RECEIVEDUPDATEDOFFER; | |
312 } | |
313 return true; | |
314 } | |
315 | |
316 bool SrtpFilter::ExpectAnswer(ContentSource source) { | |
317 return ((state_ == ST_SENTOFFER && source == CS_REMOTE) || | |
318 (state_ == ST_RECEIVEDOFFER && source == CS_LOCAL) || | |
319 (state_ == ST_SENTUPDATEDOFFER && source == CS_REMOTE) || | |
320 (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_LOCAL) || | |
321 (state_ == ST_SENTPRANSWER_NO_CRYPTO && source == CS_LOCAL) || | |
322 (state_ == ST_SENTPRANSWER && source == CS_LOCAL) || | |
323 (state_ == ST_RECEIVEDPRANSWER_NO_CRYPTO && source == CS_REMOTE) || | |
324 (state_ == ST_RECEIVEDPRANSWER && source == CS_REMOTE)); | |
325 } | |
326 | |
327 bool SrtpFilter::DoSetAnswer(const std::vector<CryptoParams>& answer_params, | |
328 ContentSource source, | |
329 bool final) { | |
330 if (!ExpectAnswer(source)) { | |
331 LOG(LS_ERROR) << "Invalid state for SRTP answer"; | |
332 return false; | |
333 } | |
334 | |
335 // If the answer doesn't requests crypto complete the negotiation of an | |
336 // unencrypted session. | |
337 // Otherwise, finalize the parameters and apply them. | |
338 if (answer_params.empty()) { | |
339 if (final) { | |
340 return ResetParams(); | |
341 } else { | |
342 // Need to wait for the final answer to decide if | |
343 // we should go to Active state. | |
344 state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO : | |
345 ST_RECEIVEDPRANSWER_NO_CRYPTO; | |
346 return true; | |
347 } | |
348 } | |
349 CryptoParams selected_params; | |
350 if (!NegotiateParams(answer_params, &selected_params)) | |
351 return false; | |
352 const CryptoParams& send_params = | |
353 (source == CS_REMOTE) ? selected_params : answer_params[0]; | |
354 const CryptoParams& recv_params = | |
355 (source == CS_REMOTE) ? answer_params[0] : selected_params; | |
356 if (!ApplyParams(send_params, recv_params)) { | |
357 return false; | |
358 } | |
359 | |
360 if (final) { | |
361 offer_params_.clear(); | |
362 state_ = ST_ACTIVE; | |
363 } else { | |
364 state_ = | |
365 (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER; | |
366 } | |
367 return true; | |
368 } | |
369 | |
370 void SrtpFilter::CreateSrtpSessions() { | |
371 send_session_.reset(new SrtpSession()); | |
372 applied_send_params_ = CryptoParams(); | |
373 recv_session_.reset(new SrtpSession()); | |
374 applied_recv_params_ = CryptoParams(); | |
375 | |
376 SignalSrtpError.repeat(send_session_->SignalSrtpError); | |
377 SignalSrtpError.repeat(recv_session_->SignalSrtpError); | |
378 | |
379 send_session_->set_signal_silent_time(signal_silent_time_in_ms_); | |
380 recv_session_->set_signal_silent_time(signal_silent_time_in_ms_); | |
381 } | |
382 | |
383 bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params, | |
384 CryptoParams* selected_params) { | |
385 // We're processing an accept. We should have exactly one set of params, | |
386 // unless the offer didn't mention crypto, in which case we shouldn't be here. | |
387 bool ret = (answer_params.size() == 1U && !offer_params_.empty()); | |
388 if (ret) { | |
389 // We should find a match between the answer params and the offered params. | |
390 std::vector<CryptoParams>::const_iterator it; | |
391 for (it = offer_params_.begin(); it != offer_params_.end(); ++it) { | |
392 if (answer_params[0].Matches(*it)) { | |
393 break; | |
394 } | |
395 } | |
396 | |
397 if (it != offer_params_.end()) { | |
398 *selected_params = *it; | |
399 } else { | |
400 ret = false; | |
401 } | |
402 } | |
403 | |
404 if (!ret) { | |
405 LOG(LS_WARNING) << "Invalid parameters in SRTP answer"; | |
406 } | |
407 return ret; | |
408 } | |
409 | |
410 bool SrtpFilter::ApplyParams(const CryptoParams& send_params, | |
411 const CryptoParams& recv_params) { | |
412 // TODO(jiayl): Split this method to apply send and receive CryptoParams | |
413 // independently, so that we can skip one method when either send or receive | |
414 // CryptoParams is unchanged. | |
415 if (applied_send_params_.cipher_suite == send_params.cipher_suite && | |
416 applied_send_params_.key_params == send_params.key_params && | |
417 applied_recv_params_.cipher_suite == recv_params.cipher_suite && | |
418 applied_recv_params_.key_params == recv_params.key_params) { | |
419 LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op."; | |
420 | |
421 // We do not want to reset the ROC if the keys are the same. So just return. | |
422 return true; | |
423 } | |
424 // TODO(juberti): Zero these buffers after use. | |
425 bool ret; | |
426 uint8_t send_key[SRTP_MASTER_KEY_LEN], recv_key[SRTP_MASTER_KEY_LEN]; | |
427 ret = (ParseKeyParams(send_params.key_params, send_key, sizeof(send_key)) && | |
428 ParseKeyParams(recv_params.key_params, recv_key, sizeof(recv_key))); | |
429 if (ret) { | |
430 CreateSrtpSessions(); | |
431 ret = (send_session_->SetSend( | |
432 rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite), send_key, | |
433 sizeof(send_key)) && | |
434 recv_session_->SetRecv( | |
435 rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite), recv_key, | |
436 sizeof(recv_key))); | |
437 } | |
438 if (ret) { | |
439 LOG(LS_INFO) << "SRTP activated with negotiated parameters:" | |
440 << " send cipher_suite " << send_params.cipher_suite | |
441 << " recv cipher_suite " << recv_params.cipher_suite; | |
442 applied_send_params_ = send_params; | |
443 applied_recv_params_ = recv_params; | |
444 } else { | |
445 LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters"; | |
446 } | |
447 return ret; | |
448 } | |
449 | |
450 bool SrtpFilter::ResetParams() { | |
451 offer_params_.clear(); | |
452 state_ = ST_INIT; | |
453 send_session_ = nullptr; | |
454 recv_session_ = nullptr; | |
455 send_rtcp_session_ = nullptr; | |
456 recv_rtcp_session_ = nullptr; | |
457 LOG(LS_INFO) << "SRTP reset to init state"; | |
458 return true; | |
459 } | |
460 | |
461 bool SrtpFilter::ParseKeyParams(const std::string& key_params, | |
462 uint8_t* key, | |
463 int len) { | |
464 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2" | |
465 | |
466 // Fail if key-method is wrong. | |
467 if (key_params.find("inline:") != 0) { | |
468 return false; | |
469 } | |
470 | |
471 // Fail if base64 decode fails, or the key is the wrong size. | |
472 std::string key_b64(key_params.substr(7)), key_str; | |
473 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, | |
474 &key_str, NULL) || | |
475 static_cast<int>(key_str.size()) != len) { | |
476 return false; | |
477 } | |
478 | |
479 memcpy(key, key_str.c_str(), len); | |
480 return true; | |
481 } | |
482 | |
483 /////////////////////////////////////////////////////////////////////////////// | |
484 // SrtpSession | |
485 | |
486 #ifdef HAVE_SRTP | |
487 | |
488 bool SrtpSession::inited_ = false; | |
489 | |
490 // This lock protects SrtpSession::inited_ and SrtpSession::sessions_. | |
491 rtc::GlobalLockPod SrtpSession::lock_; | |
492 | |
493 SrtpSession::SrtpSession() | |
494 : session_(NULL), | |
495 rtp_auth_tag_len_(0), | |
496 rtcp_auth_tag_len_(0), | |
497 srtp_stat_(new SrtpStat()), | |
498 last_send_seq_num_(-1) { | |
499 { | |
500 rtc::GlobalLockScope ls(&lock_); | |
501 sessions()->push_back(this); | |
502 } | |
503 SignalSrtpError.repeat(srtp_stat_->SignalSrtpError); | |
504 } | |
505 | |
506 SrtpSession::~SrtpSession() { | |
507 { | |
508 rtc::GlobalLockScope ls(&lock_); | |
509 sessions()->erase(std::find(sessions()->begin(), sessions()->end(), this)); | |
510 } | |
511 if (session_) { | |
512 srtp_dealloc(session_); | |
513 } | |
514 } | |
515 | |
516 bool SrtpSession::SetSend(int cs, const uint8_t* key, int len) { | |
517 return SetKey(ssrc_any_outbound, cs, key, len); | |
518 } | |
519 | |
520 bool SrtpSession::SetRecv(int cs, const uint8_t* key, int len) { | |
521 return SetKey(ssrc_any_inbound, cs, key, len); | |
522 } | |
523 | |
524 bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) { | |
525 if (!session_) { | |
526 LOG(LS_WARNING) << "Failed to protect SRTP packet: no SRTP Session"; | |
527 return false; | |
528 } | |
529 | |
530 int need_len = in_len + rtp_auth_tag_len_; // NOLINT | |
531 if (max_len < need_len) { | |
532 LOG(LS_WARNING) << "Failed to protect SRTP packet: The buffer length " | |
533 << max_len << " is less than the needed " << need_len; | |
534 return false; | |
535 } | |
536 | |
537 *out_len = in_len; | |
538 int err = srtp_protect(session_, p, out_len); | |
539 uint32_t ssrc; | |
540 if (GetRtpSsrc(p, in_len, &ssrc)) { | |
541 srtp_stat_->AddProtectRtpResult(ssrc, err); | |
542 } | |
543 int seq_num; | |
544 GetRtpSeqNum(p, in_len, &seq_num); | |
545 if (err != err_status_ok) { | |
546 LOG(LS_WARNING) << "Failed to protect SRTP packet, seqnum=" | |
547 << seq_num << ", err=" << err << ", last seqnum=" | |
548 << last_send_seq_num_; | |
549 return false; | |
550 } | |
551 last_send_seq_num_ = seq_num; | |
552 return true; | |
553 } | |
554 | |
555 bool SrtpSession::ProtectRtp(void* p, | |
556 int in_len, | |
557 int max_len, | |
558 int* out_len, | |
559 int64_t* index) { | |
560 if (!ProtectRtp(p, in_len, max_len, out_len)) { | |
561 return false; | |
562 } | |
563 return (index) ? GetSendStreamPacketIndex(p, in_len, index) : true; | |
564 } | |
565 | |
566 bool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) { | |
567 if (!session_) { | |
568 LOG(LS_WARNING) << "Failed to protect SRTCP packet: no SRTP Session"; | |
569 return false; | |
570 } | |
571 | |
572 int need_len = in_len + sizeof(uint32_t) + rtcp_auth_tag_len_; // NOLINT | |
573 if (max_len < need_len) { | |
574 LOG(LS_WARNING) << "Failed to protect SRTCP packet: The buffer length " | |
575 << max_len << " is less than the needed " << need_len; | |
576 return false; | |
577 } | |
578 | |
579 *out_len = in_len; | |
580 int err = srtp_protect_rtcp(session_, p, out_len); | |
581 srtp_stat_->AddProtectRtcpResult(err); | |
582 if (err != err_status_ok) { | |
583 LOG(LS_WARNING) << "Failed to protect SRTCP packet, err=" << err; | |
584 return false; | |
585 } | |
586 return true; | |
587 } | |
588 | |
589 bool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) { | |
590 if (!session_) { | |
591 LOG(LS_WARNING) << "Failed to unprotect SRTP packet: no SRTP Session"; | |
592 return false; | |
593 } | |
594 | |
595 *out_len = in_len; | |
596 int err = srtp_unprotect(session_, p, out_len); | |
597 uint32_t ssrc; | |
598 if (GetRtpSsrc(p, in_len, &ssrc)) { | |
599 srtp_stat_->AddUnprotectRtpResult(ssrc, err); | |
600 } | |
601 if (err != err_status_ok) { | |
602 LOG(LS_WARNING) << "Failed to unprotect SRTP packet, err=" << err; | |
603 return false; | |
604 } | |
605 return true; | |
606 } | |
607 | |
608 bool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) { | |
609 if (!session_) { | |
610 LOG(LS_WARNING) << "Failed to unprotect SRTCP packet: no SRTP Session"; | |
611 return false; | |
612 } | |
613 | |
614 *out_len = in_len; | |
615 int err = srtp_unprotect_rtcp(session_, p, out_len); | |
616 srtp_stat_->AddUnprotectRtcpResult(err); | |
617 if (err != err_status_ok) { | |
618 LOG(LS_WARNING) << "Failed to unprotect SRTCP packet, err=" << err; | |
619 return false; | |
620 } | |
621 return true; | |
622 } | |
623 | |
624 bool SrtpSession::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) { | |
625 #if defined(ENABLE_EXTERNAL_AUTH) | |
626 ExternalHmacContext* external_hmac = NULL; | |
627 // stream_template will be the reference context for other streams. | |
628 // Let's use it for getting the keys. | |
629 srtp_stream_ctx_t* srtp_context = session_->stream_template; | |
630 if (srtp_context && srtp_context->rtp_auth) { | |
631 external_hmac = reinterpret_cast<ExternalHmacContext*>( | |
632 srtp_context->rtp_auth->state); | |
633 } | |
634 | |
635 if (!external_hmac) { | |
636 LOG(LS_ERROR) << "Failed to get auth keys from libsrtp!."; | |
637 return false; | |
638 } | |
639 | |
640 *key = external_hmac->key; | |
641 *key_len = external_hmac->key_length; | |
642 *tag_len = rtp_auth_tag_len_; | |
643 return true; | |
644 #else | |
645 return false; | |
646 #endif | |
647 } | |
648 | |
649 bool SrtpSession::GetSendStreamPacketIndex(void* p, | |
650 int in_len, | |
651 int64_t* index) { | |
652 srtp_hdr_t* hdr = reinterpret_cast<srtp_hdr_t*>(p); | |
653 srtp_stream_ctx_t* stream = srtp_get_stream(session_, hdr->ssrc); | |
654 if (stream == NULL) | |
655 return false; | |
656 | |
657 // Shift packet index, put into network byte order | |
658 *index = static_cast<int64_t>( | |
659 rtc::NetworkToHost64(rdbx_get_packet_index(&stream->rtp_rdbx) << 16)); | |
660 return true; | |
661 } | |
662 | |
663 void SrtpSession::set_signal_silent_time(uint32_t signal_silent_time_in_ms) { | |
664 srtp_stat_->set_signal_silent_time(signal_silent_time_in_ms); | |
665 } | |
666 | |
667 bool SrtpSession::SetKey(int type, int cs, const uint8_t* key, int len) { | |
668 if (session_) { | |
669 LOG(LS_ERROR) << "Failed to create SRTP session: " | |
670 << "SRTP session already created"; | |
671 return false; | |
672 } | |
673 | |
674 if (!Init()) { | |
675 return false; | |
676 } | |
677 | |
678 srtp_policy_t policy; | |
679 memset(&policy, 0, sizeof(policy)); | |
680 | |
681 if (cs == rtc::SRTP_AES128_CM_SHA1_80) { | |
682 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp); | |
683 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); | |
684 } else if (cs == rtc::SRTP_AES128_CM_SHA1_32) { | |
685 crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); // rtp is 32, | |
686 crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // rtcp still 80 | |
687 } else { | |
688 LOG(LS_WARNING) << "Failed to create SRTP session: unsupported" | |
689 << " cipher_suite " << cs; | |
690 return false; | |
691 } | |
692 | |
693 if (!key || len != SRTP_MASTER_KEY_LEN) { | |
694 LOG(LS_WARNING) << "Failed to create SRTP session: invalid key"; | |
695 return false; | |
696 } | |
697 | |
698 policy.ssrc.type = static_cast<ssrc_type_t>(type); | |
699 policy.ssrc.value = 0; | |
700 policy.key = const_cast<uint8_t*>(key); | |
701 // TODO(astor) parse window size from WSH session-param | |
702 policy.window_size = 1024; | |
703 policy.allow_repeat_tx = 1; | |
704 // If external authentication option is enabled, supply custom auth module | |
705 // id EXTERNAL_HMAC_SHA1 in the policy structure. | |
706 // We want to set this option only for rtp packets. | |
707 // By default policy structure is initialized to HMAC_SHA1. | |
708 #if defined(ENABLE_EXTERNAL_AUTH) | |
709 // Enable external HMAC authentication only for outgoing streams. | |
710 if (type == ssrc_any_outbound) { | |
711 policy.rtp.auth_type = EXTERNAL_HMAC_SHA1; | |
712 } | |
713 #endif | |
714 policy.next = NULL; | |
715 | |
716 int err = srtp_create(&session_, &policy); | |
717 if (err != err_status_ok) { | |
718 session_ = NULL; | |
719 LOG(LS_ERROR) << "Failed to create SRTP session, err=" << err; | |
720 return false; | |
721 } | |
722 | |
723 | |
724 rtp_auth_tag_len_ = policy.rtp.auth_tag_len; | |
725 rtcp_auth_tag_len_ = policy.rtcp.auth_tag_len; | |
726 return true; | |
727 } | |
728 | |
729 bool SrtpSession::Init() { | |
730 rtc::GlobalLockScope ls(&lock_); | |
731 | |
732 if (!inited_) { | |
733 int err; | |
734 err = srtp_init(); | |
735 if (err != err_status_ok) { | |
736 LOG(LS_ERROR) << "Failed to init SRTP, err=" << err; | |
737 return false; | |
738 } | |
739 | |
740 err = srtp_install_event_handler(&SrtpSession::HandleEventThunk); | |
741 if (err != err_status_ok) { | |
742 LOG(LS_ERROR) << "Failed to install SRTP event handler, err=" << err; | |
743 return false; | |
744 } | |
745 #if defined(ENABLE_EXTERNAL_AUTH) | |
746 err = external_crypto_init(); | |
747 if (err != err_status_ok) { | |
748 LOG(LS_ERROR) << "Failed to initialize fake auth, err=" << err; | |
749 return false; | |
750 } | |
751 #endif | |
752 inited_ = true; | |
753 } | |
754 | |
755 return true; | |
756 } | |
757 | |
758 void SrtpSession::Terminate() { | |
759 rtc::GlobalLockScope ls(&lock_); | |
760 | |
761 if (inited_) { | |
762 int err = srtp_shutdown(); | |
763 if (err) { | |
764 LOG(LS_ERROR) << "srtp_shutdown failed. err=" << err; | |
765 return; | |
766 } | |
767 inited_ = false; | |
768 } | |
769 } | |
770 | |
771 void SrtpSession::HandleEvent(const srtp_event_data_t* ev) { | |
772 switch (ev->event) { | |
773 case event_ssrc_collision: | |
774 LOG(LS_INFO) << "SRTP event: SSRC collision"; | |
775 break; | |
776 case event_key_soft_limit: | |
777 LOG(LS_INFO) << "SRTP event: reached soft key usage limit"; | |
778 break; | |
779 case event_key_hard_limit: | |
780 LOG(LS_INFO) << "SRTP event: reached hard key usage limit"; | |
781 break; | |
782 case event_packet_index_limit: | |
783 LOG(LS_INFO) << "SRTP event: reached hard packet limit (2^48 packets)"; | |
784 break; | |
785 default: | |
786 LOG(LS_INFO) << "SRTP event: unknown " << ev->event; | |
787 break; | |
788 } | |
789 } | |
790 | |
791 void SrtpSession::HandleEventThunk(srtp_event_data_t* ev) { | |
792 rtc::GlobalLockScope ls(&lock_); | |
793 | |
794 for (std::list<SrtpSession*>::iterator it = sessions()->begin(); | |
795 it != sessions()->end(); ++it) { | |
796 if ((*it)->session_ == ev->session) { | |
797 (*it)->HandleEvent(ev); | |
798 break; | |
799 } | |
800 } | |
801 } | |
802 | |
803 std::list<SrtpSession*>* SrtpSession::sessions() { | |
804 RTC_DEFINE_STATIC_LOCAL(std::list<SrtpSession*>, sessions, ()); | |
805 return &sessions; | |
806 } | |
807 | |
808 #else // !HAVE_SRTP | |
809 | |
810 // On some systems, SRTP is not (yet) available. | |
811 | |
812 SrtpSession::SrtpSession() { | |
813 LOG(WARNING) << "SRTP implementation is missing."; | |
814 } | |
815 | |
816 SrtpSession::~SrtpSession() { | |
817 } | |
818 | |
819 bool SrtpSession::SetSend(const std::string& cs, const uint8_t* key, int len) { | |
820 return SrtpNotAvailable(__FUNCTION__); | |
821 } | |
822 | |
823 bool SrtpSession::SetRecv(const std::string& cs, const uint8_t* key, int len) { | |
824 return SrtpNotAvailable(__FUNCTION__); | |
825 } | |
826 | |
827 bool SrtpSession::ProtectRtp(void* data, int in_len, int max_len, | |
828 int* out_len) { | |
829 return SrtpNotAvailable(__FUNCTION__); | |
830 } | |
831 | |
832 bool SrtpSession::ProtectRtcp(void* data, int in_len, int max_len, | |
833 int* out_len) { | |
834 return SrtpNotAvailable(__FUNCTION__); | |
835 } | |
836 | |
837 bool SrtpSession::UnprotectRtp(void* data, int in_len, int* out_len) { | |
838 return SrtpNotAvailable(__FUNCTION__); | |
839 } | |
840 | |
841 bool SrtpSession::UnprotectRtcp(void* data, int in_len, int* out_len) { | |
842 return SrtpNotAvailable(__FUNCTION__); | |
843 } | |
844 | |
845 void SrtpSession::set_signal_silent_time(uint32_t signal_silent_time) { | |
846 // Do nothing. | |
847 } | |
848 | |
849 #endif // HAVE_SRTP | |
850 | |
851 /////////////////////////////////////////////////////////////////////////////// | |
852 // SrtpStat | |
853 | |
854 #ifdef HAVE_SRTP | |
855 | |
856 SrtpStat::SrtpStat() | |
857 : signal_silent_time_(1000) { | |
858 } | |
859 | |
860 void SrtpStat::AddProtectRtpResult(uint32_t ssrc, int result) { | |
861 FailureKey key; | |
862 key.ssrc = ssrc; | |
863 key.mode = SrtpFilter::PROTECT; | |
864 switch (result) { | |
865 case err_status_ok: | |
866 key.error = SrtpFilter::ERROR_NONE; | |
867 break; | |
868 case err_status_auth_fail: | |
869 key.error = SrtpFilter::ERROR_AUTH; | |
870 break; | |
871 default: | |
872 key.error = SrtpFilter::ERROR_FAIL; | |
873 } | |
874 HandleSrtpResult(key); | |
875 } | |
876 | |
877 void SrtpStat::AddUnprotectRtpResult(uint32_t ssrc, int result) { | |
878 FailureKey key; | |
879 key.ssrc = ssrc; | |
880 key.mode = SrtpFilter::UNPROTECT; | |
881 switch (result) { | |
882 case err_status_ok: | |
883 key.error = SrtpFilter::ERROR_NONE; | |
884 break; | |
885 case err_status_auth_fail: | |
886 key.error = SrtpFilter::ERROR_AUTH; | |
887 break; | |
888 case err_status_replay_fail: | |
889 case err_status_replay_old: | |
890 key.error = SrtpFilter::ERROR_REPLAY; | |
891 break; | |
892 default: | |
893 key.error = SrtpFilter::ERROR_FAIL; | |
894 } | |
895 HandleSrtpResult(key); | |
896 } | |
897 | |
898 void SrtpStat::AddProtectRtcpResult(int result) { | |
899 AddProtectRtpResult(0U, result); | |
900 } | |
901 | |
902 void SrtpStat::AddUnprotectRtcpResult(int result) { | |
903 AddUnprotectRtpResult(0U, result); | |
904 } | |
905 | |
906 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) { | |
907 // Handle some cases where error should be signalled right away. For other | |
908 // errors, trigger error for the first time seeing it. After that, silent | |
909 // the same error for a certain amount of time (default 1 sec). | |
910 if (key.error != SrtpFilter::ERROR_NONE) { | |
911 // For errors, signal first time and wait for 1 sec. | |
912 FailureStat* stat = &(failures_[key]); | |
913 uint32_t current_time = rtc::Time(); | |
914 if (stat->last_signal_time == 0 || | |
915 rtc::TimeDiff(current_time, stat->last_signal_time) > | |
916 static_cast<int>(signal_silent_time_)) { | |
917 SignalSrtpError(key.ssrc, key.mode, key.error); | |
918 stat->last_signal_time = current_time; | |
919 } | |
920 } | |
921 } | |
922 | |
923 #else // !HAVE_SRTP | |
924 | |
925 // On some systems, SRTP is not (yet) available. | |
926 | |
927 SrtpStat::SrtpStat() | |
928 : signal_silent_time_(1000) { | |
929 LOG(WARNING) << "SRTP implementation is missing."; | |
930 } | |
931 | |
932 void SrtpStat::AddProtectRtpResult(uint32_t ssrc, int result) { | |
933 SrtpNotAvailable(__FUNCTION__); | |
934 } | |
935 | |
936 void SrtpStat::AddUnprotectRtpResult(uint32_t ssrc, int result) { | |
937 SrtpNotAvailable(__FUNCTION__); | |
938 } | |
939 | |
940 void SrtpStat::AddProtectRtcpResult(int result) { | |
941 SrtpNotAvailable(__FUNCTION__); | |
942 } | |
943 | |
944 void SrtpStat::AddUnprotectRtcpResult(int result) { | |
945 SrtpNotAvailable(__FUNCTION__); | |
946 } | |
947 | |
948 void SrtpStat::HandleSrtpResult(const SrtpStat::FailureKey& key) { | |
949 SrtpNotAvailable(__FUNCTION__); | |
950 } | |
951 | |
952 #endif // HAVE_SRTP | |
953 | |
954 } // namespace cricket | |
OLD | NEW |