Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: net/quic/crypto/crypto_handshake.cc

Issue 13976007: Land Recent QUIC Changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Updated copyright notice Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/quic/crypto/crypto_handshake.h ('k') | net/quic/crypto/crypto_handshake_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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 &params->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 &params->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 &params->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, &params->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
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
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
OLDNEW
« no previous file with comments | « net/quic/crypto/crypto_handshake.h ('k') | net/quic/crypto/crypto_handshake_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698