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.
5 #include "net/quic/crypto/quic_crypto_client_config.h"
7 #include "base/stl_util.h"
8 #include "base/strings/string_util.h"
9 #include "net/quic/crypto/cert_compressor.h"
10 #include "net/quic/crypto/chacha20_poly1305_encrypter.h"
11 #include "net/quic/crypto/channel_id.h"
12 #include "net/quic/crypto/common_cert_set.h"
13 #include "net/quic/crypto/crypto_framer.h"
14 #include "net/quic/crypto/crypto_utils.h"
15 #include "net/quic/crypto/curve25519_key_exchange.h"
16 #include "net/quic/crypto/key_exchange.h"
17 #include "net/quic/crypto/p256_key_exchange.h"
18 #include "net/quic/crypto/proof_verifier.h"
19 #include "net/quic/crypto/quic_encrypter.h"
20 #include "net/quic/quic_session_key.h"
21 #include "net/quic/quic_utils.h"
23 using base::StringPiece
;
32 QuicCryptoClientConfig::QuicCryptoClientConfig()
33 : disable_ecdsa_(false) {}
35 QuicCryptoClientConfig::~QuicCryptoClientConfig() {
36 STLDeleteValues(&cached_states_
);
39 QuicCryptoClientConfig::CachedState::CachedState()
40 : server_config_valid_(false),
41 generation_counter_(0) {}
43 QuicCryptoClientConfig::CachedState::~CachedState() {}
45 bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now
) const {
46 if (server_config_
.empty() || !server_config_valid_
) {
50 const CryptoHandshakeMessage
* scfg
= GetServerConfig();
52 // Should be impossible short of cache corruption.
57 uint64 expiry_seconds
;
58 if (scfg
->GetUint64(kEXPY
, &expiry_seconds
) != QUIC_NO_ERROR
||
59 now
.ToUNIXSeconds() >= expiry_seconds
) {
66 bool QuicCryptoClientConfig::CachedState::IsEmpty() const {
67 return server_config_
.empty();
70 const CryptoHandshakeMessage
*
71 QuicCryptoClientConfig::CachedState::GetServerConfig() const {
72 if (server_config_
.empty()) {
77 scfg_
.reset(CryptoFramer::ParseMessage(server_config_
));
83 QuicErrorCode
QuicCryptoClientConfig::CachedState::SetServerConfig(
84 StringPiece server_config
, QuicWallTime now
, string
* error_details
) {
85 const bool matches_existing
= server_config
== server_config_
;
87 // Even if the new server config matches the existing one, we still wish to
88 // reject it if it has expired.
89 scoped_ptr
<CryptoHandshakeMessage
> new_scfg_storage
;
90 const CryptoHandshakeMessage
* new_scfg
;
92 if (!matches_existing
) {
93 new_scfg_storage
.reset(CryptoFramer::ParseMessage(server_config
));
94 new_scfg
= new_scfg_storage
.get();
96 new_scfg
= GetServerConfig();
100 *error_details
= "SCFG invalid";
101 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
104 uint64 expiry_seconds
;
105 if (new_scfg
->GetUint64(kEXPY
, &expiry_seconds
) != QUIC_NO_ERROR
) {
106 *error_details
= "SCFG missing EXPY";
107 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
110 if (now
.ToUNIXSeconds() >= expiry_seconds
) {
111 *error_details
= "SCFG has expired";
112 return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED
;
115 if (!matches_existing
) {
116 server_config_
= server_config
.as_string();
118 scfg_
.reset(new_scfg_storage
.release());
120 return QUIC_NO_ERROR
;
123 void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() {
124 server_config_
.clear();
129 void QuicCryptoClientConfig::CachedState::SetProof(const vector
<string
>& certs
,
130 StringPiece signature
) {
132 signature
!= server_config_sig_
|| certs_
.size() != certs
.size();
135 for (size_t i
= 0; i
< certs_
.size(); i
++) {
136 if (certs_
[i
] != certs
[i
]) {
147 // If the proof has changed then it needs to be revalidated.
150 server_config_sig_
= signature
.as_string();
153 void QuicCryptoClientConfig::CachedState::ClearProof() {
156 server_config_sig_
.clear();
159 void QuicCryptoClientConfig::CachedState::SetProofValid() {
160 server_config_valid_
= true;
163 void QuicCryptoClientConfig::CachedState::SetProofInvalid() {
164 server_config_valid_
= false;
165 ++generation_counter_
;
168 bool QuicCryptoClientConfig::CachedState::Initialize(
169 StringPiece server_config
,
170 StringPiece source_address_token
,
171 const vector
<string
>& certs
,
172 StringPiece signature
,
174 DCHECK(server_config_
.empty());
176 if (server_config
.empty()) {
180 string error_details
;
181 QuicErrorCode error
= SetServerConfig(server_config
, now
,
183 if (error
!= QUIC_NO_ERROR
) {
184 DVLOG(1) << "SetServerConfig failed with " << error_details
;
188 signature
.CopyToString(&server_config_sig_
);
189 source_address_token
.CopyToString(&source_address_token_
);
194 const string
& QuicCryptoClientConfig::CachedState::server_config() const {
195 return server_config_
;
199 QuicCryptoClientConfig::CachedState::source_address_token() const {
200 return source_address_token_
;
203 const vector
<string
>& QuicCryptoClientConfig::CachedState::certs() const {
207 const string
& QuicCryptoClientConfig::CachedState::signature() const {
208 return server_config_sig_
;
211 bool QuicCryptoClientConfig::CachedState::proof_valid() const {
212 return server_config_valid_
;
215 uint64
QuicCryptoClientConfig::CachedState::generation_counter() const {
216 return generation_counter_
;
219 const ProofVerifyDetails
*
220 QuicCryptoClientConfig::CachedState::proof_verify_details() const {
221 return proof_verify_details_
.get();
224 void QuicCryptoClientConfig::CachedState::set_source_address_token(
226 source_address_token_
= token
.as_string();
229 void QuicCryptoClientConfig::CachedState::SetProofVerifyDetails(
230 ProofVerifyDetails
* details
) {
231 proof_verify_details_
.reset(details
);
234 void QuicCryptoClientConfig::CachedState::InitializeFrom(
235 const QuicCryptoClientConfig::CachedState
& other
) {
236 DCHECK(server_config_
.empty());
237 DCHECK(!server_config_valid_
);
238 server_config_
= other
.server_config_
;
239 source_address_token_
= other
.source_address_token_
;
240 certs_
= other
.certs_
;
241 server_config_sig_
= other
.server_config_sig_
;
242 server_config_valid_
= other
.server_config_valid_
;
243 ++generation_counter_
;
246 void QuicCryptoClientConfig::SetDefaults() {
247 // Key exchange methods.
252 // Authenticated encryption algorithms. Prefer ChaCha20 by default.
254 if (ChaCha20Poly1305Encrypter::IsSupported()) {
255 aead
.push_back(kCC12
);
257 aead
.push_back(kAESG
);
259 disable_ecdsa_
= false;
262 QuicCryptoClientConfig::CachedState
* QuicCryptoClientConfig::LookupOrCreate(
263 const QuicSessionKey
& server_key
) {
264 CachedStateMap::const_iterator it
= cached_states_
.find(server_key
);
265 if (it
!= cached_states_
.end()) {
269 CachedState
* cached
= new CachedState
;
270 cached_states_
.insert(make_pair(server_key
, cached
));
271 PopulateFromCanonicalConfig(server_key
, cached
);
275 void QuicCryptoClientConfig::FillInchoateClientHello(
276 const QuicSessionKey
& server_key
,
277 const QuicVersion preferred_version
,
278 const CachedState
* cached
,
279 QuicCryptoNegotiatedParameters
* out_params
,
280 CryptoHandshakeMessage
* out
) const {
282 out
->set_minimum_size(kClientHelloMinimumSize
);
284 // Server name indication. We only send SNI if it's a valid domain name, as
286 if (CryptoUtils::IsValidSNI(server_key
.host())) {
287 out
->SetStringPiece(kSNI
, server_key
.host());
289 out
->SetValue(kVER
, QuicVersionToQuicTag(preferred_version
));
291 if (!cached
->source_address_token().empty()) {
292 out
->SetStringPiece(kSourceAddressTokenTag
, cached
->source_address_token());
295 if (server_key
.is_https()) {
296 if (disable_ecdsa_
) {
297 out
->SetTaglist(kPDMD
, kX59R
, 0);
299 out
->SetTaglist(kPDMD
, kX509
, 0);
303 if (common_cert_sets
) {
304 out
->SetStringPiece(kCCS
, common_cert_sets
->GetCommonHashes());
307 const vector
<string
>& certs
= cached
->certs();
308 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the
309 // client config is being used for multiple connections, another connection
310 // doesn't update the cached certificates and cause us to be unable to
311 // process the server's compressed certificate chain.
312 out_params
->cached_certs
= certs
;
313 if (!certs
.empty()) {
314 vector
<uint64
> hashes
;
315 hashes
.reserve(certs
.size());
316 for (vector
<string
>::const_iterator i
= certs
.begin();
317 i
!= certs
.end(); ++i
) {
318 hashes
.push_back(QuicUtils::FNV1a_64_Hash(i
->data(), i
->size()));
320 out
->SetVector(kCCRT
, hashes
);
324 QuicErrorCode
QuicCryptoClientConfig::FillClientHello(
325 const QuicSessionKey
& server_key
,
326 QuicConnectionId connection_id
,
327 const QuicVersion preferred_version
,
328 const CachedState
* cached
,
331 QuicCryptoNegotiatedParameters
* out_params
,
332 CryptoHandshakeMessage
* out
,
333 string
* error_details
) const {
334 DCHECK(error_details
!= NULL
);
336 FillInchoateClientHello(server_key
, preferred_version
, cached
,
339 const CryptoHandshakeMessage
* scfg
= cached
->GetServerConfig();
341 // This should never happen as our caller should have checked
342 // cached->IsComplete() before calling this function.
343 *error_details
= "Handshake not ready";
344 return QUIC_CRYPTO_INTERNAL_ERROR
;
348 if (!scfg
->GetStringPiece(kSCID
, &scid
)) {
349 *error_details
= "SCFG missing SCID";
350 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
352 out
->SetStringPiece(kSCID
, scid
);
354 const QuicTag
* their_aeads
;
355 const QuicTag
* their_key_exchanges
;
356 size_t num_their_aeads
, num_their_key_exchanges
;
357 if (scfg
->GetTaglist(kAEAD
, &their_aeads
,
358 &num_their_aeads
) != QUIC_NO_ERROR
||
359 scfg
->GetTaglist(kKEXS
, &their_key_exchanges
,
360 &num_their_key_exchanges
) != QUIC_NO_ERROR
) {
361 *error_details
= "Missing AEAD or KEXS";
362 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
365 // AEAD: the work loads on the client and server are symmetric. Since the
366 // client is more likely to be CPU-constrained, break the tie by favoring
367 // the client's preference.
368 // Key exchange: the client does more work than the server, so favor the
369 // client's preference.
370 size_t key_exchange_index
;
371 if (!QuicUtils::FindMutualTag(
372 aead
, their_aeads
, num_their_aeads
, QuicUtils::LOCAL_PRIORITY
,
373 &out_params
->aead
, NULL
) ||
374 !QuicUtils::FindMutualTag(
375 kexs
, their_key_exchanges
, num_their_key_exchanges
,
376 QuicUtils::LOCAL_PRIORITY
, &out_params
->key_exchange
,
377 &key_exchange_index
)) {
378 *error_details
= "Unsupported AEAD or KEXS";
379 return QUIC_CRYPTO_NO_SUPPORT
;
381 out
->SetTaglist(kAEAD
, out_params
->aead
, 0);
382 out
->SetTaglist(kKEXS
, out_params
->key_exchange
, 0);
384 StringPiece public_value
;
385 if (scfg
->GetNthValue24(kPUBS
, key_exchange_index
, &public_value
) !=
387 *error_details
= "Missing public value";
388 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
392 if (!scfg
->GetStringPiece(kORBT
, &orbit
) || orbit
.size() != kOrbitSize
) {
393 *error_details
= "SCFG missing OBIT";
394 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
;
397 CryptoUtils::GenerateNonce(now
, rand
, orbit
, &out_params
->client_nonce
);
398 out
->SetStringPiece(kNONC
, out_params
->client_nonce
);
399 if (!out_params
->server_nonce
.empty()) {
400 out
->SetStringPiece(kServerNonceTag
, out_params
->server_nonce
);
403 switch (out_params
->key_exchange
) {
405 out_params
->client_key_exchange
.reset(Curve25519KeyExchange::New(
406 Curve25519KeyExchange::NewPrivateKey(rand
)));
409 out_params
->client_key_exchange
.reset(P256KeyExchange::New(
410 P256KeyExchange::NewPrivateKey()));
414 *error_details
= "Configured to support an unknown key exchange";
415 return QUIC_CRYPTO_INTERNAL_ERROR
;
418 if (!out_params
->client_key_exchange
->CalculateSharedKey(
419 public_value
, &out_params
->initial_premaster_secret
)) {
420 *error_details
= "Key exchange failure";
421 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
423 out
->SetStringPiece(kPUBS
, out_params
->client_key_exchange
->public_value());
425 bool do_channel_id
= false;
426 if (channel_id_signer_
.get()) {
427 const QuicTag
* their_proof_demands
;
428 size_t num_their_proof_demands
;
429 if (scfg
->GetTaglist(kPDMD
, &their_proof_demands
,
430 &num_their_proof_demands
) == QUIC_NO_ERROR
) {
431 for (size_t i
= 0; i
< num_their_proof_demands
; i
++) {
432 if (their_proof_demands
[i
] == kCHID
) {
433 do_channel_id
= true;
441 // In order to calculate the encryption key for the CETV block we need to
442 // serialise the client hello as it currently is (i.e. without the CETV
443 // block). For this, the client hello is serialized without padding.
444 const size_t orig_min_size
= out
->minimum_size();
445 out
->set_minimum_size(0);
447 CryptoHandshakeMessage cetv
;
451 const QuicData
& client_hello_serialized
= out
->GetSerialized();
452 hkdf_input
.append(QuicCryptoConfig::kCETVLabel
,
453 strlen(QuicCryptoConfig::kCETVLabel
) + 1);
454 hkdf_input
.append(reinterpret_cast<char*>(&connection_id
),
455 sizeof(connection_id
));
456 hkdf_input
.append(client_hello_serialized
.data(),
457 client_hello_serialized
.length());
458 hkdf_input
.append(cached
->server_config());
460 string key
, signature
;
461 if (!channel_id_signer_
->Sign(server_key
.host(), hkdf_input
,
463 *error_details
= "Channel ID signature failed";
464 return QUIC_INVALID_CHANNEL_ID_SIGNATURE
;
467 cetv
.SetStringPiece(kCIDK
, key
);
468 cetv
.SetStringPiece(kCIDS
, signature
);
470 CrypterPair crypters
;
471 if (!CryptoUtils::DeriveKeys(out_params
->initial_premaster_secret
,
472 out_params
->aead
, out_params
->client_nonce
,
473 out_params
->server_nonce
, hkdf_input
,
474 CryptoUtils::CLIENT
, &crypters
)) {
475 *error_details
= "Symmetric key setup failed";
476 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED
;
479 const QuicData
& cetv_plaintext
= cetv
.GetSerialized();
480 scoped_ptr
<QuicData
> cetv_ciphertext(crypters
.encrypter
->EncryptPacket(
481 0 /* sequence number */,
482 StringPiece() /* associated data */,
483 cetv_plaintext
.AsStringPiece()));
484 if (!cetv_ciphertext
.get()) {
485 *error_details
= "Packet encryption failed";
486 return QUIC_ENCRYPTION_FAILURE
;
489 out
->SetStringPiece(kCETV
, cetv_ciphertext
->AsStringPiece());
492 out
->set_minimum_size(orig_min_size
);
495 out_params
->hkdf_input_suffix
.clear();
496 out_params
->hkdf_input_suffix
.append(reinterpret_cast<char*>(&connection_id
),
497 sizeof(connection_id
));
498 const QuicData
& client_hello_serialized
= out
->GetSerialized();
499 out_params
->hkdf_input_suffix
.append(client_hello_serialized
.data(),
500 client_hello_serialized
.length());
501 out_params
->hkdf_input_suffix
.append(cached
->server_config());
504 const size_t label_len
= strlen(QuicCryptoConfig::kInitialLabel
) + 1;
505 hkdf_input
.reserve(label_len
+ out_params
->hkdf_input_suffix
.size());
506 hkdf_input
.append(QuicCryptoConfig::kInitialLabel
, label_len
);
507 hkdf_input
.append(out_params
->hkdf_input_suffix
);
509 if (!CryptoUtils::DeriveKeys(
510 out_params
->initial_premaster_secret
, out_params
->aead
,
511 out_params
->client_nonce
, out_params
->server_nonce
, hkdf_input
,
512 CryptoUtils::CLIENT
, &out_params
->initial_crypters
)) {
513 *error_details
= "Symmetric key setup failed";
514 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED
;
517 return QUIC_NO_ERROR
;
520 QuicErrorCode
QuicCryptoClientConfig::ProcessRejection(
521 const CryptoHandshakeMessage
& rej
,
524 QuicCryptoNegotiatedParameters
* out_params
,
525 string
* error_details
) {
526 DCHECK(error_details
!= NULL
);
528 if (rej
.tag() != kREJ
) {
529 *error_details
= "Message is not REJ";
530 return QUIC_CRYPTO_INTERNAL_ERROR
;
534 if (!rej
.GetStringPiece(kSCFG
, &scfg
)) {
535 *error_details
= "Missing SCFG";
536 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
;
539 QuicErrorCode error
= cached
->SetServerConfig(scfg
, now
, error_details
);
540 if (error
!= QUIC_NO_ERROR
) {
545 if (rej
.GetStringPiece(kSourceAddressTokenTag
, &token
)) {
546 cached
->set_source_address_token(token
);
550 if (rej
.GetStringPiece(kServerNonceTag
, &nonce
)) {
551 out_params
->server_nonce
= nonce
.as_string();
554 StringPiece proof
, cert_bytes
;
555 bool has_proof
= rej
.GetStringPiece(kPROF
, &proof
);
556 bool has_cert
= rej
.GetStringPiece(kCertificateTag
, &cert_bytes
);
557 if (has_proof
&& has_cert
) {
558 vector
<string
> certs
;
559 if (!CertCompressor::DecompressChain(cert_bytes
, out_params
->cached_certs
,
560 common_cert_sets
, &certs
)) {
561 *error_details
= "Certificate data invalid";
562 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
565 cached
->SetProof(certs
, proof
);
567 cached
->ClearProof();
568 if (has_proof
&& !has_cert
) {
569 *error_details
= "Certificate missing";
570 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
573 if (!has_proof
&& has_cert
) {
574 *error_details
= "Proof missing";
575 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
579 return QUIC_NO_ERROR
;
582 QuicErrorCode
QuicCryptoClientConfig::ProcessServerHello(
583 const CryptoHandshakeMessage
& server_hello
,
584 QuicConnectionId connection_id
,
585 const QuicVersionVector
& negotiated_versions
,
587 QuicCryptoNegotiatedParameters
* out_params
,
588 string
* error_details
) {
589 DCHECK(error_details
!= NULL
);
591 if (server_hello
.tag() != kSHLO
) {
592 *error_details
= "Bad tag";
593 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE
;
596 const QuicTag
* supported_version_tags
;
597 size_t num_supported_versions
;
599 if (server_hello
.GetTaglist(kVER
, &supported_version_tags
,
600 &num_supported_versions
) != QUIC_NO_ERROR
) {
601 *error_details
= "server hello missing version list";
602 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
604 if (!negotiated_versions
.empty()) {
605 bool mismatch
= num_supported_versions
!= negotiated_versions
.size();
606 for (size_t i
= 0; i
< num_supported_versions
&& !mismatch
; ++i
) {
607 mismatch
= QuicTagToQuicVersion(supported_version_tags
[i
]) !=
608 negotiated_versions
[i
];
610 // The server sent a list of supported versions, and the connection
611 // reports that there was a version negotiation during the handshake.
612 // Ensure that these two lists are identical.
614 *error_details
= "Downgrade attack detected";
615 return QUIC_VERSION_NEGOTIATION_MISMATCH
;
619 // Learn about updated source address tokens.
621 if (server_hello
.GetStringPiece(kSourceAddressTokenTag
, &token
)) {
622 cached
->set_source_address_token(token
);
626 // learn about updated SCFGs.
628 StringPiece public_value
;
629 if (!server_hello
.GetStringPiece(kPUBS
, &public_value
)) {
630 *error_details
= "server hello missing forward secure public value";
631 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
634 if (!out_params
->client_key_exchange
->CalculateSharedKey(
635 public_value
, &out_params
->forward_secure_premaster_secret
)) {
636 *error_details
= "Key exchange failure";
637 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
641 const size_t label_len
= strlen(QuicCryptoConfig::kForwardSecureLabel
) + 1;
642 hkdf_input
.reserve(label_len
+ out_params
->hkdf_input_suffix
.size());
643 hkdf_input
.append(QuicCryptoConfig::kForwardSecureLabel
, label_len
);
644 hkdf_input
.append(out_params
->hkdf_input_suffix
);
646 if (!CryptoUtils::DeriveKeys(
647 out_params
->forward_secure_premaster_secret
, out_params
->aead
,
648 out_params
->client_nonce
, out_params
->server_nonce
, hkdf_input
,
649 CryptoUtils::CLIENT
, &out_params
->forward_secure_crypters
)) {
650 *error_details
= "Symmetric key setup failed";
651 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED
;
654 return QUIC_NO_ERROR
;
657 ProofVerifier
* QuicCryptoClientConfig::proof_verifier() const {
658 return proof_verifier_
.get();
661 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier
* verifier
) {
662 proof_verifier_
.reset(verifier
);
665 ChannelIDSigner
* QuicCryptoClientConfig::channel_id_signer() const {
666 return channel_id_signer_
.get();
669 void QuicCryptoClientConfig::SetChannelIDSigner(ChannelIDSigner
* signer
) {
670 channel_id_signer_
.reset(signer
);
673 void QuicCryptoClientConfig::InitializeFrom(
674 const QuicSessionKey
& server_key
,
675 const QuicSessionKey
& canonical_server_key
,
676 QuicCryptoClientConfig
* canonical_crypto_config
) {
677 CachedState
* canonical_cached
=
678 canonical_crypto_config
->LookupOrCreate(canonical_server_key
);
679 if (!canonical_cached
->proof_valid()) {
682 CachedState
* cached
= LookupOrCreate(server_key
);
683 cached
->InitializeFrom(*canonical_cached
);
686 void QuicCryptoClientConfig::AddCanonicalSuffix(const string
& suffix
) {
687 canoncial_suffixes_
.push_back(suffix
);
690 void QuicCryptoClientConfig::PreferAesGcm() {
691 DCHECK(!aead
.empty());
692 if (aead
.size() <= 1) {
695 QuicTagVector::iterator pos
= find(aead
.begin(), aead
.end(), kAESG
);
696 if (pos
!= aead
.end()) {
698 aead
.insert(aead
.begin(), kAESG
);
702 void QuicCryptoClientConfig::DisableEcdsa() {
703 disable_ecdsa_
= true;
706 void QuicCryptoClientConfig::PopulateFromCanonicalConfig(
707 const QuicSessionKey
& server_key
,
708 CachedState
* server_state
) {
709 DCHECK(server_state
->IsEmpty());
711 for (; i
< canoncial_suffixes_
.size(); ++i
) {
712 if (EndsWith(server_key
.host(), canoncial_suffixes_
[i
], false)) {
716 if (i
== canoncial_suffixes_
.size())
719 QuicSessionKey
suffix_server_key(canoncial_suffixes_
[i
], server_key
.port(),
720 server_key
.is_https(),
721 server_key
.privacy_mode());
722 if (!ContainsKey(canonical_server_map_
, suffix_server_key
)) {
723 // This is the first host we've seen which matches the suffix, so make it
725 canonical_server_map_
[suffix_server_key
] = server_key
;
729 const QuicSessionKey
& canonical_server_key
=
730 canonical_server_map_
[suffix_server_key
];
731 CachedState
* canonical_state
= cached_states_
[canonical_server_key
];
732 if (!canonical_state
->proof_valid()) {
736 // Update canonical version to point at the "most recent" entry.
737 canonical_server_map_
[suffix_server_key
] = server_key
;
739 server_state
->InitializeFrom(*canonical_state
);