| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2009 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2009 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/pc/srtpfilter.h" | 11 #include "webrtc/pc/srtpfilter.h" |
| 12 | 12 |
| 13 #include <string.h> | 13 #include <string.h> |
| 14 | 14 |
| 15 #include <algorithm> | 15 #include <algorithm> |
| 16 | 16 |
| 17 #include "webrtc/media/base/rtputils.h" | 17 #include "webrtc/media/base/rtputils.h" |
| 18 #include "webrtc/pc/srtpsession.h" | 18 #include "webrtc/pc/srtpsession.h" |
| 19 #include "webrtc/rtc_base/base64.h" | 19 #include "webrtc/rtc_base/base64.h" |
| 20 #include "webrtc/rtc_base/buffer.h" | |
| 21 #include "webrtc/rtc_base/byteorder.h" | 20 #include "webrtc/rtc_base/byteorder.h" |
| 22 #include "webrtc/rtc_base/checks.h" | 21 #include "webrtc/rtc_base/checks.h" |
| 23 #include "webrtc/rtc_base/logging.h" | 22 #include "webrtc/rtc_base/logging.h" |
| 24 #include "webrtc/rtc_base/stringencode.h" | 23 #include "webrtc/rtc_base/stringencode.h" |
| 25 #include "webrtc/rtc_base/timeutils.h" | 24 #include "webrtc/rtc_base/timeutils.h" |
| 26 | 25 |
| 27 namespace cricket { | 26 namespace cricket { |
| 28 | 27 |
| 29 // NOTE: This is called from ChannelManager D'tor. | 28 // NOTE: This is called from ChannelManager D'tor. |
| 30 void ShutdownSrtp() { | 29 void ShutdownSrtp() { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 56 ContentSource source) { | 55 ContentSource source) { |
| 57 return DoSetAnswer(answer_params, source, true); | 56 return DoSetAnswer(answer_params, source, true); |
| 58 } | 57 } |
| 59 | 58 |
| 60 bool SrtpFilter::SetProvisionalAnswer( | 59 bool SrtpFilter::SetProvisionalAnswer( |
| 61 const std::vector<CryptoParams>& answer_params, | 60 const std::vector<CryptoParams>& answer_params, |
| 62 ContentSource source) { | 61 ContentSource source) { |
| 63 return DoSetAnswer(answer_params, source, false); | 62 return DoSetAnswer(answer_params, source, false); |
| 64 } | 63 } |
| 65 | 64 |
| 66 bool SrtpFilter::SetRtpParams(int send_cs, | |
| 67 const uint8_t* send_key, | |
| 68 int send_key_len, | |
| 69 int recv_cs, | |
| 70 const uint8_t* recv_key, | |
| 71 int recv_key_len) { | |
| 72 if (IsActive()) { | |
| 73 LOG(LS_ERROR) << "Tried to set SRTP Params when filter already active"; | |
| 74 return false; | |
| 75 } | |
| 76 CreateSrtpSessions(); | |
| 77 send_session_->SetEncryptedHeaderExtensionIds( | |
| 78 send_encrypted_header_extension_ids_); | |
| 79 if (!send_session_->SetSend(send_cs, send_key, send_key_len)) { | |
| 80 return false; | |
| 81 } | |
| 82 | |
| 83 recv_session_->SetEncryptedHeaderExtensionIds( | |
| 84 recv_encrypted_header_extension_ids_); | |
| 85 if (!recv_session_->SetRecv(recv_cs, recv_key, recv_key_len)) { | |
| 86 return false; | |
| 87 } | |
| 88 | |
| 89 state_ = ST_ACTIVE; | |
| 90 | |
| 91 LOG(LS_INFO) << "SRTP activated with negotiated parameters:" | |
| 92 << " send cipher_suite " << send_cs | |
| 93 << " recv cipher_suite " << recv_cs; | |
| 94 return true; | |
| 95 } | |
| 96 | |
| 97 bool SrtpFilter::UpdateRtpParams(int send_cs, | |
| 98 const uint8_t* send_key, | |
| 99 int send_key_len, | |
| 100 int recv_cs, | |
| 101 const uint8_t* recv_key, | |
| 102 int recv_key_len) { | |
| 103 if (!IsActive()) { | |
| 104 LOG(LS_ERROR) << "Tried to update SRTP Params when filter is not active"; | |
| 105 return false; | |
| 106 } | |
| 107 send_session_->SetEncryptedHeaderExtensionIds( | |
| 108 send_encrypted_header_extension_ids_); | |
| 109 if (!send_session_->UpdateSend(send_cs, send_key, send_key_len)) { | |
| 110 return false; | |
| 111 } | |
| 112 | |
| 113 recv_session_->SetEncryptedHeaderExtensionIds( | |
| 114 recv_encrypted_header_extension_ids_); | |
| 115 if (!recv_session_->UpdateRecv(recv_cs, recv_key, recv_key_len)) { | |
| 116 return false; | |
| 117 } | |
| 118 | |
| 119 LOG(LS_INFO) << "SRTP updated with negotiated parameters:" | |
| 120 << " send cipher_suite " << send_cs | |
| 121 << " recv cipher_suite " << recv_cs; | |
| 122 return true; | |
| 123 } | |
| 124 | |
| 125 // This function is provided separately because DTLS-SRTP behaves | |
| 126 // differently in RTP/RTCP mux and non-mux modes. | |
| 127 // | |
| 128 // - In the non-muxed case, RTP and RTCP are keyed with different | |
| 129 // keys (from different DTLS handshakes), and so we need a new | |
| 130 // SrtpSession. | |
| 131 // - In the muxed case, they are keyed with the same keys, so | |
| 132 // this function is not needed | |
| 133 bool SrtpFilter::SetRtcpParams(int send_cs, | |
| 134 const uint8_t* send_key, | |
| 135 int send_key_len, | |
| 136 int recv_cs, | |
| 137 const uint8_t* recv_key, | |
| 138 int recv_key_len) { | |
| 139 // This can only be called once, but can be safely called after | |
| 140 // SetRtpParams | |
| 141 if (send_rtcp_session_ || recv_rtcp_session_) { | |
| 142 LOG(LS_ERROR) << "Tried to set SRTCP Params when filter already active"; | |
| 143 return false; | |
| 144 } | |
| 145 | |
| 146 send_rtcp_session_.reset(new SrtpSession()); | |
| 147 if (!send_rtcp_session_->SetRecv(send_cs, send_key, send_key_len)) { | |
| 148 return false; | |
| 149 } | |
| 150 | |
| 151 recv_rtcp_session_.reset(new SrtpSession()); | |
| 152 if (!recv_rtcp_session_->SetRecv(recv_cs, recv_key, recv_key_len)) { | |
| 153 return false; | |
| 154 } | |
| 155 | |
| 156 LOG(LS_INFO) << "SRTCP activated with negotiated parameters:" | |
| 157 << " send cipher_suite " << send_cs | |
| 158 << " recv cipher_suite " << recv_cs; | |
| 159 | |
| 160 return true; | |
| 161 } | |
| 162 | |
| 163 bool SrtpFilter::ProtectRtp(void* p, int in_len, int max_len, int* out_len) { | |
| 164 if (!IsActive()) { | |
| 165 LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active"; | |
| 166 return false; | |
| 167 } | |
| 168 RTC_CHECK(send_session_); | |
| 169 return send_session_->ProtectRtp(p, in_len, max_len, out_len); | |
| 170 } | |
| 171 | |
| 172 bool SrtpFilter::ProtectRtp(void* p, | |
| 173 int in_len, | |
| 174 int max_len, | |
| 175 int* out_len, | |
| 176 int64_t* index) { | |
| 177 if (!IsActive()) { | |
| 178 LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active"; | |
| 179 return false; | |
| 180 } | |
| 181 RTC_CHECK(send_session_); | |
| 182 return send_session_->ProtectRtp(p, in_len, max_len, out_len, index); | |
| 183 } | |
| 184 | |
| 185 bool SrtpFilter::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) { | |
| 186 if (!IsActive()) { | |
| 187 LOG(LS_WARNING) << "Failed to ProtectRtcp: SRTP not active"; | |
| 188 return false; | |
| 189 } | |
| 190 if (send_rtcp_session_) { | |
| 191 return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len); | |
| 192 } else { | |
| 193 RTC_CHECK(send_session_); | |
| 194 return send_session_->ProtectRtcp(p, in_len, max_len, out_len); | |
| 195 } | |
| 196 } | |
| 197 | |
| 198 bool SrtpFilter::UnprotectRtp(void* p, int in_len, int* out_len) { | |
| 199 if (!IsActive()) { | |
| 200 LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active"; | |
| 201 return false; | |
| 202 } | |
| 203 RTC_CHECK(recv_session_); | |
| 204 return recv_session_->UnprotectRtp(p, in_len, out_len); | |
| 205 } | |
| 206 | |
| 207 bool SrtpFilter::UnprotectRtcp(void* p, int in_len, int* out_len) { | |
| 208 if (!IsActive()) { | |
| 209 LOG(LS_WARNING) << "Failed to UnprotectRtcp: SRTP not active"; | |
| 210 return false; | |
| 211 } | |
| 212 if (recv_rtcp_session_) { | |
| 213 return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len); | |
| 214 } else { | |
| 215 RTC_CHECK(recv_session_); | |
| 216 return recv_session_->UnprotectRtcp(p, in_len, out_len); | |
| 217 } | |
| 218 } | |
| 219 | |
| 220 bool SrtpFilter::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) { | |
| 221 if (!IsActive()) { | |
| 222 LOG(LS_WARNING) << "Failed to GetRtpAuthParams: SRTP not active"; | |
| 223 return false; | |
| 224 } | |
| 225 | |
| 226 RTC_CHECK(send_session_); | |
| 227 return send_session_->GetRtpAuthParams(key, key_len, tag_len); | |
| 228 } | |
| 229 | |
| 230 bool SrtpFilter::GetSrtpOverhead(int* srtp_overhead) const { | |
| 231 if (!IsActive()) { | |
| 232 LOG(LS_WARNING) << "Failed to GetSrtpOverhead: SRTP not active"; | |
| 233 return false; | |
| 234 } | |
| 235 | |
| 236 RTC_CHECK(send_session_); | |
| 237 *srtp_overhead = send_session_->GetSrtpOverhead(); | |
| 238 return true; | |
| 239 } | |
| 240 | |
| 241 void SrtpFilter::EnableExternalAuth() { | |
| 242 RTC_DCHECK(!IsActive()); | |
| 243 external_auth_enabled_ = true; | |
| 244 } | |
| 245 | |
| 246 bool SrtpFilter::IsExternalAuthEnabled() const { | |
| 247 return external_auth_enabled_; | |
| 248 } | |
| 249 | |
| 250 bool SrtpFilter::IsExternalAuthActive() const { | |
| 251 if (!IsActive()) { | |
| 252 LOG(LS_WARNING) << "Failed to check IsExternalAuthActive: SRTP not active"; | |
| 253 return false; | |
| 254 } | |
| 255 | |
| 256 RTC_CHECK(send_session_); | |
| 257 return send_session_->IsExternalAuthActive(); | |
| 258 } | |
| 259 | |
| 260 void SrtpFilter::SetEncryptedHeaderExtensionIds(ContentSource source, | |
| 261 const std::vector<int>& extension_ids) { | |
| 262 if (source == CS_LOCAL) { | |
| 263 recv_encrypted_header_extension_ids_ = extension_ids; | |
| 264 } else { | |
| 265 send_encrypted_header_extension_ids_ = extension_ids; | |
| 266 } | |
| 267 } | |
| 268 | |
| 269 bool SrtpFilter::ExpectOffer(ContentSource source) { | 65 bool SrtpFilter::ExpectOffer(ContentSource source) { |
| 270 return ((state_ == ST_INIT) || | 66 return ((state_ == ST_INIT) || |
| 271 (state_ == ST_ACTIVE) || | 67 (state_ == ST_ACTIVE) || |
| 272 (state_ == ST_SENTOFFER && source == CS_LOCAL) || | 68 (state_ == ST_SENTOFFER && source == CS_LOCAL) || |
| 273 (state_ == ST_SENTUPDATEDOFFER && source == CS_LOCAL) || | 69 (state_ == ST_SENTUPDATEDOFFER && source == CS_LOCAL) || |
| 274 (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) || | 70 (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) || |
| 275 (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE)); | 71 (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE)); |
| 276 } | 72 } |
| 277 | 73 |
| 278 bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params, | 74 bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 // Need to wait for the final answer to decide if | 112 // Need to wait for the final answer to decide if |
| 317 // we should go to Active state. | 113 // we should go to Active state. |
| 318 state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO : | 114 state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO : |
| 319 ST_RECEIVEDPRANSWER_NO_CRYPTO; | 115 ST_RECEIVEDPRANSWER_NO_CRYPTO; |
| 320 return true; | 116 return true; |
| 321 } | 117 } |
| 322 } | 118 } |
| 323 CryptoParams selected_params; | 119 CryptoParams selected_params; |
| 324 if (!NegotiateParams(answer_params, &selected_params)) | 120 if (!NegotiateParams(answer_params, &selected_params)) |
| 325 return false; | 121 return false; |
| 326 const CryptoParams& send_params = | 122 |
| 123 const CryptoParams& new_send_params = |
| 327 (source == CS_REMOTE) ? selected_params : answer_params[0]; | 124 (source == CS_REMOTE) ? selected_params : answer_params[0]; |
| 328 const CryptoParams& recv_params = | 125 const CryptoParams& new_recv_params = |
| 329 (source == CS_REMOTE) ? answer_params[0] : selected_params; | 126 (source == CS_REMOTE) ? answer_params[0] : selected_params; |
| 330 if (!ApplyParams(send_params, recv_params)) { | 127 if (!ApplySendParams(new_send_params) || !ApplyRecvParams(new_recv_params)) { |
| 331 return false; | 128 return false; |
| 332 } | 129 } |
| 130 applied_send_params_ = new_send_params; |
| 131 applied_recv_params_ = new_recv_params; |
| 333 | 132 |
| 334 if (final) { | 133 if (final) { |
| 335 offer_params_.clear(); | 134 offer_params_.clear(); |
| 336 state_ = ST_ACTIVE; | 135 state_ = ST_ACTIVE; |
| 337 } else { | 136 } else { |
| 338 state_ = | 137 state_ = |
| 339 (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER; | 138 (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER; |
| 340 } | 139 } |
| 341 return true; | 140 return true; |
| 342 } | 141 } |
| 343 | 142 |
| 344 void SrtpFilter::CreateSrtpSessions() { | |
| 345 send_session_.reset(new SrtpSession()); | |
| 346 applied_send_params_ = CryptoParams(); | |
| 347 recv_session_.reset(new SrtpSession()); | |
| 348 applied_recv_params_ = CryptoParams(); | |
| 349 | |
| 350 if (external_auth_enabled_) { | |
| 351 send_session_->EnableExternalAuth(); | |
| 352 } | |
| 353 } | |
| 354 | |
| 355 bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params, | 143 bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params, |
| 356 CryptoParams* selected_params) { | 144 CryptoParams* selected_params) { |
| 357 // We're processing an accept. We should have exactly one set of params, | 145 // We're processing an accept. We should have exactly one set of params, |
| 358 // unless the offer didn't mention crypto, in which case we shouldn't be here. | 146 // unless the offer didn't mention crypto, in which case we shouldn't be here. |
| 359 bool ret = (answer_params.size() == 1U && !offer_params_.empty()); | 147 bool ret = (answer_params.size() == 1U && !offer_params_.empty()); |
| 360 if (ret) { | 148 if (ret) { |
| 361 // We should find a match between the answer params and the offered params. | 149 // We should find a match between the answer params and the offered params. |
| 362 std::vector<CryptoParams>::const_iterator it; | 150 std::vector<CryptoParams>::const_iterator it; |
| 363 for (it = offer_params_.begin(); it != offer_params_.end(); ++it) { | 151 for (it = offer_params_.begin(); it != offer_params_.end(); ++it) { |
| 364 if (answer_params[0].Matches(*it)) { | 152 if (answer_params[0].Matches(*it)) { |
| 365 break; | 153 break; |
| 366 } | 154 } |
| 367 } | 155 } |
| 368 | 156 |
| 369 if (it != offer_params_.end()) { | 157 if (it != offer_params_.end()) { |
| 370 *selected_params = *it; | 158 *selected_params = *it; |
| 371 } else { | 159 } else { |
| 372 ret = false; | 160 ret = false; |
| 373 } | 161 } |
| 374 } | 162 } |
| 375 | 163 |
| 376 if (!ret) { | 164 if (!ret) { |
| 377 LOG(LS_WARNING) << "Invalid parameters in SRTP answer"; | 165 LOG(LS_WARNING) << "Invalid parameters in SRTP answer"; |
| 378 } | 166 } |
| 379 return ret; | 167 return ret; |
| 380 } | 168 } |
| 381 | 169 |
| 382 bool SrtpFilter::ApplyParams(const CryptoParams& send_params, | 170 bool SrtpFilter::ResetParams() { |
| 383 const CryptoParams& recv_params) { | 171 offer_params_.clear(); |
| 384 // TODO(jiayl): Split this method to apply send and receive CryptoParams | 172 applied_send_params_ = CryptoParams(); |
| 385 // independently, so that we can skip one method when either send or receive | 173 applied_recv_params_ = CryptoParams(); |
| 386 // CryptoParams is unchanged. | 174 send_cipher_suite_ = rtc::Optional<int>(); |
| 175 recv_cipher_suite_ = rtc::Optional<int>(); |
| 176 send_key_.Clear(); |
| 177 recv_key_.Clear(); |
| 178 state_ = ST_INIT; |
| 179 return true; |
| 180 } |
| 181 |
| 182 bool SrtpFilter::ApplySendParams(const CryptoParams& send_params) { |
| 387 if (applied_send_params_.cipher_suite == send_params.cipher_suite && | 183 if (applied_send_params_.cipher_suite == send_params.cipher_suite && |
| 388 applied_send_params_.key_params == send_params.key_params && | 184 applied_send_params_.key_params == send_params.key_params) { |
| 389 applied_recv_params_.cipher_suite == recv_params.cipher_suite && | 185 LOG(LS_INFO) << "Applying the same SRTP send parameters again. No-op."; |
| 390 applied_recv_params_.key_params == recv_params.key_params) { | |
| 391 LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op."; | |
| 392 | 186 |
| 393 // We do not want to reset the ROC if the keys are the same. So just return. | 187 // We do not want to reset the ROC if the keys are the same. So just return. |
| 394 return true; | 188 return true; |
| 395 } | 189 } |
| 396 | 190 |
| 397 int send_suite = rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite); | 191 send_cipher_suite_ = rtc::Optional<int>( |
| 398 int recv_suite = rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite); | 192 rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite)); |
| 399 if (send_suite == rtc::SRTP_INVALID_CRYPTO_SUITE || | 193 if (send_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) { |
| 400 recv_suite == rtc::SRTP_INVALID_CRYPTO_SUITE) { | |
| 401 LOG(LS_WARNING) << "Unknown crypto suite(s) received:" | 194 LOG(LS_WARNING) << "Unknown crypto suite(s) received:" |
| 402 << " send cipher_suite " << send_params.cipher_suite | 195 << " send cipher_suite " << send_params.cipher_suite; |
| 196 return false; |
| 197 } |
| 198 |
| 199 int send_key_len, send_salt_len; |
| 200 if (!rtc::GetSrtpKeyAndSaltLengths(*send_cipher_suite_, &send_key_len, |
| 201 &send_salt_len)) { |
| 202 LOG(LS_WARNING) << "Could not get lengths for crypto suite(s):" |
| 203 << " send cipher_suite " << send_params.cipher_suite; |
| 204 return false; |
| 205 } |
| 206 |
| 207 send_key_ = rtc::Buffer(send_key_len + send_salt_len); |
| 208 return ParseKeyParams(send_params.key_params, send_key_.data(), |
| 209 send_key_.size()); |
| 210 } |
| 211 |
| 212 bool SrtpFilter::ApplyRecvParams(const CryptoParams& recv_params) { |
| 213 if (applied_recv_params_.cipher_suite == recv_params.cipher_suite && |
| 214 applied_recv_params_.key_params == recv_params.key_params) { |
| 215 LOG(LS_INFO) << "Applying the same SRTP recv parameters again. No-op."; |
| 216 |
| 217 // We do not want to reset the ROC if the keys are the same. So just return. |
| 218 return true; |
| 219 } |
| 220 |
| 221 recv_cipher_suite_ = rtc::Optional<int>( |
| 222 rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite)); |
| 223 if (recv_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) { |
| 224 LOG(LS_WARNING) << "Unknown crypto suite(s) received:" |
| 403 << " recv cipher_suite " << recv_params.cipher_suite; | 225 << " recv cipher_suite " << recv_params.cipher_suite; |
| 404 return false; | 226 return false; |
| 405 } | 227 } |
| 406 | 228 |
| 407 int send_key_len, send_salt_len; | |
| 408 int recv_key_len, recv_salt_len; | 229 int recv_key_len, recv_salt_len; |
| 409 if (!rtc::GetSrtpKeyAndSaltLengths(send_suite, &send_key_len, | 230 if (!rtc::GetSrtpKeyAndSaltLengths(*recv_cipher_suite_, &recv_key_len, |
| 410 &send_salt_len) || | |
| 411 !rtc::GetSrtpKeyAndSaltLengths(recv_suite, &recv_key_len, | |
| 412 &recv_salt_len)) { | 231 &recv_salt_len)) { |
| 413 LOG(LS_WARNING) << "Could not get lengths for crypto suite(s):" | 232 LOG(LS_WARNING) << "Could not get lengths for crypto suite(s):" |
| 414 << " send cipher_suite " << send_params.cipher_suite | |
| 415 << " recv cipher_suite " << recv_params.cipher_suite; | 233 << " recv cipher_suite " << recv_params.cipher_suite; |
| 416 return false; | 234 return false; |
| 417 } | 235 } |
| 418 | 236 |
| 419 // TODO(juberti): Zero these buffers after use. | 237 recv_key_ = rtc::Buffer(recv_key_len + recv_salt_len); |
| 420 bool ret; | 238 return ParseKeyParams(recv_params.key_params, recv_key_.data(), |
| 421 rtc::Buffer send_key(send_key_len + send_salt_len); | 239 recv_key_.size()); |
| 422 rtc::Buffer recv_key(recv_key_len + recv_salt_len); | |
| 423 ret = (ParseKeyParams(send_params.key_params, send_key.data(), | |
| 424 send_key.size()) && | |
| 425 ParseKeyParams(recv_params.key_params, recv_key.data(), | |
| 426 recv_key.size())); | |
| 427 if (ret) { | |
| 428 CreateSrtpSessions(); | |
| 429 send_session_->SetEncryptedHeaderExtensionIds( | |
| 430 send_encrypted_header_extension_ids_); | |
| 431 recv_session_->SetEncryptedHeaderExtensionIds( | |
| 432 recv_encrypted_header_extension_ids_); | |
| 433 ret = (send_session_->SetSend( | |
| 434 rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite), | |
| 435 send_key.data(), send_key.size()) && | |
| 436 recv_session_->SetRecv( | |
| 437 rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite), | |
| 438 recv_key.data(), recv_key.size())); | |
| 439 } | |
| 440 if (ret) { | |
| 441 LOG(LS_INFO) << "SRTP activated with negotiated parameters:" | |
| 442 << " send cipher_suite " << send_params.cipher_suite | |
| 443 << " recv cipher_suite " << recv_params.cipher_suite; | |
| 444 applied_send_params_ = send_params; | |
| 445 applied_recv_params_ = recv_params; | |
| 446 } else { | |
| 447 LOG(LS_WARNING) << "Failed to apply negotiated SRTP parameters"; | |
| 448 } | |
| 449 return ret; | |
| 450 } | |
| 451 | |
| 452 bool SrtpFilter::ResetParams() { | |
| 453 offer_params_.clear(); | |
| 454 state_ = ST_INIT; | |
| 455 send_session_ = nullptr; | |
| 456 recv_session_ = nullptr; | |
| 457 send_rtcp_session_ = nullptr; | |
| 458 recv_rtcp_session_ = nullptr; | |
| 459 LOG(LS_INFO) << "SRTP reset to init state"; | |
| 460 return true; | |
| 461 } | 240 } |
| 462 | 241 |
| 463 bool SrtpFilter::ParseKeyParams(const std::string& key_params, | 242 bool SrtpFilter::ParseKeyParams(const std::string& key_params, |
| 464 uint8_t* key, | 243 uint8_t* key, |
| 465 size_t len) { | 244 size_t len) { |
| 466 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2" | 245 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2" |
| 467 | 246 |
| 468 // Fail if key-method is wrong. | 247 // Fail if key-method is wrong. |
| 469 if (key_params.find("inline:") != 0) { | 248 if (key_params.find("inline:") != 0) { |
| 470 return false; | 249 return false; |
| 471 } | 250 } |
| 472 | 251 |
| 473 // Fail if base64 decode fails, or the key is the wrong size. | 252 // Fail if base64 decode fails, or the key is the wrong size. |
| 474 std::string key_b64(key_params.substr(7)), key_str; | 253 std::string key_b64(key_params.substr(7)), key_str; |
| 475 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, | 254 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, &key_str, |
| 476 &key_str, nullptr) || key_str.size() != len) { | 255 nullptr) || |
| 256 key_str.size() != len) { |
| 477 return false; | 257 return false; |
| 478 } | 258 } |
| 479 | 259 |
| 480 memcpy(key, key_str.c_str(), len); | 260 memcpy(key, key_str.c_str(), len); |
| 481 return true; | 261 return true; |
| 482 } | 262 } |
| 483 | 263 |
| 484 } // namespace cricket | 264 } // namespace cricket |
| OLD | NEW |