| 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_client_config.h" | 5 #include "net/quic/crypto/quic_crypto_client_config.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "base/metrics/sparse_histogram.h" | 8 #include "base/metrics/sparse_histogram.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 return true; | 104 return true; |
| 105 } | 105 } |
| 106 | 106 |
| 107 bool QuicCryptoClientConfig::CachedState::IsEmpty() const { | 107 bool QuicCryptoClientConfig::CachedState::IsEmpty() const { |
| 108 return server_config_.empty(); | 108 return server_config_.empty(); |
| 109 } | 109 } |
| 110 | 110 |
| 111 const CryptoHandshakeMessage* | 111 const CryptoHandshakeMessage* |
| 112 QuicCryptoClientConfig::CachedState::GetServerConfig() const { | 112 QuicCryptoClientConfig::CachedState::GetServerConfig() const { |
| 113 if (server_config_.empty()) { | 113 if (server_config_.empty()) { |
| 114 return NULL; | 114 return nullptr; |
| 115 } | 115 } |
| 116 | 116 |
| 117 if (!scfg_.get()) { | 117 if (!scfg_.get()) { |
| 118 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); | 118 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); |
| 119 DCHECK(scfg_.get()); | 119 DCHECK(scfg_.get()); |
| 120 } | 120 } |
| 121 return scfg_.get(); | 121 return scfg_.get(); |
| 122 } | 122 } |
| 123 | 123 |
| 124 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig( | 124 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig( |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 | 285 |
| 286 void QuicCryptoClientConfig::CachedState::InitializeFrom( | 286 void QuicCryptoClientConfig::CachedState::InitializeFrom( |
| 287 const QuicCryptoClientConfig::CachedState& other) { | 287 const QuicCryptoClientConfig::CachedState& other) { |
| 288 DCHECK(server_config_.empty()); | 288 DCHECK(server_config_.empty()); |
| 289 DCHECK(!server_config_valid_); | 289 DCHECK(!server_config_valid_); |
| 290 server_config_ = other.server_config_; | 290 server_config_ = other.server_config_; |
| 291 source_address_token_ = other.source_address_token_; | 291 source_address_token_ = other.source_address_token_; |
| 292 certs_ = other.certs_; | 292 certs_ = other.certs_; |
| 293 server_config_sig_ = other.server_config_sig_; | 293 server_config_sig_ = other.server_config_sig_; |
| 294 server_config_valid_ = other.server_config_valid_; | 294 server_config_valid_ = other.server_config_valid_; |
| 295 if (other.proof_verify_details_.get() != NULL) { | 295 if (other.proof_verify_details_.get() != nullptr) { |
| 296 proof_verify_details_.reset(other.proof_verify_details_->Clone()); | 296 proof_verify_details_.reset(other.proof_verify_details_->Clone()); |
| 297 } | 297 } |
| 298 ++generation_counter_; | 298 ++generation_counter_; |
| 299 } | 299 } |
| 300 | 300 |
| 301 void QuicCryptoClientConfig::SetDefaults() { | 301 void QuicCryptoClientConfig::SetDefaults() { |
| 302 // Key exchange methods. | 302 // Key exchange methods. |
| 303 kexs.resize(2); | 303 kexs.resize(2); |
| 304 kexs[0] = kC255; | 304 kexs[0] = kC255; |
| 305 kexs[1] = kP256; | 305 kexs[1] = kP256; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 const QuicServerId& server_id, | 391 const QuicServerId& server_id, |
| 392 QuicConnectionId connection_id, | 392 QuicConnectionId connection_id, |
| 393 const QuicVersion preferred_version, | 393 const QuicVersion preferred_version, |
| 394 const CachedState* cached, | 394 const CachedState* cached, |
| 395 QuicWallTime now, | 395 QuicWallTime now, |
| 396 QuicRandom* rand, | 396 QuicRandom* rand, |
| 397 const ChannelIDKey* channel_id_key, | 397 const ChannelIDKey* channel_id_key, |
| 398 QuicCryptoNegotiatedParameters* out_params, | 398 QuicCryptoNegotiatedParameters* out_params, |
| 399 CryptoHandshakeMessage* out, | 399 CryptoHandshakeMessage* out, |
| 400 string* error_details) const { | 400 string* error_details) const { |
| 401 DCHECK(error_details != NULL); | 401 DCHECK(error_details != nullptr); |
| 402 | 402 |
| 403 FillInchoateClientHello(server_id, preferred_version, cached, | 403 FillInchoateClientHello(server_id, preferred_version, cached, |
| 404 out_params, out); | 404 out_params, out); |
| 405 | 405 |
| 406 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); | 406 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); |
| 407 if (!scfg) { | 407 if (!scfg) { |
| 408 // This should never happen as our caller should have checked | 408 // This should never happen as our caller should have checked |
| 409 // cached->IsComplete() before calling this function. | 409 // cached->IsComplete() before calling this function. |
| 410 *error_details = "Handshake not ready"; | 410 *error_details = "Handshake not ready"; |
| 411 return QUIC_CRYPTO_INTERNAL_ERROR; | 411 return QUIC_CRYPTO_INTERNAL_ERROR; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 430 } | 430 } |
| 431 | 431 |
| 432 // AEAD: the work loads on the client and server are symmetric. Since the | 432 // AEAD: the work loads on the client and server are symmetric. Since the |
| 433 // client is more likely to be CPU-constrained, break the tie by favoring | 433 // client is more likely to be CPU-constrained, break the tie by favoring |
| 434 // the client's preference. | 434 // the client's preference. |
| 435 // Key exchange: the client does more work than the server, so favor the | 435 // Key exchange: the client does more work than the server, so favor the |
| 436 // client's preference. | 436 // client's preference. |
| 437 size_t key_exchange_index; | 437 size_t key_exchange_index; |
| 438 if (!QuicUtils::FindMutualTag( | 438 if (!QuicUtils::FindMutualTag( |
| 439 aead, their_aeads, num_their_aeads, QuicUtils::LOCAL_PRIORITY, | 439 aead, their_aeads, num_their_aeads, QuicUtils::LOCAL_PRIORITY, |
| 440 &out_params->aead, NULL) || | 440 &out_params->aead, nullptr) || |
| 441 !QuicUtils::FindMutualTag( | 441 !QuicUtils::FindMutualTag( |
| 442 kexs, their_key_exchanges, num_their_key_exchanges, | 442 kexs, their_key_exchanges, num_their_key_exchanges, |
| 443 QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange, | 443 QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange, |
| 444 &key_exchange_index)) { | 444 &key_exchange_index)) { |
| 445 *error_details = "Unsupported AEAD or KEXS"; | 445 *error_details = "Unsupported AEAD or KEXS"; |
| 446 return QUIC_CRYPTO_NO_SUPPORT; | 446 return QUIC_CRYPTO_NO_SUPPORT; |
| 447 } | 447 } |
| 448 out->SetTaglist(kAEAD, out_params->aead, 0); | 448 out->SetTaglist(kAEAD, out_params->aead, 0); |
| 449 out->SetTaglist(kKEXS, out_params->key_exchange, 0); | 449 out->SetTaglist(kKEXS, out_params->key_exchange, 0); |
| 450 | 450 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 } | 517 } |
| 518 | 518 |
| 519 cetv.SetStringPiece(kCIDK, key); | 519 cetv.SetStringPiece(kCIDK, key); |
| 520 cetv.SetStringPiece(kCIDS, signature); | 520 cetv.SetStringPiece(kCIDS, signature); |
| 521 | 521 |
| 522 CrypterPair crypters; | 522 CrypterPair crypters; |
| 523 if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, | 523 if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, |
| 524 out_params->aead, out_params->client_nonce, | 524 out_params->aead, out_params->client_nonce, |
| 525 out_params->server_nonce, hkdf_input, | 525 out_params->server_nonce, hkdf_input, |
| 526 CryptoUtils::CLIENT, &crypters, | 526 CryptoUtils::CLIENT, &crypters, |
| 527 NULL /* subkey secret */)) { | 527 nullptr /* subkey secret */)) { |
| 528 *error_details = "Symmetric key setup failed"; | 528 *error_details = "Symmetric key setup failed"; |
| 529 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; | 529 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; |
| 530 } | 530 } |
| 531 | 531 |
| 532 const QuicData& cetv_plaintext = cetv.GetSerialized(); | 532 const QuicData& cetv_plaintext = cetv.GetSerialized(); |
| 533 scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket( | 533 scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket( |
| 534 0 /* sequence number */, | 534 0 /* sequence number */, |
| 535 StringPiece() /* associated data */, | 535 StringPiece() /* associated data */, |
| 536 cetv_plaintext.AsStringPiece())); | 536 cetv_plaintext.AsStringPiece())); |
| 537 if (!cetv_ciphertext.get()) { | 537 if (!cetv_ciphertext.get()) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 560 string hkdf_input; | 560 string hkdf_input; |
| 561 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; | 561 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; |
| 562 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); | 562 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); |
| 563 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); | 563 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); |
| 564 hkdf_input.append(out_params->hkdf_input_suffix); | 564 hkdf_input.append(out_params->hkdf_input_suffix); |
| 565 | 565 |
| 566 if (!CryptoUtils::DeriveKeys( | 566 if (!CryptoUtils::DeriveKeys( |
| 567 out_params->initial_premaster_secret, out_params->aead, | 567 out_params->initial_premaster_secret, out_params->aead, |
| 568 out_params->client_nonce, out_params->server_nonce, hkdf_input, | 568 out_params->client_nonce, out_params->server_nonce, hkdf_input, |
| 569 CryptoUtils::CLIENT, &out_params->initial_crypters, | 569 CryptoUtils::CLIENT, &out_params->initial_crypters, |
| 570 NULL /* subkey secret */)) { | 570 nullptr /* subkey secret */)) { |
| 571 *error_details = "Symmetric key setup failed"; | 571 *error_details = "Symmetric key setup failed"; |
| 572 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; | 572 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; |
| 573 } | 573 } |
| 574 | 574 |
| 575 return QUIC_NO_ERROR; | 575 return QUIC_NO_ERROR; |
| 576 } | 576 } |
| 577 | 577 |
| 578 QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig( | 578 QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig( |
| 579 const CryptoHandshakeMessage& message, | 579 const CryptoHandshakeMessage& message, |
| 580 QuicWallTime now, | 580 QuicWallTime now, |
| 581 const vector<string>& cached_certs, | 581 const vector<string>& cached_certs, |
| 582 CachedState* cached, | 582 CachedState* cached, |
| 583 string* error_details) { | 583 string* error_details) { |
| 584 DCHECK(error_details != NULL); | 584 DCHECK(error_details != nullptr); |
| 585 | 585 |
| 586 StringPiece scfg; | 586 StringPiece scfg; |
| 587 if (!message.GetStringPiece(kSCFG, &scfg)) { | 587 if (!message.GetStringPiece(kSCFG, &scfg)) { |
| 588 *error_details = "Missing SCFG"; | 588 *error_details = "Missing SCFG"; |
| 589 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | 589 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; |
| 590 } | 590 } |
| 591 | 591 |
| 592 QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details); | 592 QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details); |
| 593 if (error != QUIC_NO_ERROR) { | 593 if (error != QUIC_NO_ERROR) { |
| 594 return error; | 594 return error; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 605 if (has_proof && has_cert) { | 605 if (has_proof && has_cert) { |
| 606 vector<string> certs; | 606 vector<string> certs; |
| 607 if (!CertCompressor::DecompressChain(cert_bytes, cached_certs, | 607 if (!CertCompressor::DecompressChain(cert_bytes, cached_certs, |
| 608 common_cert_sets, &certs)) { | 608 common_cert_sets, &certs)) { |
| 609 *error_details = "Certificate data invalid"; | 609 *error_details = "Certificate data invalid"; |
| 610 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 610 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 611 } | 611 } |
| 612 | 612 |
| 613 cached->SetProof(certs, proof); | 613 cached->SetProof(certs, proof); |
| 614 } else { | 614 } else { |
| 615 if (proof_verifier() != NULL) { | 615 if (proof_verifier() != nullptr) { |
| 616 // Secure QUIC: clear existing proof as we have been sent a new SCFG | 616 // Secure QUIC: clear existing proof as we have been sent a new SCFG |
| 617 // without matching proof/certs. | 617 // without matching proof/certs. |
| 618 cached->ClearProof(); | 618 cached->ClearProof(); |
| 619 } | 619 } |
| 620 | 620 |
| 621 if (has_proof && !has_cert) { | 621 if (has_proof && !has_cert) { |
| 622 *error_details = "Certificate missing"; | 622 *error_details = "Certificate missing"; |
| 623 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 623 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 624 } | 624 } |
| 625 | 625 |
| 626 if (!has_proof && has_cert) { | 626 if (!has_proof && has_cert) { |
| 627 *error_details = "Proof missing"; | 627 *error_details = "Proof missing"; |
| 628 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 628 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 629 } | 629 } |
| 630 } | 630 } |
| 631 | 631 |
| 632 return QUIC_NO_ERROR; | 632 return QUIC_NO_ERROR; |
| 633 } | 633 } |
| 634 | 634 |
| 635 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( | 635 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( |
| 636 const CryptoHandshakeMessage& rej, | 636 const CryptoHandshakeMessage& rej, |
| 637 QuicWallTime now, | 637 QuicWallTime now, |
| 638 CachedState* cached, | 638 CachedState* cached, |
| 639 bool is_https, | 639 bool is_https, |
| 640 QuicCryptoNegotiatedParameters* out_params, | 640 QuicCryptoNegotiatedParameters* out_params, |
| 641 string* error_details) { | 641 string* error_details) { |
| 642 DCHECK(error_details != NULL); | 642 DCHECK(error_details != nullptr); |
| 643 | 643 |
| 644 if (rej.tag() != kREJ) { | 644 if (rej.tag() != kREJ) { |
| 645 *error_details = "Message is not REJ"; | 645 *error_details = "Message is not REJ"; |
| 646 return QUIC_CRYPTO_INTERNAL_ERROR; | 646 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 647 } | 647 } |
| 648 | 648 |
| 649 QuicErrorCode error = CacheNewServerConfig(rej, now, out_params->cached_certs, | 649 QuicErrorCode error = CacheNewServerConfig(rej, now, out_params->cached_certs, |
| 650 cached, error_details); | 650 cached, error_details); |
| 651 if (error != QUIC_NO_ERROR) { | 651 if (error != QUIC_NO_ERROR) { |
| 652 return error; | 652 return error; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 return QUIC_NO_ERROR; | 685 return QUIC_NO_ERROR; |
| 686 } | 686 } |
| 687 | 687 |
| 688 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( | 688 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( |
| 689 const CryptoHandshakeMessage& server_hello, | 689 const CryptoHandshakeMessage& server_hello, |
| 690 QuicConnectionId connection_id, | 690 QuicConnectionId connection_id, |
| 691 const QuicVersionVector& negotiated_versions, | 691 const QuicVersionVector& negotiated_versions, |
| 692 CachedState* cached, | 692 CachedState* cached, |
| 693 QuicCryptoNegotiatedParameters* out_params, | 693 QuicCryptoNegotiatedParameters* out_params, |
| 694 string* error_details) { | 694 string* error_details) { |
| 695 DCHECK(error_details != NULL); | 695 DCHECK(error_details != nullptr); |
| 696 | 696 |
| 697 if (server_hello.tag() != kSHLO) { | 697 if (server_hello.tag() != kSHLO) { |
| 698 *error_details = "Bad tag"; | 698 *error_details = "Bad tag"; |
| 699 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; | 699 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; |
| 700 } | 700 } |
| 701 | 701 |
| 702 const QuicTag* supported_version_tags; | 702 const QuicTag* supported_version_tags; |
| 703 size_t num_supported_versions; | 703 size_t num_supported_versions; |
| 704 | 704 |
| 705 if (server_hello.GetTaglist(kVER, &supported_version_tags, | 705 if (server_hello.GetTaglist(kVER, &supported_version_tags, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 | 760 |
| 761 return QUIC_NO_ERROR; | 761 return QUIC_NO_ERROR; |
| 762 } | 762 } |
| 763 | 763 |
| 764 QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate( | 764 QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate( |
| 765 const CryptoHandshakeMessage& server_config_update, | 765 const CryptoHandshakeMessage& server_config_update, |
| 766 QuicWallTime now, | 766 QuicWallTime now, |
| 767 CachedState* cached, | 767 CachedState* cached, |
| 768 QuicCryptoNegotiatedParameters* out_params, | 768 QuicCryptoNegotiatedParameters* out_params, |
| 769 string* error_details) { | 769 string* error_details) { |
| 770 DCHECK(error_details != NULL); | 770 DCHECK(error_details != nullptr); |
| 771 | 771 |
| 772 if (server_config_update.tag() != kSCUP) { | 772 if (server_config_update.tag() != kSCUP) { |
| 773 *error_details = "ServerConfigUpdate must have kSCUP tag."; | 773 *error_details = "ServerConfigUpdate must have kSCUP tag."; |
| 774 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; | 774 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; |
| 775 } | 775 } |
| 776 | 776 |
| 777 return CacheNewServerConfig(server_config_update, now, | 777 return CacheNewServerConfig(server_config_update, now, |
| 778 out_params->cached_certs, cached, error_details); | 778 out_params->cached_certs, cached, error_details); |
| 779 } | 779 } |
| 780 | 780 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 return; | 857 return; |
| 858 } | 858 } |
| 859 | 859 |
| 860 // Update canonical version to point at the "most recent" entry. | 860 // Update canonical version to point at the "most recent" entry. |
| 861 canonical_server_map_[suffix_server_id] = server_id; | 861 canonical_server_map_[suffix_server_id] = server_id; |
| 862 | 862 |
| 863 server_state->InitializeFrom(*canonical_state); | 863 server_state->InitializeFrom(*canonical_state); |
| 864 } | 864 } |
| 865 | 865 |
| 866 } // namespace net | 866 } // namespace net |
| OLD | NEW |