OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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/quic_crypto_server_config.h" | 5 #include "net/quic/crypto/quic_crypto_server_config.h" |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 | 9 |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 | 39 |
40 using base::StringPiece; | 40 using base::StringPiece; |
41 using crypto::SecureHash; | 41 using crypto::SecureHash; |
42 using std::map; | 42 using std::map; |
43 using std::sort; | 43 using std::sort; |
44 using std::string; | 44 using std::string; |
45 using std::vector; | 45 using std::vector; |
46 | 46 |
47 namespace net { | 47 namespace net { |
48 | 48 |
| 49 namespace { |
| 50 |
| 51 string DeriveSourceAddressTokenKey(StringPiece source_address_token_secret) { |
| 52 crypto::HKDF hkdf(source_address_token_secret, |
| 53 StringPiece() /* no salt */, |
| 54 "QUIC source address token key", |
| 55 CryptoSecretBoxer::GetKeySize(), |
| 56 0 /* no fixed IV needed */); |
| 57 return hkdf.server_write_key().as_string(); |
| 58 } |
| 59 |
| 60 } // namespace |
| 61 |
49 // ClientHelloInfo contains information about a client hello message that is | 62 // ClientHelloInfo contains information about a client hello message that is |
50 // only kept for as long as it's being processed. | 63 // only kept for as long as it's being processed. |
51 struct ClientHelloInfo { | 64 struct ClientHelloInfo { |
52 ClientHelloInfo(const IPEndPoint& in_client_ip, QuicWallTime in_now) | 65 ClientHelloInfo(const IPEndPoint& in_client_ip, QuicWallTime in_now) |
53 : client_ip(in_client_ip), | 66 : client_ip(in_client_ip), |
54 now(in_now), | 67 now(in_now), |
55 valid_source_address_token(false), | 68 valid_source_address_token(false), |
56 client_nonce_well_formed(false), | 69 client_nonce_well_formed(false), |
57 unique(false) {} | 70 unique(false) {} |
58 | 71 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 primary_config_(NULL), | 189 primary_config_(NULL), |
177 next_config_promotion_time_(QuicWallTime::Zero()), | 190 next_config_promotion_time_(QuicWallTime::Zero()), |
178 server_nonce_strike_register_lock_(), | 191 server_nonce_strike_register_lock_(), |
179 strike_register_no_startup_period_(false), | 192 strike_register_no_startup_period_(false), |
180 strike_register_max_entries_(1 << 10), | 193 strike_register_max_entries_(1 << 10), |
181 strike_register_window_secs_(600), | 194 strike_register_window_secs_(600), |
182 source_address_token_future_secs_(3600), | 195 source_address_token_future_secs_(3600), |
183 source_address_token_lifetime_secs_(86400), | 196 source_address_token_lifetime_secs_(86400), |
184 server_nonce_strike_register_max_entries_(1 << 10), | 197 server_nonce_strike_register_max_entries_(1 << 10), |
185 server_nonce_strike_register_window_secs_(120) { | 198 server_nonce_strike_register_window_secs_(120) { |
186 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */, | 199 default_source_address_token_boxer_.SetKey( |
187 "QUIC source address token key", | 200 DeriveSourceAddressTokenKey(source_address_token_secret)); |
188 CryptoSecretBoxer::GetKeySize(), | |
189 0 /* no fixed IV needed */); | |
190 source_address_token_boxer_.SetKey(hkdf.server_write_key()); | |
191 | 201 |
192 // Generate a random key and orbit for server nonces. | 202 // Generate a random key and orbit for server nonces. |
193 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_)); | 203 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_)); |
194 const size_t key_size = server_nonce_boxer_.GetKeySize(); | 204 const size_t key_size = server_nonce_boxer_.GetKeySize(); |
195 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]); | 205 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]); |
196 rand->RandBytes(key_bytes.get(), key_size); | 206 rand->RandBytes(key_bytes.get(), key_size); |
197 | 207 |
198 server_nonce_boxer_.SetKey( | 208 server_nonce_boxer_.SetKey( |
199 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size)); | 209 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size)); |
200 } | 210 } |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 } else { | 389 } else { |
380 VLOG(1) << "Updating configs:"; | 390 VLOG(1) << "Updating configs:"; |
381 | 391 |
382 base::AutoLock locked(configs_lock_); | 392 base::AutoLock locked(configs_lock_); |
383 ConfigMap new_configs; | 393 ConfigMap new_configs; |
384 | 394 |
385 for (vector<scoped_refptr<Config> >::const_iterator i = | 395 for (vector<scoped_refptr<Config> >::const_iterator i = |
386 parsed_configs.begin(); | 396 parsed_configs.begin(); |
387 i != parsed_configs.end(); ++i) { | 397 i != parsed_configs.end(); ++i) { |
388 scoped_refptr<Config> config = *i; | 398 scoped_refptr<Config> config = *i; |
| 399 |
389 ConfigMap::iterator it = configs_.find(config->id); | 400 ConfigMap::iterator it = configs_.find(config->id); |
390 if (it != configs_.end()) { | 401 if (it != configs_.end()) { |
391 VLOG(1) | 402 VLOG(1) |
392 << "Keeping scid: " << base::HexEncode( | 403 << "Keeping scid: " << base::HexEncode( |
393 config->id.data(), config->id.size()) | 404 config->id.data(), config->id.size()) |
394 << " orbit: " << base::HexEncode( | 405 << " orbit: " << base::HexEncode( |
395 reinterpret_cast<const char *>(config->orbit), kOrbitSize) | 406 reinterpret_cast<const char *>(config->orbit), kOrbitSize) |
396 << " new primary_time " << config->primary_time.ToUNIXSeconds() | 407 << " new primary_time " << config->primary_time.ToUNIXSeconds() |
397 << " old primary_time " << it->second->primary_time.ToUNIXSeconds() | 408 << " old primary_time " << it->second->primary_time.ToUNIXSeconds() |
398 << " new priority " << config->priority | 409 << " new priority " << config->priority |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 const CryptoHandshakeMessage& client_hello, | 444 const CryptoHandshakeMessage& client_hello, |
434 IPEndPoint client_ip, | 445 IPEndPoint client_ip, |
435 const QuicClock* clock, | 446 const QuicClock* clock, |
436 ValidateClientHelloResultCallback* done_cb) const { | 447 ValidateClientHelloResultCallback* done_cb) const { |
437 const QuicWallTime now(clock->WallNow()); | 448 const QuicWallTime now(clock->WallNow()); |
438 | 449 |
439 ValidateClientHelloResultCallback::Result* result = | 450 ValidateClientHelloResultCallback::Result* result = |
440 new ValidateClientHelloResultCallback::Result( | 451 new ValidateClientHelloResultCallback::Result( |
441 client_hello, client_ip, now); | 452 client_hello, client_ip, now); |
442 | 453 |
| 454 StringPiece requested_scid; |
| 455 client_hello.GetStringPiece(kSCID, &requested_scid); |
| 456 |
443 uint8 primary_orbit[kOrbitSize]; | 457 uint8 primary_orbit[kOrbitSize]; |
| 458 scoped_refptr<Config> requested_config; |
444 { | 459 { |
445 base::AutoLock locked(configs_lock_); | 460 base::AutoLock locked(configs_lock_); |
446 | 461 |
447 if (!primary_config_.get()) { | 462 if (!primary_config_.get()) { |
448 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR; | 463 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR; |
449 result->error_details = "No configurations loaded"; | 464 result->error_details = "No configurations loaded"; |
450 } else { | 465 } else { |
451 if (!next_config_promotion_time_.IsZero() && | 466 if (!next_config_promotion_time_.IsZero() && |
452 next_config_promotion_time_.IsAfter(now)) { | 467 next_config_promotion_time_.IsAfter(now)) { |
453 SelectNewPrimaryConfig(now); | 468 SelectNewPrimaryConfig(now); |
454 DCHECK(primary_config_); | 469 DCHECK(primary_config_); |
455 DCHECK(configs_.find(primary_config_->id)->second == primary_config_); | 470 DCHECK(configs_.find(primary_config_->id)->second == primary_config_); |
456 } | 471 } |
457 | 472 |
458 memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit)); | 473 memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit)); |
459 } | 474 } |
| 475 |
| 476 requested_config = GetConfigWithScid(requested_scid); |
460 } | 477 } |
461 | 478 |
462 if (result->error_code == QUIC_NO_ERROR) { | 479 if (result->error_code == QUIC_NO_ERROR) { |
463 EvaluateClientHello(primary_orbit, result, done_cb); | 480 EvaluateClientHello(primary_orbit, requested_config, result, done_cb); |
464 } else { | 481 } else { |
465 done_cb->Run(result); | 482 done_cb->Run(result); |
466 } | 483 } |
467 } | 484 } |
468 | 485 |
469 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( | 486 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( |
470 const ValidateClientHelloResultCallback::Result& validate_chlo_result, | 487 const ValidateClientHelloResultCallback::Result& validate_chlo_result, |
471 QuicConnectionId connection_id, | 488 QuicConnectionId connection_id, |
472 IPEndPoint client_address, | 489 IPEndPoint client_address, |
473 QuicVersion version, | 490 QuicVersion version, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 return QUIC_CRYPTO_INTERNAL_ERROR; | 537 return QUIC_CRYPTO_INTERNAL_ERROR; |
521 } | 538 } |
522 | 539 |
523 if (!next_config_promotion_time_.IsZero() && | 540 if (!next_config_promotion_time_.IsZero() && |
524 next_config_promotion_time_.IsAfter(now)) { | 541 next_config_promotion_time_.IsAfter(now)) { |
525 SelectNewPrimaryConfig(now); | 542 SelectNewPrimaryConfig(now); |
526 DCHECK(primary_config_); | 543 DCHECK(primary_config_); |
527 DCHECK(configs_.find(primary_config_->id)->second == primary_config_); | 544 DCHECK(configs_.find(primary_config_->id)->second == primary_config_); |
528 } | 545 } |
529 | 546 |
| 547 // We'll use the config that the client requested in order to do |
| 548 // key-agreement. Otherwise we'll give it a copy of |primary_config_| |
| 549 // to use. |
530 primary_config = primary_config_; | 550 primary_config = primary_config_; |
531 | 551 |
532 if (!requested_scid.empty()) { | 552 requested_config = GetConfigWithScid(requested_scid); |
533 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string()); | |
534 if (it != configs_.end()) { | |
535 // We'll use the config that the client requested in order to do | |
536 // key-agreement. Otherwise we'll give it a copy of |primary_config_| | |
537 // to use. | |
538 requested_config = it->second; | |
539 } | |
540 } | |
541 } | 553 } |
542 | 554 |
543 if (validate_chlo_result.error_code != QUIC_NO_ERROR) { | 555 if (validate_chlo_result.error_code != QUIC_NO_ERROR) { |
544 *error_details = validate_chlo_result.error_details; | 556 *error_details = validate_chlo_result.error_details; |
545 return validate_chlo_result.error_code; | 557 return validate_chlo_result.error_code; |
546 } | 558 } |
547 | 559 |
548 out->Clear(); | 560 out->Clear(); |
549 | 561 |
550 if (!info.valid_source_address_token || | 562 if (!info.valid_source_address_token || |
551 !info.client_nonce_well_formed || | 563 !info.client_nonce_well_formed || |
552 !info.unique || | 564 !info.unique || |
553 !requested_config.get()) { | 565 !requested_config.get()) { |
554 BuildRejection(primary_config.get(), client_hello, info, rand, out); | 566 BuildRejection(*primary_config, client_hello, info, rand, out); |
555 return QUIC_NO_ERROR; | 567 return QUIC_NO_ERROR; |
556 } | 568 } |
557 | 569 |
558 const QuicTag* their_aeads; | 570 const QuicTag* their_aeads; |
559 const QuicTag* their_key_exchanges; | 571 const QuicTag* their_key_exchanges; |
560 size_t num_their_aeads, num_their_key_exchanges; | 572 size_t num_their_aeads, num_their_key_exchanges; |
561 if (client_hello.GetTaglist(kAEAD, &their_aeads, | 573 if (client_hello.GetTaglist(kAEAD, &their_aeads, |
562 &num_their_aeads) != QUIC_NO_ERROR || | 574 &num_their_aeads) != QUIC_NO_ERROR || |
563 client_hello.GetTaglist(kKEXS, &their_key_exchanges, | 575 client_hello.GetTaglist(kKEXS, &their_key_exchanges, |
564 &num_their_key_exchanges) != QUIC_NO_ERROR || | 576 &num_their_key_exchanges) != QUIC_NO_ERROR || |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
711 } | 723 } |
712 | 724 |
713 out->set_tag(kSHLO); | 725 out->set_tag(kSHLO); |
714 QuicTagVector supported_version_tags; | 726 QuicTagVector supported_version_tags; |
715 for (size_t i = 0; i < supported_versions.size(); ++i) { | 727 for (size_t i = 0; i < supported_versions.size(); ++i) { |
716 supported_version_tags.push_back | 728 supported_version_tags.push_back |
717 (QuicVersionToQuicTag(supported_versions[i])); | 729 (QuicVersionToQuicTag(supported_versions[i])); |
718 } | 730 } |
719 out->SetVector(kVER, supported_version_tags); | 731 out->SetVector(kVER, supported_version_tags); |
720 out->SetStringPiece(kSourceAddressTokenTag, | 732 out->SetStringPiece(kSourceAddressTokenTag, |
721 NewSourceAddressToken(client_address, rand, info.now)); | 733 NewSourceAddressToken( |
| 734 *requested_config, |
| 735 client_address, rand, |
| 736 info.now)); |
722 QuicSocketAddressCoder address_coder(client_address); | 737 QuicSocketAddressCoder address_coder(client_address); |
723 out->SetStringPiece(kCADR, address_coder.Encode()); | 738 out->SetStringPiece(kCADR, address_coder.Encode()); |
724 out->SetStringPiece(kPUBS, forward_secure_public_value); | 739 out->SetStringPiece(kPUBS, forward_secure_public_value); |
725 | 740 |
726 // Set initial receive window for flow control. | 741 // Set initial receive window for flow control. |
727 out->SetValue(kIFCW, initial_flow_control_window_bytes); | 742 out->SetValue(kIFCW, initial_flow_control_window_bytes); |
728 | 743 |
729 return QUIC_NO_ERROR; | 744 return QUIC_NO_ERROR; |
730 } | 745 } |
731 | 746 |
| 747 scoped_refptr<QuicCryptoServerConfig::Config> |
| 748 QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid) const { |
| 749 // In Chromium, we will dead lock if the lock is held by the current thread. |
| 750 // Chromium doesn't have AssertReaderHeld API call. |
| 751 // configs_lock_.AssertReaderHeld(); |
| 752 |
| 753 if (!requested_scid.empty()) { |
| 754 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string()); |
| 755 if (it != configs_.end()) { |
| 756 // We'll use the config that the client requested in order to do |
| 757 // key-agreement. |
| 758 return scoped_refptr<Config>(it->second); |
| 759 } |
| 760 } |
| 761 |
| 762 return scoped_refptr<Config>(); |
| 763 } |
| 764 |
732 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for | 765 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for |
733 // Config's based on their primary_time. | 766 // Config's based on their primary_time. |
734 // static | 767 // static |
735 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan( | 768 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan( |
736 const scoped_refptr<Config>& a, | 769 const scoped_refptr<Config>& a, |
737 const scoped_refptr<Config>& b) { | 770 const scoped_refptr<Config>& b) { |
738 if (a->primary_time.IsBefore(b->primary_time) || | 771 if (a->primary_time.IsBefore(b->primary_time) || |
739 b->primary_time.IsBefore(a->primary_time)) { | 772 b->primary_time.IsBefore(a->primary_time)) { |
740 // Primary times differ. | 773 // Primary times differ. |
741 return a->primary_time.IsBefore(b->primary_time); | 774 return a->primary_time.IsBefore(b->primary_time); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 // and highest priority candidate primary. | 849 // and highest priority candidate primary. |
817 scoped_refptr<Config> new_primary(best_candidate); | 850 scoped_refptr<Config> new_primary(best_candidate); |
818 if (primary_config_.get()) { | 851 if (primary_config_.get()) { |
819 primary_config_->is_primary = false; | 852 primary_config_->is_primary = false; |
820 } | 853 } |
821 primary_config_ = new_primary; | 854 primary_config_ = new_primary; |
822 new_primary->is_primary = true; | 855 new_primary->is_primary = true; |
823 DVLOG(1) << "New primary config. orbit: " | 856 DVLOG(1) << "New primary config. orbit: " |
824 << base::HexEncode( | 857 << base::HexEncode( |
825 reinterpret_cast<const char*>(primary_config_->orbit), | 858 reinterpret_cast<const char*>(primary_config_->orbit), |
826 kOrbitSize); | 859 kOrbitSize) |
| 860 << " scid: " << base::HexEncode(primary_config_->id.data(), |
| 861 primary_config_->id.size()); |
827 next_config_promotion_time_ = QuicWallTime::Zero(); | 862 next_config_promotion_time_ = QuicWallTime::Zero(); |
828 if (primary_config_changed_cb_.get() != NULL) { | 863 if (primary_config_changed_cb_.get() != NULL) { |
829 primary_config_changed_cb_->Run(primary_config_->id); | 864 primary_config_changed_cb_->Run(primary_config_->id); |
830 } | 865 } |
831 } | 866 } |
832 | 867 |
833 void QuicCryptoServerConfig::EvaluateClientHello( | 868 void QuicCryptoServerConfig::EvaluateClientHello( |
834 const uint8* primary_orbit, | 869 const uint8* primary_orbit, |
| 870 scoped_refptr<Config> requested_config, |
835 ValidateClientHelloResultCallback::Result* client_hello_state, | 871 ValidateClientHelloResultCallback::Result* client_hello_state, |
836 ValidateClientHelloResultCallback* done_cb) const { | 872 ValidateClientHelloResultCallback* done_cb) const { |
837 ValidateClientHelloHelper helper(client_hello_state, done_cb); | 873 ValidateClientHelloHelper helper(client_hello_state, done_cb); |
838 | 874 |
839 const CryptoHandshakeMessage& client_hello = | 875 const CryptoHandshakeMessage& client_hello = |
840 client_hello_state->client_hello; | 876 client_hello_state->client_hello; |
841 ClientHelloInfo* info = &(client_hello_state->info); | 877 ClientHelloInfo* info = &(client_hello_state->info); |
842 | 878 |
843 if (client_hello.size() < kClientHelloMinimumSize) { | 879 if (client_hello.size() < kClientHelloMinimumSize) { |
844 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH, | 880 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH, |
845 "Client hello too small"); | 881 "Client hello too small"); |
846 return; | 882 return; |
847 } | 883 } |
848 | 884 |
849 if (client_hello.GetStringPiece(kSNI, &info->sni) && | 885 if (client_hello.GetStringPiece(kSNI, &info->sni) && |
850 !CryptoUtils::IsValidSNI(info->sni)) { | 886 !CryptoUtils::IsValidSNI(info->sni)) { |
851 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, | 887 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, |
852 "Invalid SNI name"); | 888 "Invalid SNI name"); |
853 return; | 889 return; |
854 } | 890 } |
855 | 891 |
856 StringPiece srct; | 892 StringPiece srct; |
857 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) && | 893 if (requested_config.get() != NULL && |
858 ValidateSourceAddressToken(srct, info->client_ip, info->now)) { | 894 client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) && |
| 895 ValidateSourceAddressToken(*requested_config, |
| 896 srct, |
| 897 info->client_ip, |
| 898 info->now)) { |
859 info->valid_source_address_token = true; | 899 info->valid_source_address_token = true; |
860 } else { | 900 } else { |
861 // No valid source address token. | 901 // No server config with the requested ID, or no valid source address token. |
862 helper.ValidationComplete(QUIC_NO_ERROR, ""); | 902 helper.ValidationComplete(QUIC_NO_ERROR, ""); |
863 return; | 903 return; |
864 } | 904 } |
865 | 905 |
866 if (client_hello.GetStringPiece(kNONC, &info->client_nonce) && | 906 if (client_hello.GetStringPiece(kNONC, &info->client_nonce) && |
867 info->client_nonce.size() == kNonceSize) { | 907 info->client_nonce.size() == kNonceSize) { |
868 info->client_nonce_well_formed = true; | 908 info->client_nonce_well_formed = true; |
869 } else { | 909 } else { |
870 // Invalid client nonce. | 910 // Invalid client nonce. |
871 DVLOG(1) << "Invalid client nonce."; | 911 DVLOG(1) << "Invalid client nonce."; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 } | 948 } |
909 | 949 |
910 strike_register_client->VerifyNonceIsValidAndUnique( | 950 strike_register_client->VerifyNonceIsValidAndUnique( |
911 info->client_nonce, | 951 info->client_nonce, |
912 info->now, | 952 info->now, |
913 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb)); | 953 new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb)); |
914 helper.StartedAsyncCallback(); | 954 helper.StartedAsyncCallback(); |
915 } | 955 } |
916 | 956 |
917 void QuicCryptoServerConfig::BuildRejection( | 957 void QuicCryptoServerConfig::BuildRejection( |
918 const scoped_refptr<Config>& config, | 958 const Config& config, |
919 const CryptoHandshakeMessage& client_hello, | 959 const CryptoHandshakeMessage& client_hello, |
920 const ClientHelloInfo& info, | 960 const ClientHelloInfo& info, |
921 QuicRandom* rand, | 961 QuicRandom* rand, |
922 CryptoHandshakeMessage* out) const { | 962 CryptoHandshakeMessage* out) const { |
923 out->set_tag(kREJ); | 963 out->set_tag(kREJ); |
924 out->SetStringPiece(kSCFG, config->serialized); | 964 out->SetStringPiece(kSCFG, config.serialized); |
925 out->SetStringPiece(kSourceAddressTokenTag, | 965 out->SetStringPiece(kSourceAddressTokenTag, |
926 NewSourceAddressToken(info.client_ip, rand, info.now)); | 966 NewSourceAddressToken( |
| 967 config, |
| 968 info.client_ip, |
| 969 rand, |
| 970 info.now)); |
927 if (replay_protection_) { | 971 if (replay_protection_) { |
928 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now)); | 972 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now)); |
929 } | 973 } |
930 | 974 |
931 // The client may have requested a certificate chain. | 975 // The client may have requested a certificate chain. |
932 const QuicTag* their_proof_demands; | 976 const QuicTag* their_proof_demands; |
933 size_t num_their_proof_demands; | 977 size_t num_their_proof_demands; |
934 | 978 |
935 if (proof_source_.get() == NULL || | 979 if (proof_source_.get() == NULL || |
936 client_hello.GetTaglist(kPDMD, &their_proof_demands, | 980 client_hello.GetTaglist(kPDMD, &their_proof_demands, |
(...skipping 14 matching lines...) Expand all Loading... |
951 break; | 995 break; |
952 } | 996 } |
953 } | 997 } |
954 | 998 |
955 if (!x509_supported) { | 999 if (!x509_supported) { |
956 return; | 1000 return; |
957 } | 1001 } |
958 | 1002 |
959 const vector<string>* certs; | 1003 const vector<string>* certs; |
960 string signature; | 1004 string signature; |
961 if (!proof_source_->GetProof(info.sni.as_string(), config->serialized, | 1005 if (!proof_source_->GetProof(info.sni.as_string(), config.serialized, |
962 x509_ecdsa_supported, &certs, &signature)) { | 1006 x509_ecdsa_supported, &certs, &signature)) { |
963 return; | 1007 return; |
964 } | 1008 } |
965 | 1009 |
966 StringPiece their_common_set_hashes; | 1010 StringPiece their_common_set_hashes; |
967 StringPiece their_cached_cert_hashes; | 1011 StringPiece their_cached_cert_hashes; |
968 client_hello.GetStringPiece(kCCS, &their_common_set_hashes); | 1012 client_hello.GetStringPiece(kCCS, &their_common_set_hashes); |
969 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes); | 1013 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes); |
970 | 1014 |
971 const string compressed = CertCompressor::CompressChain( | 1015 const string compressed = CertCompressor::CompressChain( |
972 *certs, their_common_set_hashes, their_cached_cert_hashes, | 1016 *certs, their_common_set_hashes, their_cached_cert_hashes, |
973 config->common_cert_sets); | 1017 config.common_cert_sets); |
974 | 1018 |
975 // kREJOverheadBytes is a very rough estimate of how much of a REJ | 1019 // kREJOverheadBytes is a very rough estimate of how much of a REJ |
976 // message is taken up by things other than the certificates. | 1020 // message is taken up by things other than the certificates. |
977 // STK: 56 bytes | 1021 // STK: 56 bytes |
978 // SNO: 56 bytes | 1022 // SNO: 56 bytes |
979 // SCFG | 1023 // SCFG |
980 // SCID: 16 bytes | 1024 // SCID: 16 bytes |
981 // PUBS: 38 bytes | 1025 // PUBS: 38 bytes |
982 const size_t kREJOverheadBytes = 166; | 1026 const size_t kREJOverheadBytes = 166; |
983 // kMultiplier is the multiple of the CHLO message size that a REJ message | 1027 // kMultiplier is the multiple of the CHLO message size that a REJ message |
(...skipping 22 matching lines...) Expand all Loading... |
1006 | 1050 |
1007 if (msg->tag() != kSCFG) { | 1051 if (msg->tag() != kSCFG) { |
1008 LOG(WARNING) << "Server config message has tag " << msg->tag() | 1052 LOG(WARNING) << "Server config message has tag " << msg->tag() |
1009 << " expected " << kSCFG; | 1053 << " expected " << kSCFG; |
1010 return NULL; | 1054 return NULL; |
1011 } | 1055 } |
1012 | 1056 |
1013 scoped_refptr<Config> config(new Config); | 1057 scoped_refptr<Config> config(new Config); |
1014 config->serialized = protobuf->config(); | 1058 config->serialized = protobuf->config(); |
1015 | 1059 |
| 1060 if (!protobuf->has_source_address_token_secret_override()) { |
| 1061 // Use the default boxer. |
| 1062 config->source_address_token_boxer = &default_source_address_token_boxer_; |
| 1063 } else { |
| 1064 // Create override boxer instance. |
| 1065 CryptoSecretBoxer* boxer = new CryptoSecretBoxer; |
| 1066 boxer->SetKey(DeriveSourceAddressTokenKey( |
| 1067 protobuf->source_address_token_secret_override())); |
| 1068 config->source_address_token_boxer_storage.reset(boxer); |
| 1069 config->source_address_token_boxer = boxer; |
| 1070 } |
| 1071 |
1016 if (protobuf->has_primary_time()) { | 1072 if (protobuf->has_primary_time()) { |
1017 config->primary_time = | 1073 config->primary_time = |
1018 QuicWallTime::FromUNIXSeconds(protobuf->primary_time()); | 1074 QuicWallTime::FromUNIXSeconds(protobuf->primary_time()); |
1019 } | 1075 } |
1020 | 1076 |
1021 config->priority = protobuf->priority(); | 1077 config->priority = protobuf->priority(); |
1022 | 1078 |
1023 StringPiece scid; | 1079 StringPiece scid; |
1024 if (!msg->GetStringPiece(kSCID, &scid)) { | 1080 if (!msg->GetStringPiece(kSCID, &scid)) { |
1025 LOG(WARNING) << "Server config message is missing SCID"; | 1081 LOG(WARNING) << "Server config message is missing SCID"; |
(...skipping 11 matching lines...) Expand all Loading... |
1037 | 1093 |
1038 const QuicTag* kexs_tags; | 1094 const QuicTag* kexs_tags; |
1039 size_t kexs_len; | 1095 size_t kexs_len; |
1040 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) { | 1096 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) { |
1041 LOG(WARNING) << "Server config message is missing KEXS"; | 1097 LOG(WARNING) << "Server config message is missing KEXS"; |
1042 return NULL; | 1098 return NULL; |
1043 } | 1099 } |
1044 | 1100 |
1045 StringPiece orbit; | 1101 StringPiece orbit; |
1046 if (!msg->GetStringPiece(kORBT, &orbit)) { | 1102 if (!msg->GetStringPiece(kORBT, &orbit)) { |
1047 LOG(WARNING) << "Server config message is missing OBIT"; | 1103 LOG(WARNING) << "Server config message is missing ORBT"; |
1048 return NULL; | 1104 return NULL; |
1049 } | 1105 } |
1050 | 1106 |
1051 if (orbit.size() != kOrbitSize) { | 1107 if (orbit.size() != kOrbitSize) { |
1052 LOG(WARNING) << "Orbit value in server config is the wrong length." | 1108 LOG(WARNING) << "Orbit value in server config is the wrong length." |
1053 " Got " << orbit.size() << " want " << kOrbitSize; | 1109 " Got " << orbit.size() << " want " << kOrbitSize; |
1054 return NULL; | 1110 return NULL; |
1055 } | 1111 } |
1056 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size); | 1112 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size); |
1057 memcpy(config->orbit, orbit.data(), sizeof(config->orbit)); | 1113 memcpy(config->orbit, orbit.data(), sizeof(config->orbit)); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 server_nonce_strike_register_window_secs_ = window_secs; | 1267 server_nonce_strike_register_window_secs_ = window_secs; |
1212 } | 1268 } |
1213 | 1269 |
1214 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb( | 1270 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb( |
1215 PrimaryConfigChangedCallback* cb) { | 1271 PrimaryConfigChangedCallback* cb) { |
1216 base::AutoLock locked(configs_lock_); | 1272 base::AutoLock locked(configs_lock_); |
1217 primary_config_changed_cb_.reset(cb); | 1273 primary_config_changed_cb_.reset(cb); |
1218 } | 1274 } |
1219 | 1275 |
1220 string QuicCryptoServerConfig::NewSourceAddressToken( | 1276 string QuicCryptoServerConfig::NewSourceAddressToken( |
| 1277 const Config& config, |
1221 const IPEndPoint& ip, | 1278 const IPEndPoint& ip, |
1222 QuicRandom* rand, | 1279 QuicRandom* rand, |
1223 QuicWallTime now) const { | 1280 QuicWallTime now) const { |
1224 SourceAddressToken source_address_token; | 1281 SourceAddressToken source_address_token; |
1225 source_address_token.set_ip(IPAddressToPackedString(ip.address())); | 1282 source_address_token.set_ip(IPAddressToPackedString(ip.address())); |
1226 source_address_token.set_timestamp(now.ToUNIXSeconds()); | 1283 source_address_token.set_timestamp(now.ToUNIXSeconds()); |
1227 | 1284 |
1228 return source_address_token_boxer_.Box( | 1285 return config.source_address_token_boxer->Box( |
1229 rand, source_address_token.SerializeAsString()); | 1286 rand, source_address_token.SerializeAsString()); |
1230 } | 1287 } |
1231 | 1288 |
1232 bool QuicCryptoServerConfig::ValidateSourceAddressToken( | 1289 bool QuicCryptoServerConfig::ValidateSourceAddressToken( |
| 1290 const Config& config, |
1233 StringPiece token, | 1291 StringPiece token, |
1234 const IPEndPoint& ip, | 1292 const IPEndPoint& ip, |
1235 QuicWallTime now) const { | 1293 QuicWallTime now) const { |
1236 string storage; | 1294 string storage; |
1237 StringPiece plaintext; | 1295 StringPiece plaintext; |
1238 if (!source_address_token_boxer_.Unbox(token, &storage, &plaintext)) { | 1296 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) { |
1239 return false; | 1297 return false; |
1240 } | 1298 } |
1241 | 1299 |
1242 SourceAddressToken source_address_token; | 1300 SourceAddressToken source_address_token; |
1243 if (!source_address_token.ParseFromArray(plaintext.data(), | 1301 if (!source_address_token.ParseFromArray(plaintext.data(), |
1244 plaintext.size())) { | 1302 plaintext.size())) { |
1245 return false; | 1303 return false; |
1246 } | 1304 } |
1247 | 1305 |
1248 if (source_address_token.ip() != IPAddressToPackedString(ip.address())) { | 1306 if (source_address_token.ip() != IPAddressToPackedString(ip.address())) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 server_nonce, static_cast<uint32>(now.ToUNIXSeconds())); | 1388 server_nonce, static_cast<uint32>(now.ToUNIXSeconds())); |
1331 } | 1389 } |
1332 | 1390 |
1333 return is_unique; | 1391 return is_unique; |
1334 } | 1392 } |
1335 | 1393 |
1336 QuicCryptoServerConfig::Config::Config() | 1394 QuicCryptoServerConfig::Config::Config() |
1337 : channel_id_enabled(false), | 1395 : channel_id_enabled(false), |
1338 is_primary(false), | 1396 is_primary(false), |
1339 primary_time(QuicWallTime::Zero()), | 1397 primary_time(QuicWallTime::Zero()), |
1340 priority(0) {} | 1398 priority(0), |
| 1399 source_address_token_boxer(NULL) {} |
1341 | 1400 |
1342 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } | 1401 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } |
1343 | 1402 |
1344 } // namespace net | 1403 } // namespace net |
OLD | NEW |