Lots of random cleanups, mostly for native_theme_win.cc:
[chromium-blink-merge.git] / net / quic / crypto / quic_crypto_client_config.cc
blobeed8cf10e8503af2f40c3376552135e365b8dad1
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_utils.h"
22 using base::StringPiece;
23 using std::find;
24 using std::make_pair;
25 using std::map;
26 using std::string;
27 using std::vector;
29 namespace net {
31 QuicCryptoClientConfig::QuicCryptoClientConfig()
32 : disable_ecdsa_(false) {}
34 QuicCryptoClientConfig::~QuicCryptoClientConfig() {
35 STLDeleteValues(&cached_states_);
38 QuicCryptoClientConfig::CachedState::CachedState()
39 : server_config_valid_(false),
40 generation_counter_(0) {}
42 QuicCryptoClientConfig::CachedState::~CachedState() {}
44 bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const {
45 if (server_config_.empty() || !server_config_valid_) {
46 return false;
49 const CryptoHandshakeMessage* scfg = GetServerConfig();
50 if (!scfg) {
51 // Should be impossible short of cache corruption.
52 DCHECK(false);
53 return false;
56 uint64 expiry_seconds;
57 if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR ||
58 now.ToUNIXSeconds() >= expiry_seconds) {
59 return false;
62 return true;
65 bool QuicCryptoClientConfig::CachedState::IsEmpty() const {
66 return server_config_.empty();
69 const CryptoHandshakeMessage*
70 QuicCryptoClientConfig::CachedState::GetServerConfig() const {
71 if (server_config_.empty()) {
72 return NULL;
75 if (!scfg_.get()) {
76 scfg_.reset(CryptoFramer::ParseMessage(server_config_));
77 DCHECK(scfg_.get());
79 return scfg_.get();
82 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig(
83 StringPiece server_config, QuicWallTime now, string* error_details) {
84 const bool matches_existing = server_config == server_config_;
86 // Even if the new server config matches the existing one, we still wish to
87 // reject it if it has expired.
88 scoped_ptr<CryptoHandshakeMessage> new_scfg_storage;
89 const CryptoHandshakeMessage* new_scfg;
91 if (!matches_existing) {
92 new_scfg_storage.reset(CryptoFramer::ParseMessage(server_config));
93 new_scfg = new_scfg_storage.get();
94 } else {
95 new_scfg = GetServerConfig();
98 if (!new_scfg) {
99 *error_details = "SCFG invalid";
100 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
103 uint64 expiry_seconds;
104 if (new_scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
105 *error_details = "SCFG missing EXPY";
106 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
109 if (now.ToUNIXSeconds() >= expiry_seconds) {
110 *error_details = "SCFG has expired";
111 return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED;
114 if (!matches_existing) {
115 server_config_ = server_config.as_string();
116 SetProofInvalid();
117 scfg_.reset(new_scfg_storage.release());
119 return QUIC_NO_ERROR;
122 void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() {
123 server_config_.clear();
124 scfg_.reset();
125 SetProofInvalid();
128 void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs,
129 StringPiece signature) {
130 bool has_changed =
131 signature != server_config_sig_ || certs_.size() != certs.size();
133 if (!has_changed) {
134 for (size_t i = 0; i < certs_.size(); i++) {
135 if (certs_[i] != certs[i]) {
136 has_changed = true;
137 break;
142 if (!has_changed) {
143 return;
146 // If the proof has changed then it needs to be revalidated.
147 SetProofInvalid();
148 certs_ = certs;
149 server_config_sig_ = signature.as_string();
152 void QuicCryptoClientConfig::CachedState::Clear() {
153 server_config_.clear();
154 source_address_token_.clear();
155 certs_.clear();
156 server_config_sig_.clear();
157 server_config_valid_ = false;
158 proof_verify_details_.reset();
159 scfg_.reset();
160 ++generation_counter_;
163 void QuicCryptoClientConfig::CachedState::ClearProof() {
164 SetProofInvalid();
165 certs_.clear();
166 server_config_sig_.clear();
169 void QuicCryptoClientConfig::CachedState::SetProofValid() {
170 server_config_valid_ = true;
173 void QuicCryptoClientConfig::CachedState::SetProofInvalid() {
174 server_config_valid_ = false;
175 ++generation_counter_;
178 bool QuicCryptoClientConfig::CachedState::Initialize(
179 StringPiece server_config,
180 StringPiece source_address_token,
181 const vector<string>& certs,
182 StringPiece signature,
183 QuicWallTime now) {
184 DCHECK(server_config_.empty());
186 if (server_config.empty()) {
187 return false;
190 string error_details;
191 QuicErrorCode error = SetServerConfig(server_config, now,
192 &error_details);
193 if (error != QUIC_NO_ERROR) {
194 DVLOG(1) << "SetServerConfig failed with " << error_details;
195 return false;
198 signature.CopyToString(&server_config_sig_);
199 source_address_token.CopyToString(&source_address_token_);
200 certs_ = certs;
201 return true;
204 const string& QuicCryptoClientConfig::CachedState::server_config() const {
205 return server_config_;
208 const string&
209 QuicCryptoClientConfig::CachedState::source_address_token() const {
210 return source_address_token_;
213 const vector<string>& QuicCryptoClientConfig::CachedState::certs() const {
214 return certs_;
217 const string& QuicCryptoClientConfig::CachedState::signature() const {
218 return server_config_sig_;
221 bool QuicCryptoClientConfig::CachedState::proof_valid() const {
222 return server_config_valid_;
225 uint64 QuicCryptoClientConfig::CachedState::generation_counter() const {
226 return generation_counter_;
229 const ProofVerifyDetails*
230 QuicCryptoClientConfig::CachedState::proof_verify_details() const {
231 return proof_verify_details_.get();
234 void QuicCryptoClientConfig::CachedState::set_source_address_token(
235 StringPiece token) {
236 source_address_token_ = token.as_string();
239 void QuicCryptoClientConfig::CachedState::SetProofVerifyDetails(
240 ProofVerifyDetails* details) {
241 proof_verify_details_.reset(details);
244 void QuicCryptoClientConfig::CachedState::InitializeFrom(
245 const QuicCryptoClientConfig::CachedState& other) {
246 DCHECK(server_config_.empty());
247 DCHECK(!server_config_valid_);
248 server_config_ = other.server_config_;
249 source_address_token_ = other.source_address_token_;
250 certs_ = other.certs_;
251 server_config_sig_ = other.server_config_sig_;
252 server_config_valid_ = other.server_config_valid_;
253 ++generation_counter_;
256 void QuicCryptoClientConfig::SetDefaults() {
257 // Key exchange methods.
258 kexs.resize(2);
259 kexs[0] = kC255;
260 kexs[1] = kP256;
262 // Authenticated encryption algorithms. Prefer ChaCha20 by default.
263 aead.clear();
264 if (ChaCha20Poly1305Encrypter::IsSupported()) {
265 aead.push_back(kCC12);
267 aead.push_back(kAESG);
269 disable_ecdsa_ = false;
272 QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate(
273 const QuicServerId& server_id) {
274 CachedStateMap::const_iterator it = cached_states_.find(server_id);
275 if (it != cached_states_.end()) {
276 return it->second;
279 CachedState* cached = new CachedState;
280 cached_states_.insert(make_pair(server_id, cached));
281 PopulateFromCanonicalConfig(server_id, cached);
282 return cached;
285 void QuicCryptoClientConfig::ClearCachedStates() {
286 for (CachedStateMap::const_iterator it = cached_states_.begin();
287 it != cached_states_.end(); ++it) {
288 it->second->Clear();
292 void QuicCryptoClientConfig::FillInchoateClientHello(
293 const QuicServerId& server_id,
294 const QuicVersion preferred_version,
295 const CachedState* cached,
296 QuicCryptoNegotiatedParameters* out_params,
297 CryptoHandshakeMessage* out) const {
298 out->set_tag(kCHLO);
299 out->set_minimum_size(kClientHelloMinimumSize);
301 // Server name indication. We only send SNI if it's a valid domain name, as
302 // per the spec.
303 if (CryptoUtils::IsValidSNI(server_id.host())) {
304 out->SetStringPiece(kSNI, server_id.host());
306 out->SetValue(kVER, QuicVersionToQuicTag(preferred_version));
308 if (!user_agent_id_.empty()) {
309 out->SetStringPiece(kUAID, user_agent_id_);
312 if (!cached->source_address_token().empty()) {
313 out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
316 if (server_id.is_https()) {
317 if (disable_ecdsa_) {
318 out->SetTaglist(kPDMD, kX59R, 0);
319 } else {
320 out->SetTaglist(kPDMD, kX509, 0);
324 if (common_cert_sets) {
325 out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes());
328 const vector<string>& certs = cached->certs();
329 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the
330 // client config is being used for multiple connections, another connection
331 // doesn't update the cached certificates and cause us to be unable to
332 // process the server's compressed certificate chain.
333 out_params->cached_certs = certs;
334 if (!certs.empty()) {
335 vector<uint64> hashes;
336 hashes.reserve(certs.size());
337 for (vector<string>::const_iterator i = certs.begin();
338 i != certs.end(); ++i) {
339 hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
341 out->SetVector(kCCRT, hashes);
345 QuicErrorCode QuicCryptoClientConfig::FillClientHello(
346 const QuicServerId& server_id,
347 QuicConnectionId connection_id,
348 const QuicVersion preferred_version,
349 const CachedState* cached,
350 QuicWallTime now,
351 QuicRandom* rand,
352 const ChannelIDKey* channel_id_key,
353 QuicCryptoNegotiatedParameters* out_params,
354 CryptoHandshakeMessage* out,
355 string* error_details) const {
356 DCHECK(error_details != NULL);
358 FillInchoateClientHello(server_id, preferred_version, cached,
359 out_params, out);
361 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
362 if (!scfg) {
363 // This should never happen as our caller should have checked
364 // cached->IsComplete() before calling this function.
365 *error_details = "Handshake not ready";
366 return QUIC_CRYPTO_INTERNAL_ERROR;
369 StringPiece scid;
370 if (!scfg->GetStringPiece(kSCID, &scid)) {
371 *error_details = "SCFG missing SCID";
372 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
374 out->SetStringPiece(kSCID, scid);
376 const QuicTag* their_aeads;
377 const QuicTag* their_key_exchanges;
378 size_t num_their_aeads, num_their_key_exchanges;
379 if (scfg->GetTaglist(kAEAD, &their_aeads,
380 &num_their_aeads) != QUIC_NO_ERROR ||
381 scfg->GetTaglist(kKEXS, &their_key_exchanges,
382 &num_their_key_exchanges) != QUIC_NO_ERROR) {
383 *error_details = "Missing AEAD or KEXS";
384 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
387 // AEAD: the work loads on the client and server are symmetric. Since the
388 // client is more likely to be CPU-constrained, break the tie by favoring
389 // the client's preference.
390 // Key exchange: the client does more work than the server, so favor the
391 // client's preference.
392 size_t key_exchange_index;
393 if (!QuicUtils::FindMutualTag(
394 aead, their_aeads, num_their_aeads, QuicUtils::LOCAL_PRIORITY,
395 &out_params->aead, NULL) ||
396 !QuicUtils::FindMutualTag(
397 kexs, their_key_exchanges, num_their_key_exchanges,
398 QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange,
399 &key_exchange_index)) {
400 *error_details = "Unsupported AEAD or KEXS";
401 return QUIC_CRYPTO_NO_SUPPORT;
403 out->SetTaglist(kAEAD, out_params->aead, 0);
404 out->SetTaglist(kKEXS, out_params->key_exchange, 0);
406 StringPiece public_value;
407 if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) !=
408 QUIC_NO_ERROR) {
409 *error_details = "Missing public value";
410 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
413 StringPiece orbit;
414 if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) {
415 *error_details = "SCFG missing OBIT";
416 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
419 CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce);
420 out->SetStringPiece(kNONC, out_params->client_nonce);
421 if (!out_params->server_nonce.empty()) {
422 out->SetStringPiece(kServerNonceTag, out_params->server_nonce);
425 switch (out_params->key_exchange) {
426 case kC255:
427 out_params->client_key_exchange.reset(Curve25519KeyExchange::New(
428 Curve25519KeyExchange::NewPrivateKey(rand)));
429 break;
430 case kP256:
431 out_params->client_key_exchange.reset(P256KeyExchange::New(
432 P256KeyExchange::NewPrivateKey()));
433 break;
434 default:
435 DCHECK(false);
436 *error_details = "Configured to support an unknown key exchange";
437 return QUIC_CRYPTO_INTERNAL_ERROR;
440 if (!out_params->client_key_exchange->CalculateSharedKey(
441 public_value, &out_params->initial_premaster_secret)) {
442 *error_details = "Key exchange failure";
443 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
445 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value());
447 if (channel_id_key) {
448 // In order to calculate the encryption key for the CETV block we need to
449 // serialise the client hello as it currently is (i.e. without the CETV
450 // block). For this, the client hello is serialized without padding.
451 const size_t orig_min_size = out->minimum_size();
452 out->set_minimum_size(0);
454 CryptoHandshakeMessage cetv;
455 cetv.set_tag(kCETV);
457 string hkdf_input;
458 const QuicData& client_hello_serialized = out->GetSerialized();
459 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
460 strlen(QuicCryptoConfig::kCETVLabel) + 1);
461 hkdf_input.append(reinterpret_cast<char*>(&connection_id),
462 sizeof(connection_id));
463 hkdf_input.append(client_hello_serialized.data(),
464 client_hello_serialized.length());
465 hkdf_input.append(cached->server_config());
467 string key = channel_id_key->SerializeKey();
468 string signature;
469 if (!channel_id_key->Sign(hkdf_input, &signature)) {
470 *error_details = "Channel ID signature failed";
471 return QUIC_INVALID_CHANNEL_ID_SIGNATURE;
474 cetv.SetStringPiece(kCIDK, key);
475 cetv.SetStringPiece(kCIDS, signature);
477 CrypterPair crypters;
478 if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret,
479 out_params->aead, out_params->client_nonce,
480 out_params->server_nonce, hkdf_input,
481 CryptoUtils::CLIENT, &crypters)) {
482 *error_details = "Symmetric key setup failed";
483 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
486 const QuicData& cetv_plaintext = cetv.GetSerialized();
487 scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket(
488 0 /* sequence number */,
489 StringPiece() /* associated data */,
490 cetv_plaintext.AsStringPiece()));
491 if (!cetv_ciphertext.get()) {
492 *error_details = "Packet encryption failed";
493 return QUIC_ENCRYPTION_FAILURE;
496 out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece());
497 out->MarkDirty();
499 out->set_minimum_size(orig_min_size);
502 // Derive the symmetric keys and set up the encrypters and decrypters.
503 // Set the following members of out_params:
504 // out_params->hkdf_input_suffix
505 // out_params->initial_crypters
506 out_params->hkdf_input_suffix.clear();
507 out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&connection_id),
508 sizeof(connection_id));
509 const QuicData& client_hello_serialized = out->GetSerialized();
510 out_params->hkdf_input_suffix.append(client_hello_serialized.data(),
511 client_hello_serialized.length());
512 out_params->hkdf_input_suffix.append(cached->server_config());
514 string hkdf_input;
515 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
516 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
517 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
518 hkdf_input.append(out_params->hkdf_input_suffix);
520 if (!CryptoUtils::DeriveKeys(
521 out_params->initial_premaster_secret, out_params->aead,
522 out_params->client_nonce, out_params->server_nonce, hkdf_input,
523 CryptoUtils::CLIENT, &out_params->initial_crypters)) {
524 *error_details = "Symmetric key setup failed";
525 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
528 return QUIC_NO_ERROR;
531 QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
532 const CryptoHandshakeMessage& rej,
533 QuicWallTime now,
534 CachedState* cached,
535 QuicCryptoNegotiatedParameters* out_params,
536 string* error_details) {
537 DCHECK(error_details != NULL);
539 if (rej.tag() != kREJ) {
540 *error_details = "Message is not REJ";
541 return QUIC_CRYPTO_INTERNAL_ERROR;
544 StringPiece scfg;
545 if (!rej.GetStringPiece(kSCFG, &scfg)) {
546 *error_details = "Missing SCFG";
547 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
550 QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details);
551 if (error != QUIC_NO_ERROR) {
552 return error;
555 StringPiece token;
556 if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) {
557 cached->set_source_address_token(token);
560 StringPiece nonce;
561 if (rej.GetStringPiece(kServerNonceTag, &nonce)) {
562 out_params->server_nonce = nonce.as_string();
565 StringPiece proof, cert_bytes;
566 bool has_proof = rej.GetStringPiece(kPROF, &proof);
567 bool has_cert = rej.GetStringPiece(kCertificateTag, &cert_bytes);
568 if (has_proof && has_cert) {
569 vector<string> certs;
570 if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs,
571 common_cert_sets, &certs)) {
572 *error_details = "Certificate data invalid";
573 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
576 cached->SetProof(certs, proof);
577 } else {
578 cached->ClearProof();
579 if (has_proof && !has_cert) {
580 *error_details = "Certificate missing";
581 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
584 if (!has_proof && has_cert) {
585 *error_details = "Proof missing";
586 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
590 const uint32* reject_reasons;
591 size_t num_reject_reasons;
592 COMPILE_ASSERT(sizeof(QuicTag) == sizeof(uint32), header_out_of_sync);
593 if (rej.GetTaglist(kRREJ, &reject_reasons,
594 &num_reject_reasons) == QUIC_NO_ERROR) {
595 #if defined(DEBUG)
596 uint32 packed_error = 0;
597 for (size_t i = 0; i < num_reject_reasons; ++i) {
598 // HANDSHAKE_OK is 0 and don't report that as error.
599 if (reject_reasons[i] == HANDSHAKE_OK || reject_reasons[i] >= 32) {
600 continue;
602 HandshakeFailureReason reason =
603 static_cast<HandshakeFailureReason>(reject_reasons[i]);
604 packed_error |= 1 << (reason - 1);
606 DVLOG(1) << "Reasons for rejection: " << packed_error;
607 #endif
610 return QUIC_NO_ERROR;
613 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
614 const CryptoHandshakeMessage& server_hello,
615 QuicConnectionId connection_id,
616 const QuicVersionVector& negotiated_versions,
617 CachedState* cached,
618 QuicCryptoNegotiatedParameters* out_params,
619 string* error_details) {
620 DCHECK(error_details != NULL);
622 if (server_hello.tag() != kSHLO) {
623 *error_details = "Bad tag";
624 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
627 const QuicTag* supported_version_tags;
628 size_t num_supported_versions;
630 if (server_hello.GetTaglist(kVER, &supported_version_tags,
631 &num_supported_versions) != QUIC_NO_ERROR) {
632 *error_details = "server hello missing version list";
633 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
635 if (!negotiated_versions.empty()) {
636 bool mismatch = num_supported_versions != negotiated_versions.size();
637 for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) {
638 mismatch = QuicTagToQuicVersion(supported_version_tags[i]) !=
639 negotiated_versions[i];
641 // The server sent a list of supported versions, and the connection
642 // reports that there was a version negotiation during the handshake.
643 // Ensure that these two lists are identical.
644 if (mismatch) {
645 *error_details = "Downgrade attack detected";
646 return QUIC_VERSION_NEGOTIATION_MISMATCH;
650 // Learn about updated source address tokens.
651 StringPiece token;
652 if (server_hello.GetStringPiece(kSourceAddressTokenTag, &token)) {
653 cached->set_source_address_token(token);
656 // TODO(agl):
657 // learn about updated SCFGs.
659 StringPiece public_value;
660 if (!server_hello.GetStringPiece(kPUBS, &public_value)) {
661 *error_details = "server hello missing forward secure public value";
662 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
665 if (!out_params->client_key_exchange->CalculateSharedKey(
666 public_value, &out_params->forward_secure_premaster_secret)) {
667 *error_details = "Key exchange failure";
668 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
671 string hkdf_input;
672 const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
673 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
674 hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len);
675 hkdf_input.append(out_params->hkdf_input_suffix);
677 if (!CryptoUtils::DeriveKeys(
678 out_params->forward_secure_premaster_secret, out_params->aead,
679 out_params->client_nonce, out_params->server_nonce, hkdf_input,
680 CryptoUtils::CLIENT, &out_params->forward_secure_crypters)) {
681 *error_details = "Symmetric key setup failed";
682 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
685 return QUIC_NO_ERROR;
688 ProofVerifier* QuicCryptoClientConfig::proof_verifier() const {
689 return proof_verifier_.get();
692 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) {
693 proof_verifier_.reset(verifier);
696 ChannelIDSource* QuicCryptoClientConfig::channel_id_source() const {
697 return channel_id_source_.get();
700 void QuicCryptoClientConfig::SetChannelIDSource(ChannelIDSource* source) {
701 channel_id_source_.reset(source);
704 void QuicCryptoClientConfig::InitializeFrom(
705 const QuicServerId& server_id,
706 const QuicServerId& canonical_server_id,
707 QuicCryptoClientConfig* canonical_crypto_config) {
708 CachedState* canonical_cached =
709 canonical_crypto_config->LookupOrCreate(canonical_server_id);
710 if (!canonical_cached->proof_valid()) {
711 return;
713 CachedState* cached = LookupOrCreate(server_id);
714 cached->InitializeFrom(*canonical_cached);
717 void QuicCryptoClientConfig::AddCanonicalSuffix(const string& suffix) {
718 canoncial_suffixes_.push_back(suffix);
721 void QuicCryptoClientConfig::PreferAesGcm() {
722 DCHECK(!aead.empty());
723 if (aead.size() <= 1) {
724 return;
726 QuicTagVector::iterator pos = find(aead.begin(), aead.end(), kAESG);
727 if (pos != aead.end()) {
728 aead.erase(pos);
729 aead.insert(aead.begin(), kAESG);
733 void QuicCryptoClientConfig::DisableEcdsa() {
734 disable_ecdsa_ = true;
737 void QuicCryptoClientConfig::PopulateFromCanonicalConfig(
738 const QuicServerId& server_id,
739 CachedState* server_state) {
740 DCHECK(server_state->IsEmpty());
741 size_t i = 0;
742 for (; i < canoncial_suffixes_.size(); ++i) {
743 if (EndsWith(server_id.host(), canoncial_suffixes_[i], false)) {
744 break;
747 if (i == canoncial_suffixes_.size())
748 return;
750 QuicServerId suffix_server_id(canoncial_suffixes_[i], server_id.port(),
751 server_id.is_https(),
752 server_id.privacy_mode());
753 if (!ContainsKey(canonical_server_map_, suffix_server_id)) {
754 // This is the first host we've seen which matches the suffix, so make it
755 // canonical.
756 canonical_server_map_[suffix_server_id] = server_id;
757 return;
760 const QuicServerId& canonical_server_id =
761 canonical_server_map_[suffix_server_id];
762 CachedState* canonical_state = cached_states_[canonical_server_id];
763 if (!canonical_state->proof_valid()) {
764 return;
767 // Update canonical version to point at the "most recent" entry.
768 canonical_server_map_[suffix_server_id] = server_id;
770 server_state->InitializeFrom(*canonical_state);
773 } // namespace net