media/webrtc/signaling/src/mediapipeline/SrtpFlow.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 // Original author: ekr@rtfm.com
     7 #include "logging.h"
     8 #include "SrtpFlow.h"
    10 #include "srtp.h"
    11 #include "ssl.h"
    12 #include "sslproto.h"
    14 #include "mozilla/RefPtr.h"
    16 // Logging context
    17 using namespace mozilla;
    18 MOZ_MTLOG_MODULE("mediapipeline")
    20 namespace mozilla {
    22 bool SrtpFlow::initialized;  // Static
    24 SrtpFlow::~SrtpFlow() {
    25   if (session_) {
    26     srtp_dealloc(session_);
    27   }
    28 }
    30 RefPtr<SrtpFlow> SrtpFlow::Create(int cipher_suite,
    31                                            bool inbound,
    32                                            const void *key,
    33                                            size_t key_len) {
    34   nsresult res = Init();
    35   if (!NS_SUCCEEDED(res))
    36     return nullptr;
    38   RefPtr<SrtpFlow> flow = new SrtpFlow();
    40   if (!key) {
    41     MOZ_MTLOG(ML_ERROR, "Null SRTP key specified");
    42     return nullptr;
    43   }
    45   if (key_len != SRTP_TOTAL_KEY_LENGTH) {
    46     MOZ_MTLOG(ML_ERROR, "Invalid SRTP key length");
    47     return nullptr;
    48   }
    50   srtp_policy_t policy;
    51   memset(&policy, 0, sizeof(srtp_policy_t));
    53   // Note that we set the same cipher suite for RTP and RTCP
    54   // since any flow can only have one cipher suite with DTLS-SRTP
    55   switch (cipher_suite) {
    56     case SRTP_AES128_CM_HMAC_SHA1_80:
    57       MOZ_MTLOG(ML_DEBUG,
    58                 "Setting SRTP cipher suite SRTP_AES128_CM_HMAC_SHA1_80");
    59       crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
    60       crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
    61       break;
    62     case SRTP_AES128_CM_HMAC_SHA1_32:
    63       MOZ_MTLOG(ML_DEBUG,
    64                 "Setting SRTP cipher suite SRTP_AES128_CM_HMAC_SHA1_32");
    65       crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp);
    66       crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // 80-bit per RFC 5764
    67       break;                                                   // S 4.1.2.
    68     default:
    69       MOZ_MTLOG(ML_ERROR, "Request to set unknown SRTP cipher suite");
    70       return nullptr;
    71   }
    72   // This key is copied into the srtp_t object, so we don't
    73   // need to keep it.
    74   policy.key = const_cast<unsigned char *>(
    75       static_cast<const unsigned char *>(key));
    76   policy.ssrc.type = inbound ? ssrc_any_inbound : ssrc_any_outbound;
    77   policy.ssrc.value = 0;
    78   policy.ekt = nullptr;
    79   policy.window_size = 1024;   // Use the Chrome value.  Needs to be revisited.  Default is 128
    80   policy.allow_repeat_tx = 1;  // Use Chrome value; needed for NACK mode to work
    81   policy.next = nullptr;
    83   // Now make the session
    84   err_status_t r = srtp_create(&flow->session_, &policy);
    85   if (r != err_status_ok) {
    86     MOZ_MTLOG(ML_ERROR, "Error creating srtp session");
    87     return nullptr;
    88   }
    90   return flow;
    91 }
    94 nsresult SrtpFlow::CheckInputs(bool protect, void *in, int in_len,
    95                                int max_len, int *out_len) {
    96   MOZ_ASSERT(in);
    97   if (!in) {
    98     MOZ_MTLOG(ML_ERROR, "NULL input value");
    99     return NS_ERROR_NULL_POINTER;
   100   }
   102   if (in_len < 0) {
   103     MOZ_MTLOG(ML_ERROR, "Input length is negative");
   104     return NS_ERROR_ILLEGAL_VALUE;
   105   }
   107   if (max_len < 0) {
   108     MOZ_MTLOG(ML_ERROR, "Max output length is negative");
   109     return NS_ERROR_ILLEGAL_VALUE;
   110   }
   112   if (protect) {
   113     if ((max_len < SRTP_MAX_EXPANSION) ||
   114         ((max_len - SRTP_MAX_EXPANSION) < in_len)) {
   115       MOZ_MTLOG(ML_ERROR, "Output too short");
   116       return NS_ERROR_ILLEGAL_VALUE;
   117     }
   118   }
   119   else {
   120     if (in_len > max_len) {
   121       MOZ_MTLOG(ML_ERROR, "Output too short");
   122       return NS_ERROR_ILLEGAL_VALUE;
   123     }
   124   }
   126   return NS_OK;
   127 }
   129 nsresult SrtpFlow::ProtectRtp(void *in, int in_len,
   130                               int max_len, int *out_len) {
   131   nsresult res = CheckInputs(true, in, in_len, max_len, out_len);
   132   if (NS_FAILED(res))
   133     return res;
   135   int len = in_len;
   136   err_status_t r = srtp_protect(session_, in, &len);
   138   if (r != err_status_ok) {
   139     MOZ_MTLOG(ML_ERROR, "Error protecting SRTP packet");
   140     return NS_ERROR_FAILURE;
   141   }
   143   MOZ_ASSERT(len <= max_len);
   144   *out_len = len;
   147   MOZ_MTLOG(ML_DEBUG, "Successfully protected an SRTP packet of len "
   148             << *out_len);
   150   return NS_OK;
   151 }
   153 nsresult SrtpFlow::UnprotectRtp(void *in, int in_len,
   154                                 int max_len, int *out_len) {
   155   nsresult res = CheckInputs(false, in, in_len, max_len, out_len);
   156   if (NS_FAILED(res))
   157     return res;
   159   int len = in_len;
   160   err_status_t r = srtp_unprotect(session_, in, &len);
   162   if (r != err_status_ok) {
   163     MOZ_MTLOG(ML_ERROR, "Error unprotecting SRTP packet error=" << (int)r);
   164     return NS_ERROR_FAILURE;
   165   }
   167   MOZ_ASSERT(len <= max_len);
   168   *out_len = len;
   170   MOZ_MTLOG(ML_DEBUG, "Successfully unprotected an SRTP packet of len "
   171             << *out_len);
   173   return NS_OK;
   174 }
   176 nsresult SrtpFlow::ProtectRtcp(void *in, int in_len,
   177                                int max_len, int *out_len) {
   178   nsresult res = CheckInputs(true, in, in_len, max_len, out_len);
   179   if (NS_FAILED(res))
   180     return res;
   182   int len = in_len;
   183   err_status_t r = srtp_protect_rtcp(session_, in, &len);
   185   if (r != err_status_ok) {
   186     MOZ_MTLOG(ML_ERROR, "Error protecting SRTCP packet");
   187     return NS_ERROR_FAILURE;
   188   }
   190   MOZ_ASSERT(len <= max_len);
   191   *out_len = len;
   193   MOZ_MTLOG(ML_DEBUG, "Successfully protected an SRTCP packet of len "
   194             << *out_len);
   196   return NS_OK;
   197 }
   199 nsresult SrtpFlow::UnprotectRtcp(void *in, int in_len,
   200                                  int max_len, int *out_len) {
   201   nsresult res = CheckInputs(false, in, in_len, max_len, out_len);
   202   if (NS_FAILED(res))
   203     return res;
   205   int len = in_len;
   206   err_status_t r = srtp_unprotect_rtcp(session_, in, &len);
   208   if (r != err_status_ok) {
   209     MOZ_MTLOG(ML_ERROR, "Error unprotecting SRTCP packet error=" << (int)r);
   210     return NS_ERROR_FAILURE;
   211   }
   213   MOZ_ASSERT(len <= max_len);
   214   *out_len = len;
   216   MOZ_MTLOG(ML_DEBUG, "Successfully unprotected an SRTCP packet of len "
   217             << *out_len);
   219   return NS_OK;
   220 }
   222 // Statics
   223 void SrtpFlow::srtp_event_handler(srtp_event_data_t *data) {
   224   // TODO(ekr@rtfm.com): Implement this
   225   MOZ_CRASH();
   226 }
   228 nsresult SrtpFlow::Init() {
   229   if (!initialized) {
   230     err_status_t r = srtp_init();
   231     if (r != err_status_ok) {
   232       MOZ_MTLOG(ML_ERROR, "Could not initialize SRTP");
   233       MOZ_ASSERT(PR_FALSE);
   234       return NS_ERROR_FAILURE;
   235     }
   237     r = srtp_install_event_handler(&SrtpFlow::srtp_event_handler);
   238     if (r != err_status_ok) {
   239       MOZ_MTLOG(ML_ERROR, "Could not install SRTP event handler");
   240       MOZ_ASSERT(PR_FALSE);
   241       return NS_ERROR_FAILURE;
   242     }
   244     initialized = true;
   245   }
   247   return NS_OK;
   248 }
   250 }  // end of namespace

mercurial