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" |
20 #include "webrtc/rtc_base/byteorder.h" | 21 #include "webrtc/rtc_base/byteorder.h" |
21 #include "webrtc/rtc_base/checks.h" | 22 #include "webrtc/rtc_base/checks.h" |
22 #include "webrtc/rtc_base/logging.h" | 23 #include "webrtc/rtc_base/logging.h" |
23 #include "webrtc/rtc_base/stringencode.h" | 24 #include "webrtc/rtc_base/stringencode.h" |
24 #include "webrtc/rtc_base/timeutils.h" | 25 #include "webrtc/rtc_base/timeutils.h" |
25 | 26 |
26 namespace cricket { | 27 namespace cricket { |
27 | 28 |
28 // NOTE: This is called from ChannelManager D'tor. | 29 // NOTE: This is called from ChannelManager D'tor. |
29 void ShutdownSrtp() { | 30 void ShutdownSrtp() { |
(...skipping 25 matching lines...) Expand all Loading... |
55 ContentSource source) { | 56 ContentSource source) { |
56 return DoSetAnswer(answer_params, source, true); | 57 return DoSetAnswer(answer_params, source, true); |
57 } | 58 } |
58 | 59 |
59 bool SrtpFilter::SetProvisionalAnswer( | 60 bool SrtpFilter::SetProvisionalAnswer( |
60 const std::vector<CryptoParams>& answer_params, | 61 const std::vector<CryptoParams>& answer_params, |
61 ContentSource source) { | 62 ContentSource source) { |
62 return DoSetAnswer(answer_params, source, false); | 63 return DoSetAnswer(answer_params, source, false); |
63 } | 64 } |
64 | 65 |
| 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 |
65 bool SrtpFilter::ExpectOffer(ContentSource source) { | 269 bool SrtpFilter::ExpectOffer(ContentSource source) { |
66 return ((state_ == ST_INIT) || | 270 return ((state_ == ST_INIT) || |
67 (state_ == ST_ACTIVE) || | 271 (state_ == ST_ACTIVE) || |
68 (state_ == ST_SENTOFFER && source == CS_LOCAL) || | 272 (state_ == ST_SENTOFFER && source == CS_LOCAL) || |
69 (state_ == ST_SENTUPDATEDOFFER && source == CS_LOCAL) || | 273 (state_ == ST_SENTUPDATEDOFFER && source == CS_LOCAL) || |
70 (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) || | 274 (state_ == ST_RECEIVEDOFFER && source == CS_REMOTE) || |
71 (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE)); | 275 (state_ == ST_RECEIVEDUPDATEDOFFER && source == CS_REMOTE)); |
72 } | 276 } |
73 | 277 |
74 bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params, | 278 bool SrtpFilter::StoreParams(const std::vector<CryptoParams>& params, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 // Need to wait for the final answer to decide if | 316 // Need to wait for the final answer to decide if |
113 // we should go to Active state. | 317 // we should go to Active state. |
114 state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO : | 318 state_ = (source == CS_LOCAL) ? ST_SENTPRANSWER_NO_CRYPTO : |
115 ST_RECEIVEDPRANSWER_NO_CRYPTO; | 319 ST_RECEIVEDPRANSWER_NO_CRYPTO; |
116 return true; | 320 return true; |
117 } | 321 } |
118 } | 322 } |
119 CryptoParams selected_params; | 323 CryptoParams selected_params; |
120 if (!NegotiateParams(answer_params, &selected_params)) | 324 if (!NegotiateParams(answer_params, &selected_params)) |
121 return false; | 325 return false; |
122 | 326 const CryptoParams& send_params = |
123 const CryptoParams& new_send_params = | |
124 (source == CS_REMOTE) ? selected_params : answer_params[0]; | 327 (source == CS_REMOTE) ? selected_params : answer_params[0]; |
125 const CryptoParams& new_recv_params = | 328 const CryptoParams& recv_params = |
126 (source == CS_REMOTE) ? answer_params[0] : selected_params; | 329 (source == CS_REMOTE) ? answer_params[0] : selected_params; |
127 if (!ApplySendParams(new_send_params) || !ApplyRecvParams(new_recv_params)) { | 330 if (!ApplyParams(send_params, recv_params)) { |
128 return false; | 331 return false; |
129 } | 332 } |
130 applied_send_params_ = new_send_params; | |
131 applied_recv_params_ = new_recv_params; | |
132 | 333 |
133 if (final) { | 334 if (final) { |
134 offer_params_.clear(); | 335 offer_params_.clear(); |
135 state_ = ST_ACTIVE; | 336 state_ = ST_ACTIVE; |
136 } else { | 337 } else { |
137 state_ = | 338 state_ = |
138 (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER; | 339 (source == CS_LOCAL) ? ST_SENTPRANSWER : ST_RECEIVEDPRANSWER; |
139 } | 340 } |
140 return true; | 341 return true; |
141 } | 342 } |
142 | 343 |
| 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 |
143 bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params, | 355 bool SrtpFilter::NegotiateParams(const std::vector<CryptoParams>& answer_params, |
144 CryptoParams* selected_params) { | 356 CryptoParams* selected_params) { |
145 // We're processing an accept. We should have exactly one set of params, | 357 // We're processing an accept. We should have exactly one set of params, |
146 // unless the offer didn't mention crypto, in which case we shouldn't be here. | 358 // unless the offer didn't mention crypto, in which case we shouldn't be here. |
147 bool ret = (answer_params.size() == 1U && !offer_params_.empty()); | 359 bool ret = (answer_params.size() == 1U && !offer_params_.empty()); |
148 if (ret) { | 360 if (ret) { |
149 // We should find a match between the answer params and the offered params. | 361 // We should find a match between the answer params and the offered params. |
150 std::vector<CryptoParams>::const_iterator it; | 362 std::vector<CryptoParams>::const_iterator it; |
151 for (it = offer_params_.begin(); it != offer_params_.end(); ++it) { | 363 for (it = offer_params_.begin(); it != offer_params_.end(); ++it) { |
152 if (answer_params[0].Matches(*it)) { | 364 if (answer_params[0].Matches(*it)) { |
153 break; | 365 break; |
154 } | 366 } |
155 } | 367 } |
156 | 368 |
157 if (it != offer_params_.end()) { | 369 if (it != offer_params_.end()) { |
158 *selected_params = *it; | 370 *selected_params = *it; |
159 } else { | 371 } else { |
160 ret = false; | 372 ret = false; |
161 } | 373 } |
162 } | 374 } |
163 | 375 |
164 if (!ret) { | 376 if (!ret) { |
165 LOG(LS_WARNING) << "Invalid parameters in SRTP answer"; | 377 LOG(LS_WARNING) << "Invalid parameters in SRTP answer"; |
166 } | 378 } |
167 return ret; | 379 return ret; |
168 } | 380 } |
169 | 381 |
| 382 bool SrtpFilter::ApplyParams(const CryptoParams& send_params, |
| 383 const CryptoParams& recv_params) { |
| 384 // TODO(jiayl): Split this method to apply send and receive CryptoParams |
| 385 // independently, so that we can skip one method when either send or receive |
| 386 // CryptoParams is unchanged. |
| 387 if (applied_send_params_.cipher_suite == send_params.cipher_suite && |
| 388 applied_send_params_.key_params == send_params.key_params && |
| 389 applied_recv_params_.cipher_suite == recv_params.cipher_suite && |
| 390 applied_recv_params_.key_params == recv_params.key_params) { |
| 391 LOG(LS_INFO) << "Applying the same SRTP parameters again. No-op."; |
| 392 |
| 393 // We do not want to reset the ROC if the keys are the same. So just return. |
| 394 return true; |
| 395 } |
| 396 |
| 397 int send_suite = rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite); |
| 398 int recv_suite = rtc::SrtpCryptoSuiteFromName(recv_params.cipher_suite); |
| 399 if (send_suite == rtc::SRTP_INVALID_CRYPTO_SUITE || |
| 400 recv_suite == rtc::SRTP_INVALID_CRYPTO_SUITE) { |
| 401 LOG(LS_WARNING) << "Unknown crypto suite(s) received:" |
| 402 << " send cipher_suite " << send_params.cipher_suite |
| 403 << " recv cipher_suite " << recv_params.cipher_suite; |
| 404 return false; |
| 405 } |
| 406 |
| 407 int send_key_len, send_salt_len; |
| 408 int recv_key_len, recv_salt_len; |
| 409 if (!rtc::GetSrtpKeyAndSaltLengths(send_suite, &send_key_len, |
| 410 &send_salt_len) || |
| 411 !rtc::GetSrtpKeyAndSaltLengths(recv_suite, &recv_key_len, |
| 412 &recv_salt_len)) { |
| 413 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; |
| 416 return false; |
| 417 } |
| 418 |
| 419 // TODO(juberti): Zero these buffers after use. |
| 420 bool ret; |
| 421 rtc::Buffer send_key(send_key_len + send_salt_len); |
| 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 |
170 bool SrtpFilter::ResetParams() { | 452 bool SrtpFilter::ResetParams() { |
171 offer_params_.clear(); | 453 offer_params_.clear(); |
172 applied_send_params_ = CryptoParams(); | |
173 applied_recv_params_ = CryptoParams(); | |
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; | 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"; |
179 return true; | 460 return true; |
180 } | 461 } |
181 | 462 |
182 bool SrtpFilter::ApplySendParams(const CryptoParams& send_params) { | |
183 if (applied_send_params_.cipher_suite == send_params.cipher_suite && | |
184 applied_send_params_.key_params == send_params.key_params) { | |
185 LOG(LS_INFO) << "Applying the same SRTP send parameters again. No-op."; | |
186 | |
187 // We do not want to reset the ROC if the keys are the same. So just return. | |
188 return true; | |
189 } | |
190 | |
191 send_cipher_suite_ = rtc::Optional<int>( | |
192 rtc::SrtpCryptoSuiteFromName(send_params.cipher_suite)); | |
193 if (send_cipher_suite_ == rtc::SRTP_INVALID_CRYPTO_SUITE) { | |
194 LOG(LS_WARNING) << "Unknown crypto suite(s) received:" | |
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:" | |
225 << " recv cipher_suite " << recv_params.cipher_suite; | |
226 return false; | |
227 } | |
228 | |
229 int recv_key_len, recv_salt_len; | |
230 if (!rtc::GetSrtpKeyAndSaltLengths(*recv_cipher_suite_, &recv_key_len, | |
231 &recv_salt_len)) { | |
232 LOG(LS_WARNING) << "Could not get lengths for crypto suite(s):" | |
233 << " recv cipher_suite " << recv_params.cipher_suite; | |
234 return false; | |
235 } | |
236 | |
237 recv_key_ = rtc::Buffer(recv_key_len + recv_salt_len); | |
238 return ParseKeyParams(recv_params.key_params, recv_key_.data(), | |
239 recv_key_.size()); | |
240 } | |
241 | |
242 bool SrtpFilter::ParseKeyParams(const std::string& key_params, | 463 bool SrtpFilter::ParseKeyParams(const std::string& key_params, |
243 uint8_t* key, | 464 uint8_t* key, |
244 size_t len) { | 465 size_t len) { |
245 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2" | 466 // example key_params: "inline:YUJDZGVmZ2hpSktMbW9QUXJzVHVWd3l6MTIzNDU2" |
246 | 467 |
247 // Fail if key-method is wrong. | 468 // Fail if key-method is wrong. |
248 if (key_params.find("inline:") != 0) { | 469 if (key_params.find("inline:") != 0) { |
249 return false; | 470 return false; |
250 } | 471 } |
251 | 472 |
252 // Fail if base64 decode fails, or the key is the wrong size. | 473 // Fail if base64 decode fails, or the key is the wrong size. |
253 std::string key_b64(key_params.substr(7)), key_str; | 474 std::string key_b64(key_params.substr(7)), key_str; |
254 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, &key_str, | 475 if (!rtc::Base64::Decode(key_b64, rtc::Base64::DO_STRICT, |
255 nullptr) || | 476 &key_str, nullptr) || key_str.size() != len) { |
256 key_str.size() != len) { | |
257 return false; | 477 return false; |
258 } | 478 } |
259 | 479 |
260 memcpy(key, key_str.c_str(), len); | 480 memcpy(key, key_str.c_str(), len); |
261 return true; | 481 return true; |
262 } | 482 } |
263 | 483 |
264 } // namespace cricket | 484 } // namespace cricket |
OLD | NEW |