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.

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

mercurial