Home | History | Annotate | Download | only in crypto
      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
      3 // found in the LICENSE file.
      4 
      5 #include "net/quic/crypto/quic_crypto_client_config.h"
      6 
      7 #include "base/stl_util.h"
      8 #include "base/strings/string_util.h"
      9 #include "net/quic/crypto/cert_compressor.h"
     10 #include "net/quic/crypto/chacha20_poly1305_encrypter.h"
     11 #include "net/quic/crypto/channel_id.h"
     12 #include "net/quic/crypto/common_cert_set.h"
     13 #include "net/quic/crypto/crypto_framer.h"
     14 #include "net/quic/crypto/crypto_utils.h"
     15 #include "net/quic/crypto/curve25519_key_exchange.h"
     16 #include "net/quic/crypto/key_exchange.h"
     17 #include "net/quic/crypto/p256_key_exchange.h"
     18 #include "net/quic/crypto/proof_verifier.h"
     19 #include "net/quic/crypto/quic_encrypter.h"
     20 #include "net/quic/quic_utils.h"
     21 
     22 using base::StringPiece;
     23 using std::find;
     24 using std::make_pair;
     25 using std::map;
     26 using std::string;
     27 using std::vector;
     28 
     29 namespace net {
     30 
     31 QuicCryptoClientConfig::QuicCryptoClientConfig()
     32     : disable_ecdsa_(false) {}
     33 
     34 QuicCryptoClientConfig::~QuicCryptoClientConfig() {
     35   STLDeleteValues(&cached_states_);
     36 }
     37 
     38 QuicCryptoClientConfig::CachedState::CachedState()
     39     : server_config_valid_(false),
     40       generation_counter_(0) {}
     41 
     42 QuicCryptoClientConfig::CachedState::~CachedState() {}
     43 
     44 bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const {
     45   if (server_config_.empty() || !server_config_valid_) {
     46     return false;
     47   }
     48 
     49   const CryptoHandshakeMessage* scfg = GetServerConfig();
     50   if (!scfg) {
     51     // Should be impossible short of cache corruption.
     52     DCHECK(false);
     53     return false;
     54   }
     55 
     56   uint64 expiry_seconds;
     57   if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR ||
     58       now.ToUNIXSeconds() >= expiry_seconds) {
     59     return false;
     60   }
     61 
     62   return true;
     63 }
     64 
     65 bool QuicCryptoClientConfig::CachedState::IsEmpty() const {
     66   return server_config_.empty();
     67 }
     68 
     69 const CryptoHandshakeMessage*
     70 QuicCryptoClientConfig::CachedState::GetServerConfig() const {
     71   if (server_config_.empty()) {
     72     return NULL;
     73   }
     74 
     75   if (!scfg_.get()) {
     76     scfg_.reset(CryptoFramer::ParseMessage(server_config_));
     77     DCHECK(scfg_.get());
     78   }
     79   return scfg_.get();
     80 }
     81 
     82 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig(
     83     StringPiece server_config, QuicWallTime now, string* error_details) {
     84   const bool matches_existing = server_config == server_config_;
     85 
     86   // Even if the new server config matches the existing one, we still wish to
     87   // reject it if it has expired.
     88   scoped_ptr<CryptoHandshakeMessage> new_scfg_storage;
     89   const CryptoHandshakeMessage* new_scfg;
     90 
     91   if (!matches_existing) {
     92     new_scfg_storage.reset(CryptoFramer::ParseMessage(server_config));
     93     new_scfg = new_scfg_storage.get();
     94   } else {
     95     new_scfg = GetServerConfig();
     96   }
     97 
     98   if (!new_scfg) {
     99     *error_details = "SCFG invalid";
    100     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    101   }
    102 
    103   uint64 expiry_seconds;
    104   if (new_scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
    105     *error_details = "SCFG missing EXPY";
    106     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    107   }
    108 
    109   if (now.ToUNIXSeconds() >= expiry_seconds) {
    110     *error_details = "SCFG has expired";
    111     return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED;
    112   }
    113 
    114   if (!matches_existing) {
    115     server_config_ = server_config.as_string();
    116     SetProofInvalid();
    117     scfg_.reset(new_scfg_storage.release());
    118   }
    119   return QUIC_NO_ERROR;
    120 }
    121 
    122 void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() {
    123   server_config_.clear();
    124   scfg_.reset();
    125   SetProofInvalid();
    126 }
    127 
    128 void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs,
    129                                                    StringPiece signature) {
    130   bool has_changed =
    131       signature != server_config_sig_ || certs_.size() != certs.size();
    132 
    133   if (!has_changed) {
    134     for (size_t i = 0; i < certs_.size(); i++) {
    135       if (certs_[i] != certs[i]) {
    136         has_changed = true;
    137         break;
    138       }
    139     }
    140   }
    141 
    142   if (!has_changed) {
    143     return;
    144   }
    145 
    146   // If the proof has changed then it needs to be revalidated.
    147   SetProofInvalid();
    148   certs_ = certs;
    149   server_config_sig_ = signature.as_string();
    150 }
    151 
    152 void QuicCryptoClientConfig::CachedState::Clear() {
    153   server_config_.clear();
    154   source_address_token_.clear();
    155   certs_.clear();
    156   server_config_sig_.clear();
    157   server_config_valid_ = false;
    158   proof_verify_details_.reset();
    159   scfg_.reset();
    160   ++generation_counter_;
    161 }
    162 
    163 void QuicCryptoClientConfig::CachedState::ClearProof() {
    164   SetProofInvalid();
    165   certs_.clear();
    166   server_config_sig_.clear();
    167 }
    168 
    169 void QuicCryptoClientConfig::CachedState::SetProofValid() {
    170   server_config_valid_ = true;
    171 }
    172 
    173 void QuicCryptoClientConfig::CachedState::SetProofInvalid() {
    174   server_config_valid_ = false;
    175   ++generation_counter_;
    176 }
    177 
    178 bool QuicCryptoClientConfig::CachedState::Initialize(
    179     StringPiece server_config,
    180     StringPiece source_address_token,
    181     const vector<string>& certs,
    182     StringPiece signature,
    183     QuicWallTime now) {
    184   DCHECK(server_config_.empty());
    185 
    186   if (server_config.empty()) {
    187     return false;
    188   }
    189 
    190   string error_details;
    191   QuicErrorCode error = SetServerConfig(server_config, now,
    192                                         &error_details);
    193   if (error != QUIC_NO_ERROR) {
    194     DVLOG(1) << "SetServerConfig failed with " << error_details;
    195     return false;
    196   }
    197 
    198   signature.CopyToString(&server_config_sig_);
    199   source_address_token.CopyToString(&source_address_token_);
    200   certs_ = certs;
    201   return true;
    202 }
    203 
    204 const string& QuicCryptoClientConfig::CachedState::server_config() const {
    205   return server_config_;
    206 }
    207 
    208 const string&
    209 QuicCryptoClientConfig::CachedState::source_address_token() const {
    210   return source_address_token_;
    211 }
    212 
    213 const vector<string>& QuicCryptoClientConfig::CachedState::certs() const {
    214   return certs_;
    215 }
    216 
    217 const string& QuicCryptoClientConfig::CachedState::signature() const {
    218   return server_config_sig_;
    219 }
    220 
    221 bool QuicCryptoClientConfig::CachedState::proof_valid() const {
    222   return server_config_valid_;
    223 }
    224 
    225 uint64 QuicCryptoClientConfig::CachedState::generation_counter() const {
    226   return generation_counter_;
    227 }
    228 
    229 const ProofVerifyDetails*
    230 QuicCryptoClientConfig::CachedState::proof_verify_details() const {
    231   return proof_verify_details_.get();
    232 }
    233 
    234 void QuicCryptoClientConfig::CachedState::set_source_address_token(
    235     StringPiece token) {
    236   source_address_token_ = token.as_string();
    237 }
    238 
    239 void QuicCryptoClientConfig::CachedState::SetProofVerifyDetails(
    240     ProofVerifyDetails* details) {
    241   proof_verify_details_.reset(details);
    242 }
    243 
    244 void QuicCryptoClientConfig::CachedState::InitializeFrom(
    245     const QuicCryptoClientConfig::CachedState& other) {
    246   DCHECK(server_config_.empty());
    247   DCHECK(!server_config_valid_);
    248   server_config_ = other.server_config_;
    249   source_address_token_ = other.source_address_token_;
    250   certs_ = other.certs_;
    251   server_config_sig_ = other.server_config_sig_;
    252   server_config_valid_ = other.server_config_valid_;
    253   ++generation_counter_;
    254 }
    255 
    256 void QuicCryptoClientConfig::SetDefaults() {
    257   // Key exchange methods.
    258   kexs.resize(2);
    259   kexs[0] = kC255;
    260   kexs[1] = kP256;
    261 
    262   // Authenticated encryption algorithms. Prefer ChaCha20 by default.
    263   aead.clear();
    264   if (ChaCha20Poly1305Encrypter::IsSupported()) {
    265     aead.push_back(kCC12);
    266   }
    267   aead.push_back(kAESG);
    268 
    269   disable_ecdsa_ = false;
    270 }
    271 
    272 QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate(
    273     const QuicServerId& server_id) {
    274   CachedStateMap::const_iterator it = cached_states_.find(server_id);
    275   if (it != cached_states_.end()) {
    276     return it->second;
    277   }
    278 
    279   CachedState* cached = new CachedState;
    280   cached_states_.insert(make_pair(server_id, cached));
    281   PopulateFromCanonicalConfig(server_id, cached);
    282   return cached;
    283 }
    284 
    285 void QuicCryptoClientConfig::ClearCachedStates() {
    286   for (CachedStateMap::const_iterator it = cached_states_.begin();
    287        it != cached_states_.end(); ++it) {
    288     it->second->Clear();
    289   }
    290 }
    291 
    292 void QuicCryptoClientConfig::FillInchoateClientHello(
    293     const QuicServerId& server_id,
    294     const QuicVersion preferred_version,
    295     const CachedState* cached,
    296     QuicCryptoNegotiatedParameters* out_params,
    297     CryptoHandshakeMessage* out) const {
    298   out->set_tag(kCHLO);
    299   out->set_minimum_size(kClientHelloMinimumSize);
    300 
    301   // Server name indication. We only send SNI if it's a valid domain name, as
    302   // per the spec.
    303   if (CryptoUtils::IsValidSNI(server_id.host())) {
    304     out->SetStringPiece(kSNI, server_id.host());
    305   }
    306   out->SetValue(kVER, QuicVersionToQuicTag(preferred_version));
    307 
    308   if (!user_agent_id_.empty()) {
    309     out->SetStringPiece(kUAID, user_agent_id_);
    310   }
    311 
    312   if (!cached->source_address_token().empty()) {
    313     out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
    314   }
    315 
    316   if (server_id.is_https()) {
    317     if (disable_ecdsa_) {
    318       out->SetTaglist(kPDMD, kX59R, 0);
    319     } else {
    320       out->SetTaglist(kPDMD, kX509, 0);
    321     }
    322   }
    323 
    324   if (common_cert_sets) {
    325     out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes());
    326   }
    327 
    328   const vector<string>& certs = cached->certs();
    329   // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the
    330   // client config is being used for multiple connections, another connection
    331   // doesn't update the cached certificates and cause us to be unable to
    332   // process the server's compressed certificate chain.
    333   out_params->cached_certs = certs;
    334   if (!certs.empty()) {
    335     vector<uint64> hashes;
    336     hashes.reserve(certs.size());
    337     for (vector<string>::const_iterator i = certs.begin();
    338          i != certs.end(); ++i) {
    339       hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
    340     }
    341     out->SetVector(kCCRT, hashes);
    342   }
    343 }
    344 
    345 QuicErrorCode QuicCryptoClientConfig::FillClientHello(
    346     const QuicServerId& server_id,
    347     QuicConnectionId connection_id,
    348     const QuicVersion preferred_version,
    349     const CachedState* cached,
    350     QuicWallTime now,
    351     QuicRandom* rand,
    352     const ChannelIDKey* channel_id_key,
    353     QuicCryptoNegotiatedParameters* out_params,
    354     CryptoHandshakeMessage* out,
    355     string* error_details) const {
    356   DCHECK(error_details != NULL);
    357 
    358   FillInchoateClientHello(server_id, preferred_version, cached,
    359                           out_params, out);
    360 
    361   const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
    362   if (!scfg) {
    363     // This should never happen as our caller should have checked
    364     // cached->IsComplete() before calling this function.
    365     *error_details = "Handshake not ready";
    366     return QUIC_CRYPTO_INTERNAL_ERROR;
    367   }
    368 
    369   StringPiece scid;
    370   if (!scfg->GetStringPiece(kSCID, &scid)) {
    371     *error_details = "SCFG missing SCID";
    372     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    373   }
    374   out->SetStringPiece(kSCID, scid);
    375 
    376   const QuicTag* their_aeads;
    377   const QuicTag* their_key_exchanges;
    378   size_t num_their_aeads, num_their_key_exchanges;
    379   if (scfg->GetTaglist(kAEAD, &their_aeads,
    380                        &num_their_aeads) != QUIC_NO_ERROR ||
    381       scfg->GetTaglist(kKEXS, &their_key_exchanges,
    382                        &num_their_key_exchanges) != QUIC_NO_ERROR) {
    383     *error_details = "Missing AEAD or KEXS";
    384     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    385   }
    386 
    387   // AEAD: the work loads on the client and server are symmetric. Since the
    388   // client is more likely to be CPU-constrained, break the tie by favoring
    389   // the client's preference.
    390   // Key exchange: the client does more work than the server, so favor the
    391   // client's preference.
    392   size_t key_exchange_index;
    393   if (!QuicUtils::FindMutualTag(
    394           aead, their_aeads, num_their_aeads, QuicUtils::LOCAL_PRIORITY,
    395           &out_params->aead, NULL) ||
    396       !QuicUtils::FindMutualTag(
    397           kexs, their_key_exchanges, num_their_key_exchanges,
    398           QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange,
    399           &key_exchange_index)) {
    400     *error_details = "Unsupported AEAD or KEXS";
    401     return QUIC_CRYPTO_NO_SUPPORT;
    402   }
    403   out->SetTaglist(kAEAD, out_params->aead, 0);
    404   out->SetTaglist(kKEXS, out_params->key_exchange, 0);
    405 
    406   StringPiece public_value;
    407   if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) !=
    408           QUIC_NO_ERROR) {
    409     *error_details = "Missing public value";
    410     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    411   }
    412 
    413   StringPiece orbit;
    414   if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) {
    415     *error_details = "SCFG missing OBIT";
    416     return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
    417   }
    418 
    419   CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce);
    420   out->SetStringPiece(kNONC, out_params->client_nonce);
    421   if (!out_params->server_nonce.empty()) {
    422     out->SetStringPiece(kServerNonceTag, out_params->server_nonce);
    423   }
    424 
    425   switch (out_params->key_exchange) {
    426     case kC255:
    427       out_params->client_key_exchange.reset(Curve25519KeyExchange::New(
    428           Curve25519KeyExchange::NewPrivateKey(rand)));
    429       break;
    430     case kP256:
    431       out_params->client_key_exchange.reset(P256KeyExchange::New(
    432           P256KeyExchange::NewPrivateKey()));
    433       break;
    434     default:
    435       DCHECK(false);
    436       *error_details = "Configured to support an unknown key exchange";
    437       return QUIC_CRYPTO_INTERNAL_ERROR;
    438   }
    439 
    440   if (!out_params->client_key_exchange->CalculateSharedKey(
    441           public_value, &out_params->initial_premaster_secret)) {
    442     *error_details = "Key exchange failure";
    443     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    444   }
    445   out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value());
    446 
    447   if (channel_id_key) {
    448     // In order to calculate the encryption key for the CETV block we need to
    449     // serialise the client hello as it currently is (i.e. without the CETV
    450     // block). For this, the client hello is serialized without padding.
    451     const size_t orig_min_size = out->minimum_size();
    452     out->set_minimum_size(0);
    453 
    454     CryptoHandshakeMessage cetv;
    455     cetv.set_tag(kCETV);
    456 
    457     string hkdf_input;
    458     const QuicData& client_hello_serialized = out->GetSerialized();
    459     hkdf_input.append(QuicCryptoConfig::kCETVLabel,
    460                       strlen(QuicCryptoConfig::kCETVLabel) + 1);
    461     hkdf_input.append(reinterpret_cast<char*>(&connection_id),
    462                       sizeof(connection_id));
    463     hkdf_input.append(client_hello_serialized.data(),
    464                       client_hello_serialized.length());
    465     hkdf_input.append(cached->server_config());
    466 
    467     string key = channel_id_key->SerializeKey();
    468     string signature;
    469     if (!channel_id_key->Sign(hkdf_input, &signature)) {
    470       *error_details = "Channel ID signature failed";
    471       return QUIC_INVALID_CHANNEL_ID_SIGNATURE;
    472     }
    473 
    474     cetv.SetStringPiece(kCIDK, key);
    475     cetv.SetStringPiece(kCIDS, signature);
    476 
    477     CrypterPair crypters;
    478     if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret,
    479                                  out_params->aead, out_params->client_nonce,
    480                                  out_params->server_nonce, hkdf_input,
    481                                  CryptoUtils::CLIENT, &crypters)) {
    482       *error_details = "Symmetric key setup failed";
    483       return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
    484     }
    485 
    486     const QuicData& cetv_plaintext = cetv.GetSerialized();
    487     scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket(
    488         0 /* sequence number */,
    489         StringPiece() /* associated data */,
    490         cetv_plaintext.AsStringPiece()));
    491     if (!cetv_ciphertext.get()) {
    492       *error_details = "Packet encryption failed";
    493       return QUIC_ENCRYPTION_FAILURE;
    494     }
    495 
    496     out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece());
    497     out->MarkDirty();
    498 
    499     out->set_minimum_size(orig_min_size);
    500   }
    501 
    502   // Derive the symmetric keys and set up the encrypters and decrypters.
    503   // Set the following members of out_params:
    504   //   out_params->hkdf_input_suffix
    505   //   out_params->initial_crypters
    506   out_params->hkdf_input_suffix.clear();
    507   out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&connection_id),
    508                                        sizeof(connection_id));
    509   const QuicData& client_hello_serialized = out->GetSerialized();
    510   out_params->hkdf_input_suffix.append(client_hello_serialized.data(),
    511                                        client_hello_serialized.length());
    512   out_params->hkdf_input_suffix.append(cached->server_config());
    513 
    514   string hkdf_input;
    515   const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
    516   hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
    517   hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
    518   hkdf_input.append(out_params->hkdf_input_suffix);
    519 
    520   if (!CryptoUtils::DeriveKeys(
    521            out_params->initial_premaster_secret, out_params->aead,
    522            out_params->client_nonce, out_params->server_nonce, hkdf_input,
    523            CryptoUtils::CLIENT, &out_params->initial_crypters)) {
    524     *error_details = "Symmetric key setup failed";
    525     return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
    526   }
    527 
    528   return QUIC_NO_ERROR;
    529 }
    530 
    531 QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
    532     const CryptoHandshakeMessage& rej,
    533     QuicWallTime now,
    534     CachedState* cached,
    535     QuicCryptoNegotiatedParameters* out_params,
    536     string* error_details) {
    537   DCHECK(error_details != NULL);
    538 
    539   if (rej.tag() != kREJ) {
    540     *error_details = "Message is not REJ";
    541     return QUIC_CRYPTO_INTERNAL_ERROR;
    542   }
    543 
    544   StringPiece scfg;
    545   if (!rej.GetStringPiece(kSCFG, &scfg)) {
    546     *error_details = "Missing SCFG";
    547     return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
    548   }
    549 
    550   QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details);
    551   if (error != QUIC_NO_ERROR) {
    552     return error;
    553   }
    554 
    555   StringPiece token;
    556   if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) {
    557     cached->set_source_address_token(token);
    558   }
    559 
    560   StringPiece nonce;
    561   if (rej.GetStringPiece(kServerNonceTag, &nonce)) {
    562     out_params->server_nonce = nonce.as_string();
    563   }
    564 
    565   StringPiece proof, cert_bytes;
    566   bool has_proof = rej.GetStringPiece(kPROF, &proof);
    567   bool has_cert = rej.GetStringPiece(kCertificateTag, &cert_bytes);
    568   if (has_proof && has_cert) {
    569     vector<string> certs;
    570     if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs,
    571                                          common_cert_sets, &certs)) {
    572       *error_details = "Certificate data invalid";
    573       return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    574     }
    575 
    576     cached->SetProof(certs, proof);
    577   } else {
    578     cached->ClearProof();
    579     if (has_proof && !has_cert) {
    580       *error_details = "Certificate missing";
    581       return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    582     }
    583 
    584     if (!has_proof && has_cert) {
    585       *error_details = "Proof missing";
    586       return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    587     }
    588   }
    589 
    590   const QuicTag* reject_reasons;
    591   size_t num_reject_reasons;
    592   if (rej.GetTaglist(kRREJ, &reject_reasons,
    593                      &num_reject_reasons) == QUIC_NO_ERROR) {
    594 #if defined(DEBUG)
    595     for (size_t i = 0; i < num_reject_reasons; ++i) {
    596       DVLOG(1) << "Reasons for rejection: " << reject_reasons[i];
    597     }
    598 #endif
    599   }
    600 
    601   return QUIC_NO_ERROR;
    602 }
    603 
    604 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
    605     const CryptoHandshakeMessage& server_hello,
    606     QuicConnectionId connection_id,
    607     const QuicVersionVector& negotiated_versions,
    608     CachedState* cached,
    609     QuicCryptoNegotiatedParameters* out_params,
    610     string* error_details) {
    611   DCHECK(error_details != NULL);
    612 
    613   if (server_hello.tag() != kSHLO) {
    614     *error_details = "Bad tag";
    615     return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
    616   }
    617 
    618   const QuicTag* supported_version_tags;
    619   size_t num_supported_versions;
    620 
    621   if (server_hello.GetTaglist(kVER, &supported_version_tags,
    622                               &num_supported_versions) != QUIC_NO_ERROR) {
    623     *error_details = "server hello missing version list";
    624     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    625   }
    626   if (!negotiated_versions.empty()) {
    627     bool mismatch = num_supported_versions != negotiated_versions.size();
    628     for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) {
    629       mismatch = QuicTagToQuicVersion(supported_version_tags[i]) !=
    630           negotiated_versions[i];
    631     }
    632     // The server sent a list of supported versions, and the connection
    633     // reports that there was a version negotiation during the handshake.
    634       // Ensure that these two lists are identical.
    635     if (mismatch) {
    636       *error_details = "Downgrade attack detected";
    637       return QUIC_VERSION_NEGOTIATION_MISMATCH;
    638     }
    639   }
    640 
    641   // Learn about updated source address tokens.
    642   StringPiece token;
    643   if (server_hello.GetStringPiece(kSourceAddressTokenTag, &token)) {
    644     cached->set_source_address_token(token);
    645   }
    646 
    647   // TODO(agl):
    648   //   learn about updated SCFGs.
    649 
    650   StringPiece public_value;
    651   if (!server_hello.GetStringPiece(kPUBS, &public_value)) {
    652     *error_details = "server hello missing forward secure public value";
    653     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    654   }
    655 
    656   if (!out_params->client_key_exchange->CalculateSharedKey(
    657           public_value, &out_params->forward_secure_premaster_secret)) {
    658     *error_details = "Key exchange failure";
    659     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
    660   }
    661 
    662   string hkdf_input;
    663   const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
    664   hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
    665   hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len);
    666   hkdf_input.append(out_params->hkdf_input_suffix);
    667 
    668   if (!CryptoUtils::DeriveKeys(
    669            out_params->forward_secure_premaster_secret, out_params->aead,
    670            out_params->client_nonce, out_params->server_nonce, hkdf_input,
    671            CryptoUtils::CLIENT, &out_params->forward_secure_crypters)) {
    672     *error_details = "Symmetric key setup failed";
    673     return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
    674   }
    675 
    676   return QUIC_NO_ERROR;
    677 }
    678 
    679 ProofVerifier* QuicCryptoClientConfig::proof_verifier() const {
    680   return proof_verifier_.get();
    681 }
    682 
    683 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) {
    684   proof_verifier_.reset(verifier);
    685 }
    686 
    687 ChannelIDSource* QuicCryptoClientConfig::channel_id_source() const {
    688   return channel_id_source_.get();
    689 }
    690 
    691 void QuicCryptoClientConfig::SetChannelIDSource(ChannelIDSource* source) {
    692   channel_id_source_.reset(source);
    693 }
    694 
    695 void QuicCryptoClientConfig::InitializeFrom(
    696     const QuicServerId& server_id,
    697     const QuicServerId& canonical_server_id,
    698     QuicCryptoClientConfig* canonical_crypto_config) {
    699   CachedState* canonical_cached =
    700       canonical_crypto_config->LookupOrCreate(canonical_server_id);
    701   if (!canonical_cached->proof_valid()) {
    702     return;
    703   }
    704   CachedState* cached = LookupOrCreate(server_id);
    705   cached->InitializeFrom(*canonical_cached);
    706 }
    707 
    708 void QuicCryptoClientConfig::AddCanonicalSuffix(const string& suffix) {
    709   canoncial_suffixes_.push_back(suffix);
    710 }
    711 
    712 void QuicCryptoClientConfig::PreferAesGcm() {
    713   DCHECK(!aead.empty());
    714   if (aead.size() <= 1) {
    715     return;
    716   }
    717   QuicTagVector::iterator pos = find(aead.begin(), aead.end(), kAESG);
    718   if (pos != aead.end()) {
    719     aead.erase(pos);
    720     aead.insert(aead.begin(), kAESG);
    721   }
    722 }
    723 
    724 void QuicCryptoClientConfig::DisableEcdsa() {
    725   disable_ecdsa_ = true;
    726 }
    727 
    728 void QuicCryptoClientConfig::PopulateFromCanonicalConfig(
    729     const QuicServerId& server_id,
    730     CachedState* server_state) {
    731   DCHECK(server_state->IsEmpty());
    732   size_t i = 0;
    733   for (; i < canoncial_suffixes_.size(); ++i) {
    734     if (EndsWith(server_id.host(), canoncial_suffixes_[i], false)) {
    735       break;
    736     }
    737   }
    738   if (i == canoncial_suffixes_.size())
    739     return;
    740 
    741   QuicServerId suffix_server_id(canoncial_suffixes_[i], server_id.port(),
    742                                 server_id.is_https(),
    743                                 server_id.privacy_mode());
    744   if (!ContainsKey(canonical_server_map_, suffix_server_id)) {
    745     // This is the first host we've seen which matches the suffix, so make it
    746     // canonical.
    747     canonical_server_map_[suffix_server_id] = server_id;
    748     return;
    749   }
    750 
    751   const QuicServerId& canonical_server_id =
    752       canonical_server_map_[suffix_server_id];
    753   CachedState* canonical_state = cached_states_[canonical_server_id];
    754   if (!canonical_state->proof_valid()) {
    755     return;
    756   }
    757 
    758   // Update canonical version to point at the "most recent" entry.
    759   canonical_server_map_[suffix_server_id] = server_id;
    760 
    761   server_state->InitializeFrom(*canonical_state);
    762 }
    763 
    764 }  // namespace net
    765