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