| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/crypto/crypto_handshake.h" | 5 #include "net/quic/crypto/crypto_handshake.h" |
| 6 | 6 |
| 7 #include <ctype.h> | 7 #include <ctype.h> |
| 8 | 8 |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
| 13 #include "crypto/hkdf.h" | 13 #include "crypto/hkdf.h" |
| 14 #include "crypto/secure_hash.h" | 14 #include "crypto/secure_hash.h" |
| 15 #include "net/base/net_util.h" | 15 #include "net/base/net_util.h" |
| 16 #include "net/quic/crypto/aes_128_gcm_decrypter.h" | 16 #include "net/quic/crypto/aes_128_gcm_decrypter.h" |
| 17 #include "net/quic/crypto/aes_128_gcm_encrypter.h" | 17 #include "net/quic/crypto/aes_128_gcm_encrypter.h" |
| 18 #include "net/quic/crypto/crypto_framer.h" | 18 #include "net/quic/crypto/crypto_framer.h" |
| 19 #include "net/quic/crypto/crypto_utils.h" | 19 #include "net/quic/crypto/crypto_utils.h" |
| 20 #include "net/quic/crypto/curve25519_key_exchange.h" | 20 #include "net/quic/crypto/curve25519_key_exchange.h" |
| 21 #include "net/quic/crypto/key_exchange.h" | 21 #include "net/quic/crypto/key_exchange.h" |
| 22 #include "net/quic/crypto/p256_key_exchange.h" | 22 #include "net/quic/crypto/p256_key_exchange.h" |
| 23 #include "net/quic/crypto/quic_decrypter.h" | 23 #include "net/quic/crypto/quic_decrypter.h" |
| 24 #include "net/quic/crypto/quic_encrypter.h" | 24 #include "net/quic/crypto/quic_encrypter.h" |
| 25 #include "net/quic/crypto/quic_random.h" | 25 #include "net/quic/crypto/quic_random.h" |
| 26 #include "net/quic/crypto/strike_register.h" |
| 27 #include "net/quic/quic_clock.h" |
| 26 #include "net/quic/quic_protocol.h" | 28 #include "net/quic/quic_protocol.h" |
| 27 | 29 |
| 28 using base::StringPiece; | 30 using base::StringPiece; |
| 29 using crypto::SecureHash; | 31 using crypto::SecureHash; |
| 30 using std::map; | 32 using std::map; |
| 31 using std::string; | 33 using std::string; |
| 32 using std::vector; | 34 using std::vector; |
| 33 | 35 |
| 34 namespace net { | 36 namespace net { |
| 35 | 37 |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 const string& QuicCryptoClientConfig::CachedState::server_config() | 414 const string& QuicCryptoClientConfig::CachedState::server_config() |
| 413 const { | 415 const { |
| 414 return server_config_; | 416 return server_config_; |
| 415 } | 417 } |
| 416 | 418 |
| 417 const string& QuicCryptoClientConfig::CachedState::source_address_token() | 419 const string& QuicCryptoClientConfig::CachedState::source_address_token() |
| 418 const { | 420 const { |
| 419 return source_address_token_; | 421 return source_address_token_; |
| 420 } | 422 } |
| 421 | 423 |
| 422 const string& QuicCryptoClientConfig::CachedState::orbit() const { | |
| 423 return orbit_; | |
| 424 } | |
| 425 | |
| 426 void QuicCryptoClientConfig::CachedState::set_source_address_token( | 424 void QuicCryptoClientConfig::CachedState::set_source_address_token( |
| 427 StringPiece token) { | 425 StringPiece token) { |
| 428 source_address_token_ = token.as_string(); | 426 source_address_token_ = token.as_string(); |
| 429 } | 427 } |
| 430 | 428 |
| 431 void QuicCryptoClientConfig::SetDefaults() { | 429 void QuicCryptoClientConfig::SetDefaults() { |
| 432 // Version must be 0. | 430 // Version must be 0. |
| 433 version = kVersion; | 431 version = kVersion; |
| 434 | 432 |
| 435 // Key exchange methods. | 433 // Key exchange methods. |
| 436 kexs.resize(2); | 434 kexs.resize(2); |
| 437 kexs[0] = kC255; | 435 kexs[0] = kC255; |
| 438 kexs[1] = kP256; | 436 kexs[1] = kP256; |
| 439 | 437 |
| 440 // Authenticated encryption algorithms. | 438 // Authenticated encryption algorithms. |
| 441 aead.resize(1); | 439 aead.resize(1); |
| 442 aead[0] = kAESG; | 440 aead[0] = kAESG; |
| 443 } | 441 } |
| 444 | 442 |
| 445 const QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::Lookup( | 443 const QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::Lookup( |
| 446 const string& server_hostname) { | 444 const string& server_hostname) const { |
| 447 map<string, CachedState*>::const_iterator it = | 445 map<string, CachedState*>::const_iterator it = |
| 448 cached_states_.find(server_hostname); | 446 cached_states_.find(server_hostname); |
| 449 if (it == cached_states_.end()) { | 447 if (it == cached_states_.end()) { |
| 450 return NULL; | 448 return NULL; |
| 451 } | 449 } |
| 452 return it->second; | 450 return it->second; |
| 453 } | 451 } |
| 454 | 452 |
| 455 void QuicCryptoClientConfig::FillInchoateClientHello( | 453 void QuicCryptoClientConfig::FillInchoateClientHello( |
| 456 const string& server_hostname, | 454 const string& server_hostname, |
| 457 const CachedState* cached, | 455 const CachedState* cached, |
| 458 CryptoHandshakeMessage* out) { | 456 CryptoHandshakeMessage* out) const { |
| 459 out->set_tag(kCHLO); | 457 out->set_tag(kCHLO); |
| 460 | 458 |
| 461 // Server name indication. | 459 // Server name indication. |
| 462 // If server_hostname is not an IP address literal, it is a DNS hostname. | 460 // If server_hostname is not an IP address literal, it is a DNS hostname. |
| 463 IPAddressNumber ip; | 461 IPAddressNumber ip; |
| 464 if (!server_hostname.empty() && | 462 if (!server_hostname.empty() && |
| 465 !ParseIPLiteralToNumber(server_hostname, &ip)) { | 463 !ParseIPLiteralToNumber(server_hostname, &ip)) { |
| 466 out->SetStringPiece(kSNI, server_hostname); | 464 out->SetStringPiece(kSNI, server_hostname); |
| 467 } | 465 } |
| 468 out->SetValue(kVERS, version); | 466 out->SetValue(kVERS, version); |
| 469 | 467 |
| 470 if (cached && !cached->source_address_token().empty()) { | 468 if (cached && !cached->source_address_token().empty()) { |
| 471 out->SetStringPiece(kSRCT, cached->source_address_token()); | 469 out->SetStringPiece(kSRCT, cached->source_address_token()); |
| 472 } | 470 } |
| 473 } | 471 } |
| 474 | 472 |
| 475 QuicErrorCode QuicCryptoClientConfig::FillClientHello( | 473 QuicErrorCode QuicCryptoClientConfig::FillClientHello( |
| 476 const string& server_hostname, | 474 const string& server_hostname, |
| 477 QuicGuid guid, | 475 QuicGuid guid, |
| 478 const CachedState* cached, | 476 const CachedState* cached, |
| 479 const QuicClock* clock, | 477 const QuicClock* clock, |
| 480 QuicRandom* rand, | 478 QuicRandom* rand, |
| 481 QuicCryptoNegotiatedParameters* out_params, | 479 QuicCryptoNegotiatedParameters* out_params, |
| 482 CryptoHandshakeMessage* out, | 480 CryptoHandshakeMessage* out, |
| 483 string* error_details) { | 481 string* error_details) const { |
| 484 FillInchoateClientHello(server_hostname, cached, out); | 482 FillInchoateClientHello(server_hostname, cached, out); |
| 485 | 483 |
| 486 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); | 484 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); |
| 487 if (!scfg) { | 485 if (!scfg) { |
| 488 // This should never happen as our caller should have checked | 486 // This should never happen as our caller should have checked |
| 489 // cached->is_complete() before calling this function. | 487 // cached->is_complete() before calling this function. |
| 490 if (error_details) { | 488 if (error_details) { |
| 491 *error_details = "Handshake not ready"; | 489 *error_details = "Handshake not ready"; |
| 492 } | 490 } |
| 493 return QUIC_CRYPTO_INTERNAL_ERROR; | 491 return QUIC_CRYPTO_INTERNAL_ERROR; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 | 543 |
| 546 StringPiece public_value; | 544 StringPiece public_value; |
| 547 if (scfg->GetNthValue16(kPUBS, key_exchange_index, &public_value) != | 545 if (scfg->GetNthValue16(kPUBS, key_exchange_index, &public_value) != |
| 548 QUIC_NO_ERROR) { | 546 QUIC_NO_ERROR) { |
| 549 if (error_details) { | 547 if (error_details) { |
| 550 *error_details = "Missing public value"; | 548 *error_details = "Missing public value"; |
| 551 } | 549 } |
| 552 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 550 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 553 } | 551 } |
| 554 | 552 |
| 553 StringPiece orbit; |
| 554 if (!scfg->GetStringPiece(kORBT, &orbit) || |
| 555 orbit.size() != kOrbitSize) { |
| 556 if (error_details) { |
| 557 *error_details = "SCFG missing OBIT"; |
| 558 } |
| 559 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; |
| 560 } |
| 561 |
| 555 string nonce; | 562 string nonce; |
| 556 CryptoUtils::GenerateNonce(clock, rand, cached->orbit(), &nonce); | 563 CryptoUtils::GenerateNonce(clock->NowAsDeltaSinceUnixEpoch(), rand, orbit, |
| 564 &nonce); |
| 557 out->SetStringPiece(kNONC, nonce); | 565 out->SetStringPiece(kNONC, nonce); |
| 558 | 566 |
| 559 scoped_ptr<KeyExchange> key_exchange; | 567 scoped_ptr<KeyExchange> key_exchange; |
| 560 switch (out_params->key_exchange) { | 568 switch (out_params->key_exchange) { |
| 561 case kC255: | 569 case kC255: |
| 562 key_exchange.reset(Curve25519KeyExchange::New( | 570 key_exchange.reset(Curve25519KeyExchange::New( |
| 563 Curve25519KeyExchange::NewPrivateKey(rand))); | 571 Curve25519KeyExchange::NewPrivateKey(rand))); |
| 564 break; | 572 break; |
| 565 case kP256: | 573 case kP256: |
| 566 key_exchange.reset(P256KeyExchange::New( | 574 key_exchange.reset(P256KeyExchange::New( |
| (...skipping 25 matching lines...) Expand all Loading... |
| 592 hkdf_input.append(cached->server_config()); | 600 hkdf_input.append(cached->server_config()); |
| 593 | 601 |
| 594 CryptoUtils::DeriveKeys(out_params, nonce, hkdf_input, CryptoUtils::CLIENT); | 602 CryptoUtils::DeriveKeys(out_params, nonce, hkdf_input, CryptoUtils::CLIENT); |
| 595 | 603 |
| 596 return QUIC_NO_ERROR; | 604 return QUIC_NO_ERROR; |
| 597 } | 605 } |
| 598 | 606 |
| 599 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( | 607 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( |
| 600 const string& server_hostname, | 608 const string& server_hostname, |
| 601 const CryptoHandshakeMessage& rej, | 609 const CryptoHandshakeMessage& rej, |
| 610 QuicCryptoNegotiatedParameters* out_params, |
| 602 string* error_details) { | 611 string* error_details) { |
| 603 CachedState* cached; | 612 CachedState* cached; |
| 604 | 613 |
| 605 map<string, CachedState*>::const_iterator it = | 614 map<string, CachedState*>::const_iterator it = |
| 606 cached_states_.find(server_hostname); | 615 cached_states_.find(server_hostname); |
| 607 if (it == cached_states_.end()) { | 616 if (it == cached_states_.end()) { |
| 608 cached = new CachedState; | 617 cached = new CachedState; |
| 609 cached_states_[server_hostname] = cached; | 618 cached_states_[server_hostname] = cached; |
| 610 } else { | 619 } else { |
| 611 cached = it->second; | 620 cached = it->second; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 624 *error_details = "Invalid SCFG"; | 633 *error_details = "Invalid SCFG"; |
| 625 } | 634 } |
| 626 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 635 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 627 } | 636 } |
| 628 | 637 |
| 629 StringPiece token; | 638 StringPiece token; |
| 630 if (rej.GetStringPiece(kSRCT, &token)) { | 639 if (rej.GetStringPiece(kSRCT, &token)) { |
| 631 cached->set_source_address_token(token); | 640 cached->set_source_address_token(token); |
| 632 } | 641 } |
| 633 | 642 |
| 643 StringPiece nonce; |
| 644 if (rej.GetStringPiece(kNONC, &nonce) && |
| 645 nonce.size() == kNonceSize) { |
| 646 out_params->server_nonce = nonce.as_string(); |
| 647 } |
| 648 |
| 634 return QUIC_NO_ERROR; | 649 return QUIC_NO_ERROR; |
| 635 } | 650 } |
| 636 | 651 |
| 637 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( | 652 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( |
| 638 const CryptoHandshakeMessage& server_hello, | 653 const CryptoHandshakeMessage& server_hello, |
| 639 const string& nonce, | 654 const string& nonce, |
| 640 QuicCryptoNegotiatedParameters* out_params, | 655 QuicCryptoNegotiatedParameters* out_params, |
| 641 string* error_details) { | 656 string* error_details) { |
| 642 if (server_hello.tag() != kSHLO) { | 657 if (server_hello.tag() != kSHLO) { |
| 643 *error_details = "Bad tag"; | 658 *error_details = "Bad tag"; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 659 // AES-GCM is used to encrypt and authenticate source address tokens. The | 674 // AES-GCM is used to encrypt and authenticate source address tokens. The |
| 660 // full, 96-bit nonce is used but we must ensure that an attacker cannot | 675 // full, 96-bit nonce is used but we must ensure that an attacker cannot |
| 661 // obtain two source address tokens with the same nonce. This occurs with | 676 // obtain two source address tokens with the same nonce. This occurs with |
| 662 // probability 0.5 after 2**48 values. We assume that obtaining 2**48 | 677 // probability 0.5 after 2**48 values. We assume that obtaining 2**48 |
| 663 // source address tokens is not possible: at a rate of 10M packets per | 678 // source address tokens is not possible: at a rate of 10M packets per |
| 664 // second, it would still take the attacker a year to obtain the needed | 679 // second, it would still take the attacker a year to obtain the needed |
| 665 // number of packets. | 680 // number of packets. |
| 666 // | 681 // |
| 667 // TODO(agl): switch to an encrypter with a larger nonce space (i.e. | 682 // TODO(agl): switch to an encrypter with a larger nonce space (i.e. |
| 668 // Salsa20+Poly1305). | 683 // Salsa20+Poly1305). |
| 669 : source_address_token_encrypter_(new Aes128GcmEncrypter), | 684 : strike_register_lock_(), |
| 685 source_address_token_encrypter_(new Aes128GcmEncrypter), |
| 670 source_address_token_decrypter_(new Aes128GcmDecrypter) { | 686 source_address_token_decrypter_(new Aes128GcmDecrypter) { |
| 671 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */, | 687 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */, |
| 672 "QUIC source address token key", | 688 "QUIC source address token key", |
| 673 source_address_token_encrypter_->GetKeySize(), | 689 source_address_token_encrypter_->GetKeySize(), |
| 674 0 /* no fixed IV needed */); | 690 0 /* no fixed IV needed */); |
| 675 source_address_token_encrypter_->SetKey(hkdf.server_write_key()); | 691 source_address_token_encrypter_->SetKey(hkdf.server_write_key()); |
| 676 source_address_token_decrypter_->SetKey(hkdf.server_write_key()); | 692 source_address_token_decrypter_->SetKey(hkdf.server_write_key()); |
| 677 } | 693 } |
| 678 | 694 |
| 679 QuicCryptoServerConfig::~QuicCryptoServerConfig() { | 695 QuicCryptoServerConfig::~QuicCryptoServerConfig() { |
| 680 STLDeleteValues(&configs_); | 696 STLDeleteValues(&configs_); |
| 681 } | 697 } |
| 682 | 698 |
| 683 // static | 699 // static |
| 684 QuicServerConfigProtobuf* QuicCryptoServerConfig::ConfigForTesting( | 700 QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig( |
| 685 QuicRandom* rand, | 701 QuicRandom* rand, |
| 686 const QuicClock* clock, | 702 const QuicClock* clock, |
| 687 const CryptoHandshakeMessage& extra_tags) { | 703 const CryptoHandshakeMessage& extra_tags) { |
| 688 CryptoHandshakeMessage msg; | 704 CryptoHandshakeMessage msg; |
| 689 | 705 |
| 690 const string curve25519_private_key = | 706 const string curve25519_private_key = |
| 691 Curve25519KeyExchange::NewPrivateKey(rand); | 707 Curve25519KeyExchange::NewPrivateKey(rand); |
| 692 scoped_ptr<Curve25519KeyExchange> curve25519( | 708 scoped_ptr<Curve25519KeyExchange> curve25519( |
| 693 Curve25519KeyExchange::New(curve25519_private_key)); | 709 Curve25519KeyExchange::New(curve25519_private_key)); |
| 694 StringPiece curve25519_public_value = curve25519->public_value(); | 710 StringPiece curve25519_public_value = curve25519->public_value(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 715 msg.SetTaglist(kAEAD, kAESG, 0); | 731 msg.SetTaglist(kAEAD, kAESG, 0); |
| 716 msg.SetValue(kVERS, static_cast<uint16>(0)); | 732 msg.SetValue(kVERS, static_cast<uint16>(0)); |
| 717 msg.SetStringPiece(kPUBS, encoded_public_values); | 733 msg.SetStringPiece(kPUBS, encoded_public_values); |
| 718 msg.Insert(extra_tags.tag_value_map().begin(), | 734 msg.Insert(extra_tags.tag_value_map().begin(), |
| 719 extra_tags.tag_value_map().end()); | 735 extra_tags.tag_value_map().end()); |
| 720 | 736 |
| 721 char scid_bytes[16]; | 737 char scid_bytes[16]; |
| 722 rand->RandBytes(scid_bytes, sizeof(scid_bytes)); | 738 rand->RandBytes(scid_bytes, sizeof(scid_bytes)); |
| 723 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes))); | 739 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes))); |
| 724 | 740 |
| 741 char orbit_bytes[kOrbitSize]; |
| 742 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes)); |
| 743 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes))); |
| 744 |
| 725 scoped_ptr<QuicData> serialized( | 745 scoped_ptr<QuicData> serialized( |
| 726 CryptoFramer::ConstructHandshakeMessage(msg)); | 746 CryptoFramer::ConstructHandshakeMessage(msg)); |
| 727 | 747 |
| 728 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf); | 748 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf); |
| 729 config->set_config(serialized->AsStringPiece()); | 749 config->set_config(serialized->AsStringPiece()); |
| 730 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key(); | 750 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key(); |
| 731 curve25519_key->set_tag(kC255); | 751 curve25519_key->set_tag(kC255); |
| 732 curve25519_key->set_private_key(curve25519_private_key); | 752 curve25519_key->set_private_key(curve25519_private_key); |
| 733 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key(); | 753 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key(); |
| 734 p256_key->set_tag(kP256); | 754 p256_key->set_tag(kP256); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 } | 791 } |
| 772 config->aead = vector<CryptoTag>(aead_tags, aead_tags + aead_len); | 792 config->aead = vector<CryptoTag>(aead_tags, aead_tags + aead_len); |
| 773 | 793 |
| 774 const CryptoTag* kexs_tags; | 794 const CryptoTag* kexs_tags; |
| 775 size_t kexs_len; | 795 size_t kexs_len; |
| 776 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) { | 796 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) { |
| 777 LOG(WARNING) << "Server config message is missing KEXS"; | 797 LOG(WARNING) << "Server config message is missing KEXS"; |
| 778 return NULL; | 798 return NULL; |
| 779 } | 799 } |
| 780 | 800 |
| 801 StringPiece orbit; |
| 802 if (!msg->GetStringPiece(kORBT, &orbit)) { |
| 803 LOG(WARNING) << "Server config message is missing OBIT"; |
| 804 return NULL; |
| 805 } |
| 806 |
| 807 if (orbit.size() != kOrbitSize) { |
| 808 LOG(WARNING) << "Orbit value in server config is the wrong length." |
| 809 " Got " << orbit.size() << " want " << kOrbitSize; |
| 810 return NULL; |
| 811 } |
| 812 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size); |
| 813 memcpy(config->orbit, orbit.data(), sizeof(config->orbit)); |
| 814 |
| 781 if (kexs_len != protobuf->key_size()) { | 815 if (kexs_len != protobuf->key_size()) { |
| 782 LOG(WARNING) << "Server config has " | 816 LOG(WARNING) << "Server config has " |
| 783 << kexs_len | 817 << kexs_len |
| 784 << " key exchange methods configured, but " | 818 << " key exchange methods configured, but " |
| 785 << protobuf->key_size() | 819 << protobuf->key_size() |
| 786 << " private keys"; | 820 << " private keys"; |
| 787 return NULL; | 821 return NULL; |
| 788 } | 822 } |
| 789 | 823 |
| 790 for (size_t i = 0; i < kexs_len; i++) { | 824 for (size_t i = 0; i < kexs_len; i++) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 char id_bytes[16]; | 893 char id_bytes[16]; |
| 860 sha256->Finish(id_bytes, sizeof(id_bytes)); | 894 sha256->Finish(id_bytes, sizeof(id_bytes)); |
| 861 const string id(id_bytes, sizeof(id_bytes)); | 895 const string id(id_bytes, sizeof(id_bytes)); |
| 862 | 896 |
| 863 configs_[id] = config.release(); | 897 configs_[id] = config.release(); |
| 864 active_config_ = id; | 898 active_config_ = id; |
| 865 | 899 |
| 866 return msg.release(); | 900 return msg.release(); |
| 867 } | 901 } |
| 868 | 902 |
| 869 CryptoHandshakeMessage* QuicCryptoServerConfig::AddTestingConfig( | 903 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig( |
| 870 QuicRandom* rand, | 904 QuicRandom* rand, |
| 871 const QuicClock* clock, | 905 const QuicClock* clock, |
| 872 const CryptoHandshakeMessage& extra_tags) { | 906 const CryptoHandshakeMessage& extra_tags) { |
| 873 scoped_ptr<QuicServerConfigProtobuf> config(ConfigForTesting( | 907 scoped_ptr<QuicServerConfigProtobuf> config(DefaultConfig( |
| 874 rand, clock, extra_tags)); | 908 rand, clock, extra_tags)); |
| 875 return AddConfig(config.get()); | 909 return AddConfig(config.get()); |
| 876 } | 910 } |
| 877 | 911 |
| 878 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( | 912 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( |
| 879 const CryptoHandshakeMessage& client_hello, | 913 const CryptoHandshakeMessage& client_hello, |
| 880 QuicGuid guid, | 914 QuicGuid guid, |
| 881 const IPEndPoint& client_ip, | 915 const IPEndPoint& client_ip, |
| 882 QuicTime::Delta now_since_unix_epoch, | 916 QuicTime::Delta now_since_unix_epoch, |
| 883 QuicRandom* rand, | 917 QuicRandom* rand, |
| 918 QuicCryptoNegotiatedParameters *params, |
| 884 CryptoHandshakeMessage* out, | 919 CryptoHandshakeMessage* out, |
| 885 QuicCryptoNegotiatedParameters *out_params, | 920 string* error_details) const { |
| 886 string* error_details) { | |
| 887 CHECK(!configs_.empty()); | 921 CHECK(!configs_.empty()); |
| 888 // FIXME(agl): we should use the client's SCID, not just the active config. | 922 // FIXME(agl): we should use the client's SCID, not just the active config. |
| 889 const Config* config(configs_[active_config_]); | 923 map<ServerConfigID, Config*>::const_iterator it = |
| 924 configs_.find(active_config_); |
| 925 if (it == configs_.end()) { |
| 926 *error_details = "No valid server config loaded"; |
| 927 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 928 } |
| 929 const Config* const config(it->second); |
| 890 | 930 |
| 891 bool valid_source_address_token = false; | 931 bool valid_source_address_token = false; |
| 892 StringPiece srct; | 932 StringPiece srct; |
| 893 if (client_hello.GetStringPiece(kSRCT, &srct) && | 933 if (client_hello.GetStringPiece(kSRCT, &srct) && |
| 894 ValidateSourceAddressToken(srct, client_ip, now_since_unix_epoch)) { | 934 ValidateSourceAddressToken(srct, client_ip, now_since_unix_epoch)) { |
| 895 valid_source_address_token = true; | 935 valid_source_address_token = true; |
| 896 } | 936 } |
| 897 | 937 |
| 898 const string fresh_source_address_token = | 938 const string fresh_source_address_token = |
| 899 NewSourceAddressToken(client_ip, rand, now_since_unix_epoch); | 939 NewSourceAddressToken(client_ip, rand, now_since_unix_epoch); |
| 900 | 940 |
| 941 // If we previously sent a REJ to this client then we may have stored a |
| 942 // server nonce in |params|. In which case, we know that the connection |
| 943 // is unique because the server nonce will be mixed into the key generation. |
| 944 bool unique_by_server_nonce = !params->server_nonce.empty(); |
| 945 // If we can't ensure uniqueness by a server nonce, then we will try and use |
| 946 // the strike register. |
| 947 bool unique_by_strike_register = false; |
| 948 |
| 949 StringPiece client_nonce; |
| 950 bool client_nonce_well_formed = false; |
| 951 if (client_hello.GetStringPiece(kNONC, &client_nonce) && |
| 952 client_nonce.size() == kNonceSize) { |
| 953 client_nonce_well_formed = true; |
| 954 if (!unique_by_server_nonce) { |
| 955 base::AutoLock auto_lock(strike_register_lock_); |
| 956 |
| 957 if (strike_register_.get() == NULL) { |
| 958 strike_register_.reset(new StrikeRegister( |
| 959 // TODO(agl): these magic numbers should come from config. |
| 960 1024 /* max entries */, |
| 961 static_cast<uint32>(now_since_unix_epoch.ToSeconds()), |
| 962 600 /* window secs */, config->orbit)); |
| 963 } |
| 964 unique_by_strike_register = strike_register_->Insert( |
| 965 reinterpret_cast<const uint8*>(client_nonce.data()), |
| 966 static_cast<uint32>(now_since_unix_epoch.ToSeconds())); |
| 967 } |
| 968 } |
| 969 |
| 901 StringPiece scid; | 970 StringPiece scid; |
| 902 if (!client_hello.GetStringPiece(kSCID, &scid) || | 971 if (!client_hello.GetStringPiece(kSCID, &scid) || |
| 903 scid.as_string() != config->id || | 972 scid.as_string() != config->id || |
| 904 !valid_source_address_token) { | 973 !valid_source_address_token || |
| 974 !client_nonce_well_formed || |
| 975 (!unique_by_strike_register && |
| 976 !unique_by_server_nonce)) { |
| 905 // If the client didn't provide a server config ID, or gave the wrong one, | 977 // If the client didn't provide a server config ID, or gave the wrong one, |
| 906 // then the handshake cannot possibly complete. We reject the handshake and | 978 // then the handshake cannot possibly complete. We reject the handshake and |
| 907 // give the client enough information to do better next time. | 979 // give the client enough information to do better next time. |
| 908 out->Clear(); | 980 out->Clear(); |
| 909 out->set_tag(kREJ); | 981 out->set_tag(kREJ); |
| 910 out->SetStringPiece(kSCFG, config->serialized); | 982 out->SetStringPiece(kSCFG, config->serialized); |
| 911 out->SetStringPiece(kSRCT, fresh_source_address_token); | 983 out->SetStringPiece(kSRCT, fresh_source_address_token); |
| 984 if (params->server_nonce.empty()) { |
| 985 CryptoUtils::GenerateNonce( |
| 986 now_since_unix_epoch, rand, |
| 987 StringPiece(reinterpret_cast<const char*>(config->orbit), |
| 988 sizeof(config->orbit)), |
| 989 ¶ms->server_nonce); |
| 990 } |
| 991 out->SetStringPiece(kNONC, params->server_nonce); |
| 912 return QUIC_NO_ERROR; | 992 return QUIC_NO_ERROR; |
| 913 } | 993 } |
| 914 | 994 |
| 915 const CryptoTag* their_aeads; | 995 const CryptoTag* their_aeads; |
| 916 const CryptoTag* their_key_exchanges; | 996 const CryptoTag* their_key_exchanges; |
| 917 size_t num_their_aeads, num_their_key_exchanges; | 997 size_t num_their_aeads, num_their_key_exchanges; |
| 918 if (client_hello.GetTaglist(kAEAD, &their_aeads, | 998 if (client_hello.GetTaglist(kAEAD, &their_aeads, |
| 919 &num_their_aeads) != QUIC_NO_ERROR || | 999 &num_their_aeads) != QUIC_NO_ERROR || |
| 920 client_hello.GetTaglist(kKEXS, &their_key_exchanges, | 1000 client_hello.GetTaglist(kKEXS, &their_key_exchanges, |
| 921 &num_their_key_exchanges) != QUIC_NO_ERROR || | 1001 &num_their_key_exchanges) != QUIC_NO_ERROR || |
| 922 num_their_aeads != 1 || | 1002 num_their_aeads != 1 || |
| 923 num_their_key_exchanges != 1) { | 1003 num_their_key_exchanges != 1) { |
| 924 if (error_details) { | 1004 if (error_details) { |
| 925 *error_details = "Missing or invalid AEAD or KEXS"; | 1005 *error_details = "Missing or invalid AEAD or KEXS"; |
| 926 } | 1006 } |
| 927 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 1007 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 928 } | 1008 } |
| 929 | 1009 |
| 930 size_t key_exchange_index; | 1010 size_t key_exchange_index; |
| 931 if (!CryptoUtils::FindMutualTag(config->aead, | 1011 if (!CryptoUtils::FindMutualTag(config->aead, |
| 932 their_aeads, num_their_aeads, | 1012 their_aeads, num_their_aeads, |
| 933 CryptoUtils::LOCAL_PRIORITY, | 1013 CryptoUtils::LOCAL_PRIORITY, |
| 934 &out_params->aead, | 1014 ¶ms->aead, |
| 935 NULL) || | 1015 NULL) || |
| 936 !CryptoUtils::FindMutualTag(config->kexs, | 1016 !CryptoUtils::FindMutualTag(config->kexs, |
| 937 their_key_exchanges, num_their_key_exchanges, | 1017 their_key_exchanges, num_their_key_exchanges, |
| 938 CryptoUtils::LOCAL_PRIORITY, | 1018 CryptoUtils::LOCAL_PRIORITY, |
| 939 &out_params->key_exchange, | 1019 ¶ms->key_exchange, |
| 940 &key_exchange_index)) { | 1020 &key_exchange_index)) { |
| 941 if (error_details) { | 1021 if (error_details) { |
| 942 *error_details = "Unsupported AEAD or KEXS"; | 1022 *error_details = "Unsupported AEAD or KEXS"; |
| 943 } | 1023 } |
| 944 return QUIC_CRYPTO_NO_SUPPORT; | 1024 return QUIC_CRYPTO_NO_SUPPORT; |
| 945 } | 1025 } |
| 946 | 1026 |
| 947 StringPiece public_value; | 1027 StringPiece public_value; |
| 948 if (!client_hello.GetStringPiece(kPUBS, &public_value)) { | 1028 if (!client_hello.GetStringPiece(kPUBS, &public_value)) { |
| 949 if (error_details) { | 1029 if (error_details) { |
| 950 *error_details = "Missing public value"; | 1030 *error_details = "Missing public value"; |
| 951 } | 1031 } |
| 952 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 1032 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 953 } | 1033 } |
| 954 | 1034 |
| 955 if (!config->key_exchanges[key_exchange_index]->CalculateSharedKey( | 1035 if (!config->key_exchanges[key_exchange_index]->CalculateSharedKey( |
| 956 public_value, &out_params->premaster_secret)) { | 1036 public_value, ¶ms->premaster_secret)) { |
| 957 if (error_details) { | 1037 if (error_details) { |
| 958 *error_details = "Invalid public value"; | 1038 *error_details = "Invalid public value"; |
| 959 } | 1039 } |
| 960 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 1040 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 961 } | 1041 } |
| 962 | 1042 |
| 963 out_params->server_config_id = scid.as_string(); | 1043 params->server_config_id = scid.as_string(); |
| 964 | |
| 965 StringPiece client_nonce; | |
| 966 if (!client_hello.GetStringPiece(kNONC, &client_nonce)) { | |
| 967 if (error_details) { | |
| 968 *error_details = "Invalid nonce"; | |
| 969 } | |
| 970 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | |
| 971 } | |
| 972 | 1044 |
| 973 string hkdf_input(kLabel, arraysize(kLabel)); | 1045 string hkdf_input(kLabel, arraysize(kLabel)); |
| 974 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid)); | 1046 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid)); |
| 975 | 1047 |
| 976 const QuicData& client_hello_serialized = client_hello.GetSerialized(); | 1048 const QuicData& client_hello_serialized = client_hello.GetSerialized(); |
| 977 hkdf_input.append(client_hello_serialized.data(), | 1049 hkdf_input.append(client_hello_serialized.data(), |
| 978 client_hello_serialized.length()); | 1050 client_hello_serialized.length()); |
| 979 hkdf_input.append(config->serialized); | 1051 hkdf_input.append(config->serialized); |
| 980 | 1052 |
| 981 CryptoUtils::DeriveKeys(out_params, client_nonce, hkdf_input, | 1053 CryptoUtils::DeriveKeys(params, client_nonce, hkdf_input, |
| 982 CryptoUtils::SERVER); | 1054 CryptoUtils::SERVER); |
| 983 | 1055 |
| 984 out->set_tag(kSHLO); | 1056 out->set_tag(kSHLO); |
| 985 out->SetStringPiece(kSRCT, fresh_source_address_token); | 1057 out->SetStringPiece(kSRCT, fresh_source_address_token); |
| 986 return QUIC_NO_ERROR; | 1058 return QUIC_NO_ERROR; |
| 987 } | 1059 } |
| 988 | 1060 |
| 989 string QuicCryptoServerConfig::NewSourceAddressToken( | 1061 string QuicCryptoServerConfig::NewSourceAddressToken( |
| 990 const IPEndPoint& ip, | 1062 const IPEndPoint& ip, |
| 991 QuicRandom* rand, | 1063 QuicRandom* rand, |
| 992 QuicTime::Delta now_since_epoch) { | 1064 QuicTime::Delta now_since_epoch) const { |
| 993 SourceAddressToken source_address_token; | 1065 SourceAddressToken source_address_token; |
| 994 source_address_token.set_ip(ip.ToString()); | 1066 source_address_token.set_ip(ip.ToString()); |
| 995 source_address_token.set_timestamp(now_since_epoch.ToSeconds()); | 1067 source_address_token.set_timestamp(now_since_epoch.ToSeconds()); |
| 996 | 1068 |
| 997 string plaintext = source_address_token.SerializeAsString(); | 1069 string plaintext = source_address_token.SerializeAsString(); |
| 998 char nonce[12]; | 1070 char nonce[12]; |
| 999 DCHECK_EQ(sizeof(nonce), | 1071 DCHECK_EQ(sizeof(nonce), |
| 1000 source_address_token_encrypter_->GetNoncePrefixSize() + | 1072 source_address_token_encrypter_->GetNoncePrefixSize() + |
| 1001 sizeof(QuicPacketSequenceNumber)); | 1073 sizeof(QuicPacketSequenceNumber)); |
| 1002 rand->RandBytes(nonce, sizeof(nonce)); | 1074 rand->RandBytes(nonce, sizeof(nonce)); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1013 DCHECK(false); | 1085 DCHECK(false); |
| 1014 return string(); | 1086 return string(); |
| 1015 } | 1087 } |
| 1016 | 1088 |
| 1017 return result; | 1089 return result; |
| 1018 } | 1090 } |
| 1019 | 1091 |
| 1020 bool QuicCryptoServerConfig::ValidateSourceAddressToken( | 1092 bool QuicCryptoServerConfig::ValidateSourceAddressToken( |
| 1021 StringPiece token, | 1093 StringPiece token, |
| 1022 const IPEndPoint& ip, | 1094 const IPEndPoint& ip, |
| 1023 QuicTime::Delta now_since_epoch) { | 1095 QuicTime::Delta now_since_epoch) const { |
| 1024 char nonce[12]; | 1096 char nonce[12]; |
| 1025 DCHECK_EQ(sizeof(nonce), | 1097 DCHECK_EQ(sizeof(nonce), |
| 1026 source_address_token_encrypter_->GetNoncePrefixSize() + | 1098 source_address_token_encrypter_->GetNoncePrefixSize() + |
| 1027 sizeof(QuicPacketSequenceNumber)); | 1099 sizeof(QuicPacketSequenceNumber)); |
| 1028 | 1100 |
| 1029 if (token.size() <= sizeof(nonce)) { | 1101 if (token.size() <= sizeof(nonce)) { |
| 1030 return false; | 1102 return false; |
| 1031 } | 1103 } |
| 1032 memcpy(&nonce, token.data(), sizeof(nonce)); | 1104 memcpy(&nonce, token.data(), sizeof(nonce)); |
| 1033 token.remove_prefix(sizeof(nonce)); | 1105 token.remove_prefix(sizeof(nonce)); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1079 } | 1151 } |
| 1080 | 1152 |
| 1081 QuicCryptoServerConfig::Config::Config() { | 1153 QuicCryptoServerConfig::Config::Config() { |
| 1082 } | 1154 } |
| 1083 | 1155 |
| 1084 QuicCryptoServerConfig::Config::~Config() { | 1156 QuicCryptoServerConfig::Config::~Config() { |
| 1085 STLDeleteElements(&key_exchanges); | 1157 STLDeleteElements(&key_exchanges); |
| 1086 } | 1158 } |
| 1087 | 1159 |
| 1088 } // namespace net | 1160 } // namespace net |
| OLD | NEW |