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

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

Issue 15074007: Land Recent QUIC changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix for windows Created 7 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « net/quic/crypto/crypto_server_config.h ('k') | net/quic/crypto/crypto_utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/crypto/crypto_server_config.h" 5 #include "net/quic/crypto/crypto_server_config.h"
6 6
7 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "crypto/hkdf.h" 8 #include "crypto/hkdf.h"
9 #include "crypto/secure_hash.h" 9 #include "crypto/secure_hash.h"
10 #include "net/quic/crypto/aes_128_gcm_decrypter.h" 10 #include "net/quic/crypto/aes_128_gcm_decrypter.h"
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 // obtain two source address tokens with the same nonce. This occurs with 45 // obtain two source address tokens with the same nonce. This occurs with
46 // probability 0.5 after 2**48 values. We assume that obtaining 2**48 46 // probability 0.5 after 2**48 values. We assume that obtaining 2**48
47 // source address tokens is not possible: at a rate of 10M packets per 47 // source address tokens is not possible: at a rate of 10M packets per
48 // second, it would still take the attacker a year to obtain the needed 48 // second, it would still take the attacker a year to obtain the needed
49 // number of packets. 49 // number of packets.
50 // 50 //
51 // TODO(agl): switch to an encrypter with a larger nonce space (i.e. 51 // TODO(agl): switch to an encrypter with a larger nonce space (i.e.
52 // Salsa20+Poly1305). 52 // Salsa20+Poly1305).
53 : strike_register_lock_(), 53 : strike_register_lock_(),
54 source_address_token_encrypter_(new Aes128GcmEncrypter), 54 source_address_token_encrypter_(new Aes128GcmEncrypter),
55 source_address_token_decrypter_(new Aes128GcmDecrypter) { 55 source_address_token_decrypter_(new Aes128GcmDecrypter),
56 strike_register_max_entries_(1 << 10),
57 strike_register_window_secs_(600),
58 source_address_token_future_secs_(3600),
59 source_address_token_lifetime_secs_(86400) {
56 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */, 60 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */,
57 "QUIC source address token key", 61 "QUIC source address token key",
58 source_address_token_encrypter_->GetKeySize(), 62 source_address_token_encrypter_->GetKeySize(),
59 0 /* no fixed IV needed */); 63 0 /* no fixed IV needed */);
60 source_address_token_encrypter_->SetKey(hkdf.server_write_key()); 64 source_address_token_encrypter_->SetKey(hkdf.server_write_key());
61 source_address_token_decrypter_->SetKey(hkdf.server_write_key()); 65 source_address_token_decrypter_->SetKey(hkdf.server_write_key());
62 } 66 }
63 67
64 QuicCryptoServerConfig::~QuicCryptoServerConfig() { 68 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
65 STLDeleteValues(&configs_); 69 STLDeleteValues(&configs_);
66 } 70 }
67 71
68 // static 72 // static
69 QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig( 73 QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
70 QuicRandom* rand, 74 QuicRandom* rand,
71 const QuicClock* clock, 75 const QuicClock* clock,
72 const CryptoHandshakeMessage& extra_tags,
73 uint64 expiry_time) { 76 uint64 expiry_time) {
74 CryptoHandshakeMessage msg; 77 CryptoHandshakeMessage msg;
75 78
76 const string curve25519_private_key = 79 const string curve25519_private_key =
77 Curve25519KeyExchange::NewPrivateKey(rand); 80 Curve25519KeyExchange::NewPrivateKey(rand);
78 scoped_ptr<Curve25519KeyExchange> curve25519( 81 scoped_ptr<Curve25519KeyExchange> curve25519(
79 Curve25519KeyExchange::New(curve25519_private_key)); 82 Curve25519KeyExchange::New(curve25519_private_key));
80 StringPiece curve25519_public_value = curve25519->public_value(); 83 StringPiece curve25519_public_value = curve25519->public_value();
81 84
82 const string p256_private_key = P256KeyExchange::NewPrivateKey(); 85 const string p256_private_key = P256KeyExchange::NewPrivateKey();
(...skipping 11 matching lines...) Expand all
94 encoded_public_values.push_back(p256_public_value.size() >> 8); 97 encoded_public_values.push_back(p256_public_value.size() >> 8);
95 encoded_public_values.push_back(p256_public_value.size() >> 16); 98 encoded_public_values.push_back(p256_public_value.size() >> 16);
96 encoded_public_values.append(p256_public_value.data(), 99 encoded_public_values.append(p256_public_value.data(),
97 p256_public_value.size()); 100 p256_public_value.size());
98 101
99 msg.set_tag(kSCFG); 102 msg.set_tag(kSCFG);
100 msg.SetTaglist(kKEXS, kC255, kP256, 0); 103 msg.SetTaglist(kKEXS, kC255, kP256, 0);
101 msg.SetTaglist(kAEAD, kAESG, 0); 104 msg.SetTaglist(kAEAD, kAESG, 0);
102 msg.SetValue(kVERS, static_cast<uint16>(0)); 105 msg.SetValue(kVERS, static_cast<uint16>(0));
103 msg.SetStringPiece(kPUBS, encoded_public_values); 106 msg.SetStringPiece(kPUBS, encoded_public_values);
104 msg.Insert(extra_tags.tag_value_map().begin(),
105 extra_tags.tag_value_map().end());
106 107
107 if (expiry_time == 0) { 108 if (expiry_time == 0) {
108 const QuicWallTime now = clock->WallNow(); 109 const QuicWallTime now = clock->WallNow();
109 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds( 110 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
110 60 * 60 * 24 * 180 /* 180 days, ~six months */)); 111 60 * 60 * 24 * 180 /* 180 days, ~six months */));
111 const uint64 expiry_seconds = expiry.ToUNIXSeconds(); 112 const uint64 expiry_seconds = expiry.ToUNIXSeconds();
112 msg.SetValue(kEXPY, expiry_seconds); 113 msg.SetValue(kEXPY, expiry_seconds);
113 } else { 114 } else {
114 msg.SetValue(kEXPY, expiry_time); 115 msg.SetValue(kEXPY, expiry_time);
115 } 116 }
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 271
271 configs_[id] = config.release(); 272 configs_[id] = config.release();
272 active_config_ = id; 273 active_config_ = id;
273 274
274 return msg.release(); 275 return msg.release();
275 } 276 }
276 277
277 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig( 278 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
278 QuicRandom* rand, 279 QuicRandom* rand,
279 const QuicClock* clock, 280 const QuicClock* clock,
280 const CryptoHandshakeMessage& extra_tags,
281 uint64 expiry_time) { 281 uint64 expiry_time) {
282 scoped_ptr<QuicServerConfigProtobuf> config(DefaultConfig( 282 scoped_ptr<QuicServerConfigProtobuf> config(
283 rand, clock, extra_tags, expiry_time)); 283 DefaultConfig(rand, clock, expiry_time));
284 return AddConfig(config.get()); 284 return AddConfig(config.get());
285 } 285 }
286 286
287 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( 287 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
288 const CryptoHandshakeMessage& client_hello, 288 const CryptoHandshakeMessage& client_hello,
289 QuicGuid guid, 289 QuicGuid guid,
290 const IPEndPoint& client_ip, 290 const IPEndPoint& client_ip,
291 const QuicClock* clock, 291 const QuicClock* clock,
292 QuicRandom* rand, 292 QuicRandom* rand,
293 QuicCryptoNegotiatedParameters *params, 293 QuicCryptoNegotiatedParameters *params,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 327
328 StringPiece client_nonce; 328 StringPiece client_nonce;
329 bool client_nonce_well_formed = false; 329 bool client_nonce_well_formed = false;
330 if (client_hello.GetStringPiece(kNONC, &client_nonce) && 330 if (client_hello.GetStringPiece(kNONC, &client_nonce) &&
331 client_nonce.size() == kNonceSize) { 331 client_nonce.size() == kNonceSize) {
332 client_nonce_well_formed = true; 332 client_nonce_well_formed = true;
333 base::AutoLock auto_lock(strike_register_lock_); 333 base::AutoLock auto_lock(strike_register_lock_);
334 334
335 if (strike_register_.get() == NULL) { 335 if (strike_register_.get() == NULL) {
336 strike_register_.reset(new StrikeRegister( 336 strike_register_.reset(new StrikeRegister(
337 // TODO(agl): these magic numbers should come from config. 337 strike_register_max_entries_,
338 1024 /* max entries */,
339 static_cast<uint32>(now.ToUNIXSeconds()), 338 static_cast<uint32>(now.ToUNIXSeconds()),
340 600 /* window secs */, config->orbit)); 339 strike_register_window_secs_,
340 config->orbit));
341 } 341 }
342 unique_by_strike_register = strike_register_->Insert( 342 unique_by_strike_register = strike_register_->Insert(
343 reinterpret_cast<const uint8*>(client_nonce.data()), 343 reinterpret_cast<const uint8*>(client_nonce.data()),
344 static_cast<uint32>(now.ToUNIXSeconds())); 344 static_cast<uint32>(now.ToUNIXSeconds()));
345 } 345 }
346 346
347 StringPiece server_nonce; 347 StringPiece server_nonce;
348 client_hello.GetStringPiece(kServerNonceTag, &server_nonce); 348 client_hello.GetStringPiece(kServerNonceTag, &server_nonce);
349 const bool server_nonce_matches = server_nonce == params->server_nonce; 349 const bool server_nonce_matches = server_nonce == params->server_nonce;
350 350
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 break; 394 break;
395 } 395 }
396 396
397 StringPiece their_common_set_hashes; 397 StringPiece their_common_set_hashes;
398 StringPiece their_cached_cert_hashes; 398 StringPiece their_cached_cert_hashes;
399 client_hello.GetStringPiece(kCCS, &their_common_set_hashes); 399 client_hello.GetStringPiece(kCCS, &their_common_set_hashes);
400 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes); 400 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes);
401 401
402 const string compressed = CertCompressor::CompressChain( 402 const string compressed = CertCompressor::CompressChain(
403 *certs, their_common_set_hashes, their_cached_cert_hashes, 403 *certs, their_common_set_hashes, their_cached_cert_hashes,
404 config->common_cert_set_.get()); 404 config->common_cert_sets.get());
405 405
406 // kMaxUnverifiedSize is the number of bytes that the certificate chain 406 // kMaxUnverifiedSize is the number of bytes that the certificate chain
407 // and signature can consume before we will demand a valid 407 // and signature can consume before we will demand a valid
408 // source-address token. 408 // source-address token.
409 static const size_t kMaxUnverifiedSize = 400; 409 static const size_t kMaxUnverifiedSize = 400;
410 if (valid_source_address_token || 410 if (valid_source_address_token ||
411 signature.size() + compressed.size() < kMaxUnverifiedSize) { 411 signature.size() + compressed.size() < kMaxUnverifiedSize) {
412 out->SetStringPiece(kCertificateTag, compressed); 412 out->SetStringPiece(kCertificateTag, compressed);
413 out->SetStringPiece(kPROF, signature); 413 out->SetStringPiece(kPROF, signature);
414 } 414 }
(...skipping 11 matching lines...) Expand all
426 &num_their_aeads) != QUIC_NO_ERROR || 426 &num_their_aeads) != QUIC_NO_ERROR ||
427 client_hello.GetTaglist(kKEXS, &their_key_exchanges, 427 client_hello.GetTaglist(kKEXS, &their_key_exchanges,
428 &num_their_key_exchanges) != QUIC_NO_ERROR || 428 &num_their_key_exchanges) != QUIC_NO_ERROR ||
429 num_their_aeads != 1 || 429 num_their_aeads != 1 ||
430 num_their_key_exchanges != 1) { 430 num_their_key_exchanges != 1) {
431 *error_details = "Missing or invalid AEAD or KEXS"; 431 *error_details = "Missing or invalid AEAD or KEXS";
432 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 432 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
433 } 433 }
434 434
435 size_t key_exchange_index; 435 size_t key_exchange_index;
436 if (!CryptoUtils::FindMutualTag(config->aead, their_aeads, num_their_aeads, 436 if (!QuicUtils::FindMutualTag(config->aead, their_aeads, num_their_aeads,
437 CryptoUtils::LOCAL_PRIORITY, &params->aead, 437 QuicUtils::LOCAL_PRIORITY, &params->aead,
438 NULL) || 438 NULL) ||
439 !CryptoUtils::FindMutualTag( 439 !QuicUtils::FindMutualTag(
440 config->kexs, their_key_exchanges, num_their_key_exchanges, 440 config->kexs, their_key_exchanges, num_their_key_exchanges,
441 CryptoUtils::LOCAL_PRIORITY, &params->key_exchange, 441 QuicUtils::LOCAL_PRIORITY, &params->key_exchange,
442 &key_exchange_index)) { 442 &key_exchange_index)) {
443 *error_details = "Unsupported AEAD or KEXS"; 443 *error_details = "Unsupported AEAD or KEXS";
444 return QUIC_CRYPTO_NO_SUPPORT; 444 return QUIC_CRYPTO_NO_SUPPORT;
445 } 445 }
446 446
447 StringPiece public_value; 447 StringPiece public_value;
448 if (!client_hello.GetStringPiece(kPUBS, &public_value)) { 448 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
449 *error_details = "Missing public value"; 449 *error_details = "Missing public value";
450 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 450 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
451 } 451 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 516
517 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) { 517 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
518 proof_source_.reset(proof_source); 518 proof_source_.reset(proof_source);
519 } 519 }
520 520
521 void QuicCryptoServerConfig::SetEphemeralKeySource( 521 void QuicCryptoServerConfig::SetEphemeralKeySource(
522 EphemeralKeySource* ephemeral_key_source) { 522 EphemeralKeySource* ephemeral_key_source) {
523 ephemeral_key_source_.reset(ephemeral_key_source); 523 ephemeral_key_source_.reset(ephemeral_key_source);
524 } 524 }
525 525
526 void QuicCryptoServerConfig::set_strike_register_max_entries(
527 uint32 max_entries) {
528 DCHECK(!strike_register_.get());
529 strike_register_max_entries_ = max_entries;
530 }
531
532 void QuicCryptoServerConfig::set_strike_register_window_secs(
533 uint32 window_secs) {
534 DCHECK(!strike_register_.get());
535 strike_register_window_secs_ = window_secs;
536 }
537
538 void QuicCryptoServerConfig::set_source_address_token_future_secs(
539 uint32 future_secs) {
540 source_address_token_future_secs_ = future_secs;
541 }
542
543 void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
544 uint32 lifetime_secs) {
545 source_address_token_lifetime_secs_ = lifetime_secs;
546 }
547
526 string QuicCryptoServerConfig::NewSourceAddressToken( 548 string QuicCryptoServerConfig::NewSourceAddressToken(
527 const IPEndPoint& ip, 549 const IPEndPoint& ip,
528 QuicRandom* rand, 550 QuicRandom* rand,
529 QuicWallTime now) const { 551 QuicWallTime now) const {
530 SourceAddressToken source_address_token; 552 SourceAddressToken source_address_token;
531 source_address_token.set_ip(ip.ToString()); 553 source_address_token.set_ip(ip.ToString());
532 source_address_token.set_timestamp(now.ToUNIXSeconds()); 554 source_address_token.set_timestamp(now.ToUNIXSeconds());
533 555
534 string plaintext = source_address_token.SerializeAsString(); 556 string plaintext = source_address_token.SerializeAsString();
535 char nonce[12]; 557 char nonce[12];
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 615
594 if (source_address_token.ip() != ip.ToString()) { 616 if (source_address_token.ip() != ip.ToString()) {
595 // It's for a different IP address. 617 // It's for a different IP address.
596 return false; 618 return false;
597 } 619 }
598 620
599 const QuicWallTime timestamp( 621 const QuicWallTime timestamp(
600 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp())); 622 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
601 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp)); 623 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
602 624
603 // TODO(agl): consider whether and how these magic values should be moved to 625 if (now.IsBefore(timestamp) &&
604 // a config. 626 delta.ToSeconds() > source_address_token_future_secs_) {
605 if (now.IsBefore(timestamp) && delta.ToSeconds() > 3600) {
606 // We only allow timestamps to be from an hour in the future.
607 return false; 627 return false;
608 } 628 }
609 629
610 if (now.IsAfter(timestamp) && delta.ToSeconds() > 86400) { 630 if (now.IsAfter(timestamp) &&
611 // We allow one day into the past. 631 delta.ToSeconds() > source_address_token_lifetime_secs_) {
612 return false; 632 return false;
613 } 633 }
614 634
615 return true; 635 return true;
616 } 636 }
617 637
618 QuicCryptoServerConfig::Config::Config() {} 638 QuicCryptoServerConfig::Config::Config() {}
619 639
620 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } 640 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }
621 641
622 } // namespace net 642 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/crypto_server_config.h ('k') | net/quic/crypto/crypto_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698