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