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

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

Issue 12806002: Land Recent QUIC Changes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: minor comment fix Created 7 years, 9 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_handshake.h ('k') | net/quic/crypto/crypto_protocol.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_handshake.h" 5 #include "net/quic/crypto/crypto_handshake.h"
6 6
7 #include "base/memory/scoped_ptr.h" 7 #include "base/memory/scoped_ptr.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "crypto/hkdf.h"
9 #include "crypto/secure_hash.h" 10 #include "crypto/secure_hash.h"
10 #include "net/base/net_util.h" 11 #include "net/base/net_util.h"
11 #include "net/quic/crypto/crypto_framer.h" 12 #include "net/quic/crypto/crypto_framer.h"
12 #include "net/quic/crypto/crypto_utils.h" 13 #include "net/quic/crypto/crypto_utils.h"
13 #include "net/quic/crypto/curve25519_key_exchange.h" 14 #include "net/quic/crypto/curve25519_key_exchange.h"
14 #include "net/quic/crypto/key_exchange.h" 15 #include "net/quic/crypto/key_exchange.h"
16 #include "net/quic/crypto/quic_decrypter.h"
17 #include "net/quic/crypto/quic_encrypter.h"
15 #include "net/quic/crypto/quic_random.h" 18 #include "net/quic/crypto/quic_random.h"
16 #include "net/quic/quic_protocol.h" 19 #include "net/quic/quic_protocol.h"
17 20
18 using base::StringPiece; 21 using base::StringPiece;
19 using crypto::SecureHash; 22 using crypto::SecureHash;
20 using std::string; 23 using std::string;
21 using std::vector; 24 using std::vector;
22 25
23 namespace net { 26 namespace net {
24 // kVersion contains the one (and, for the moment, only) version number that we 27 // kVersion contains the one (and, for the moment, only) version number that we
25 // implement. 28 // implement.
26 static const uint16 kVersion = 0; 29 static const uint16 kVersion = 0;
27 30
31 static const char kLabel[] = "QUIC key expansion";
32
28 using crypto::SecureHash; 33 using crypto::SecureHash;
29 34
30 QuicServerConfigProtobuf::QuicServerConfigProtobuf() { 35 QuicServerConfigProtobuf::QuicServerConfigProtobuf() {
31 } 36 }
32 37
33 QuicServerConfigProtobuf::~QuicServerConfigProtobuf() { 38 QuicServerConfigProtobuf::~QuicServerConfigProtobuf() {
34 STLDeleteElements(&keys_); 39 STLDeleteElements(&keys_);
35 } 40 }
36 41
42 CryptoHandshakeMessage::CryptoHandshakeMessage() {}
43
44 CryptoHandshakeMessage::CryptoHandshakeMessage(
45 const CryptoHandshakeMessage& other)
46 : tag(other.tag),
47 tag_value_map(other.tag_value_map) {
48 // Don't copy serialized_. scoped_ptr doesn't have a copy constructor.
49 // The new object can reconstruct serialized_ lazily.
50 }
51
52 CryptoHandshakeMessage::~CryptoHandshakeMessage() {}
53
54 CryptoHandshakeMessage& CryptoHandshakeMessage::operator=(
55 const CryptoHandshakeMessage& other) {
56 tag = other.tag;
57 tag_value_map = other.tag_value_map;
58 // Don't copy serialized_. scoped_ptr doesn't have an assignment operator.
59 // However, invalidate serialized_.
60 serialized_.reset();
61 return *this;
62 }
63
64 const QuicData& CryptoHandshakeMessage::GetSerialized() const {
65 if (!serialized_.get()) {
66 serialized_.reset(CryptoFramer::ConstructHandshakeMessage(*this));
67 }
68 return *serialized_.get();
69 }
70
71 void CryptoHandshakeMessage::SetTaglist(CryptoTag tag, ...) {
72 // Warning, if sizeof(CryptoTag) > sizeof(int) then this function will break
73 // because the terminating 0 will only be promoted to int.
74 COMPILE_ASSERT(sizeof(CryptoTag) <= sizeof(int),
75 crypto_tag_not_be_larger_than_int_or_varargs_will_break);
76
77 vector<CryptoTag> tags;
78 va_list ap;
79
80 va_start(ap, tag);
81 for (;;) {
82 CryptoTag tag = va_arg(ap, CryptoTag);
83 if (tag == 0) {
84 break;
85 }
86 tags.push_back(tag);
87 }
88
89 // Because of the way that we keep tags in memory, we can copy the contents
90 // of the vector and get the correct bytes in wire format. See
91 // crypto_protocol.h. This assumes that the system is little-endian.
92 SetVector(tag, tags);
93
94 va_end(ap);
95 }
96
97 QuicErrorCode CryptoHandshakeMessage::GetTaglist(CryptoTag tag,
98 const CryptoTag** out_tags,
99 size_t* out_len) const {
100 CryptoTagValueMap::const_iterator it = tag_value_map.find(tag);
101 QuicErrorCode ret = QUIC_NO_ERROR;
102
103 if (it == tag_value_map.end()) {
104 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
105 } else if (it->second.size() % sizeof(CryptoTag) != 0) {
106 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
107 }
108
109 if (ret != QUIC_NO_ERROR) {
110 *out_tags = NULL;
111 *out_len = 0;
112 return ret;
113 }
114
115 *out_tags = reinterpret_cast<const CryptoTag*>(it->second.data());
116 *out_len = it->second.size() / sizeof(CryptoTag);
117 return ret;
118 }
119
120 bool CryptoHandshakeMessage::GetStringPiece(CryptoTag tag,
121 StringPiece* out) const {
122 CryptoTagValueMap::const_iterator it = tag_value_map.find(tag);
123 if (it == tag_value_map.end()) {
124 return false;
125 }
126 *out = it->second;
127 return true;
128 }
129
130 QuicErrorCode CryptoHandshakeMessage::GetNthValue16(
131 CryptoTag tag,
132 unsigned index,
133 StringPiece* out) const {
134 StringPiece value;
135 if (!GetStringPiece(tag, &value)) {
136 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
137 }
138
139 for (unsigned i = 0;; i++) {
140 if (value.empty()) {
141 return QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND;
142 }
143 if (value.size() < 2) {
144 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
145 }
146
147 const unsigned char* data =
148 reinterpret_cast<const unsigned char*>(value.data());
149 size_t size = static_cast<size_t>(data[0]) |
150 (static_cast<size_t>(data[1]) << 8);
151 value.remove_prefix(2);
152
153 if (value.size() < size) {
154 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
155 }
156
157 if (i == index) {
158 *out = StringPiece(value.data(), size);
159 return QUIC_NO_ERROR;
160 }
161
162 value.remove_prefix(size);
163 }
164 }
165
166 bool CryptoHandshakeMessage::GetString(CryptoTag tag, string* out) const {
167 CryptoTagValueMap::const_iterator it = tag_value_map.find(tag);
168 if (it == tag_value_map.end()) {
169 return false;
170 }
171 *out = it->second;
172 return true;
173 }
174
175 QuicErrorCode CryptoHandshakeMessage::GetUint16(CryptoTag tag,
176 uint16* out) const {
177 return GetPOD(tag, out, sizeof(uint16));
178 }
179
180 QuicErrorCode CryptoHandshakeMessage::GetUint32(CryptoTag tag,
181 uint32* out) const {
182 return GetPOD(tag, out, sizeof(uint32));
183 }
184
185 QuicErrorCode CryptoHandshakeMessage::GetPOD(
186 CryptoTag tag, void* out, size_t len) const {
187 CryptoTagValueMap::const_iterator it = tag_value_map.find(tag);
188 QuicErrorCode ret = QUIC_NO_ERROR;
189
190 if (it == tag_value_map.end()) {
191 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
192 } else if (it->second.size() != len) {
193 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
194 }
195
196 if (ret != QUIC_NO_ERROR) {
197 memset(out, 0, len);
198 return ret;
199 }
200
201 memcpy(out, it->second.data(), len);
202 return ret;
203 }
204
37 QuicCryptoNegotiatedParams::QuicCryptoNegotiatedParams() 205 QuicCryptoNegotiatedParams::QuicCryptoNegotiatedParams()
38 : version(0), 206 : version(0),
39 key_exchange(0), 207 key_exchange(0),
40 aead(0) { 208 aead(0) {
41 } 209 }
42 210
43 QuicCryptoNegotiatedParams::~QuicCryptoNegotiatedParams() { 211 QuicCryptoNegotiatedParams::~QuicCryptoNegotiatedParams() {
44 } 212 }
45 213
46
47 QuicCryptoConfig::QuicCryptoConfig() 214 QuicCryptoConfig::QuicCryptoConfig()
48 : version(0) { 215 : version(0) {
49 } 216 }
50 217
51 QuicCryptoConfig::~QuicCryptoConfig() { 218 QuicCryptoConfig::~QuicCryptoConfig() {
52 STLDeleteElements(&key_exchanges); 219 STLDeleteElements(&key_exchanges);
53 } 220 }
54 221
55 bool QuicCryptoConfig::ProcessPeerHandshake( 222 bool QuicCryptoConfig::ProcessPeerHandshake(
56 const CryptoHandshakeMessage& peer_msg, 223 const CryptoHandshakeMessage& peer_msg,
57 CryptoUtils::Priority priority, 224 CryptoUtils::Priority priority,
58 QuicCryptoNegotiatedParams* out_params, 225 QuicCryptoNegotiatedParams* out_params,
59 string *error_details) const { 226 string* error_details) const {
60 if (peer_msg.GetUint16(kVERS, &out_params->version) != QUIC_NO_ERROR || 227 if (peer_msg.GetUint16(kVERS, &out_params->version) != QUIC_NO_ERROR ||
61 out_params->version != kVersion) { 228 out_params->version != kVersion) {
62 if (error_details) { 229 if (error_details) {
63 *error_details = "Bad version"; 230 *error_details = "Bad version";
64 } 231 }
65 return false; 232 return false;
66 } 233 }
67 234
68 const CryptoTag* their_aeads; 235 const CryptoTag* their_aeads;
69 const CryptoTag* their_key_exchanges; 236 const CryptoTag* their_key_exchanges;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 &out_params->premaster_secret)) { 285 &out_params->premaster_secret)) {
119 if (error_details) { 286 if (error_details) {
120 *error_details = "Key exchange failure"; 287 *error_details = "Key exchange failure";
121 } 288 }
122 return false; 289 return false;
123 } 290 }
124 291
125 return true; 292 return true;
126 } 293 }
127 294
295 QuicCryptoClientConfig::QuicCryptoClientConfig()
296 : hkdf_info(kLabel, arraysize(kLabel)) {
297 }
298
128 void QuicCryptoClientConfig::SetDefaults(QuicRandom* rand) { 299 void QuicCryptoClientConfig::SetDefaults(QuicRandom* rand) {
129 // Version must be 0. 300 // Version must be 0.
130 version = kVersion; 301 version = kVersion;
131 302
132 // Key exchange methods. 303 // Key exchange methods.
133 const string private_key = Curve25519KeyExchange::NewPrivateKey(rand); 304 const string private_key = Curve25519KeyExchange::NewPrivateKey(rand);
134 key_exchanges.clear(); 305 key_exchanges.clear();
135 key_exchanges.push_back(Curve25519KeyExchange::New(private_key)); 306 key_exchanges.push_back(Curve25519KeyExchange::New(private_key));
136 kexs.resize(1); 307 kexs.resize(1);
137 kexs[0] = kC255; 308 kexs[0] = kC255;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 // If server_hostname is not an IP address literal, it is a DNS hostname. 347 // If server_hostname is not an IP address literal, it is a DNS hostname.
177 IPAddressNumber ip; 348 IPAddressNumber ip;
178 if (!server_hostname.empty() && 349 if (!server_hostname.empty() &&
179 !ParseIPLiteralToNumber(server_hostname, &ip)) { 350 !ParseIPLiteralToNumber(server_hostname, &ip)) {
180 out->tag_value_map[kSNI] = server_hostname; 351 out->tag_value_map[kSNI] = server_hostname;
181 } 352 }
182 } 353 }
183 354
184 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( 355 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
185 const CryptoHandshakeMessage& server_hello, 356 const CryptoHandshakeMessage& server_hello,
357 const string& nonce,
186 QuicCryptoNegotiatedParams* out_params, 358 QuicCryptoNegotiatedParams* out_params,
187 string* error_details) { 359 string* error_details) {
188 if (server_hello.tag != kSHLO) { 360 if (server_hello.tag != kSHLO) {
189 *error_details = "Bad tag"; 361 *error_details = "Bad tag";
190 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; 362 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
191 } 363 }
192 364
193 StringPiece scfg_bytes; 365 StringPiece scfg_bytes;
194 if (!server_hello.GetStringPiece(kSCFG, &scfg_bytes)) { 366 if (!server_hello.GetStringPiece(kSCFG, &scfg_bytes)) {
195 *error_details = "Missing SCFG"; 367 *error_details = "Missing SCFG";
196 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 368 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
197 } 369 }
198 370
199 scoped_ptr<CryptoHandshakeMessage> scfg( 371 scoped_ptr<CryptoHandshakeMessage> scfg(
200 CryptoFramer::ParseMessage(scfg_bytes)); 372 CryptoFramer::ParseMessage(scfg_bytes));
201 if (!scfg.get() || 373 if (!scfg.get() || scfg->tag != kSCFG) {
202 scfg->tag != kSCFG) {
203 *error_details = "Invalid SCFG"; 374 *error_details = "Invalid SCFG";
204 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 375 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
205 } 376 }
206 377
207 if (!ProcessPeerHandshake(*scfg, CryptoUtils::PEER_PRIORITY, out_params, 378 if (!ProcessPeerHandshake(*scfg, CryptoUtils::PEER_PRIORITY, out_params,
208 error_details)) { 379 error_details)) {
209 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 380 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
210 } 381 }
211 382
383 hkdf_info.append(scfg_bytes.data(), scfg_bytes.size());
384
385 out_params->encrypter.reset(QuicEncrypter::Create(out_params->aead));
386 out_params->decrypter.reset(QuicDecrypter::Create(out_params->aead));
387 size_t key_bytes = out_params->encrypter->GetKeySize();
388 size_t nonce_prefix_bytes = out_params->encrypter->GetNoncePrefixSize();
389 uint32 key_length_in_bits = 8 * 2 * (key_bytes + nonce_prefix_bytes);
390 hkdf_info.append(reinterpret_cast<char*>(&key_length_in_bits),
391 sizeof(key_length_in_bits));
392
393 crypto::HKDF hkdf(out_params->premaster_secret, nonce,
394 hkdf_info, key_bytes, nonce_prefix_bytes);
395 out_params->encrypter->SetKey(hkdf.client_write_key());
396 out_params->encrypter->SetNoncePrefix(hkdf.client_write_iv());
397 out_params->decrypter->SetKey(hkdf.server_write_key());
398 out_params->decrypter->SetNoncePrefix(hkdf.server_write_iv());
399
212 return QUIC_NO_ERROR; 400 return QUIC_NO_ERROR;
213 } 401 }
214 402
215 403
216 QuicCryptoServerConfig::QuicCryptoServerConfig() { 404 QuicCryptoServerConfig::QuicCryptoServerConfig()
405 : hkdf_info(kLabel, arraysize(kLabel)) {
217 } 406 }
218 407
219 QuicCryptoServerConfig::~QuicCryptoServerConfig() { 408 QuicCryptoServerConfig::~QuicCryptoServerConfig() {
220 STLDeleteValues(&configs_); 409 STLDeleteValues(&configs_);
221 } 410 }
222 411
223 // static 412 // static
224 QuicServerConfigProtobuf* QuicCryptoServerConfig::ConfigForTesting( 413 QuicServerConfigProtobuf* QuicCryptoServerConfig::ConfigForTesting(
225 QuicRandom* rand, 414 QuicRandom* rand,
226 const QuicClock* clock, 415 const QuicClock* clock,
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 out->tag = kREJ; 582 out->tag = kREJ;
394 out->tag_value_map.clear(); 583 out->tag_value_map.clear();
395 584
396 if (!config->ProcessPeerHandshake(client_hello, 585 if (!config->ProcessPeerHandshake(client_hello,
397 CryptoUtils::LOCAL_PRIORITY, 586 CryptoUtils::LOCAL_PRIORITY,
398 out_params, 587 out_params,
399 error_details)) { 588 error_details)) {
400 return false; 589 return false;
401 } 590 }
402 591
592 StringPiece client_nonce;
593 if (!client_hello.GetStringPiece(kNONC, &client_nonce)) {
594 return false;
595 }
596
597 const QuicData& client_hello_serialized = client_hello.GetSerialized();
598 hkdf_info.append(client_hello_serialized.data(),
599 client_hello_serialized.length());
600 hkdf_info.append(config->serialized);
601
602 out_params->encrypter.reset(QuicEncrypter::Create(out_params->aead));
603 out_params->decrypter.reset(QuicDecrypter::Create(out_params->aead));
604 size_t key_bytes = out_params->encrypter->GetKeySize();
605 size_t nonce_prefix_bytes = out_params->encrypter->GetNoncePrefixSize();
606 uint32 key_length_in_bits = 8 * 2 * (key_bytes + nonce_prefix_bytes);
607 hkdf_info.append(reinterpret_cast<char*>(&key_length_in_bits),
608 sizeof(key_length_in_bits));
609
610 crypto::HKDF hkdf(out_params->premaster_secret, client_nonce,
611 hkdf_info, key_bytes, nonce_prefix_bytes);
612 out_params->encrypter->SetKey(hkdf.server_write_key());
613 out_params->encrypter->SetNoncePrefix(hkdf.server_write_iv());
614 out_params->decrypter->SetKey(hkdf.client_write_key());
615 out_params->decrypter->SetNoncePrefix(hkdf.client_write_iv());
616
403 // TODO(agl): This is obviously missing most of the handshake. 617 // TODO(agl): This is obviously missing most of the handshake.
404 out->tag = kSHLO; 618 out->tag = kSHLO;
405 out->tag_value_map[kNONC] = nonce; 619 out->tag_value_map[kNONC] = nonce;
406 out->tag_value_map[kSCFG] = config->serialized; 620 out->tag_value_map[kSCFG] = config->serialized;
407 return true; 621 return true;
408 } 622 }
409 623
410 QuicCryptoServerConfig::Config::Config() { 624 QuicCryptoServerConfig::Config::Config() {
411 } 625 }
412 626
413 QuicCryptoServerConfig::Config::~Config() { 627 QuicCryptoServerConfig::Config::~Config() {
414 } 628 }
415 629
416 } // namespace net 630 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/crypto_handshake.h ('k') | net/quic/crypto/crypto_protocol.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698