/* * Copyright 2017 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
~SrtpTransportTest() { if (srtp_transport1_) {
srtp_transport1_->UnregisterRtpDemuxerSink(&rtp_sink1_);
} if (srtp_transport2_) {
srtp_transport2_->UnregisterRtpDemuxerSink(&rtp_sink2_);
}
}
// With external auth enabled, SRTP doesn't write the auth tag and // unprotect would fail. Check accessing the information about the // tag instead, similar to what the actual code would do that relies // on external auth. void TestRtpAuthParams(SrtpTransport* transport, int crypto_suite) { int overhead;
EXPECT_TRUE(transport->GetSrtpOverhead(&overhead)); switch (crypto_suite) { case rtc::kSrtpAes128CmSha1_32:
EXPECT_EQ(32 / 8, overhead); // 32-bit tag. break; case rtc::kSrtpAes128CmSha1_80:
EXPECT_EQ(80 / 8, overhead); // 80-bit tag. break; default:
RTC_DCHECK_NOTREACHED(); break;
}
uint8_t* auth_key = nullptr; int key_len = 0; int tag_len = 0;
EXPECT_TRUE(transport->GetRtpAuthParams(&auth_key, &key_len, &tag_len));
EXPECT_NE(nullptr, auth_key);
EXPECT_EQ(160 / 8, key_len); // Length of SHA-1 is 160 bits.
EXPECT_EQ(overhead, tag_len);
}
void TestSendRecvRtpPacket(int crypto_suite) {
size_t rtp_len = sizeof(kPcmuFrame);
size_t packet_size = rtp_len + rtc::rtp_auth_tag_len(crypto_suite);
rtc::Buffer rtp_packet_buffer(packet_size); char* rtp_packet_data = rtp_packet_buffer.data<char>();
memcpy(rtp_packet_data, kPcmuFrame, rtp_len); // In order to be able to run this test function multiple times we can not // use the same sequence number twice. Increase the sequence number by one.
rtc::SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_data) + 2,
++sequence_number_);
rtc::CopyOnWriteBuffer rtp_packet1to2(rtp_packet_data, rtp_len,
packet_size);
rtc::CopyOnWriteBuffer rtp_packet2to1(rtp_packet_data, rtp_len,
packet_size);
rtc::PacketOptions options; // Send a packet from `srtp_transport1_` to `srtp_transport2_` and verify // that the packet can be successfully received and decrypted.
ASSERT_TRUE(srtp_transport1_->SendRtpPacket(&rtp_packet1to2, options,
cricket::PF_SRTP_BYPASS)); if (srtp_transport1_->IsExternalAuthActive()) {
TestRtpAuthParams(srtp_transport1_.get(), crypto_suite);
} else {
ASSERT_TRUE(rtp_sink2_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink2_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len)); // Get the encrypted packet from underneath packet transport and verify // the data is actually encrypted. auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
srtp_transport1_->rtp_packet_transport());
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
original_rtp_data, rtp_len));
}
// Do the same thing in the opposite direction;
ASSERT_TRUE(srtp_transport2_->SendRtpPacket(&rtp_packet2to1, options,
cricket::PF_SRTP_BYPASS)); if (srtp_transport2_->IsExternalAuthActive()) {
TestRtpAuthParams(srtp_transport2_.get(), crypto_suite);
} else {
ASSERT_TRUE(rtp_sink1_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink1_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len)); auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
srtp_transport2_->rtp_packet_transport());
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
original_rtp_data, rtp_len));
}
}
rtc::PacketOptions options; // Send a packet from `srtp_transport1_` to `srtp_transport2_` and verify // that the packet can be successfully received and decrypted.
ASSERT_TRUE(srtp_transport1_->SendRtcpPacket(&rtcp_packet1to2, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(rtp_sink2_.last_recv_rtcp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink2_.last_recv_rtcp_packet().data(),
rtcp_packet_data, rtcp_len)); // Get the encrypted packet from underneath packet transport and verify the // data is actually encrypted. auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
srtp_transport1_->rtp_packet_transport());
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
rtcp_packet_data, rtcp_len));
// Do the same thing in the opposite direction;
ASSERT_TRUE(srtp_transport2_->SendRtcpPacket(&rtcp_packet2to1, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(rtp_sink1_.last_recv_rtcp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink1_.last_recv_rtcp_packet().data(),
rtcp_packet_data, rtcp_len));
fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
srtp_transport2_->rtp_packet_transport());
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
rtcp_packet_data, rtcp_len));
}
void TestSendRecvPacketWithEncryptedHeaderExtension( int crypto_suite, const std::vector<int>& encrypted_header_ids) {
size_t rtp_len = sizeof(kPcmuFrameWithExtensions);
size_t packet_size = rtp_len + rtc::rtp_auth_tag_len(crypto_suite);
rtc::Buffer rtp_packet_buffer(packet_size); char* rtp_packet_data = rtp_packet_buffer.data<char>();
memcpy(rtp_packet_data, kPcmuFrameWithExtensions, rtp_len); // In order to be able to run this test function multiple times we can not // use the same sequence number twice. Increase the sequence number by one.
rtc::SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_data) + 2,
++sequence_number_);
rtc::CopyOnWriteBuffer rtp_packet1to2(rtp_packet_data, rtp_len,
packet_size);
rtc::CopyOnWriteBuffer rtp_packet2to1(rtp_packet_data, rtp_len,
packet_size);
rtc::PacketOptions options; // Send a packet from `srtp_transport1_` to `srtp_transport2_` and verify // that the packet can be successfully received and decrypted.
ASSERT_TRUE(srtp_transport1_->SendRtpPacket(&rtp_packet1to2, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(rtp_sink2_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink2_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len)); // Get the encrypted packet from underneath packet transport and verify the // data and header extension are actually encrypted. auto fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
srtp_transport1_->rtp_packet_transport());
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
original_rtp_data, rtp_len));
CompareHeaderExtensions( reinterpret_cast<constchar*>(
fake_rtp_packet_transport->last_sent_packet()->data()),
fake_rtp_packet_transport->last_sent_packet()->size(),
original_rtp_data, rtp_len, encrypted_header_ids, false);
// Do the same thing in the opposite direction;
ASSERT_TRUE(srtp_transport2_->SendRtpPacket(&rtp_packet2to1, options,
cricket::PF_SRTP_BYPASS));
ASSERT_TRUE(rtp_sink1_.last_recv_rtp_packet().data());
EXPECT_EQ(0, memcmp(rtp_sink1_.last_recv_rtp_packet().data(),
original_rtp_data, rtp_len));
fake_rtp_packet_transport = static_cast<rtc::FakePacketTransport*>(
srtp_transport2_->rtp_packet_transport());
EXPECT_NE(0, memcmp(fake_rtp_packet_transport->last_sent_packet()->data(),
original_rtp_data, rtp_len));
CompareHeaderExtensions( reinterpret_cast<constchar*>(
fake_rtp_packet_transport->last_sent_packet()->data()),
fake_rtp_packet_transport->last_sent_packet()->size(),
original_rtp_data, rtp_len, encrypted_header_ids, false);
}
// Run all tests both with and without external auth enabled.
INSTANTIATE_TEST_SUITE_P(ExternalAuth,
SrtpTransportTestWithExternalAuth,
::testing::Values(true, false));
// Create a packet and try to send it three times.
size_t rtp_len = sizeof(kPcmuFrame);
size_t packet_size = rtp_len + rtc::rtp_auth_tag_len(rtc::kSrtpAeadAes128Gcm);
rtc::Buffer rtp_packet_buffer(packet_size); char* rtp_packet_data = rtp_packet_buffer.data<char>();
memcpy(rtp_packet_data, kPcmuFrame, rtp_len);
// First attempt will succeed.
rtc::CopyOnWriteBuffer first_try(rtp_packet_data, rtp_len, packet_size);
EXPECT_TRUE(srtp_transport->SendRtpPacket(&first_try, rtc::PacketOptions(),
cricket::PF_SRTP_BYPASS));
EXPECT_EQ(rtp_sink.rtp_count(), 1);
// Second attempt will be rejected by libSRTP as a replay attack // (srtp_err_status_replay_fail) since the sequence number was already seen. // Hence the packet never reaches the sink.
rtc::CopyOnWriteBuffer second_try(rtp_packet_data, rtp_len, packet_size);
EXPECT_TRUE(srtp_transport->SendRtpPacket(&second_try, rtc::PacketOptions(),
cricket::PF_SRTP_BYPASS));
EXPECT_EQ(rtp_sink.rtp_count(), 1);
// Reset the sink.
EXPECT_TRUE(srtp_transport->UnregisterRtpDemuxerSink(&rtp_sink));
EXPECT_TRUE(
srtp_transport->RegisterRtpDemuxerSink(demuxer_criteria, &rtp_sink));
// Third attempt will succeed again since libSRTP does not remember seeing // the sequence number after the reset.
rtc::CopyOnWriteBuffer third_try(rtp_packet_data, rtp_len, packet_size);
EXPECT_TRUE(srtp_transport->SendRtpPacket(&third_try, rtc::PacketOptions(),
cricket::PF_SRTP_BYPASS));
EXPECT_EQ(rtp_sink.rtp_count(), 2); // Clear the sink to clean up.
srtp_transport->UnregisterRtpDemuxerSink(&rtp_sink);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.