xref: /aosp_15_r20/external/webrtc/pc/dtls_srtp_transport.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2017 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "pc/dtls_srtp_transport.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <string.h>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include <string>
16*d9f75844SAndroid Build Coastguard Worker #include <utility>
17*d9f75844SAndroid Build Coastguard Worker 
18*d9f75844SAndroid Build Coastguard Worker #include "api/dtls_transport_interface.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_stream_adapter.h"
22*d9f75844SAndroid Build Coastguard Worker 
23*d9f75844SAndroid Build Coastguard Worker namespace {
24*d9f75844SAndroid Build Coastguard Worker // Value specified in RFC 5764.
25*d9f75844SAndroid Build Coastguard Worker static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp";
26*d9f75844SAndroid Build Coastguard Worker }  // namespace
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
29*d9f75844SAndroid Build Coastguard Worker 
DtlsSrtpTransport(bool rtcp_mux_enabled,const FieldTrialsView & field_trials)30*d9f75844SAndroid Build Coastguard Worker DtlsSrtpTransport::DtlsSrtpTransport(bool rtcp_mux_enabled,
31*d9f75844SAndroid Build Coastguard Worker                                      const FieldTrialsView& field_trials)
32*d9f75844SAndroid Build Coastguard Worker     : SrtpTransport(rtcp_mux_enabled, field_trials) {}
33*d9f75844SAndroid Build Coastguard Worker 
SetDtlsTransports(cricket::DtlsTransportInternal * rtp_dtls_transport,cricket::DtlsTransportInternal * rtcp_dtls_transport)34*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::SetDtlsTransports(
35*d9f75844SAndroid Build Coastguard Worker     cricket::DtlsTransportInternal* rtp_dtls_transport,
36*d9f75844SAndroid Build Coastguard Worker     cricket::DtlsTransportInternal* rtcp_dtls_transport) {
37*d9f75844SAndroid Build Coastguard Worker   // Transport names should be the same.
38*d9f75844SAndroid Build Coastguard Worker   if (rtp_dtls_transport && rtcp_dtls_transport) {
39*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(rtp_dtls_transport->transport_name() ==
40*d9f75844SAndroid Build Coastguard Worker                rtcp_dtls_transport->transport_name());
41*d9f75844SAndroid Build Coastguard Worker   }
42*d9f75844SAndroid Build Coastguard Worker 
43*d9f75844SAndroid Build Coastguard Worker   // When using DTLS-SRTP, we must reset the SrtpTransport every time the
44*d9f75844SAndroid Build Coastguard Worker   // DtlsTransport changes and wait until the DTLS handshake is complete to set
45*d9f75844SAndroid Build Coastguard Worker   // the newly negotiated parameters.
46*d9f75844SAndroid Build Coastguard Worker   // If `active_reset_srtp_params_` is true, intentionally reset the SRTP
47*d9f75844SAndroid Build Coastguard Worker   // parameter even though the DtlsTransport may not change.
48*d9f75844SAndroid Build Coastguard Worker   if (IsSrtpActive() && (rtp_dtls_transport != rtp_dtls_transport_ ||
49*d9f75844SAndroid Build Coastguard Worker                          active_reset_srtp_params_)) {
50*d9f75844SAndroid Build Coastguard Worker     ResetParams();
51*d9f75844SAndroid Build Coastguard Worker   }
52*d9f75844SAndroid Build Coastguard Worker 
53*d9f75844SAndroid Build Coastguard Worker   const std::string transport_name =
54*d9f75844SAndroid Build Coastguard Worker       rtp_dtls_transport ? rtp_dtls_transport->transport_name() : "null";
55*d9f75844SAndroid Build Coastguard Worker 
56*d9f75844SAndroid Build Coastguard Worker   if (rtcp_dtls_transport && rtcp_dtls_transport != rtcp_dtls_transport_) {
57*d9f75844SAndroid Build Coastguard Worker     // This would only be possible if using BUNDLE but not rtcp-mux, which isn't
58*d9f75844SAndroid Build Coastguard Worker     // allowed according to the BUNDLE spec.
59*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK(!(IsSrtpActive()))
60*d9f75844SAndroid Build Coastguard Worker         << "Setting RTCP for DTLS/SRTP after the DTLS is active "
61*d9f75844SAndroid Build Coastguard Worker            "should never happen.";
62*d9f75844SAndroid Build Coastguard Worker   }
63*d9f75844SAndroid Build Coastguard Worker 
64*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Setting RTCP Transport on " << transport_name
65*d9f75844SAndroid Build Coastguard Worker                    << " transport " << rtcp_dtls_transport;
66*d9f75844SAndroid Build Coastguard Worker   SetRtcpDtlsTransport(rtcp_dtls_transport);
67*d9f75844SAndroid Build Coastguard Worker   SetRtcpPacketTransport(rtcp_dtls_transport);
68*d9f75844SAndroid Build Coastguard Worker 
69*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Setting RTP Transport on " << transport_name
70*d9f75844SAndroid Build Coastguard Worker                    << " transport " << rtp_dtls_transport;
71*d9f75844SAndroid Build Coastguard Worker   SetRtpDtlsTransport(rtp_dtls_transport);
72*d9f75844SAndroid Build Coastguard Worker   SetRtpPacketTransport(rtp_dtls_transport);
73*d9f75844SAndroid Build Coastguard Worker 
74*d9f75844SAndroid Build Coastguard Worker   MaybeSetupDtlsSrtp();
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker 
SetRtcpMuxEnabled(bool enable)77*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::SetRtcpMuxEnabled(bool enable) {
78*d9f75844SAndroid Build Coastguard Worker   SrtpTransport::SetRtcpMuxEnabled(enable);
79*d9f75844SAndroid Build Coastguard Worker   if (enable) {
80*d9f75844SAndroid Build Coastguard Worker     MaybeSetupDtlsSrtp();
81*d9f75844SAndroid Build Coastguard Worker   }
82*d9f75844SAndroid Build Coastguard Worker }
83*d9f75844SAndroid Build Coastguard Worker 
UpdateSendEncryptedHeaderExtensionIds(const std::vector<int> & send_extension_ids)84*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::UpdateSendEncryptedHeaderExtensionIds(
85*d9f75844SAndroid Build Coastguard Worker     const std::vector<int>& send_extension_ids) {
86*d9f75844SAndroid Build Coastguard Worker   if (send_extension_ids_ == send_extension_ids) {
87*d9f75844SAndroid Build Coastguard Worker     return;
88*d9f75844SAndroid Build Coastguard Worker   }
89*d9f75844SAndroid Build Coastguard Worker   send_extension_ids_.emplace(send_extension_ids);
90*d9f75844SAndroid Build Coastguard Worker   if (DtlsHandshakeCompleted()) {
91*d9f75844SAndroid Build Coastguard Worker     // Reset the crypto parameters to update the send extension IDs.
92*d9f75844SAndroid Build Coastguard Worker     SetupRtpDtlsSrtp();
93*d9f75844SAndroid Build Coastguard Worker   }
94*d9f75844SAndroid Build Coastguard Worker }
95*d9f75844SAndroid Build Coastguard Worker 
UpdateRecvEncryptedHeaderExtensionIds(const std::vector<int> & recv_extension_ids)96*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::UpdateRecvEncryptedHeaderExtensionIds(
97*d9f75844SAndroid Build Coastguard Worker     const std::vector<int>& recv_extension_ids) {
98*d9f75844SAndroid Build Coastguard Worker   if (recv_extension_ids_ == recv_extension_ids) {
99*d9f75844SAndroid Build Coastguard Worker     return;
100*d9f75844SAndroid Build Coastguard Worker   }
101*d9f75844SAndroid Build Coastguard Worker   recv_extension_ids_.emplace(recv_extension_ids);
102*d9f75844SAndroid Build Coastguard Worker   if (DtlsHandshakeCompleted()) {
103*d9f75844SAndroid Build Coastguard Worker     // Reset the crypto parameters to update the receive extension IDs.
104*d9f75844SAndroid Build Coastguard Worker     SetupRtpDtlsSrtp();
105*d9f75844SAndroid Build Coastguard Worker   }
106*d9f75844SAndroid Build Coastguard Worker }
107*d9f75844SAndroid Build Coastguard Worker 
IsDtlsActive()108*d9f75844SAndroid Build Coastguard Worker bool DtlsSrtpTransport::IsDtlsActive() {
109*d9f75844SAndroid Build Coastguard Worker   auto rtcp_dtls_transport =
110*d9f75844SAndroid Build Coastguard Worker       rtcp_mux_enabled() ? nullptr : rtcp_dtls_transport_;
111*d9f75844SAndroid Build Coastguard Worker   return (rtp_dtls_transport_ && rtp_dtls_transport_->IsDtlsActive() &&
112*d9f75844SAndroid Build Coastguard Worker           (!rtcp_dtls_transport || rtcp_dtls_transport->IsDtlsActive()));
113*d9f75844SAndroid Build Coastguard Worker }
114*d9f75844SAndroid Build Coastguard Worker 
IsDtlsConnected()115*d9f75844SAndroid Build Coastguard Worker bool DtlsSrtpTransport::IsDtlsConnected() {
116*d9f75844SAndroid Build Coastguard Worker   auto rtcp_dtls_transport =
117*d9f75844SAndroid Build Coastguard Worker       rtcp_mux_enabled() ? nullptr : rtcp_dtls_transport_;
118*d9f75844SAndroid Build Coastguard Worker   return (rtp_dtls_transport_ &&
119*d9f75844SAndroid Build Coastguard Worker           rtp_dtls_transport_->dtls_state() == DtlsTransportState::kConnected &&
120*d9f75844SAndroid Build Coastguard Worker           (!rtcp_dtls_transport || rtcp_dtls_transport->dtls_state() ==
121*d9f75844SAndroid Build Coastguard Worker                                        DtlsTransportState::kConnected));
122*d9f75844SAndroid Build Coastguard Worker }
123*d9f75844SAndroid Build Coastguard Worker 
IsDtlsWritable()124*d9f75844SAndroid Build Coastguard Worker bool DtlsSrtpTransport::IsDtlsWritable() {
125*d9f75844SAndroid Build Coastguard Worker   auto rtcp_packet_transport =
126*d9f75844SAndroid Build Coastguard Worker       rtcp_mux_enabled() ? nullptr : rtcp_dtls_transport_;
127*d9f75844SAndroid Build Coastguard Worker   return rtp_dtls_transport_ && rtp_dtls_transport_->writable() &&
128*d9f75844SAndroid Build Coastguard Worker          (!rtcp_packet_transport || rtcp_packet_transport->writable());
129*d9f75844SAndroid Build Coastguard Worker }
130*d9f75844SAndroid Build Coastguard Worker 
DtlsHandshakeCompleted()131*d9f75844SAndroid Build Coastguard Worker bool DtlsSrtpTransport::DtlsHandshakeCompleted() {
132*d9f75844SAndroid Build Coastguard Worker   return IsDtlsActive() && IsDtlsConnected();
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker 
MaybeSetupDtlsSrtp()135*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::MaybeSetupDtlsSrtp() {
136*d9f75844SAndroid Build Coastguard Worker   if (IsSrtpActive() || !IsDtlsWritable()) {
137*d9f75844SAndroid Build Coastguard Worker     return;
138*d9f75844SAndroid Build Coastguard Worker   }
139*d9f75844SAndroid Build Coastguard Worker 
140*d9f75844SAndroid Build Coastguard Worker   SetupRtpDtlsSrtp();
141*d9f75844SAndroid Build Coastguard Worker 
142*d9f75844SAndroid Build Coastguard Worker   if (!rtcp_mux_enabled() && rtcp_dtls_transport_) {
143*d9f75844SAndroid Build Coastguard Worker     SetupRtcpDtlsSrtp();
144*d9f75844SAndroid Build Coastguard Worker   }
145*d9f75844SAndroid Build Coastguard Worker }
146*d9f75844SAndroid Build Coastguard Worker 
SetupRtpDtlsSrtp()147*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::SetupRtpDtlsSrtp() {
148*d9f75844SAndroid Build Coastguard Worker   // Use an empty encrypted header extension ID vector if not set. This could
149*d9f75844SAndroid Build Coastguard Worker   // happen when the DTLS handshake is completed before processing the
150*d9f75844SAndroid Build Coastguard Worker   // Offer/Answer which contains the encrypted header extension IDs.
151*d9f75844SAndroid Build Coastguard Worker   std::vector<int> send_extension_ids;
152*d9f75844SAndroid Build Coastguard Worker   std::vector<int> recv_extension_ids;
153*d9f75844SAndroid Build Coastguard Worker   if (send_extension_ids_) {
154*d9f75844SAndroid Build Coastguard Worker     send_extension_ids = *send_extension_ids_;
155*d9f75844SAndroid Build Coastguard Worker   }
156*d9f75844SAndroid Build Coastguard Worker   if (recv_extension_ids_) {
157*d9f75844SAndroid Build Coastguard Worker     recv_extension_ids = *recv_extension_ids_;
158*d9f75844SAndroid Build Coastguard Worker   }
159*d9f75844SAndroid Build Coastguard Worker 
160*d9f75844SAndroid Build Coastguard Worker   int selected_crypto_suite;
161*d9f75844SAndroid Build Coastguard Worker   rtc::ZeroOnFreeBuffer<unsigned char> send_key;
162*d9f75844SAndroid Build Coastguard Worker   rtc::ZeroOnFreeBuffer<unsigned char> recv_key;
163*d9f75844SAndroid Build Coastguard Worker 
164*d9f75844SAndroid Build Coastguard Worker   if (!ExtractParams(rtp_dtls_transport_, &selected_crypto_suite, &send_key,
165*d9f75844SAndroid Build Coastguard Worker                      &recv_key) ||
166*d9f75844SAndroid Build Coastguard Worker       !SetRtpParams(selected_crypto_suite, &send_key[0],
167*d9f75844SAndroid Build Coastguard Worker                     static_cast<int>(send_key.size()), send_extension_ids,
168*d9f75844SAndroid Build Coastguard Worker                     selected_crypto_suite, &recv_key[0],
169*d9f75844SAndroid Build Coastguard Worker                     static_cast<int>(recv_key.size()), recv_extension_ids)) {
170*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "DTLS-SRTP key installation for RTP failed";
171*d9f75844SAndroid Build Coastguard Worker   }
172*d9f75844SAndroid Build Coastguard Worker }
173*d9f75844SAndroid Build Coastguard Worker 
SetupRtcpDtlsSrtp()174*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::SetupRtcpDtlsSrtp() {
175*d9f75844SAndroid Build Coastguard Worker   // Return if the DTLS-SRTP is active because the encrypted header extension
176*d9f75844SAndroid Build Coastguard Worker   // IDs don't need to be updated for RTCP and the crypto params don't need to
177*d9f75844SAndroid Build Coastguard Worker   // be reset.
178*d9f75844SAndroid Build Coastguard Worker   if (IsSrtpActive()) {
179*d9f75844SAndroid Build Coastguard Worker     return;
180*d9f75844SAndroid Build Coastguard Worker   }
181*d9f75844SAndroid Build Coastguard Worker 
182*d9f75844SAndroid Build Coastguard Worker   std::vector<int> send_extension_ids;
183*d9f75844SAndroid Build Coastguard Worker   std::vector<int> recv_extension_ids;
184*d9f75844SAndroid Build Coastguard Worker   if (send_extension_ids_) {
185*d9f75844SAndroid Build Coastguard Worker     send_extension_ids = *send_extension_ids_;
186*d9f75844SAndroid Build Coastguard Worker   }
187*d9f75844SAndroid Build Coastguard Worker   if (recv_extension_ids_) {
188*d9f75844SAndroid Build Coastguard Worker     recv_extension_ids = *recv_extension_ids_;
189*d9f75844SAndroid Build Coastguard Worker   }
190*d9f75844SAndroid Build Coastguard Worker 
191*d9f75844SAndroid Build Coastguard Worker   int selected_crypto_suite;
192*d9f75844SAndroid Build Coastguard Worker   rtc::ZeroOnFreeBuffer<unsigned char> rtcp_send_key;
193*d9f75844SAndroid Build Coastguard Worker   rtc::ZeroOnFreeBuffer<unsigned char> rtcp_recv_key;
194*d9f75844SAndroid Build Coastguard Worker   if (!ExtractParams(rtcp_dtls_transport_, &selected_crypto_suite,
195*d9f75844SAndroid Build Coastguard Worker                      &rtcp_send_key, &rtcp_recv_key) ||
196*d9f75844SAndroid Build Coastguard Worker       !SetRtcpParams(selected_crypto_suite, &rtcp_send_key[0],
197*d9f75844SAndroid Build Coastguard Worker                      static_cast<int>(rtcp_send_key.size()), send_extension_ids,
198*d9f75844SAndroid Build Coastguard Worker                      selected_crypto_suite, &rtcp_recv_key[0],
199*d9f75844SAndroid Build Coastguard Worker                      static_cast<int>(rtcp_recv_key.size()),
200*d9f75844SAndroid Build Coastguard Worker                      recv_extension_ids)) {
201*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "DTLS-SRTP key installation for RTCP failed";
202*d9f75844SAndroid Build Coastguard Worker   }
203*d9f75844SAndroid Build Coastguard Worker }
204*d9f75844SAndroid Build Coastguard Worker 
ExtractParams(cricket::DtlsTransportInternal * dtls_transport,int * selected_crypto_suite,rtc::ZeroOnFreeBuffer<unsigned char> * send_key,rtc::ZeroOnFreeBuffer<unsigned char> * recv_key)205*d9f75844SAndroid Build Coastguard Worker bool DtlsSrtpTransport::ExtractParams(
206*d9f75844SAndroid Build Coastguard Worker     cricket::DtlsTransportInternal* dtls_transport,
207*d9f75844SAndroid Build Coastguard Worker     int* selected_crypto_suite,
208*d9f75844SAndroid Build Coastguard Worker     rtc::ZeroOnFreeBuffer<unsigned char>* send_key,
209*d9f75844SAndroid Build Coastguard Worker     rtc::ZeroOnFreeBuffer<unsigned char>* recv_key) {
210*d9f75844SAndroid Build Coastguard Worker   if (!dtls_transport || !dtls_transport->IsDtlsActive()) {
211*d9f75844SAndroid Build Coastguard Worker     return false;
212*d9f75844SAndroid Build Coastguard Worker   }
213*d9f75844SAndroid Build Coastguard Worker 
214*d9f75844SAndroid Build Coastguard Worker   if (!dtls_transport->GetSrtpCryptoSuite(selected_crypto_suite)) {
215*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite";
216*d9f75844SAndroid Build Coastguard Worker     return false;
217*d9f75844SAndroid Build Coastguard Worker   }
218*d9f75844SAndroid Build Coastguard Worker 
219*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Extracting keys from transport: "
220*d9f75844SAndroid Build Coastguard Worker                    << dtls_transport->transport_name();
221*d9f75844SAndroid Build Coastguard Worker 
222*d9f75844SAndroid Build Coastguard Worker   int key_len;
223*d9f75844SAndroid Build Coastguard Worker   int salt_len;
224*d9f75844SAndroid Build Coastguard Worker   if (!rtc::GetSrtpKeyAndSaltLengths((*selected_crypto_suite), &key_len,
225*d9f75844SAndroid Build Coastguard Worker                                      &salt_len)) {
226*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << "Unknown DTLS-SRTP crypto suite"
227*d9f75844SAndroid Build Coastguard Worker                       << selected_crypto_suite;
228*d9f75844SAndroid Build Coastguard Worker     return false;
229*d9f75844SAndroid Build Coastguard Worker   }
230*d9f75844SAndroid Build Coastguard Worker 
231*d9f75844SAndroid Build Coastguard Worker   // OK, we're now doing DTLS (RFC 5764)
232*d9f75844SAndroid Build Coastguard Worker   rtc::ZeroOnFreeBuffer<unsigned char> dtls_buffer(key_len * 2 + salt_len * 2);
233*d9f75844SAndroid Build Coastguard Worker 
234*d9f75844SAndroid Build Coastguard Worker   // RFC 5705 exporter using the RFC 5764 parameters
235*d9f75844SAndroid Build Coastguard Worker   if (!dtls_transport->ExportKeyingMaterial(kDtlsSrtpExporterLabel, NULL, 0,
236*d9f75844SAndroid Build Coastguard Worker                                             false, &dtls_buffer[0],
237*d9f75844SAndroid Build Coastguard Worker                                             dtls_buffer.size())) {
238*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "DTLS-SRTP key export failed";
239*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_NOTREACHED();  // This should never happen
240*d9f75844SAndroid Build Coastguard Worker     return false;
241*d9f75844SAndroid Build Coastguard Worker   }
242*d9f75844SAndroid Build Coastguard Worker 
243*d9f75844SAndroid Build Coastguard Worker   // Sync up the keys with the DTLS-SRTP interface
244*d9f75844SAndroid Build Coastguard Worker   rtc::ZeroOnFreeBuffer<unsigned char> client_write_key(key_len + salt_len);
245*d9f75844SAndroid Build Coastguard Worker   rtc::ZeroOnFreeBuffer<unsigned char> server_write_key(key_len + salt_len);
246*d9f75844SAndroid Build Coastguard Worker   size_t offset = 0;
247*d9f75844SAndroid Build Coastguard Worker   memcpy(&client_write_key[0], &dtls_buffer[offset], key_len);
248*d9f75844SAndroid Build Coastguard Worker   offset += key_len;
249*d9f75844SAndroid Build Coastguard Worker   memcpy(&server_write_key[0], &dtls_buffer[offset], key_len);
250*d9f75844SAndroid Build Coastguard Worker   offset += key_len;
251*d9f75844SAndroid Build Coastguard Worker   memcpy(&client_write_key[key_len], &dtls_buffer[offset], salt_len);
252*d9f75844SAndroid Build Coastguard Worker   offset += salt_len;
253*d9f75844SAndroid Build Coastguard Worker   memcpy(&server_write_key[key_len], &dtls_buffer[offset], salt_len);
254*d9f75844SAndroid Build Coastguard Worker 
255*d9f75844SAndroid Build Coastguard Worker   rtc::SSLRole role;
256*d9f75844SAndroid Build Coastguard Worker   if (!dtls_transport->GetDtlsRole(&role)) {
257*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Failed to get the DTLS role.";
258*d9f75844SAndroid Build Coastguard Worker     return false;
259*d9f75844SAndroid Build Coastguard Worker   }
260*d9f75844SAndroid Build Coastguard Worker 
261*d9f75844SAndroid Build Coastguard Worker   if (role == rtc::SSL_SERVER) {
262*d9f75844SAndroid Build Coastguard Worker     *send_key = std::move(server_write_key);
263*d9f75844SAndroid Build Coastguard Worker     *recv_key = std::move(client_write_key);
264*d9f75844SAndroid Build Coastguard Worker   } else {
265*d9f75844SAndroid Build Coastguard Worker     *send_key = std::move(client_write_key);
266*d9f75844SAndroid Build Coastguard Worker     *recv_key = std::move(server_write_key);
267*d9f75844SAndroid Build Coastguard Worker   }
268*d9f75844SAndroid Build Coastguard Worker   return true;
269*d9f75844SAndroid Build Coastguard Worker }
270*d9f75844SAndroid Build Coastguard Worker 
SetDtlsTransport(cricket::DtlsTransportInternal * new_dtls_transport,cricket::DtlsTransportInternal ** old_dtls_transport)271*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::SetDtlsTransport(
272*d9f75844SAndroid Build Coastguard Worker     cricket::DtlsTransportInternal* new_dtls_transport,
273*d9f75844SAndroid Build Coastguard Worker     cricket::DtlsTransportInternal** old_dtls_transport) {
274*d9f75844SAndroid Build Coastguard Worker   if (*old_dtls_transport == new_dtls_transport) {
275*d9f75844SAndroid Build Coastguard Worker     return;
276*d9f75844SAndroid Build Coastguard Worker   }
277*d9f75844SAndroid Build Coastguard Worker 
278*d9f75844SAndroid Build Coastguard Worker   if (*old_dtls_transport) {
279*d9f75844SAndroid Build Coastguard Worker     (*old_dtls_transport)->UnsubscribeDtlsTransportState(this);
280*d9f75844SAndroid Build Coastguard Worker   }
281*d9f75844SAndroid Build Coastguard Worker 
282*d9f75844SAndroid Build Coastguard Worker   *old_dtls_transport = new_dtls_transport;
283*d9f75844SAndroid Build Coastguard Worker 
284*d9f75844SAndroid Build Coastguard Worker   if (new_dtls_transport) {
285*d9f75844SAndroid Build Coastguard Worker     new_dtls_transport->SubscribeDtlsTransportState(
286*d9f75844SAndroid Build Coastguard Worker         this,
287*d9f75844SAndroid Build Coastguard Worker         [this](cricket::DtlsTransportInternal* transport,
288*d9f75844SAndroid Build Coastguard Worker                DtlsTransportState state) { OnDtlsState(transport, state); });
289*d9f75844SAndroid Build Coastguard Worker   }
290*d9f75844SAndroid Build Coastguard Worker }
291*d9f75844SAndroid Build Coastguard Worker 
SetRtpDtlsTransport(cricket::DtlsTransportInternal * rtp_dtls_transport)292*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::SetRtpDtlsTransport(
293*d9f75844SAndroid Build Coastguard Worker     cricket::DtlsTransportInternal* rtp_dtls_transport) {
294*d9f75844SAndroid Build Coastguard Worker   SetDtlsTransport(rtp_dtls_transport, &rtp_dtls_transport_);
295*d9f75844SAndroid Build Coastguard Worker }
296*d9f75844SAndroid Build Coastguard Worker 
SetRtcpDtlsTransport(cricket::DtlsTransportInternal * rtcp_dtls_transport)297*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::SetRtcpDtlsTransport(
298*d9f75844SAndroid Build Coastguard Worker     cricket::DtlsTransportInternal* rtcp_dtls_transport) {
299*d9f75844SAndroid Build Coastguard Worker   SetDtlsTransport(rtcp_dtls_transport, &rtcp_dtls_transport_);
300*d9f75844SAndroid Build Coastguard Worker }
301*d9f75844SAndroid Build Coastguard Worker 
OnDtlsState(cricket::DtlsTransportInternal * transport,DtlsTransportState state)302*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::OnDtlsState(cricket::DtlsTransportInternal* transport,
303*d9f75844SAndroid Build Coastguard Worker                                     DtlsTransportState state) {
304*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(transport == rtp_dtls_transport_ ||
305*d9f75844SAndroid Build Coastguard Worker              transport == rtcp_dtls_transport_);
306*d9f75844SAndroid Build Coastguard Worker 
307*d9f75844SAndroid Build Coastguard Worker   if (on_dtls_state_change_) {
308*d9f75844SAndroid Build Coastguard Worker     on_dtls_state_change_();
309*d9f75844SAndroid Build Coastguard Worker   }
310*d9f75844SAndroid Build Coastguard Worker 
311*d9f75844SAndroid Build Coastguard Worker   if (state != DtlsTransportState::kConnected) {
312*d9f75844SAndroid Build Coastguard Worker     ResetParams();
313*d9f75844SAndroid Build Coastguard Worker     return;
314*d9f75844SAndroid Build Coastguard Worker   }
315*d9f75844SAndroid Build Coastguard Worker 
316*d9f75844SAndroid Build Coastguard Worker   MaybeSetupDtlsSrtp();
317*d9f75844SAndroid Build Coastguard Worker }
318*d9f75844SAndroid Build Coastguard Worker 
OnWritableState(rtc::PacketTransportInternal * packet_transport)319*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::OnWritableState(
320*d9f75844SAndroid Build Coastguard Worker     rtc::PacketTransportInternal* packet_transport) {
321*d9f75844SAndroid Build Coastguard Worker   MaybeSetupDtlsSrtp();
322*d9f75844SAndroid Build Coastguard Worker }
323*d9f75844SAndroid Build Coastguard Worker 
SetOnDtlsStateChange(std::function<void (void)> callback)324*d9f75844SAndroid Build Coastguard Worker void DtlsSrtpTransport::SetOnDtlsStateChange(
325*d9f75844SAndroid Build Coastguard Worker     std::function<void(void)> callback) {
326*d9f75844SAndroid Build Coastguard Worker   on_dtls_state_change_ = std::move(callback);
327*d9f75844SAndroid Build Coastguard Worker }
328*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
329