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/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" 21 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; 28 29 namespace net { 30 31 QuicCryptoClientConfig::QuicCryptoClientConfig() 32 : disable_ecdsa_(false) {} 33 34 QuicCryptoClientConfig::~QuicCryptoClientConfig() { 35 STLDeleteValues(&cached_states_); 36 } 37 38 QuicCryptoClientConfig::CachedState::CachedState() 39 : server_config_valid_(false), 40 generation_counter_(0) {} 41 42 QuicCryptoClientConfig::CachedState::~CachedState() {} 43 44 bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const { 45 if (server_config_.empty() || !server_config_valid_) { 46 return false; 47 } 48 49 const CryptoHandshakeMessage* scfg = GetServerConfig(); 50 if (!scfg) { 51 // Should be impossible short of cache corruption. 52 DCHECK(false); 53 return false; 54 } 55 56 uint64 expiry_seconds; 57 if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR || 58 now.ToUNIXSeconds() >= expiry_seconds) { 59 return false; 60 } 61 62 return true; 63 } 64 65 bool QuicCryptoClientConfig::CachedState::IsEmpty() const { 66 return server_config_.empty(); 67 } 68 69 const CryptoHandshakeMessage* 70 QuicCryptoClientConfig::CachedState::GetServerConfig() const { 71 if (server_config_.empty()) { 72 return NULL; 73 } 74 75 if (!scfg_.get()) { 76 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); 77 DCHECK(scfg_.get()); 78 } 79 return scfg_.get(); 80 } 81 82 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig( 83 StringPiece server_config, QuicWallTime now, string* error_details) { 84 const bool matches_existing = server_config == server_config_; 85 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; 90 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(); 96 } 97 98 if (!new_scfg) { 99 *error_details = "SCFG invalid"; 100 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 101 } 102 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; 107 } 108 109 if (now.ToUNIXSeconds() >= expiry_seconds) { 110 *error_details = "SCFG has expired"; 111 return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED; 112 } 113 114 if (!matches_existing) { 115 server_config_ = server_config.as_string(); 116 SetProofInvalid(); 117 scfg_.reset(new_scfg_storage.release()); 118 } 119 return QUIC_NO_ERROR; 120 } 121 122 void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() { 123 server_config_.clear(); 124 scfg_.reset(); 125 SetProofInvalid(); 126 } 127 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(); 132 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; 138 } 139 } 140 } 141 142 if (!has_changed) { 143 return; 144 } 145 146 // If the proof has changed then it needs to be revalidated. 147 SetProofInvalid(); 148 certs_ = certs; 149 server_config_sig_ = signature.as_string(); 150 } 151 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_; 161 } 162 163 void QuicCryptoClientConfig::CachedState::ClearProof() { 164 SetProofInvalid(); 165 certs_.clear(); 166 server_config_sig_.clear(); 167 } 168 169 void QuicCryptoClientConfig::CachedState::SetProofValid() { 170 server_config_valid_ = true; 171 } 172 173 void QuicCryptoClientConfig::CachedState::SetProofInvalid() { 174 server_config_valid_ = false; 175 ++generation_counter_; 176 } 177 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()); 185 186 if (server_config.empty()) { 187 return false; 188 } 189 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; 196 } 197 198 signature.CopyToString(&server_config_sig_); 199 source_address_token.CopyToString(&source_address_token_); 200 certs_ = certs; 201 return true; 202 } 203 204 const string& QuicCryptoClientConfig::CachedState::server_config() const { 205 return server_config_; 206 } 207 208 const string& 209 QuicCryptoClientConfig::CachedState::source_address_token() const { 210 return source_address_token_; 211 } 212 213 const vector<string>& QuicCryptoClientConfig::CachedState::certs() const { 214 return certs_; 215 } 216 217 const string& QuicCryptoClientConfig::CachedState::signature() const { 218 return server_config_sig_; 219 } 220 221 bool QuicCryptoClientConfig::CachedState::proof_valid() const { 222 return server_config_valid_; 223 } 224 225 uint64 QuicCryptoClientConfig::CachedState::generation_counter() const { 226 return generation_counter_; 227 } 228 229 const ProofVerifyDetails* 230 QuicCryptoClientConfig::CachedState::proof_verify_details() const { 231 return proof_verify_details_.get(); 232 } 233 234 void QuicCryptoClientConfig::CachedState::set_source_address_token( 235 StringPiece token) { 236 source_address_token_ = token.as_string(); 237 } 238 239 void QuicCryptoClientConfig::CachedState::SetProofVerifyDetails( 240 ProofVerifyDetails* details) { 241 proof_verify_details_.reset(details); 242 } 243 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_; 254 } 255 256 void QuicCryptoClientConfig::SetDefaults() { 257 // Key exchange methods. 258 kexs.resize(2); 259 kexs[0] = kC255; 260 kexs[1] = kP256; 261 262 // Authenticated encryption algorithms. Prefer ChaCha20 by default. 263 aead.clear(); 264 if (ChaCha20Poly1305Encrypter::IsSupported()) { 265 aead.push_back(kCC12); 266 } 267 aead.push_back(kAESG); 268 269 disable_ecdsa_ = false; 270 } 271 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; 277 } 278 279 CachedState* cached = new CachedState; 280 cached_states_.insert(make_pair(server_id, cached)); 281 PopulateFromCanonicalConfig(server_id, cached); 282 return cached; 283 } 284 285 void QuicCryptoClientConfig::ClearCachedStates() { 286 for (CachedStateMap::const_iterator it = cached_states_.begin(); 287 it != cached_states_.end(); ++it) { 288 it->second->Clear(); 289 } 290 } 291 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); 300 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()); 305 } 306 out->SetValue(kVER, QuicVersionToQuicTag(preferred_version)); 307 308 if (!user_agent_id_.empty()) { 309 out->SetStringPiece(kUAID, user_agent_id_); 310 } 311 312 if (!cached->source_address_token().empty()) { 313 out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token()); 314 } 315 316 if (server_id.is_https()) { 317 if (disable_ecdsa_) { 318 out->SetTaglist(kPDMD, kX59R, 0); 319 } else { 320 out->SetTaglist(kPDMD, kX509, 0); 321 } 322 } 323 324 if (common_cert_sets) { 325 out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes()); 326 } 327 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())); 340 } 341 out->SetVector(kCCRT, hashes); 342 } 343 } 344 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); 357 358 FillInchoateClientHello(server_id, preferred_version, cached, 359 out_params, out); 360 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; 367 } 368 369 StringPiece scid; 370 if (!scfg->GetStringPiece(kSCID, &scid)) { 371 *error_details = "SCFG missing SCID"; 372 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 373 } 374 out->SetStringPiece(kSCID, scid); 375 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; 385 } 386 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; 402 } 403 out->SetTaglist(kAEAD, out_params->aead, 0); 404 out->SetTaglist(kKEXS, out_params->key_exchange, 0); 405 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; 411 } 412 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; 417 } 418 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); 423 } 424 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; 438 } 439 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; 444 } 445 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); 446 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); 453 454 CryptoHandshakeMessage cetv; 455 cetv.set_tag(kCETV); 456 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()); 466 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; 472 } 473 474 cetv.SetStringPiece(kCIDK, key); 475 cetv.SetStringPiece(kCIDS, signature); 476 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; 484 } 485 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; 494 } 495 496 out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece()); 497 out->MarkDirty(); 498 499 out->set_minimum_size(orig_min_size); 500 } 501 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()); 513 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); 519 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; 526 } 527 528 return QUIC_NO_ERROR; 529 } 530 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); 538 539 if (rej.tag() != kREJ) { 540 *error_details = "Message is not REJ"; 541 return QUIC_CRYPTO_INTERNAL_ERROR; 542 } 543 544 StringPiece scfg; 545 if (!rej.GetStringPiece(kSCFG, &scfg)) { 546 *error_details = "Missing SCFG"; 547 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 548 } 549 550 QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details); 551 if (error != QUIC_NO_ERROR) { 552 return error; 553 } 554 555 StringPiece token; 556 if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) { 557 cached->set_source_address_token(token); 558 } 559 560 StringPiece nonce; 561 if (rej.GetStringPiece(kServerNonceTag, &nonce)) { 562 out_params->server_nonce = nonce.as_string(); 563 } 564 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; 574 } 575 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; 582 } 583 584 if (!has_proof && has_cert) { 585 *error_details = "Proof missing"; 586 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 587 } 588 } 589 590 const QuicTag* reject_reasons; 591 size_t num_reject_reasons; 592 if (rej.GetTaglist(kRREJ, &reject_reasons, 593 &num_reject_reasons) == QUIC_NO_ERROR) { 594 #if defined(DEBUG) 595 for (size_t i = 0; i < num_reject_reasons; ++i) { 596 DVLOG(1) << "Reasons for rejection: " << reject_reasons[i]; 597 } 598 #endif 599 } 600 601 return QUIC_NO_ERROR; 602 } 603 604 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( 605 const CryptoHandshakeMessage& server_hello, 606 QuicConnectionId connection_id, 607 const QuicVersionVector& negotiated_versions, 608 CachedState* cached, 609 QuicCryptoNegotiatedParameters* out_params, 610 string* error_details) { 611 DCHECK(error_details != NULL); 612 613 if (server_hello.tag() != kSHLO) { 614 *error_details = "Bad tag"; 615 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; 616 } 617 618 const QuicTag* supported_version_tags; 619 size_t num_supported_versions; 620 621 if (server_hello.GetTaglist(kVER, &supported_version_tags, 622 &num_supported_versions) != QUIC_NO_ERROR) { 623 *error_details = "server hello missing version list"; 624 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 625 } 626 if (!negotiated_versions.empty()) { 627 bool mismatch = num_supported_versions != negotiated_versions.size(); 628 for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) { 629 mismatch = QuicTagToQuicVersion(supported_version_tags[i]) != 630 negotiated_versions[i]; 631 } 632 // The server sent a list of supported versions, and the connection 633 // reports that there was a version negotiation during the handshake. 634 // Ensure that these two lists are identical. 635 if (mismatch) { 636 *error_details = "Downgrade attack detected"; 637 return QUIC_VERSION_NEGOTIATION_MISMATCH; 638 } 639 } 640 641 // Learn about updated source address tokens. 642 StringPiece token; 643 if (server_hello.GetStringPiece(kSourceAddressTokenTag, &token)) { 644 cached->set_source_address_token(token); 645 } 646 647 // TODO(agl): 648 // learn about updated SCFGs. 649 650 StringPiece public_value; 651 if (!server_hello.GetStringPiece(kPUBS, &public_value)) { 652 *error_details = "server hello missing forward secure public value"; 653 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 654 } 655 656 if (!out_params->client_key_exchange->CalculateSharedKey( 657 public_value, &out_params->forward_secure_premaster_secret)) { 658 *error_details = "Key exchange failure"; 659 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 660 } 661 662 string hkdf_input; 663 const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1; 664 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); 665 hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len); 666 hkdf_input.append(out_params->hkdf_input_suffix); 667 668 if (!CryptoUtils::DeriveKeys( 669 out_params->forward_secure_premaster_secret, out_params->aead, 670 out_params->client_nonce, out_params->server_nonce, hkdf_input, 671 CryptoUtils::CLIENT, &out_params->forward_secure_crypters)) { 672 *error_details = "Symmetric key setup failed"; 673 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED; 674 } 675 676 return QUIC_NO_ERROR; 677 } 678 679 ProofVerifier* QuicCryptoClientConfig::proof_verifier() const { 680 return proof_verifier_.get(); 681 } 682 683 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) { 684 proof_verifier_.reset(verifier); 685 } 686 687 ChannelIDSource* QuicCryptoClientConfig::channel_id_source() const { 688 return channel_id_source_.get(); 689 } 690 691 void QuicCryptoClientConfig::SetChannelIDSource(ChannelIDSource* source) { 692 channel_id_source_.reset(source); 693 } 694 695 void QuicCryptoClientConfig::InitializeFrom( 696 const QuicServerId& server_id, 697 const QuicServerId& canonical_server_id, 698 QuicCryptoClientConfig* canonical_crypto_config) { 699 CachedState* canonical_cached = 700 canonical_crypto_config->LookupOrCreate(canonical_server_id); 701 if (!canonical_cached->proof_valid()) { 702 return; 703 } 704 CachedState* cached = LookupOrCreate(server_id); 705 cached->InitializeFrom(*canonical_cached); 706 } 707 708 void QuicCryptoClientConfig::AddCanonicalSuffix(const string& suffix) { 709 canoncial_suffixes_.push_back(suffix); 710 } 711 712 void QuicCryptoClientConfig::PreferAesGcm() { 713 DCHECK(!aead.empty()); 714 if (aead.size() <= 1) { 715 return; 716 } 717 QuicTagVector::iterator pos = find(aead.begin(), aead.end(), kAESG); 718 if (pos != aead.end()) { 719 aead.erase(pos); 720 aead.insert(aead.begin(), kAESG); 721 } 722 } 723 724 void QuicCryptoClientConfig::DisableEcdsa() { 725 disable_ecdsa_ = true; 726 } 727 728 void QuicCryptoClientConfig::PopulateFromCanonicalConfig( 729 const QuicServerId& server_id, 730 CachedState* server_state) { 731 DCHECK(server_state->IsEmpty()); 732 size_t i = 0; 733 for (; i < canoncial_suffixes_.size(); ++i) { 734 if (EndsWith(server_id.host(), canoncial_suffixes_[i], false)) { 735 break; 736 } 737 } 738 if (i == canoncial_suffixes_.size()) 739 return; 740 741 QuicServerId suffix_server_id(canoncial_suffixes_[i], server_id.port(), 742 server_id.is_https(), 743 server_id.privacy_mode()); 744 if (!ContainsKey(canonical_server_map_, suffix_server_id)) { 745 // This is the first host we've seen which matches the suffix, so make it 746 // canonical. 747 canonical_server_map_[suffix_server_id] = server_id; 748 return; 749 } 750 751 const QuicServerId& canonical_server_id = 752 canonical_server_map_[suffix_server_id]; 753 CachedState* canonical_state = cached_states_[canonical_server_id]; 754 if (!canonical_state->proof_valid()) { 755 return; 756 } 757 758 // Update canonical version to point at the "most recent" entry. 759 canonical_server_map_[suffix_server_id] = server_id; 760 761 server_state->InitializeFrom(*canonical_state); 762 } 763 764 } // namespace net 765