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 "net/quic/test_tools/crypto_test_utils.h" 6 7 #include "net/quic/crypto/channel_id.h" 8 #include "net/quic/crypto/common_cert_set.h" 9 #include "net/quic/crypto/crypto_handshake.h" 10 #include "net/quic/crypto/quic_crypto_server_config.h" 11 #include "net/quic/crypto/quic_decrypter.h" 12 #include "net/quic/crypto/quic_encrypter.h" 13 #include "net/quic/crypto/quic_random.h" 14 #include "net/quic/quic_clock.h" 15 #include "net/quic/quic_crypto_client_stream.h" 16 #include "net/quic/quic_crypto_server_stream.h" 17 #include "net/quic/quic_crypto_stream.h" 18 #include "net/quic/test_tools/quic_connection_peer.h" 19 #include "net/quic/test_tools/quic_test_utils.h" 20 #include "net/quic/test_tools/simple_quic_framer.h" 21 22 using base::StringPiece; 23 using std::make_pair; 24 using std::pair; 25 using std::string; 26 using std::vector; 27 28 namespace net { 29 namespace test { 30 31 namespace { 32 33 // CryptoFramerVisitor is a framer visitor that records handshake messages. 34 class CryptoFramerVisitor : public CryptoFramerVisitorInterface { 35 public: 36 CryptoFramerVisitor() 37 : error_(false) { 38 } 39 40 virtual void OnError(CryptoFramer* framer) OVERRIDE { 41 error_ = true; 42 } 43 44 virtual void OnHandshakeMessage( 45 const CryptoHandshakeMessage& message) OVERRIDE { 46 messages_.push_back(message); 47 } 48 49 bool error() const { 50 return error_; 51 } 52 53 const vector<CryptoHandshakeMessage>& messages() const { 54 return messages_; 55 } 56 57 private: 58 bool error_; 59 vector<CryptoHandshakeMessage> messages_; 60 }; 61 62 // MovePackets parses crypto handshake messages from packet number 63 // |*inout_packet_index| through to the last packet and has |dest_stream| 64 // process them. |*inout_packet_index| is updated with an index one greater 65 // than the last packet processed. 66 void MovePackets(PacketSavingConnection* source_conn, 67 size_t *inout_packet_index, 68 QuicCryptoStream* dest_stream, 69 PacketSavingConnection* dest_conn) { 70 SimpleQuicFramer framer; 71 CryptoFramer crypto_framer; 72 CryptoFramerVisitor crypto_visitor; 73 74 // In order to properly test the code we need to perform encryption and 75 // decryption so that the crypters latch when expected. The crypters are in 76 // |dest_conn|, but we don't want to try and use them there. Instead we swap 77 // them into |framer|, perform the decryption with them, and then swap them 78 // back. 79 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer()); 80 81 crypto_framer.set_visitor(&crypto_visitor); 82 83 size_t index = *inout_packet_index; 84 for (; index < source_conn->encrypted_packets_.size(); index++) { 85 ASSERT_TRUE(framer.ProcessPacket(*source_conn->encrypted_packets_[index])); 86 for (vector<QuicStreamFrame>::const_iterator 87 i = framer.stream_frames().begin(); 88 i != framer.stream_frames().end(); ++i) { 89 scoped_ptr<string> frame_data(i->GetDataAsString()); 90 ASSERT_TRUE(crypto_framer.ProcessInput(*frame_data)); 91 ASSERT_FALSE(crypto_visitor.error()); 92 } 93 } 94 *inout_packet_index = index; 95 96 QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer()); 97 98 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining()); 99 100 for (vector<CryptoHandshakeMessage>::const_iterator 101 i = crypto_visitor.messages().begin(); 102 i != crypto_visitor.messages().end(); ++i) { 103 dest_stream->OnHandshakeMessage(*i); 104 } 105 } 106 107 // HexChar parses |c| as a hex character. If valid, it sets |*value| to the 108 // value of the hex character and returns true. Otherwise it returns false. 109 bool HexChar(char c, uint8* value) { 110 if (c >= '0' && c <= '9') { 111 *value = c - '0'; 112 return true; 113 } 114 if (c >= 'a' && c <= 'f') { 115 *value = c - 'a' + 10; 116 return true; 117 } 118 if (c >= 'A' && c <= 'F') { 119 *value = c - 'A' + 10; 120 return true; 121 } 122 return false; 123 } 124 125 } // anonymous namespace 126 127 CryptoTestUtils::FakeClientOptions::FakeClientOptions() 128 : dont_verify_certs(false), 129 channel_id_enabled(false) { 130 } 131 132 // static 133 int CryptoTestUtils::HandshakeWithFakeServer( 134 PacketSavingConnection* client_conn, 135 QuicCryptoClientStream* client) { 136 PacketSavingConnection* server_conn = new PacketSavingConnection(true); 137 TestSession server_session(server_conn, DefaultQuicConfig()); 138 139 QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING, 140 QuicRandom::GetInstance()); 141 SetupCryptoServerConfigForTest( 142 server_session.connection()->clock(), 143 server_session.connection()->random_generator(), 144 server_session.config(), &crypto_config); 145 146 QuicCryptoServerStream server(crypto_config, &server_session); 147 server_session.SetCryptoStream(&server); 148 149 // The client's handshake must have been started already. 150 CHECK_NE(0u, client_conn->packets_.size()); 151 152 CommunicateHandshakeMessages(client_conn, client, server_conn, &server); 153 154 CompareClientAndServerKeys(client, &server); 155 156 return client->num_sent_client_hellos(); 157 } 158 159 // static 160 int CryptoTestUtils::HandshakeWithFakeClient( 161 PacketSavingConnection* server_conn, 162 QuicCryptoServerStream* server, 163 const FakeClientOptions& options) { 164 PacketSavingConnection* client_conn = new PacketSavingConnection(false); 165 TestSession client_session(client_conn, DefaultQuicConfig()); 166 QuicCryptoClientConfig crypto_config; 167 168 client_session.config()->SetDefaults(); 169 crypto_config.SetDefaults(); 170 // TODO(rtenneti): Enable testing of ProofVerifier. 171 // if (!options.dont_verify_certs) { 172 // crypto_config.SetProofVerifier(ProofVerifierForTesting()); 173 // } 174 if (options.channel_id_enabled) { 175 crypto_config.SetChannelIDSigner(ChannelIDSignerForTesting()); 176 } 177 QuicCryptoClientStream client("test.example.com", &client_session, 178 &crypto_config); 179 client_session.SetCryptoStream(&client); 180 181 CHECK(client.CryptoConnect()); 182 CHECK_EQ(1u, client_conn->packets_.size()); 183 184 CommunicateHandshakeMessages(client_conn, &client, server_conn, server); 185 186 CompareClientAndServerKeys(&client, server); 187 188 if (options.channel_id_enabled) { 189 EXPECT_EQ(crypto_config.channel_id_signer()->GetKeyForHostname( 190 "test.example.com"), 191 server->crypto_negotiated_params().channel_id); 192 } 193 194 return client.num_sent_client_hellos(); 195 } 196 197 // static 198 void CryptoTestUtils::SetupCryptoServerConfigForTest( 199 const QuicClock* clock, 200 QuicRandom* rand, 201 QuicConfig* config, 202 QuicCryptoServerConfig* crypto_config) { 203 config->SetDefaults(); 204 QuicCryptoServerConfig::ConfigOptions options; 205 options.channel_id_enabled = true; 206 scoped_ptr<CryptoHandshakeMessage> scfg( 207 crypto_config->AddDefaultConfig(rand, clock, options)); 208 } 209 210 // static 211 void CryptoTestUtils::CommunicateHandshakeMessages( 212 PacketSavingConnection* a_conn, 213 QuicCryptoStream* a, 214 PacketSavingConnection* b_conn, 215 QuicCryptoStream* b) { 216 size_t a_i = 0, b_i = 0; 217 while (!a->handshake_confirmed()) { 218 ASSERT_GT(a_conn->packets_.size(), a_i); 219 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i 220 << " packets a->b"; 221 MovePackets(a_conn, &a_i, b, b_conn); 222 223 ASSERT_GT(b_conn->packets_.size(), b_i); 224 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i 225 << " packets b->a"; 226 if (b_conn->packets_.size() - b_i == 2) { 227 LOG(INFO) << "here"; 228 } 229 MovePackets(b_conn, &b_i, a, a_conn); 230 } 231 } 232 233 pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake( 234 PacketSavingConnection* a_conn, 235 QuicCryptoStream* a, 236 size_t a_i, 237 PacketSavingConnection* b_conn, 238 QuicCryptoStream* b, 239 size_t b_i) { 240 LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i 241 << " packets a->b"; 242 MovePackets(a_conn, &a_i, b, b_conn); 243 244 LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i 245 << " packets b->a"; 246 if (b_conn->packets_.size() - b_i == 2) { 247 LOG(INFO) << "here"; 248 } 249 MovePackets(b_conn, &b_i, a, a_conn); 250 251 return make_pair(a_i, b_i); 252 } 253 254 // static 255 string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message, 256 QuicTag tag) { 257 QuicTagValueMap::const_iterator it = message.tag_value_map().find(tag); 258 if (it == message.tag_value_map().end()) { 259 return string(); 260 } 261 return it->second; 262 } 263 264 class MockCommonCertSets : public CommonCertSets { 265 public: 266 MockCommonCertSets(StringPiece cert, uint64 hash, uint32 index) 267 : cert_(cert.as_string()), 268 hash_(hash), 269 index_(index) { 270 } 271 272 virtual StringPiece GetCommonHashes() const OVERRIDE { 273 CHECK(false) << "not implemented"; 274 return StringPiece(); 275 } 276 277 virtual StringPiece GetCert(uint64 hash, uint32 index) const OVERRIDE { 278 if (hash == hash_ && index == index_) { 279 return cert_; 280 } 281 return StringPiece(); 282 } 283 284 virtual bool MatchCert(StringPiece cert, 285 StringPiece common_set_hashes, 286 uint64* out_hash, 287 uint32* out_index) const OVERRIDE { 288 if (cert != cert_) { 289 return false; 290 } 291 292 if (common_set_hashes.size() % sizeof(uint64) != 0) { 293 return false; 294 } 295 bool client_has_set = false; 296 for (size_t i = 0; i < common_set_hashes.size(); i += sizeof(uint64)) { 297 uint64 hash; 298 memcpy(&hash, common_set_hashes.data() + i, sizeof(hash)); 299 if (hash == hash_) { 300 client_has_set = true; 301 break; 302 } 303 } 304 305 if (!client_has_set) { 306 return false; 307 } 308 309 *out_hash = hash_; 310 *out_index = index_; 311 return true; 312 } 313 314 private: 315 const string cert_; 316 const uint64 hash_; 317 const uint32 index_; 318 }; 319 320 CommonCertSets* CryptoTestUtils::MockCommonCertSets(StringPiece cert, 321 uint64 hash, 322 uint32 index) { 323 return new class MockCommonCertSets(cert, hash, index); 324 } 325 326 void CryptoTestUtils::CompareClientAndServerKeys( 327 QuicCryptoClientStream* client, 328 QuicCryptoServerStream* server) { 329 const QuicEncrypter* client_encrypter( 330 client->session()->connection()->encrypter(ENCRYPTION_INITIAL)); 331 const QuicDecrypter* client_decrypter( 332 client->session()->connection()->decrypter()); 333 const QuicEncrypter* client_forward_secure_encrypter( 334 client->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE)); 335 const QuicDecrypter* client_forward_secure_decrypter( 336 client->session()->connection()->alternative_decrypter()); 337 const QuicEncrypter* server_encrypter( 338 server->session()->connection()->encrypter(ENCRYPTION_INITIAL)); 339 const QuicDecrypter* server_decrypter( 340 server->session()->connection()->decrypter()); 341 const QuicEncrypter* server_forward_secure_encrypter( 342 server->session()->connection()->encrypter(ENCRYPTION_FORWARD_SECURE)); 343 const QuicDecrypter* server_forward_secure_decrypter( 344 server->session()->connection()->alternative_decrypter()); 345 346 StringPiece client_encrypter_key = client_encrypter->GetKey(); 347 StringPiece client_encrypter_iv = client_encrypter->GetNoncePrefix(); 348 StringPiece client_decrypter_key = client_decrypter->GetKey(); 349 StringPiece client_decrypter_iv = client_decrypter->GetNoncePrefix(); 350 StringPiece client_forward_secure_encrypter_key = 351 client_forward_secure_encrypter->GetKey(); 352 StringPiece client_forward_secure_encrypter_iv = 353 client_forward_secure_encrypter->GetNoncePrefix(); 354 StringPiece client_forward_secure_decrypter_key = 355 client_forward_secure_decrypter->GetKey(); 356 StringPiece client_forward_secure_decrypter_iv = 357 client_forward_secure_decrypter->GetNoncePrefix(); 358 StringPiece server_encrypter_key = server_encrypter->GetKey(); 359 StringPiece server_encrypter_iv = server_encrypter->GetNoncePrefix(); 360 StringPiece server_decrypter_key = server_decrypter->GetKey(); 361 StringPiece server_decrypter_iv = server_decrypter->GetNoncePrefix(); 362 StringPiece server_forward_secure_encrypter_key = 363 server_forward_secure_encrypter->GetKey(); 364 StringPiece server_forward_secure_encrypter_iv = 365 server_forward_secure_encrypter->GetNoncePrefix(); 366 StringPiece server_forward_secure_decrypter_key = 367 server_forward_secure_decrypter->GetKey(); 368 StringPiece server_forward_secure_decrypter_iv = 369 server_forward_secure_decrypter->GetNoncePrefix(); 370 371 CompareCharArraysWithHexError("client write key", 372 client_encrypter_key.data(), 373 client_encrypter_key.length(), 374 server_decrypter_key.data(), 375 server_decrypter_key.length()); 376 CompareCharArraysWithHexError("client write IV", 377 client_encrypter_iv.data(), 378 client_encrypter_iv.length(), 379 server_decrypter_iv.data(), 380 server_decrypter_iv.length()); 381 CompareCharArraysWithHexError("server write key", 382 server_encrypter_key.data(), 383 server_encrypter_key.length(), 384 client_decrypter_key.data(), 385 client_decrypter_key.length()); 386 CompareCharArraysWithHexError("server write IV", 387 server_encrypter_iv.data(), 388 server_encrypter_iv.length(), 389 client_decrypter_iv.data(), 390 client_decrypter_iv.length()); 391 CompareCharArraysWithHexError("client forward secure write key", 392 client_forward_secure_encrypter_key.data(), 393 client_forward_secure_encrypter_key.length(), 394 server_forward_secure_decrypter_key.data(), 395 server_forward_secure_decrypter_key.length()); 396 CompareCharArraysWithHexError("client forward secure write IV", 397 client_forward_secure_encrypter_iv.data(), 398 client_forward_secure_encrypter_iv.length(), 399 server_forward_secure_decrypter_iv.data(), 400 server_forward_secure_decrypter_iv.length()); 401 CompareCharArraysWithHexError("server forward secure write key", 402 server_forward_secure_encrypter_key.data(), 403 server_forward_secure_encrypter_key.length(), 404 client_forward_secure_decrypter_key.data(), 405 client_forward_secure_decrypter_key.length()); 406 CompareCharArraysWithHexError("server forward secure write IV", 407 server_forward_secure_encrypter_iv.data(), 408 server_forward_secure_encrypter_iv.length(), 409 client_forward_secure_decrypter_iv.data(), 410 client_forward_secure_decrypter_iv.length()); 411 } 412 413 // static 414 QuicTag CryptoTestUtils::ParseTag(const char* tagstr) { 415 const size_t len = strlen(tagstr); 416 CHECK_NE(0u, len); 417 418 QuicTag tag = 0; 419 420 if (tagstr[0] == '#') { 421 CHECK_EQ(static_cast<size_t>(1 + 2*4), len); 422 tagstr++; 423 424 for (size_t i = 0; i < 8; i++) { 425 tag <<= 4; 426 427 uint8 v = 0; 428 CHECK(HexChar(tagstr[i], &v)); 429 tag |= v; 430 } 431 432 return tag; 433 } 434 435 CHECK_LE(len, 4u); 436 for (size_t i = 0; i < 4; i++) { 437 tag >>= 8; 438 if (i < len) { 439 tag |= static_cast<uint32>(tagstr[i]) << 24; 440 } 441 } 442 443 return tag; 444 } 445 446 // static 447 CryptoHandshakeMessage CryptoTestUtils::Message(const char* message_tag, ...) { 448 va_list ap; 449 va_start(ap, message_tag); 450 451 CryptoHandshakeMessage message = BuildMessage(message_tag, ap); 452 va_end(ap); 453 return message; 454 } 455 456 // static 457 CryptoHandshakeMessage CryptoTestUtils::BuildMessage(const char* message_tag, 458 va_list ap) { 459 CryptoHandshakeMessage msg; 460 msg.set_tag(ParseTag(message_tag)); 461 462 for (;;) { 463 const char* tagstr = va_arg(ap, const char*); 464 if (tagstr == NULL) { 465 break; 466 } 467 468 if (tagstr[0] == '$') { 469 // Special value. 470 const char* const special = tagstr + 1; 471 if (strcmp(special, "padding") == 0) { 472 const int min_bytes = va_arg(ap, int); 473 msg.set_minimum_size(min_bytes); 474 } else { 475 CHECK(false) << "Unknown special value: " << special; 476 } 477 478 continue; 479 } 480 481 const QuicTag tag = ParseTag(tagstr); 482 const char* valuestr = va_arg(ap, const char*); 483 484 size_t len = strlen(valuestr); 485 if (len > 0 && valuestr[0] == '#') { 486 valuestr++; 487 len--; 488 489 CHECK(len % 2 == 0); 490 scoped_ptr<uint8[]> buf(new uint8[len/2]); 491 492 for (size_t i = 0; i < len/2; i++) { 493 uint8 v = 0; 494 CHECK(HexChar(valuestr[i*2], &v)); 495 buf[i] = v << 4; 496 CHECK(HexChar(valuestr[i*2 + 1], &v)); 497 buf[i] |= v; 498 } 499 500 msg.SetStringPiece( 501 tag, StringPiece(reinterpret_cast<char*>(buf.get()), len/2)); 502 continue; 503 } 504 505 msg.SetStringPiece(tag, valuestr); 506 } 507 508 // The CryptoHandshakeMessage needs to be serialized and parsed to ensure 509 // that any padding is included. 510 scoped_ptr<QuicData> bytes(CryptoFramer::ConstructHandshakeMessage(msg)); 511 scoped_ptr<CryptoHandshakeMessage> parsed( 512 CryptoFramer::ParseMessage(bytes->AsStringPiece())); 513 CHECK(parsed.get()); 514 515 return *parsed; 516 } 517 518 } // namespace test 519 } // namespace net 520