xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_framer_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/crypto/crypto_framer.h"
6 
7 #include <map>
8 #include <memory>
9 #include <vector>
10 
11 #include "absl/base/macros.h"
12 #include "absl/strings/string_view.h"
13 #include "quiche/quic/core/crypto/crypto_handshake.h"
14 #include "quiche/quic/core/crypto/crypto_protocol.h"
15 #include "quiche/quic/core/quic_packets.h"
16 #include "quiche/quic/platform/api/quic_logging.h"
17 #include "quiche/quic/platform/api/quic_test.h"
18 #include "quiche/quic/test_tools/crypto_test_utils.h"
19 #include "quiche/quic/test_tools/quic_test_utils.h"
20 #include "quiche/common/test_tools/quiche_test_utils.h"
21 
22 namespace quic {
23 namespace test {
24 namespace {
25 
AsChars(unsigned char * data)26 char* AsChars(unsigned char* data) { return reinterpret_cast<char*>(data); }
27 
28 class TestCryptoVisitor : public CryptoFramerVisitorInterface {
29  public:
TestCryptoVisitor()30   TestCryptoVisitor() : error_count_(0) {}
31 
OnError(CryptoFramer * framer)32   void OnError(CryptoFramer* framer) override {
33     QUIC_DLOG(ERROR) << "CryptoFramer Error: " << framer->error();
34     ++error_count_;
35   }
36 
OnHandshakeMessage(const CryptoHandshakeMessage & message)37   void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
38     messages_.push_back(message);
39   }
40 
41   // Counters from the visitor callbacks.
42   int error_count_;
43 
44   std::vector<CryptoHandshakeMessage> messages_;
45 };
46 
TEST(CryptoFramerTest,ConstructHandshakeMessage)47 TEST(CryptoFramerTest, ConstructHandshakeMessage) {
48   CryptoHandshakeMessage message;
49   message.set_tag(0xFFAA7733);
50   message.SetStringPiece(0x12345678, "abcdef");
51   message.SetStringPiece(0x12345679, "ghijk");
52   message.SetStringPiece(0x1234567A, "lmnopqr");
53 
54   unsigned char packet[] = {// tag
55                             0x33, 0x77, 0xAA, 0xFF,
56                             // num entries
57                             0x03, 0x00,
58                             // padding
59                             0x00, 0x00,
60                             // tag 1
61                             0x78, 0x56, 0x34, 0x12,
62                             // end offset 1
63                             0x06, 0x00, 0x00, 0x00,
64                             // tag 2
65                             0x79, 0x56, 0x34, 0x12,
66                             // end offset 2
67                             0x0b, 0x00, 0x00, 0x00,
68                             // tag 3
69                             0x7A, 0x56, 0x34, 0x12,
70                             // end offset 3
71                             0x12, 0x00, 0x00, 0x00,
72                             // value 1
73                             'a', 'b', 'c', 'd', 'e', 'f',
74                             // value 2
75                             'g', 'h', 'i', 'j', 'k',
76                             // value 3
77                             'l', 'm', 'n', 'o', 'p', 'q', 'r'};
78 
79   CryptoFramer framer;
80   std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
81   ASSERT_TRUE(data != nullptr);
82   quiche::test::CompareCharArraysWithHexError(
83       "constructed packet", data->data(), data->length(), AsChars(packet),
84       ABSL_ARRAYSIZE(packet));
85 }
86 
TEST(CryptoFramerTest,ConstructHandshakeMessageWithTwoKeys)87 TEST(CryptoFramerTest, ConstructHandshakeMessageWithTwoKeys) {
88   CryptoHandshakeMessage message;
89   message.set_tag(0xFFAA7733);
90   message.SetStringPiece(0x12345678, "abcdef");
91   message.SetStringPiece(0x12345679, "ghijk");
92 
93   unsigned char packet[] = {// tag
94                             0x33, 0x77, 0xAA, 0xFF,
95                             // num entries
96                             0x02, 0x00,
97                             // padding
98                             0x00, 0x00,
99                             // tag 1
100                             0x78, 0x56, 0x34, 0x12,
101                             // end offset 1
102                             0x06, 0x00, 0x00, 0x00,
103                             // tag 2
104                             0x79, 0x56, 0x34, 0x12,
105                             // end offset 2
106                             0x0b, 0x00, 0x00, 0x00,
107                             // value 1
108                             'a', 'b', 'c', 'd', 'e', 'f',
109                             // value 2
110                             'g', 'h', 'i', 'j', 'k'};
111 
112   CryptoFramer framer;
113   std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
114   ASSERT_TRUE(data != nullptr);
115 
116   quiche::test::CompareCharArraysWithHexError(
117       "constructed packet", data->data(), data->length(), AsChars(packet),
118       ABSL_ARRAYSIZE(packet));
119 }
120 
TEST(CryptoFramerTest,ConstructHandshakeMessageZeroLength)121 TEST(CryptoFramerTest, ConstructHandshakeMessageZeroLength) {
122   CryptoHandshakeMessage message;
123   message.set_tag(0xFFAA7733);
124   message.SetStringPiece(0x12345678, "");
125 
126   unsigned char packet[] = {// tag
127                             0x33, 0x77, 0xAA, 0xFF,
128                             // num entries
129                             0x01, 0x00,
130                             // padding
131                             0x00, 0x00,
132                             // tag 1
133                             0x78, 0x56, 0x34, 0x12,
134                             // end offset 1
135                             0x00, 0x00, 0x00, 0x00};
136 
137   CryptoFramer framer;
138   std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
139   ASSERT_TRUE(data != nullptr);
140 
141   quiche::test::CompareCharArraysWithHexError(
142       "constructed packet", data->data(), data->length(), AsChars(packet),
143       ABSL_ARRAYSIZE(packet));
144 }
145 
TEST(CryptoFramerTest,ConstructHandshakeMessageTooManyEntries)146 TEST(CryptoFramerTest, ConstructHandshakeMessageTooManyEntries) {
147   CryptoHandshakeMessage message;
148   message.set_tag(0xFFAA7733);
149   for (uint32_t key = 1; key <= kMaxEntries + 1; ++key) {
150     message.SetStringPiece(key, "abcdef");
151   }
152 
153   CryptoFramer framer;
154   std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
155   EXPECT_TRUE(data == nullptr);
156 }
157 
TEST(CryptoFramerTest,ConstructHandshakeMessageMinimumSize)158 TEST(CryptoFramerTest, ConstructHandshakeMessageMinimumSize) {
159   CryptoHandshakeMessage message;
160   message.set_tag(0xFFAA7733);
161   message.SetStringPiece(0x01020304, "test");
162   message.set_minimum_size(64);
163 
164   unsigned char packet[] = {// tag
165                             0x33, 0x77, 0xAA, 0xFF,
166                             // num entries
167                             0x02, 0x00,
168                             // padding
169                             0x00, 0x00,
170                             // tag 1
171                             'P', 'A', 'D', 0,
172                             // end offset 1
173                             0x24, 0x00, 0x00, 0x00,
174                             // tag 2
175                             0x04, 0x03, 0x02, 0x01,
176                             // end offset 2
177                             0x28, 0x00, 0x00, 0x00,
178                             // 36 bytes of padding.
179                             '-', '-', '-', '-', '-', '-', '-', '-', '-', '-',
180                             '-', '-', '-', '-', '-', '-', '-', '-', '-', '-',
181                             '-', '-', '-', '-', '-', '-', '-', '-', '-', '-',
182                             '-', '-', '-', '-', '-', '-',
183                             // value 2
184                             't', 'e', 's', 't'};
185 
186   CryptoFramer framer;
187   std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
188   ASSERT_TRUE(data != nullptr);
189 
190   quiche::test::CompareCharArraysWithHexError(
191       "constructed packet", data->data(), data->length(), AsChars(packet),
192       ABSL_ARRAYSIZE(packet));
193 }
194 
TEST(CryptoFramerTest,ConstructHandshakeMessageMinimumSizePadLast)195 TEST(CryptoFramerTest, ConstructHandshakeMessageMinimumSizePadLast) {
196   CryptoHandshakeMessage message;
197   message.set_tag(0xFFAA7733);
198   message.SetStringPiece(1, "");
199   message.set_minimum_size(64);
200 
201   unsigned char packet[] = {// tag
202                             0x33, 0x77, 0xAA, 0xFF,
203                             // num entries
204                             0x02, 0x00,
205                             // padding
206                             0x00, 0x00,
207                             // tag 1
208                             0x01, 0x00, 0x00, 0x00,
209                             // end offset 1
210                             0x00, 0x00, 0x00, 0x00,
211                             // tag 2
212                             'P', 'A', 'D', 0,
213                             // end offset 2
214                             0x28, 0x00, 0x00, 0x00,
215                             // 40 bytes of padding.
216                             '-', '-', '-', '-', '-', '-', '-', '-', '-', '-',
217                             '-', '-', '-', '-', '-', '-', '-', '-', '-', '-',
218                             '-', '-', '-', '-', '-', '-', '-', '-', '-', '-',
219                             '-', '-', '-', '-', '-', '-', '-', '-', '-', '-'};
220 
221   CryptoFramer framer;
222   std::unique_ptr<QuicData> data = framer.ConstructHandshakeMessage(message);
223   ASSERT_TRUE(data != nullptr);
224 
225   quiche::test::CompareCharArraysWithHexError(
226       "constructed packet", data->data(), data->length(), AsChars(packet),
227       ABSL_ARRAYSIZE(packet));
228 }
229 
TEST(CryptoFramerTest,ProcessInput)230 TEST(CryptoFramerTest, ProcessInput) {
231   test::TestCryptoVisitor visitor;
232   CryptoFramer framer;
233   framer.set_visitor(&visitor);
234 
235   unsigned char input[] = {// tag
236                            0x33, 0x77, 0xAA, 0xFF,
237                            // num entries
238                            0x02, 0x00,
239                            // padding
240                            0x00, 0x00,
241                            // tag 1
242                            0x78, 0x56, 0x34, 0x12,
243                            // end offset 1
244                            0x06, 0x00, 0x00, 0x00,
245                            // tag 2
246                            0x79, 0x56, 0x34, 0x12,
247                            // end offset 2
248                            0x0b, 0x00, 0x00, 0x00,
249                            // value 1
250                            'a', 'b', 'c', 'd', 'e', 'f',
251                            // value 2
252                            'g', 'h', 'i', 'j', 'k'};
253 
254   EXPECT_TRUE(framer.ProcessInput(
255       absl::string_view(AsChars(input), ABSL_ARRAYSIZE(input))));
256   EXPECT_EQ(0u, framer.InputBytesRemaining());
257   EXPECT_EQ(0, visitor.error_count_);
258   ASSERT_EQ(1u, visitor.messages_.size());
259   const CryptoHandshakeMessage& message = visitor.messages_[0];
260   EXPECT_EQ(0xFFAA7733, message.tag());
261   EXPECT_EQ(2u, message.tag_value_map().size());
262   EXPECT_EQ("abcdef", crypto_test_utils::GetValueForTag(message, 0x12345678));
263   EXPECT_EQ("ghijk", crypto_test_utils::GetValueForTag(message, 0x12345679));
264 }
265 
TEST(CryptoFramerTest,ProcessInputWithThreeKeys)266 TEST(CryptoFramerTest, ProcessInputWithThreeKeys) {
267   test::TestCryptoVisitor visitor;
268   CryptoFramer framer;
269   framer.set_visitor(&visitor);
270 
271   unsigned char input[] = {// tag
272                            0x33, 0x77, 0xAA, 0xFF,
273                            // num entries
274                            0x03, 0x00,
275                            // padding
276                            0x00, 0x00,
277                            // tag 1
278                            0x78, 0x56, 0x34, 0x12,
279                            // end offset 1
280                            0x06, 0x00, 0x00, 0x00,
281                            // tag 2
282                            0x79, 0x56, 0x34, 0x12,
283                            // end offset 2
284                            0x0b, 0x00, 0x00, 0x00,
285                            // tag 3
286                            0x7A, 0x56, 0x34, 0x12,
287                            // end offset 3
288                            0x12, 0x00, 0x00, 0x00,
289                            // value 1
290                            'a', 'b', 'c', 'd', 'e', 'f',
291                            // value 2
292                            'g', 'h', 'i', 'j', 'k',
293                            // value 3
294                            'l', 'm', 'n', 'o', 'p', 'q', 'r'};
295 
296   EXPECT_TRUE(framer.ProcessInput(
297       absl::string_view(AsChars(input), ABSL_ARRAYSIZE(input))));
298   EXPECT_EQ(0u, framer.InputBytesRemaining());
299   EXPECT_EQ(0, visitor.error_count_);
300   ASSERT_EQ(1u, visitor.messages_.size());
301   const CryptoHandshakeMessage& message = visitor.messages_[0];
302   EXPECT_EQ(0xFFAA7733, message.tag());
303   EXPECT_EQ(3u, message.tag_value_map().size());
304   EXPECT_EQ("abcdef", crypto_test_utils::GetValueForTag(message, 0x12345678));
305   EXPECT_EQ("ghijk", crypto_test_utils::GetValueForTag(message, 0x12345679));
306   EXPECT_EQ("lmnopqr", crypto_test_utils::GetValueForTag(message, 0x1234567A));
307 }
308 
TEST(CryptoFramerTest,ProcessInputIncrementally)309 TEST(CryptoFramerTest, ProcessInputIncrementally) {
310   test::TestCryptoVisitor visitor;
311   CryptoFramer framer;
312   framer.set_visitor(&visitor);
313 
314   unsigned char input[] = {// tag
315                            0x33, 0x77, 0xAA, 0xFF,
316                            // num entries
317                            0x02, 0x00,
318                            // padding
319                            0x00, 0x00,
320                            // tag 1
321                            0x78, 0x56, 0x34, 0x12,
322                            // end offset 1
323                            0x06, 0x00, 0x00, 0x00,
324                            // tag 2
325                            0x79, 0x56, 0x34, 0x12,
326                            // end offset 2
327                            0x0b, 0x00, 0x00, 0x00,
328                            // value 1
329                            'a', 'b', 'c', 'd', 'e', 'f',
330                            // value 2
331                            'g', 'h', 'i', 'j', 'k'};
332 
333   for (size_t i = 0; i < ABSL_ARRAYSIZE(input); i++) {
334     EXPECT_TRUE(framer.ProcessInput(absl::string_view(AsChars(input) + i, 1)));
335   }
336   EXPECT_EQ(0u, framer.InputBytesRemaining());
337   ASSERT_EQ(1u, visitor.messages_.size());
338   const CryptoHandshakeMessage& message = visitor.messages_[0];
339   EXPECT_EQ(0xFFAA7733, message.tag());
340   EXPECT_EQ(2u, message.tag_value_map().size());
341   EXPECT_EQ("abcdef", crypto_test_utils::GetValueForTag(message, 0x12345678));
342   EXPECT_EQ("ghijk", crypto_test_utils::GetValueForTag(message, 0x12345679));
343 }
344 
TEST(CryptoFramerTest,ProcessInputTagsOutOfOrder)345 TEST(CryptoFramerTest, ProcessInputTagsOutOfOrder) {
346   test::TestCryptoVisitor visitor;
347   CryptoFramer framer;
348   framer.set_visitor(&visitor);
349 
350   unsigned char input[] = {// tag
351                            0x33, 0x77, 0xAA, 0xFF,
352                            // num entries
353                            0x02, 0x00,
354                            // padding
355                            0x00, 0x00,
356                            // tag 1
357                            0x78, 0x56, 0x34, 0x13,
358                            // end offset 1
359                            0x01, 0x00, 0x00, 0x00,
360                            // tag 2
361                            0x79, 0x56, 0x34, 0x12,
362                            // end offset 2
363                            0x02, 0x00, 0x00, 0x00};
364 
365   EXPECT_FALSE(framer.ProcessInput(
366       absl::string_view(AsChars(input), ABSL_ARRAYSIZE(input))));
367   EXPECT_THAT(framer.error(), IsError(QUIC_CRYPTO_TAGS_OUT_OF_ORDER));
368   EXPECT_EQ(1, visitor.error_count_);
369 }
370 
TEST(CryptoFramerTest,ProcessEndOffsetsOutOfOrder)371 TEST(CryptoFramerTest, ProcessEndOffsetsOutOfOrder) {
372   test::TestCryptoVisitor visitor;
373   CryptoFramer framer;
374   framer.set_visitor(&visitor);
375 
376   unsigned char input[] = {// tag
377                            0x33, 0x77, 0xAA, 0xFF,
378                            // num entries
379                            0x02, 0x00,
380                            // padding
381                            0x00, 0x00,
382                            // tag 1
383                            0x79, 0x56, 0x34, 0x12,
384                            // end offset 1
385                            0x01, 0x00, 0x00, 0x00,
386                            // tag 2
387                            0x78, 0x56, 0x34, 0x13,
388                            // end offset 2
389                            0x00, 0x00, 0x00, 0x00};
390 
391   EXPECT_FALSE(framer.ProcessInput(
392       absl::string_view(AsChars(input), ABSL_ARRAYSIZE(input))));
393   EXPECT_THAT(framer.error(), IsError(QUIC_CRYPTO_TAGS_OUT_OF_ORDER));
394   EXPECT_EQ(1, visitor.error_count_);
395 }
396 
TEST(CryptoFramerTest,ProcessInputTooManyEntries)397 TEST(CryptoFramerTest, ProcessInputTooManyEntries) {
398   test::TestCryptoVisitor visitor;
399   CryptoFramer framer;
400   framer.set_visitor(&visitor);
401 
402   unsigned char input[] = {// tag
403                            0x33, 0x77, 0xAA, 0xFF,
404                            // num entries
405                            0xA0, 0x00,
406                            // padding
407                            0x00, 0x00};
408 
409   EXPECT_FALSE(framer.ProcessInput(
410       absl::string_view(AsChars(input), ABSL_ARRAYSIZE(input))));
411   EXPECT_THAT(framer.error(), IsError(QUIC_CRYPTO_TOO_MANY_ENTRIES));
412   EXPECT_EQ(1, visitor.error_count_);
413 }
414 
TEST(CryptoFramerTest,ProcessInputZeroLength)415 TEST(CryptoFramerTest, ProcessInputZeroLength) {
416   test::TestCryptoVisitor visitor;
417   CryptoFramer framer;
418   framer.set_visitor(&visitor);
419 
420   unsigned char input[] = {// tag
421                            0x33, 0x77, 0xAA, 0xFF,
422                            // num entries
423                            0x02, 0x00,
424                            // padding
425                            0x00, 0x00,
426                            // tag 1
427                            0x78, 0x56, 0x34, 0x12,
428                            // end offset 1
429                            0x00, 0x00, 0x00, 0x00,
430                            // tag 2
431                            0x79, 0x56, 0x34, 0x12,
432                            // end offset 2
433                            0x05, 0x00, 0x00, 0x00};
434 
435   EXPECT_TRUE(framer.ProcessInput(
436       absl::string_view(AsChars(input), ABSL_ARRAYSIZE(input))));
437   EXPECT_EQ(0, visitor.error_count_);
438 }
439 
440 }  // namespace
441 }  // namespace test
442 }  // namespace quic
443