| 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/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 Loading... |
| 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 Loading... |
| 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], ×tamp)) { | |
| 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 Loading... |
| 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 Loading... |
| 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 ¶ms->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 ¶ms->aead, | |
| 1015 NULL) || | |
| 1016 !CryptoUtils::FindMutualTag(config->kexs, | |
| 1017 their_key_exchanges, num_their_key_exchanges, | |
| 1018 CryptoUtils::LOCAL_PRIORITY, | |
| 1019 ¶ms->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, ¶ms->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 |
| OLD | NEW |