1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/quic/crypto/quic_crypto_server_config.h"
10 #include "base/stl_util.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "crypto/hkdf.h"
13 #include "crypto/secure_hash.h"
14 #include "net/base/net_util.h"
15 #include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
16 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
17 #include "net/quic/crypto/cert_compressor.h"
18 #include "net/quic/crypto/chacha20_poly1305_encrypter.h"
19 #include "net/quic/crypto/channel_id.h"
20 #include "net/quic/crypto/crypto_framer.h"
21 #include "net/quic/crypto/crypto_handshake_message.h"
22 #include "net/quic/crypto/crypto_server_config_protobuf.h"
23 #include "net/quic/crypto/crypto_utils.h"
24 #include "net/quic/crypto/curve25519_key_exchange.h"
25 #include "net/quic/crypto/ephemeral_key_source.h"
26 #include "net/quic/crypto/key_exchange.h"
27 #include "net/quic/crypto/local_strike_register_client.h"
28 #include "net/quic/crypto/p256_key_exchange.h"
29 #include "net/quic/crypto/proof_source.h"
30 #include "net/quic/crypto/quic_decrypter.h"
31 #include "net/quic/crypto/quic_encrypter.h"
32 #include "net/quic/crypto/quic_random.h"
33 #include "net/quic/crypto/source_address_token.h"
34 #include "net/quic/crypto/strike_register.h"
35 #include "net/quic/crypto/strike_register_client.h"
36 #include "net/quic/quic_clock.h"
37 #include "net/quic/quic_flags.h"
38 #include "net/quic/quic_protocol.h"
39 #include "net/quic/quic_socket_address_coder.h"
40 #include "net/quic/quic_utils.h"
42 using base::StringPiece
;
43 using crypto::SecureHash
;
53 const size_t kMaxTokenAddresses
= 4;
55 string
DeriveSourceAddressTokenKey(StringPiece source_address_token_secret
) {
56 crypto::HKDF
hkdf(source_address_token_secret
,
57 StringPiece() /* no salt */,
58 "QUIC source address token key",
59 CryptoSecretBoxer::GetKeySize(),
60 0 /* no fixed IV needed */,
61 0 /* no subkey secret */);
62 return hkdf
.server_write_key().as_string();
67 class ValidateClientHelloHelper
{
69 ValidateClientHelloHelper(ValidateClientHelloResultCallback::Result
* result
,
70 ValidateClientHelloResultCallback
* done_cb
)
71 : result_(result
), done_cb_(done_cb
) {
74 ~ValidateClientHelloHelper() {
75 LOG_IF(DFATAL
, done_cb_
!= nullptr)
76 << "Deleting ValidateClientHelloHelper with a pending callback.";
79 void ValidationComplete(QuicErrorCode error_code
, const char* error_details
) {
80 result_
->error_code
= error_code
;
81 result_
->error_details
= error_details
;
82 done_cb_
->Run(result_
);
86 void StartedAsyncCallback() {
91 void DetachCallback() {
92 LOG_IF(DFATAL
, done_cb_
== nullptr) << "Callback already detached.";
96 ValidateClientHelloResultCallback::Result
* result_
;
97 ValidateClientHelloResultCallback
* done_cb_
;
99 DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper
);
102 class VerifyNonceIsValidAndUniqueCallback
103 : public StrikeRegisterClient::ResultCallback
{
105 VerifyNonceIsValidAndUniqueCallback(
106 ValidateClientHelloResultCallback::Result
* result
,
107 ValidateClientHelloResultCallback
* done_cb
)
108 : result_(result
), done_cb_(done_cb
) {
112 void RunImpl(bool nonce_is_valid_and_unique
,
113 InsertStatus nonce_error
) override
{
114 DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique
115 << " nonce_error: " << nonce_error
;
116 result_
->info
.unique
= nonce_is_valid_and_unique
;
117 if (!nonce_is_valid_and_unique
) {
118 HandshakeFailureReason client_nonce_error
;
119 switch (nonce_error
) {
120 case NONCE_INVALID_FAILURE
:
121 client_nonce_error
= CLIENT_NONCE_INVALID_FAILURE
;
123 case NONCE_NOT_UNIQUE_FAILURE
:
124 client_nonce_error
= CLIENT_NONCE_NOT_UNIQUE_FAILURE
;
126 case NONCE_INVALID_ORBIT_FAILURE
:
127 client_nonce_error
= CLIENT_NONCE_INVALID_ORBIT_FAILURE
;
129 case NONCE_INVALID_TIME_FAILURE
:
130 client_nonce_error
= CLIENT_NONCE_INVALID_TIME_FAILURE
;
132 case STRIKE_REGISTER_TIMEOUT
:
133 client_nonce_error
= CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT
;
135 case STRIKE_REGISTER_FAILURE
:
136 client_nonce_error
= CLIENT_NONCE_STRIKE_REGISTER_FAILURE
;
138 case NONCE_UNKNOWN_FAILURE
:
139 client_nonce_error
= CLIENT_NONCE_UNKNOWN_FAILURE
;
143 LOG(DFATAL
) << "Unexpected client nonce error: " << nonce_error
;
144 client_nonce_error
= CLIENT_NONCE_UNKNOWN_FAILURE
;
147 result_
->info
.reject_reasons
.push_back(client_nonce_error
);
149 done_cb_
->Run(result_
);
153 ValidateClientHelloResultCallback::Result
* result_
;
154 ValidateClientHelloResultCallback
* done_cb_
;
156 DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback
);
160 const char QuicCryptoServerConfig::TESTING
[] = "secret string for testing";
162 ClientHelloInfo::ClientHelloInfo(const IPEndPoint
& in_client_ip
,
164 : client_ip(in_client_ip
),
166 valid_source_address_token(false),
167 client_nonce_well_formed(false),
171 ClientHelloInfo::~ClientHelloInfo() {
174 PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {
177 PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {
180 ValidateClientHelloResultCallback::Result::Result(
181 const CryptoHandshakeMessage
& in_client_hello
,
182 IPEndPoint in_client_ip
,
184 : client_hello(in_client_hello
),
185 info(in_client_ip
, in_now
),
186 error_code(QUIC_NO_ERROR
) {
189 ValidateClientHelloResultCallback::Result::~Result() {
192 ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {
195 ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {
198 void ValidateClientHelloResultCallback::Run(const Result
* result
) {
199 RunImpl(result
->client_hello
, *result
);
204 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
205 : expiry_time(QuicWallTime::Zero()),
206 channel_id_enabled(false),
209 QuicCryptoServerConfig::QuicCryptoServerConfig(
210 StringPiece source_address_token_secret
,
212 : replay_protection_(true),
214 primary_config_(nullptr),
215 next_config_promotion_time_(QuicWallTime::Zero()),
216 server_nonce_strike_register_lock_(),
217 strike_register_no_startup_period_(false),
218 strike_register_max_entries_(1 << 10),
219 strike_register_window_secs_(600),
220 source_address_token_future_secs_(3600),
221 source_address_token_lifetime_secs_(86400),
222 server_nonce_strike_register_max_entries_(1 << 10),
223 server_nonce_strike_register_window_secs_(120) {
224 default_source_address_token_boxer_
.SetKey(
225 DeriveSourceAddressTokenKey(source_address_token_secret
));
227 // Generate a random key and orbit for server nonces.
228 rand
->RandBytes(server_nonce_orbit_
, sizeof(server_nonce_orbit_
));
229 const size_t key_size
= server_nonce_boxer_
.GetKeySize();
230 scoped_ptr
<uint8
[]> key_bytes(new uint8
[key_size
]);
231 rand
->RandBytes(key_bytes
.get(), key_size
);
233 server_nonce_boxer_
.SetKey(
234 StringPiece(reinterpret_cast<char*>(key_bytes
.get()), key_size
));
237 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
238 primary_config_
= nullptr;
242 QuicServerConfigProtobuf
* QuicCryptoServerConfig::GenerateConfig(
244 const QuicClock
* clock
,
245 const ConfigOptions
& options
) {
246 CryptoHandshakeMessage msg
;
248 const string curve25519_private_key
=
249 Curve25519KeyExchange::NewPrivateKey(rand
);
250 scoped_ptr
<Curve25519KeyExchange
> curve25519(
251 Curve25519KeyExchange::New(curve25519_private_key
));
252 StringPiece curve25519_public_value
= curve25519
->public_value();
254 string encoded_public_values
;
255 // First three bytes encode the length of the public value.
256 DCHECK_LT(curve25519_public_value
.size(), (1U << 24));
257 encoded_public_values
.push_back(
258 static_cast<char>(curve25519_public_value
.size()));
259 encoded_public_values
.push_back(
260 static_cast<char>(curve25519_public_value
.size() >> 8));
261 encoded_public_values
.push_back(
262 static_cast<char>(curve25519_public_value
.size() >> 16));
263 encoded_public_values
.append(curve25519_public_value
.data(),
264 curve25519_public_value
.size());
266 string p256_private_key
;
268 p256_private_key
= P256KeyExchange::NewPrivateKey();
269 scoped_ptr
<P256KeyExchange
> p256(P256KeyExchange::New(p256_private_key
));
270 StringPiece p256_public_value
= p256
->public_value();
272 DCHECK_LT(p256_public_value
.size(), (1U << 24));
273 encoded_public_values
.push_back(
274 static_cast<char>(p256_public_value
.size()));
275 encoded_public_values
.push_back(
276 static_cast<char>(p256_public_value
.size() >> 8));
277 encoded_public_values
.push_back(
278 static_cast<char>(p256_public_value
.size() >> 16));
279 encoded_public_values
.append(p256_public_value
.data(),
280 p256_public_value
.size());
285 msg
.SetTaglist(kKEXS
, kC255
, kP256
, 0);
287 msg
.SetTaglist(kKEXS
, kC255
, 0);
289 if (ChaCha20Poly1305Encrypter::IsSupported()) {
290 msg
.SetTaglist(kAEAD
, kAESG
, kCC12
, 0);
292 msg
.SetTaglist(kAEAD
, kAESG
, 0);
294 msg
.SetStringPiece(kPUBS
, encoded_public_values
);
296 if (options
.expiry_time
.IsZero()) {
297 const QuicWallTime now
= clock
->WallNow();
298 const QuicWallTime expiry
= now
.Add(QuicTime::Delta::FromSeconds(
299 60 * 60 * 24 * 180 /* 180 days, ~six months */));
300 const uint64 expiry_seconds
= expiry
.ToUNIXSeconds();
301 msg
.SetValue(kEXPY
, expiry_seconds
);
303 msg
.SetValue(kEXPY
, options
.expiry_time
.ToUNIXSeconds());
306 char orbit_bytes
[kOrbitSize
];
307 if (options
.orbit
.size() == sizeof(orbit_bytes
)) {
308 memcpy(orbit_bytes
, options
.orbit
.data(), sizeof(orbit_bytes
));
310 DCHECK(options
.orbit
.empty());
311 rand
->RandBytes(orbit_bytes
, sizeof(orbit_bytes
));
313 msg
.SetStringPiece(kORBT
, StringPiece(orbit_bytes
, sizeof(orbit_bytes
)));
315 if (options
.channel_id_enabled
) {
316 msg
.SetTaglist(kPDMD
, kCHID
, 0);
319 if (options
.id
.empty()) {
320 // We need to ensure that the SCID changes whenever the server config does
321 // thus we make it a hash of the rest of the server config.
322 scoped_ptr
<QuicData
> serialized(
323 CryptoFramer::ConstructHandshakeMessage(msg
));
324 scoped_ptr
<SecureHash
> hash(SecureHash::Create(SecureHash::SHA256
));
325 hash
->Update(serialized
->data(), serialized
->length());
328 hash
->Finish(scid_bytes
, sizeof(scid_bytes
));
329 msg
.SetStringPiece(kSCID
, StringPiece(scid_bytes
, sizeof(scid_bytes
)));
331 msg
.SetStringPiece(kSCID
, options
.id
);
333 // Don't put new tags below this point. The SCID generation should hash over
334 // everything but itself and so extra tags should be added prior to the
335 // preceeding if block.
337 scoped_ptr
<QuicData
> serialized(CryptoFramer::ConstructHandshakeMessage(msg
));
339 scoped_ptr
<QuicServerConfigProtobuf
> config(new QuicServerConfigProtobuf
);
340 config
->set_config(serialized
->AsStringPiece());
341 QuicServerConfigProtobuf::PrivateKey
* curve25519_key
= config
->add_key();
342 curve25519_key
->set_tag(kC255
);
343 curve25519_key
->set_private_key(curve25519_private_key
);
346 QuicServerConfigProtobuf::PrivateKey
* p256_key
= config
->add_key();
347 p256_key
->set_tag(kP256
);
348 p256_key
->set_private_key(p256_private_key
);
351 return config
.release();
354 CryptoHandshakeMessage
* QuicCryptoServerConfig::AddConfig(
355 QuicServerConfigProtobuf
* protobuf
,
356 const QuicWallTime now
) {
357 scoped_ptr
<CryptoHandshakeMessage
> msg(
358 CryptoFramer::ParseMessage(protobuf
->config()));
361 LOG(WARNING
) << "Failed to parse server config message";
365 scoped_refptr
<Config
> config(ParseConfigProtobuf(protobuf
));
367 LOG(WARNING
) << "Failed to parse server config message";
372 base::AutoLock
locked(configs_lock_
);
373 if (configs_
.find(config
->id
) != configs_
.end()) {
374 LOG(WARNING
) << "Failed to add config because another with the same "
375 "server config id already exists: "
376 << base::HexEncode(config
->id
.data(), config
->id
.size());
380 configs_
[config
->id
] = config
;
381 SelectNewPrimaryConfig(now
);
382 DCHECK(primary_config_
.get());
383 DCHECK_EQ(configs_
.find(primary_config_
->id
)->second
, primary_config_
);
386 return msg
.release();
389 CryptoHandshakeMessage
* QuicCryptoServerConfig::AddDefaultConfig(
391 const QuicClock
* clock
,
392 const ConfigOptions
& options
) {
393 scoped_ptr
<QuicServerConfigProtobuf
> config(
394 GenerateConfig(rand
, clock
, options
));
395 return AddConfig(config
.get(), clock
->WallNow());
398 bool QuicCryptoServerConfig::SetConfigs(
399 const vector
<QuicServerConfigProtobuf
*>& protobufs
,
400 const QuicWallTime now
) {
401 vector
<scoped_refptr
<Config
> > parsed_configs
;
404 for (vector
<QuicServerConfigProtobuf
*>::const_iterator i
= protobufs
.begin();
405 i
!= protobufs
.end(); ++i
) {
406 scoped_refptr
<Config
> config(ParseConfigProtobuf(*i
));
412 parsed_configs
.push_back(config
);
415 if (parsed_configs
.empty()) {
416 LOG(WARNING
) << "New config list is empty.";
421 LOG(WARNING
) << "Rejecting QUIC configs because of above errors";
423 VLOG(1) << "Updating configs:";
425 base::AutoLock
locked(configs_lock_
);
426 ConfigMap new_configs
;
428 for (vector
<scoped_refptr
<Config
> >::const_iterator i
=
429 parsed_configs
.begin();
430 i
!= parsed_configs
.end(); ++i
) {
431 scoped_refptr
<Config
> config
= *i
;
433 ConfigMap::iterator it
= configs_
.find(config
->id
);
434 if (it
!= configs_
.end()) {
436 << "Keeping scid: " << base::HexEncode(
437 config
->id
.data(), config
->id
.size())
438 << " orbit: " << base::HexEncode(
439 reinterpret_cast<const char *>(config
->orbit
), kOrbitSize
)
440 << " new primary_time " << config
->primary_time
.ToUNIXSeconds()
441 << " old primary_time " << it
->second
->primary_time
.ToUNIXSeconds()
442 << " new priority " << config
->priority
443 << " old priority " << it
->second
->priority
;
444 // Update primary_time and priority.
445 it
->second
->primary_time
= config
->primary_time
;
446 it
->second
->priority
= config
->priority
;
447 new_configs
.insert(*it
);
449 VLOG(1) << "Adding scid: " << base::HexEncode(
450 config
->id
.data(), config
->id
.size())
451 << " orbit: " << base::HexEncode(
452 reinterpret_cast<const char *>(config
->orbit
), kOrbitSize
)
453 << " primary_time " << config
->primary_time
.ToUNIXSeconds()
454 << " priority " << config
->priority
;
455 new_configs
.insert(std::make_pair(config
->id
, config
));
459 configs_
.swap(new_configs
);
460 SelectNewPrimaryConfig(now
);
461 DCHECK(primary_config_
.get());
462 DCHECK_EQ(configs_
.find(primary_config_
->id
)->second
, primary_config_
);
468 void QuicCryptoServerConfig::GetConfigIds(vector
<string
>* scids
) const {
469 base::AutoLock
locked(configs_lock_
);
470 for (ConfigMap::const_iterator it
= configs_
.begin();
471 it
!= configs_
.end(); ++it
) {
472 scids
->push_back(it
->first
);
476 void QuicCryptoServerConfig::ValidateClientHello(
477 const CryptoHandshakeMessage
& client_hello
,
478 IPEndPoint client_ip
,
479 const QuicClock
* clock
,
480 ValidateClientHelloResultCallback
* done_cb
) const {
481 const QuicWallTime
now(clock
->WallNow());
483 ValidateClientHelloResultCallback::Result
* result
=
484 new ValidateClientHelloResultCallback::Result(
485 client_hello
, client_ip
, now
);
487 StringPiece requested_scid
;
488 client_hello
.GetStringPiece(kSCID
, &requested_scid
);
490 uint8 primary_orbit
[kOrbitSize
];
491 scoped_refptr
<Config
> requested_config
;
493 base::AutoLock
locked(configs_lock_
);
495 if (!primary_config_
.get()) {
496 result
->error_code
= QUIC_CRYPTO_INTERNAL_ERROR
;
497 result
->error_details
= "No configurations loaded";
499 if (!next_config_promotion_time_
.IsZero() &&
500 next_config_promotion_time_
.IsAfter(now
)) {
501 SelectNewPrimaryConfig(now
);
502 DCHECK(primary_config_
.get());
503 DCHECK_EQ(configs_
.find(primary_config_
->id
)->second
, primary_config_
);
506 memcpy(primary_orbit
, primary_config_
->orbit
, sizeof(primary_orbit
));
509 requested_config
= GetConfigWithScid(requested_scid
);
512 if (result
->error_code
== QUIC_NO_ERROR
) {
513 EvaluateClientHello(primary_orbit
, requested_config
, result
, done_cb
);
515 done_cb
->Run(result
);
519 QuicErrorCode
QuicCryptoServerConfig::ProcessClientHello(
520 const ValidateClientHelloResultCallback::Result
& validate_chlo_result
,
521 QuicConnectionId connection_id
,
522 const IPEndPoint
& server_ip
,
523 const IPEndPoint
& client_address
,
525 const QuicVersionVector
& supported_versions
,
526 const QuicClock
* clock
,
528 QuicCryptoNegotiatedParameters
* params
,
529 CryptoHandshakeMessage
* out
,
530 string
* error_details
) const {
531 DCHECK(error_details
);
533 const CryptoHandshakeMessage
& client_hello
=
534 validate_chlo_result
.client_hello
;
535 const ClientHelloInfo
& info
= validate_chlo_result
.info
;
537 // If the client's preferred version is not the version we are currently
538 // speaking, then the client went through a version negotiation. In this
539 // case, we need to make sure that we actually do not support this version
540 // and that it wasn't a downgrade attack.
541 QuicTag client_version_tag
;
542 if (client_hello
.GetUint32(kVER
, &client_version_tag
) != QUIC_NO_ERROR
) {
543 *error_details
= "client hello missing version list";
544 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
546 QuicVersion client_version
= QuicTagToQuicVersion(client_version_tag
);
547 if (client_version
!= version
) {
548 // Just because client_version is a valid version enum doesn't mean that
549 // this server actually supports that version, so we check to see if
550 // it's actually in the supported versions list.
551 for (size_t i
= 0; i
< supported_versions
.size(); ++i
) {
552 if (client_version
== supported_versions
[i
]) {
553 *error_details
= "Downgrade attack detected";
554 return QUIC_VERSION_NEGOTIATION_MISMATCH
;
559 StringPiece requested_scid
;
560 client_hello
.GetStringPiece(kSCID
, &requested_scid
);
561 const QuicWallTime
now(clock
->WallNow());
563 scoped_refptr
<Config
> requested_config
;
564 scoped_refptr
<Config
> primary_config
;
566 base::AutoLock
locked(configs_lock_
);
568 if (!primary_config_
.get()) {
569 *error_details
= "No configurations loaded";
570 return QUIC_CRYPTO_INTERNAL_ERROR
;
573 if (!next_config_promotion_time_
.IsZero() &&
574 next_config_promotion_time_
.IsAfter(now
)) {
575 SelectNewPrimaryConfig(now
);
576 DCHECK(primary_config_
.get());
577 DCHECK_EQ(configs_
.find(primary_config_
->id
)->second
, primary_config_
);
580 // We'll use the config that the client requested in order to do
581 // key-agreement. Otherwise we'll give it a copy of |primary_config_|
583 primary_config
= primary_config_
;
585 requested_config
= GetConfigWithScid(requested_scid
);
588 if (validate_chlo_result
.error_code
!= QUIC_NO_ERROR
) {
589 *error_details
= validate_chlo_result
.error_details
;
590 return validate_chlo_result
.error_code
;
595 if (!info
.valid_source_address_token
||
596 !info
.client_nonce_well_formed
||
598 !requested_config
.get()) {
599 BuildRejection(server_ip
, *primary_config
.get(), client_hello
, info
,
600 validate_chlo_result
.cached_network_params
, rand
, params
,
602 return QUIC_NO_ERROR
;
605 const QuicTag
* their_aeads
;
606 const QuicTag
* their_key_exchanges
;
607 size_t num_their_aeads
, num_their_key_exchanges
;
608 if (client_hello
.GetTaglist(kAEAD
, &their_aeads
,
609 &num_their_aeads
) != QUIC_NO_ERROR
||
610 client_hello
.GetTaglist(kKEXS
, &their_key_exchanges
,
611 &num_their_key_exchanges
) != QUIC_NO_ERROR
||
612 num_their_aeads
!= 1 ||
613 num_their_key_exchanges
!= 1) {
614 *error_details
= "Missing or invalid AEAD or KEXS";
615 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
618 size_t key_exchange_index
;
619 if (!QuicUtils::FindMutualTag(requested_config
->aead
, their_aeads
,
620 num_their_aeads
, QuicUtils::LOCAL_PRIORITY
,
621 ¶ms
->aead
, nullptr) ||
622 !QuicUtils::FindMutualTag(
623 requested_config
->kexs
, their_key_exchanges
, num_their_key_exchanges
,
624 QuicUtils::LOCAL_PRIORITY
, ¶ms
->key_exchange
,
625 &key_exchange_index
)) {
626 *error_details
= "Unsupported AEAD or KEXS";
627 return QUIC_CRYPTO_NO_SUPPORT
;
630 StringPiece public_value
;
631 if (!client_hello
.GetStringPiece(kPUBS
, &public_value
)) {
632 *error_details
= "Missing public value";
633 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
636 const KeyExchange
* key_exchange
=
637 requested_config
->key_exchanges
[key_exchange_index
];
638 if (!key_exchange
->CalculateSharedKey(public_value
,
639 ¶ms
->initial_premaster_secret
)) {
640 *error_details
= "Invalid public value";
641 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
644 if (!info
.sni
.empty()) {
645 scoped_ptr
<char[]> sni_tmp(new char[info
.sni
.length() + 1]);
646 memcpy(sni_tmp
.get(), info
.sni
.data(), info
.sni
.length());
647 sni_tmp
[info
.sni
.length()] = 0;
648 params
->sni
= CryptoUtils::NormalizeHostname(sni_tmp
.get());
652 const QuicData
& client_hello_serialized
= client_hello
.GetSerialized();
653 hkdf_suffix
.reserve(sizeof(connection_id
) + client_hello_serialized
.length() +
654 requested_config
->serialized
.size());
655 hkdf_suffix
.append(reinterpret_cast<char*>(&connection_id
),
656 sizeof(connection_id
));
657 hkdf_suffix
.append(client_hello_serialized
.data(),
658 client_hello_serialized
.length());
659 hkdf_suffix
.append(requested_config
->serialized
);
661 StringPiece cetv_ciphertext
;
662 if (requested_config
->channel_id_enabled
&&
663 client_hello
.GetStringPiece(kCETV
, &cetv_ciphertext
)) {
664 CryptoHandshakeMessage
client_hello_copy(client_hello
);
665 client_hello_copy
.Erase(kCETV
);
666 client_hello_copy
.Erase(kPAD
);
668 const QuicData
& client_hello_copy_serialized
=
669 client_hello_copy
.GetSerialized();
671 hkdf_input
.append(QuicCryptoConfig::kCETVLabel
,
672 strlen(QuicCryptoConfig::kCETVLabel
) + 1);
673 hkdf_input
.append(reinterpret_cast<char*>(&connection_id
),
674 sizeof(connection_id
));
675 hkdf_input
.append(client_hello_copy_serialized
.data(),
676 client_hello_copy_serialized
.length());
677 hkdf_input
.append(requested_config
->serialized
);
679 CrypterPair crypters
;
680 if (!CryptoUtils::DeriveKeys(params
->initial_premaster_secret
, params
->aead
,
681 info
.client_nonce
, info
.server_nonce
,
682 hkdf_input
, CryptoUtils::SERVER
, &crypters
,
683 nullptr /* subkey secret */)) {
684 *error_details
= "Symmetric key setup failed";
685 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED
;
688 char plaintext
[kMaxPacketSize
];
689 size_t plaintext_length
= 0;
690 const bool success
= crypters
.decrypter
->DecryptPacket(
691 0 /* sequence number */, StringPiece() /* associated data */,
692 cetv_ciphertext
, plaintext
, &plaintext_length
, kMaxPacketSize
);
694 *error_details
= "CETV decryption failure";
695 return QUIC_PACKET_TOO_LARGE
;
697 scoped_ptr
<CryptoHandshakeMessage
> cetv(
698 CryptoFramer::ParseMessage(StringPiece(plaintext
, plaintext_length
)));
700 *error_details
= "CETV parse error";
701 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
704 StringPiece key
, signature
;
705 if (cetv
->GetStringPiece(kCIDK
, &key
) &&
706 cetv
->GetStringPiece(kCIDS
, &signature
)) {
707 if (!ChannelIDVerifier::Verify(key
, hkdf_input
, signature
)) {
708 *error_details
= "ChannelID signature failure";
709 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
712 params
->channel_id
= key
.as_string();
717 size_t label_len
= strlen(QuicCryptoConfig::kInitialLabel
) + 1;
718 hkdf_input
.reserve(label_len
+ hkdf_suffix
.size());
719 hkdf_input
.append(QuicCryptoConfig::kInitialLabel
, label_len
);
720 hkdf_input
.append(hkdf_suffix
);
722 if (!CryptoUtils::DeriveKeys(params
->initial_premaster_secret
, params
->aead
,
723 info
.client_nonce
, info
.server_nonce
, hkdf_input
,
725 ¶ms
->initial_crypters
,
726 nullptr /* subkey secret */)) {
727 *error_details
= "Symmetric key setup failed";
728 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED
;
731 string forward_secure_public_value
;
732 if (ephemeral_key_source_
.get()) {
733 params
->forward_secure_premaster_secret
=
734 ephemeral_key_source_
->CalculateForwardSecureKey(
735 key_exchange
, rand
, clock
->ApproximateNow(), public_value
,
736 &forward_secure_public_value
);
738 scoped_ptr
<KeyExchange
> forward_secure_key_exchange(
739 key_exchange
->NewKeyPair(rand
));
740 forward_secure_public_value
=
741 forward_secure_key_exchange
->public_value().as_string();
742 if (!forward_secure_key_exchange
->CalculateSharedKey(
743 public_value
, ¶ms
->forward_secure_premaster_secret
)) {
744 *error_details
= "Invalid public value";
745 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
;
749 string forward_secure_hkdf_input
;
750 label_len
= strlen(QuicCryptoConfig::kForwardSecureLabel
) + 1;
751 forward_secure_hkdf_input
.reserve(label_len
+ hkdf_suffix
.size());
752 forward_secure_hkdf_input
.append(QuicCryptoConfig::kForwardSecureLabel
,
754 forward_secure_hkdf_input
.append(hkdf_suffix
);
756 if (!CryptoUtils::DeriveKeys(
757 params
->forward_secure_premaster_secret
, params
->aead
,
758 info
.client_nonce
, info
.server_nonce
, forward_secure_hkdf_input
,
759 CryptoUtils::SERVER
, ¶ms
->forward_secure_crypters
,
760 ¶ms
->subkey_secret
)) {
761 *error_details
= "Symmetric key setup failed";
762 return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED
;
766 QuicTagVector supported_version_tags
;
767 for (size_t i
= 0; i
< supported_versions
.size(); ++i
) {
768 supported_version_tags
.push_back
769 (QuicVersionToQuicTag(supported_versions
[i
]));
771 out
->SetVector(kVER
, supported_version_tags
);
773 kSourceAddressTokenTag
,
774 NewSourceAddressToken(*requested_config
.get(), info
.source_address_tokens
,
775 client_address
, rand
, info
.now
, nullptr));
776 QuicSocketAddressCoder
address_coder(client_address
);
777 out
->SetStringPiece(kCADR
, address_coder
.Encode());
778 out
->SetStringPiece(kPUBS
, forward_secure_public_value
);
780 return QUIC_NO_ERROR
;
783 scoped_refptr
<QuicCryptoServerConfig::Config
>
784 QuicCryptoServerConfig::GetConfigWithScid(StringPiece requested_scid
) const {
785 // In Chromium, we will dead lock if the lock is held by the current thread.
786 // Chromium doesn't have AssertReaderHeld API call.
787 // configs_lock_.AssertReaderHeld();
789 if (!requested_scid
.empty()) {
790 ConfigMap::const_iterator it
= configs_
.find(requested_scid
.as_string());
791 if (it
!= configs_
.end()) {
792 // We'll use the config that the client requested in order to do
794 return scoped_refptr
<Config
>(it
->second
);
798 return scoped_refptr
<Config
>();
801 // ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
802 // Config's based on their primary_time.
804 bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
805 const scoped_refptr
<Config
>& a
,
806 const scoped_refptr
<Config
>& b
) {
807 if (a
->primary_time
.IsBefore(b
->primary_time
) ||
808 b
->primary_time
.IsBefore(a
->primary_time
)) {
809 // Primary times differ.
810 return a
->primary_time
.IsBefore(b
->primary_time
);
811 } else if (a
->priority
!= b
->priority
) {
812 // Primary times are equal, sort backwards by priority.
813 return a
->priority
< b
->priority
;
815 // Primary times and priorities are equal, sort by config id.
816 return a
->id
< b
->id
;
820 void QuicCryptoServerConfig::SelectNewPrimaryConfig(
821 const QuicWallTime now
) const {
822 vector
<scoped_refptr
<Config
> > configs
;
823 configs
.reserve(configs_
.size());
825 for (ConfigMap::const_iterator it
= configs_
.begin();
826 it
!= configs_
.end(); ++it
) {
827 // TODO(avd) Exclude expired configs?
828 configs
.push_back(it
->second
);
831 if (configs
.empty()) {
832 if (primary_config_
.get()) {
833 LOG(DFATAL
) << "No valid QUIC server config. Keeping the current config.";
835 LOG(DFATAL
) << "No valid QUIC server config.";
840 std::sort(configs
.begin(), configs
.end(), ConfigPrimaryTimeLessThan
);
842 Config
* best_candidate
= configs
[0].get();
844 for (size_t i
= 0; i
< configs
.size(); ++i
) {
845 const scoped_refptr
<Config
> config(configs
[i
]);
846 if (!config
->primary_time
.IsAfter(now
)) {
847 if (config
->primary_time
.IsAfter(best_candidate
->primary_time
)) {
848 best_candidate
= config
.get();
853 // This is the first config with a primary_time in the future. Thus the
854 // previous Config should be the primary and this one should determine the
855 // next_config_promotion_time_.
856 scoped_refptr
<Config
> new_primary(best_candidate
);
858 // We need the primary_time of the next config.
859 if (configs
.size() > 1) {
860 next_config_promotion_time_
= configs
[1]->primary_time
;
862 next_config_promotion_time_
= QuicWallTime::Zero();
865 next_config_promotion_time_
= config
->primary_time
;
868 if (primary_config_
.get()) {
869 primary_config_
->is_primary
= false;
871 primary_config_
= new_primary
;
872 new_primary
->is_primary
= true;
873 DVLOG(1) << "New primary config. orbit: "
875 reinterpret_cast<const char*>(primary_config_
->orbit
),
877 if (primary_config_changed_cb_
.get() != nullptr) {
878 primary_config_changed_cb_
->Run(primary_config_
->id
);
884 // All config's primary times are in the past. We should make the most recent
885 // and highest priority candidate primary.
886 scoped_refptr
<Config
> new_primary(best_candidate
);
887 if (primary_config_
.get()) {
888 primary_config_
->is_primary
= false;
890 primary_config_
= new_primary
;
891 new_primary
->is_primary
= true;
892 DVLOG(1) << "New primary config. orbit: "
894 reinterpret_cast<const char*>(primary_config_
->orbit
),
896 << " scid: " << base::HexEncode(primary_config_
->id
.data(),
897 primary_config_
->id
.size());
898 next_config_promotion_time_
= QuicWallTime::Zero();
899 if (primary_config_changed_cb_
.get() != nullptr) {
900 primary_config_changed_cb_
->Run(primary_config_
->id
);
904 void QuicCryptoServerConfig::EvaluateClientHello(
905 const uint8
* primary_orbit
,
906 scoped_refptr
<Config
> requested_config
,
907 ValidateClientHelloResultCallback::Result
* client_hello_state
,
908 ValidateClientHelloResultCallback
* done_cb
) const {
909 ValidateClientHelloHelper
helper(client_hello_state
, done_cb
);
911 const CryptoHandshakeMessage
& client_hello
=
912 client_hello_state
->client_hello
;
913 ClientHelloInfo
* info
= &(client_hello_state
->info
);
915 if (client_hello
.size() < kClientHelloMinimumSize
) {
916 helper
.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH
,
917 "Client hello too small");
921 if (client_hello
.GetStringPiece(kSNI
, &info
->sni
) &&
922 !CryptoUtils::IsValidSNI(info
->sni
)) {
923 helper
.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER
,
928 client_hello
.GetStringPiece(kUAID
, &info
->user_agent_id
);
930 if (!requested_config
.get()) {
931 StringPiece requested_scid
;
932 if (client_hello
.GetStringPiece(kSCID
, &requested_scid
)) {
933 info
->reject_reasons
.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE
);
935 info
->reject_reasons
.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE
);
937 // No server config with the requested ID.
938 helper
.ValidationComplete(QUIC_NO_ERROR
, "");
942 HandshakeFailureReason source_address_token_error
;
944 if (client_hello
.GetStringPiece(kSourceAddressTokenTag
, &srct
)) {
945 if (!FLAGS_quic_use_multiple_address_in_source_tokens
) {
946 source_address_token_error
= ValidateSourceAddressToken(
947 *requested_config
.get(), srct
, info
->client_ip
, info
->now
,
948 &client_hello_state
->cached_network_params
);
950 source_address_token_error
= ParseSourceAddressToken(
951 *requested_config
.get(), srct
, &info
->source_address_tokens
);
953 if (source_address_token_error
== HANDSHAKE_OK
) {
954 source_address_token_error
= ValidateSourceAddressTokens(
955 info
->source_address_tokens
, info
->client_ip
, info
->now
,
956 &client_hello_state
->cached_network_params
);
959 info
->valid_source_address_token
=
960 (source_address_token_error
== HANDSHAKE_OK
);
962 source_address_token_error
= SOURCE_ADDRESS_TOKEN_INVALID_FAILURE
;
965 bool found_error
= false;
966 if (source_address_token_error
!= HANDSHAKE_OK
) {
967 info
->reject_reasons
.push_back(source_address_token_error
);
968 // No valid source address token.
969 if (FLAGS_use_early_return_when_verifying_chlo
) {
970 helper
.ValidationComplete(QUIC_NO_ERROR
, "");
976 if (client_hello
.GetStringPiece(kNONC
, &info
->client_nonce
) &&
977 info
->client_nonce
.size() == kNonceSize
) {
978 info
->client_nonce_well_formed
= true;
980 info
->reject_reasons
.push_back(CLIENT_NONCE_INVALID_FAILURE
);
981 // Invalid client nonce.
982 DVLOG(1) << "Invalid client nonce.";
983 if (FLAGS_use_early_return_when_verifying_chlo
) {
984 helper
.ValidationComplete(QUIC_NO_ERROR
, "");
990 if (!replay_protection_
) {
994 DVLOG(1) << "No replay protection.";
995 helper
.ValidationComplete(QUIC_NO_ERROR
, "");
999 client_hello
.GetStringPiece(kServerNonceTag
, &info
->server_nonce
);
1000 if (!info
->server_nonce
.empty()) {
1001 // If the server nonce is present, use it to establish uniqueness.
1002 HandshakeFailureReason server_nonce_error
=
1003 ValidateServerNonce(info
->server_nonce
, info
->now
);
1004 if (server_nonce_error
== HANDSHAKE_OK
) {
1005 info
->unique
= true;
1007 info
->reject_reasons
.push_back(server_nonce_error
);
1008 info
->unique
= false;
1010 DVLOG(1) << "Using server nonce, unique: " << info
->unique
;
1011 helper
.ValidationComplete(QUIC_NO_ERROR
, "");
1015 // We want to contact strike register only if there are no errors because it
1016 // is a RPC call and is expensive.
1018 helper
.ValidationComplete(QUIC_NO_ERROR
, "");
1022 // Use the client nonce to establish uniqueness.
1023 StrikeRegisterClient
* strike_register_client
;
1025 base::AutoLock
locked(strike_register_client_lock_
);
1027 if (strike_register_client_
.get() == nullptr) {
1028 strike_register_client_
.reset(new LocalStrikeRegisterClient(
1029 strike_register_max_entries_
,
1030 static_cast<uint32
>(info
->now
.ToUNIXSeconds()),
1031 strike_register_window_secs_
,
1033 strike_register_no_startup_period_
?
1034 StrikeRegister::NO_STARTUP_PERIOD_NEEDED
:
1035 StrikeRegister::DENY_REQUESTS_AT_STARTUP
));
1037 strike_register_client
= strike_register_client_
.get();
1040 strike_register_client
->VerifyNonceIsValidAndUnique(
1043 new VerifyNonceIsValidAndUniqueCallback(client_hello_state
, done_cb
));
1044 helper
.StartedAsyncCallback();
1047 bool QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
1048 const SourceAddressTokens
& previous_source_address_tokens
,
1049 const IPEndPoint
& server_ip
,
1050 const IPEndPoint
& client_ip
,
1051 const QuicClock
* clock
,
1053 const QuicCryptoNegotiatedParameters
& params
,
1054 const CachedNetworkParameters
* cached_network_params
,
1055 CryptoHandshakeMessage
* out
) const {
1056 base::AutoLock
locked(configs_lock_
);
1057 out
->set_tag(kSCUP
);
1058 out
->SetStringPiece(kSCFG
, primary_config_
->serialized
);
1059 out
->SetStringPiece(
1060 kSourceAddressTokenTag
,
1061 NewSourceAddressToken(*primary_config_
.get(),
1062 previous_source_address_tokens
, client_ip
, rand
,
1063 clock
->WallNow(), cached_network_params
));
1065 if (proof_source_
== nullptr) {
1066 // Insecure QUIC, can send SCFG without proof.
1070 const vector
<string
>* certs
;
1072 if (!proof_source_
->GetProof(
1073 server_ip
, params
.sni
, primary_config_
->serialized
,
1074 params
.x509_ecdsa_supported
, &certs
, &signature
)) {
1075 DVLOG(1) << "Server: failed to get proof.";
1079 const string compressed
= CertCompressor::CompressChain(
1080 *certs
, params
.client_common_set_hashes
, params
.client_cached_cert_hashes
,
1081 primary_config_
->common_cert_sets
);
1083 out
->SetStringPiece(kCertificateTag
, compressed
);
1084 out
->SetStringPiece(kPROF
, signature
);
1088 void QuicCryptoServerConfig::BuildRejection(
1089 const IPEndPoint
& server_ip
,
1090 const Config
& config
,
1091 const CryptoHandshakeMessage
& client_hello
,
1092 const ClientHelloInfo
& info
,
1093 const CachedNetworkParameters
& cached_network_params
,
1095 QuicCryptoNegotiatedParameters
* params
,
1096 CryptoHandshakeMessage
* out
) const {
1098 out
->SetStringPiece(kSCFG
, config
.serialized
);
1099 out
->SetStringPiece(
1100 kSourceAddressTokenTag
,
1101 NewSourceAddressToken(config
, info
.source_address_tokens
, info
.client_ip
,
1102 rand
, info
.now
, &cached_network_params
));
1103 if (replay_protection_
) {
1104 out
->SetStringPiece(kServerNonceTag
, NewServerNonce(rand
, info
.now
));
1107 // Send client the reject reason for debugging purposes.
1108 DCHECK_LT(0u, info
.reject_reasons
.size());
1109 out
->SetVector(kRREJ
, info
.reject_reasons
);
1111 // The client may have requested a certificate chain.
1112 const QuicTag
* their_proof_demands
;
1113 size_t num_their_proof_demands
;
1115 if (proof_source_
.get() == nullptr ||
1116 client_hello
.GetTaglist(kPDMD
, &their_proof_demands
,
1117 &num_their_proof_demands
) !=
1122 bool x509_supported
= false;
1123 for (size_t i
= 0; i
< num_their_proof_demands
; i
++) {
1124 switch (their_proof_demands
[i
]) {
1126 x509_supported
= true;
1127 params
->x509_ecdsa_supported
= true;
1130 x509_supported
= true;
1135 if (!x509_supported
) {
1139 const vector
<string
>* certs
;
1141 if (!proof_source_
->GetProof(server_ip
, info
.sni
.as_string(),
1142 config
.serialized
, params
->x509_ecdsa_supported
,
1143 &certs
, &signature
)) {
1147 StringPiece client_common_set_hashes
;
1148 if (client_hello
.GetStringPiece(kCCS
, &client_common_set_hashes
)) {
1149 params
->client_common_set_hashes
= client_common_set_hashes
.as_string();
1152 StringPiece client_cached_cert_hashes
;
1153 if (client_hello
.GetStringPiece(kCCRT
, &client_cached_cert_hashes
)) {
1154 params
->client_cached_cert_hashes
= client_cached_cert_hashes
.as_string();
1157 const string compressed
= CertCompressor::CompressChain(
1158 *certs
, params
->client_common_set_hashes
,
1159 params
->client_cached_cert_hashes
, config
.common_cert_sets
);
1161 // kREJOverheadBytes is a very rough estimate of how much of a REJ
1162 // message is taken up by things other than the certificates.
1168 const size_t kREJOverheadBytes
= 166;
1169 // kMultiplier is the multiple of the CHLO message size that a REJ message
1170 // must stay under when the client doesn't present a valid source-address
1172 const size_t kMultiplier
= 2;
1173 // max_unverified_size is the number of bytes that the certificate chain
1174 // and signature can consume before we will demand a valid source-address
1176 const size_t max_unverified_size
=
1177 client_hello
.size() * kMultiplier
- kREJOverheadBytes
;
1178 static_assert(kClientHelloMinimumSize
* kMultiplier
>= kREJOverheadBytes
,
1179 "overhead calculation may overflow");
1180 if (info
.valid_source_address_token
||
1181 signature
.size() + compressed
.size() < max_unverified_size
) {
1182 out
->SetStringPiece(kCertificateTag
, compressed
);
1183 out
->SetStringPiece(kPROF
, signature
);
1187 scoped_refptr
<QuicCryptoServerConfig::Config
>
1188 QuicCryptoServerConfig::ParseConfigProtobuf(
1189 QuicServerConfigProtobuf
* protobuf
) {
1190 scoped_ptr
<CryptoHandshakeMessage
> msg(
1191 CryptoFramer::ParseMessage(protobuf
->config()));
1193 if (msg
->tag() != kSCFG
) {
1194 LOG(WARNING
) << "Server config message has tag " << msg
->tag()
1195 << " expected " << kSCFG
;
1199 scoped_refptr
<Config
> config(new Config
);
1200 config
->serialized
= protobuf
->config();
1202 if (!protobuf
->has_source_address_token_secret_override()) {
1203 // Use the default boxer.
1204 config
->source_address_token_boxer
= &default_source_address_token_boxer_
;
1206 // Create override boxer instance.
1207 CryptoSecretBoxer
* boxer
= new CryptoSecretBoxer
;
1208 boxer
->SetKey(DeriveSourceAddressTokenKey(
1209 protobuf
->source_address_token_secret_override()));
1210 config
->source_address_token_boxer_storage
.reset(boxer
);
1211 config
->source_address_token_boxer
= boxer
;
1214 if (protobuf
->has_primary_time()) {
1215 config
->primary_time
=
1216 QuicWallTime::FromUNIXSeconds(protobuf
->primary_time());
1219 config
->priority
= protobuf
->priority();
1222 if (!msg
->GetStringPiece(kSCID
, &scid
)) {
1223 LOG(WARNING
) << "Server config message is missing SCID";
1226 config
->id
= scid
.as_string();
1228 const QuicTag
* aead_tags
;
1230 if (msg
->GetTaglist(kAEAD
, &aead_tags
, &aead_len
) != QUIC_NO_ERROR
) {
1231 LOG(WARNING
) << "Server config message is missing AEAD";
1234 config
->aead
= vector
<QuicTag
>(aead_tags
, aead_tags
+ aead_len
);
1236 const QuicTag
* kexs_tags
;
1238 if (msg
->GetTaglist(kKEXS
, &kexs_tags
, &kexs_len
) != QUIC_NO_ERROR
) {
1239 LOG(WARNING
) << "Server config message is missing KEXS";
1244 if (!msg
->GetStringPiece(kORBT
, &orbit
)) {
1245 LOG(WARNING
) << "Server config message is missing ORBT";
1249 if (orbit
.size() != kOrbitSize
) {
1250 LOG(WARNING
) << "Orbit value in server config is the wrong length."
1251 " Got " << orbit
.size() << " want " << kOrbitSize
;
1254 static_assert(sizeof(config
->orbit
) == kOrbitSize
,
1255 "orbit has incorrect size");
1256 memcpy(config
->orbit
, orbit
.data(), sizeof(config
->orbit
));
1259 StrikeRegisterClient
* strike_register_client
;
1261 base::AutoLock
locked(strike_register_client_lock_
);
1262 strike_register_client
= strike_register_client_
.get();
1265 if (strike_register_client
!= nullptr &&
1266 !strike_register_client
->IsKnownOrbit(orbit
)) {
1268 << "Rejecting server config with orbit that the strike register "
1269 "client doesn't know about.";
1274 if (kexs_len
!= protobuf
->key_size()) {
1275 LOG(WARNING
) << "Server config has " << kexs_len
1276 << " key exchange methods configured, but "
1277 << protobuf
->key_size() << " private keys";
1281 const QuicTag
* proof_demand_tags
;
1282 size_t num_proof_demand_tags
;
1283 if (msg
->GetTaglist(kPDMD
, &proof_demand_tags
, &num_proof_demand_tags
) ==
1285 for (size_t i
= 0; i
< num_proof_demand_tags
; i
++) {
1286 if (proof_demand_tags
[i
] == kCHID
) {
1287 config
->channel_id_enabled
= true;
1293 for (size_t i
= 0; i
< kexs_len
; i
++) {
1294 const QuicTag tag
= kexs_tags
[i
];
1297 config
->kexs
.push_back(tag
);
1299 for (size_t j
= 0; j
< protobuf
->key_size(); j
++) {
1300 const QuicServerConfigProtobuf::PrivateKey
& key
= protobuf
->key(i
);
1301 if (key
.tag() == tag
) {
1302 private_key
= key
.private_key();
1307 if (private_key
.empty()) {
1308 LOG(WARNING
) << "Server config contains key exchange method without "
1309 "corresponding private key: " << tag
;
1313 scoped_ptr
<KeyExchange
> ka
;
1316 ka
.reset(Curve25519KeyExchange::New(private_key
));
1318 LOG(WARNING
) << "Server config contained an invalid curve25519"
1324 ka
.reset(P256KeyExchange::New(private_key
));
1326 LOG(WARNING
) << "Server config contained an invalid P-256"
1332 LOG(WARNING
) << "Server config message contains unknown key exchange "
1337 for (vector
<KeyExchange
*>::const_iterator j
= config
->key_exchanges
.begin();
1338 j
!= config
->key_exchanges
.end(); ++j
) {
1339 if ((*j
)->tag() == tag
) {
1340 LOG(WARNING
) << "Duplicate key exchange in config: " << tag
;
1345 config
->key_exchanges
.push_back(ka
.release());
1351 void QuicCryptoServerConfig::SetProofSource(ProofSource
* proof_source
) {
1352 proof_source_
.reset(proof_source
);
1355 void QuicCryptoServerConfig::SetEphemeralKeySource(
1356 EphemeralKeySource
* ephemeral_key_source
) {
1357 ephemeral_key_source_
.reset(ephemeral_key_source
);
1360 void QuicCryptoServerConfig::SetStrikeRegisterClient(
1361 StrikeRegisterClient
* strike_register_client
) {
1362 base::AutoLock
locker(strike_register_client_lock_
);
1363 DCHECK(!strike_register_client_
.get());
1364 strike_register_client_
.reset(strike_register_client
);
1367 void QuicCryptoServerConfig::set_replay_protection(bool on
) {
1368 replay_protection_
= on
;
1371 void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
1372 base::AutoLock
locker(strike_register_client_lock_
);
1373 DCHECK(!strike_register_client_
.get());
1374 strike_register_no_startup_period_
= true;
1377 void QuicCryptoServerConfig::set_strike_register_max_entries(
1378 uint32 max_entries
) {
1379 base::AutoLock
locker(strike_register_client_lock_
);
1380 DCHECK(!strike_register_client_
.get());
1381 strike_register_max_entries_
= max_entries
;
1384 void QuicCryptoServerConfig::set_strike_register_window_secs(
1385 uint32 window_secs
) {
1386 base::AutoLock
locker(strike_register_client_lock_
);
1387 DCHECK(!strike_register_client_
.get());
1388 strike_register_window_secs_
= window_secs
;
1391 void QuicCryptoServerConfig::set_source_address_token_future_secs(
1392 uint32 future_secs
) {
1393 source_address_token_future_secs_
= future_secs
;
1396 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
1397 uint32 lifetime_secs
) {
1398 source_address_token_lifetime_secs_
= lifetime_secs
;
1401 void QuicCryptoServerConfig::set_server_nonce_strike_register_max_entries(
1402 uint32 max_entries
) {
1403 DCHECK(!server_nonce_strike_register_
.get());
1404 server_nonce_strike_register_max_entries_
= max_entries
;
1407 void QuicCryptoServerConfig::set_server_nonce_strike_register_window_secs(
1408 uint32 window_secs
) {
1409 DCHECK(!server_nonce_strike_register_
.get());
1410 server_nonce_strike_register_window_secs_
= window_secs
;
1413 void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
1414 PrimaryConfigChangedCallback
* cb
) {
1415 base::AutoLock
locked(configs_lock_
);
1416 primary_config_changed_cb_
.reset(cb
);
1419 string
QuicCryptoServerConfig::NewSourceAddressToken(
1420 const Config
& config
,
1421 const SourceAddressTokens
& previous_tokens
,
1422 const IPEndPoint
& ip
,
1425 const CachedNetworkParameters
* cached_network_params
) const {
1426 IPAddressNumber ip_address
= ip
.address();
1427 if (ip
.GetSockAddrFamily() == AF_INET
) {
1428 ip_address
= ConvertIPv4NumberToIPv6Number(ip_address
);
1430 SourceAddressTokens source_address_tokens
;
1431 SourceAddressToken
* source_address_token
= source_address_tokens
.add_tokens();
1432 source_address_token
->set_ip(IPAddressToPackedString(ip_address
));
1433 source_address_token
->set_timestamp(now
.ToUNIXSeconds());
1434 if (cached_network_params
!= nullptr) {
1435 *(source_address_token
->mutable_cached_network_parameters()) =
1436 *cached_network_params
;
1439 if (!FLAGS_quic_use_multiple_address_in_source_tokens
) {
1440 return config
.source_address_token_boxer
->Box(
1441 rand
, source_address_token
->SerializeAsString());
1444 // Append previous tokens.
1445 for (size_t i
= 0; i
< previous_tokens
.tokens_size(); i
++) {
1446 const SourceAddressToken
& token
= previous_tokens
.tokens(i
);
1447 if (source_address_tokens
.tokens_size() > kMaxTokenAddresses
) {
1451 if (token
.ip() == source_address_token
->ip()) {
1452 // It's for the same IP address.
1456 if (ValidateSourceAddressTokenTimestamp(token
, now
) != HANDSHAKE_OK
) {
1460 *(source_address_tokens
.add_tokens()) = token
;
1463 return config
.source_address_token_boxer
->Box(
1464 rand
, source_address_tokens
.SerializeAsString());
1467 bool QuicCryptoServerConfig::HasProofSource() const {
1468 return proof_source_
!= nullptr;
1471 HandshakeFailureReason
QuicCryptoServerConfig::ParseSourceAddressToken(
1472 const Config
& config
,
1474 SourceAddressTokens
* tokens
) const {
1476 StringPiece plaintext
;
1477 if (!config
.source_address_token_boxer
->Unbox(token
, &storage
, &plaintext
)) {
1478 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
;
1481 if (!FLAGS_quic_use_multiple_address_in_source_tokens
) {
1482 SourceAddressToken source_address_token
;
1483 if (!source_address_token
.ParseFromArray(plaintext
.data(),
1484 plaintext
.size())) {
1485 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE
;
1487 *(tokens
->add_tokens()) = source_address_token
;
1488 return HANDSHAKE_OK
;
1491 if (!tokens
->ParseFromArray(plaintext
.data(), plaintext
.size())) {
1492 // Some clients might still be using the old source token format so
1493 // attempt to parse that format.
1494 // TODO(rch): remove this code once the new format is ubiquitous.
1495 SourceAddressToken source_address_token
;
1496 if (!source_address_token
.ParseFromArray(plaintext
.data(),
1497 plaintext
.size())) {
1498 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE
;
1500 *tokens
->add_tokens() = source_address_token
;
1503 return HANDSHAKE_OK
;
1506 HandshakeFailureReason
QuicCryptoServerConfig::ValidateSourceAddressToken(
1507 const Config
& config
,
1509 const IPEndPoint
& ip
,
1511 CachedNetworkParameters
* cached_network_params
) const {
1513 StringPiece plaintext
;
1514 if (!config
.source_address_token_boxer
->Unbox(token
, &storage
, &plaintext
)) {
1515 return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
;
1518 SourceAddressToken source_address_token
;
1519 if (!source_address_token
.ParseFromArray(plaintext
.data(),
1520 plaintext
.size())) {
1521 return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE
;
1524 IPAddressNumber ip_address
= ip
.address();
1525 if (ip
.GetSockAddrFamily() == AF_INET
) {
1526 ip_address
= ConvertIPv4NumberToIPv6Number(ip_address
);
1528 if (source_address_token
.ip() != IPAddressToPackedString(ip_address
)) {
1529 // It's for a different IP address.
1530 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE
;
1533 const QuicWallTime
timestamp(
1534 QuicWallTime::FromUNIXSeconds(source_address_token
.timestamp()));
1535 const QuicTime::Delta
delta(now
.AbsoluteDifference(timestamp
));
1537 if (now
.IsBefore(timestamp
) &&
1538 delta
.ToSeconds() > source_address_token_future_secs_
) {
1539 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE
;
1542 if (now
.IsAfter(timestamp
) &&
1543 delta
.ToSeconds() > source_address_token_lifetime_secs_
) {
1544 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE
;
1547 if (source_address_token
.has_cached_network_parameters()) {
1548 *cached_network_params
= source_address_token
.cached_network_parameters();
1551 return HANDSHAKE_OK
;
1554 HandshakeFailureReason
QuicCryptoServerConfig::ValidateSourceAddressTokens(
1555 const SourceAddressTokens
& source_address_tokens
,
1556 const IPEndPoint
& ip
,
1558 CachedNetworkParameters
* cached_network_params
) const {
1559 HandshakeFailureReason reason
=
1560 SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE
;
1561 for (size_t i
= 0; i
< source_address_tokens
.tokens_size(); i
++) {
1562 const SourceAddressToken
& token
= source_address_tokens
.tokens(i
);
1563 reason
= ValidateSingleSourceAddressToken(token
, ip
, now
);
1564 if (reason
== HANDSHAKE_OK
) {
1565 if (token
.has_cached_network_parameters()) {
1566 *cached_network_params
= token
.cached_network_parameters();
1574 HandshakeFailureReason
QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
1575 const SourceAddressToken
& source_address_token
,
1576 const IPEndPoint
& ip
,
1577 QuicWallTime now
) const {
1578 IPAddressNumber ip_address
= ip
.address();
1579 if (ip
.GetSockAddrFamily() == AF_INET
) {
1580 ip_address
= ConvertIPv4NumberToIPv6Number(ip_address
);
1582 if (source_address_token
.ip() != IPAddressToPackedString(ip_address
)) {
1583 // It's for a different IP address.
1584 return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE
;
1587 return ValidateSourceAddressTokenTimestamp(source_address_token
, now
);
1590 HandshakeFailureReason
1591 QuicCryptoServerConfig::ValidateSourceAddressTokenTimestamp(
1592 const SourceAddressToken
& source_address_token
,
1593 QuicWallTime now
) const {
1594 const QuicWallTime
timestamp(
1595 QuicWallTime::FromUNIXSeconds(source_address_token
.timestamp()));
1596 const QuicTime::Delta
delta(now
.AbsoluteDifference(timestamp
));
1598 if (now
.IsBefore(timestamp
) &&
1599 delta
.ToSeconds() > source_address_token_future_secs_
) {
1600 return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE
;
1603 if (now
.IsAfter(timestamp
) &&
1604 delta
.ToSeconds() > source_address_token_lifetime_secs_
) {
1605 return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE
;
1608 return HANDSHAKE_OK
;
1611 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
1613 static const size_t kServerNoncePlaintextSize
=
1614 4 /* timestamp */ + 20 /* random bytes */;
1616 string
QuicCryptoServerConfig::NewServerNonce(QuicRandom
* rand
,
1617 QuicWallTime now
) const {
1618 const uint32 timestamp
= static_cast<uint32
>(now
.ToUNIXSeconds());
1620 uint8 server_nonce
[kServerNoncePlaintextSize
];
1621 static_assert(sizeof(server_nonce
) > sizeof(timestamp
), "nonce too small");
1622 server_nonce
[0] = static_cast<uint8
>(timestamp
>> 24);
1623 server_nonce
[1] = static_cast<uint8
>(timestamp
>> 16);
1624 server_nonce
[2] = static_cast<uint8
>(timestamp
>> 8);
1625 server_nonce
[3] = static_cast<uint8
>(timestamp
);
1626 rand
->RandBytes(&server_nonce
[sizeof(timestamp
)],
1627 sizeof(server_nonce
) - sizeof(timestamp
));
1629 return server_nonce_boxer_
.Box(
1631 StringPiece(reinterpret_cast<char*>(server_nonce
), sizeof(server_nonce
)));
1634 HandshakeFailureReason
QuicCryptoServerConfig::ValidateServerNonce(
1636 QuicWallTime now
) const {
1638 StringPiece plaintext
;
1639 if (!server_nonce_boxer_
.Unbox(token
, &storage
, &plaintext
)) {
1640 return SERVER_NONCE_DECRYPTION_FAILURE
;
1643 // plaintext contains:
1645 // uint8[20] random bytes
1647 if (plaintext
.size() != kServerNoncePlaintextSize
) {
1648 // This should never happen because the value decrypted correctly.
1649 LOG(DFATAL
) << "Seemingly valid server nonce had incorrect length.";
1650 return SERVER_NONCE_INVALID_FAILURE
;
1653 uint8 server_nonce
[32];
1654 memcpy(server_nonce
, plaintext
.data(), 4);
1655 memcpy(server_nonce
+ 4, server_nonce_orbit_
, sizeof(server_nonce_orbit_
));
1656 memcpy(server_nonce
+ 4 + sizeof(server_nonce_orbit_
), plaintext
.data() + 4,
1658 static_assert(4 + sizeof(server_nonce_orbit_
) + 20 == sizeof(server_nonce
),
1659 "bad nonce buffer length");
1661 InsertStatus nonce_error
;
1663 base::AutoLock
auto_lock(server_nonce_strike_register_lock_
);
1664 if (server_nonce_strike_register_
.get() == nullptr) {
1665 server_nonce_strike_register_
.reset(new StrikeRegister(
1666 server_nonce_strike_register_max_entries_
,
1667 static_cast<uint32
>(now
.ToUNIXSeconds()),
1668 server_nonce_strike_register_window_secs_
, server_nonce_orbit_
,
1669 StrikeRegister::NO_STARTUP_PERIOD_NEEDED
));
1671 nonce_error
= server_nonce_strike_register_
->Insert(
1672 server_nonce
, static_cast<uint32
>(now
.ToUNIXSeconds()));
1675 switch (nonce_error
) {
1677 return HANDSHAKE_OK
;
1678 case NONCE_INVALID_FAILURE
:
1679 case NONCE_INVALID_ORBIT_FAILURE
:
1680 return SERVER_NONCE_INVALID_FAILURE
;
1681 case NONCE_NOT_UNIQUE_FAILURE
:
1682 return SERVER_NONCE_NOT_UNIQUE_FAILURE
;
1683 case NONCE_INVALID_TIME_FAILURE
:
1684 return SERVER_NONCE_INVALID_TIME_FAILURE
;
1685 case NONCE_UNKNOWN_FAILURE
:
1686 case STRIKE_REGISTER_TIMEOUT
:
1687 case STRIKE_REGISTER_FAILURE
:
1689 LOG(DFATAL
) << "Unexpected server nonce error: " << nonce_error
;
1690 return SERVER_NONCE_NOT_UNIQUE_FAILURE
;
1694 QuicCryptoServerConfig::Config::Config()
1695 : channel_id_enabled(false),
1697 primary_time(QuicWallTime::Zero()),
1699 source_address_token_boxer(nullptr) {}
1701 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges
); }