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

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

Issue 14287009: Land Recent QUIC Changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Merge with Tot 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
« no previous file with comments | « net/quic/crypto/crypto_handshake.h ('k') | net/quic/crypto/crypto_protocol.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_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/secure_hash.h" 13 #include "crypto/secure_hash.h"
14 #include "net/base/net_util.h" 14 #include "net/base/net_util.h"
15 #include "net/quic/crypto/crypto_framer.h" 15 #include "net/quic/crypto/crypto_framer.h"
16 #include "net/quic/crypto/crypto_utils.h" 16 #include "net/quic/crypto/crypto_utils.h"
17 #include "net/quic/crypto/curve25519_key_exchange.h" 17 #include "net/quic/crypto/curve25519_key_exchange.h"
18 #include "net/quic/crypto/key_exchange.h" 18 #include "net/quic/crypto/key_exchange.h"
19 #include "net/quic/crypto/p256_key_exchange.h" 19 #include "net/quic/crypto/p256_key_exchange.h"
20 #include "net/quic/crypto/proof_verifier.h"
20 #include "net/quic/crypto/quic_decrypter.h" 21 #include "net/quic/crypto/quic_decrypter.h"
21 #include "net/quic/crypto/quic_encrypter.h" 22 #include "net/quic/crypto/quic_encrypter.h"
22 #include "net/quic/crypto/quic_random.h" 23 #include "net/quic/crypto/quic_random.h"
23 #include "net/quic/quic_clock.h" 24 #include "net/quic/quic_clock.h"
24 #include "net/quic/quic_protocol.h" 25 #include "net/quic/quic_protocol.h"
25 26
26 using base::StringPiece; 27 using base::StringPiece;
27 using crypto::SecureHash;
28 using std::map; 28 using std::map;
29 using std::string; 29 using std::string;
30 using std::vector; 30 using std::vector;
31 31
32 namespace net { 32 namespace net {
33 33
34 CryptoHandshakeMessage::CryptoHandshakeMessage() : tag_(0) {} 34 CryptoHandshakeMessage::CryptoHandshakeMessage() : tag_(0) {}
35 35
36 CryptoHandshakeMessage::CryptoHandshakeMessage( 36 CryptoHandshakeMessage::CryptoHandshakeMessage(
37 const CryptoHandshakeMessage& other) 37 const CryptoHandshakeMessage& other)
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 } 90 }
91 91
92 // Because of the way that we keep tags in memory, we can copy the contents 92 // Because of the way that we keep tags in memory, we can copy the contents
93 // of the vector and get the correct bytes in wire format. See 93 // of the vector and get the correct bytes in wire format. See
94 // crypto_protocol.h. This assumes that the system is little-endian. 94 // crypto_protocol.h. This assumes that the system is little-endian.
95 SetVector(tag, tags); 95 SetVector(tag, tags);
96 96
97 va_end(ap); 97 va_end(ap);
98 } 98 }
99 99
100 void CryptoHandshakeMessage::SetStringPiece(CryptoTag tag, 100 void CryptoHandshakeMessage::SetStringPiece(CryptoTag tag, StringPiece value) {
101 StringPiece value) {
102 tag_value_map_[tag] = value.as_string(); 101 tag_value_map_[tag] = value.as_string();
103 } 102 }
104 103
105 QuicErrorCode CryptoHandshakeMessage::GetTaglist(CryptoTag tag, 104 QuicErrorCode CryptoHandshakeMessage::GetTaglist(CryptoTag tag,
106 const CryptoTag** out_tags, 105 const CryptoTag** out_tags,
107 size_t* out_len) const { 106 size_t* out_len) const {
108 CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag); 107 CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag);
109 QuicErrorCode ret = QUIC_NO_ERROR; 108 QuicErrorCode ret = QUIC_NO_ERROR;
110 109
111 if (it == tag_value_map_.end()) { 110 if (it == tag_value_map_.end()) {
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 } 313 }
315 314
316 315
317 // static 316 // static
318 const char QuicCryptoConfig::kLabel[] = "QUIC key expansion"; 317 const char QuicCryptoConfig::kLabel[] = "QUIC key expansion";
319 318
320 QuicCryptoConfig::QuicCryptoConfig() 319 QuicCryptoConfig::QuicCryptoConfig()
321 : version(0) { 320 : version(0) {
322 } 321 }
323 322
324 QuicCryptoConfig::~QuicCryptoConfig() { 323 QuicCryptoConfig::~QuicCryptoConfig() {}
325 }
326 324
327 325 QuicCryptoClientConfig::QuicCryptoClientConfig() {}
328 QuicCryptoClientConfig::QuicCryptoClientConfig() {
329 }
330 326
331 QuicCryptoClientConfig::~QuicCryptoClientConfig() { 327 QuicCryptoClientConfig::~QuicCryptoClientConfig() {
332 STLDeleteValues(&cached_states_); 328 STLDeleteValues(&cached_states_);
333 } 329 }
334 330
335 QuicCryptoClientConfig::CachedState::CachedState() { 331 QuicCryptoClientConfig::CachedState::CachedState()
336 } 332 : server_config_valid_(false) {}
337 333
338 QuicCryptoClientConfig::CachedState::~CachedState() { 334 QuicCryptoClientConfig::CachedState::~CachedState() {}
339 }
340 335
341 bool QuicCryptoClientConfig::CachedState::is_complete() const { 336 bool QuicCryptoClientConfig::CachedState::is_complete() const {
342 return !server_config_.empty(); 337 return !server_config_.empty() && server_config_valid_;
343 } 338 }
344 339
345 const CryptoHandshakeMessage* 340 const CryptoHandshakeMessage*
346 QuicCryptoClientConfig::CachedState::GetServerConfig() const { 341 QuicCryptoClientConfig::CachedState::GetServerConfig() const {
347 if (server_config_.empty()) { 342 if (server_config_.empty()) {
348 return NULL; 343 return NULL;
349 } 344 }
350 345
351 if (!scfg_.get()) { 346 if (!scfg_.get()) {
352 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); 347 scfg_.reset(CryptoFramer::ParseMessage(server_config_));
353 DCHECK(scfg_.get()); 348 DCHECK(scfg_.get());
354 } 349 }
355 return scfg_.get(); 350 return scfg_.get();
356 } 351 }
357 352
358 bool QuicCryptoClientConfig::CachedState::SetServerConfig( 353 bool QuicCryptoClientConfig::CachedState::SetServerConfig(
359 StringPiece scfg) { 354 StringPiece scfg) {
360 scfg_.reset(CryptoFramer::ParseMessage(scfg)); 355 scfg_.reset(CryptoFramer::ParseMessage(scfg));
361 if (!scfg_.get()) { 356 if (!scfg_.get()) {
362 return false; 357 return false;
363 } 358 }
364 server_config_ = scfg.as_string(); 359 server_config_ = scfg.as_string();
365 return true; 360 return true;
366 } 361 }
367 362
368 const string& QuicCryptoClientConfig::CachedState::server_config() 363 void QuicCryptoClientConfig::CachedState::SetProof(
369 const { 364 const vector<StringPiece>& certs, StringPiece signature) {
365 bool has_changed = signature != server_config_sig_;
366
367 if (certs.size() != certs_.size()) {
368 has_changed = true;
369 }
370 if (!has_changed) {
371 for (size_t i = 0; i < certs_.size(); i++) {
372 if (certs[i] != certs_[i]) {
373 has_changed = true;
374 break;
375 }
376 }
377 }
378
379 if (!has_changed) {
380 return;
381 }
382
383 // If the proof has changed then it needs to be revalidated.
384 server_config_valid_ = false;
385 certs_.clear();
386 for (vector<StringPiece>::const_iterator i = certs.begin();
387 i != certs.end(); ++i) {
388 certs_.push_back(i->as_string());
389 }
390 server_config_sig_ = signature.as_string();
391 }
392
393 void QuicCryptoClientConfig::CachedState::SetProofValid() {
394 server_config_valid_ = true;
395 }
396
397 const string&
398 QuicCryptoClientConfig::CachedState::server_config() const {
370 return server_config_; 399 return server_config_;
371 } 400 }
372 401
373 const string& QuicCryptoClientConfig::CachedState::source_address_token() 402 const string&
374 const { 403 QuicCryptoClientConfig::CachedState::source_address_token() const {
375 return source_address_token_; 404 return source_address_token_;
376 } 405 }
377 406
407 const vector<string>& QuicCryptoClientConfig::CachedState::certs() const {
408 return certs_;
409 }
410
411 const string& QuicCryptoClientConfig::CachedState::signature() const {
412 return server_config_sig_;
413 }
414
415 bool QuicCryptoClientConfig::CachedState::proof_valid() const {
416 return server_config_valid_;
417 }
418
378 void QuicCryptoClientConfig::CachedState::set_source_address_token( 419 void QuicCryptoClientConfig::CachedState::set_source_address_token(
379 StringPiece token) { 420 StringPiece token) {
380 source_address_token_ = token.as_string(); 421 source_address_token_ = token.as_string();
381 } 422 }
382 423
383 void QuicCryptoClientConfig::SetDefaults() { 424 void QuicCryptoClientConfig::SetDefaults() {
384 // Version must be 0. 425 // Version must be 0.
385 version = QuicCryptoConfig::CONFIG_VERSION; 426 version = QuicCryptoConfig::CONFIG_VERSION;
386 427
387 // Key exchange methods. 428 // Key exchange methods.
388 kexs.resize(2); 429 kexs.resize(2);
389 kexs[0] = kC255; 430 kexs[0] = kC255;
390 kexs[1] = kP256; 431 kexs[1] = kP256;
391 432
392 // Authenticated encryption algorithms. 433 // Authenticated encryption algorithms.
393 aead.resize(1); 434 aead.resize(1);
394 aead[0] = kAESG; 435 aead[0] = kAESG;
395 } 436 }
396 437
397 const QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::Lookup( 438 QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate(
398 const string& server_hostname) const { 439 const string& server_hostname) {
399 map<string, CachedState*>::const_iterator it = 440 map<string, CachedState*>::const_iterator it =
400 cached_states_.find(server_hostname); 441 cached_states_.find(server_hostname);
401 if (it == cached_states_.end()) { 442 if (it != cached_states_.end()) {
402 return NULL; 443 return it->second;
403 } 444 }
404 return it->second; 445
446 CachedState* cached = new CachedState;
447 cached_states_.insert(make_pair(server_hostname, cached));
448 return cached;
405 } 449 }
406 450
407 void QuicCryptoClientConfig::FillInchoateClientHello( 451 void QuicCryptoClientConfig::FillInchoateClientHello(
408 const string& server_hostname, 452 const string& server_hostname,
409 const CachedState* cached, 453 const CachedState* cached,
410 CryptoHandshakeMessage* out) const { 454 CryptoHandshakeMessage* out) const {
411 out->set_tag(kCHLO); 455 out->set_tag(kCHLO);
412 456
413 // Server name indication. 457 // Server name indication.
414 // If server_hostname is not an IP address literal, it is a DNS hostname. 458 // If server_hostname is not an IP address literal, it is a DNS hostname.
415 IPAddressNumber ip; 459 IPAddressNumber ip;
416 if (!server_hostname.empty() && 460 if (!server_hostname.empty() &&
417 !ParseIPLiteralToNumber(server_hostname, &ip)) { 461 !ParseIPLiteralToNumber(server_hostname, &ip)) {
418 out->SetStringPiece(kSNI, server_hostname); 462 out->SetStringPiece(kSNI, server_hostname);
419 } 463 }
420 out->SetValue(kVERS, version); 464 out->SetValue(kVERS, version);
421 465
422 if (cached && !cached->source_address_token().empty()) { 466 if (!cached->source_address_token().empty()) {
423 out->SetStringPiece(kSRCT, cached->source_address_token()); 467 out->SetStringPiece(kSRCT, cached->source_address_token());
424 } 468 }
425 469
426 out->SetTaglist(kPDMD, kX509, 0); 470 out->SetTaglist(kPDMD, kX509, 0);
427 } 471 }
428 472
429 QuicErrorCode QuicCryptoClientConfig::FillClientHello( 473 QuicErrorCode QuicCryptoClientConfig::FillClientHello(
430 const string& server_hostname, 474 const string& server_hostname,
431 QuicGuid guid, 475 QuicGuid guid,
432 const CachedState* cached, 476 const CachedState* cached,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 &out_params->key_exchange, 528 &out_params->key_exchange,
485 &key_exchange_index)) { 529 &key_exchange_index)) {
486 *error_details = "Unsupported AEAD or KEXS"; 530 *error_details = "Unsupported AEAD or KEXS";
487 return QUIC_CRYPTO_NO_SUPPORT; 531 return QUIC_CRYPTO_NO_SUPPORT;
488 } 532 }
489 out->SetTaglist(kAEAD, out_params->aead, 0); 533 out->SetTaglist(kAEAD, out_params->aead, 0);
490 out->SetTaglist(kKEXS, out_params->key_exchange, 0); 534 out->SetTaglist(kKEXS, out_params->key_exchange, 0);
491 535
492 StringPiece public_value; 536 StringPiece public_value;
493 if (scfg->GetNthValue16(kPUBS, key_exchange_index, &public_value) != 537 if (scfg->GetNthValue16(kPUBS, key_exchange_index, &public_value) !=
494 QUIC_NO_ERROR) { 538 QUIC_NO_ERROR) {
495 *error_details = "Missing public value"; 539 *error_details = "Missing public value";
496 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 540 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
497 } 541 }
498 542
499 StringPiece orbit; 543 StringPiece orbit;
500 if (!scfg->GetStringPiece(kORBT, &orbit) || 544 if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) {
501 orbit.size() != kOrbitSize) {
502 *error_details = "SCFG missing OBIT"; 545 *error_details = "SCFG missing OBIT";
503 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 546 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
504 } 547 }
505 548
506 string nonce; 549 string nonce;
507 CryptoUtils::GenerateNonce(clock->NowAsDeltaSinceUnixEpoch(), rand, orbit, 550 CryptoUtils::GenerateNonce(clock->NowAsDeltaSinceUnixEpoch(), rand, orbit,
508 &nonce); 551 &nonce);
509 out->SetStringPiece(kNONC, nonce); 552 out->SetStringPiece(kNONC, nonce);
510 553
511 scoped_ptr<KeyExchange> key_exchange; 554 scoped_ptr<KeyExchange> key_exchange;
(...skipping 27 matching lines...) Expand all
539 hkdf_input.append(client_hello_serialized.data(), 582 hkdf_input.append(client_hello_serialized.data(),
540 client_hello_serialized.length()); 583 client_hello_serialized.length());
541 hkdf_input.append(cached->server_config()); 584 hkdf_input.append(cached->server_config());
542 585
543 CryptoUtils::DeriveKeys(out_params, nonce, hkdf_input, CryptoUtils::CLIENT); 586 CryptoUtils::DeriveKeys(out_params, nonce, hkdf_input, CryptoUtils::CLIENT);
544 587
545 return QUIC_NO_ERROR; 588 return QUIC_NO_ERROR;
546 } 589 }
547 590
548 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( 591 QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
549 const string& server_hostname, 592 CachedState* cached,
550 const CryptoHandshakeMessage& rej, 593 const CryptoHandshakeMessage& rej,
551 QuicCryptoNegotiatedParameters* out_params, 594 QuicCryptoNegotiatedParameters* out_params,
552 string* error_details) { 595 string* error_details) {
553 DCHECK(error_details != NULL); 596 DCHECK(error_details != NULL);
554 597
555 CachedState* cached;
556 map<string, CachedState*>::const_iterator it =
557 cached_states_.find(server_hostname);
558 if (it == cached_states_.end()) {
559 cached = new CachedState;
560 cached_states_[server_hostname] = cached;
561 } else {
562 cached = it->second;
563 }
564
565 StringPiece scfg; 598 StringPiece scfg;
566 if (!rej.GetStringPiece(kSCFG, &scfg)) { 599 if (!rej.GetStringPiece(kSCFG, &scfg)) {
567 *error_details = "Missing SCFG"; 600 *error_details = "Missing SCFG";
568 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 601 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
569 } 602 }
570 603
571 if (!cached->SetServerConfig(scfg)) { 604 if (!cached->SetServerConfig(scfg)) {
572 *error_details = "Invalid SCFG"; 605 *error_details = "Invalid SCFG";
573 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 606 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
574 } 607 }
575 608
576 StringPiece token; 609 StringPiece token;
577 if (rej.GetStringPiece(kSRCT, &token)) { 610 if (rej.GetStringPiece(kSRCT, &token)) {
578 cached->set_source_address_token(token); 611 cached->set_source_address_token(token);
579 } 612 }
580 613
581 StringPiece nonce; 614 StringPiece nonce;
582 if (rej.GetStringPiece(kNONC, &nonce) && 615 if (rej.GetStringPiece(kNONC, &nonce) &&
583 nonce.size() == kNonceSize) { 616 nonce.size() == kNonceSize) {
584 out_params->server_nonce = nonce.as_string(); 617 out_params->server_nonce = nonce.as_string();
585 } 618 }
586 619
620 StringPiece proof, cert_bytes;
621 if (rej.GetStringPiece(kPROF, &proof) &&
622 rej.GetStringPiece(kCERT, &cert_bytes)) {
623 vector<StringPiece> certs;
624 while (!cert_bytes.empty()) {
625 if (cert_bytes.size() < 3) {
626 *error_details = "Certificate length truncated";
627 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
628 }
629 size_t len = static_cast<size_t>(cert_bytes[0]) |
630 static_cast<size_t>(cert_bytes[1]) << 8 |
631 static_cast<size_t>(cert_bytes[2]) << 16;
632 if (len == 0) {
633 *error_details = "Zero length certificate";
634 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
635 }
636 cert_bytes.remove_prefix(3);
637 if (cert_bytes.size() < len) {
638 *error_details = "Certificate truncated";
639 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
640 }
641 certs.push_back(StringPiece(cert_bytes.data(), len));
642 cert_bytes.remove_prefix(len);
643 }
644
645 cached->SetProof(certs, proof);
646 }
647
587 return QUIC_NO_ERROR; 648 return QUIC_NO_ERROR;
588 } 649 }
589 650
590 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( 651 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
591 const CryptoHandshakeMessage& server_hello, 652 const CryptoHandshakeMessage& server_hello,
592 const string& nonce, 653 const string& nonce,
593 QuicCryptoNegotiatedParameters* out_params, 654 QuicCryptoNegotiatedParameters* out_params,
594 string* error_details) { 655 string* error_details) {
595 DCHECK(error_details != NULL); 656 DCHECK(error_details != NULL);
596 657
597 if (server_hello.tag() != kSHLO) { 658 if (server_hello.tag() != kSHLO) {
598 *error_details = "Bad tag"; 659 *error_details = "Bad tag";
599 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; 660 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
600 } 661 }
601 662
602 // TODO(agl): 663 // TODO(agl):
603 // learn about updated SCFGs. 664 // learn about updated SCFGs.
604 // read ephemeral public value for forward-secret keys. 665 // read ephemeral public value for forward-secret keys.
605 666
606 return QUIC_NO_ERROR; 667 return QUIC_NO_ERROR;
607 } 668 }
608 669
670 const ProofVerifier* QuicCryptoClientConfig::proof_verifier() const {
671 return proof_verifier_.get();
672 }
673
674 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) {
675 proof_verifier_.reset(verifier);
676 }
677
609 } // namespace net 678 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/crypto_handshake.h ('k') | net/quic/crypto/crypto_protocol.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698