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