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