Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(388)

Side by Side Diff: net/quic/crypto/quic_crypto_server_config.cc

Issue 2193073003: Move shared files in net/quic/ into net/quic/core/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: io_thread_unittest.cc Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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_server_config.h"
6
7 #include <stdlib.h>
8
9 #include <algorithm>
10 #include <memory>
11
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/stl_util.h"
15 #include "crypto/hkdf.h"
16 #include "crypto/secure_hash.h"
17 #include "net/base/ip_address.h"
18 #include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
19 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
20 #include "net/quic/crypto/cert_compressor.h"
21 #include "net/quic/crypto/chacha20_poly1305_encrypter.h"
22 #include "net/quic/crypto/channel_id.h"
23 #include "net/quic/crypto/crypto_framer.h"
24 #include "net/quic/crypto/crypto_handshake_message.h"
25 #include "net/quic/crypto/crypto_server_config_protobuf.h"
26 #include "net/quic/crypto/crypto_utils.h"
27 #include "net/quic/crypto/curve25519_key_exchange.h"
28 #include "net/quic/crypto/ephemeral_key_source.h"
29 #include "net/quic/crypto/key_exchange.h"
30 #include "net/quic/crypto/local_strike_register_client.h"
31 #include "net/quic/crypto/p256_key_exchange.h"
32 #include "net/quic/crypto/proof_source.h"
33 #include "net/quic/crypto/quic_decrypter.h"
34 #include "net/quic/crypto/quic_encrypter.h"
35 #include "net/quic/crypto/quic_random.h"
36 #include "net/quic/crypto/strike_register.h"
37 #include "net/quic/crypto/strike_register_client.h"
38 #include "net/quic/proto/source_address_token.pb.h"
39 #include "net/quic/quic_bug_tracker.h"
40 #include "net/quic/quic_clock.h"
41 #include "net/quic/quic_flags.h"
42 #include "net/quic/quic_protocol.h"
43 #include "net/quic/quic_socket_address_coder.h"
44 #include "net/quic/quic_utils.h"
45
46 using base::StringPiece;
47 using crypto::SecureHash;
48 using std::map;
49 using std::sort;
50 using std::string;
51 using std::vector;
52
53 namespace net {
54
55 namespace {
56
57 // kMultiplier is the multiple of the CHLO message size that a REJ message
58 // must stay under when the client doesn't present a valid source-address
59 // token. This is used to protect QUIC from amplification attacks.
60 // TODO(rch): Reduce this to 2 again once b/25933682 is fixed.
61 const size_t kMultiplier = 3;
62
63 const int kMaxTokenAddresses = 4;
64
65 string DeriveSourceAddressTokenKey(StringPiece source_address_token_secret) {
66 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */,
67 "QUIC source address token key",
68 CryptoSecretBoxer::GetKeySize(), 0 /* no fixed IV needed */,
69 0 /* no subkey secret */);
70 return hkdf.server_write_key().as_string();
71 }
72
73 IPAddress DualstackIPAddress(const IPAddress& ip) {
74 if (ip.IsIPv4()) {
75 return ConvertIPv4ToIPv4MappedIPv6(ip);
76 }
77 return ip;
78 }
79
80 } // namespace
81
82 class ValidateClientHelloHelper {
83 public:
84 ValidateClientHelloHelper(ValidateClientHelloResultCallback::Result* result,
85 ValidateClientHelloResultCallback* done_cb)
86 : result_(result), done_cb_(done_cb) {}
87
88 ~ValidateClientHelloHelper() {
89 QUIC_BUG_IF(done_cb_ != nullptr)
90 << "Deleting ValidateClientHelloHelper with a pending callback.";
91 }
92
93 void ValidationComplete(
94 QuicErrorCode error_code,
95 const char* error_details,
96 std::unique_ptr<ProofSource::Details> proof_source_details) {
97 result_->error_code = error_code;
98 result_->error_details = error_details;
99 done_cb_->Run(result_, std::move(proof_source_details));
100 DetachCallback();
101 }
102
103 void DetachCallback() {
104 QUIC_BUG_IF(done_cb_ == nullptr) << "Callback already detached.";
105 done_cb_ = nullptr;
106 }
107
108 private:
109 ValidateClientHelloResultCallback::Result* result_;
110 ValidateClientHelloResultCallback* done_cb_;
111
112 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper);
113 };
114
115 class VerifyNonceIsValidAndUniqueCallback
116 : public StrikeRegisterClient::ResultCallback {
117 public:
118 VerifyNonceIsValidAndUniqueCallback(
119 ValidateClientHelloResultCallback::Result* result,
120 std::unique_ptr<ProofSource::Details> proof_source_details,
121 ValidateClientHelloResultCallback* done_cb)
122 : result_(result),
123 proof_source_details_(std::move(proof_source_details)),
124 done_cb_(done_cb) {}
125
126 protected:
127 void RunImpl(bool nonce_is_valid_and_unique,
128 InsertStatus nonce_error) override {
129 DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique
130 << " nonce_error: " << nonce_error;
131 if (!nonce_is_valid_and_unique) {
132 HandshakeFailureReason client_nonce_error;
133 switch (nonce_error) {
134 case NONCE_INVALID_FAILURE:
135 client_nonce_error = CLIENT_NONCE_INVALID_FAILURE;
136 break;
137 case NONCE_NOT_UNIQUE_FAILURE:
138 client_nonce_error = CLIENT_NONCE_NOT_UNIQUE_FAILURE;
139 break;
140 case NONCE_INVALID_ORBIT_FAILURE:
141 client_nonce_error = CLIENT_NONCE_INVALID_ORBIT_FAILURE;
142 break;
143 case NONCE_INVALID_TIME_FAILURE:
144 client_nonce_error = CLIENT_NONCE_INVALID_TIME_FAILURE;
145 break;
146 case STRIKE_REGISTER_TIMEOUT:
147 client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT;
148 break;
149 case STRIKE_REGISTER_FAILURE:
150 client_nonce_error = CLIENT_NONCE_STRIKE_REGISTER_FAILURE;
151 break;
152 case NONCE_UNKNOWN_FAILURE:
153 client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
154 break;
155 case NONCE_OK:
156 default:
157 QUIC_BUG << "Unexpected client nonce error: " << nonce_error;
158 client_nonce_error = CLIENT_NONCE_UNKNOWN_FAILURE;
159 break;
160 }
161 result_->info.reject_reasons.push_back(client_nonce_error);
162 }
163 done_cb_->Run(result_, std::move(proof_source_details_));
164 }
165
166 private:
167 ValidateClientHelloResultCallback::Result* result_;
168 std::unique_ptr<ProofSource::Details> proof_source_details_;
169 ValidateClientHelloResultCallback* done_cb_;
170
171 DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback);
172 };
173
174 // static
175 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
176
177 ClientHelloInfo::ClientHelloInfo(const IPAddress& in_client_ip,
178 QuicWallTime in_now)
179 : client_ip(in_client_ip), now(in_now), valid_source_address_token(false) {}
180
181 ClientHelloInfo::~ClientHelloInfo() {}
182
183 PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {}
184
185 PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {}
186
187 ValidateClientHelloResultCallback::Result::Result(
188 const CryptoHandshakeMessage& in_client_hello,
189 IPAddress in_client_ip,
190 QuicWallTime in_now)
191 : client_hello(in_client_hello),
192 info(in_client_ip, in_now),
193 error_code(QUIC_NO_ERROR) {}
194
195 ValidateClientHelloResultCallback::Result::~Result() {}
196
197 ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {}
198
199 ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {}
200
201 void ValidateClientHelloResultCallback::Run(
202 const Result* result,
203 std::unique_ptr<ProofSource::Details> details) {
204 RunImpl(result->client_hello, *result, std::move(details));
205 delete result;
206 delete this;
207 }
208
209 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
210 : expiry_time(QuicWallTime::Zero()),
211 channel_id_enabled(false),
212 token_binding_enabled(false),
213 p256(false) {}
214
215 QuicCryptoServerConfig::ConfigOptions::ConfigOptions(
216 const ConfigOptions& other) = default;
217
218 QuicCryptoServerConfig::QuicCryptoServerConfig(
219 StringPiece source_address_token_secret,
220 QuicRandom* server_nonce_entropy,
221 std::unique_ptr<ProofSource> proof_source)
222 : replay_protection_(true),
223 chlo_multiplier_(kMultiplier),
224 configs_lock_(),
225 primary_config_(nullptr),
226 next_config_promotion_time_(QuicWallTime::Zero()),
227 server_nonce_strike_register_lock_(),
228 proof_source_(std::move(proof_source)),
229 strike_register_no_startup_period_(false),
230 strike_register_max_entries_(1 << 10),
231 strike_register_window_secs_(600),
232 source_address_token_future_secs_(3600),
233 source_address_token_lifetime_secs_(86400),
234 server_nonce_strike_register_max_entries_(1 << 10),
235 server_nonce_strike_register_window_secs_(120),
236 enable_serving_sct_(false) {
237 DCHECK(proof_source_.get());
238 default_source_address_token_boxer_.SetKeys(
239 {DeriveSourceAddressTokenKey(source_address_token_secret)});
240
241 // Generate a random key and orbit for server nonces.
242 server_nonce_entropy->RandBytes(server_nonce_orbit_,
243 sizeof(server_nonce_orbit_));
244 const size_t key_size = server_nonce_boxer_.GetKeySize();
245 std::unique_ptr<uint8_t[]> key_bytes(new uint8_t[key_size]);
246 server_nonce_entropy->RandBytes(key_bytes.get(), key_size);
247
248 server_nonce_boxer_.SetKeys(
249 {string(reinterpret_cast<char*>(key_bytes.get()), key_size)});
250 }
251
252 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
253 primary_config_ = nullptr;
254 }
255
256 // static
257 QuicServerConfigProtobuf* QuicCryptoServerConfig::GenerateConfig(
258 QuicRandom* rand,
259 const QuicClock* clock,
260 const ConfigOptions& options) {
261 CryptoHandshakeMessage msg;
262
263 const string curve25519_private_key =
264 Curve25519KeyExchange::NewPrivateKey(rand);
265 std::unique_ptr<Curve25519KeyExchange> curve25519(
266 Curve25519KeyExchange::New(curve25519_private_key));
267 StringPiece curve25519_public_value = curve25519->public_value();
268
269 string encoded_public_values;
270 // First three bytes encode the length of the public value.
271 DCHECK_LT(curve25519_public_value.size(), (1U << 24));
272 encoded_public_values.push_back(
273 static_cast<char>(curve25519_public_value.size()));
274 encoded_public_values.push_back(
275 static_cast<char>(curve25519_public_value.size() >> 8));
276 encoded_public_values.push_back(
277 static_cast<char>(curve25519_public_value.size() >> 16));
278 encoded_public_values.append(curve25519_public_value.data(),
279 curve25519_public_value.size());
280
281 string p256_private_key;
282 if (options.p256) {
283 p256_private_key = P256KeyExchange::NewPrivateKey();
284 std::unique_ptr<P256KeyExchange> p256(
285 P256KeyExchange::New(p256_private_key));
286 StringPiece p256_public_value = p256->public_value();
287
288 DCHECK_LT(p256_public_value.size(), (1U << 24));
289 encoded_public_values.push_back(
290 static_cast<char>(p256_public_value.size()));
291 encoded_public_values.push_back(
292 static_cast<char>(p256_public_value.size() >> 8));
293 encoded_public_values.push_back(
294 static_cast<char>(p256_public_value.size() >> 16));
295 encoded_public_values.append(p256_public_value.data(),
296 p256_public_value.size());
297 }
298
299 msg.set_tag(kSCFG);
300 if (options.p256) {
301 msg.SetVector(kKEXS, QuicTagVector{kC255, kP256});
302 } else {
303 msg.SetVector(kKEXS, QuicTagVector{kC255});
304 }
305 msg.SetVector(kAEAD, QuicTagVector{kAESG, kCC20});
306 msg.SetStringPiece(kPUBS, encoded_public_values);
307
308 if (options.expiry_time.IsZero()) {
309 const QuicWallTime now = clock->WallNow();
310 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
311 60 * 60 * 24 * 180 /* 180 days, ~six months */));
312 const uint64_t expiry_seconds = expiry.ToUNIXSeconds();
313 msg.SetValue(kEXPY, expiry_seconds);
314 } else {
315 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
316 }
317
318 char orbit_bytes[kOrbitSize];
319 if (options.orbit.size() == sizeof(orbit_bytes)) {
320 memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
321 } else {
322 DCHECK(options.orbit.empty());
323 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
324 }
325 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
326
327 if (options.channel_id_enabled) {
328 msg.SetVector(kPDMD, QuicTagVector{kCHID});
329 }
330
331 if (options.token_binding_enabled) {
332 msg.SetVector(kTBKP, QuicTagVector{kP256});
333 }
334
335 if (options.id.empty()) {
336 // We need to ensure that the SCID changes whenever the server config does
337 // thus we make it a hash of the rest of the server config.
338 std::unique_ptr<QuicData> serialized(
339 CryptoFramer::ConstructHandshakeMessage(msg));
340 std::unique_ptr<SecureHash> hash(SecureHash::Create(SecureHash::SHA256));
341 hash->Update(serialized->data(), serialized->length());
342
343 char scid_bytes[16];
344 hash->Finish(scid_bytes, sizeof(scid_bytes));
345 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
346 } else {
347 msg.SetStringPiece(kSCID, options.id);
348 }
349 // Don't put new tags below this point. The SCID generation should hash over
350 // everything but itself and so extra tags should be added prior to the
351 // preceeding if block.
352
353 std::unique_ptr<QuicData> serialized(
354 CryptoFramer::ConstructHandshakeMessage(msg));
355
356 std::unique_ptr<QuicServerConfigProtobuf> config(
357 new QuicServerConfigProtobuf);
358 config->set_config(serialized->AsStringPiece());
359 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
360 curve25519_key->set_tag(kC255);
361 curve25519_key->set_private_key(curve25519_private_key);
362
363 if (options.p256) {
364 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
365 p256_key->set_tag(kP256);
366 p256_key->set_private_key(p256_private_key);
367 }
368
369 return config.release();
370 }
371
372 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
373 QuicServerConfigProtobuf* protobuf,
374 const QuicWallTime now) {
375 std::unique_ptr<CryptoHandshakeMessage> msg(
376 CryptoFramer::ParseMessage(protobuf->config()));
377
378 if (!msg.get()) {
379 LOG(WARNING) << "Failed to parse server config message";
380 return nullptr;
381 }
382
383 scoped_refptr<Config> config(ParseConfigProtobuf(protobuf));
384 if (!config.get()) {
385 LOG(WARNING) << "Failed to parse server config message";
386 return nullptr;
387 }
388
389 {
390 base::AutoLock locked(configs_lock_);
391 if (configs_.find(config->id) != configs_.end()) {
392 LOG(WARNING) << "Failed to add config because another with the same "
393 "server config id already exists: "
394 << QuicUtils::HexEncode(config->id);
395 return nullptr;
396 }
397
398 configs_[config->id] = config;
399 SelectNewPrimaryConfig(now);
400 DCHECK(primary_config_.get());
401 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
402 }
403
404 return msg.release();
405 }
406
407 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
408 QuicRandom* rand,
409 const QuicClock* clock,
410 const ConfigOptions& options) {
411 std::unique_ptr<QuicServerConfigProtobuf> config(
412 GenerateConfig(rand, clock, options));
413 return AddConfig(config.get(), clock->WallNow());
414 }
415
416 bool QuicCryptoServerConfig::SetConfigs(
417 const vector<QuicServerConfigProtobuf*>& protobufs,
418 const QuicWallTime now) {
419 vector<scoped_refptr<Config>> parsed_configs;
420 bool ok = true;
421
422 for (vector<QuicServerConfigProtobuf*>::const_iterator i = protobufs.begin();
423 i != protobufs.end(); ++i) {
424 scoped_refptr<Config> config(ParseConfigProtobuf(*i));
425 if (!config.get()) {
426 ok = false;
427 break;
428 }
429
430 parsed_configs.push_back(config);
431 }
432
433 if (parsed_configs.empty()) {
434 LOG(WARNING) << "New config list is empty.";
435 ok = false;
436 }
437
438 if (!ok) {
439 LOG(WARNING) << "Rejecting QUIC configs because of above errors";
440 } else {
441 VLOG(1) << "Updating configs:";
442
443 base::AutoLock locked(configs_lock_);
444 ConfigMap new_configs;
445
446 for (vector<scoped_refptr<Config>>::const_iterator i =
447 parsed_configs.begin();
448 i != parsed_configs.end(); ++i) {
449 scoped_refptr<Config> config = *i;
450
451 ConfigMap::iterator it = configs_.find(config->id);
452 if (it != configs_.end()) {
453 VLOG(1) << "Keeping scid: " << QuicUtils::HexEncode(config->id)
454 << " orbit: "
455 << QuicUtils::HexEncode(
456 reinterpret_cast<const char*>(config->orbit), kOrbitSize)
457 << " new primary_time " << config->primary_time.ToUNIXSeconds()
458 << " old primary_time "
459 << it->second->primary_time.ToUNIXSeconds() << " new priority "
460 << config->priority << " old priority " << it->second->priority;
461 // Update primary_time and priority.
462 it->second->primary_time = config->primary_time;
463 it->second->priority = config->priority;
464 new_configs.insert(*it);
465 } else {
466 VLOG(1) << "Adding scid: " << QuicUtils::HexEncode(config->id)
467 << " orbit: "
468 << QuicUtils::HexEncode(
469 reinterpret_cast<const char*>(config->orbit), kOrbitSize)
470 << " primary_time " << config->primary_time.ToUNIXSeconds()
471 << " priority " << config->priority;
472 new_configs.insert(std::make_pair(config->id, config));
473 }
474 }
475
476 configs_.swap(new_configs);
477 SelectNewPrimaryConfig(now);
478 DCHECK(primary_config_.get());
479 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
480 }
481
482 return ok;
483 }
484
485 void QuicCryptoServerConfig::SetDefaultSourceAddressTokenKeys(
486 const vector<string>& keys) {
487 default_source_address_token_boxer_.SetKeys(keys);
488 }
489
490 void QuicCryptoServerConfig::GetConfigIds(vector<string>* scids) const {
491 base::AutoLock locked(configs_lock_);
492 for (ConfigMap::const_iterator it = configs_.begin(); it != configs_.end();
493 ++it) {
494 scids->push_back(it->first);
495 }
496 }
497
498 void QuicCryptoServerConfig::ValidateClientHello(
499 const CryptoHandshakeMessage& client_hello,
500 const IPAddress& client_ip,
501 const IPAddress& server_ip,
502 QuicVersion version,
503 const QuicClock* clock,
504 QuicCryptoProof* crypto_proof,
505 ValidateClientHelloResultCallback* done_cb) const {
506 const QuicWallTime now(clock->WallNow());
507
508 ValidateClientHelloResultCallback::Result* result =
509 new ValidateClientHelloResultCallback::Result(client_hello, client_ip,
510 now);
511
512 StringPiece requested_scid;
513 client_hello.GetStringPiece(kSCID, &requested_scid);
514
515 uint8_t primary_orbit[kOrbitSize];
516 scoped_refptr<Config> requested_config;
517 scoped_refptr<Config> primary_config;
518 {
519 base::AutoLock locked(configs_lock_);
520
521 if (!primary_config_.get()) {
522 result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
523 result->error_details = "No configurations loaded";
524 } else {
525 if (!next_config_promotion_time_.IsZero() &&
526 next_config_promotion_time_.IsAfter(now)) {
527 SelectNewPrimaryConfig(now);
528 DCHECK(primary_config_.get());
529 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
530 }
531
532 memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit));
533 }
534
535 requested_config = GetConfigWithScid(requested_scid);
536 primary_config = primary_config_;
537 crypto_proof->config = primary_config_;
538 }
539
540 if (result->error_code == QUIC_NO_ERROR) {
541 if (FLAGS_quic_refresh_proof && version > QUIC_VERSION_30) {
542 // QUIC v31 and above require a new proof for each CHLO so clear the
543 // existing proof, if any.
544 crypto_proof->chain = nullptr;
545 crypto_proof->signature = "";
546 crypto_proof->cert_sct = "";
547 }
548 EvaluateClientHello(server_ip, version, primary_orbit, requested_config,
549 primary_config, crypto_proof, result, done_cb);
550 } else {
551 done_cb->Run(result, nullptr /* proof_source_details */);
552 }
553 }
554
555 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
556 const ValidateClientHelloResultCallback::Result& validate_chlo_result,
557 bool reject_only,
558 QuicConnectionId connection_id,
559 const IPAddress& server_ip,
560 const IPEndPoint& client_address,
561 QuicVersion version,
562 const QuicVersionVector& supported_versions,
563 bool use_stateless_rejects,
564 QuicConnectionId server_designated_connection_id,
565 const QuicClock* clock,
566 QuicRandom* rand,
567 QuicCompressedCertsCache* compressed_certs_cache,
568 QuicCryptoNegotiatedParameters* params,
569 QuicCryptoProof* crypto_proof,
570 CryptoHandshakeMessage* out,
571 DiversificationNonce* out_diversification_nonce,
572 string* error_details) const {
573 DCHECK(error_details);
574
575 const CryptoHandshakeMessage& client_hello =
576 validate_chlo_result.client_hello;
577 const ClientHelloInfo& info = validate_chlo_result.info;
578
579 QuicErrorCode valid = CryptoUtils::ValidateClientHello(
580 client_hello, version, supported_versions, error_details);
581 if (valid != QUIC_NO_ERROR)
582 return valid;
583
584 StringPiece requested_scid;
585 client_hello.GetStringPiece(kSCID, &requested_scid);
586 const QuicWallTime now(clock->WallNow());
587
588 scoped_refptr<Config> requested_config;
589 scoped_refptr<Config> primary_config;
590 {
591 base::AutoLock locked(configs_lock_);
592
593 if (!primary_config_.get()) {
594 *error_details = "No configurations loaded";
595 return QUIC_CRYPTO_INTERNAL_ERROR;
596 }
597
598 if (!next_config_promotion_time_.IsZero() &&
599 next_config_promotion_time_.IsAfter(now)) {
600 SelectNewPrimaryConfig(now);
601 DCHECK(primary_config_.get());
602 DCHECK_EQ(configs_.find(primary_config_->id)->second, primary_config_);
603 }
604
605 // Use the config that the client requested in order to do key-agreement.
606 // Otherwise give it a copy of |primary_config_| to use.
607 primary_config = crypto_proof->config;
608 requested_config = GetConfigWithScid(requested_scid);
609 }
610
611 if (validate_chlo_result.error_code != QUIC_NO_ERROR) {
612 *error_details = validate_chlo_result.error_details;
613 return validate_chlo_result.error_code;
614 }
615
616 out->Clear();
617
618 bool x509_supported = false;
619 bool x509_ecdsa_supported = false;
620 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported);
621 if (!x509_supported && FLAGS_quic_require_x509) {
622 *error_details = "Missing or invalid PDMD";
623 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
624 }
625 DCHECK(proof_source_.get());
626 string chlo_hash;
627 CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash);
628 // No need to get a new proof if one was already generated.
629 if (!crypto_proof->chain &&
630 !proof_source_->GetProof(
631 server_ip, info.sni.as_string(), primary_config->serialized, version,
632 chlo_hash, x509_ecdsa_supported, &crypto_proof->chain,
633 &crypto_proof->signature, &crypto_proof->cert_sct)) {
634 return QUIC_HANDSHAKE_FAILED;
635 }
636
637 StringPiece cert_sct;
638 if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) &&
639 cert_sct.empty()) {
640 params->sct_supported_by_client = true;
641 }
642
643 if (!info.reject_reasons.empty() || !requested_config.get()) {
644 BuildRejection(version, *primary_config, client_hello, info,
645 validate_chlo_result.cached_network_params,
646 use_stateless_rejects, server_designated_connection_id, rand,
647 compressed_certs_cache, params, *crypto_proof, out);
648 return QUIC_NO_ERROR;
649 }
650
651 if (reject_only) {
652 return QUIC_NO_ERROR;
653 }
654
655 const QuicTag* their_aeads;
656 const QuicTag* their_key_exchanges;
657 size_t num_their_aeads, num_their_key_exchanges;
658 if (client_hello.GetTaglist(kAEAD, &their_aeads, &num_their_aeads) !=
659 QUIC_NO_ERROR ||
660 client_hello.GetTaglist(kKEXS, &their_key_exchanges,
661 &num_their_key_exchanges) != QUIC_NO_ERROR ||
662 num_their_aeads != 1 || num_their_key_exchanges != 1) {
663 *error_details = "Missing or invalid AEAD or KEXS";
664 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
665 }
666
667 size_t key_exchange_index;
668 if (!QuicUtils::FindMutualTag(requested_config->aead, their_aeads,
669 num_their_aeads, QuicUtils::LOCAL_PRIORITY,
670 &params->aead, nullptr) ||
671 !QuicUtils::FindMutualTag(requested_config->kexs, their_key_exchanges,
672 num_their_key_exchanges,
673 QuicUtils::LOCAL_PRIORITY,
674 &params->key_exchange, &key_exchange_index)) {
675 *error_details = "Unsupported AEAD or KEXS";
676 return QUIC_CRYPTO_NO_SUPPORT;
677 }
678
679 if (!requested_config->tb_key_params.empty()) {
680 const QuicTag* their_tbkps;
681 size_t num_their_tbkps;
682 switch (client_hello.GetTaglist(kTBKP, &their_tbkps, &num_their_tbkps)) {
683 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
684 break;
685 case QUIC_NO_ERROR:
686 if (QuicUtils::FindMutualTag(
687 requested_config->tb_key_params, their_tbkps, num_their_tbkps,
688 QuicUtils::LOCAL_PRIORITY, &params->token_binding_key_param,
689 nullptr)) {
690 break;
691 }
692 default:
693 *error_details = "Invalid Token Binding key parameter";
694 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
695 }
696 }
697
698 StringPiece public_value;
699 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
700 *error_details = "Missing public value";
701 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
702 }
703
704 const KeyExchange* key_exchange =
705 requested_config->key_exchanges[key_exchange_index];
706 if (!key_exchange->CalculateSharedKey(public_value,
707 &params->initial_premaster_secret)) {
708 *error_details = "Invalid public value";
709 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
710 }
711
712 if (!info.sni.empty()) {
713 std::unique_ptr<char[]> sni_tmp(new char[info.sni.length() + 1]);
714 memcpy(sni_tmp.get(), info.sni.data(), info.sni.length());
715 sni_tmp[info.sni.length()] = 0;
716 params->sni = CryptoUtils::NormalizeHostname(sni_tmp.get());
717 }
718
719 string hkdf_suffix;
720 const QuicData& client_hello_serialized = client_hello.GetSerialized();
721 hkdf_suffix.reserve(sizeof(connection_id) + client_hello_serialized.length() +
722 requested_config->serialized.size());
723 hkdf_suffix.append(reinterpret_cast<char*>(&connection_id),
724 sizeof(connection_id));
725 hkdf_suffix.append(client_hello_serialized.data(),
726 client_hello_serialized.length());
727 hkdf_suffix.append(requested_config->serialized);
728 DCHECK(proof_source_.get());
729 if (crypto_proof->chain->certs.empty()) {
730 *error_details = "Failed to get certs";
731 return QUIC_CRYPTO_INTERNAL_ERROR;
732 }
733 hkdf_suffix.append(crypto_proof->chain->certs.at(0));
734
735 StringPiece cetv_ciphertext;
736 if (requested_config->channel_id_enabled &&
737 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
738 CryptoHandshakeMessage client_hello_copy(client_hello);
739 client_hello_copy.Erase(kCETV);
740 client_hello_copy.Erase(kPAD);
741
742 const QuicData& client_hello_copy_serialized =
743 client_hello_copy.GetSerialized();
744 string hkdf_input;
745 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
746 strlen(QuicCryptoConfig::kCETVLabel) + 1);
747 hkdf_input.append(reinterpret_cast<char*>(&connection_id),
748 sizeof(connection_id));
749 hkdf_input.append(client_hello_copy_serialized.data(),
750 client_hello_copy_serialized.length());
751 hkdf_input.append(requested_config->serialized);
752
753 CrypterPair crypters;
754 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
755 info.client_nonce, info.server_nonce,
756 hkdf_input, Perspective::IS_SERVER,
757 CryptoUtils::Diversification::Never(),
758 &crypters, nullptr /* subkey secret */)) {
759 *error_details = "Symmetric key setup failed";
760 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
761 }
762
763 char plaintext[kMaxPacketSize];
764 size_t plaintext_length = 0;
765 const bool success = crypters.decrypter->DecryptPacket(
766 kDefaultPathId, 0 /* packet number */,
767 StringPiece() /* associated data */, cetv_ciphertext, plaintext,
768 &plaintext_length, kMaxPacketSize);
769 if (!success) {
770 *error_details = "CETV decryption failure";
771 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
772 }
773 std::unique_ptr<CryptoHandshakeMessage> cetv(
774 CryptoFramer::ParseMessage(StringPiece(plaintext, plaintext_length)));
775 if (!cetv.get()) {
776 *error_details = "CETV parse error";
777 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
778 }
779
780 StringPiece key, signature;
781 if (cetv->GetStringPiece(kCIDK, &key) &&
782 cetv->GetStringPiece(kCIDS, &signature)) {
783 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
784 *error_details = "ChannelID signature failure";
785 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
786 }
787
788 params->channel_id = key.as_string();
789 }
790 }
791
792 string hkdf_input;
793 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
794 hkdf_input.reserve(label_len + hkdf_suffix.size());
795 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
796 hkdf_input.append(hkdf_suffix);
797
798 string* subkey_secret = &params->initial_subkey_secret;
799 CryptoUtils::Diversification diversification =
800 CryptoUtils::Diversification::Never();
801 if (version > QUIC_VERSION_32) {
802 rand->RandBytes(reinterpret_cast<char*>(out_diversification_nonce),
803 sizeof(*out_diversification_nonce));
804 diversification =
805 CryptoUtils::Diversification::Now(out_diversification_nonce);
806 }
807
808 if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
809 info.client_nonce, info.server_nonce, hkdf_input,
810 Perspective::IS_SERVER, diversification,
811 &params->initial_crypters, subkey_secret)) {
812 *error_details = "Symmetric key setup failed";
813 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
814 }
815
816 string forward_secure_public_value;
817 if (ephemeral_key_source_.get()) {
818 params->forward_secure_premaster_secret =
819 ephemeral_key_source_->CalculateForwardSecureKey(
820 key_exchange, rand, clock->ApproximateNow(), public_value,
821 &forward_secure_public_value);
822 } else {
823 std::unique_ptr<KeyExchange> forward_secure_key_exchange(
824 key_exchange->NewKeyPair(rand));
825 forward_secure_public_value =
826 forward_secure_key_exchange->public_value().as_string();
827 if (!forward_secure_key_exchange->CalculateSharedKey(
828 public_value, &params->forward_secure_premaster_secret)) {
829 *error_details = "Invalid public value";
830 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
831 }
832 }
833
834 string forward_secure_hkdf_input;
835 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
836 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
837 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
838 label_len);
839 forward_secure_hkdf_input.append(hkdf_suffix);
840
841 string shlo_nonce;
842 shlo_nonce = NewServerNonce(rand, info.now);
843 out->SetStringPiece(kServerNonceTag, shlo_nonce);
844
845 if (!CryptoUtils::DeriveKeys(
846 params->forward_secure_premaster_secret, params->aead,
847 info.client_nonce,
848 shlo_nonce.empty() ? info.server_nonce : shlo_nonce,
849 forward_secure_hkdf_input, Perspective::IS_SERVER,
850 CryptoUtils::Diversification::Never(),
851 &params->forward_secure_crypters, &params->subkey_secret)) {
852 *error_details = "Symmetric key setup failed";
853 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
854 }
855
856 out->set_tag(kSHLO);
857 QuicTagVector supported_version_tags;
858 for (size_t i = 0; i < supported_versions.size(); ++i) {
859 supported_version_tags.push_back(
860 QuicVersionToQuicTag(supported_versions[i]));
861 }
862 out->SetVector(kVER, supported_version_tags);
863 out->SetStringPiece(
864 kSourceAddressTokenTag,
865 NewSourceAddressToken(*requested_config.get(), info.source_address_tokens,
866 client_address.address(), rand, info.now, nullptr));
867 QuicSocketAddressCoder address_coder(client_address);
868 out->SetStringPiece(kCADR, address_coder.Encode());
869 out->SetStringPiece(kPUBS, forward_secure_public_value);
870
871 return QUIC_NO_ERROR;
872 }
873
874 scoped_refptr<QuicCryptoServerConfig::Config>
875 QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid) const {
876 // In Chromium, we will dead lock if the lock is held by the current thread.
877 // Chromium doesn't have AssertReaderHeld API call.
878 // configs_lock_.AssertReaderHeld();
879
880 if (!requested_scid.empty()) {
881 ConfigMap::const_iterator it = configs_.find(requested_scid.as_string());
882 if (it != configs_.end()) {
883 // We'll use the config that the client requested in order to do
884 // key-agreement.
885 return scoped_refptr<Config>(it->second);
886 }
887 }
888
889 return scoped_refptr<Config>();
890 }
891
892 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
893 // Config's based on their primary_time.
894 // static
895 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
896 const scoped_refptr<Config>& a,
897 const scoped_refptr<Config>& b) {
898 if (a->primary_time.IsBefore(b->primary_time) ||
899 b->primary_time.IsBefore(a->primary_time)) {
900 // Primary times differ.
901 return a->primary_time.IsBefore(b->primary_time);
902 } else if (a->priority != b->priority) {
903 // Primary times are equal, sort backwards by priority.
904 return a->priority < b->priority;
905 } else {
906 // Primary times and priorities are equal, sort by config id.
907 return a->id < b->id;
908 }
909 }
910
911 void QuicCryptoServerConfig::SelectNewPrimaryConfig(
912 const QuicWallTime now) const {
913 vector<scoped_refptr<Config>> configs;
914 configs.reserve(configs_.size());
915
916 for (ConfigMap::const_iterator it = configs_.begin(); it != configs_.end();
917 ++it) {
918 // TODO(avd) Exclude expired configs?
919 configs.push_back(it->second);
920 }
921
922 if (configs.empty()) {
923 if (primary_config_.get()) {
924 QUIC_BUG << "No valid QUIC server config. Keeping the current config.";
925 } else {
926 QUIC_BUG << "No valid QUIC server config.";
927 }
928 return;
929 }
930
931 std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);
932
933 Config* best_candidate = configs[0].get();
934
935 for (size_t i = 0; i < configs.size(); ++i) {
936 const scoped_refptr<Config> config(configs[i]);
937 if (!config->primary_time.IsAfter(now)) {
938 if (config->primary_time.IsAfter(best_candidate->primary_time)) {
939 best_candidate = config.get();
940 }
941 continue;
942 }
943
944 // This is the first config with a primary_time in the future. Thus the
945 // previous Config should be the primary and this one should determine the
946 // next_config_promotion_time_.
947 scoped_refptr<Config> new_primary(best_candidate);
948 if (i == 0) {
949 // We need the primary_time of the next config.
950 if (configs.size() > 1) {
951 next_config_promotion_time_ = configs[1]->primary_time;
952 } else {
953 next_config_promotion_time_ = QuicWallTime::Zero();
954 }
955 } else {
956 next_config_promotion_time_ = config->primary_time;
957 }
958
959 if (primary_config_.get()) {
960 primary_config_->is_primary = false;
961 }
962 primary_config_ = new_primary;
963 new_primary->is_primary = true;
964 DVLOG(1) << "New primary config. orbit: "
965 << QuicUtils::HexEncode(
966 reinterpret_cast<const char*>(primary_config_->orbit),
967 kOrbitSize);
968 if (primary_config_changed_cb_.get() != nullptr) {
969 primary_config_changed_cb_->Run(primary_config_->id);
970 }
971
972 return;
973 }
974
975 // All config's primary times are in the past. We should make the most recent
976 // and highest priority candidate primary.
977 scoped_refptr<Config> new_primary(best_candidate);
978 if (primary_config_.get()) {
979 primary_config_->is_primary = false;
980 }
981 primary_config_ = new_primary;
982 new_primary->is_primary = true;
983 DVLOG(1) << "New primary config. orbit: "
984 << QuicUtils::HexEncode(
985 reinterpret_cast<const char*>(primary_config_->orbit),
986 kOrbitSize)
987 << " scid: " << QuicUtils::HexEncode(primary_config_->id);
988 next_config_promotion_time_ = QuicWallTime::Zero();
989 if (primary_config_changed_cb_.get() != nullptr) {
990 primary_config_changed_cb_->Run(primary_config_->id);
991 }
992 }
993
994 class EvaluateClientHelloCallback : public ProofSource::Callback {
995 public:
996 EvaluateClientHelloCallback(
997 const QuicCryptoServerConfig& config,
998 bool found_error,
999 const IPAddress& server_ip,
1000 QuicVersion version,
1001 const uint8_t* primary_orbit,
1002 scoped_refptr<QuicCryptoServerConfig::Config> requested_config,
1003 scoped_refptr<QuicCryptoServerConfig::Config> primary_config,
1004 QuicCryptoProof* crypto_proof,
1005 ValidateClientHelloResultCallback::Result* client_hello_state,
1006 ValidateClientHelloResultCallback* done_cb)
1007 : config_(config),
1008 found_error_(found_error),
1009 server_ip_(server_ip),
1010 version_(version),
1011 primary_orbit_(primary_orbit),
1012 requested_config_(std::move(requested_config)),
1013 primary_config_(std::move(primary_config)),
1014 crypto_proof_(crypto_proof),
1015 client_hello_state_(client_hello_state),
1016 done_cb_(done_cb) {}
1017
1018 void Run(bool ok,
1019 const scoped_refptr<ProofSource::Chain>& chain,
1020 const string& signature,
1021 const string& leaf_cert_sct,
1022 std::unique_ptr<ProofSource::Details> details) override {
1023 if (ok) {
1024 crypto_proof_->chain = chain;
1025 crypto_proof_->signature = signature;
1026 crypto_proof_->cert_sct = leaf_cert_sct;
1027 }
1028 config_.EvaluateClientHelloAfterGetProof(
1029 found_error_, server_ip_, version_, primary_orbit_, requested_config_,
1030 primary_config_, crypto_proof_, std::move(details), !ok,
1031 client_hello_state_, done_cb_);
1032 }
1033
1034 private:
1035 const QuicCryptoServerConfig& config_;
1036 const bool found_error_;
1037 const IPAddress& server_ip_;
1038 const QuicVersion version_;
1039 const uint8_t* primary_orbit_;
1040 const scoped_refptr<QuicCryptoServerConfig::Config> requested_config_;
1041 const scoped_refptr<QuicCryptoServerConfig::Config> primary_config_;
1042 QuicCryptoProof* crypto_proof_;
1043 ValidateClientHelloResultCallback::Result* client_hello_state_;
1044 ValidateClientHelloResultCallback* done_cb_;
1045 };
1046
1047 void QuicCryptoServerConfig::EvaluateClientHello(
1048 const IPAddress& server_ip,
1049 QuicVersion version,
1050 const uint8_t* primary_orbit,
1051 scoped_refptr<Config> requested_config,
1052 scoped_refptr<Config> primary_config,
1053 QuicCryptoProof* crypto_proof,
1054 ValidateClientHelloResultCallback::Result* client_hello_state,
1055 ValidateClientHelloResultCallback* done_cb) const {
1056 ValidateClientHelloHelper helper(client_hello_state, done_cb);
1057
1058 const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
1059 ClientHelloInfo* info = &(client_hello_state->info);
1060
1061 if (client_hello.size() < kClientHelloMinimumSize) {
1062 helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
1063 "Client hello too small", nullptr);
1064 return;
1065 }
1066
1067 if (client_hello.GetStringPiece(kSNI, &info->sni) &&
1068 !CryptoUtils::IsValidSNI(info->sni)) {
1069 helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
1070 "Invalid SNI name", nullptr);
1071 return;
1072 }
1073
1074 client_hello.GetStringPiece(kUAID, &info->user_agent_id);
1075
1076 HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON;
1077 StringPiece srct;
1078 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
1079 Config& config = requested_config ? *requested_config : *primary_config;
1080 source_address_token_error =
1081 ParseSourceAddressToken(config, srct, &info->source_address_tokens);
1082
1083 if (source_address_token_error == HANDSHAKE_OK) {
1084 source_address_token_error = ValidateSourceAddressTokens(
1085 info->source_address_tokens, info->client_ip, info->now,
1086 &client_hello_state->cached_network_params);
1087 }
1088 info->valid_source_address_token =
1089 (source_address_token_error == HANDSHAKE_OK);
1090 } else {
1091 source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
1092 }
1093
1094 if (!requested_config.get()) {
1095 StringPiece requested_scid;
1096 if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
1097 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
1098 } else {
1099 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
1100 }
1101 // No server config with the requested ID.
1102 helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
1103 return;
1104 }
1105
1106 if (!client_hello.GetStringPiece(kNONC, &info->client_nonce)) {
1107 info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
1108 // Report no client nonce as INCHOATE_HELLO_FAILURE.
1109 helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
1110 return;
1111 }
1112
1113 bool found_error = false;
1114 if (source_address_token_error != HANDSHAKE_OK) {
1115 info->reject_reasons.push_back(source_address_token_error);
1116 // No valid source address token.
1117 found_error = true;
1118 }
1119
1120 bool get_proof_failed = false;
1121 bool x509_supported = false;
1122 bool x509_ecdsa_supported = false;
1123 ParseProofDemand(client_hello, &x509_supported, &x509_ecdsa_supported);
1124 string serialized_config = primary_config->serialized;
1125 string chlo_hash;
1126 CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash);
1127 bool need_proof = true;
1128 if (FLAGS_quic_refresh_proof) {
1129 need_proof = !crypto_proof->chain;
1130 }
1131 if (FLAGS_enable_async_get_proof) {
1132 if (need_proof) {
1133 // Make an async call to GetProof and setup the callback to trampoline
1134 // back into EvaluateClientHelloAfterGetProof
1135 std::unique_ptr<EvaluateClientHelloCallback> cb(
1136 new EvaluateClientHelloCallback(
1137 *this, found_error, server_ip, version, primary_orbit,
1138 requested_config, primary_config, crypto_proof,
1139 client_hello_state, done_cb));
1140 proof_source_->GetProof(server_ip, info->sni.as_string(),
1141 serialized_config, version, chlo_hash,
1142 x509_ecdsa_supported, std::move(cb));
1143 helper.DetachCallback();
1144 return;
1145 }
1146 }
1147
1148 // No need to get a new proof if one was already generated.
1149 if (need_proof &&
1150 !proof_source_->GetProof(
1151 server_ip, info->sni.as_string(), serialized_config, version,
1152 chlo_hash, x509_ecdsa_supported, &crypto_proof->chain,
1153 &crypto_proof->signature, &crypto_proof->cert_sct)) {
1154 get_proof_failed = true;
1155 }
1156
1157 // Details are null because the synchronous version of GetProof does not
1158 // return any stats. Eventually the synchronous codepath will be eliminated.
1159 EvaluateClientHelloAfterGetProof(
1160 found_error, server_ip, version, primary_orbit, requested_config,
1161 primary_config, crypto_proof, nullptr /* proof_source_details */,
1162 get_proof_failed, client_hello_state, done_cb);
1163 helper.DetachCallback();
1164 }
1165
1166 void QuicCryptoServerConfig::EvaluateClientHelloAfterGetProof(
1167 bool found_error,
1168 const IPAddress& server_ip,
1169 QuicVersion version,
1170 const uint8_t* primary_orbit,
1171 scoped_refptr<Config> requested_config,
1172 scoped_refptr<Config> primary_config,
1173 QuicCryptoProof* crypto_proof,
1174 std::unique_ptr<ProofSource::Details> proof_source_details,
1175 bool get_proof_failed,
1176 ValidateClientHelloResultCallback::Result* client_hello_state,
1177 ValidateClientHelloResultCallback* done_cb) const {
1178 ValidateClientHelloHelper helper(client_hello_state, done_cb);
1179 const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
1180 ClientHelloInfo* info = &(client_hello_state->info);
1181
1182 if (get_proof_failed) {
1183 found_error = true;
1184 info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
1185 }
1186
1187 if (!ValidateExpectedLeafCertificate(client_hello, *crypto_proof)) {
1188 found_error = true;
1189 info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
1190 }
1191
1192 if (info->client_nonce.size() != kNonceSize) {
1193 info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
1194 // Invalid client nonce.
1195 LOG(ERROR) << "Invalid client nonce: " << client_hello.DebugString();
1196 DVLOG(1) << "Invalid client nonce.";
1197 found_error = true;
1198 }
1199
1200 // Server nonce is optional, and used for key derivation if present.
1201 client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
1202
1203 if (version > QUIC_VERSION_32) {
1204 DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_33 and higher.";
1205 // If the server nonce is empty and we're requiring handshake confirmation
1206 // for DoS reasons then we must reject the CHLO.
1207 if (FLAGS_quic_require_handshake_confirmation &&
1208 info->server_nonce.empty()) {
1209 info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
1210 }
1211 helper.ValidationComplete(QUIC_NO_ERROR, "",
1212 std::move(proof_source_details));
1213 return;
1214 }
1215
1216 if (!replay_protection_) {
1217 DVLOG(1) << "No replay protection.";
1218 helper.ValidationComplete(QUIC_NO_ERROR, "",
1219 std::move(proof_source_details));
1220 return;
1221 }
1222
1223 if (!info->server_nonce.empty()) {
1224 // If the server nonce is present, use it to establish uniqueness.
1225 HandshakeFailureReason server_nonce_error =
1226 ValidateServerNonce(info->server_nonce, info->now);
1227 bool is_unique = server_nonce_error == HANDSHAKE_OK;
1228 if (!is_unique) {
1229 info->reject_reasons.push_back(server_nonce_error);
1230 }
1231 DVLOG(1) << "Using server nonce, unique: " << is_unique;
1232 helper.ValidationComplete(QUIC_NO_ERROR, "",
1233 std::move(proof_source_details));
1234 return;
1235 }
1236 // If we hit this block, the server nonce was empty. If we're requiring
1237 // handshake confirmation for DoS reasons and there's no server nonce present,
1238 // reject the CHLO.
1239 if (FLAGS_quic_require_handshake_confirmation ||
1240 FLAGS_quic_require_handshake_confirmation_pre33) {
1241 info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
1242 helper.ValidationComplete(QUIC_NO_ERROR, "",
1243 std::move(proof_source_details));
1244 return;
1245 }
1246
1247 // We want to contact strike register only if there are no errors because it
1248 // is a RPC call and is expensive.
1249 if (found_error) {
1250 helper.ValidationComplete(QUIC_NO_ERROR, "",
1251 std::move(proof_source_details));
1252 return;
1253 }
1254
1255 // Use the client nonce to establish uniqueness.
1256 StrikeRegisterClient* strike_register_client;
1257 {
1258 base::AutoLock locked(strike_register_client_lock_);
1259 strike_register_client = strike_register_client_.get();
1260 }
1261
1262 if (!strike_register_client) {
1263 // Either a valid server nonces or a strike register is required.
1264 // Since neither are present, reject the handshake which will send a
1265 // server nonce to the client.
1266 info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
1267 helper.ValidationComplete(QUIC_NO_ERROR, "",
1268 std::move(proof_source_details));
1269 return;
1270 }
1271
1272 strike_register_client->VerifyNonceIsValidAndUnique(
1273 info->client_nonce, info->now,
1274 new VerifyNonceIsValidAndUniqueCallback(
1275 client_hello_state, std::move(proof_source_details), done_cb));
1276 helper.DetachCallback();
1277 }
1278
1279 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1280 QuicVersion version,
1281 StringPiece chlo_hash,
1282 const SourceAddressTokens& previous_source_address_tokens,
1283 const IPAddress& server_ip,
1284 const IPAddress& client_ip,
1285 const QuicClock* clock,
1286 QuicRandom* rand,
1287 QuicCompressedCertsCache* compressed_certs_cache,
1288 const QuicCryptoNegotiatedParameters& params,
1289 const CachedNetworkParameters* cached_network_params,
1290 CryptoHandshakeMessage* out) const {
1291 string serialized;
1292 string source_address_token;
1293 const CommonCertSets* common_cert_sets;
1294 {
1295 base::AutoLock locked(configs_lock_);
1296 serialized = primary_config_->serialized;
1297 common_cert_sets = primary_config_->common_cert_sets;
1298 source_address_token = NewSourceAddressToken(
1299 *primary_config_, previous_source_address_tokens, client_ip, rand,
1300 clock->WallNow(), cached_network_params);
1301 }
1302
1303 out->set_tag(kSCUP);
1304 out->SetStringPiece(kSCFG, serialized);
1305 out->SetStringPiece(kSourceAddressTokenTag, source_address_token);
1306
1307 scoped_refptr<ProofSource::Chain> chain;
1308 string signature;
1309 string cert_sct;
1310 if (!proof_source_->GetProof(server_ip, params.sni, serialized, version,
1311 chlo_hash, params.x509_ecdsa_supported, &chain,
1312 &signature, &cert_sct)) {
1313 DVLOG(1) << "Server: failed to get proof.";
1314 return false;
1315 }
1316
1317 const string compressed = CompressChain(
1318 compressed_certs_cache, chain, params.client_common_set_hashes,
1319 params.client_cached_cert_hashes, common_cert_sets);
1320
1321 out->SetStringPiece(kCertificateTag, compressed);
1322 out->SetStringPiece(kPROF, signature);
1323 if (params.sct_supported_by_client && enable_serving_sct_) {
1324 if (cert_sct.empty()) {
1325 DLOG(WARNING) << "SCT is expected but it is empty.";
1326 } else {
1327 out->SetStringPiece(kCertificateSCTTag, cert_sct);
1328 }
1329 }
1330 return true;
1331 }
1332
1333 void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1334 QuicVersion version,
1335 StringPiece chlo_hash,
1336 const SourceAddressTokens& previous_source_address_tokens,
1337 const IPAddress& server_ip,
1338 const IPAddress& client_ip,
1339 const QuicClock* clock,
1340 QuicRandom* rand,
1341 QuicCompressedCertsCache* compressed_certs_cache,
1342 const QuicCryptoNegotiatedParameters& params,
1343 const CachedNetworkParameters* cached_network_params,
1344 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
1345 string serialized;
1346 string source_address_token;
1347 const CommonCertSets* common_cert_sets;
1348 {
1349 base::AutoLock locked(configs_lock_);
1350 serialized = primary_config_->serialized;
1351 common_cert_sets = primary_config_->common_cert_sets;
1352 source_address_token = NewSourceAddressToken(
1353 *primary_config_, previous_source_address_tokens, client_ip, rand,
1354 clock->WallNow(), cached_network_params);
1355 }
1356
1357 CryptoHandshakeMessage message;
1358 message.set_tag(kSCUP);
1359 message.SetStringPiece(kSCFG, serialized);
1360 message.SetStringPiece(kSourceAddressTokenTag, source_address_token);
1361
1362 std::unique_ptr<BuildServerConfigUpdateMessageProofSourceCallback>
1363 proof_source_cb(new BuildServerConfigUpdateMessageProofSourceCallback(
1364 this, version, compressed_certs_cache, common_cert_sets, params,
1365 std::move(message), std::move(cb)));
1366
1367 proof_source_->GetProof(server_ip, params.sni, serialized, version, chlo_hash,
1368 params.x509_ecdsa_supported,
1369 std::move(proof_source_cb));
1370 }
1371
1372 QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
1373 ~BuildServerConfigUpdateMessageProofSourceCallback() {}
1374
1375 QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
1376 BuildServerConfigUpdateMessageProofSourceCallback(
1377 const QuicCryptoServerConfig* config,
1378 QuicVersion version,
1379 QuicCompressedCertsCache* compressed_certs_cache,
1380 const CommonCertSets* common_cert_sets,
1381 const QuicCryptoNegotiatedParameters& params,
1382 CryptoHandshakeMessage message,
1383 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb)
1384 : config_(config),
1385 version_(version),
1386 compressed_certs_cache_(compressed_certs_cache),
1387 common_cert_sets_(common_cert_sets),
1388 client_common_set_hashes_(params.client_common_set_hashes),
1389 client_cached_cert_hashes_(params.client_cached_cert_hashes),
1390 sct_supported_by_client_(params.sct_supported_by_client),
1391 message_(std::move(message)),
1392 cb_(std::move(cb)) {}
1393
1394 void QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
1395 Run(bool ok,
1396 const scoped_refptr<ProofSource::Chain>& chain,
1397 const string& signature,
1398 const string& leaf_cert_sct,
1399 std::unique_ptr<ProofSource::Details> details) {
1400 config_->FinishBuildServerConfigUpdateMessage(
1401 version_, compressed_certs_cache_, common_cert_sets_,
1402 client_common_set_hashes_, client_cached_cert_hashes_,
1403 sct_supported_by_client_, ok, chain, signature, leaf_cert_sct,
1404 std::move(details), std::move(message_), std::move(cb_));
1405 }
1406
1407 void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
1408 QuicVersion version,
1409 QuicCompressedCertsCache* compressed_certs_cache,
1410 const CommonCertSets* common_cert_sets,
1411 const string& client_common_set_hashes,
1412 const string& client_cached_cert_hashes,
1413 bool sct_supported_by_client,
1414 bool ok,
1415 const scoped_refptr<ProofSource::Chain>& chain,
1416 const string& signature,
1417 const string& leaf_cert_sct,
1418 std::unique_ptr<ProofSource::Details> details,
1419 CryptoHandshakeMessage message,
1420 std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
1421 if (!ok) {
1422 cb->Run(false, message);
1423 return;
1424 }
1425
1426 const string compressed =
1427 CompressChain(compressed_certs_cache, chain, client_common_set_hashes,
1428 client_cached_cert_hashes, common_cert_sets);
1429
1430 message.SetStringPiece(kCertificateTag, compressed);
1431 message.SetStringPiece(kPROF, signature);
1432 if (sct_supported_by_client && enable_serving_sct_) {
1433 if (leaf_cert_sct.empty()) {
1434 DLOG(WARNING) << "SCT is expected but it is empty.";
1435 } else {
1436 message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct);
1437 }
1438 }
1439
1440 cb->Run(true, message);
1441 }
1442
1443 void QuicCryptoServerConfig::BuildRejection(
1444 QuicVersion version,
1445 const Config& config,
1446 const CryptoHandshakeMessage& client_hello,
1447 const ClientHelloInfo& info,
1448 const CachedNetworkParameters& cached_network_params,
1449 bool use_stateless_rejects,
1450 QuicConnectionId server_designated_connection_id,
1451 QuicRandom* rand,
1452 QuicCompressedCertsCache* compressed_certs_cache,
1453 QuicCryptoNegotiatedParameters* params,
1454 const QuicCryptoProof& crypto_proof,
1455 CryptoHandshakeMessage* out) const {
1456 if (FLAGS_enable_quic_stateless_reject_support && use_stateless_rejects) {
1457 DVLOG(1) << "QUIC Crypto server config returning stateless reject "
1458 << "with server-designated connection ID "
1459 << server_designated_connection_id;
1460 out->set_tag(kSREJ);
1461 out->SetValue(kRCID, server_designated_connection_id);
1462 } else {
1463 out->set_tag(kREJ);
1464 }
1465 out->SetStringPiece(kSCFG, config.serialized);
1466 out->SetStringPiece(
1467 kSourceAddressTokenTag,
1468 NewSourceAddressToken(config, info.source_address_tokens, info.client_ip,
1469 rand, info.now, &cached_network_params));
1470 if (replay_protection_) {
1471 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
1472 }
1473
1474 // Send client the reject reason for debugging purposes.
1475 DCHECK_LT(0u, info.reject_reasons.size());
1476 out->SetVector(kRREJ, info.reject_reasons);
1477
1478 // The client may have requested a certificate chain.
1479 bool x509_supported = false;
1480 ParseProofDemand(client_hello, &x509_supported,
1481 &params->x509_ecdsa_supported);
1482 if (!x509_supported && FLAGS_quic_require_x509) {
1483 QUIC_BUG << "x509 certificates not supported in proof demand";
1484 return;
1485 }
1486
1487 StringPiece client_common_set_hashes;
1488 if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) {
1489 params->client_common_set_hashes = client_common_set_hashes.as_string();
1490 }
1491
1492 StringPiece client_cached_cert_hashes;
1493 if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) {
1494 params->client_cached_cert_hashes = client_cached_cert_hashes.as_string();
1495 }
1496
1497 const string compressed =
1498 CompressChain(compressed_certs_cache, crypto_proof.chain,
1499 params->client_common_set_hashes,
1500 params->client_cached_cert_hashes, config.common_cert_sets);
1501
1502 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1503 // message is taken up by things other than the certificates.
1504 // STK: 56 bytes
1505 // SNO: 56 bytes
1506 // SCFG
1507 // SCID: 16 bytes
1508 // PUBS: 38 bytes
1509 const size_t kREJOverheadBytes = 166;
1510 // max_unverified_size is the number of bytes that the certificate chain,
1511 // signature, and (optionally) signed certificate timestamp can consume before
1512 // we will demand a valid source-address token.
1513 const size_t max_unverified_size =
1514 client_hello.size() * chlo_multiplier_ - kREJOverheadBytes;
1515 static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
1516 "overhead calculation may underflow");
1517 bool should_return_sct =
1518 params->sct_supported_by_client && enable_serving_sct_;
1519 const size_t sct_size = should_return_sct ? crypto_proof.cert_sct.size() : 0;
1520 if (info.valid_source_address_token ||
1521 crypto_proof.signature.size() + compressed.size() + sct_size <
1522 max_unverified_size) {
1523 out->SetStringPiece(kCertificateTag, compressed);
1524 out->SetStringPiece(kPROF, crypto_proof.signature);
1525 if (should_return_sct) {
1526 if (crypto_proof.cert_sct.empty()) {
1527 DLOG(WARNING) << "SCT is expected but it is empty.";
1528 } else {
1529 out->SetStringPiece(kCertificateSCTTag, crypto_proof.cert_sct);
1530 }
1531 }
1532 }
1533 }
1534
1535 string QuicCryptoServerConfig::CompressChain(
1536 QuicCompressedCertsCache* compressed_certs_cache,
1537 const scoped_refptr<ProofSource::Chain>& chain,
1538 const string& client_common_set_hashes,
1539 const string& client_cached_cert_hashes,
1540 const CommonCertSets* common_sets) {
1541 // Check whether the compressed certs is available in the cache.
1542 DCHECK(compressed_certs_cache);
1543 const string* cached_value = compressed_certs_cache->GetCompressedCert(
1544 chain, client_common_set_hashes, client_cached_cert_hashes);
1545 if (cached_value) {
1546 return *cached_value;
1547 }
1548
1549 const string compressed =
1550 CertCompressor::CompressChain(chain->certs, client_common_set_hashes,
1551 client_common_set_hashes, common_sets);
1552
1553 // Insert the newly compressed cert to cache.
1554 compressed_certs_cache->Insert(chain, client_common_set_hashes,
1555 client_cached_cert_hashes, compressed);
1556 return compressed;
1557 }
1558
1559 scoped_refptr<QuicCryptoServerConfig::Config>
1560 QuicCryptoServerConfig::ParseConfigProtobuf(
1561 QuicServerConfigProtobuf* protobuf) {
1562 std::unique_ptr<CryptoHandshakeMessage> msg(
1563 CryptoFramer::ParseMessage(protobuf->config()));
1564
1565 if (msg->tag() != kSCFG) {
1566 LOG(WARNING) << "Server config message has tag " << msg->tag()
1567 << " expected " << kSCFG;
1568 return nullptr;
1569 }
1570
1571 scoped_refptr<Config> config(new Config);
1572 config->serialized = protobuf->config();
1573
1574 if (!protobuf->has_source_address_token_secret_override()) {
1575 // Use the default boxer.
1576 config->source_address_token_boxer = &default_source_address_token_boxer_;
1577 } else {
1578 // Create override boxer instance.
1579 CryptoSecretBoxer* boxer = new CryptoSecretBoxer;
1580 boxer->SetKeys({DeriveSourceAddressTokenKey(
1581 protobuf->source_address_token_secret_override())});
1582 config->source_address_token_boxer_storage.reset(boxer);
1583 config->source_address_token_boxer = boxer;
1584 }
1585
1586 if (protobuf->has_primary_time()) {
1587 config->primary_time =
1588 QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
1589 }
1590
1591 config->priority = protobuf->priority();
1592
1593 StringPiece scid;
1594 if (!msg->GetStringPiece(kSCID, &scid)) {
1595 LOG(WARNING) << "Server config message is missing SCID";
1596 return nullptr;
1597 }
1598 config->id = scid.as_string();
1599
1600 const QuicTag* aead_tags;
1601 size_t aead_len;
1602 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
1603 LOG(WARNING) << "Server config message is missing AEAD";
1604 return nullptr;
1605 }
1606 config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
1607
1608 const QuicTag* kexs_tags;
1609 size_t kexs_len;
1610 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
1611 LOG(WARNING) << "Server config message is missing KEXS";
1612 return nullptr;
1613 }
1614
1615 const QuicTag* tbkp_tags;
1616 size_t tbkp_len;
1617 QuicErrorCode err;
1618 if ((err = msg->GetTaglist(kTBKP, &tbkp_tags, &tbkp_len)) !=
1619 QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND &&
1620 err != QUIC_NO_ERROR) {
1621 LOG(WARNING) << "Server config message is missing or has invalid TBKP";
1622 return nullptr;
1623 }
1624 config->tb_key_params = vector<QuicTag>(tbkp_tags, tbkp_tags + tbkp_len);
1625
1626 StringPiece orbit;
1627 if (!msg->GetStringPiece(kORBT, &orbit)) {
1628 LOG(WARNING) << "Server config message is missing ORBT";
1629 return nullptr;
1630 }
1631
1632 if (orbit.size() != kOrbitSize) {
1633 LOG(WARNING) << "Orbit value in server config is the wrong length."
1634 " Got "
1635 << orbit.size() << " want " << kOrbitSize;
1636 return nullptr;
1637 }
1638 static_assert(sizeof(config->orbit) == kOrbitSize,
1639 "orbit has incorrect size");
1640 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
1641
1642 {
1643 StrikeRegisterClient* strike_register_client;
1644 {
1645 base::AutoLock locked(strike_register_client_lock_);
1646 strike_register_client = strike_register_client_.get();
1647 }
1648
1649 if (strike_register_client != nullptr &&
1650 !strike_register_client->IsKnownOrbit(orbit)) {
1651 LOG(WARNING)
1652 << "Rejecting server config with orbit that the strike register "
1653 "client doesn't know about.";
1654 return nullptr;
1655 }
1656 }
1657
1658 if (kexs_len != protobuf->key_size()) {
1659 LOG(WARNING) << "Server config has " << kexs_len
1660 << " key exchange methods configured, but "
1661 << protobuf->key_size() << " private keys";
1662 return nullptr;
1663 }
1664
1665 const QuicTag* proof_demand_tags;
1666 size_t num_proof_demand_tags;
1667 if (msg->GetTaglist(kPDMD, &proof_demand_tags, &num_proof_demand_tags) ==
1668 QUIC_NO_ERROR) {
1669 for (size_t i = 0; i < num_proof_demand_tags; i++) {
1670 if (proof_demand_tags[i] == kCHID) {
1671 config->channel_id_enabled = true;
1672 break;
1673 }
1674 }
1675 }
1676
1677 for (size_t i = 0; i < kexs_len; i++) {
1678 const QuicTag tag = kexs_tags[i];
1679 string private_key;
1680
1681 config->kexs.push_back(tag);
1682
1683 for (size_t j = 0; j < protobuf->key_size(); j++) {
1684 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
1685 if (key.tag() == tag) {
1686 private_key = key.private_key();
1687 break;
1688 }
1689 }
1690
1691 if (private_key.empty()) {
1692 LOG(WARNING) << "Server config contains key exchange method without "
1693 "corresponding private key: "
1694 << tag;
1695 return nullptr;
1696 }
1697
1698 std::unique_ptr<KeyExchange> ka;
1699 switch (tag) {
1700 case kC255:
1701 ka.reset(Curve25519KeyExchange::New(private_key));
1702 if (!ka.get()) {
1703 LOG(WARNING) << "Server config contained an invalid curve25519"
1704 " private key.";
1705 return nullptr;
1706 }
1707 break;
1708 case kP256:
1709 ka.reset(P256KeyExchange::New(private_key));
1710 if (!ka.get()) {
1711 LOG(WARNING) << "Server config contained an invalid P-256"
1712 " private key.";
1713 return nullptr;
1714 }
1715 break;
1716 default:
1717 LOG(WARNING) << "Server config message contains unknown key exchange "
1718 "method: "
1719 << tag;
1720 return nullptr;
1721 }
1722
1723 for (const KeyExchange* key_exchange : config->key_exchanges) {
1724 if (key_exchange->tag() == tag) {
1725 LOG(WARNING) << "Duplicate key exchange in config: " << tag;
1726 return nullptr;
1727 }
1728 }
1729
1730 config->key_exchanges.push_back(ka.release());
1731 }
1732
1733 return config;
1734 }
1735
1736 void QuicCryptoServerConfig::SetEphemeralKeySource(
1737 EphemeralKeySource* ephemeral_key_source) {
1738 ephemeral_key_source_.reset(ephemeral_key_source);
1739 }
1740
1741 void QuicCryptoServerConfig::SetStrikeRegisterClient(
1742 StrikeRegisterClient* strike_register_client) {
1743 base::AutoLock locker(strike_register_client_lock_);
1744 DCHECK(!strike_register_client_.get());
1745 strike_register_client_.reset(strike_register_client);
1746 }
1747
1748 void QuicCryptoServerConfig::set_replay_protection(bool on) {
1749 replay_protection_ = on;
1750 }
1751
1752 void QuicCryptoServerConfig::set_chlo_multiplier(size_t multiplier) {
1753 chlo_multiplier_ = multiplier;
1754 }
1755
1756 void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
1757 base::AutoLock locker(strike_register_client_lock_);
1758 DCHECK(!strike_register_client_.get());
1759 strike_register_no_startup_period_ = true;
1760 }
1761
1762 void QuicCryptoServerConfig::set_strike_register_max_entries(
1763 uint32_t max_entries) {
1764 base::AutoLock locker(strike_register_client_lock_);
1765 DCHECK(!strike_register_client_.get());
1766 strike_register_max_entries_ = max_entries;
1767 }
1768
1769 void QuicCryptoServerConfig::set_strike_register_window_secs(
1770 uint32_t window_secs) {
1771 base::AutoLock locker(strike_register_client_lock_);
1772 DCHECK(!strike_register_client_.get());
1773 strike_register_window_secs_ = window_secs;
1774 }
1775
1776 void QuicCryptoServerConfig::set_source_address_token_future_secs(
1777 uint32_t future_secs) {
1778 source_address_token_future_secs_ = future_secs;
1779 }
1780
1781 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1782 uint32_t lifetime_secs) {
1783 source_address_token_lifetime_secs_ = lifetime_secs;
1784 }
1785
1786 void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries(
1787 uint32_t max_entries) {
1788 DCHECK(!server_nonce_strike_register_.get());
1789 server_nonce_strike_register_max_entries_ = max_entries;
1790 }
1791
1792 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
1793 uint32_t window_secs) {
1794 DCHECK(!server_nonce_strike_register_.get());
1795 server_nonce_strike_register_window_secs_ = window_secs;
1796 }
1797
1798 void QuicCryptoServerConfig::set_enable_serving_sct(bool enable_serving_sct) {
1799 enable_serving_sct_ = enable_serving_sct;
1800 }
1801
1802 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1803 PrimaryConfigChangedCallback* cb) {
1804 base::AutoLock locked(configs_lock_);
1805 primary_config_changed_cb_.reset(cb);
1806 }
1807
1808 string QuicCryptoServerConfig::NewSourceAddressToken(
1809 const Config& config,
1810 const SourceAddressTokens& previous_tokens,
1811 const IPAddress& ip,
1812 QuicRandom* rand,
1813 QuicWallTime now,
1814 const CachedNetworkParameters* cached_network_params) const {
1815 SourceAddressTokens source_address_tokens;
1816 SourceAddressToken* source_address_token = source_address_tokens.add_tokens();
1817 source_address_token->set_ip(IPAddressToPackedString(DualstackIPAddress(ip)));
1818 source_address_token->set_timestamp(now.ToUNIXSeconds());
1819 if (cached_network_params != nullptr) {
1820 *(source_address_token->mutable_cached_network_parameters()) =
1821 *cached_network_params;
1822 }
1823
1824 // Append previous tokens.
1825 for (const SourceAddressToken& token : previous_tokens.tokens()) {
1826 if (source_address_tokens.tokens_size() > kMaxTokenAddresses) {
1827 break;
1828 }
1829
1830 if (token.ip() == source_address_token->ip()) {
1831 // It's for the same IP address.
1832 continue;
1833 }
1834
1835 if (ValidateSourceAddressTokenTimestamp(token, now) != HANDSHAKE_OK) {
1836 continue;
1837 }
1838
1839 *(source_address_tokens.add_tokens()) = token;
1840 }
1841
1842 return config.source_address_token_boxer->Box(
1843 rand, source_address_tokens.SerializeAsString());
1844 }
1845
1846 int QuicCryptoServerConfig::NumberOfConfigs() const {
1847 base::AutoLock locked(configs_lock_);
1848 return configs_.size();
1849 }
1850
1851 HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
1852 const Config& config,
1853 StringPiece token,
1854 SourceAddressTokens* tokens) const {
1855 string storage;
1856 StringPiece plaintext;
1857 if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
1858 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
1859 }
1860
1861 if (!tokens->ParseFromArray(plaintext.data(), plaintext.size())) {
1862 // Some clients might still be using the old source token format so
1863 // attempt to parse that format.
1864 // TODO(rch): remove this code once the new format is ubiquitous.
1865 SourceAddressToken source_address_token;
1866 if (!source_address_token.ParseFromArray(plaintext.data(),
1867 plaintext.size())) {
1868 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
1869 }
1870 *tokens->add_tokens() = source_address_token;
1871 }
1872
1873 return HANDSHAKE_OK;
1874 }
1875
1876 HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
1877 const SourceAddressTokens& source_address_tokens,
1878 const IPAddress& ip,
1879 QuicWallTime now,
1880 CachedNetworkParameters* cached_network_params) const {
1881 HandshakeFailureReason reason =
1882 SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1883 for (const SourceAddressToken& token : source_address_tokens.tokens()) {
1884 reason = ValidateSingleSourceAddressToken(token, ip, now);
1885 if (reason == HANDSHAKE_OK) {
1886 if (token.has_cached_network_parameters()) {
1887 *cached_network_params = token.cached_network_parameters();
1888 }
1889 break;
1890 }
1891 }
1892 return reason;
1893 }
1894
1895 HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
1896 const SourceAddressToken& source_address_token,
1897 const IPAddress& ip,
1898 QuicWallTime now) const {
1899 if (source_address_token.ip() !=
1900 IPAddressToPackedString(DualstackIPAddress(ip))) {
1901 // It's for a different IP address.
1902 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
1903 }
1904
1905 return ValidateSourceAddressTokenTimestamp(source_address_token, now);
1906 }
1907
1908 HandshakeFailureReason
1909 QuicCryptoServerConfig::ValidateSourceAddressTokenTimestamp(
1910 const SourceAddressToken& source_address_token,
1911 QuicWallTime now) const {
1912 const QuicWallTime timestamp(
1913 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
1914 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
1915
1916 if (now.IsBefore(timestamp) &&
1917 delta.ToSeconds() > source_address_token_future_secs_) {
1918 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
1919 }
1920
1921 if (now.IsAfter(timestamp) &&
1922 delta.ToSeconds() > source_address_token_lifetime_secs_) {
1923 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
1924 }
1925
1926 return HANDSHAKE_OK;
1927 }
1928
1929 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1930 // nonce.
1931 static const size_t kServerNoncePlaintextSize =
1932 4 /* timestamp */ + 20 /* random bytes */;
1933
1934 string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
1935 QuicWallTime now) const {
1936 const uint32_t timestamp = static_cast<uint32_t>(now.ToUNIXSeconds());
1937
1938 uint8_t server_nonce[kServerNoncePlaintextSize];
1939 static_assert(sizeof(server_nonce) > sizeof(timestamp), "nonce too small");
1940 server_nonce[0] = static_cast<uint8_t>(timestamp >> 24);
1941 server_nonce[1] = static_cast<uint8_t>(timestamp >> 16);
1942 server_nonce[2] = static_cast<uint8_t>(timestamp >> 8);
1943 server_nonce[3] = static_cast<uint8_t>(timestamp);
1944 rand->RandBytes(&server_nonce[sizeof(timestamp)],
1945 sizeof(server_nonce) - sizeof(timestamp));
1946
1947 return server_nonce_boxer_.Box(
1948 rand,
1949 StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce)));
1950 }
1951
1952 HandshakeFailureReason QuicCryptoServerConfig::ValidateServerNonce(
1953 StringPiece token,
1954 QuicWallTime now) const {
1955 string storage;
1956 StringPiece plaintext;
1957 if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) {
1958 return SERVER_NONCE_DECRYPTION_FAILURE;
1959 }
1960
1961 // plaintext contains:
1962 // uint32_t timestamp
1963 // uint8_t[20] random bytes
1964
1965 if (plaintext.size() != kServerNoncePlaintextSize) {
1966 // This should never happen because the value decrypted correctly.
1967 QUIC_BUG << "Seemingly valid server nonce had incorrect length.";
1968 return SERVER_NONCE_INVALID_FAILURE;
1969 }
1970
1971 uint8_t server_nonce[32];
1972 memcpy(server_nonce, plaintext.data(), 4);
1973 memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_));
1974 memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4,
1975 20);
1976 static_assert(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
1977 "bad nonce buffer length");
1978
1979 InsertStatus nonce_error;
1980 {
1981 base::AutoLock auto_lock(server_nonce_strike_register_lock_);
1982 if (server_nonce_strike_register_.get() == nullptr) {
1983 server_nonce_strike_register_.reset(new StrikeRegister(
1984 server_nonce_strike_register_max_entries_,
1985 static_cast<uint32_t>(now.ToUNIXSeconds()),
1986 server_nonce_strike_register_window_secs_, server_nonce_orbit_,
1987 StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
1988 }
1989 nonce_error = server_nonce_strike_register_->Insert(
1990 server_nonce, static_cast<uint32_t>(now.ToUNIXSeconds()));
1991 }
1992
1993 switch (nonce_error) {
1994 case NONCE_OK:
1995 return HANDSHAKE_OK;
1996 case NONCE_INVALID_FAILURE:
1997 case NONCE_INVALID_ORBIT_FAILURE:
1998 return SERVER_NONCE_INVALID_FAILURE;
1999 case NONCE_NOT_UNIQUE_FAILURE:
2000 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
2001 case NONCE_INVALID_TIME_FAILURE:
2002 return SERVER_NONCE_INVALID_TIME_FAILURE;
2003 case NONCE_UNKNOWN_FAILURE:
2004 case STRIKE_REGISTER_TIMEOUT:
2005 case STRIKE_REGISTER_FAILURE:
2006 default:
2007 QUIC_BUG << "Unexpected server nonce error: " << nonce_error;
2008 return SERVER_NONCE_NOT_UNIQUE_FAILURE;
2009 }
2010 }
2011
2012 bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
2013 const CryptoHandshakeMessage& client_hello,
2014 const QuicCryptoProof& crypto_proof) const {
2015 if (crypto_proof.chain->certs.empty()) {
2016 return false;
2017 }
2018
2019 uint64_t hash_from_client;
2020 if (client_hello.GetUint64(kXLCT, &hash_from_client) != QUIC_NO_ERROR) {
2021 return false;
2022 }
2023 return CryptoUtils::ComputeLeafCertHash(crypto_proof.chain->certs.at(0)) ==
2024 hash_from_client;
2025 }
2026
2027 void QuicCryptoServerConfig::ParseProofDemand(
2028 const CryptoHandshakeMessage& client_hello,
2029 bool* x509_supported,
2030 bool* x509_ecdsa_supported) const {
2031 const QuicTag* their_proof_demands;
2032 size_t num_their_proof_demands;
2033
2034 if (client_hello.GetTaglist(kPDMD, &their_proof_demands,
2035 &num_their_proof_demands) != QUIC_NO_ERROR) {
2036 return;
2037 }
2038
2039 *x509_supported = false;
2040 for (size_t i = 0; i < num_their_proof_demands; i++) {
2041 switch (their_proof_demands[i]) {
2042 case kX509:
2043 *x509_supported = true;
2044 *x509_ecdsa_supported = true;
2045 break;
2046 case kX59R:
2047 *x509_supported = true;
2048 break;
2049 }
2050 }
2051 }
2052
2053 QuicCryptoServerConfig::Config::Config()
2054 : channel_id_enabled(false),
2055 is_primary(false),
2056 primary_time(QuicWallTime::Zero()),
2057 priority(0),
2058 source_address_token_boxer(nullptr) {}
2059
2060 QuicCryptoServerConfig::Config::~Config() {
2061 STLDeleteElements(&key_exchanges);
2062 }
2063
2064 QuicCryptoProof::QuicCryptoProof() {}
2065 QuicCryptoProof::~QuicCryptoProof() {}
2066 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/quic_crypto_server_config.h ('k') | net/quic/crypto/quic_crypto_server_config_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698