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