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