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

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

Issue 15937012: Land Recent QUIC changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Small bug fixes Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/crypto/crypto_server_config.h" 5 #include "net/quic/crypto/crypto_server_config.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "crypto/hkdf.h" 10 #include "crypto/hkdf.h"
11 #include "crypto/secure_hash.h" 11 #include "crypto/secure_hash.h"
12 #include "net/quic/crypto/aes_128_gcm_12_decrypter.h" 12 #include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
13 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h" 13 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
14 #include "net/quic/crypto/cert_compressor.h" 14 #include "net/quic/crypto/cert_compressor.h"
15 #include "net/quic/crypto/channel_id.h"
15 #include "net/quic/crypto/crypto_framer.h" 16 #include "net/quic/crypto/crypto_framer.h"
16 #include "net/quic/crypto/crypto_server_config_protobuf.h" 17 #include "net/quic/crypto/crypto_server_config_protobuf.h"
17 #include "net/quic/crypto/crypto_utils.h" 18 #include "net/quic/crypto/crypto_utils.h"
18 #include "net/quic/crypto/curve25519_key_exchange.h" 19 #include "net/quic/crypto/curve25519_key_exchange.h"
19 #include "net/quic/crypto/ephemeral_key_source.h" 20 #include "net/quic/crypto/ephemeral_key_source.h"
20 #include "net/quic/crypto/key_exchange.h" 21 #include "net/quic/crypto/key_exchange.h"
21 #include "net/quic/crypto/p256_key_exchange.h" 22 #include "net/quic/crypto/p256_key_exchange.h"
22 #include "net/quic/crypto/proof_source.h" 23 #include "net/quic/crypto/proof_source.h"
23 #include "net/quic/crypto/quic_decrypter.h" 24 #include "net/quic/crypto/quic_decrypter.h"
24 #include "net/quic/crypto/quic_encrypter.h" 25 #include "net/quic/crypto/quic_encrypter.h"
25 #include "net/quic/crypto/quic_random.h" 26 #include "net/quic/crypto/quic_random.h"
26 #include "net/quic/crypto/source_address_token.h" 27 #include "net/quic/crypto/source_address_token.h"
27 #include "net/quic/crypto/strike_register.h" 28 #include "net/quic/crypto/strike_register.h"
28 #include "net/quic/quic_clock.h" 29 #include "net/quic/quic_clock.h"
29 #include "net/quic/quic_protocol.h" 30 #include "net/quic/quic_protocol.h"
30 #include "net/quic/quic_utils.h" 31 #include "net/quic/quic_utils.h"
31 32
32 using base::StringPiece; 33 using base::StringPiece;
33 using crypto::SecureHash; 34 using crypto::SecureHash;
34 using std::map; 35 using std::map;
35 using std::string; 36 using std::string;
36 using std::vector; 37 using std::vector;
37 38
38 namespace net { 39 namespace net {
39 40
40 // static 41 // static
41 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing"; 42 const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
42 43
44 QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
45 : expiry_time(QuicWallTime::Zero()),
46 channel_id_enabled(false) { }
47
43 QuicCryptoServerConfig::QuicCryptoServerConfig( 48 QuicCryptoServerConfig::QuicCryptoServerConfig(
44 StringPiece source_address_token_secret) 49 StringPiece source_address_token_secret,
50 QuicRandom* rand)
45 : strike_register_lock_(), 51 : strike_register_lock_(),
52 server_nonce_strike_register_lock_(),
46 strike_register_max_entries_(1 << 10), 53 strike_register_max_entries_(1 << 10),
47 strike_register_window_secs_(600), 54 strike_register_window_secs_(600),
48 source_address_token_future_secs_(3600), 55 source_address_token_future_secs_(3600),
49 source_address_token_lifetime_secs_(86400) { 56 source_address_token_lifetime_secs_(86400),
57 server_nonce_strike_register_max_entries_(1 << 10),
58 server_nonce_strike_register_window_secs_(120) {
50 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */, 59 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */,
51 "QUIC source address token key", 60 "QUIC source address token key",
52 CryptoSecretBoxer::GetKeySize(), 61 CryptoSecretBoxer::GetKeySize(),
53 0 /* no fixed IV needed */); 62 0 /* no fixed IV needed */);
54 source_address_token_boxer_.SetKey(hkdf.server_write_key()); 63 source_address_token_boxer_.SetKey(hkdf.server_write_key());
64
65 // Generate a random key and orbit for server nonces.
66 rand->RandBytes(server_nonce_orbit_, sizeof(server_nonce_orbit_));
67 const size_t key_size = server_nonce_boxer_.GetKeySize();
68 scoped_ptr<uint8[]> key_bytes(new uint8[key_size]);
69 rand->RandBytes(key_bytes.get(), key_size);
70
71 server_nonce_boxer_.SetKey(
72 StringPiece(reinterpret_cast<char*>(key_bytes.get()), key_size));
55 } 73 }
56 74
57 QuicCryptoServerConfig::~QuicCryptoServerConfig() { 75 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
58 STLDeleteValues(&configs_); 76 STLDeleteValues(&configs_);
59 } 77 }
60 78
61 // static 79 // static
62 QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig( 80 QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
63 QuicRandom* rand, 81 QuicRandom* rand,
64 const QuicClock* clock, 82 const QuicClock* clock,
65 uint64 expiry_time) { 83 const ConfigOptions& options) {
66 CryptoHandshakeMessage msg; 84 CryptoHandshakeMessage msg;
67 85
68 const string curve25519_private_key = 86 const string curve25519_private_key =
69 Curve25519KeyExchange::NewPrivateKey(rand); 87 Curve25519KeyExchange::NewPrivateKey(rand);
70 scoped_ptr<Curve25519KeyExchange> curve25519( 88 scoped_ptr<Curve25519KeyExchange> curve25519(
71 Curve25519KeyExchange::New(curve25519_private_key)); 89 Curve25519KeyExchange::New(curve25519_private_key));
72 StringPiece curve25519_public_value = curve25519->public_value(); 90 StringPiece curve25519_public_value = curve25519->public_value();
73 91
74 const string p256_private_key = P256KeyExchange::NewPrivateKey(); 92 const string p256_private_key = P256KeyExchange::NewPrivateKey();
75 scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key)); 93 scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
(...skipping 11 matching lines...) Expand all
87 encoded_public_values.push_back(p256_public_value.size() >> 16); 105 encoded_public_values.push_back(p256_public_value.size() >> 16);
88 encoded_public_values.append(p256_public_value.data(), 106 encoded_public_values.append(p256_public_value.data(),
89 p256_public_value.size()); 107 p256_public_value.size());
90 108
91 msg.set_tag(kSCFG); 109 msg.set_tag(kSCFG);
92 msg.SetTaglist(kKEXS, kC255, kP256, 0); 110 msg.SetTaglist(kKEXS, kC255, kP256, 0);
93 msg.SetTaglist(kAEAD, kAESG, 0); 111 msg.SetTaglist(kAEAD, kAESG, 0);
94 msg.SetValue(kVERS, static_cast<uint16>(0)); 112 msg.SetValue(kVERS, static_cast<uint16>(0));
95 msg.SetStringPiece(kPUBS, encoded_public_values); 113 msg.SetStringPiece(kPUBS, encoded_public_values);
96 114
97 if (expiry_time == 0) { 115 if (options.expiry_time.IsZero()) {
98 const QuicWallTime now = clock->WallNow(); 116 const QuicWallTime now = clock->WallNow();
99 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds( 117 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
100 60 * 60 * 24 * 180 /* 180 days, ~six months */)); 118 60 * 60 * 24 * 180 /* 180 days, ~six months */));
101 const uint64 expiry_seconds = expiry.ToUNIXSeconds(); 119 const uint64 expiry_seconds = expiry.ToUNIXSeconds();
102 msg.SetValue(kEXPY, expiry_seconds); 120 msg.SetValue(kEXPY, expiry_seconds);
103 } else { 121 } else {
104 msg.SetValue(kEXPY, expiry_time); 122 msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
105 } 123 }
106 124
107 char scid_bytes[16]; 125 char scid_bytes[16];
108 rand->RandBytes(scid_bytes, sizeof(scid_bytes)); 126 rand->RandBytes(scid_bytes, sizeof(scid_bytes));
109 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes))); 127 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
110 128
111 char orbit_bytes[kOrbitSize]; 129 char orbit_bytes[kOrbitSize];
112 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes)); 130 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
113 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes))); 131 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
114 132
133 if (options.channel_id_enabled) {
134 msg.SetTaglist(kPDMD, kCHID, 0);
135 }
136
115 scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg)); 137 scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg));
116 138
117 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf); 139 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
118 config->set_config(serialized->AsStringPiece()); 140 config->set_config(serialized->AsStringPiece());
119 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key(); 141 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
120 curve25519_key->set_tag(kC255); 142 curve25519_key->set_tag(kC255);
121 curve25519_key->set_private_key(curve25519_private_key); 143 curve25519_key->set_private_key(curve25519_private_key);
122 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key(); 144 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
123 p256_key->set_tag(kP256); 145 p256_key->set_tag(kP256);
124 p256_key->set_private_key(p256_private_key); 146 p256_key->set_private_key(p256_private_key);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size); 202 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size);
181 memcpy(config->orbit, orbit.data(), sizeof(config->orbit)); 203 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
182 204
183 if (kexs_len != protobuf->key_size()) { 205 if (kexs_len != protobuf->key_size()) {
184 LOG(WARNING) << "Server config has " << kexs_len 206 LOG(WARNING) << "Server config has " << kexs_len
185 << " key exchange methods configured, but " 207 << " key exchange methods configured, but "
186 << protobuf->key_size() << " private keys"; 208 << protobuf->key_size() << " private keys";
187 return NULL; 209 return NULL;
188 } 210 }
189 211
212 const QuicTag* proof_demand_tags;
213 size_t num_proof_demand_tags;
214 if (msg->GetTaglist(kPDMD, &proof_demand_tags, &num_proof_demand_tags) ==
215 QUIC_NO_ERROR) {
216 for (size_t i = 0; i < num_proof_demand_tags; i++) {
217 if (proof_demand_tags[i] == kCHID) {
218 config->channel_id_enabled = true;
219 break;
220 }
221 }
222 }
223
190 for (size_t i = 0; i < kexs_len; i++) { 224 for (size_t i = 0; i < kexs_len; i++) {
191 const QuicTag tag = kexs_tags[i]; 225 const QuicTag tag = kexs_tags[i];
192 string private_key; 226 string private_key;
193 227
194 config->kexs.push_back(tag); 228 config->kexs.push_back(tag);
195 229
196 for (size_t j = 0; j < protobuf->key_size(); j++) { 230 for (size_t j = 0; j < protobuf->key_size(); j++) {
197 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i); 231 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
198 if (key.tag() == tag) { 232 if (key.tag() == tag) {
199 private_key = key.private_key(); 233 private_key = key.private_key();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 if (msg->GetUint16(kVERS, &config->version) != QUIC_NO_ERROR) { 279 if (msg->GetUint16(kVERS, &config->version) != QUIC_NO_ERROR) {
246 LOG(WARNING) << "Server config message is missing version"; 280 LOG(WARNING) << "Server config message is missing version";
247 return NULL; 281 return NULL;
248 } 282 }
249 283
250 if (config->version != QuicCryptoConfig::CONFIG_VERSION) { 284 if (config->version != QuicCryptoConfig::CONFIG_VERSION) {
251 LOG(WARNING) << "Server config specifies an unsupported version"; 285 LOG(WARNING) << "Server config specifies an unsupported version";
252 return NULL; 286 return NULL;
253 } 287 }
254 288
289 // FIXME(agl): this is mismatched with |DefaultConfig|, which generates a
290 // random id.
255 scoped_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256)); 291 scoped_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256));
256 sha256->Update(protobuf->config().data(), protobuf->config().size()); 292 sha256->Update(protobuf->config().data(), protobuf->config().size());
257 char id_bytes[16]; 293 char id_bytes[16];
258 sha256->Finish(id_bytes, sizeof(id_bytes)); 294 sha256->Finish(id_bytes, sizeof(id_bytes));
259 const string id(id_bytes, sizeof(id_bytes)); 295 const string id(id_bytes, sizeof(id_bytes));
260 296
261 configs_[id] = config.release(); 297 configs_[id] = config.release();
262 active_config_ = id; 298 active_config_ = id;
263 299
264 return msg.release(); 300 return msg.release();
265 } 301 }
266 302
267 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig( 303 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
268 QuicRandom* rand, 304 QuicRandom* rand,
269 const QuicClock* clock, 305 const QuicClock* clock,
270 uint64 expiry_time) { 306 const ConfigOptions& options) {
271 scoped_ptr<QuicServerConfigProtobuf> config( 307 scoped_ptr<QuicServerConfigProtobuf> config(
272 DefaultConfig(rand, clock, expiry_time)); 308 DefaultConfig(rand, clock, options));
273 return AddConfig(config.get()); 309 return AddConfig(config.get());
274 } 310 }
275 311
276 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( 312 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
277 const CryptoHandshakeMessage& client_hello, 313 const CryptoHandshakeMessage& client_hello,
278 QuicGuid guid, 314 QuicGuid guid,
279 const IPEndPoint& client_ip, 315 const IPEndPoint& client_ip,
280 const QuicClock* clock, 316 const QuicClock* clock,
281 QuicRandom* rand, 317 QuicRandom* rand,
282 QuicCryptoNegotiatedParameters *params, 318 QuicCryptoNegotiatedParameters *params,
(...skipping 21 matching lines...) Expand all
304 } 340 }
305 341
306 const QuicWallTime now = clock->WallNow(); 342 const QuicWallTime now = clock->WallNow();
307 bool valid_source_address_token = false; 343 bool valid_source_address_token = false;
308 StringPiece srct; 344 StringPiece srct;
309 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) && 345 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) &&
310 ValidateSourceAddressToken(srct, client_ip, now)) { 346 ValidateSourceAddressToken(srct, client_ip, now)) {
311 valid_source_address_token = true; 347 valid_source_address_token = true;
312 } 348 }
313 349
314 const string fresh_source_address_token = 350 StringPiece sni;
315 NewSourceAddressToken(client_ip, rand, now); 351 if (client_hello.GetStringPiece(kSNI, &sni) &&
352 !CryptoUtils::IsValidSNI(sni)) {
353 *error_details = "Invalid SNI name";
354 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
355 }
316 356
317 // If we previously sent a REJ to this client then we may have stored a 357 // The client nonce is used first to try and establish uniqueness.
318 // server nonce in |params|. In which case, we know that the connection
319 // is unique because the server nonce will be mixed into the key generation.
320 bool unique_by_server_nonce = !params->server_nonce.empty();
321 // If we can't ensure uniqueness by a server nonce, then we will try and use
322 // the strike register.
323 bool unique_by_strike_register = false; 358 bool unique_by_strike_register = false;
324 359
325 StringPiece client_nonce; 360 StringPiece client_nonce;
326 bool client_nonce_well_formed = false; 361 bool client_nonce_well_formed = false;
327 if (client_hello.GetStringPiece(kNONC, &client_nonce) && 362 if (client_hello.GetStringPiece(kNONC, &client_nonce) &&
328 client_nonce.size() == kNonceSize) { 363 client_nonce.size() == kNonceSize) {
329 client_nonce_well_formed = true; 364 client_nonce_well_formed = true;
330 base::AutoLock auto_lock(strike_register_lock_); 365 base::AutoLock auto_lock(strike_register_lock_);
331 366
332 if (strike_register_.get() == NULL) { 367 if (strike_register_.get() == NULL) {
333 strike_register_.reset(new StrikeRegister( 368 strike_register_.reset(new StrikeRegister(
334 strike_register_max_entries_, 369 strike_register_max_entries_,
335 static_cast<uint32>(now.ToUNIXSeconds()), 370 static_cast<uint32>(now.ToUNIXSeconds()),
336 strike_register_window_secs_, 371 strike_register_window_secs_,
337 config->orbit)); 372 config->orbit,
373 StrikeRegister::DENY_REQUESTS_AT_STARTUP));
338 } 374 }
339 unique_by_strike_register = strike_register_->Insert( 375 unique_by_strike_register = strike_register_->Insert(
340 reinterpret_cast<const uint8*>(client_nonce.data()), 376 reinterpret_cast<const uint8*>(client_nonce.data()),
341 static_cast<uint32>(now.ToUNIXSeconds())); 377 static_cast<uint32>(now.ToUNIXSeconds()));
342 } 378 }
343 379
344 StringPiece server_nonce; 380 StringPiece server_nonce;
345 client_hello.GetStringPiece(kServerNonceTag, &server_nonce); 381 client_hello.GetStringPiece(kServerNonceTag, &server_nonce);
346 const bool server_nonce_matches = server_nonce == params->server_nonce; 382
383 // If the client nonce didn't establish uniqueness then an echoed server
384 // nonce may.
385 bool unique_by_server_nonce = false;
386 if (!unique_by_strike_register && !server_nonce.empty()) {
387 unique_by_server_nonce = ValidateServerNonce(server_nonce, now);
388 }
347 389
348 out->Clear(); 390 out->Clear();
349 391
350 StringPiece sni;
351 if (client_hello.GetStringPiece(kSNI, &sni) &&
352 !CryptoUtils::IsValidSNI(sni)) {
353 *error_details = "Invalid SNI name";
354 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
355 }
356
357 StringPiece scid; 392 StringPiece scid;
358 if (!client_hello.GetStringPiece(kSCID, &scid) || 393 if (!client_hello.GetStringPiece(kSCID, &scid) ||
359 scid.as_string() != config->id || 394 scid.as_string() != config->id ||
360 !valid_source_address_token || 395 !valid_source_address_token ||
361 !client_nonce_well_formed || 396 !client_nonce_well_formed ||
362 !server_nonce_matches ||
363 (!unique_by_strike_register && 397 (!unique_by_strike_register &&
364 !unique_by_server_nonce)) { 398 !unique_by_server_nonce)) {
365 // If the client didn't provide a server config ID, or gave the wrong one, 399 // If the client didn't provide a server config ID, or gave the wrong one,
366 // then the handshake cannot possibly complete. We reject the handshake and 400 // then the handshake cannot possibly complete. We reject the handshake and
367 // give the client enough information to do better next time. 401 // give the client enough information to do better next time.
368 out->set_tag(kREJ); 402 out->set_tag(kREJ);
369 out->SetStringPiece(kSCFG, config->serialized); 403 out->SetStringPiece(kSCFG, config->serialized);
370 out->SetStringPiece(kSourceAddressTokenTag, fresh_source_address_token); 404 out->SetStringPiece(kSourceAddressTokenTag,
371 if (params->server_nonce.empty()) { 405 NewSourceAddressToken(client_ip, rand, now));
372 CryptoUtils::GenerateNonce( 406 out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, now));
373 now, rand, StringPiece(reinterpret_cast<const char*>(config->orbit),
374 sizeof(config->orbit)),
375 &params->server_nonce);
376 }
377 out->SetStringPiece(kServerNonceTag, params->server_nonce);
378 407
379 // The client may have requested a certificate chain. 408 // The client may have requested a certificate chain.
380 const QuicTag* their_proof_demands; 409 const QuicTag* their_proof_demands;
381 size_t num_their_proof_demands; 410 size_t num_their_proof_demands;
382 411
383 if (proof_source_.get() != NULL && !sni.empty() && 412 if (proof_source_.get() != NULL && !sni.empty() &&
384 client_hello.GetTaglist(kPDMD, &their_proof_demands, 413 client_hello.GetTaglist(kPDMD, &their_proof_demands,
385 &num_their_proof_demands) == QUIC_NO_ERROR) { 414 &num_their_proof_demands) == QUIC_NO_ERROR) {
386 for (size_t i = 0; i < num_their_proof_demands; i++) { 415 for (size_t i = 0; i < num_their_proof_demands; i++) {
387 if (their_proof_demands[i] != kX509) { 416 if (their_proof_demands[i] != kX509) {
388 continue; 417 continue;
389 } 418 }
390 419
391 const vector<string>* certs; 420 const vector<string>* certs;
392 string signature; 421 string signature;
393 if (!proof_source_->GetProof(sni.as_string(), config->serialized, 422 if (!proof_source_->GetProof(sni.as_string(), config->serialized,
394 &certs, &signature)) { 423 &certs, &signature)) {
395 break; 424 break;
396 } 425 }
397 426
398 StringPiece their_common_set_hashes; 427 StringPiece their_common_set_hashes;
399 StringPiece their_cached_cert_hashes; 428 StringPiece their_cached_cert_hashes;
400 client_hello.GetStringPiece(kCCS, &their_common_set_hashes); 429 client_hello.GetStringPiece(kCCS, &their_common_set_hashes);
401 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes); 430 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes);
402 431
403 const string compressed = CertCompressor::CompressChain( 432 const string compressed = CertCompressor::CompressChain(
404 *certs, their_common_set_hashes, their_cached_cert_hashes, 433 *certs, their_common_set_hashes, their_cached_cert_hashes,
405 config->common_cert_sets.get()); 434 config->common_cert_sets);
406 435
407 // kMaxUnverifiedSize is the number of bytes that the certificate chain 436 // kMaxUnverifiedSize is the number of bytes that the certificate chain
408 // and signature can consume before we will demand a valid 437 // and signature can consume before we will demand a valid
409 // source-address token. 438 // source-address token.
439 // TODO(agl): make this configurable.
410 static const size_t kMaxUnverifiedSize = 400; 440 static const size_t kMaxUnverifiedSize = 400;
411 if (valid_source_address_token || 441 if (valid_source_address_token ||
412 signature.size() + compressed.size() < kMaxUnverifiedSize) { 442 signature.size() + compressed.size() < kMaxUnverifiedSize) {
413 out->SetStringPiece(kCertificateTag, compressed); 443 out->SetStringPiece(kCertificateTag, compressed);
414 out->SetStringPiece(kPROF, signature); 444 out->SetStringPiece(kPROF, signature);
415 } 445 }
416 break; 446 break;
417 } 447 }
418 } 448 }
419 449
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 498
469 string hkdf_suffix; 499 string hkdf_suffix;
470 const QuicData& client_hello_serialized = client_hello.GetSerialized(); 500 const QuicData& client_hello_serialized = client_hello.GetSerialized();
471 hkdf_suffix.reserve(sizeof(guid) + client_hello_serialized.length() + 501 hkdf_suffix.reserve(sizeof(guid) + client_hello_serialized.length() +
472 config->serialized.size()); 502 config->serialized.size());
473 hkdf_suffix.append(reinterpret_cast<char*>(&guid), sizeof(guid)); 503 hkdf_suffix.append(reinterpret_cast<char*>(&guid), sizeof(guid));
474 hkdf_suffix.append(client_hello_serialized.data(), 504 hkdf_suffix.append(client_hello_serialized.data(),
475 client_hello_serialized.length()); 505 client_hello_serialized.length());
476 hkdf_suffix.append(config->serialized); 506 hkdf_suffix.append(config->serialized);
477 507
508 StringPiece cetv_ciphertext;
509 if (config->channel_id_enabled &&
510 client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
511 CryptoHandshakeMessage client_hello_copy(client_hello);
512 client_hello_copy.Erase(kCETV);
513 client_hello_copy.Erase(kPAD);
514
515 const QuicData& client_hello_serialized = client_hello_copy.GetSerialized();
516 string hkdf_input;
517 hkdf_input.append(QuicCryptoConfig::kCETVLabel,
518 strlen(QuicCryptoConfig::kCETVLabel) + 1);
519 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
520 hkdf_input.append(client_hello_serialized.data(),
521 client_hello_serialized.length());
522 hkdf_input.append(config->serialized);
523
524 CrypterPair crypters;
525 CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
526 client_nonce, server_nonce, hkdf_input,
527 CryptoUtils::SERVER, &crypters);
528
529 scoped_ptr<QuicData> cetv_plaintext(crypters.decrypter->DecryptPacket(
530 0 /* sequence number */, StringPiece() /* associated data */,
531 cetv_ciphertext));
532 if (!cetv_plaintext.get()) {
533 *error_details = "CETV decryption failure";
534 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
535 }
536
537 scoped_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
538 cetv_plaintext->AsStringPiece()));
539 if (!cetv.get()) {
540 *error_details = "CETV parse error";
541 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
542 }
543
544 StringPiece key, signature;
545 if (cetv->GetStringPiece(kCIDK, &key) &&
546 cetv->GetStringPiece(kCIDS, &signature)) {
547 if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
548 *error_details = "ChannelID signature failure";
549 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
550 }
551
552 params->channel_id = key.as_string();
553 }
554 }
555
478 string hkdf_input; 556 string hkdf_input;
479 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; 557 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
480 hkdf_input.reserve(label_len + hkdf_suffix.size()); 558 hkdf_input.reserve(label_len + hkdf_suffix.size());
481 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); 559 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
482 hkdf_input.append(hkdf_suffix); 560 hkdf_input.append(hkdf_suffix);
483 561
484 CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead, 562 CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
485 client_nonce, params->server_nonce, hkdf_input, 563 client_nonce, server_nonce, hkdf_input,
486 CryptoUtils::SERVER, &params->initial_crypters); 564 CryptoUtils::SERVER, &params->initial_crypters);
487 565
488 string forward_secure_public_value; 566 string forward_secure_public_value;
489 if (ephemeral_key_source_.get()) { 567 if (ephemeral_key_source_.get()) {
490 params->forward_secure_premaster_secret = 568 params->forward_secure_premaster_secret =
491 ephemeral_key_source_->CalculateForwardSecureKey( 569 ephemeral_key_source_->CalculateForwardSecureKey(
492 key_exchange, rand, clock->ApproximateNow(), public_value, 570 key_exchange, rand, clock->ApproximateNow(), public_value,
493 &forward_secure_public_value); 571 &forward_secure_public_value);
494 } else { 572 } else {
495 scoped_ptr<KeyExchange> forward_secure_key_exchange( 573 scoped_ptr<KeyExchange> forward_secure_key_exchange(
496 key_exchange->NewKeyPair(rand)); 574 key_exchange->NewKeyPair(rand));
497 forward_secure_public_value = 575 forward_secure_public_value =
498 forward_secure_key_exchange->public_value().as_string(); 576 forward_secure_key_exchange->public_value().as_string();
499 if (!forward_secure_key_exchange->CalculateSharedKey( 577 if (!forward_secure_key_exchange->CalculateSharedKey(
500 public_value, &params->forward_secure_premaster_secret)) { 578 public_value, &params->forward_secure_premaster_secret)) {
501 *error_details = "Invalid public value"; 579 *error_details = "Invalid public value";
502 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 580 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
503 } 581 }
504 } 582 }
505 583
506 string forward_secure_hkdf_input; 584 string forward_secure_hkdf_input;
507 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1; 585 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
508 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size()); 586 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
509 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, 587 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
510 label_len); 588 label_len);
511 forward_secure_hkdf_input.append(hkdf_suffix); 589 forward_secure_hkdf_input.append(hkdf_suffix);
512 590
513 CryptoUtils::DeriveKeys(params->forward_secure_premaster_secret, params->aead, 591 CryptoUtils::DeriveKeys(params->forward_secure_premaster_secret, params->aead,
514 client_nonce, params->server_nonce, 592 client_nonce, server_nonce, forward_secure_hkdf_input,
515 forward_secure_hkdf_input, CryptoUtils::SERVER, 593 CryptoUtils::SERVER,
516 &params->forward_secure_crypters); 594 &params->forward_secure_crypters);
517 595
518 out->set_tag(kSHLO); 596 out->set_tag(kSHLO);
519 out->SetStringPiece(kSourceAddressTokenTag, fresh_source_address_token); 597 out->SetStringPiece(kSourceAddressTokenTag,
598 NewSourceAddressToken(client_ip, rand, now));
520 out->SetStringPiece(kPUBS, forward_secure_public_value); 599 out->SetStringPiece(kPUBS, forward_secure_public_value);
521 return QUIC_NO_ERROR; 600 return QUIC_NO_ERROR;
522 } 601 }
523 602
524 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) { 603 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
525 proof_source_.reset(proof_source); 604 proof_source_.reset(proof_source);
526 } 605 }
527 606
528 void QuicCryptoServerConfig::SetEphemeralKeySource( 607 void QuicCryptoServerConfig::SetEphemeralKeySource(
529 EphemeralKeySource* ephemeral_key_source) { 608 EphemeralKeySource* ephemeral_key_source) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 } 674 }
596 675
597 if (now.IsAfter(timestamp) && 676 if (now.IsAfter(timestamp) &&
598 delta.ToSeconds() > source_address_token_lifetime_secs_) { 677 delta.ToSeconds() > source_address_token_lifetime_secs_) {
599 return false; 678 return false;
600 } 679 }
601 680
602 return true; 681 return true;
603 } 682 }
604 683
605 QuicCryptoServerConfig::Config::Config() {} 684 // kServerNoncePlaintextSize is the number of bytes in an unencrypted server
685 // nonce.
686 static const size_t kServerNoncePlaintextSize =
687 4 /* timestamp */ + 20 /* random bytes */;
688
689 string QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
690 QuicWallTime now) const {
691 const uint32 timestamp = static_cast<uint32>(now.ToUNIXSeconds());
692
693 uint8 server_nonce[kServerNoncePlaintextSize];
694 COMPILE_ASSERT(sizeof(server_nonce) > sizeof(timestamp), nonce_too_small);
695 server_nonce[0] = static_cast<uint8>(timestamp >> 24);
696 server_nonce[1] = static_cast<uint8>(timestamp >> 16);
697 server_nonce[2] = static_cast<uint8>(timestamp >> 8);
698 server_nonce[3] = static_cast<uint8>(timestamp);
699 rand->RandBytes(&server_nonce[sizeof(timestamp)],
700 sizeof(server_nonce) - sizeof(timestamp));
701
702 return server_nonce_boxer_.Box(
703 rand,
704 StringPiece(reinterpret_cast<char*>(server_nonce), sizeof(server_nonce)));
705 }
706
707 bool QuicCryptoServerConfig::ValidateServerNonce(StringPiece token,
708 QuicWallTime now) const {
709 string storage;
710 StringPiece plaintext;
711 if (!server_nonce_boxer_.Unbox(token, &storage, &plaintext)) {
712 return false;
713 }
714
715 // plaintext contains:
716 // uint32 timestamp
717 // uint8[20] random bytes
718
719 if (plaintext.size() != kServerNoncePlaintextSize) {
720 // This should never happen because the value decrypted correctly.
721 LOG(DFATAL) << "Seemingly valid server nonce had incorrect length.";
722 return false;
723 }
724
725 uint8 server_nonce[32];
726 memcpy(server_nonce, plaintext.data(), 4);
727 memcpy(server_nonce + 4, server_nonce_orbit_, sizeof(server_nonce_orbit_));
728 memcpy(server_nonce + 4 + sizeof(server_nonce_orbit_), plaintext.data() + 4,
729 20);
730 COMPILE_ASSERT(4 + sizeof(server_nonce_orbit_) + 20 == sizeof(server_nonce),
731 bad_nonce_buffer_length);
732
733 bool is_unique;
734 {
735 base::AutoLock auto_lock(server_nonce_strike_register_lock_);
736 if (server_nonce_strike_register_.get() == NULL) {
737 server_nonce_strike_register_.reset(new StrikeRegister(
738 server_nonce_strike_register_max_entries_,
739 static_cast<uint32>(now.ToUNIXSeconds()),
740 server_nonce_strike_register_window_secs_, server_nonce_orbit_,
741 StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
742 }
743 is_unique = server_nonce_strike_register_->Insert(
744 server_nonce, static_cast<uint32>(now.ToUNIXSeconds()));
745 }
746
747 return is_unique;
748 }
749
750 QuicCryptoServerConfig::Config::Config() : channel_id_enabled(false) { }
606 751
607 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); } 752 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }
608 753
609 } // namespace net 754 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698