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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: net/quic/crypto/crypto_handshake.cc
diff --git a/net/quic/crypto/crypto_handshake.cc b/net/quic/crypto/crypto_handshake.cc
index 1d9b01b809f06d3c018d88ba7f726bb0a743c309..59ecd425e7972d4894428f718519d40422535c49 100644
--- a/net/quic/crypto/crypto_handshake.cc
+++ b/net/quic/crypto/crypto_handshake.cc
@@ -10,11 +10,8 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
-#include "crypto/hkdf.h"
#include "crypto/secure_hash.h"
#include "net/base/net_util.h"
-#include "net/quic/crypto/aes_128_gcm_decrypter.h"
-#include "net/quic/crypto/aes_128_gcm_encrypter.h"
#include "net/quic/crypto/crypto_framer.h"
#include "net/quic/crypto/crypto_utils.h"
#include "net/quic/crypto/curve25519_key_exchange.h"
@@ -23,7 +20,6 @@
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/quic_random.h"
-#include "net/quic/crypto/strike_register.h"
#include "net/quic/quic_clock.h"
#include "net/quic/quic_protocol.h"
@@ -35,23 +31,6 @@ using std::vector;
namespace net {
-// kVersion contains the one (and, for the moment, only) version number that we
-// implement.
-static const uint16 kVersion = 0;
-
-// kLabel is constant that is used in key derivation to tie the resulting key
-// to this protocol.
-static const char kLabel[] = "QUIC key expansion";
-
-using crypto::SecureHash;
-
-QuicServerConfigProtobuf::QuicServerConfigProtobuf() {
-}
-
-QuicServerConfigProtobuf::~QuicServerConfigProtobuf() {
- STLDeleteElements(&keys_);
-}
-
CryptoHandshakeMessage::CryptoHandshakeMessage() : tag_(0) {}
CryptoHandshakeMessage::CryptoHandshakeMessage(
@@ -284,6 +263,7 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
case kKEXS:
case kAEAD:
case kCGST:
+ case kPDMD:
// tag lists
if (it->second.size() % sizeof(CryptoTag) == 0) {
for (size_t j = 0; j < it->second.size(); j += sizeof(CryptoTag)) {
@@ -324,35 +304,6 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
return ret;
}
-SourceAddressToken::SourceAddressToken() {
-}
-
-SourceAddressToken::~SourceAddressToken() {
-}
-
-string SourceAddressToken::SerializeAsString() const {
- return ip_ + " " + base::Int64ToString(timestamp_);
-}
-
-bool SourceAddressToken::ParseFromArray(unsigned char* plaintext,
- size_t plaintext_length) {
- string data(reinterpret_cast<const char*>(plaintext), plaintext_length);
- std::vector<std::string> results;
- base::SplitString(data, ' ', &results);
- if (results.size() < 2) {
- return false;
- }
-
- int64 timestamp;
- if (!base::StringToInt64(results[1], &timestamp)) {
- return false;
- }
-
- ip_ = results[0];
- timestamp_ = timestamp;
- return true;
-}
-
QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters()
: version(0),
key_exchange(0),
@@ -363,6 +314,9 @@ QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {
}
+// static
+const char QuicCryptoConfig::kLabel[] = "QUIC key expansion";
+
QuicCryptoConfig::QuicCryptoConfig()
: version(0) {
}
@@ -428,7 +382,7 @@ void QuicCryptoClientConfig::CachedState::set_source_address_token(
void QuicCryptoClientConfig::SetDefaults() {
// Version must be 0.
- version = kVersion;
+ version = QuicCryptoConfig::CONFIG_VERSION;
// Key exchange methods.
kexs.resize(2);
@@ -468,6 +422,8 @@ void QuicCryptoClientConfig::FillInchoateClientHello(
if (cached && !cached->source_address_token().empty()) {
out->SetStringPiece(kSRCT, cached->source_address_token());
}
+
+ out->SetTaglist(kPDMD, kX509, 0);
}
QuicErrorCode QuicCryptoClientConfig::FillClientHello(
@@ -479,34 +435,30 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
QuicCryptoNegotiatedParameters* out_params,
CryptoHandshakeMessage* out,
string* error_details) const {
+ DCHECK(error_details != NULL);
+
FillInchoateClientHello(server_hostname, cached, out);
const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
if (!scfg) {
// This should never happen as our caller should have checked
// cached->is_complete() before calling this function.
- if (error_details) {
- *error_details = "Handshake not ready";
- }
+ *error_details = "Handshake not ready";
return QUIC_CRYPTO_INTERNAL_ERROR;
}
StringPiece scid;
if (!scfg->GetStringPiece(kSCID, &scid)) {
- if (error_details) {
- *error_details = "SCFG missing SCID";
- }
+ *error_details = "SCFG missing SCID";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
out->SetStringPiece(kSCID, scid);
// Calculate the mutual algorithms that the connection is going to use.
if (scfg->GetUint16(kVERS, &out_params->version) != QUIC_NO_ERROR ||
- out_params->version != kVersion) {
- if (error_details) {
- *error_details = "Bad version";
- }
- return QUIC_VERSION_NOT_SUPPORTED;
+ out_params->version != QuicCryptoConfig::CONFIG_VERSION) {
+ *error_details = "Bad version";
+ return QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
}
const CryptoTag* their_aeads;
@@ -516,9 +468,7 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
&num_their_aeads) != QUIC_NO_ERROR ||
scfg->GetTaglist(kKEXS, &their_key_exchanges,
&num_their_key_exchanges) != QUIC_NO_ERROR) {
- if (error_details) {
- *error_details = "Missing AEAD or KEXS";
- }
+ *error_details = "Missing AEAD or KEXS";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
@@ -533,9 +483,7 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
CryptoUtils::PEER_PRIORITY,
&out_params->key_exchange,
&key_exchange_index)) {
- if (error_details) {
- *error_details = "Unsupported AEAD or KEXS";
- }
+ *error_details = "Unsupported AEAD or KEXS";
return QUIC_CRYPTO_NO_SUPPORT;
}
out->SetTaglist(kAEAD, out_params->aead, 0);
@@ -544,18 +492,14 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
StringPiece public_value;
if (scfg->GetNthValue16(kPUBS, key_exchange_index, &public_value) !=
QUIC_NO_ERROR) {
- if (error_details) {
- *error_details = "Missing public value";
- }
+ *error_details = "Missing public value";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
StringPiece orbit;
if (!scfg->GetStringPiece(kORBT, &orbit) ||
orbit.size() != kOrbitSize) {
- if (error_details) {
- *error_details = "SCFG missing OBIT";
- }
+ *error_details = "SCFG missing OBIT";
return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
}
@@ -576,22 +520,19 @@ QuicErrorCode QuicCryptoClientConfig::FillClientHello(
break;
default:
DCHECK(false);
- if (error_details) {
- *error_details = "Configured to support an unknown key exchange";
- }
+ *error_details = "Configured to support an unknown key exchange";
return QUIC_CRYPTO_INTERNAL_ERROR;
}
if (!key_exchange->CalculateSharedKey(public_value,
&out_params->premaster_secret)) {
- if (error_details) {
- *error_details = "Key exchange failure";
- }
+ *error_details = "Key exchange failure";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
out->SetStringPiece(kPUBS, key_exchange->public_value());
- string hkdf_input(kLabel, arraysize(kLabel));
+ string hkdf_input(QuicCryptoConfig::kLabel,
+ strlen(QuicCryptoConfig::kLabel) + 1);
hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
const QuicData& client_hello_serialized = out->GetSerialized();
@@ -609,8 +550,9 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
const CryptoHandshakeMessage& rej,
QuicCryptoNegotiatedParameters* out_params,
string* error_details) {
- CachedState* cached;
+ DCHECK(error_details != NULL);
+ CachedState* cached;
map<string, CachedState*>::const_iterator it =
cached_states_.find(server_hostname);
if (it == cached_states_.end()) {
@@ -622,16 +564,12 @@ QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
StringPiece scfg;
if (!rej.GetStringPiece(kSCFG, &scfg)) {
- if (error_details) {
- *error_details = "Missing SCFG";
- }
+ *error_details = "Missing SCFG";
return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
}
if (!cached->SetServerConfig(scfg)) {
- if (error_details) {
- *error_details = "Invalid SCFG";
- }
+ *error_details = "Invalid SCFG";
return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
}
@@ -654,6 +592,8 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
const string& nonce,
QuicCryptoNegotiatedParameters* out_params,
string* error_details) {
+ DCHECK(error_details != NULL);
+
if (server_hello.tag() != kSHLO) {
*error_details = "Bad tag";
return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
@@ -666,495 +606,4 @@ QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
return QUIC_NO_ERROR;
}
-// static
-const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
-
-QuicCryptoServerConfig::QuicCryptoServerConfig(
- StringPiece source_address_token_secret)
- // AES-GCM is used to encrypt and authenticate source address tokens. The
- // full, 96-bit nonce is used but we must ensure that an attacker cannot
- // obtain two source address tokens with the same nonce. This occurs with
- // probability 0.5 after 2**48 values. We assume that obtaining 2**48
- // source address tokens is not possible: at a rate of 10M packets per
- // second, it would still take the attacker a year to obtain the needed
- // number of packets.
- //
- // TODO(agl): switch to an encrypter with a larger nonce space (i.e.
- // Salsa20+Poly1305).
- : strike_register_lock_(),
- source_address_token_encrypter_(new Aes128GcmEncrypter),
- source_address_token_decrypter_(new Aes128GcmDecrypter) {
- crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */,
- "QUIC source address token key",
- source_address_token_encrypter_->GetKeySize(),
- 0 /* no fixed IV needed */);
- source_address_token_encrypter_->SetKey(hkdf.server_write_key());
- source_address_token_decrypter_->SetKey(hkdf.server_write_key());
-}
-
-QuicCryptoServerConfig::~QuicCryptoServerConfig() {
- STLDeleteValues(&configs_);
-}
-
-// static
-QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
- QuicRandom* rand,
- const QuicClock* clock,
- const CryptoHandshakeMessage& extra_tags) {
- CryptoHandshakeMessage msg;
-
- const string curve25519_private_key =
- Curve25519KeyExchange::NewPrivateKey(rand);
- scoped_ptr<Curve25519KeyExchange> curve25519(
- Curve25519KeyExchange::New(curve25519_private_key));
- StringPiece curve25519_public_value = curve25519->public_value();
-
- const string p256_private_key =
- P256KeyExchange::NewPrivateKey();
- scoped_ptr<P256KeyExchange> p256(
- P256KeyExchange::New(p256_private_key));
- StringPiece p256_public_value = p256->public_value();
-
- string encoded_public_values;
- // First two bytes encode the length of the public value.
- encoded_public_values.push_back(curve25519_public_value.size());
- encoded_public_values.push_back(curve25519_public_value.size() >> 8);
- encoded_public_values.append(curve25519_public_value.data(),
- curve25519_public_value.size());
- encoded_public_values.push_back(p256_public_value.size());
- encoded_public_values.push_back(p256_public_value.size() >> 8);
- encoded_public_values.append(p256_public_value.data(),
- p256_public_value.size());
-
- msg.set_tag(kSCFG);
- msg.SetTaglist(kKEXS, kC255, kP256, 0);
- msg.SetTaglist(kAEAD, kAESG, 0);
- msg.SetValue(kVERS, static_cast<uint16>(0));
- msg.SetStringPiece(kPUBS, encoded_public_values);
- msg.Insert(extra_tags.tag_value_map().begin(),
- extra_tags.tag_value_map().end());
-
- char scid_bytes[16];
- rand->RandBytes(scid_bytes, sizeof(scid_bytes));
- msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
-
- char orbit_bytes[kOrbitSize];
- rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
- msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
-
- scoped_ptr<QuicData> serialized(
- CryptoFramer::ConstructHandshakeMessage(msg));
-
- scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
- config->set_config(serialized->AsStringPiece());
- QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
- curve25519_key->set_tag(kC255);
- curve25519_key->set_private_key(curve25519_private_key);
- QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
- p256_key->set_tag(kP256);
- p256_key->set_private_key(p256_private_key);
-
- return config.release();
-}
-
-CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
- QuicServerConfigProtobuf* protobuf) {
- scoped_ptr<CryptoHandshakeMessage> msg(
- CryptoFramer::ParseMessage(protobuf->config()));
-
- if (!msg.get()) {
- LOG(WARNING) << "Failed to parse server config message";
- return NULL;
- }
- if (msg->tag() != kSCFG) {
- LOG(WARNING) << "Server config message has tag "
- << msg->tag() << " expected "
- << kSCFG;
- return NULL;
- }
-
- scoped_ptr<Config> config(new Config);
- config->serialized = protobuf->config();
-
- StringPiece scid;
- if (!msg->GetStringPiece(kSCID, &scid)) {
- LOG(WARNING) << "Server config message is missing SCID";
- return NULL;
- }
- config->id = scid.as_string();
-
- const CryptoTag* aead_tags;
- size_t aead_len;
- if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
- LOG(WARNING) << "Server config message is missing AEAD";
- return NULL;
- }
- config->aead = vector<CryptoTag>(aead_tags, aead_tags + aead_len);
-
- const CryptoTag* kexs_tags;
- size_t kexs_len;
- if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
- LOG(WARNING) << "Server config message is missing KEXS";
- return NULL;
- }
-
- StringPiece orbit;
- if (!msg->GetStringPiece(kORBT, &orbit)) {
- LOG(WARNING) << "Server config message is missing OBIT";
- return NULL;
- }
-
- if (orbit.size() != kOrbitSize) {
- LOG(WARNING) << "Orbit value in server config is the wrong length."
- " Got " << orbit.size() << " want " << kOrbitSize;
- return NULL;
- }
- COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size);
- memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
-
- if (kexs_len != protobuf->key_size()) {
- LOG(WARNING) << "Server config has "
- << kexs_len
- << " key exchange methods configured, but "
- << protobuf->key_size()
- << " private keys";
- return NULL;
- }
-
- for (size_t i = 0; i < kexs_len; i++) {
- const CryptoTag tag = kexs_tags[i];
- string private_key;
-
- config->kexs.push_back(tag);
-
- for (size_t j = 0; j < protobuf->key_size(); j++) {
- const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
- if (key.tag() == tag) {
- private_key = key.private_key();
- break;
- }
- }
-
- if (private_key.empty()) {
- LOG(WARNING) << "Server config contains key exchange method without "
- "corresponding private key: "
- << tag;
- return NULL;
- }
-
- scoped_ptr<KeyExchange> ka;
- switch (tag) {
- case kC255:
- ka.reset(Curve25519KeyExchange::New(private_key));
- if (!ka.get()) {
- LOG(WARNING) << "Server config contained an invalid curve25519"
- " private key.";
- return NULL;
- }
- break;
- case kP256:
- ka.reset(P256KeyExchange::New(private_key));
- if (!ka.get()) {
- LOG(WARNING) << "Server config contained an invalid P-256"
- " private key.";
- return NULL;
- }
- break;
- default:
- LOG(WARNING) << "Server config message contains unknown key exchange "
- "method: "
- << tag;
- return NULL;
- }
-
- for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin();
- i != config->key_exchanges.end(); ++i) {
- if ((*i)->tag() == tag) {
- LOG(WARNING) << "Duplicate key exchange in config: " << tag;
- return NULL;
- }
- }
-
- config->key_exchanges.push_back(ka.release());
- }
-
- if (msg->GetUint16(kVERS, &config->version) != QUIC_NO_ERROR) {
- LOG(WARNING) << "Server config message is missing version";
- return NULL;
- }
-
- if (config->version != kVersion) {
- LOG(WARNING) << "Server config specifies an unsupported version";
- return NULL;
- }
-
- scoped_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256));
- sha256->Update(protobuf->config().data(), protobuf->config().size());
- char id_bytes[16];
- sha256->Finish(id_bytes, sizeof(id_bytes));
- const string id(id_bytes, sizeof(id_bytes));
-
- configs_[id] = config.release();
- active_config_ = id;
-
- return msg.release();
-}
-
-CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
- QuicRandom* rand,
- const QuicClock* clock,
- const CryptoHandshakeMessage& extra_tags) {
- scoped_ptr<QuicServerConfigProtobuf> config(DefaultConfig(
- rand, clock, extra_tags));
- return AddConfig(config.get());
-}
-
-QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
- const CryptoHandshakeMessage& client_hello,
- QuicGuid guid,
- const IPEndPoint& client_ip,
- QuicTime::Delta now_since_unix_epoch,
- QuicRandom* rand,
- QuicCryptoNegotiatedParameters *params,
- CryptoHandshakeMessage* out,
- string* error_details) const {
- CHECK(!configs_.empty());
- // FIXME(agl): we should use the client's SCID, not just the active config.
- map<ServerConfigID, Config*>::const_iterator it =
- configs_.find(active_config_);
- if (it == configs_.end()) {
- *error_details = "No valid server config loaded";
- return QUIC_CRYPTO_INTERNAL_ERROR;
- }
- const Config* const config(it->second);
-
- bool valid_source_address_token = false;
- StringPiece srct;
- if (client_hello.GetStringPiece(kSRCT, &srct) &&
- ValidateSourceAddressToken(srct, client_ip, now_since_unix_epoch)) {
- valid_source_address_token = true;
- }
-
- const string fresh_source_address_token =
- NewSourceAddressToken(client_ip, rand, now_since_unix_epoch);
-
- // If we previously sent a REJ to this client then we may have stored a
- // server nonce in |params|. In which case, we know that the connection
- // is unique because the server nonce will be mixed into the key generation.
- bool unique_by_server_nonce = !params->server_nonce.empty();
- // If we can't ensure uniqueness by a server nonce, then we will try and use
- // the strike register.
- bool unique_by_strike_register = false;
-
- StringPiece client_nonce;
- bool client_nonce_well_formed = false;
- if (client_hello.GetStringPiece(kNONC, &client_nonce) &&
- client_nonce.size() == kNonceSize) {
- client_nonce_well_formed = true;
- if (!unique_by_server_nonce) {
- base::AutoLock auto_lock(strike_register_lock_);
-
- if (strike_register_.get() == NULL) {
- strike_register_.reset(new StrikeRegister(
- // TODO(agl): these magic numbers should come from config.
- 1024 /* max entries */,
- static_cast<uint32>(now_since_unix_epoch.ToSeconds()),
- 600 /* window secs */, config->orbit));
- }
- unique_by_strike_register = strike_register_->Insert(
- reinterpret_cast<const uint8*>(client_nonce.data()),
- static_cast<uint32>(now_since_unix_epoch.ToSeconds()));
- }
- }
-
- StringPiece scid;
- if (!client_hello.GetStringPiece(kSCID, &scid) ||
- scid.as_string() != config->id ||
- !valid_source_address_token ||
- !client_nonce_well_formed ||
- (!unique_by_strike_register &&
- !unique_by_server_nonce)) {
- // If the client didn't provide a server config ID, or gave the wrong one,
- // then the handshake cannot possibly complete. We reject the handshake and
- // give the client enough information to do better next time.
- out->Clear();
- out->set_tag(kREJ);
- out->SetStringPiece(kSCFG, config->serialized);
- out->SetStringPiece(kSRCT, fresh_source_address_token);
- if (params->server_nonce.empty()) {
- CryptoUtils::GenerateNonce(
- now_since_unix_epoch, rand,
- StringPiece(reinterpret_cast<const char*>(config->orbit),
- sizeof(config->orbit)),
- &params->server_nonce);
- }
- out->SetStringPiece(kNONC, params->server_nonce);
- return QUIC_NO_ERROR;
- }
-
- const CryptoTag* their_aeads;
- const CryptoTag* their_key_exchanges;
- size_t num_their_aeads, num_their_key_exchanges;
- if (client_hello.GetTaglist(kAEAD, &their_aeads,
- &num_their_aeads) != QUIC_NO_ERROR ||
- client_hello.GetTaglist(kKEXS, &their_key_exchanges,
- &num_their_key_exchanges) != QUIC_NO_ERROR ||
- num_their_aeads != 1 ||
- num_their_key_exchanges != 1) {
- if (error_details) {
- *error_details = "Missing or invalid AEAD or KEXS";
- }
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- size_t key_exchange_index;
- if (!CryptoUtils::FindMutualTag(config->aead,
- their_aeads, num_their_aeads,
- CryptoUtils::LOCAL_PRIORITY,
- &params->aead,
- NULL) ||
- !CryptoUtils::FindMutualTag(config->kexs,
- their_key_exchanges, num_their_key_exchanges,
- CryptoUtils::LOCAL_PRIORITY,
- &params->key_exchange,
- &key_exchange_index)) {
- if (error_details) {
- *error_details = "Unsupported AEAD or KEXS";
- }
- return QUIC_CRYPTO_NO_SUPPORT;
- }
-
- StringPiece public_value;
- if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
- if (error_details) {
- *error_details = "Missing public value";
- }
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- if (!config->key_exchanges[key_exchange_index]->CalculateSharedKey(
- public_value, &params->premaster_secret)) {
- if (error_details) {
- *error_details = "Invalid public value";
- }
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- params->server_config_id = scid.as_string();
-
- string hkdf_input(kLabel, arraysize(kLabel));
- hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
-
- const QuicData& client_hello_serialized = client_hello.GetSerialized();
- hkdf_input.append(client_hello_serialized.data(),
- client_hello_serialized.length());
- hkdf_input.append(config->serialized);
-
- CryptoUtils::DeriveKeys(params, client_nonce, hkdf_input,
- CryptoUtils::SERVER);
-
- out->set_tag(kSHLO);
- out->SetStringPiece(kSRCT, fresh_source_address_token);
- return QUIC_NO_ERROR;
-}
-
-string QuicCryptoServerConfig::NewSourceAddressToken(
- const IPEndPoint& ip,
- QuicRandom* rand,
- QuicTime::Delta now_since_epoch) const {
- SourceAddressToken source_address_token;
- source_address_token.set_ip(ip.ToString());
- source_address_token.set_timestamp(now_since_epoch.ToSeconds());
-
- string plaintext = source_address_token.SerializeAsString();
- char nonce[12];
- DCHECK_EQ(sizeof(nonce),
- source_address_token_encrypter_->GetNoncePrefixSize() +
- sizeof(QuicPacketSequenceNumber));
- rand->RandBytes(nonce, sizeof(nonce));
-
- size_t ciphertext_size =
- source_address_token_encrypter_->GetCiphertextSize(plaintext.size());
- string result;
- result.resize(sizeof(nonce) + ciphertext_size);
- memcpy(&result[0], &nonce, sizeof(nonce));
-
- if (!source_address_token_encrypter_->Encrypt(
- StringPiece(nonce, sizeof(nonce)), StringPiece(), plaintext,
- reinterpret_cast<unsigned char*>(&result[sizeof(nonce)]))) {
- DCHECK(false);
- return string();
- }
-
- return result;
-}
-
-bool QuicCryptoServerConfig::ValidateSourceAddressToken(
- StringPiece token,
- const IPEndPoint& ip,
- QuicTime::Delta now_since_epoch) const {
- char nonce[12];
- DCHECK_EQ(sizeof(nonce),
- source_address_token_encrypter_->GetNoncePrefixSize() +
- sizeof(QuicPacketSequenceNumber));
-
- if (token.size() <= sizeof(nonce)) {
- return false;
- }
- memcpy(&nonce, token.data(), sizeof(nonce));
- token.remove_prefix(sizeof(nonce));
-
- unsigned char plaintext_stack[128];
- scoped_ptr<unsigned char[]> plaintext_heap;
- unsigned char* plaintext;
- if (token.size() <= sizeof(plaintext_stack)) {
- plaintext = plaintext_stack;
- } else {
- plaintext_heap.reset(new unsigned char[token.size()]);
- plaintext = plaintext_heap.get();
- }
- size_t plaintext_length;
-
- if (!source_address_token_decrypter_->Decrypt(
- StringPiece(nonce, sizeof(nonce)), StringPiece(), token,
- plaintext, &plaintext_length)) {
- return false;
- }
-
- SourceAddressToken source_address_token;
- if (!source_address_token.ParseFromArray(plaintext, plaintext_length)) {
- return false;
- }
-
- if (source_address_token.ip() != ip.ToString()) {
- // It's for a different IP address.
- return false;
- }
-
- const QuicTime::Delta delta(now_since_epoch.Subtract(
- QuicTime::Delta::FromSeconds(source_address_token.timestamp())));
- const int64 delta_secs = delta.ToSeconds();
-
- // TODO(agl): consider whether and how these magic values should be moved to
- // a config.
- if (delta_secs < -3600) {
- // We only allow timestamps to be from an hour in the future.
- return false;
- }
-
- if (delta_secs > 86400) {
- // We allow one day into the past.
- return false;
- }
-
- return true;
-}
-
-QuicCryptoServerConfig::Config::Config() {
-}
-
-QuicCryptoServerConfig::Config::~Config() {
- STLDeleteElements(&key_exchanges);
-}
-
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698