OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |