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 |