xref: /aosp_15_r20/external/webrtc/pc/srtp_session_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2004 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 "pc/srtp_session.h"
12 
13 #include <string.h>
14 
15 #include <string>
16 
17 #include "media/base/fake_rtp.h"
18 #include "pc/test/srtp_test_util.h"
19 #include "rtc_base/byte_order.h"
20 #include "rtc_base/ssl_stream_adapter.h"  // For rtc::SRTP_*
21 #include "system_wrappers/include/metrics.h"
22 #include "test/gmock.h"
23 #include "test/gtest.h"
24 #include "test/scoped_key_value_config.h"
25 #include "third_party/libsrtp/include/srtp.h"
26 
27 using ::testing::ElementsAre;
28 using ::testing::Pair;
29 
30 namespace rtc {
31 
32 std::vector<int> kEncryptedHeaderExtensionIds;
33 
34 class SrtpSessionTest : public ::testing::Test {
35  public:
SrtpSessionTest()36   SrtpSessionTest() : s1_(field_trials_), s2_(field_trials_) {
37     webrtc::metrics::Reset();
38   }
39 
40  protected:
SetUp()41   virtual void SetUp() {
42     rtp_len_ = sizeof(kPcmuFrame);
43     rtcp_len_ = sizeof(kRtcpReport);
44     memcpy(rtp_packet_, kPcmuFrame, rtp_len_);
45     memcpy(rtcp_packet_, kRtcpReport, rtcp_len_);
46   }
TestProtectRtp(const std::string & cs)47   void TestProtectRtp(const std::string& cs) {
48     int out_len = 0;
49     EXPECT_TRUE(
50         s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_), &out_len));
51     EXPECT_EQ(out_len, rtp_len_ + rtp_auth_tag_len(cs));
52     EXPECT_NE(0, memcmp(rtp_packet_, kPcmuFrame, rtp_len_));
53     rtp_len_ = out_len;
54   }
TestProtectRtcp(const std::string & cs)55   void TestProtectRtcp(const std::string& cs) {
56     int out_len = 0;
57     EXPECT_TRUE(s1_.ProtectRtcp(rtcp_packet_, rtcp_len_, sizeof(rtcp_packet_),
58                                 &out_len));
59     EXPECT_EQ(out_len, rtcp_len_ + 4 + rtcp_auth_tag_len(cs));  // NOLINT
60     EXPECT_NE(0, memcmp(rtcp_packet_, kRtcpReport, rtcp_len_));
61     rtcp_len_ = out_len;
62   }
TestUnprotectRtp(const std::string & cs)63   void TestUnprotectRtp(const std::string& cs) {
64     int out_len = 0, expected_len = sizeof(kPcmuFrame);
65     EXPECT_TRUE(s2_.UnprotectRtp(rtp_packet_, rtp_len_, &out_len));
66     EXPECT_EQ(expected_len, out_len);
67     EXPECT_EQ(0, memcmp(rtp_packet_, kPcmuFrame, out_len));
68   }
TestUnprotectRtcp(const std::string & cs)69   void TestUnprotectRtcp(const std::string& cs) {
70     int out_len = 0, expected_len = sizeof(kRtcpReport);
71     EXPECT_TRUE(s2_.UnprotectRtcp(rtcp_packet_, rtcp_len_, &out_len));
72     EXPECT_EQ(expected_len, out_len);
73     EXPECT_EQ(0, memcmp(rtcp_packet_, kRtcpReport, out_len));
74   }
75   webrtc::test::ScopedKeyValueConfig field_trials_;
76   cricket::SrtpSession s1_;
77   cricket::SrtpSession s2_;
78   char rtp_packet_[sizeof(kPcmuFrame) + 10];
79   char rtcp_packet_[sizeof(kRtcpReport) + 4 + 10];
80   int rtp_len_;
81   int rtcp_len_;
82 };
83 
84 // Test that we can set up the session and keys properly.
TEST_F(SrtpSessionTest,TestGoodSetup)85 TEST_F(SrtpSessionTest, TestGoodSetup) {
86   EXPECT_TRUE(s1_.SetSend(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
87                           kEncryptedHeaderExtensionIds));
88   EXPECT_TRUE(s2_.SetRecv(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
89                           kEncryptedHeaderExtensionIds));
90 }
91 
92 // Test that we can't change the keys once set.
TEST_F(SrtpSessionTest,TestBadSetup)93 TEST_F(SrtpSessionTest, TestBadSetup) {
94   EXPECT_TRUE(s1_.SetSend(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
95                           kEncryptedHeaderExtensionIds));
96   EXPECT_TRUE(s2_.SetRecv(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
97                           kEncryptedHeaderExtensionIds));
98   EXPECT_FALSE(s1_.SetSend(kSrtpAes128CmSha1_80, kTestKey2, kTestKeyLen,
99                            kEncryptedHeaderExtensionIds));
100   EXPECT_FALSE(s2_.SetRecv(kSrtpAes128CmSha1_80, kTestKey2, kTestKeyLen,
101                            kEncryptedHeaderExtensionIds));
102 }
103 
104 // Test that we fail keys of the wrong length.
TEST_F(SrtpSessionTest,TestKeysTooShort)105 TEST_F(SrtpSessionTest, TestKeysTooShort) {
106   EXPECT_FALSE(s1_.SetSend(kSrtpAes128CmSha1_80, kTestKey1, 1,
107                            kEncryptedHeaderExtensionIds));
108   EXPECT_FALSE(s2_.SetRecv(kSrtpAes128CmSha1_80, kTestKey1, 1,
109                            kEncryptedHeaderExtensionIds));
110 }
111 
112 // Test that we can encrypt and decrypt RTP/RTCP using AES_CM_128_HMAC_SHA1_80.
TEST_F(SrtpSessionTest,TestProtect_AES_CM_128_HMAC_SHA1_80)113 TEST_F(SrtpSessionTest, TestProtect_AES_CM_128_HMAC_SHA1_80) {
114   EXPECT_TRUE(s1_.SetSend(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
115                           kEncryptedHeaderExtensionIds));
116   EXPECT_TRUE(s2_.SetRecv(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
117                           kEncryptedHeaderExtensionIds));
118   TestProtectRtp(kCsAesCm128HmacSha1_80);
119   TestProtectRtcp(kCsAesCm128HmacSha1_80);
120   TestUnprotectRtp(kCsAesCm128HmacSha1_80);
121   TestUnprotectRtcp(kCsAesCm128HmacSha1_80);
122 }
123 
124 // Test that we can encrypt and decrypt RTP/RTCP using AES_CM_128_HMAC_SHA1_32.
TEST_F(SrtpSessionTest,TestProtect_AES_CM_128_HMAC_SHA1_32)125 TEST_F(SrtpSessionTest, TestProtect_AES_CM_128_HMAC_SHA1_32) {
126   EXPECT_TRUE(s1_.SetSend(kSrtpAes128CmSha1_32, kTestKey1, kTestKeyLen,
127                           kEncryptedHeaderExtensionIds));
128   EXPECT_TRUE(s2_.SetRecv(kSrtpAes128CmSha1_32, kTestKey1, kTestKeyLen,
129                           kEncryptedHeaderExtensionIds));
130   TestProtectRtp(kCsAesCm128HmacSha1_32);
131   TestProtectRtcp(kCsAesCm128HmacSha1_32);
132   TestUnprotectRtp(kCsAesCm128HmacSha1_32);
133   TestUnprotectRtcp(kCsAesCm128HmacSha1_32);
134 }
135 
TEST_F(SrtpSessionTest,TestGetSendStreamPacketIndex)136 TEST_F(SrtpSessionTest, TestGetSendStreamPacketIndex) {
137   EXPECT_TRUE(s1_.SetSend(kSrtpAes128CmSha1_32, kTestKey1, kTestKeyLen,
138                           kEncryptedHeaderExtensionIds));
139   int64_t index;
140   int out_len = 0;
141   EXPECT_TRUE(s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_),
142                              &out_len, &index));
143   // `index` will be shifted by 16.
144   int64_t be64_index = static_cast<int64_t>(NetworkToHost64(1 << 16));
145   EXPECT_EQ(be64_index, index);
146 }
147 
148 // Test that we fail to unprotect if someone tampers with the RTP/RTCP paylaods.
TEST_F(SrtpSessionTest,TestTamperReject)149 TEST_F(SrtpSessionTest, TestTamperReject) {
150   int out_len;
151   EXPECT_TRUE(s1_.SetSend(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
152                           kEncryptedHeaderExtensionIds));
153   EXPECT_TRUE(s2_.SetRecv(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
154                           kEncryptedHeaderExtensionIds));
155   TestProtectRtp(kCsAesCm128HmacSha1_80);
156   TestProtectRtcp(kCsAesCm128HmacSha1_80);
157   rtp_packet_[0] = 0x12;
158   rtcp_packet_[1] = 0x34;
159   EXPECT_FALSE(s2_.UnprotectRtp(rtp_packet_, rtp_len_, &out_len));
160   EXPECT_METRIC_THAT(
161       webrtc::metrics::Samples("WebRTC.PeerConnection.SrtpUnprotectError"),
162       ElementsAre(Pair(srtp_err_status_bad_param, 1)));
163   EXPECT_FALSE(s2_.UnprotectRtcp(rtcp_packet_, rtcp_len_, &out_len));
164   EXPECT_METRIC_THAT(
165       webrtc::metrics::Samples("WebRTC.PeerConnection.SrtcpUnprotectError"),
166       ElementsAre(Pair(srtp_err_status_auth_fail, 1)));
167 }
168 
169 // Test that we fail to unprotect if the payloads are not authenticated.
TEST_F(SrtpSessionTest,TestUnencryptReject)170 TEST_F(SrtpSessionTest, TestUnencryptReject) {
171   int out_len;
172   EXPECT_TRUE(s1_.SetSend(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
173                           kEncryptedHeaderExtensionIds));
174   EXPECT_TRUE(s2_.SetRecv(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
175                           kEncryptedHeaderExtensionIds));
176   EXPECT_FALSE(s2_.UnprotectRtp(rtp_packet_, rtp_len_, &out_len));
177   EXPECT_METRIC_THAT(
178       webrtc::metrics::Samples("WebRTC.PeerConnection.SrtpUnprotectError"),
179       ElementsAre(Pair(srtp_err_status_auth_fail, 1)));
180   EXPECT_FALSE(s2_.UnprotectRtcp(rtcp_packet_, rtcp_len_, &out_len));
181   EXPECT_METRIC_THAT(
182       webrtc::metrics::Samples("WebRTC.PeerConnection.SrtcpUnprotectError"),
183       ElementsAre(Pair(srtp_err_status_cant_check, 1)));
184 }
185 
186 // Test that we fail when using buffers that are too small.
TEST_F(SrtpSessionTest,TestBuffersTooSmall)187 TEST_F(SrtpSessionTest, TestBuffersTooSmall) {
188   int out_len;
189   EXPECT_TRUE(s1_.SetSend(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
190                           kEncryptedHeaderExtensionIds));
191   EXPECT_FALSE(s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_) - 10,
192                               &out_len));
193   EXPECT_FALSE(s1_.ProtectRtcp(rtcp_packet_, rtcp_len_,
194                                sizeof(rtcp_packet_) - 14, &out_len));
195 }
196 
TEST_F(SrtpSessionTest,TestReplay)197 TEST_F(SrtpSessionTest, TestReplay) {
198   static const uint16_t kMaxSeqnum = static_cast<uint16_t>(-1);
199   static const uint16_t seqnum_big = 62275;
200   static const uint16_t seqnum_small = 10;
201   static const uint16_t replay_window = 1024;
202   int out_len;
203 
204   EXPECT_TRUE(s1_.SetSend(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
205                           kEncryptedHeaderExtensionIds));
206   EXPECT_TRUE(s2_.SetRecv(kSrtpAes128CmSha1_80, kTestKey1, kTestKeyLen,
207                           kEncryptedHeaderExtensionIds));
208 
209   // Initial sequence number.
210   SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_) + 2, seqnum_big);
211   EXPECT_TRUE(
212       s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_), &out_len));
213 
214   // Replay within the 1024 window should succeed.
215   SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_) + 2,
216           seqnum_big - replay_window + 1);
217   EXPECT_TRUE(
218       s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_), &out_len));
219 
220   // Replay out side of the 1024 window should fail.
221   SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_) + 2,
222           seqnum_big - replay_window - 1);
223   EXPECT_FALSE(
224       s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_), &out_len));
225 
226   // Increment sequence number to a small number.
227   SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_) + 2, seqnum_small);
228   EXPECT_TRUE(
229       s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_), &out_len));
230 
231   // Replay around 0 but out side of the 1024 window should fail.
232   SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_) + 2,
233           kMaxSeqnum + seqnum_small - replay_window - 1);
234   EXPECT_FALSE(
235       s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_), &out_len));
236 
237   // Replay around 0 but within the 1024 window should succeed.
238   for (uint16_t seqnum = 65000; seqnum < 65003; ++seqnum) {
239     SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_) + 2, seqnum);
240     EXPECT_TRUE(
241         s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_), &out_len));
242   }
243 
244   // Go back to normal sequence nubmer.
245   // NOTE: without the fix in libsrtp, this would fail. This is because
246   // without the fix, the loop above would keep incrementing local sequence
247   // number in libsrtp, eventually the new sequence number would go out side
248   // of the window.
249   SetBE16(reinterpret_cast<uint8_t*>(rtp_packet_) + 2, seqnum_small + 1);
250   EXPECT_TRUE(
251       s1_.ProtectRtp(rtp_packet_, rtp_len_, sizeof(rtp_packet_), &out_len));
252 }
253 
254 }  // namespace rtc
255