Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: webrtc/pc/srtptransport_unittest.cc

Issue 2997983002: Completed the functionalities of SrtpTransport. (Closed)
Patch Set: Added unit tests for SrtpTransport. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« webrtc/pc/srtptransport.h ('K') | « webrtc/pc/srtptransport.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2017 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/srtptransport.h" 11 #include "webrtc/pc/srtptransport.h"
12 12
13 #include "webrtc/media/base/fakertp.h"
14 #include "webrtc/p2p/base/dtlstransportinternal.h"
15 #include "webrtc/p2p/base/fakepackettransport.h"
13 #include "webrtc/pc/rtptransport.h" 16 #include "webrtc/pc/rtptransport.h"
14 #include "webrtc/pc/rtptransporttestutil.h" 17 #include "webrtc/pc/rtptransporttestutil.h"
18 #include "webrtc/pc/srtptestutil.h"
15 #include "webrtc/rtc_base/asyncpacketsocket.h" 19 #include "webrtc/rtc_base/asyncpacketsocket.h"
16 #include "webrtc/rtc_base/gunit.h" 20 #include "webrtc/rtc_base/gunit.h"
17 #include "webrtc/rtc_base/ptr_util.h" 21 #include "webrtc/rtc_base/ptr_util.h"
18 #include "webrtc/test/gmock.h" 22 #include "webrtc/rtc_base/sslstreamadapter.h"
23
24 using rtc::kTestKey1;
25 using rtc::kTestKey2;
26 using rtc::kTestKeyLen;
27 using rtc::SRTP_AEAD_AES_128_GCM;
19 28
20 namespace webrtc { 29 namespace webrtc {
21 30 static const uint8_t kTestKeyGcm128_1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ12";
22 using testing::_; 31 static const uint8_t kTestKeyGcm128_2[] = "21ZYXWVUTSRQPONMLKJIHGFEDCBA";
23 using testing::Return; 32 static const int kTestKeyGcm128Len = 28; // 128 bits key + 96 bits salt.
24 33 static const uint8_t kTestKeyGcm256_1[] =
25 class MockRtpTransport : public RtpTransport { 34 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr";
35 static const uint8_t kTestKeyGcm256_2[] =
36 "rqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA";
37 static const int kTestKeyGcm256Len = 44; // 256 bits key + 96 bits salt.
38
39 class FakeRtpTransport : public RtpTransport {
26 public: 40 public:
27 MockRtpTransport() : RtpTransport(true) {} 41 FakeRtpTransport() : RtpTransport(true) {
28 42 rtp_packet_transport_ =
29 MOCK_METHOD4(SendPacket, 43 rtc::MakeUnique<rtc::FakePacketTransport>("FakePacketTransport");
30 bool(bool rtcp, 44 SetRtpPacketTransport(rtp_packet_transport_.get());
31 rtc::CopyOnWriteBuffer* packet, 45 }
32 const rtc::PacketOptions& options, 46
33 int flags)); 47 void Connect(FakeRtpTransport* peer) { peer_ = peer; }
34 48
35 void PretendReceivedPacket() { 49 bool SendPacket(bool rtcp,
50 rtc::CopyOnWriteBuffer* packet,
51 const rtc::PacketOptions& options,
52 int flags) override {
53 if (peer_) {
54 peer_->set_last_recv_encrypted_packet(packet);
55 peer_->SignalPacketReceived(rtcp, packet, rtc::PacketTime());
56 }
57 return true;
58 }
59
60 void set_last_recv_encrypted_packet(rtc::CopyOnWriteBuffer* packet) {
61 rtp_packet_transport_->set_last_received_packet(packet);
62 }
63
64 private:
65 FakeRtpTransport* peer_ = nullptr;
66 std::unique_ptr<rtc::FakePacketTransport> rtp_packet_transport_;
67 };
68
69 class SrtpTransportTest : public testing::Test, public sigslot::has_slots<> {
70 protected:
71 SrtpTransportTest() {
72 auto rtp_transport1 = rtc::MakeUnique<FakeRtpTransport>();
73 auto rtp_transport2 = rtc::MakeUnique<FakeRtpTransport>();
74 rtp_transport1->Connect(rtp_transport2.get());
75 rtp_transport2->Connect(rtp_transport1.get());
76
77 srtp_transport1_ =
78 rtc::MakeUnique<SrtpTransport>(std::move(rtp_transport1), "content");
79 srtp_transport2_ =
80 rtc::MakeUnique<SrtpTransport>(std::move(rtp_transport2), "content");
81
82 srtp_transport1_->SignalPacketReceived.connect(
83 this, &SrtpTransportTest::OnPacketReceived1);
84 srtp_transport2_->SignalPacketReceived.connect(
85 this, &SrtpTransportTest::OnPacketReceived2);
86 }
87
88 void OnPacketReceived1(bool rtcp,
89 rtc::CopyOnWriteBuffer* packet,
90 const rtc::PacketTime& packet_time) {
91 LOG(LS_INFO) << "SrtpTransport1 Received a packet.";
92 last_recv_packet1_ = *packet;
93 }
94
95 void OnPacketReceived2(bool rtcp,
96 rtc::CopyOnWriteBuffer* packet,
97 const rtc::PacketTime& packet_time) {
98 LOG(LS_INFO) << "SrtpTransport2 Received a packet.";
99 last_recv_packet2_ = *packet;
100 }
101
102 void TestSendRecvRtpPacket(const std::string& cipher_suite_name) {
36 bool rtcp = false; 103 bool rtcp = false;
37 rtc::CopyOnWriteBuffer buffer; 104
38 rtc::PacketTime time; 105 int rtp_len = sizeof(kPcmuFrame);
39 SignalPacketReceived(rtcp, &buffer, time); 106 int packet_size = rtp_len + rtc::rtp_auth_tag_len(cipher_suite_name);
40 } 107 char rtp_packet_data[packet_size];
108 memcpy(rtp_packet_data, kPcmuFrame, rtp_len);
109 // In order to be able to run this test function multiple times we can not
110 // use the same sequence number twice. Increase the sequence number by one.
111 rtc::SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_data) + 2,
112 ++sequence_number_);
113 rtc::CopyOnWriteBuffer rtp_packet(rtp_packet_data, rtp_len, packet_size);
114
115 char original_rtp_data[rtp_len];
116 memcpy(original_rtp_data, rtp_packet_data, rtp_len);
117
118 rtc::PacketOptions options;
119 int flags = cricket::PF_NORMAL;
120 // Send a packet from |srtp_transport1_| to |srtp_transport2_| and verify
121 // that the packet can be successfully received and decrypted.
122 ASSERT_TRUE(
123 srtp_transport1_->SendPacket(rtcp, &rtp_packet, options, flags));
124 ASSERT_TRUE(last_recv_packet2_.data());
125 EXPECT_TRUE(memcmp(last_recv_packet2_.data(), original_rtp_data, rtp_len) ==
126 0);
127 // Get the encrypted packet from underneath packet transport and verify the
128 // data is actually encrypted.
129 auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
130 srtp_transport2_->rtp_packet_transport());
131 EXPECT_FALSE(
132 memcmp(fake_rtp_packet_transport->last_received_packet()->data(),
133 original_rtp_data, rtp_len) == 0);
134
135 // Do the same thing in the opposite direction;
136 ASSERT_TRUE(
137 srtp_transport2_->SendPacket(rtcp, &rtp_packet, options, flags));
138 ASSERT_TRUE(last_recv_packet1_.data());
139 EXPECT_TRUE(memcmp(last_recv_packet1_.data(), original_rtp_data, rtp_len) ==
140 0);
141 fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
142 srtp_transport1_->rtp_packet_transport());
143 EXPECT_FALSE(
144 memcmp(fake_rtp_packet_transport->last_received_packet()->data(),
145 original_rtp_data, rtp_len) == 0);
146 }
147
148 void TestSendRecvRtcpPacket(const std::string& cipher_suite_name) {
149 bool rtcp = true;
150
151 int rtcp_len = sizeof(kRtcpReport);
152 int packet_size = rtcp_len + 4 + rtc::rtcp_auth_tag_len(cipher_suite_name);
153 char rtcp_packet_data[packet_size];
154 memcpy(rtcp_packet_data, kRtcpReport, rtcp_len);
155
156 rtc::CopyOnWriteBuffer rtcp_packet(rtcp_packet_data, rtcp_len, packet_size);
157
158 rtc::PacketOptions options;
159 int flags = cricket::PF_NORMAL;
160 // Send a packet from |srtp_transport1_| to |srtp_transport2_| and verify
161 // that the packet can be successfully received and decrypted.
162 ASSERT_TRUE(
163 srtp_transport1_->SendPacket(rtcp, &rtcp_packet, options, flags));
164 ASSERT_TRUE(last_recv_packet2_.data());
165 EXPECT_TRUE(memcmp(last_recv_packet2_.data(), rtcp_packet_data, rtcp_len) ==
166 0);
167 // Get the encrypted packet from underneath packet transport and verify the
168 // data is actually encrypted.
169 auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
170 srtp_transport2_->rtp_packet_transport());
171 EXPECT_FALSE(
172 memcmp(fake_rtp_packet_transport->last_received_packet()->data(),
173 rtcp_packet_data, rtcp_len) == 0);
174
175 // Do the same thing in the opposite direction;
176 ASSERT_TRUE(
177 srtp_transport2_->SendPacket(rtcp, &rtcp_packet, options, flags));
178 ASSERT_TRUE(last_recv_packet1_.data());
179 EXPECT_TRUE(memcmp(last_recv_packet1_.data(), rtcp_packet_data, rtcp_len) ==
180 0);
181 fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
182 srtp_transport1_->rtp_packet_transport());
183 EXPECT_FALSE(
184 memcmp(fake_rtp_packet_transport->last_received_packet()->data(),
185 rtcp_packet_data, rtcp_len) == 0);
186 }
187
188 void TestSendRecvPacket(bool enable_external_auth,
189 int cs,
190 const uint8_t* key1,
191 int key1_len,
192 const uint8_t* key2,
193 int key2_len,
194 const std::string& cipher_suite_name) {
195 EXPECT_EQ(key1_len, key2_len);
196 EXPECT_EQ(cipher_suite_name, rtc::SrtpCryptoSuiteToName(cs));
197 if (enable_external_auth) {
198 srtp_transport1_->EnableExternalAuth();
199 srtp_transport2_->EnableExternalAuth();
200 }
201 EXPECT_TRUE(
202 srtp_transport1_->SetRtpParams(cs, key1, key1_len, cs, key2, key2_len));
203 EXPECT_TRUE(
204 srtp_transport2_->SetRtpParams(cs, key2, key2_len, cs, key1, key1_len));
205 EXPECT_TRUE(srtp_transport1_->SetRtcpParams(cs, key1, key1_len, cs, key2,
206 key2_len));
207 EXPECT_TRUE(srtp_transport2_->SetRtcpParams(cs, key2, key2_len, cs, key1,
208 key1_len));
209 EXPECT_TRUE(srtp_transport1_->IsActive());
210 EXPECT_TRUE(srtp_transport2_->IsActive());
211 if (rtc::IsGcmCryptoSuite(cs)) {
212 EXPECT_FALSE(srtp_transport1_->IsExternalAuthActive());
213 EXPECT_FALSE(srtp_transport2_->IsExternalAuthActive());
214 } else if (enable_external_auth) {
215 EXPECT_TRUE(srtp_transport1_->IsExternalAuthActive());
216 EXPECT_TRUE(srtp_transport2_->IsExternalAuthActive());
217 }
218 TestSendRecvRtpPacket(cipher_suite_name);
219 TestSendRecvRtcpPacket(cipher_suite_name);
220 }
221
222 void TestSendRecvPacketWithEncryptedHeaderExtension(
223 const std::string& cs,
224 const std::vector<int>& encrypted_header_ids) {
225 bool rtcp = false;
226
227 int rtp_len = sizeof(kPcmuFrameWithExtensions);
228 int packet_size = rtp_len + rtc::rtp_auth_tag_len(cs);
229 char rtp_packet_data[packet_size];
230 memcpy(rtp_packet_data, kPcmuFrameWithExtensions, rtp_len);
231 // In order to be able to run this test function multiple times we can not
232 // use the same sequence number twice. Increase the sequence number by one.
233 rtc::SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_data) + 2,
234 ++sequence_number_);
235 rtc::CopyOnWriteBuffer rtp_packet(rtp_packet_data, rtp_len, packet_size);
236
237 char original_rtp_data[rtp_len];
238 memcpy(original_rtp_data, rtp_packet_data, rtp_len);
239
240 rtc::PacketOptions options;
241 int flags = cricket::PF_NORMAL;
242 // Send a packet from |srtp_transport1_| to |srtp_transport2_| and verify
243 // that the packet can be successfully received and decrypted.
244 ASSERT_TRUE(
245 srtp_transport1_->SendPacket(rtcp, &rtp_packet, options, flags));
246 ASSERT_TRUE(last_recv_packet2_.data());
247 EXPECT_TRUE(memcmp(last_recv_packet2_.data(), original_rtp_data, rtp_len) ==
248 0);
249 // Get the encrypted packet from underneath packet transport and verify the
250 // data and header extension are actually encrypted.
251 auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
252 srtp_transport2_->rtp_packet_transport());
253 EXPECT_FALSE(
254 memcmp(fake_rtp_packet_transport->last_received_packet()->data(),
255 original_rtp_data, rtp_len) == 0);
256 CompareHeaderExtensions(
257 reinterpret_cast<const char*>(
258 fake_rtp_packet_transport->last_received_packet()->data()),
259 fake_rtp_packet_transport->last_received_packet()->size(),
260 original_rtp_data, rtp_len, encrypted_header_ids, false);
261
262 // Do the same thing in the opposite direction;
263 ASSERT_TRUE(
264 srtp_transport2_->SendPacket(rtcp, &rtp_packet, options, flags));
265 ASSERT_TRUE(last_recv_packet1_.data());
266 EXPECT_TRUE(memcmp(last_recv_packet1_.data(), original_rtp_data, rtp_len) ==
267 0);
268 fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
269 srtp_transport1_->rtp_packet_transport());
270 EXPECT_FALSE(
271 memcmp(fake_rtp_packet_transport->last_received_packet()->data(),
272 original_rtp_data, rtp_len) == 0);
273 CompareHeaderExtensions(
274 reinterpret_cast<const char*>(
275 fake_rtp_packet_transport->last_received_packet()->data()),
276 fake_rtp_packet_transport->last_received_packet()->size(),
277 original_rtp_data, rtp_len, encrypted_header_ids, false);
278 }
279
280 void TestSendRecvEncryptedHeaderExtension(int cs,
281 const uint8_t* key1,
282 int key1_len,
283 const uint8_t* key2,
284 int key2_len,
285 const std::string& cs_name) {
286 std::vector<int> encrypted_headers;
287 encrypted_headers.push_back(1);
288 // Don't encrypt header ids 2 and 3.
289 encrypted_headers.push_back(4);
290 EXPECT_EQ(key1_len, key2_len);
291 EXPECT_EQ(cs_name, rtc::SrtpCryptoSuiteToName(cs));
292 srtp_transport1_->SetEncryptedHeaderExtensionIds(cricket::CS_LOCAL,
293 encrypted_headers);
294 srtp_transport1_->SetEncryptedHeaderExtensionIds(cricket::CS_REMOTE,
295 encrypted_headers);
296 srtp_transport2_->SetEncryptedHeaderExtensionIds(cricket::CS_LOCAL,
297 encrypted_headers);
298 srtp_transport2_->SetEncryptedHeaderExtensionIds(cricket::CS_REMOTE,
299 encrypted_headers);
300 EXPECT_TRUE(
301 srtp_transport1_->SetRtpParams(cs, key1, key1_len, cs, key2, key2_len));
302 EXPECT_TRUE(
303 srtp_transport2_->SetRtpParams(cs, key2, key2_len, cs, key1, key1_len));
304 EXPECT_TRUE(srtp_transport1_->IsActive());
305 EXPECT_TRUE(srtp_transport2_->IsActive());
306 EXPECT_FALSE(srtp_transport1_->IsExternalAuthActive());
307 EXPECT_FALSE(srtp_transport2_->IsExternalAuthActive());
308 TestSendRecvPacketWithEncryptedHeaderExtension(cs_name, encrypted_headers);
309 }
310
311 std::unique_ptr<SrtpTransport> srtp_transport1_;
312 std::unique_ptr<SrtpTransport> srtp_transport2_;
313
314 rtc::CopyOnWriteBuffer last_recv_packet1_;
315 rtc::CopyOnWriteBuffer last_recv_packet2_;
316 int sequence_number_ = 0;
41 }; 317 };
42 318
43 TEST(SrtpTransportTest, SendPacket) { 319 TEST_F(SrtpTransportTest, SendAndRecvPacket_AES_CM_128_HMAC_SHA1_80) {
44 auto rtp_transport = rtc::MakeUnique<MockRtpTransport>(); 320 bool enable_external_auth = false;
45 EXPECT_CALL(*rtp_transport, SendPacket(_, _, _, _)).WillOnce(Return(true)); 321 TestSendRecvPacket(enable_external_auth, rtc::SRTP_AES128_CM_SHA1_80,
46 322 kTestKey1, kTestKeyLen, kTestKey2, kTestKeyLen,
47 SrtpTransport srtp_transport(std::move(rtp_transport), "a"); 323 rtc::CS_AES_CM_128_HMAC_SHA1_80);
48 324 }
49 const bool rtcp = false; 325
50 rtc::CopyOnWriteBuffer packet; 326 TEST_F(SrtpTransportTest,
51 rtc::PacketOptions options; 327 SendAndRecvPacketWithHeaderExtension_AES_CM_128_HMAC_SHA1_80) {
52 int flags = 0; 328 TestSendRecvEncryptedHeaderExtension(rtc::SRTP_AES128_CM_SHA1_80, kTestKey1,
53 EXPECT_TRUE(srtp_transport.SendPacket(rtcp, &packet, options, flags)); 329 kTestKeyLen, kTestKey2, kTestKeyLen,
54 330 rtc::CS_AES_CM_128_HMAC_SHA1_80);
55 // TODO(zstein): Also verify that the packet received by RtpTransport has been 331 }
56 // protected once SrtpTransport handles that. 332
57 } 333 TEST_F(SrtpTransportTest, SendAndRecvPacket_AES_CM_128_HMAC_SHA1_32) {
58 334 bool enable_external_auth = false;
59 // Test that SrtpTransport fires SignalPacketReceived when the underlying 335 TestSendRecvPacket(enable_external_auth, rtc::SRTP_AES128_CM_SHA1_32,
60 // RtpTransport fires SignalPacketReceived. 336 kTestKey1, kTestKeyLen, kTestKey2, kTestKeyLen,
61 TEST(SrtpTransportTest, SignalPacketReceived) { 337 rtc::CS_AES_CM_128_HMAC_SHA1_32);
62 auto rtp_transport = rtc::MakeUnique<MockRtpTransport>(); 338 }
63 MockRtpTransport* rtp_transport_raw = rtp_transport.get(); 339
64 SrtpTransport srtp_transport(std::move(rtp_transport), "a"); 340 TEST_F(SrtpTransportTest,
65 341 SendAndRecvPacketWithHeaderExtension_AES_CM_128_HMAC_SHA1_32) {
66 SignalPacketReceivedCounter counter(&srtp_transport); 342 TestSendRecvEncryptedHeaderExtension(rtc::SRTP_AES128_CM_SHA1_32, kTestKey1,
67 343 kTestKeyLen, kTestKey2, kTestKeyLen,
68 rtp_transport_raw->PretendReceivedPacket(); 344 rtc::CS_AES_CM_128_HMAC_SHA1_32);
69 345 }
70 EXPECT_EQ(1, counter.rtp_count()); 346
71 347 TEST_F(SrtpTransportTest, SendAndRecvPacket_SRTP_AEAD_AES_128_GCM) {
72 // TODO(zstein): Also verify that the packet is unprotected once SrtpTransport 348 bool enable_external_auth = false;
73 // handles that. 349 TestSendRecvPacket(enable_external_auth, rtc::SRTP_AEAD_AES_128_GCM,
350 kTestKeyGcm128_1, kTestKeyGcm128Len, kTestKeyGcm128_2,
351 kTestKeyGcm128Len, rtc::CS_AEAD_AES_128_GCM);
352 }
353
354 TEST_F(SrtpTransportTest,
355 SendAndRecvPacketWithHeaderExtension_SRTP_AEAD_AES_128_GCM) {
356 TestSendRecvEncryptedHeaderExtension(
357 rtc::SRTP_AEAD_AES_128_GCM, kTestKeyGcm128_1, kTestKeyGcm128Len,
358 kTestKeyGcm128_2, kTestKeyGcm128Len, rtc::CS_AEAD_AES_128_GCM);
359 }
360
361 TEST_F(SrtpTransportTest, SendAndRecvPacket_SRTP_AEAD_AES_256_GCM) {
362 bool enable_external_auth = false;
Taylor Brandstetter 2017/08/23 22:13:30 These tests aren't using external auth, like the t
Zhi Huang 2017/08/24 23:38:07 Thanks for the detailed explanation! Done.
363 TestSendRecvPacket(enable_external_auth, rtc::SRTP_AEAD_AES_256_GCM,
364 kTestKeyGcm256_1, kTestKeyGcm256Len, kTestKeyGcm256_2,
365 kTestKeyGcm256Len, rtc::CS_AEAD_AES_256_GCM);
366 }
367
368 TEST_F(SrtpTransportTest,
369 SendAndRecvPacketWithHeaderExtension_SRTP_AEAD_AES_256_GCM) {
370 TestSendRecvEncryptedHeaderExtension(
371 rtc::SRTP_AEAD_AES_256_GCM, kTestKeyGcm256_1, kTestKeyGcm256Len,
372 kTestKeyGcm256_2, kTestKeyGcm256Len, rtc::CS_AEAD_AES_256_GCM);
74 } 373 }
75 374
76 } // namespace webrtc 375 } // namespace webrtc
OLDNEW
« webrtc/pc/srtptransport.h ('K') | « webrtc/pc/srtptransport.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698