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

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

Issue 14816006: Land Recent QUIC changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added missing NET_PRIVATE_EXPORT to QuicWallTime Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/quic/crypto/crypto_server_config.h ('k') | net/quic/crypto/crypto_server_config_protobuf.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/crypto/crypto_server_config.h" 5 #include "net/quic/crypto/crypto_server_config.h"
6 6
7 #include "base/stl_util.h" 7 #include "base/stl_util.h"
8 #include "crypto/hkdf.h" 8 #include "crypto/hkdf.h"
9 #include "crypto/secure_hash.h" 9 #include "crypto/secure_hash.h"
10 #include "net/quic/crypto/aes_128_gcm_decrypter.h" 10 #include "net/quic/crypto/aes_128_gcm_decrypter.h"
11 #include "net/quic/crypto/aes_128_gcm_encrypter.h" 11 #include "net/quic/crypto/aes_128_gcm_encrypter.h"
12 #include "net/quic/crypto/cert_compressor.h" 12 #include "net/quic/crypto/cert_compressor.h"
13 #include "net/quic/crypto/crypto_framer.h" 13 #include "net/quic/crypto/crypto_framer.h"
14 #include "net/quic/crypto/crypto_server_config_protobuf.h" 14 #include "net/quic/crypto/crypto_server_config_protobuf.h"
15 #include "net/quic/crypto/crypto_utils.h" 15 #include "net/quic/crypto/crypto_utils.h"
16 #include "net/quic/crypto/curve25519_key_exchange.h" 16 #include "net/quic/crypto/curve25519_key_exchange.h"
17 #include "net/quic/crypto/ephemeral_key_source.h"
17 #include "net/quic/crypto/key_exchange.h" 18 #include "net/quic/crypto/key_exchange.h"
18 #include "net/quic/crypto/p256_key_exchange.h" 19 #include "net/quic/crypto/p256_key_exchange.h"
19 #include "net/quic/crypto/proof_source.h" 20 #include "net/quic/crypto/proof_source.h"
20 #include "net/quic/crypto/quic_decrypter.h" 21 #include "net/quic/crypto/quic_decrypter.h"
21 #include "net/quic/crypto/quic_encrypter.h" 22 #include "net/quic/crypto/quic_encrypter.h"
22 #include "net/quic/crypto/quic_random.h" 23 #include "net/quic/crypto/quic_random.h"
23 #include "net/quic/crypto/source_address_token.h" 24 #include "net/quic/crypto/source_address_token.h"
24 #include "net/quic/crypto/strike_register.h" 25 #include "net/quic/crypto/strike_register.h"
25 #include "net/quic/quic_clock.h" 26 #include "net/quic/quic_clock.h"
26 #include "net/quic/quic_protocol.h" 27 #include "net/quic/quic_protocol.h"
(...skipping 18 matching lines...) Expand all
45 // probability 0.5 after 2**48 values. We assume that obtaining 2**48 46 // probability 0.5 after 2**48 values. We assume that obtaining 2**48
46 // source address tokens is not possible: at a rate of 10M packets per 47 // source address tokens is not possible: at a rate of 10M packets per
47 // second, it would still take the attacker a year to obtain the needed 48 // second, it would still take the attacker a year to obtain the needed
48 // number of packets. 49 // number of packets.
49 // 50 //
50 // TODO(agl): switch to an encrypter with a larger nonce space (i.e. 51 // TODO(agl): switch to an encrypter with a larger nonce space (i.e.
51 // Salsa20+Poly1305). 52 // Salsa20+Poly1305).
52 : strike_register_lock_(), 53 : strike_register_lock_(),
53 source_address_token_encrypter_(new Aes128GcmEncrypter), 54 source_address_token_encrypter_(new Aes128GcmEncrypter),
54 source_address_token_decrypter_(new Aes128GcmDecrypter) { 55 source_address_token_decrypter_(new Aes128GcmDecrypter) {
55 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */, 56 crypto::HKDF hkdf(source_address_token_secret, StringPiece() /* no salt */,
56 "QUIC source address token key", 57 "QUIC source address token key",
57 source_address_token_encrypter_->GetKeySize(), 58 source_address_token_encrypter_->GetKeySize(),
58 0 /* no fixed IV needed */); 59 0 /* no fixed IV needed */);
59 source_address_token_encrypter_->SetKey(hkdf.server_write_key()); 60 source_address_token_encrypter_->SetKey(hkdf.server_write_key());
60 source_address_token_decrypter_->SetKey(hkdf.server_write_key()); 61 source_address_token_decrypter_->SetKey(hkdf.server_write_key());
61 } 62 }
62 63
63 QuicCryptoServerConfig::~QuicCryptoServerConfig() { 64 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
64 STLDeleteValues(&configs_); 65 STLDeleteValues(&configs_);
65 } 66 }
66 67
67 // static 68 // static
68 QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig( 69 QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
69 QuicRandom* rand, 70 QuicRandom* rand,
70 const QuicClock* clock, 71 const QuicClock* clock,
71 const CryptoHandshakeMessage& extra_tags) { 72 const CryptoHandshakeMessage& extra_tags,
73 uint64 expiry_time) {
72 CryptoHandshakeMessage msg; 74 CryptoHandshakeMessage msg;
73 75
74 const string curve25519_private_key = 76 const string curve25519_private_key =
75 Curve25519KeyExchange::NewPrivateKey(rand); 77 Curve25519KeyExchange::NewPrivateKey(rand);
76 scoped_ptr<Curve25519KeyExchange> curve25519( 78 scoped_ptr<Curve25519KeyExchange> curve25519(
77 Curve25519KeyExchange::New(curve25519_private_key)); 79 Curve25519KeyExchange::New(curve25519_private_key));
78 StringPiece curve25519_public_value = curve25519->public_value(); 80 StringPiece curve25519_public_value = curve25519->public_value();
79 81
80 const string p256_private_key = 82 const string p256_private_key = P256KeyExchange::NewPrivateKey();
81 P256KeyExchange::NewPrivateKey(); 83 scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
82 scoped_ptr<P256KeyExchange> p256(
83 P256KeyExchange::New(p256_private_key));
84 StringPiece p256_public_value = p256->public_value(); 84 StringPiece p256_public_value = p256->public_value();
85 85
86 string encoded_public_values; 86 string encoded_public_values;
87 // First two bytes encode the length of the public value. 87 // First three bytes encode the length of the public value.
88 encoded_public_values.push_back(curve25519_public_value.size()); 88 encoded_public_values.push_back(curve25519_public_value.size());
89 encoded_public_values.push_back(curve25519_public_value.size() >> 8); 89 encoded_public_values.push_back(curve25519_public_value.size() >> 8);
90 encoded_public_values.push_back(curve25519_public_value.size() >> 16);
90 encoded_public_values.append(curve25519_public_value.data(), 91 encoded_public_values.append(curve25519_public_value.data(),
91 curve25519_public_value.size()); 92 curve25519_public_value.size());
92 encoded_public_values.push_back(p256_public_value.size()); 93 encoded_public_values.push_back(p256_public_value.size());
93 encoded_public_values.push_back(p256_public_value.size() >> 8); 94 encoded_public_values.push_back(p256_public_value.size() >> 8);
95 encoded_public_values.push_back(p256_public_value.size() >> 16);
94 encoded_public_values.append(p256_public_value.data(), 96 encoded_public_values.append(p256_public_value.data(),
95 p256_public_value.size()); 97 p256_public_value.size());
96 98
97 msg.set_tag(kSCFG); 99 msg.set_tag(kSCFG);
98 msg.SetTaglist(kKEXS, kC255, kP256, 0); 100 msg.SetTaglist(kKEXS, kC255, kP256, 0);
99 msg.SetTaglist(kAEAD, kAESG, 0); 101 msg.SetTaglist(kAEAD, kAESG, 0);
100 msg.SetValue(kVERS, static_cast<uint16>(0)); 102 msg.SetValue(kVERS, static_cast<uint16>(0));
101 msg.SetStringPiece(kPUBS, encoded_public_values); 103 msg.SetStringPiece(kPUBS, encoded_public_values);
102 msg.Insert(extra_tags.tag_value_map().begin(), 104 msg.Insert(extra_tags.tag_value_map().begin(),
103 extra_tags.tag_value_map().end()); 105 extra_tags.tag_value_map().end());
104 106
107 if (expiry_time == 0) {
108 const QuicWallTime now = clock->WallNow();
109 const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
110 60 * 60 * 24 * 180 /* 180 days, ~six months */));
111 const uint64 expiry_seconds = expiry.ToUNIXSeconds();
112 msg.SetValue(kEXPY, expiry_seconds);
113 } else {
114 msg.SetValue(kEXPY, expiry_time);
115 }
116
105 char scid_bytes[16]; 117 char scid_bytes[16];
106 rand->RandBytes(scid_bytes, sizeof(scid_bytes)); 118 rand->RandBytes(scid_bytes, sizeof(scid_bytes));
107 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes))); 119 msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
108 120
109 char orbit_bytes[kOrbitSize]; 121 char orbit_bytes[kOrbitSize];
110 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes)); 122 rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
111 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes))); 123 msg.SetStringPiece(kORBT, StringPiece(orbit_bytes, sizeof(orbit_bytes)));
112 124
113 scoped_ptr<QuicData> serialized( 125 scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg));
114 CryptoFramer::ConstructHandshakeMessage(msg));
115 126
116 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf); 127 scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
117 config->set_config(serialized->AsStringPiece()); 128 config->set_config(serialized->AsStringPiece());
118 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key(); 129 QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
119 curve25519_key->set_tag(kC255); 130 curve25519_key->set_tag(kC255);
120 curve25519_key->set_private_key(curve25519_private_key); 131 curve25519_key->set_private_key(curve25519_private_key);
121 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key(); 132 QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
122 p256_key->set_tag(kP256); 133 p256_key->set_tag(kP256);
123 p256_key->set_private_key(p256_private_key); 134 p256_key->set_private_key(p256_private_key);
124 135
125 return config.release(); 136 return config.release();
126 } 137 }
127 138
128 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig( 139 CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
129 QuicServerConfigProtobuf* protobuf) { 140 QuicServerConfigProtobuf* protobuf) {
130 scoped_ptr<CryptoHandshakeMessage> msg( 141 scoped_ptr<CryptoHandshakeMessage> msg(
131 CryptoFramer::ParseMessage(protobuf->config())); 142 CryptoFramer::ParseMessage(protobuf->config()));
132 143
133 if (!msg.get()) { 144 if (!msg.get()) {
134 LOG(WARNING) << "Failed to parse server config message"; 145 LOG(WARNING) << "Failed to parse server config message";
135 return NULL; 146 return NULL;
136 } 147 }
137 if (msg->tag() != kSCFG) { 148 if (msg->tag() != kSCFG) {
138 LOG(WARNING) << "Server config message has tag " 149 LOG(WARNING) << "Server config message has tag " << msg->tag()
139 << msg->tag() << " expected " 150 << " expected " << kSCFG;
140 << kSCFG;
141 return NULL; 151 return NULL;
142 } 152 }
143 153
144 scoped_ptr<Config> config(new Config); 154 scoped_ptr<Config> config(new Config);
145 config->serialized = protobuf->config(); 155 config->serialized = protobuf->config();
146 156
147 StringPiece scid; 157 StringPiece scid;
148 if (!msg->GetStringPiece(kSCID, &scid)) { 158 if (!msg->GetStringPiece(kSCID, &scid)) {
149 LOG(WARNING) << "Server config message is missing SCID"; 159 LOG(WARNING) << "Server config message is missing SCID";
150 return NULL; 160 return NULL;
151 } 161 }
152 config->id = scid.as_string(); 162 config->id = scid.as_string();
153 163
154 const CryptoTag* aead_tags; 164 const QuicTag* aead_tags;
155 size_t aead_len; 165 size_t aead_len;
156 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) { 166 if (msg->GetTaglist(kAEAD, &aead_tags, &aead_len) != QUIC_NO_ERROR) {
157 LOG(WARNING) << "Server config message is missing AEAD"; 167 LOG(WARNING) << "Server config message is missing AEAD";
158 return NULL; 168 return NULL;
159 } 169 }
160 config->aead = vector<CryptoTag>(aead_tags, aead_tags + aead_len); 170 config->aead = vector<QuicTag>(aead_tags, aead_tags + aead_len);
161 171
162 const CryptoTag* kexs_tags; 172 const QuicTag* kexs_tags;
163 size_t kexs_len; 173 size_t kexs_len;
164 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) { 174 if (msg->GetTaglist(kKEXS, &kexs_tags, &kexs_len) != QUIC_NO_ERROR) {
165 LOG(WARNING) << "Server config message is missing KEXS"; 175 LOG(WARNING) << "Server config message is missing KEXS";
166 return NULL; 176 return NULL;
167 } 177 }
168 178
169 StringPiece orbit; 179 StringPiece orbit;
170 if (!msg->GetStringPiece(kORBT, &orbit)) { 180 if (!msg->GetStringPiece(kORBT, &orbit)) {
171 LOG(WARNING) << "Server config message is missing OBIT"; 181 LOG(WARNING) << "Server config message is missing OBIT";
172 return NULL; 182 return NULL;
173 } 183 }
174 184
175 if (orbit.size() != kOrbitSize) { 185 if (orbit.size() != kOrbitSize) {
176 LOG(WARNING) << "Orbit value in server config is the wrong length." 186 LOG(WARNING) << "Orbit value in server config is the wrong length."
177 " Got " << orbit.size() << " want " << kOrbitSize; 187 " Got " << orbit.size() << " want " << kOrbitSize;
178 return NULL; 188 return NULL;
179 } 189 }
180 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size); 190 COMPILE_ASSERT(sizeof(config->orbit) == kOrbitSize, orbit_incorrect_size);
181 memcpy(config->orbit, orbit.data(), sizeof(config->orbit)); 191 memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
182 192
183 if (kexs_len != protobuf->key_size()) { 193 if (kexs_len != protobuf->key_size()) {
184 LOG(WARNING) << "Server config has " 194 LOG(WARNING) << "Server config has " << kexs_len
185 << kexs_len
186 << " key exchange methods configured, but " 195 << " key exchange methods configured, but "
187 << protobuf->key_size() 196 << protobuf->key_size() << " private keys";
188 << " private keys";
189 return NULL; 197 return NULL;
190 } 198 }
191 199
192 for (size_t i = 0; i < kexs_len; i++) { 200 for (size_t i = 0; i < kexs_len; i++) {
193 const CryptoTag tag = kexs_tags[i]; 201 const QuicTag tag = kexs_tags[i];
194 string private_key; 202 string private_key;
195 203
196 config->kexs.push_back(tag); 204 config->kexs.push_back(tag);
197 205
198 for (size_t j = 0; j < protobuf->key_size(); j++) { 206 for (size_t j = 0; j < protobuf->key_size(); j++) {
199 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i); 207 const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
200 if (key.tag() == tag) { 208 if (key.tag() == tag) {
201 private_key = key.private_key(); 209 private_key = key.private_key();
202 break; 210 break;
203 } 211 }
204 } 212 }
205 213
206 if (private_key.empty()) { 214 if (private_key.empty()) {
207 LOG(WARNING) << "Server config contains key exchange method without " 215 LOG(WARNING) << "Server config contains key exchange method without "
208 "corresponding private key: " 216 "corresponding private key: " << tag;
209 << tag;
210 return NULL; 217 return NULL;
211 } 218 }
212 219
213 scoped_ptr<KeyExchange> ka; 220 scoped_ptr<KeyExchange> ka;
214 switch (tag) { 221 switch (tag) {
215 case kC255: 222 case kC255:
216 ka.reset(Curve25519KeyExchange::New(private_key)); 223 ka.reset(Curve25519KeyExchange::New(private_key));
217 if (!ka.get()) { 224 if (!ka.get()) {
218 LOG(WARNING) << "Server config contained an invalid curve25519" 225 LOG(WARNING) << "Server config contained an invalid curve25519"
219 " private key."; 226 " private key.";
227 return NULL;
228 }
229 break;
230 case kP256:
231 ka.reset(P256KeyExchange::New(private_key));
232 if (!ka.get()) {
233 LOG(WARNING) << "Server config contained an invalid P-256"
234 " private key.";
235 return NULL;
236 }
237 break;
238 default:
239 LOG(WARNING) << "Server config message contains unknown key exchange "
240 "method: " << tag;
220 return NULL; 241 return NULL;
221 }
222 break;
223 case kP256:
224 ka.reset(P256KeyExchange::New(private_key));
225 if (!ka.get()) {
226 LOG(WARNING) << "Server config contained an invalid P-256"
227 " private key.";
228 return NULL;
229 }
230 break;
231 default:
232 LOG(WARNING) << "Server config message contains unknown key exchange "
233 "method: "
234 << tag;
235 return NULL;
236 } 242 }
237 243
238 for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin(); 244 for (vector<KeyExchange*>::const_iterator i = config->key_exchanges.begin();
239 i != config->key_exchanges.end(); ++i) { 245 i != config->key_exchanges.end(); ++i) {
240 if ((*i)->tag() == tag) { 246 if ((*i)->tag() == tag) {
241 LOG(WARNING) << "Duplicate key exchange in config: " << tag; 247 LOG(WARNING) << "Duplicate key exchange in config: " << tag;
242 return NULL; 248 return NULL;
243 } 249 }
244 } 250 }
245 251
(...skipping 18 matching lines...) Expand all
264 270
265 configs_[id] = config.release(); 271 configs_[id] = config.release();
266 active_config_ = id; 272 active_config_ = id;
267 273
268 return msg.release(); 274 return msg.release();
269 } 275 }
270 276
271 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig( 277 CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
272 QuicRandom* rand, 278 QuicRandom* rand,
273 const QuicClock* clock, 279 const QuicClock* clock,
274 const CryptoHandshakeMessage& extra_tags) { 280 const CryptoHandshakeMessage& extra_tags,
281 uint64 expiry_time) {
275 scoped_ptr<QuicServerConfigProtobuf> config(DefaultConfig( 282 scoped_ptr<QuicServerConfigProtobuf> config(DefaultConfig(
276 rand, clock, extra_tags)); 283 rand, clock, extra_tags, expiry_time));
277 return AddConfig(config.get()); 284 return AddConfig(config.get());
278 } 285 }
279 286
280 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello( 287 QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
281 const CryptoHandshakeMessage& client_hello, 288 const CryptoHandshakeMessage& client_hello,
282 QuicGuid guid, 289 QuicGuid guid,
283 const IPEndPoint& client_ip, 290 const IPEndPoint& client_ip,
284 QuicTime::Delta now_since_unix_epoch, 291 const QuicClock* clock,
285 QuicRandom* rand, 292 QuicRandom* rand,
286 QuicCryptoNegotiatedParameters *params, 293 QuicCryptoNegotiatedParameters *params,
287 CryptoHandshakeMessage* out, 294 CryptoHandshakeMessage* out,
288 string* error_details) const { 295 string* error_details) const {
289 DCHECK(error_details); 296 DCHECK(error_details);
290 297
291 CHECK(!configs_.empty()); 298 CHECK(!configs_.empty());
292 299
293 // FIXME(agl): we should use the client's SCID, not just the active config. 300 // FIXME(agl): we should use the client's SCID, not just the active config.
294 map<ServerConfigID, Config*>::const_iterator it = 301 map<ServerConfigID, Config*>::const_iterator it =
295 configs_.find(active_config_); 302 configs_.find(active_config_);
296 if (it == configs_.end()) { 303 if (it == configs_.end()) {
297 *error_details = "No valid server config loaded"; 304 *error_details = "No valid server config loaded";
298 return QUIC_CRYPTO_INTERNAL_ERROR; 305 return QUIC_CRYPTO_INTERNAL_ERROR;
299 } 306 }
300 const Config* const config(it->second); 307 const Config* const config(it->second);
301 308
309 const QuicWallTime now = clock->WallNow();
302 bool valid_source_address_token = false; 310 bool valid_source_address_token = false;
303 StringPiece srct; 311 StringPiece srct;
304 if (client_hello.GetStringPiece(kSRCT, &srct) && 312 if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) &&
305 ValidateSourceAddressToken(srct, client_ip, now_since_unix_epoch)) { 313 ValidateSourceAddressToken(srct, client_ip, now)) {
306 valid_source_address_token = true; 314 valid_source_address_token = true;
307 } 315 }
308 316
309 const string fresh_source_address_token = 317 const string fresh_source_address_token =
310 NewSourceAddressToken(client_ip, rand, now_since_unix_epoch); 318 NewSourceAddressToken(client_ip, rand, now);
311 319
312 // If we previously sent a REJ to this client then we may have stored a 320 // If we previously sent a REJ to this client then we may have stored a
313 // server nonce in |params|. In which case, we know that the connection 321 // server nonce in |params|. In which case, we know that the connection
314 // is unique because the server nonce will be mixed into the key generation. 322 // is unique because the server nonce will be mixed into the key generation.
315 bool unique_by_server_nonce = !params->server_nonce.empty(); 323 bool unique_by_server_nonce = !params->server_nonce.empty();
316 // If we can't ensure uniqueness by a server nonce, then we will try and use 324 // If we can't ensure uniqueness by a server nonce, then we will try and use
317 // the strike register. 325 // the strike register.
318 bool unique_by_strike_register = false; 326 bool unique_by_strike_register = false;
319 327
320 StringPiece client_nonce; 328 StringPiece client_nonce;
321 bool client_nonce_well_formed = false; 329 bool client_nonce_well_formed = false;
322 if (client_hello.GetStringPiece(kNONC, &client_nonce) && 330 if (client_hello.GetStringPiece(kNONC, &client_nonce) &&
323 client_nonce.size() == kNonceSize) { 331 client_nonce.size() == kNonceSize) {
324 client_nonce_well_formed = true; 332 client_nonce_well_formed = true;
325 base::AutoLock auto_lock(strike_register_lock_); 333 base::AutoLock auto_lock(strike_register_lock_);
326 334
327 if (strike_register_.get() == NULL) { 335 if (strike_register_.get() == NULL) {
328 strike_register_.reset(new StrikeRegister( 336 strike_register_.reset(new StrikeRegister(
329 // TODO(agl): these magic numbers should come from config. 337 // TODO(agl): these magic numbers should come from config.
330 1024 /* max entries */, 338 1024 /* max entries */,
331 static_cast<uint32>(now_since_unix_epoch.ToSeconds()), 339 static_cast<uint32>(now.ToUNIXSeconds()),
332 600 /* window secs */, config->orbit)); 340 600 /* window secs */, config->orbit));
333 } 341 }
334 unique_by_strike_register = strike_register_->Insert( 342 unique_by_strike_register = strike_register_->Insert(
335 reinterpret_cast<const uint8*>(client_nonce.data()), 343 reinterpret_cast<const uint8*>(client_nonce.data()),
336 static_cast<uint32>(now_since_unix_epoch.ToSeconds())); 344 static_cast<uint32>(now.ToUNIXSeconds()));
337 } 345 }
338 346
347 StringPiece server_nonce;
348 client_hello.GetStringPiece(kServerNonceTag, &server_nonce);
349 const bool server_nonce_matches = server_nonce == params->server_nonce;
350
339 out->Clear(); 351 out->Clear();
340 352
341 StringPiece sni; 353 StringPiece sni;
342 client_hello.GetStringPiece(kSNI, &sni); 354 client_hello.GetStringPiece(kSNI, &sni);
343 355
344 StringPiece scid; 356 StringPiece scid;
345 if (!client_hello.GetStringPiece(kSCID, &scid) || 357 if (!client_hello.GetStringPiece(kSCID, &scid) ||
346 scid.as_string() != config->id || 358 scid.as_string() != config->id ||
347 !valid_source_address_token || 359 !valid_source_address_token ||
348 !client_nonce_well_formed || 360 !client_nonce_well_formed ||
361 !server_nonce_matches ||
349 (!unique_by_strike_register && 362 (!unique_by_strike_register &&
350 !unique_by_server_nonce)) { 363 !unique_by_server_nonce)) {
351 // If the client didn't provide a server config ID, or gave the wrong one, 364 // If the client didn't provide a server config ID, or gave the wrong one,
352 // then the handshake cannot possibly complete. We reject the handshake and 365 // then the handshake cannot possibly complete. We reject the handshake and
353 // give the client enough information to do better next time. 366 // give the client enough information to do better next time.
354 out->set_tag(kREJ); 367 out->set_tag(kREJ);
355 out->SetStringPiece(kSCFG, config->serialized); 368 out->SetStringPiece(kSCFG, config->serialized);
356 out->SetStringPiece(kSRCT, fresh_source_address_token); 369 out->SetStringPiece(kSourceAddressTokenTag, fresh_source_address_token);
357 if (params->server_nonce.empty()) { 370 if (params->server_nonce.empty()) {
358 CryptoUtils::GenerateNonce( 371 CryptoUtils::GenerateNonce(
359 now_since_unix_epoch, rand, 372 now, rand, StringPiece(reinterpret_cast<const char*>(config->orbit),
360 StringPiece(reinterpret_cast<const char*>(config->orbit), 373 sizeof(config->orbit)),
361 sizeof(config->orbit)),
362 &params->server_nonce); 374 &params->server_nonce);
363 } 375 }
364 out->SetStringPiece(kNONC, params->server_nonce); 376 out->SetStringPiece(kServerNonceTag, params->server_nonce);
365 377
366 // The client may have requested a certificate chain. 378 // The client may have requested a certificate chain.
367 const CryptoTag* their_proof_demands; 379 const QuicTag* their_proof_demands;
368 size_t num_their_proof_demands; 380 size_t num_their_proof_demands;
369 381
370 if (proof_source_.get() != NULL && 382 if (proof_source_.get() != NULL && !sni.empty() &&
371 !sni.empty() &&
372 client_hello.GetTaglist(kPDMD, &their_proof_demands, 383 client_hello.GetTaglist(kPDMD, &their_proof_demands,
373 &num_their_proof_demands) == QUIC_NO_ERROR) { 384 &num_their_proof_demands) == QUIC_NO_ERROR) {
374 for (size_t i = 0; i < num_their_proof_demands; i++) { 385 for (size_t i = 0; i < num_their_proof_demands; i++) {
375 if (their_proof_demands[i] != kX509) { 386 if (their_proof_demands[i] != kX509) {
376 continue; 387 continue;
377 } 388 }
378 389
379 const vector<string>* certs; 390 const vector<string>* certs;
380 string signature; 391 string signature;
381 if (!proof_source_->GetProof(sni.as_string(), config->serialized, 392 if (!proof_source_->GetProof(sni.as_string(), config->serialized,
382 &certs, &signature)) { 393 &certs, &signature)) {
383 break; 394 break;
384 } 395 }
385 396
386 StringPiece their_common_set_hashes; 397 StringPiece their_common_set_hashes;
387 StringPiece their_cached_cert_hashes; 398 StringPiece their_cached_cert_hashes;
388 client_hello.GetStringPiece(kCCS, &their_common_set_hashes); 399 client_hello.GetStringPiece(kCCS, &their_common_set_hashes);
389 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes); 400 client_hello.GetStringPiece(kCCRT, &their_cached_cert_hashes);
390 401
391 const string compressed = CertCompressor::CompressChain( 402 const string compressed = CertCompressor::CompressChain(
392 *certs, their_common_set_hashes, their_cached_cert_hashes, 403 *certs, their_common_set_hashes, their_cached_cert_hashes,
393 config->common_cert_set_.get()); 404 config->common_cert_set_.get());
394 405
395 // kMaxUnverifiedSize is the number of bytes that the certificate chain 406 // kMaxUnverifiedSize is the number of bytes that the certificate chain
396 // and signature can consume before we will demand a valid 407 // and signature can consume before we will demand a valid
397 // source-address token. 408 // source-address token.
398 static const size_t kMaxUnverifiedSize = 400; 409 static const size_t kMaxUnverifiedSize = 400;
399 if (valid_source_address_token || 410 if (valid_source_address_token ||
400 signature.size() + compressed.size() < kMaxUnverifiedSize) { 411 signature.size() + compressed.size() < kMaxUnverifiedSize) {
401 out->SetStringPiece(kCERT, compressed); 412 out->SetStringPiece(kCertificateTag, compressed);
402 out->SetStringPiece(kPROF, signature); 413 out->SetStringPiece(kPROF, signature);
403 } 414 }
404 break; 415 break;
405 } 416 }
406 } 417 }
407 418
408 return QUIC_NO_ERROR; 419 return QUIC_NO_ERROR;
409 } 420 }
410 421
411 const CryptoTag* their_aeads; 422 const QuicTag* their_aeads;
412 const CryptoTag* their_key_exchanges; 423 const QuicTag* their_key_exchanges;
413 size_t num_their_aeads, num_their_key_exchanges; 424 size_t num_their_aeads, num_their_key_exchanges;
414 if (client_hello.GetTaglist(kAEAD, &their_aeads, 425 if (client_hello.GetTaglist(kAEAD, &their_aeads,
415 &num_their_aeads) != QUIC_NO_ERROR || 426 &num_their_aeads) != QUIC_NO_ERROR ||
416 client_hello.GetTaglist(kKEXS, &their_key_exchanges, 427 client_hello.GetTaglist(kKEXS, &their_key_exchanges,
417 &num_their_key_exchanges) != QUIC_NO_ERROR || 428 &num_their_key_exchanges) != QUIC_NO_ERROR ||
418 num_their_aeads != 1 || 429 num_their_aeads != 1 ||
419 num_their_key_exchanges != 1) { 430 num_their_key_exchanges != 1) {
420 *error_details = "Missing or invalid AEAD or KEXS"; 431 *error_details = "Missing or invalid AEAD or KEXS";
421 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 432 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
422 } 433 }
423 434
424 size_t key_exchange_index; 435 size_t key_exchange_index;
425 if (!CryptoUtils::FindMutualTag(config->aead, 436 if (!CryptoUtils::FindMutualTag(config->aead, their_aeads, num_their_aeads,
426 their_aeads, num_their_aeads, 437 CryptoUtils::LOCAL_PRIORITY, &params->aead,
427 CryptoUtils::LOCAL_PRIORITY,
428 &params->aead,
429 NULL) || 438 NULL) ||
430 !CryptoUtils::FindMutualTag(config->kexs, 439 !CryptoUtils::FindMutualTag(
431 their_key_exchanges, num_their_key_exchanges, 440 config->kexs, their_key_exchanges, num_their_key_exchanges,
432 CryptoUtils::LOCAL_PRIORITY, 441 CryptoUtils::LOCAL_PRIORITY, &params->key_exchange,
433 &params->key_exchange, 442 &key_exchange_index)) {
434 &key_exchange_index)) {
435 *error_details = "Unsupported AEAD or KEXS"; 443 *error_details = "Unsupported AEAD or KEXS";
436 return QUIC_CRYPTO_NO_SUPPORT; 444 return QUIC_CRYPTO_NO_SUPPORT;
437 } 445 }
438 446
439 StringPiece public_value; 447 StringPiece public_value;
440 if (!client_hello.GetStringPiece(kPUBS, &public_value)) { 448 if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
441 *error_details = "Missing public value"; 449 *error_details = "Missing public value";
442 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 450 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
443 } 451 }
444 452
445 if (!config->key_exchanges[key_exchange_index]->CalculateSharedKey( 453 const KeyExchange* key_exchange = config->key_exchanges[key_exchange_index];
446 public_value, &params->premaster_secret)) { 454 if (!key_exchange->CalculateSharedKey(public_value,
455 &params->initial_premaster_secret)) {
447 *error_details = "Invalid public value"; 456 *error_details = "Invalid public value";
448 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 457 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
449 } 458 }
450 459
451 params->server_config_id = scid.as_string(); 460 params->server_config_id = scid.as_string();
452 461
453 string hkdf_input(QuicCryptoConfig::kLabel, 462 string hkdf_suffix;
454 strlen(QuicCryptoConfig::kLabel) + 1); 463 const QuicData& client_hello_serialized = client_hello.GetSerialized();
455 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid)); 464 hkdf_suffix.reserve(sizeof(guid) + client_hello_serialized.length() +
465 config->serialized.size());
466 hkdf_suffix.append(reinterpret_cast<char*>(&guid), sizeof(guid));
467 hkdf_suffix.append(client_hello_serialized.data(),
468 client_hello_serialized.length());
469 hkdf_suffix.append(config->serialized);
456 470
457 const QuicData& client_hello_serialized = client_hello.GetSerialized(); 471 string hkdf_input;
458 hkdf_input.append(client_hello_serialized.data(), 472 size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
459 client_hello_serialized.length()); 473 hkdf_input.reserve(label_len + hkdf_suffix.size());
460 hkdf_input.append(config->serialized); 474 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
475 hkdf_input.append(hkdf_suffix);
461 476
462 CryptoUtils::DeriveKeys(params, client_nonce, hkdf_input, 477 CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
463 CryptoUtils::SERVER); 478 client_nonce, params->server_nonce, hkdf_input,
479 CryptoUtils::SERVER, &params->initial_crypters);
480
481 string forward_secure_public_value;
482 if (ephemeral_key_source_.get()) {
483 params->forward_secure_premaster_secret =
484 ephemeral_key_source_->CalculateForwardSecureKey(
485 key_exchange, rand, clock->ApproximateNow(), public_value,
486 &forward_secure_public_value);
487 } else {
488 scoped_ptr<KeyExchange> forward_secure_key_exchange(
489 key_exchange->NewKeyPair(rand));
490 forward_secure_public_value =
491 forward_secure_key_exchange->public_value().as_string();
492 if (!forward_secure_key_exchange->CalculateSharedKey(
493 public_value, &params->forward_secure_premaster_secret)) {
494 *error_details = "Invalid public value";
495 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
496 }
497 }
498
499 string forward_secure_hkdf_input;
500 label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
501 forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
502 forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
503 label_len);
504 forward_secure_hkdf_input.append(hkdf_suffix);
505
506 CryptoUtils::DeriveKeys(params->forward_secure_premaster_secret, params->aead,
507 client_nonce, params->server_nonce,
508 forward_secure_hkdf_input, CryptoUtils::SERVER,
509 &params->forward_secure_crypters);
464 510
465 out->set_tag(kSHLO); 511 out->set_tag(kSHLO);
466 out->SetStringPiece(kSRCT, fresh_source_address_token); 512 out->SetStringPiece(kSourceAddressTokenTag, fresh_source_address_token);
513 out->SetStringPiece(kPUBS, forward_secure_public_value);
467 return QUIC_NO_ERROR; 514 return QUIC_NO_ERROR;
468 } 515 }
469 516
470 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) { 517 void QuicCryptoServerConfig::SetProofSource(ProofSource* proof_source) {
471 proof_source_.reset(proof_source); 518 proof_source_.reset(proof_source);
472 } 519 }
473 520
521 void QuicCryptoServerConfig::SetEphemeralKeySource(
522 EphemeralKeySource* ephemeral_key_source) {
523 ephemeral_key_source_.reset(ephemeral_key_source);
524 }
525
474 string QuicCryptoServerConfig::NewSourceAddressToken( 526 string QuicCryptoServerConfig::NewSourceAddressToken(
475 const IPEndPoint& ip, 527 const IPEndPoint& ip,
476 QuicRandom* rand, 528 QuicRandom* rand,
477 QuicTime::Delta now_since_epoch) const { 529 QuicWallTime now) const {
478 SourceAddressToken source_address_token; 530 SourceAddressToken source_address_token;
479 source_address_token.set_ip(ip.ToString()); 531 source_address_token.set_ip(ip.ToString());
480 source_address_token.set_timestamp(now_since_epoch.ToSeconds()); 532 source_address_token.set_timestamp(now.ToUNIXSeconds());
481 533
482 string plaintext = source_address_token.SerializeAsString(); 534 string plaintext = source_address_token.SerializeAsString();
483 char nonce[12]; 535 char nonce[12];
484 DCHECK_EQ(sizeof(nonce), 536 DCHECK_EQ(sizeof(nonce),
485 source_address_token_encrypter_->GetNoncePrefixSize() + 537 source_address_token_encrypter_->GetNoncePrefixSize() +
486 sizeof(QuicPacketSequenceNumber)); 538 sizeof(QuicPacketSequenceNumber));
487 rand->RandBytes(nonce, sizeof(nonce)); 539 rand->RandBytes(nonce, sizeof(nonce));
488 540
489 size_t ciphertext_size = 541 size_t ciphertext_size =
490 source_address_token_encrypter_->GetCiphertextSize(plaintext.size()); 542 source_address_token_encrypter_->GetCiphertextSize(plaintext.size());
491 string result; 543 string result;
492 result.resize(sizeof(nonce) + ciphertext_size); 544 result.resize(sizeof(nonce) + ciphertext_size);
493 memcpy(&result[0], &nonce, sizeof(nonce)); 545 memcpy(&result[0], &nonce, sizeof(nonce));
494 546
495 if (!source_address_token_encrypter_->Encrypt( 547 if (!source_address_token_encrypter_->Encrypt(
496 StringPiece(nonce, sizeof(nonce)), StringPiece(), plaintext, 548 StringPiece(nonce, sizeof(nonce)), StringPiece(), plaintext,
497 reinterpret_cast<unsigned char*>(&result[sizeof(nonce)]))) { 549 reinterpret_cast<unsigned char*>(&result[sizeof(nonce)]))) {
498 DCHECK(false); 550 DCHECK(false);
499 return string(); 551 return string();
500 } 552 }
501 553
502 return result; 554 return result;
503 } 555 }
504 556
505 bool QuicCryptoServerConfig::ValidateSourceAddressToken( 557 bool QuicCryptoServerConfig::ValidateSourceAddressToken(
506 StringPiece token, 558 StringPiece token,
507 const IPEndPoint& ip, 559 const IPEndPoint& ip,
508 QuicTime::Delta now_since_epoch) const { 560 QuicWallTime now) const {
509 char nonce[12]; 561 char nonce[12];
510 DCHECK_EQ(sizeof(nonce), 562 DCHECK_EQ(sizeof(nonce),
511 source_address_token_encrypter_->GetNoncePrefixSize() + 563 source_address_token_encrypter_->GetNoncePrefixSize() +
512 sizeof(QuicPacketSequenceNumber)); 564 sizeof(QuicPacketSequenceNumber));
513 565
514 if (token.size() <= sizeof(nonce)) { 566 if (token.size() <= sizeof(nonce)) {
515 return false; 567 return false;
516 } 568 }
517 memcpy(&nonce, token.data(), sizeof(nonce)); 569 memcpy(&nonce, token.data(), sizeof(nonce));
518 token.remove_prefix(sizeof(nonce)); 570 token.remove_prefix(sizeof(nonce));
519 571
520 unsigned char plaintext_stack[128]; 572 unsigned char plaintext_stack[128];
521 scoped_ptr<unsigned char[]> plaintext_heap; 573 scoped_ptr<unsigned char[]> plaintext_heap;
522 unsigned char* plaintext; 574 unsigned char* plaintext;
523 if (token.size() <= sizeof(plaintext_stack)) { 575 if (token.size() <= sizeof(plaintext_stack)) {
524 plaintext = plaintext_stack; 576 plaintext = plaintext_stack;
525 } else { 577 } else {
526 plaintext_heap.reset(new unsigned char[token.size()]); 578 plaintext_heap.reset(new unsigned char[token.size()]);
527 plaintext = plaintext_heap.get(); 579 plaintext = plaintext_heap.get();
528 } 580 }
529 size_t plaintext_length; 581 size_t plaintext_length;
530 582
531 if (!source_address_token_decrypter_->Decrypt( 583 if (!source_address_token_decrypter_->Decrypt(
532 StringPiece(nonce, sizeof(nonce)), StringPiece(), token, 584 StringPiece(nonce, sizeof(nonce)), StringPiece(), token, plaintext,
533 plaintext, &plaintext_length)) { 585 &plaintext_length)) {
534 return false; 586 return false;
535 } 587 }
536 588
537 SourceAddressToken source_address_token; 589 SourceAddressToken source_address_token;
538 if (!source_address_token.ParseFromArray(plaintext, plaintext_length)) { 590 if (!source_address_token.ParseFromArray(plaintext, plaintext_length)) {
539 return false; 591 return false;
540 } 592 }
541 593
542 if (source_address_token.ip() != ip.ToString()) { 594 if (source_address_token.ip() != ip.ToString()) {
543 // It's for a different IP address. 595 // It's for a different IP address.
544 return false; 596 return false;
545 } 597 }
546 598
547 const QuicTime::Delta delta(now_since_epoch.Subtract( 599 const QuicWallTime timestamp(
548 QuicTime::Delta::FromSeconds(source_address_token.timestamp()))); 600 QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
549 const int64 delta_secs = delta.ToSeconds(); 601 const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));
550 602
551 // TODO(agl): consider whether and how these magic values should be moved to 603 // TODO(agl): consider whether and how these magic values should be moved to
552 // a config. 604 // a config.
553 if (delta_secs < -3600) { 605 if (now.IsBefore(timestamp) && delta.ToSeconds() > 3600) {
554 // We only allow timestamps to be from an hour in the future. 606 // We only allow timestamps to be from an hour in the future.
555 return false; 607 return false;
556 } 608 }
557 609
558 if (delta_secs > 86400) { 610 if (now.IsAfter(timestamp) && delta.ToSeconds() > 86400) {
559 // We allow one day into the past. 611 // We allow one day into the past.
560 return false; 612 return false;
561 } 613 }
562 614
563 return true; 615 return true;
564 } 616 }
565 617
566 QuicCryptoServerConfig::Config::Config() { 618 QuicCryptoServerConfig::Config::Config() {}
567 }
568 619
569 QuicCryptoServerConfig::Config::~Config() { 620 QuicCryptoServerConfig::Config::~Config() { STLDeleteElements(&key_exchanges); }
570 STLDeleteElements(&key_exchanges);
571 }
572 621
573 } // namespace net 622 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/crypto_server_config.h ('k') | net/quic/crypto/crypto_server_config_protobuf.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698