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/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <string>
10 
11 #include "absl/base/macros.h"
12 #include "absl/strings/match.h"
13 #include "absl/strings/string_view.h"
14 #include "third_party/boringssl/src/include/openssl/ssl.h"
15 #include "net/third_party/quiche/src/quic/core/crypto/cert_compressor.h"
16 #include "net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter.h"
17 #include "net/third_party/quiche/src/quic/core/crypto/common_cert_set.h"
18 #include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
19 #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
20 #include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
21 #include "net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h"
22 #include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
23 #include "net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h"
24 #include "net/third_party/quiche/src/quic/core/crypto/proof_verifier.h"
25 #include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
26 #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
27 #include "net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h"
28 #include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
29 #include "net/third_party/quiche/src/quic/core/quic_types.h"
30 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
31 #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
32 #include "net/third_party/quiche/src/quic/platform/api/quic_client_stats.h"
33 #include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h"
34 #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
35 #include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
36 #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
37 #include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
38 
39 namespace quic {
40 
41 namespace {
42 
43 // Tracks the reason (the state of the server config) for sending inchoate
44 // ClientHello to the server.
RecordInchoateClientHelloReason(QuicCryptoClientConfig::CachedState::ServerConfigState state)45 void RecordInchoateClientHelloReason(
46     QuicCryptoClientConfig::CachedState::ServerConfigState state) {
47   QUIC_CLIENT_HISTOGRAM_ENUM(
48       "QuicInchoateClientHelloReason", state,
49       QuicCryptoClientConfig::CachedState::SERVER_CONFIG_COUNT, "");
50 }
51 
52 // Tracks the state of the QUIC server information loaded from the disk cache.
RecordDiskCacheServerConfigState(QuicCryptoClientConfig::CachedState::ServerConfigState state)53 void RecordDiskCacheServerConfigState(
54     QuicCryptoClientConfig::CachedState::ServerConfigState state) {
55   QUIC_CLIENT_HISTOGRAM_ENUM(
56       "QuicServerInfo.DiskCacheState", state,
57       QuicCryptoClientConfig::CachedState::SERVER_CONFIG_COUNT, "");
58 }
59 
60 }  // namespace
61 
QuicCryptoClientConfig(std::unique_ptr<ProofVerifier> proof_verifier)62 QuicCryptoClientConfig::QuicCryptoClientConfig(
63     std::unique_ptr<ProofVerifier> proof_verifier)
64     : QuicCryptoClientConfig(std::move(proof_verifier), nullptr) {}
65 
QuicCryptoClientConfig(std::unique_ptr<ProofVerifier> proof_verifier,std::unique_ptr<SessionCache> session_cache)66 QuicCryptoClientConfig::QuicCryptoClientConfig(
67     std::unique_ptr<ProofVerifier> proof_verifier,
68     std::unique_ptr<SessionCache> session_cache)
69     : proof_verifier_(std::move(proof_verifier)),
70       session_cache_(std::move(session_cache)),
71       ssl_ctx_(TlsClientConnection::CreateSslCtx(
72           !GetQuicFlag(FLAGS_quic_disable_client_tls_zero_rtt))) {
73   DCHECK(proof_verifier_.get());
74   SetDefaults();
75 }
76 
~QuicCryptoClientConfig()77 QuicCryptoClientConfig::~QuicCryptoClientConfig() {}
78 
CachedState()79 QuicCryptoClientConfig::CachedState::CachedState()
80     : server_config_valid_(false),
81       expiration_time_(QuicWallTime::Zero()),
82       generation_counter_(0) {}
83 
~CachedState()84 QuicCryptoClientConfig::CachedState::~CachedState() {}
85 
IsComplete(QuicWallTime now) const86 bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const {
87   if (server_config_.empty()) {
88     RecordInchoateClientHelloReason(SERVER_CONFIG_EMPTY);
89     return false;
90   }
91 
92   if (!server_config_valid_) {
93     RecordInchoateClientHelloReason(SERVER_CONFIG_INVALID);
94     return false;
95   }
96 
97   const CryptoHandshakeMessage* scfg = GetServerConfig();
98   if (!scfg) {
99     // Should be impossible short of cache corruption.
100     RecordInchoateClientHelloReason(SERVER_CONFIG_CORRUPTED);
101     DCHECK(false);
102     return false;
103   }
104 
105   if (now.IsBefore(expiration_time_)) {
106     return true;
107   }
108 
109   QUIC_CLIENT_HISTOGRAM_TIMES(
110       "QuicClientHelloServerConfig.InvalidDuration",
111       QuicTime::Delta::FromSeconds(now.ToUNIXSeconds() -
112                                    expiration_time_.ToUNIXSeconds()),
113       QuicTime::Delta::FromSeconds(60),              // 1 min.
114       QuicTime::Delta::FromSeconds(20 * 24 * 3600),  // 20 days.
115       50, "");
116   RecordInchoateClientHelloReason(SERVER_CONFIG_EXPIRED);
117   return false;
118 }
119 
IsEmpty() const120 bool QuicCryptoClientConfig::CachedState::IsEmpty() const {
121   return server_config_.empty();
122 }
123 
124 const CryptoHandshakeMessage*
GetServerConfig() const125 QuicCryptoClientConfig::CachedState::GetServerConfig() const {
126   if (server_config_.empty()) {
127     return nullptr;
128   }
129 
130   if (!scfg_) {
131     scfg_ = CryptoFramer::ParseMessage(server_config_);
132     DCHECK(scfg_.get());
133   }
134   return scfg_.get();
135 }
136 
add_server_nonce(const std::string & server_nonce)137 void QuicCryptoClientConfig::CachedState::add_server_nonce(
138     const std::string& server_nonce) {
139   server_nonces_.push(server_nonce);
140 }
141 
has_server_nonce() const142 bool QuicCryptoClientConfig::CachedState::has_server_nonce() const {
143   return !server_nonces_.empty();
144 }
145 
146 QuicCryptoClientConfig::CachedState::ServerConfigState
SetServerConfig(absl::string_view server_config,QuicWallTime now,QuicWallTime expiry_time,std::string * error_details)147 QuicCryptoClientConfig::CachedState::SetServerConfig(
148     absl::string_view server_config,
149     QuicWallTime now,
150     QuicWallTime expiry_time,
151     std::string* error_details) {
152   const bool matches_existing = server_config == server_config_;
153 
154   // Even if the new server config matches the existing one, we still wish to
155   // reject it if it has expired.
156   std::unique_ptr<CryptoHandshakeMessage> new_scfg_storage;
157   const CryptoHandshakeMessage* new_scfg;
158 
159   if (!matches_existing) {
160     new_scfg_storage = CryptoFramer::ParseMessage(server_config);
161     new_scfg = new_scfg_storage.get();
162   } else {
163     new_scfg = GetServerConfig();
164   }
165 
166   if (!new_scfg) {
167     *error_details = "SCFG invalid";
168     return SERVER_CONFIG_INVALID;
169   }
170 
171   if (expiry_time.IsZero()) {
172     uint64_t expiry_seconds;
173     if (new_scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
174       *error_details = "SCFG missing EXPY";
175       return SERVER_CONFIG_INVALID_EXPIRY;
176     }
177     expiration_time_ = QuicWallTime::FromUNIXSeconds(expiry_seconds);
178   } else {
179     expiration_time_ = expiry_time;
180   }
181 
182   if (now.IsAfter(expiration_time_)) {
183     *error_details = "SCFG has expired";
184     return SERVER_CONFIG_EXPIRED;
185   }
186 
187   if (!matches_existing) {
188     server_config_ = std::string(server_config);
189     SetProofInvalid();
190     scfg_ = std::move(new_scfg_storage);
191   }
192   return SERVER_CONFIG_VALID;
193 }
194 
InvalidateServerConfig()195 void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() {
196   server_config_.clear();
197   scfg_.reset();
198   SetProofInvalid();
199 }
200 
SetProof(const std::vector<std::string> & certs,absl::string_view cert_sct,absl::string_view chlo_hash,absl::string_view signature)201 void QuicCryptoClientConfig::CachedState::SetProof(
202     const std::vector<std::string>& certs,
203     absl::string_view cert_sct,
204     absl::string_view chlo_hash,
205     absl::string_view signature) {
206   bool has_changed = signature != server_config_sig_ ||
207                      chlo_hash != chlo_hash_ || certs_.size() != certs.size();
208 
209   if (!has_changed) {
210     for (size_t i = 0; i < certs_.size(); i++) {
211       if (certs_[i] != certs[i]) {
212         has_changed = true;
213         break;
214       }
215     }
216   }
217 
218   if (!has_changed) {
219     return;
220   }
221 
222   // If the proof has changed then it needs to be revalidated.
223   SetProofInvalid();
224   certs_ = certs;
225   cert_sct_ = std::string(cert_sct);
226   chlo_hash_ = std::string(chlo_hash);
227   server_config_sig_ = std::string(signature);
228 }
229 
Clear()230 void QuicCryptoClientConfig::CachedState::Clear() {
231   server_config_.clear();
232   source_address_token_.clear();
233   certs_.clear();
234   cert_sct_.clear();
235   chlo_hash_.clear();
236   server_config_sig_.clear();
237   server_config_valid_ = false;
238   proof_verify_details_.reset();
239   scfg_.reset();
240   ++generation_counter_;
241 }
242 
ClearProof()243 void QuicCryptoClientConfig::CachedState::ClearProof() {
244   SetProofInvalid();
245   certs_.clear();
246   cert_sct_.clear();
247   chlo_hash_.clear();
248   server_config_sig_.clear();
249 }
250 
SetProofValid()251 void QuicCryptoClientConfig::CachedState::SetProofValid() {
252   server_config_valid_ = true;
253 }
254 
SetProofInvalid()255 void QuicCryptoClientConfig::CachedState::SetProofInvalid() {
256   server_config_valid_ = false;
257   ++generation_counter_;
258 }
259 
Initialize(absl::string_view server_config,absl::string_view source_address_token,const std::vector<std::string> & certs,const std::string & cert_sct,absl::string_view chlo_hash,absl::string_view signature,QuicWallTime now,QuicWallTime expiration_time)260 bool QuicCryptoClientConfig::CachedState::Initialize(
261     absl::string_view server_config,
262     absl::string_view source_address_token,
263     const std::vector<std::string>& certs,
264     const std::string& cert_sct,
265     absl::string_view chlo_hash,
266     absl::string_view signature,
267     QuicWallTime now,
268     QuicWallTime expiration_time) {
269   DCHECK(server_config_.empty());
270 
271   if (server_config.empty()) {
272     RecordDiskCacheServerConfigState(SERVER_CONFIG_EMPTY);
273     return false;
274   }
275 
276   std::string error_details;
277   ServerConfigState state =
278       SetServerConfig(server_config, now, expiration_time, &error_details);
279   RecordDiskCacheServerConfigState(state);
280   if (state != SERVER_CONFIG_VALID) {
281     QUIC_DVLOG(1) << "SetServerConfig failed with " << error_details;
282     return false;
283   }
284 
285   chlo_hash_.assign(chlo_hash.data(), chlo_hash.size());
286   server_config_sig_.assign(signature.data(), signature.size());
287   source_address_token_.assign(source_address_token.data(),
288                                source_address_token.size());
289   certs_ = certs;
290   cert_sct_ = cert_sct;
291   return true;
292 }
293 
server_config() const294 const std::string& QuicCryptoClientConfig::CachedState::server_config() const {
295   return server_config_;
296 }
297 
source_address_token() const298 const std::string& QuicCryptoClientConfig::CachedState::source_address_token()
299     const {
300   return source_address_token_;
301 }
302 
certs() const303 const std::vector<std::string>& QuicCryptoClientConfig::CachedState::certs()
304     const {
305   return certs_;
306 }
307 
cert_sct() const308 const std::string& QuicCryptoClientConfig::CachedState::cert_sct() const {
309   return cert_sct_;
310 }
311 
chlo_hash() const312 const std::string& QuicCryptoClientConfig::CachedState::chlo_hash() const {
313   return chlo_hash_;
314 }
315 
signature() const316 const std::string& QuicCryptoClientConfig::CachedState::signature() const {
317   return server_config_sig_;
318 }
319 
proof_valid() const320 bool QuicCryptoClientConfig::CachedState::proof_valid() const {
321   return server_config_valid_;
322 }
323 
generation_counter() const324 uint64_t QuicCryptoClientConfig::CachedState::generation_counter() const {
325   return generation_counter_;
326 }
327 
328 const ProofVerifyDetails*
proof_verify_details() const329 QuicCryptoClientConfig::CachedState::proof_verify_details() const {
330   return proof_verify_details_.get();
331 }
332 
set_source_address_token(absl::string_view token)333 void QuicCryptoClientConfig::CachedState::set_source_address_token(
334     absl::string_view token) {
335   source_address_token_ = std::string(token);
336 }
337 
set_cert_sct(absl::string_view cert_sct)338 void QuicCryptoClientConfig::CachedState::set_cert_sct(
339     absl::string_view cert_sct) {
340   cert_sct_ = std::string(cert_sct);
341 }
342 
SetProofVerifyDetails(ProofVerifyDetails * details)343 void QuicCryptoClientConfig::CachedState::SetProofVerifyDetails(
344     ProofVerifyDetails* details) {
345   proof_verify_details_.reset(details);
346 }
347 
InitializeFrom(const QuicCryptoClientConfig::CachedState & other)348 void QuicCryptoClientConfig::CachedState::InitializeFrom(
349     const QuicCryptoClientConfig::CachedState& other) {
350   DCHECK(server_config_.empty());
351   DCHECK(!server_config_valid_);
352   server_config_ = other.server_config_;
353   source_address_token_ = other.source_address_token_;
354   certs_ = other.certs_;
355   cert_sct_ = other.cert_sct_;
356   chlo_hash_ = other.chlo_hash_;
357   server_config_sig_ = other.server_config_sig_;
358   server_config_valid_ = other.server_config_valid_;
359   expiration_time_ = other.expiration_time_;
360   if (other.proof_verify_details_ != nullptr) {
361     proof_verify_details_.reset(other.proof_verify_details_->Clone());
362   }
363   ++generation_counter_;
364 }
365 
GetNextServerNonce()366 std::string QuicCryptoClientConfig::CachedState::GetNextServerNonce() {
367   if (server_nonces_.empty()) {
368     QUIC_BUG
369         << "Attempting to consume a server nonce that was never designated.";
370     return "";
371   }
372   const std::string server_nonce = server_nonces_.front();
373   server_nonces_.pop();
374   return server_nonce;
375 }
376 
SetDefaults()377 void QuicCryptoClientConfig::SetDefaults() {
378   // Key exchange methods.
379   kexs = {kC255, kP256};
380 
381   // Authenticated encryption algorithms. Prefer AES-GCM if hardware-supported
382   // fast implementation is available.
383   if (EVP_has_aes_hardware() == 1) {
384     aead = {kAESG, kCC20};
385   } else {
386     aead = {kCC20, kAESG};
387   }
388 }
389 
LookupOrCreate(const QuicServerId & server_id)390 QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate(
391     const QuicServerId& server_id) {
392   auto it = cached_states_.find(server_id);
393   if (it != cached_states_.end()) {
394     return it->second.get();
395   }
396 
397   CachedState* cached = new CachedState;
398   cached_states_.insert(std::make_pair(server_id, QuicWrapUnique(cached)));
399   bool cache_populated = PopulateFromCanonicalConfig(server_id, cached);
400   QUIC_CLIENT_HISTOGRAM_BOOL(
401       "QuicCryptoClientConfig.PopulatedFromCanonicalConfig", cache_populated,
402       "");
403   return cached;
404 }
405 
ClearCachedStates(const ServerIdFilter & filter)406 void QuicCryptoClientConfig::ClearCachedStates(const ServerIdFilter& filter) {
407   for (auto it = cached_states_.begin(); it != cached_states_.end(); ++it) {
408     if (filter.Matches(it->first))
409       it->second->Clear();
410   }
411 }
412 
FillInchoateClientHello(const QuicServerId & server_id,const ParsedQuicVersion preferred_version,const CachedState * cached,QuicRandom * rand,bool demand_x509_proof,QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,CryptoHandshakeMessage * out) const413 void QuicCryptoClientConfig::FillInchoateClientHello(
414     const QuicServerId& server_id,
415     const ParsedQuicVersion preferred_version,
416     const CachedState* cached,
417     QuicRandom* rand,
418     bool demand_x509_proof,
419     QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
420     CryptoHandshakeMessage* out) const {
421   out->set_tag(kCHLO);
422   out->set_minimum_size(1);
423 
424   // Server name indication. We only send SNI if it's a valid domain name, as
425   // per the spec.
426   if (QuicHostnameUtils::IsValidSNI(server_id.host())) {
427     out->SetStringPiece(kSNI, server_id.host());
428   }
429   out->SetVersion(kVER, preferred_version);
430 
431   if (!user_agent_id_.empty()) {
432     out->SetStringPiece(kUAID, user_agent_id_);
433   }
434 
435   if (!alpn_.empty()) {
436     out->SetStringPiece(kALPN, alpn_);
437   }
438 
439   // Even though this is an inchoate CHLO, send the SCID so that
440   // the STK can be validated by the server.
441   const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
442   if (scfg != nullptr) {
443     absl::string_view scid;
444     if (scfg->GetStringPiece(kSCID, &scid)) {
445       out->SetStringPiece(kSCID, scid);
446     }
447   }
448 
449   if (!cached->source_address_token().empty()) {
450     out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
451   }
452 
453   if (!demand_x509_proof) {
454     return;
455   }
456 
457   char proof_nonce[32];
458   rand->RandBytes(proof_nonce, ABSL_ARRAYSIZE(proof_nonce));
459   out->SetStringPiece(
460       kNONP, absl::string_view(proof_nonce, ABSL_ARRAYSIZE(proof_nonce)));
461 
462   out->SetVector(kPDMD, QuicTagVector{kX509});
463 
464   if (common_cert_sets) {
465     out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes());
466   }
467 
468   out->SetStringPiece(kCertificateSCTTag, "");
469 
470   const std::vector<std::string>& certs = cached->certs();
471   // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the
472   // client config is being used for multiple connections, another connection
473   // doesn't update the cached certificates and cause us to be unable to
474   // process the server's compressed certificate chain.
475   out_params->cached_certs = certs;
476   if (!certs.empty()) {
477     std::vector<uint64_t> hashes;
478     hashes.reserve(certs.size());
479     for (auto i = certs.begin(); i != certs.end(); ++i) {
480       hashes.push_back(QuicUtils::FNV1a_64_Hash(*i));
481     }
482     out->SetVector(kCCRT, hashes);
483   }
484 }
485 
FillClientHello(const QuicServerId & server_id,QuicConnectionId connection_id,const ParsedQuicVersion preferred_version,const ParsedQuicVersion actual_version,const CachedState * cached,QuicWallTime now,QuicRandom * rand,QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,CryptoHandshakeMessage * out,std::string * error_details) const486 QuicErrorCode QuicCryptoClientConfig::FillClientHello(
487     const QuicServerId& server_id,
488     QuicConnectionId connection_id,
489     const ParsedQuicVersion preferred_version,
490     const ParsedQuicVersion actual_version,
491     const CachedState* cached,
492     QuicWallTime now,
493     QuicRandom* rand,
494     QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
495     CryptoHandshakeMessage* out,
496     std::string* error_details) const {
497   DCHECK(error_details != nullptr);
498   QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
499       connection_id, preferred_version.transport_version))
500       << "FillClientHello: attempted to use connection ID " << connection_id
501       << " which is invalid with version "
502       << QuicVersionToString(preferred_version.transport_version);
503 
504   FillInchoateClientHello(server_id, preferred_version, cached, rand,
505                           /* demand_x509_proof= */ true, out_params, out);
506 
507   out->set_minimum_size(1);
508 
509   const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
510   if (!scfg) {
511     // This should never happen as our caller should have checked
512     // cached->IsComplete() before calling this function.
513     *error_details = "Handshake not ready";
514     return QUIC_CRYPTO_INTERNAL_ERROR;
515   }
516 
517   absl::string_view scid;
518   if (!scfg->GetStringPiece(kSCID, &scid)) {
519     *error_details = "SCFG missing SCID";
520     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
521   }
522   out->SetStringPiece(kSCID, scid);
523 
524   out->SetStringPiece(kCertificateSCTTag, "");
525 
526   QuicTagVector their_aeads;
527   QuicTagVector their_key_exchanges;
528   if (scfg->GetTaglist(kAEAD, &their_aeads) != QUIC_NO_ERROR ||
529       scfg->GetTaglist(kKEXS, &their_key_exchanges) != QUIC_NO_ERROR) {
530     *error_details = "Missing AEAD or KEXS";
531     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
532   }
533 
534   // AEAD: the work loads on the client and server are symmetric. Since the
535   // client is more likely to be CPU-constrained, break the tie by favoring
536   // the client's preference.
537   // Key exchange: the client does more work than the server, so favor the
538   // client's preference.
539   size_t key_exchange_index;
540   if (!FindMutualQuicTag(aead, their_aeads, &out_params->aead, nullptr) ||
541       !FindMutualQuicTag(kexs, their_key_exchanges, &out_params->key_exchange,
542                          &key_exchange_index)) {
543     *error_details = "Unsupported AEAD or KEXS";
544     return QUIC_CRYPTO_NO_SUPPORT;
545   }
546   out->SetVector(kAEAD, QuicTagVector{out_params->aead});
547   out->SetVector(kKEXS, QuicTagVector{out_params->key_exchange});
548 
549   absl::string_view public_value;
550   if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) !=
551       QUIC_NO_ERROR) {
552     *error_details = "Missing public value";
553     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
554   }
555 
556   absl::string_view orbit;
557   if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) {
558     *error_details = "SCFG missing OBIT";
559     return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
560   }
561 
562   CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce);
563   out->SetStringPiece(kNONC, out_params->client_nonce);
564   if (!out_params->server_nonce.empty()) {
565     out->SetStringPiece(kServerNonceTag, out_params->server_nonce);
566   }
567 
568   switch (out_params->key_exchange) {
569     case kC255:
570       out_params->client_key_exchange = Curve25519KeyExchange::New(
571           Curve25519KeyExchange::NewPrivateKey(rand));
572       break;
573     case kP256:
574       out_params->client_key_exchange =
575           P256KeyExchange::New(P256KeyExchange::NewPrivateKey());
576       break;
577     default:
578       DCHECK(false);
579       *error_details = "Configured to support an unknown key exchange";
580       return QUIC_CRYPTO_INTERNAL_ERROR;
581   }
582 
583   if (!out_params->client_key_exchange->CalculateSharedKeySync(
584           public_value, &out_params->initial_premaster_secret)) {
585     *error_details = "Key exchange failure";
586     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
587   }
588   out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value());
589 
590   const std::vector<std::string>& certs = cached->certs();
591   if (certs.empty()) {
592     *error_details = "No certs to calculate XLCT";
593     return QUIC_CRYPTO_INTERNAL_ERROR;
594   }
595   out->SetValue(kXLCT, CryptoUtils::ComputeLeafCertHash(certs[0]));
596 
597   // Derive the symmetric keys and set up the encrypters and decrypters.
598   // Set the following members of out_params:
599   //   out_params->hkdf_input_suffix
600   //   out_params->initial_crypters
601   out_params->hkdf_input_suffix.clear();
602   out_params->hkdf_input_suffix.append(connection_id.data(),
603                                        connection_id.length());
604   const QuicData& client_hello_serialized = out->GetSerialized();
605   out_params->hkdf_input_suffix.append(client_hello_serialized.data(),
606                                        client_hello_serialized.length());
607   out_params->hkdf_input_suffix.append(cached->server_config());
608   if (certs.empty()) {
609     *error_details = "No certs found to include in KDF";
610     return QUIC_CRYPTO_INTERNAL_ERROR;
611   }
612   out_params->hkdf_input_suffix.append(certs[0]);
613 
614   std::string hkdf_input;
615   const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
616   hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
617   hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
618   hkdf_input.append(out_params->hkdf_input_suffix);
619 
620   std::string* subkey_secret = &out_params->initial_subkey_secret;
621 
622   if (!CryptoUtils::DeriveKeys(
623           actual_version, out_params->initial_premaster_secret,
624           out_params->aead, out_params->client_nonce, out_params->server_nonce,
625           pre_shared_key_, hkdf_input, Perspective::IS_CLIENT,
626           CryptoUtils::Diversification::Pending(),
627           &out_params->initial_crypters, subkey_secret)) {
628     *error_details = "Symmetric key setup failed";
629     return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
630   }
631 
632   return QUIC_NO_ERROR;
633 }
634 
CacheNewServerConfig(const CryptoHandshakeMessage & message,QuicWallTime now,QuicTransportVersion,absl::string_view chlo_hash,const std::vector<std::string> & cached_certs,CachedState * cached,std::string * error_details)635 QuicErrorCode QuicCryptoClientConfig::CacheNewServerConfig(
636     const CryptoHandshakeMessage& message,
637     QuicWallTime now,
638     QuicTransportVersion /*version*/,
639     absl::string_view chlo_hash,
640     const std::vector<std::string>& cached_certs,
641     CachedState* cached,
642     std::string* error_details) {
643   DCHECK(error_details != nullptr);
644 
645   absl::string_view scfg;
646   if (!message.GetStringPiece(kSCFG, &scfg)) {
647     *error_details = "Missing SCFG";
648     return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
649   }
650 
651   QuicWallTime expiration_time = QuicWallTime::Zero();
652   uint64_t expiry_seconds;
653   if (message.GetUint64(kSTTL, &expiry_seconds) == QUIC_NO_ERROR) {
654     // Only cache configs for a maximum of 1 week.
655     expiration_time = now.Add(QuicTime::Delta::FromSeconds(
656         std::min(expiry_seconds, kNumSecondsPerWeek)));
657   }
658 
659   CachedState::ServerConfigState state =
660       cached->SetServerConfig(scfg, now, expiration_time, error_details);
661   if (state == CachedState::SERVER_CONFIG_EXPIRED) {
662     return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED;
663   }
664   // TODO(rtenneti): Return more specific error code than returning
665   // QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER.
666   if (state != CachedState::SERVER_CONFIG_VALID) {
667     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
668   }
669 
670   absl::string_view token;
671   if (message.GetStringPiece(kSourceAddressTokenTag, &token)) {
672     cached->set_source_address_token(token);
673   }
674 
675   absl::string_view proof, cert_bytes, cert_sct;
676   bool has_proof = message.GetStringPiece(kPROF, &proof);
677   bool has_cert = message.GetStringPiece(kCertificateTag, &cert_bytes);
678   if (has_proof && has_cert) {
679     std::vector<std::string> certs;
680     if (!CertCompressor::DecompressChain(cert_bytes, cached_certs,
681                                          common_cert_sets, &certs)) {
682       *error_details = "Certificate data invalid";
683       return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
684     }
685 
686     message.GetStringPiece(kCertificateSCTTag, &cert_sct);
687     cached->SetProof(certs, cert_sct, chlo_hash, proof);
688   } else {
689     // Secure QUIC: clear existing proof as we have been sent a new SCFG
690     // without matching proof/certs.
691     cached->ClearProof();
692 
693     if (has_proof && !has_cert) {
694       *error_details = "Certificate missing";
695       return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
696     }
697 
698     if (!has_proof && has_cert) {
699       *error_details = "Proof missing";
700       return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
701     }
702   }
703 
704   return QUIC_NO_ERROR;
705 }
706 
ProcessRejection(const CryptoHandshakeMessage & rej,QuicWallTime now,const QuicTransportVersion version,absl::string_view chlo_hash,CachedState * cached,QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,std::string * error_details)707 QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
708     const CryptoHandshakeMessage& rej,
709     QuicWallTime now,
710     const QuicTransportVersion version,
711     absl::string_view chlo_hash,
712     CachedState* cached,
713     QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
714     std::string* error_details) {
715   DCHECK(error_details != nullptr);
716 
717   if (rej.tag() != kREJ) {
718     *error_details = "Message is not REJ";
719     return QUIC_CRYPTO_INTERNAL_ERROR;
720   }
721 
722   QuicErrorCode error =
723       CacheNewServerConfig(rej, now, version, chlo_hash,
724                            out_params->cached_certs, cached, error_details);
725   if (error != QUIC_NO_ERROR) {
726     return error;
727   }
728 
729   absl::string_view nonce;
730   if (rej.GetStringPiece(kServerNonceTag, &nonce)) {
731     out_params->server_nonce = std::string(nonce);
732   }
733 
734   return QUIC_NO_ERROR;
735 }
736 
ProcessServerHello(const CryptoHandshakeMessage & server_hello,QuicConnectionId,ParsedQuicVersion version,const ParsedQuicVersionVector & negotiated_versions,CachedState * cached,QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,std::string * error_details)737 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
738     const CryptoHandshakeMessage& server_hello,
739     QuicConnectionId /*connection_id*/,
740     ParsedQuicVersion version,
741     const ParsedQuicVersionVector& negotiated_versions,
742     CachedState* cached,
743     QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
744     std::string* error_details) {
745   DCHECK(error_details != nullptr);
746 
747   QuicErrorCode valid = CryptoUtils::ValidateServerHello(
748       server_hello, negotiated_versions, error_details);
749   if (valid != QUIC_NO_ERROR) {
750     return valid;
751   }
752 
753   // Learn about updated source address tokens.
754   absl::string_view token;
755   if (server_hello.GetStringPiece(kSourceAddressTokenTag, &token)) {
756     cached->set_source_address_token(token);
757   }
758 
759   absl::string_view shlo_nonce;
760   if (!server_hello.GetStringPiece(kServerNonceTag, &shlo_nonce)) {
761     *error_details = "server hello missing server nonce";
762     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
763   }
764 
765   // TODO(agl):
766   //   learn about updated SCFGs.
767 
768   absl::string_view public_value;
769   if (!server_hello.GetStringPiece(kPUBS, &public_value)) {
770     *error_details = "server hello missing forward secure public value";
771     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
772   }
773 
774   if (!out_params->client_key_exchange->CalculateSharedKeySync(
775           public_value, &out_params->forward_secure_premaster_secret)) {
776     *error_details = "Key exchange failure";
777     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
778   }
779 
780   std::string hkdf_input;
781   const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
782   hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
783   hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len);
784   hkdf_input.append(out_params->hkdf_input_suffix);
785 
786   if (!CryptoUtils::DeriveKeys(
787           version, out_params->forward_secure_premaster_secret,
788           out_params->aead, out_params->client_nonce,
789           shlo_nonce.empty() ? out_params->server_nonce : shlo_nonce,
790           pre_shared_key_, hkdf_input, Perspective::IS_CLIENT,
791           CryptoUtils::Diversification::Never(),
792           &out_params->forward_secure_crypters, &out_params->subkey_secret)) {
793     *error_details = "Symmetric key setup failed";
794     return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
795   }
796 
797   return QUIC_NO_ERROR;
798 }
799 
ProcessServerConfigUpdate(const CryptoHandshakeMessage & server_config_update,QuicWallTime now,const QuicTransportVersion version,absl::string_view chlo_hash,CachedState * cached,QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,std::string * error_details)800 QuicErrorCode QuicCryptoClientConfig::ProcessServerConfigUpdate(
801     const CryptoHandshakeMessage& server_config_update,
802     QuicWallTime now,
803     const QuicTransportVersion version,
804     absl::string_view chlo_hash,
805     CachedState* cached,
806     QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> out_params,
807     std::string* error_details) {
808   DCHECK(error_details != nullptr);
809 
810   if (server_config_update.tag() != kSCUP) {
811     *error_details = "ServerConfigUpdate must have kSCUP tag.";
812     return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
813   }
814   return CacheNewServerConfig(server_config_update, now, version, chlo_hash,
815                               out_params->cached_certs, cached, error_details);
816 }
817 
proof_verifier() const818 ProofVerifier* QuicCryptoClientConfig::proof_verifier() const {
819   return proof_verifier_.get();
820 }
821 
session_cache() const822 SessionCache* QuicCryptoClientConfig::session_cache() const {
823   return session_cache_.get();
824 }
825 
proof_source() const826 ProofSource* QuicCryptoClientConfig::proof_source() const {
827   return proof_source_.get();
828 }
829 
set_proof_source(std::unique_ptr<ProofSource> proof_source)830 void QuicCryptoClientConfig::set_proof_source(
831     std::unique_ptr<ProofSource> proof_source) {
832   proof_source_ = std::move(proof_source);
833 }
834 
ssl_ctx() const835 SSL_CTX* QuicCryptoClientConfig::ssl_ctx() const {
836   return ssl_ctx_.get();
837 }
838 
InitializeFrom(const QuicServerId & server_id,const QuicServerId & canonical_server_id,QuicCryptoClientConfig * canonical_crypto_config)839 void QuicCryptoClientConfig::InitializeFrom(
840     const QuicServerId& server_id,
841     const QuicServerId& canonical_server_id,
842     QuicCryptoClientConfig* canonical_crypto_config) {
843   CachedState* canonical_cached =
844       canonical_crypto_config->LookupOrCreate(canonical_server_id);
845   if (!canonical_cached->proof_valid()) {
846     return;
847   }
848   CachedState* cached = LookupOrCreate(server_id);
849   cached->InitializeFrom(*canonical_cached);
850 }
851 
AddCanonicalSuffix(const std::string & suffix)852 void QuicCryptoClientConfig::AddCanonicalSuffix(const std::string& suffix) {
853   canonical_suffixes_.push_back(suffix);
854 }
855 
PopulateFromCanonicalConfig(const QuicServerId & server_id,CachedState * server_state)856 bool QuicCryptoClientConfig::PopulateFromCanonicalConfig(
857     const QuicServerId& server_id,
858     CachedState* server_state) {
859   DCHECK(server_state->IsEmpty());
860   size_t i = 0;
861   for (; i < canonical_suffixes_.size(); ++i) {
862     if (absl::EndsWithIgnoreCase(server_id.host(), canonical_suffixes_[i])) {
863       break;
864     }
865   }
866   if (i == canonical_suffixes_.size()) {
867     return false;
868   }
869 
870   QuicServerId suffix_server_id(canonical_suffixes_[i], server_id.port(),
871                                 server_id.privacy_mode_enabled());
872   if (!QuicContainsKey(canonical_server_map_, suffix_server_id)) {
873     // This is the first host we've seen which matches the suffix, so make it
874     // canonical.
875     canonical_server_map_[suffix_server_id] = server_id;
876     return false;
877   }
878 
879   const QuicServerId& canonical_server_id =
880       canonical_server_map_[suffix_server_id];
881   CachedState* canonical_state = cached_states_[canonical_server_id].get();
882   if (!canonical_state->proof_valid()) {
883     return false;
884   }
885 
886   // Update canonical version to point at the "most recent" entry.
887   canonical_server_map_[suffix_server_id] = server_id;
888 
889   server_state->InitializeFrom(*canonical_state);
890   return true;
891 }
892 
893 }  // namespace quic
894