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

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

Issue 14411004: Land Recent QUIC Changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use CONFIG_VERSION insteaf of VERSION Created 7 years, 8 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
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_handshake.h" 5 #include "net/quic/crypto/crypto_handshake.h"
6 6
7 #include <ctype.h> 7 #include <ctype.h>
8 8
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h" 12 #include "base/strings/string_split.h"
13 #include "crypto/hkdf.h"
14 #include "crypto/secure_hash.h" 13 #include "crypto/secure_hash.h"
15 #include "net/base/net_util.h" 14 #include "net/base/net_util.h"
16 #include "net/quic/crypto/aes_128_gcm_decrypter.h"
17 #include "net/quic/crypto/aes_128_gcm_encrypter.h"
18 #include "net/quic/crypto/crypto_framer.h" 15 #include "net/quic/crypto/crypto_framer.h"
19 #include "net/quic/crypto/crypto_utils.h" 16 #include "net/quic/crypto/crypto_utils.h"
20 #include "net/quic/crypto/curve25519_key_exchange.h" 17 #include "net/quic/crypto/curve25519_key_exchange.h"
21 #include "net/quic/crypto/key_exchange.h" 18 #include "net/quic/crypto/key_exchange.h"
22 #include "net/quic/crypto/p256_key_exchange.h" 19 #include "net/quic/crypto/p256_key_exchange.h"
23 #include "net/quic/crypto/quic_decrypter.h" 20 #include "net/quic/crypto/quic_decrypter.h"
24 #include "net/quic/crypto/quic_encrypter.h" 21 #include "net/quic/crypto/quic_encrypter.h"
25 #include "net/quic/crypto/quic_random.h" 22 #include "net/quic/crypto/quic_random.h"
26 #include "net/quic/crypto/strike_register.h"
27 #include "net/quic/quic_clock.h" 23 #include "net/quic/quic_clock.h"
28 #include "net/quic/quic_protocol.h" 24 #include "net/quic/quic_protocol.h"
29 25
30 using base::StringPiece; 26 using base::StringPiece;
31 using crypto::SecureHash; 27 using crypto::SecureHash;
32 using std::map; 28 using std::map;
33 using std::string; 29 using std::string;
34 using std::vector; 30 using std::vector;
35 31
36 namespace net { 32 namespace net {
37 33
38 // kVersion contains the one (and, for the moment, only) version number that we
39 // implement.
40 static const uint16 kVersion = 0;
41
42 // kLabel is constant that is used in key derivation to tie the resulting key
43 // to this protocol.
44 static const char kLabel[] = "QUIC key expansion";
45
46 using crypto::SecureHash;
47
48 QuicServerConfigProtobuf::QuicServerConfigProtobuf() {
49 }
50
51 QuicServerConfigProtobuf::~QuicServerConfigProtobuf() {
52 STLDeleteElements(&keys_);
53 }
54
55 CryptoHandshakeMessage::CryptoHandshakeMessage() : tag_(0) {} 34 CryptoHandshakeMessage::CryptoHandshakeMessage() : tag_(0) {}
56 35
57 CryptoHandshakeMessage::CryptoHandshakeMessage( 36 CryptoHandshakeMessage::CryptoHandshakeMessage(
58 const CryptoHandshakeMessage& other) 37 const CryptoHandshakeMessage& other)
59 : tag_(other.tag_), 38 : tag_(other.tag_),
60 tag_value_map_(other.tag_value_map_) { 39 tag_value_map_(other.tag_value_map_) {
61 // Don't copy serialized_. scoped_ptr doesn't have a copy constructor. 40 // Don't copy serialized_. scoped_ptr doesn't have a copy constructor.
62 // The new object can reconstruct serialized_ lazily. 41 // The new object can reconstruct serialized_ lazily.
63 } 42 }
64 43
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 if (it->second.size() == 4) { 256 if (it->second.size() == 4) {
278 uint32 value; 257 uint32 value;
279 memcpy(&value, it->second.data(), sizeof(value)); 258 memcpy(&value, it->second.data(), sizeof(value));
280 ret += base::UintToString(value); 259 ret += base::UintToString(value);
281 done = true; 260 done = true;
282 } 261 }
283 break; 262 break;
284 case kKEXS: 263 case kKEXS:
285 case kAEAD: 264 case kAEAD:
286 case kCGST: 265 case kCGST:
266 case kPDMD:
287 // tag lists 267 // tag lists
288 if (it->second.size() % sizeof(CryptoTag) == 0) { 268 if (it->second.size() % sizeof(CryptoTag) == 0) {
289 for (size_t j = 0; j < it->second.size(); j += sizeof(CryptoTag)) { 269 for (size_t j = 0; j < it->second.size(); j += sizeof(CryptoTag)) {
290 CryptoTag tag; 270 CryptoTag tag;
291 memcpy(&tag, it->second.data() + j, sizeof(tag)); 271 memcpy(&tag, it->second.data() + j, sizeof(tag));
292 if (j > 0) { 272 if (j > 0) {
293 ret += ","; 273 ret += ",";
294 } 274 }
295 ret += TagToString(tag); 275 ret += TagToString(tag);
296 } 276 }
(...skipping 20 matching lines...) Expand all
317 // then just use hex. 297 // then just use hex.
318 ret += base::HexEncode(it->second.data(), it->second.size()); 298 ret += base::HexEncode(it->second.data(), it->second.size());
319 } 299 }
320 ret += "\n"; 300 ret += "\n";
321 } 301 }
322 --indent; 302 --indent;
323 ret += string(2 * indent, ' ') + ">"; 303 ret += string(2 * indent, ' ') + ">";
324 return ret; 304 return ret;
325 } 305 }
326 306
327 SourceAddressToken::SourceAddressToken() {
328 }
329
330 SourceAddressToken::~SourceAddressToken() {
331 }
332
333 string SourceAddressToken::SerializeAsString() const {
334 return ip_ + " " + base::Int64ToString(timestamp_);
335 }
336
337 bool SourceAddressToken::ParseFromArray(unsigned char* plaintext,
338 size_t plaintext_length) {
339 string data(reinterpret_cast<const char*>(plaintext), plaintext_length);
340 std::vector<std::string> results;
341 base::SplitString(data, ' ', &results);
342 if (results.size() < 2) {
343 return false;
344 }
345
346 int64 timestamp;
347 if (!base::StringToInt64(results[1], &timestamp)) {
348 return false;
349 }
350
351 ip_ = results[0];
352 timestamp_ = timestamp;
353 return true;
354 }
355
356 QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters() 307 QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters()
357 : version(0), 308 : version(0),
358 key_exchange(0), 309 key_exchange(0),
359 aead(0) { 310 aead(0) {
360 } 311 }
361 312
362 QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() { 313 QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {
363 } 314 }
364 315
365 316
317 // static
318 const char QuicCryptoConfig::kLabel[] = "QUIC key expansion";
319
366 QuicCryptoConfig::QuicCryptoConfig() 320 QuicCryptoConfig::QuicCryptoConfig()
367 : version(0) { 321 : version(0) {
368 } 322 }
369 323
370 QuicCryptoConfig::~QuicCryptoConfig() { 324 QuicCryptoConfig::~QuicCryptoConfig() {
371 } 325 }
372 326
373 327
374 QuicCryptoClientConfig::QuicCryptoClientConfig() { 328 QuicCryptoClientConfig::QuicCryptoClientConfig() {
375 } 329 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 return source_address_token_; 375 return source_address_token_;
422 } 376 }
423 377
424 void QuicCryptoClientConfig::CachedState::set_source_address_token( 378 void QuicCryptoClientConfig::CachedState::set_source_address_token(
425 StringPiece token) { 379 StringPiece token) {
426 source_address_token_ = token.as_string(); 380 source_address_token_ = token.as_string();
427 } 381 }
428 382
429 void QuicCryptoClientConfig::SetDefaults() { 383 void QuicCryptoClientConfig::SetDefaults() {
430 // Version must be 0. 384 // Version must be 0.
431 version = kVersion; 385 version = QuicCryptoConfig::CONFIG_VERSION;
432 386
433 // Key exchange methods. 387 // Key exchange methods.
434 kexs.resize(2); 388 kexs.resize(2);
435 kexs[0] = kC255; 389 kexs[0] = kC255;
436 kexs[1] = kP256; 390 kexs[1] = kP256;
437 391
438 // Authenticated encryption algorithms. 392 // Authenticated encryption algorithms.
439 aead.resize(1); 393 aead.resize(1);
440 aead[0] = kAESG; 394 aead[0] = kAESG;
441 } 395 }
(...skipping 19 matching lines...) Expand all
461 IPAddressNumber ip; 415 IPAddressNumber ip;
462 if (!server_hostname.empty() && 416 if (!server_hostname.empty() &&
463 !ParseIPLiteralToNumber(server_hostname, &ip)) { 417 !ParseIPLiteralToNumber(server_hostname, &ip)) {
464 out->SetStringPiece(kSNI, server_hostname); 418 out->SetStringPiece(kSNI, server_hostname);
465 } 419 }
466 out->SetValue(kVERS, version); 420 out->SetValue(kVERS, version);
467 421
468 if (cached && !cached->source_address_token().empty()) { 422 if (cached && !cached->source_address_token().empty()) {
469 out->SetStringPiece(kSRCT, cached->source_address_token()); 423 out->SetStringPiece(kSRCT, cached->source_address_token());
470 } 424 }
425
426 out->SetTaglist(kPDMD, kX509, 0);
471 } 427 }
472 428
473 QuicErrorCode QuicCryptoClientConfig::FillClientHello( 429 QuicErrorCode QuicCryptoClientConfig::FillClientHello(
474 const string& server_hostname, 430 const string& server_hostname,
475 QuicGuid guid, 431 QuicGuid guid,
476 const CachedState* cached, 432 const CachedState* cached,
477 const QuicClock* clock, 433 const QuicClock* clock,
478 QuicRandom* rand, 434 QuicRandom* rand,
479 QuicCryptoNegotiatedParameters* out_params, 435 QuicCryptoNegotiatedParameters* out_params,
480 CryptoHandshakeMessage* out, 436 CryptoHandshakeMessage* out,
481 string* error_details) const { 437 string* error_details) const {
438 DCHECK(error_details != NULL);
439
482 FillInchoateClientHello(server_hostname, cached, out); 440 FillInchoateClientHello(server_hostname, cached, out);
483 441
484 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); 442 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
485 if (!scfg) { 443 if (!scfg) {
486 // This should never happen as our caller should have checked 444 // This should never happen as our caller should have checked
487 // cached->is_complete() before calling this function. 445 // cached->is_complete() before calling this function.
488 if (error_details) { 446 *error_details = "Handshake not ready";
489 *error_details = "Handshake not ready";
490 }
491 return QUIC_CRYPTO_INTERNAL_ERROR; 447 return QUIC_CRYPTO_INTERNAL_ERROR;
492 } 448 }
493 449
494 StringPiece scid; 450 StringPiece scid;
495 if (!scfg->GetStringPiece(kSCID, &scid)) { 451 if (!scfg->GetStringPiece(kSCID, &scid)) {
496 if (error_details) { 452 *error_details = "SCFG missing SCID";
497 *error_details = "SCFG missing SCID";
498 }
499 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 453 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
500 } 454 }
501 out->SetStringPiece(kSCID, scid); 455 out->SetStringPiece(kSCID, scid);
502 456
503 // Calculate the mutual algorithms that the connection is going to use. 457 // Calculate the mutual algorithms that the connection is going to use.
504 if (scfg->GetUint16(kVERS, &out_params->version) != QUIC_NO_ERROR || 458 if (scfg->GetUint16(kVERS, &out_params->version) != QUIC_NO_ERROR ||
505 out_params->version != kVersion) { 459 out_params->version != QuicCryptoConfig::CONFIG_VERSION) {
506 if (error_details) { 460 *error_details = "Bad version";
507 *error_details = "Bad version"; 461 return QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
508 }
509 return QUIC_VERSION_NOT_SUPPORTED;
510 } 462 }
511 463
512 const CryptoTag* their_aeads; 464 const CryptoTag* their_aeads;
513 const CryptoTag* their_key_exchanges; 465 const CryptoTag* their_key_exchanges;
514 size_t num_their_aeads, num_their_key_exchanges; 466 size_t num_their_aeads, num_their_key_exchanges;
515 if (scfg->GetTaglist(kAEAD, &their_aeads, 467 if (scfg->GetTaglist(kAEAD, &their_aeads,
516 &num_their_aeads) != QUIC_NO_ERROR || 468 &num_their_aeads) != QUIC_NO_ERROR ||
517 scfg->GetTaglist(kKEXS, &their_key_exchanges, 469 scfg->GetTaglist(kKEXS, &their_key_exchanges,
518 &num_their_key_exchanges) != QUIC_NO_ERROR) { 470 &num_their_key_exchanges) != QUIC_NO_ERROR) {
519 if (error_details) { 471 *error_details = "Missing AEAD or KEXS";
520 *error_details = "Missing AEAD or KEXS";
521 }
522 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 472 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
523 } 473 }
524 474
525 size_t key_exchange_index; 475 size_t key_exchange_index;
526 if (!CryptoUtils::FindMutualTag(aead, 476 if (!CryptoUtils::FindMutualTag(aead,
527 their_aeads, num_their_aeads, 477 their_aeads, num_their_aeads,
528 CryptoUtils::PEER_PRIORITY, 478 CryptoUtils::PEER_PRIORITY,
529 &out_params->aead, 479 &out_params->aead,
530 NULL) || 480 NULL) ||
531 !CryptoUtils::FindMutualTag(kexs, 481 !CryptoUtils::FindMutualTag(kexs,
532 their_key_exchanges, num_their_key_exchanges, 482 their_key_exchanges, num_their_key_exchanges,
533 CryptoUtils::PEER_PRIORITY, 483 CryptoUtils::PEER_PRIORITY,
534 &out_params->key_exchange, 484 &out_params->key_exchange,
535 &key_exchange_index)) { 485 &key_exchange_index)) {
536 if (error_details) { 486 *error_details = "Unsupported AEAD or KEXS";
537 *error_details = "Unsupported AEAD or KEXS";
538 }
539 return QUIC_CRYPTO_NO_SUPPORT; 487 return QUIC_CRYPTO_NO_SUPPORT;
540 } 488 }
541 out->SetTaglist(kAEAD, out_params->aead, 0); 489 out->SetTaglist(kAEAD, out_params->aead, 0);
542 out->SetTaglist(kKEXS, out_params->key_exchange, 0); 490 out->SetTaglist(kKEXS, out_params->key_exchange, 0);
543 491
544 StringPiece public_value; 492 StringPiece public_value;
545 if (scfg->GetNthValue16(kPUBS, key_exchange_index, &public_value) != 493 if (scfg->GetNthValue16(kPUBS, key_exchange_index, &public_value) !=
546 QUIC_NO_ERROR) { 494 QUIC_NO_ERROR) {
547 if (error_details) { 495 *error_details = "Missing public value";
548 *error_details = "Missing public value";
549 }
550 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 496 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
551 } 497 }
552 498
553 StringPiece orbit; 499 StringPiece orbit;
554 if (!scfg->GetStringPiece(kORBT, &orbit) || 500 if (!scfg->GetStringPiece(kORBT, &orbit) ||
555 orbit.size() != kOrbitSize) { 501 orbit.size() != kOrbitSize) {
556 if (error_details) { 502 *error_details = "SCFG missing OBIT";
557 *error_details = "SCFG missing OBIT";
558 }
559 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 503 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
560 } 504 }
561 505
562 string nonce; 506 string nonce;
563 CryptoUtils::GenerateNonce(clock->NowAsDeltaSinceUnixEpoch(), rand, orbit, 507 CryptoUtils::GenerateNonce(clock->NowAsDeltaSinceUnixEpoch(), rand, orbit,
564 &nonce); 508 &nonce);
565 out->SetStringPiece(kNONC, nonce); 509 out->SetStringPiece(kNONC, nonce);
566 510
567 scoped_ptr<KeyExchange> key_exchange; 511 scoped_ptr<KeyExchange> key_exchange;
568 switch (out_params->key_exchange) { 512 switch (out_params->key_exchange) {
569 case kC255: 513 case kC255:
570 key_exchange.reset(Curve25519KeyExchange::New( 514 key_exchange.reset(Curve25519KeyExchange::New(
571 Curve25519KeyExchange::NewPrivateKey(rand))); 515 Curve25519KeyExchange::NewPrivateKey(rand)));
572 break; 516 break;
573 case kP256: 517 case kP256:
574 key_exchange.reset(P256KeyExchange::New( 518 key_exchange.reset(P256KeyExchange::New(
575 P256KeyExchange::NewPrivateKey())); 519 P256KeyExchange::NewPrivateKey()));
576 break; 520 break;
577 default: 521 default:
578 DCHECK(false); 522 DCHECK(false);
579 if (error_details) { 523 *error_details = "Configured to support an unknown key exchange";
580 *error_details = "Configured to support an unknown key exchange";
581 }
582 return QUIC_CRYPTO_INTERNAL_ERROR; 524 return QUIC_CRYPTO_INTERNAL_ERROR;
583 } 525 }
584 526
585 if (!key_exchange->CalculateSharedKey(public_value, 527 if (!key_exchange->CalculateSharedKey(public_value,
586 &out_params->premaster_secret)) { 528 &out_params->premaster_secret)) {
587 if (error_details) { 529 *error_details = "Key exchange failure";
588 *error_details = "Key exchange failure";
589 }
590 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 530 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
591 } 531 }
592 out->SetStringPiece(kPUBS, key_exchange->public_value()); 532 out->SetStringPiece(kPUBS, key_exchange->public_value());
593 533
594 string hkdf_input(kLabel, arraysize(kLabel)); 534 string hkdf_input(QuicCryptoConfig::kLabel,
535 strlen(QuicCryptoConfig::kLabel) + 1);
595 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid)); 536 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
596 537
597 const QuicData& client_hello_serialized = out->GetSerialized(); 538 const QuicData& client_hello_serialized = out->GetSerialized();
598 hkdf_input.append(client_hello_serialized.data(), 539 hkdf_input.append(client_hello_serialized.data(),
599 client_hello_serialized.length()); 540 client_hello_serialized.length());
600 hkdf_input.append(cached->server_config()); 541 hkdf_input.append(cached->server_config());
601 542
602 CryptoUtils::DeriveKeys(out_params, nonce, hkdf_input, CryptoUtils::CLIENT); 543 CryptoUtils::DeriveKeys(out_params, nonce, hkdf_input, CryptoUtils::CLIENT);
603 544
604 return QUIC_NO_ERROR; 545 return QUIC_NO_ERROR;
605 } 546 }
606 547
607 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( 548 QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
608 const string& server_hostname, 549 const string& server_hostname,
609 const CryptoHandshakeMessage& rej, 550 const CryptoHandshakeMessage& rej,
610 QuicCryptoNegotiatedParameters* out_params, 551 QuicCryptoNegotiatedParameters* out_params,
611 string* error_details) { 552 string* error_details) {
553 DCHECK(error_details != NULL);
554
612 CachedState* cached; 555 CachedState* cached;
613
614 map<string, CachedState*>::const_iterator it = 556 map<string, CachedState*>::const_iterator it =
615 cached_states_.find(server_hostname); 557 cached_states_.find(server_hostname);
616 if (it == cached_states_.end()) { 558 if (it == cached_states_.end()) {
617 cached = new CachedState; 559 cached = new CachedState;
618 cached_states_[server_hostname] = cached; 560 cached_states_[server_hostname] = cached;
619 } else { 561 } else {
620 cached = it->second; 562 cached = it->second;
621 } 563 }
622 564
623 StringPiece scfg; 565 StringPiece scfg;
624 if (!rej.GetStringPiece(kSCFG, &scfg)) { 566 if (!rej.GetStringPiece(kSCFG, &scfg)) {
625 if (error_details) { 567 *error_details = "Missing SCFG";
626 *error_details = "Missing SCFG";
627 }
628 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 568 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
629 } 569 }
630 570
631 if (!cached->SetServerConfig(scfg)) { 571 if (!cached->SetServerConfig(scfg)) {
632 if (error_details) { 572 *error_details = "Invalid SCFG";
633 *error_details = "Invalid SCFG";
634 }
635 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 573 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
636 } 574 }
637 575
638 StringPiece token; 576 StringPiece token;
639 if (rej.GetStringPiece(kSRCT, &token)) { 577 if (rej.GetStringPiece(kSRCT, &token)) {
640 cached->set_source_address_token(token); 578 cached->set_source_address_token(token);
641 } 579 }
642 580
643 StringPiece nonce; 581 StringPiece nonce;
644 if (rej.GetStringPiece(kNONC, &nonce) && 582 if (rej.GetStringPiece(kNONC, &nonce) &&
645 nonce.size() == kNonceSize) { 583 nonce.size() == kNonceSize) {
646 out_params->server_nonce = nonce.as_string(); 584 out_params->server_nonce = nonce.as_string();
647 } 585 }
648 586
649 return QUIC_NO_ERROR; 587 return QUIC_NO_ERROR;
650 } 588 }
651 589
652 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( 590 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
653 const CryptoHandshakeMessage& server_hello, 591 const CryptoHandshakeMessage& server_hello,
654 const string& nonce, 592 const string& nonce,
655 QuicCryptoNegotiatedParameters* out_params, 593 QuicCryptoNegotiatedParameters* out_params,
656 string* error_details) { 594 string* error_details) {
595 DCHECK(error_details != NULL);
596
657 if (server_hello.tag() != kSHLO) { 597 if (server_hello.tag() != kSHLO) {
658 *error_details = "Bad tag"; 598 *error_details = "Bad tag";
659 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; 599 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
660 } 600 }
661 601
662 // TODO(agl): 602 // TODO(agl):
663 // learn about updated SCFGs. 603 // learn about updated SCFGs.
664 // read ephemeral public value for forward-secret keys. 604 // read ephemeral public value for forward-secret keys.
665 605
666 return QUIC_NO_ERROR; 606 return QUIC_NO_ERROR;
667 } 607 }
668 608
669 // static
670 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
671
672 QuicCryptoServerConfig::QuicCryptoServerConfig(
673 StringPiece source_address_token_secret)
674 // AES-GCM is used to encrypt and authenticate source address tokens. The
675 // full, 96-bit nonce is used but we must ensure that an attacker cannot
676 // obtain two source address tokens with the same nonce. This occurs with
677 // probability 0.5 after 2**48 values. We assume that obtaining 2**48
678 // source address tokens is not possible: at a rate of 10M packets per
679 // second, it would still take the attacker a year to obtain the needed
680 // number of packets.
681 //
682 // TODO(agl): switch to an encrypter with a larger nonce space (i.e.
683 // Salsa20+Poly1305).
684 : strike_register_lock_(),
685 source_address_token_encrypter_(new Aes128GcmEncrypter),
686 source_address_token_decrypter_(new Aes128GcmDecrypter) {
687 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */,
688 "QUIC source address token key",
689 source_address_token_encrypter_->GetKeySize(),
690 0 /* no fixed IV needed */);
691 source_address_token_encrypter_->SetKey(hkdf.server_write_key());
692 source_address_token_decrypter_->SetKey(hkdf.server_write_key());
693 }
694
695 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
696 STLDeleteValues(&configs_);
697 }
698
699 // static
700 QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
701 QuicRandom* rand,
702 const QuicClock* clock,
703 const CryptoHandshakeMessage& extra_tags) {
704 CryptoHandshakeMessage msg;
705
706 const string curve25519_private_key =
707 Curve25519KeyExchange::NewPrivateKey(rand);
708 scoped_ptr<Curve25519KeyExchange> curve25519(
709 Curve25519KeyExchange::New(curve25519_private_key));
710 StringPiece curve25519_public_value = curve25519->public_value();
711
712 const string p256_private_key =
713 P256KeyExchange::NewPrivateKey();
714 scoped_ptr<P256KeyExchange> p256(
715 P256KeyExchange::New(p256_private_key));
716 StringPiece p256_public_value = p256->public_value();
717
718 string encoded_public_values;
719 // First two bytes encode the length of the public value.
720 encoded_public_values.push_back(curve25519_public_value.size());
721 encoded_public_values.push_back(curve25519_public_value.size() >> 8);
722 encoded_public_values.append(curve25519_public_value.data(),
723 curve25519_public_value.size());
724 encoded_public_values.push_back(p256_public_value.size());
725 encoded_public_values.push_back(p256_public_value.size() >> 8);
726 encoded_public_values.append(p256_public_value.data(),
727 p256_public_value.size());
728
729 msg.set_tag(kSCFG);
730 msg.SetTaglist(kKEXS, kC255, kP256, 0);
731 msg.SetTaglist(kAEAD, kAESG, 0);
732 msg.SetValue(kVERS, static_cast<uint16>(0));
733 msg.SetStringPiece(kPUBS, encoded_public_values);
734 msg.Insert(extra_tags.tag_value_map().begin(),
735 extra_tags.tag_value_map().end());
736
737 char scid_bytes[16];
738 rand->RandBytes(scid_bytes, sizeof(scid_bytes));
739 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
740
741 char orbit_bytes[kOrbitSize];
742 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
743 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
744
745 scoped_ptr<QuicData> serialized(
746 CryptoFramer::ConstructHandshakeMessage(msg));
747
748 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
749 config->set_config(serialized->AsStringPiece());
750 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
751 curve25519_key->set_tag(kC255);
752 curve25519_key->set_private_key(curve25519_private_key);
753 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
754 p256_key->set_tag(kP256);
755 p256_key->set_private_key(p256_private_key);
756
757 return config.release();
758 }
759
760 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
761 QuicServerConfigProtobuf* protobuf) {
762 scoped_ptr<CryptoHandshakeMessage> msg(
763 CryptoFramer::ParseMessage(protobuf->config()));
764
765 if (!msg.get()) {
766 LOG(WARNING) << "Failed to parse server config message";
767 return NULL;
768 }
769 if (msg->tag() != kSCFG) {
770 LOG(WARNING) << "Server config message has tag "
771 << msg->tag() << " expected "
772 << kSCFG;
773 return NULL;
774 }
775
776 scoped_ptr<Config> config(new Config);
777 config->serialized = protobuf->config();
778
779 StringPiece scid;
780 if (!msg->GetStringPiece(kSCID, &scid)) {
781 LOG(WARNING) << "Server config message is missing SCID";
782 return NULL;
783 }
784 config->id = scid.as_string();
785
786 const CryptoTag* aead_tags;
787 size_t aead_len;
788 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
789 LOG(WARNING) << "Server config message is missing AEAD";
790 return NULL;
791 }
792 config->aead = vector<CryptoTag>(aead_tags, aead_tags + aead_len);
793
794 const CryptoTag* kexs_tags;
795 size_t kexs_len;
796 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
797 LOG(WARNING) << "Server config message is missing KEXS";
798 return NULL;
799 }
800
801 StringPiece orbit;
802 if (!msg->GetStringPiece(kORBT, &orbit)) {
803 LOG(WARNING) << "Server config message is missing OBIT";
804 return NULL;
805 }
806
807 if (orbit.size() != kOrbitSize) {
808 LOG(WARNING) << "Orbit value in server config is the wrong length."
809 " Got " << orbit.size() << " want " << kOrbitSize;
810 return NULL;
811 }
812 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size);
813 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
814
815 if (kexs_len != protobuf->key_size()) {
816 LOG(WARNING) << "Server config has "
817 << kexs_len
818 << " key exchange methods configured, but "
819 << protobuf->key_size()
820 << " private keys";
821 return NULL;
822 }
823
824 for (size_t i = 0; i < kexs_len; i++) {
825 const CryptoTag tag = kexs_tags[i];
826 string private_key;
827
828 config->kexs.push_back(tag);
829
830 for (size_t j = 0; j < protobuf->key_size(); j++) {
831 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
832 if (key.tag() == tag) {
833 private_key = key.private_key();
834 break;
835 }
836 }
837
838 if (private_key.empty()) {
839 LOG(WARNING) << "Server config contains key exchange method without "
840 "corresponding private key: "
841 << tag;
842 return NULL;
843 }
844
845 scoped_ptr<KeyExchange> ka;
846 switch (tag) {
847 case kC255:
848 ka.reset(Curve25519KeyExchange::New(private_key));
849 if (!ka.get()) {
850 LOG(WARNING) << "Server config contained an invalid curve25519"
851 " private key.";
852 return NULL;
853 }
854 break;
855 case kP256:
856 ka.reset(P256KeyExchange::New(private_key));
857 if (!ka.get()) {
858 LOG(WARNING) << "Server config contained an invalid P-256"
859 " private key.";
860 return NULL;
861 }
862 break;
863 default:
864 LOG(WARNING) << "Server config message contains unknown key exchange "
865 "method: "
866 << tag;
867 return NULL;
868 }
869
870 for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin();
871 i != config->key_exchanges.end(); ++i) {
872 if ((*i)->tag() == tag) {
873 LOG(WARNING) << "Duplicate key exchange in config: " << tag;
874 return NULL;
875 }
876 }
877
878 config->key_exchanges.push_back(ka.release());
879 }
880
881 if (msg->GetUint16(kVERS, &config->version) != QUIC_NO_ERROR) {
882 LOG(WARNING) << "Server config message is missing version";
883 return NULL;
884 }
885
886 if (config->version != kVersion) {
887 LOG(WARNING) << "Server config specifies an unsupported version";
888 return NULL;
889 }
890
891 scoped_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256));
892 sha256->Update(protobuf->config().data(), protobuf->config().size());
893 char id_bytes[16];
894 sha256->Finish(id_bytes, sizeof(id_bytes));
895 const string id(id_bytes, sizeof(id_bytes));
896
897 configs_[id] = config.release();
898 active_config_ = id;
899
900 return msg.release();
901 }
902
903 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
904 QuicRandom* rand,
905 const QuicClock* clock,
906 const CryptoHandshakeMessage& extra_tags) {
907 scoped_ptr<QuicServerConfigProtobuf> config(DefaultConfig(
908 rand, clock, extra_tags));
909 return AddConfig(config.get());
910 }
911
912 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
913 const CryptoHandshakeMessage& client_hello,
914 QuicGuid guid,
915 const IPEndPoint& client_ip,
916 QuicTime::Delta now_since_unix_epoch,
917 QuicRandom* rand,
918 QuicCryptoNegotiatedParameters *params,
919 CryptoHandshakeMessage* out,
920 string* error_details) const {
921 CHECK(!configs_.empty());
922 // FIXME(agl): we should use the client's SCID, not just the active config.
923 map<ServerConfigID, Config*>::const_iterator it =
924 configs_.find(active_config_);
925 if (it == configs_.end()) {
926 *error_details = "No valid server config loaded";
927 return QUIC_CRYPTO_INTERNAL_ERROR;
928 }
929 const Config* const config(it->second);
930
931 bool valid_source_address_token = false;
932 StringPiece srct;
933 if (client_hello.GetStringPiece(kSRCT, &srct) &&
934 ValidateSourceAddressToken(srct, client_ip, now_since_unix_epoch)) {
935 valid_source_address_token = true;
936 }
937
938 const string fresh_source_address_token =
939 NewSourceAddressToken(client_ip, rand, now_since_unix_epoch);
940
941 // If we previously sent a REJ to this client then we may have stored a
942 // server nonce in |params|. In which case, we know that the connection
943 // is unique because the server nonce will be mixed into the key generation.
944 bool unique_by_server_nonce = !params->server_nonce.empty();
945 // If we can't ensure uniqueness by a server nonce, then we will try and use
946 // the strike register.
947 bool unique_by_strike_register = false;
948
949 StringPiece client_nonce;
950 bool client_nonce_well_formed = false;
951 if (client_hello.GetStringPiece(kNONC, &client_nonce) &&
952 client_nonce.size() == kNonceSize) {
953 client_nonce_well_formed = true;
954 if (!unique_by_server_nonce) {
955 base::AutoLock auto_lock(strike_register_lock_);
956
957 if (strike_register_.get() == NULL) {
958 strike_register_.reset(new StrikeRegister(
959 // TODO(agl): these magic numbers should come from config.
960 1024 /* max entries */,
961 static_cast<uint32>(now_since_unix_epoch.ToSeconds()),
962 600 /* window secs */, config->orbit));
963 }
964 unique_by_strike_register = strike_register_->Insert(
965 reinterpret_cast<const uint8*>(client_nonce.data()),
966 static_cast<uint32>(now_since_unix_epoch.ToSeconds()));
967 }
968 }
969
970 StringPiece scid;
971 if (!client_hello.GetStringPiece(kSCID, &scid) ||
972 scid.as_string() != config->id ||
973 !valid_source_address_token ||
974 !client_nonce_well_formed ||
975 (!unique_by_strike_register &&
976 !unique_by_server_nonce)) {
977 // If the client didn't provide a server config ID, or gave the wrong one,
978 // then the handshake cannot possibly complete. We reject the handshake and
979 // give the client enough information to do better next time.
980 out->Clear();
981 out->set_tag(kREJ);
982 out->SetStringPiece(kSCFG, config->serialized);
983 out->SetStringPiece(kSRCT, fresh_source_address_token);
984 if (params->server_nonce.empty()) {
985 CryptoUtils::GenerateNonce(
986 now_since_unix_epoch, rand,
987 StringPiece(reinterpret_cast<const char*>(config->orbit),
988 sizeof(config->orbit)),
989 &params->server_nonce);
990 }
991 out->SetStringPiece(kNONC, params->server_nonce);
992 return QUIC_NO_ERROR;
993 }
994
995 const CryptoTag* their_aeads;
996 const CryptoTag* their_key_exchanges;
997 size_t num_their_aeads, num_their_key_exchanges;
998 if (client_hello.GetTaglist(kAEAD, &their_aeads,
999 &num_their_aeads) != QUIC_NO_ERROR ||
1000 client_hello.GetTaglist(kKEXS, &their_key_exchanges,
1001 &num_their_key_exchanges) != QUIC_NO_ERROR ||
1002 num_their_aeads != 1 ||
1003 num_their_key_exchanges != 1) {
1004 if (error_details) {
1005 *error_details = "Missing or invalid AEAD or KEXS";
1006 }
1007 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
1008 }
1009
1010 size_t key_exchange_index;
1011 if (!CryptoUtils::FindMutualTag(config->aead,
1012 their_aeads, num_their_aeads,
1013 CryptoUtils::LOCAL_PRIORITY,
1014 &params->aead,
1015 NULL) ||
1016 !CryptoUtils::FindMutualTag(config->kexs,
1017 their_key_exchanges, num_their_key_exchanges,
1018 CryptoUtils::LOCAL_PRIORITY,
1019 &params->key_exchange,
1020 &key_exchange_index)) {
1021 if (error_details) {
1022 *error_details = "Unsupported AEAD or KEXS";
1023 }
1024 return QUIC_CRYPTO_NO_SUPPORT;
1025 }
1026
1027 StringPiece public_value;
1028 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
1029 if (error_details) {
1030 *error_details = "Missing public value";
1031 }
1032 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
1033 }
1034
1035 if (!config->key_exchanges[key_exchange_index]->CalculateSharedKey(
1036 public_value, &params->premaster_secret)) {
1037 if (error_details) {
1038 *error_details = "Invalid public value";
1039 }
1040 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
1041 }
1042
1043 params->server_config_id = scid.as_string();
1044
1045 string hkdf_input(kLabel, arraysize(kLabel));
1046 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
1047
1048 const QuicData& client_hello_serialized = client_hello.GetSerialized();
1049 hkdf_input.append(client_hello_serialized.data(),
1050 client_hello_serialized.length());
1051 hkdf_input.append(config->serialized);
1052
1053 CryptoUtils::DeriveKeys(params, client_nonce, hkdf_input,
1054 CryptoUtils::SERVER);
1055
1056 out->set_tag(kSHLO);
1057 out->SetStringPiece(kSRCT, fresh_source_address_token);
1058 return QUIC_NO_ERROR;
1059 }
1060
1061 string QuicCryptoServerConfig::NewSourceAddressToken(
1062 const IPEndPoint& ip,
1063 QuicRandom* rand,
1064 QuicTime::Delta now_since_epoch) const {
1065 SourceAddressToken source_address_token;
1066 source_address_token.set_ip(ip.ToString());
1067 source_address_token.set_timestamp(now_since_epoch.ToSeconds());
1068
1069 string plaintext = source_address_token.SerializeAsString();
1070 char nonce[12];
1071 DCHECK_EQ(sizeof(nonce),
1072 source_address_token_encrypter_->GetNoncePrefixSize() +
1073 sizeof(QuicPacketSequenceNumber));
1074 rand->RandBytes(nonce, sizeof(nonce));
1075
1076 size_t ciphertext_size =
1077 source_address_token_encrypter_->GetCiphertextSize(plaintext.size());
1078 string result;
1079 result.resize(sizeof(nonce) + ciphertext_size);
1080 memcpy(&result[0], &nonce, sizeof(nonce));
1081
1082 if (!source_address_token_encrypter_->Encrypt(
1083 StringPiece(nonce, sizeof(nonce)), StringPiece(), plaintext,
1084 reinterpret_cast<unsigned char*>(&result[sizeof(nonce)]))) {
1085 DCHECK(false);
1086 return string();
1087 }
1088
1089 return result;
1090 }
1091
1092 bool QuicCryptoServerConfig::ValidateSourceAddressToken(
1093 StringPiece token,
1094 const IPEndPoint& ip,
1095 QuicTime::Delta now_since_epoch) const {
1096 char nonce[12];
1097 DCHECK_EQ(sizeof(nonce),
1098 source_address_token_encrypter_->GetNoncePrefixSize() +
1099 sizeof(QuicPacketSequenceNumber));
1100
1101 if (token.size() <= sizeof(nonce)) {
1102 return false;
1103 }
1104 memcpy(&nonce, token.data(), sizeof(nonce));
1105 token.remove_prefix(sizeof(nonce));
1106
1107 unsigned char plaintext_stack[128];
1108 scoped_ptr<unsigned char[]> plaintext_heap;
1109 unsigned char* plaintext;
1110 if (token.size() <= sizeof(plaintext_stack)) {
1111 plaintext = plaintext_stack;
1112 } else {
1113 plaintext_heap.reset(new unsigned char[token.size()]);
1114 plaintext = plaintext_heap.get();
1115 }
1116 size_t plaintext_length;
1117
1118 if (!source_address_token_decrypter_->Decrypt(
1119 StringPiece(nonce, sizeof(nonce)), StringPiece(), token,
1120 plaintext, &plaintext_length)) {
1121 return false;
1122 }
1123
1124 SourceAddressToken source_address_token;
1125 if (!source_address_token.ParseFromArray(plaintext, plaintext_length)) {
1126 return false;
1127 }
1128
1129 if (source_address_token.ip() != ip.ToString()) {
1130 // It's for a different IP address.
1131 return false;
1132 }
1133
1134 const QuicTime::Delta delta(now_since_epoch.Subtract(
1135 QuicTime::Delta::FromSeconds(source_address_token.timestamp())));
1136 const int64 delta_secs = delta.ToSeconds();
1137
1138 // TODO(agl): consider whether and how these magic values should be moved to
1139 // a config.
1140 if (delta_secs < -3600) {
1141 // We only allow timestamps to be from an hour in the future.
1142 return false;
1143 }
1144
1145 if (delta_secs > 86400) {
1146 // We allow one day into the past.
1147 return false;
1148 }
1149
1150 return true;
1151 }
1152
1153 QuicCryptoServerConfig::Config::Config() {
1154 }
1155
1156 QuicCryptoServerConfig::Config::~Config() {
1157 STLDeleteElements(&key_exchanges);
1158 }
1159
1160 } // namespace net 609 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698