OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. | |
3 * | |
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 | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/pc/dtlssrtptransport.h" | |
12 | |
13 #include <memory> | |
14 #include <string> | |
15 #include <utility> | |
16 | |
17 #include "webrtc/media/base/rtputils.h" | |
18 #include "webrtc/rtc_base/sslstreamadapter.h" | |
19 | |
20 namespace { | |
21 // Value specified in RFC 5764. | |
22 static const char kDtlsSrtpExporterLabel[] = "EXTRACTOR-dtls_srtp"; | |
23 } // namespace | |
24 | |
25 namespace webrtc { | |
26 | |
27 DtlsSrtpTransport::DtlsSrtpTransport( | |
28 std::unique_ptr<webrtc::SrtpTransport> transport, | |
29 const std::string& content_name) | |
30 : srtp_transport_(std::move(transport)), content_name_(content_name) { | |
31 ConnectToSrtpTransport(); | |
32 } | |
33 | |
34 void DtlsSrtpTransport::ConnectToSrtpTransport() { | |
35 RTC_DCHECK(srtp_transport_); | |
36 srtp_transport_->SignalPacketReceived.connect( | |
37 this, &DtlsSrtpTransport::OnPacketReceived); | |
38 srtp_transport_->SignalReadyToSend.connect(this, | |
39 &DtlsSrtpTransport::OnReadyToSend); | |
40 } | |
41 | |
42 void DtlsSrtpTransport::OnPacketReceived(bool rtcp, | |
43 rtc::CopyOnWriteBuffer* packet, | |
44 const rtc::PacketTime& packet_time) { | |
45 SignalPacketReceived(rtcp, packet, packet_time); | |
46 } | |
47 | |
48 void DtlsSrtpTransport::OnReadyToSend(bool ready) { | |
49 SignalReadyToSend(ready); | |
50 } | |
51 | |
52 bool DtlsSrtpTransport::SetupDtlsSrtp(bool rtcp) { | |
53 bool ret = false; | |
54 | |
55 cricket::DtlsTransportInternal* transport = | |
56 rtcp ? rtcp_dtls_transport_ : rtp_dtls_transport_; | |
57 RTC_DCHECK(transport); | |
58 RTC_DCHECK(transport->IsDtlsActive()); | |
59 | |
60 int selected_crypto_suite; | |
61 | |
62 if (!transport->GetSrtpCryptoSuite(&selected_crypto_suite)) { | |
63 LOG(LS_ERROR) << "No DTLS-SRTP selected crypto suite"; | |
64 return false; | |
65 } | |
66 | |
67 LOG(LS_INFO) << "Installing keys from DTLS-SRTP on " << content_name_ << " " | |
pthatcher
2017/09/12 00:24:44
I don't think it's worth passing in the content_na
Zhi Huang
2017/09/27 00:46:32
Ok. I'll remove it then.
| |
68 << cricket::RtpRtcpStringLiteral(rtcp); | |
69 | |
70 int key_len; | |
71 int salt_len; | |
72 if (!rtc::GetSrtpKeyAndSaltLengths(selected_crypto_suite, &key_len, | |
73 &salt_len)) { | |
74 LOG(LS_ERROR) << "Unknown DTLS-SRTP crypto suite" << selected_crypto_suite; | |
75 return false; | |
76 } | |
77 | |
78 // OK, we're now doing DTLS (RFC 5764) | |
79 std::vector<unsigned char> dtls_buffer(key_len * 2 + salt_len * 2); | |
80 | |
81 // RFC 5705 exporter using the RFC 5764 parameters | |
82 if (!transport->ExportKeyingMaterial(kDtlsSrtpExporterLabel, NULL, 0, false, | |
83 &dtls_buffer[0], dtls_buffer.size())) { | |
84 LOG(LS_WARNING) << "DTLS-SRTP key export failed"; | |
85 RTC_NOTREACHED(); // This should never happen | |
86 return false; | |
87 } | |
88 | |
89 // Sync up the keys with the DTLS-SRTP interface | |
90 std::vector<unsigned char> client_write_key(key_len + salt_len); | |
91 std::vector<unsigned char> server_write_key(key_len + salt_len); | |
92 size_t offset = 0; | |
93 memcpy(&client_write_key[0], &dtls_buffer[offset], key_len); | |
94 offset += key_len; | |
95 memcpy(&server_write_key[0], &dtls_buffer[offset], key_len); | |
96 offset += key_len; | |
97 memcpy(&client_write_key[key_len], &dtls_buffer[offset], salt_len); | |
98 offset += salt_len; | |
99 memcpy(&server_write_key[key_len], &dtls_buffer[offset], salt_len); | |
100 | |
101 std::vector<unsigned char>*send_key, *recv_key; | |
102 rtc::SSLRole role; | |
103 if (!transport->GetSslRole(&role)) { | |
104 LOG(LS_WARNING) << "GetSslRole failed"; | |
105 return false; | |
106 } | |
107 | |
108 if (role == rtc::SSL_SERVER) { | |
109 send_key = &server_write_key; | |
110 recv_key = &client_write_key; | |
111 } else { | |
112 send_key = &client_write_key; | |
113 recv_key = &server_write_key; | |
114 } | |
115 | |
116 if (rtcp) { | |
117 if (!IsActive()) { | |
118 RTC_DCHECK(srtp_transport_); | |
119 ret = srtp_transport_->SetRtcpParams( | |
120 selected_crypto_suite, &(*send_key)[0], | |
121 static_cast<int>(send_key->size()), selected_crypto_suite, | |
122 &(*recv_key)[0], static_cast<int>(recv_key->size())); | |
123 } else { | |
124 // RTCP doesn't need to call SetRtpParam because it is only used | |
125 // to make the updated encrypted RTP header extension IDs take effect. | |
126 ret = true; | |
127 } | |
128 } else { | |
129 RTC_DCHECK(srtp_transport_); | |
130 ret = srtp_transport_->SetRtpParams(selected_crypto_suite, &(*send_key)[0], | |
131 static_cast<int>(send_key->size()), | |
132 selected_crypto_suite, &(*recv_key)[0], | |
133 static_cast<int>(recv_key->size())); | |
134 } | |
135 | |
136 if (!ret) { | |
137 LOG(LS_WARNING) << "DTLS-SRTP key installation failed"; | |
138 } | |
139 active_ = ret; | |
140 return ret; | |
141 } | |
142 | |
143 void DtlsSrtpTransport::SetDtlsTransport( | |
144 bool rtcp, | |
145 cricket::DtlsTransportInternal* dtls_transport) { | |
146 rtcp ? rtcp_dtls_transport_ = dtls_transport | |
147 : rtp_dtls_transport_ = dtls_transport; | |
148 } | |
149 | |
150 void DtlsSrtpTransport::SetEncryptedHeaderExtensionIds( | |
151 cricket::ContentSource source, | |
152 const std::vector<int>& extension_ids) { | |
153 RTC_DCHECK(srtp_transport_); | |
154 srtp_transport_->SetEncryptedHeaderExtensionIds(source, extension_ids); | |
155 } | |
156 | |
157 void DtlsSrtpTransport::SetRtcpMuxEnabled(bool enable) { | |
158 RTC_DCHECK(srtp_transport_); | |
159 srtp_transport_->SetRtcpMuxEnabled(enable); | |
160 } | |
161 | |
162 rtc::PacketTransportInternal* DtlsSrtpTransport::rtp_packet_transport() const { | |
163 RTC_DCHECK(srtp_transport_); | |
164 return srtp_transport_->rtp_packet_transport(); | |
165 } | |
166 | |
167 void DtlsSrtpTransport::SetRtpPacketTransport( | |
168 rtc::PacketTransportInternal* rtp) { | |
169 RTC_DCHECK(srtp_transport_); | |
170 srtp_transport_->SetRtpPacketTransport(rtp); | |
171 } | |
172 | |
173 PacketTransportInterface* DtlsSrtpTransport::GetRtpPacketTransport() const { | |
174 RTC_DCHECK(srtp_transport_); | |
175 return srtp_transport_->GetRtpPacketTransport(); | |
176 } | |
177 | |
178 rtc::PacketTransportInternal* DtlsSrtpTransport::rtcp_packet_transport() const { | |
179 RTC_DCHECK(srtp_transport_); | |
180 return srtp_transport_->rtcp_packet_transport(); | |
181 } | |
182 | |
183 void DtlsSrtpTransport::SetRtcpPacketTransport( | |
184 rtc::PacketTransportInternal* rtcp) { | |
185 RTC_DCHECK(srtp_transport_); | |
186 srtp_transport_->SetRtcpPacketTransport(rtcp); | |
187 } | |
188 | |
189 PacketTransportInterface* DtlsSrtpTransport::GetRtcpPacketTransport() const { | |
190 RTC_DCHECK(srtp_transport_); | |
191 return srtp_transport_->GetRtcpPacketTransport(); | |
192 } | |
193 | |
194 bool DtlsSrtpTransport::IsWritable(bool rtcp) const { | |
195 RTC_DCHECK(srtp_transport_); | |
196 return srtp_transport_->IsWritable(rtcp); | |
197 } | |
198 | |
199 bool DtlsSrtpTransport::SendRtpPacket(rtc::CopyOnWriteBuffer* packet, | |
200 const rtc::PacketOptions& options, | |
201 int flags) { | |
202 RTC_DCHECK(srtp_transport_); | |
203 return srtp_transport_->SendRtpPacket(packet, options, flags); | |
204 } | |
205 | |
206 bool DtlsSrtpTransport::SendRtcpPacket(rtc::CopyOnWriteBuffer* packet, | |
207 const rtc::PacketOptions& options, | |
208 int flags) { | |
209 RTC_DCHECK(srtp_transport_); | |
210 return srtp_transport_->SendRtcpPacket(packet, options, flags); | |
211 } | |
212 | |
213 bool DtlsSrtpTransport::HandlesPayloadType(int payload_type) const { | |
214 RTC_DCHECK(srtp_transport_); | |
215 return srtp_transport_->HandlesPayloadType(payload_type); | |
216 } | |
217 | |
218 void DtlsSrtpTransport::AddHandledPayloadType(int payload_type) { | |
219 RTC_DCHECK(srtp_transport_); | |
220 srtp_transport_->AddHandledPayloadType(payload_type); | |
221 } | |
222 | |
223 void DtlsSrtpTransport::ResetParams() { | |
224 active_ = false; | |
225 if (srtp_transport_) { | |
226 srtp_transport_->ResetParams(); | |
227 } | |
228 } | |
229 | |
230 RTCError DtlsSrtpTransport::SetParameters( | |
231 const RtpTransportParameters& parameters) { | |
232 RTC_DCHECK(srtp_transport_); | |
233 return srtp_transport_->SetParameters(parameters); | |
234 } | |
235 | |
236 RtpTransportParameters DtlsSrtpTransport::GetParameters() const { | |
237 RTC_DCHECK(srtp_transport_); | |
238 return srtp_transport_->GetParameters(); | |
239 } | |
240 | |
241 } // namespace webrtc | |
OLD | NEW |