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