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

Side by Side Diff: net/quic/crypto/crypto_handshake.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_handshake.h ('k') | net/quic/crypto/crypto_handshake_test.cc » ('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 <ctype.h> 7 #include <ctype.h>
8 8
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_split.h" 12 #include "base/strings/string_split.h"
13 #include "crypto/secure_hash.h" 13 #include "crypto/secure_hash.h"
14 #include "net/base/net_util.h" 14 #include "net/base/net_util.h"
15 #include "net/quic/crypto/cert_compressor.h" 15 #include "net/quic/crypto/cert_compressor.h"
16 #include "net/quic/crypto/common_cert_set.h" 16 #include "net/quic/crypto/common_cert_set.h"
17 #include "net/quic/crypto/crypto_framer.h" 17 #include "net/quic/crypto/crypto_framer.h"
18 #include "net/quic/crypto/crypto_utils.h" 18 #include "net/quic/crypto/crypto_utils.h"
19 #include "net/quic/crypto/curve25519_key_exchange.h" 19 #include "net/quic/crypto/curve25519_key_exchange.h"
20 #include "net/quic/crypto/key_exchange.h" 20 #include "net/quic/crypto/key_exchange.h"
21 #include "net/quic/crypto/p256_key_exchange.h" 21 #include "net/quic/crypto/p256_key_exchange.h"
22 #include "net/quic/crypto/proof_verifier.h" 22 #include "net/quic/crypto/proof_verifier.h"
23 #include "net/quic/crypto/quic_decrypter.h" 23 #include "net/quic/crypto/quic_decrypter.h"
24 #include "net/quic/crypto/quic_encrypter.h" 24 #include "net/quic/crypto/quic_encrypter.h"
25 #include "net/quic/crypto/quic_random.h" 25 #include "net/quic/crypto/quic_random.h"
26 #include "net/quic/quic_clock.h"
27 #include "net/quic/quic_protocol.h" 26 #include "net/quic/quic_protocol.h"
28 #include "net/quic/quic_utils.h" 27 #include "net/quic/quic_utils.h"
29 28
30 using base::StringPiece; 29 using base::StringPiece;
31 using std::map; 30 using std::map;
32 using std::string; 31 using std::string;
33 using std::vector; 32 using std::vector;
34 33
35 namespace net { 34 namespace net {
36 35
(...skipping 25 matching lines...) Expand all
62 serialized_.reset(); 61 serialized_.reset();
63 } 62 }
64 63
65 const QuicData& CryptoHandshakeMessage::GetSerialized() const { 64 const QuicData& CryptoHandshakeMessage::GetSerialized() const {
66 if (!serialized_.get()) { 65 if (!serialized_.get()) {
67 serialized_.reset(CryptoFramer::ConstructHandshakeMessage(*this)); 66 serialized_.reset(CryptoFramer::ConstructHandshakeMessage(*this));
68 } 67 }
69 return *serialized_.get(); 68 return *serialized_.get();
70 } 69 }
71 70
72 void CryptoHandshakeMessage::Insert(CryptoTagValueMap::const_iterator begin, 71 void CryptoHandshakeMessage::Insert(QuicTagValueMap::const_iterator begin,
73 CryptoTagValueMap::const_iterator end) { 72 QuicTagValueMap::const_iterator end) {
74 tag_value_map_.insert(begin, end); 73 tag_value_map_.insert(begin, end);
75 } 74 }
76 75
77 void CryptoHandshakeMessage::SetTaglist(CryptoTag tag, ...) { 76 void CryptoHandshakeMessage::SetTaglist(QuicTag tag, ...) {
78 // Warning, if sizeof(CryptoTag) > sizeof(int) then this function will break 77 // Warning, if sizeof(QuicTag) > sizeof(int) then this function will break
79 // because the terminating 0 will only be promoted to int. 78 // because the terminating 0 will only be promoted to int.
80 COMPILE_ASSERT(sizeof(CryptoTag) <= sizeof(int), 79 COMPILE_ASSERT(sizeof(QuicTag) <= sizeof(int),
81 crypto_tag_not_be_larger_than_int_or_varargs_will_break); 80 crypto_tag_not_be_larger_than_int_or_varargs_will_break);
82 81
83 vector<CryptoTag> tags; 82 vector<QuicTag> tags;
84 va_list ap; 83 va_list ap;
85 84
86 va_start(ap, tag); 85 va_start(ap, tag);
87 for (;;) { 86 for (;;) {
88 CryptoTag list_item = va_arg(ap, CryptoTag); 87 QuicTag list_item = va_arg(ap, QuicTag);
89 if (list_item == 0) { 88 if (list_item == 0) {
90 break; 89 break;
91 } 90 }
92 tags.push_back(list_item); 91 tags.push_back(list_item);
93 } 92 }
94 93
95 // Because of the way that we keep tags in memory, we can copy the contents 94 // Because of the way that we keep tags in memory, we can copy the contents
96 // of the vector and get the correct bytes in wire format. See 95 // of the vector and get the correct bytes in wire format. See
97 // crypto_protocol.h. This assumes that the system is little-endian. 96 // crypto_protocol.h. This assumes that the system is little-endian.
98 SetVector(tag, tags); 97 SetVector(tag, tags);
99 98
100 va_end(ap); 99 va_end(ap);
101 } 100 }
102 101
103 void CryptoHandshakeMessage::SetStringPiece(CryptoTag tag, StringPiece value) { 102 void CryptoHandshakeMessage::SetStringPiece(QuicTag tag, StringPiece value) {
104 tag_value_map_[tag] = value.as_string(); 103 tag_value_map_[tag] = value.as_string();
105 } 104 }
106 105
107 QuicErrorCode CryptoHandshakeMessage::GetTaglist(CryptoTag tag, 106 QuicErrorCode CryptoHandshakeMessage::GetTaglist(QuicTag tag,
108 const CryptoTag** out_tags, 107 const QuicTag** out_tags,
109 size_t* out_len) const { 108 size_t* out_len) const {
110 CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag); 109 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
111 *out_len = 0; 110 *out_len = 0;
112 QuicErrorCode ret = QUIC_NO_ERROR; 111 QuicErrorCode ret = QUIC_NO_ERROR;
113 112
114 if (it == tag_value_map_.end()) { 113 if (it == tag_value_map_.end()) {
115 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 114 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
116 } else if (it->second.size() % sizeof(CryptoTag) != 0) { 115 } else if (it->second.size() % sizeof(QuicTag) != 0) {
117 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 116 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
118 } 117 }
119 118
120 if (ret != QUIC_NO_ERROR) { 119 if (ret != QUIC_NO_ERROR) {
121 *out_tags = NULL; 120 *out_tags = NULL;
122 *out_len = 0; 121 *out_len = 0;
123 return ret; 122 return ret;
124 } 123 }
125 124
126 *out_tags = reinterpret_cast<const CryptoTag*>(it->second.data()); 125 *out_tags = reinterpret_cast<const QuicTag*>(it->second.data());
127 *out_len = it->second.size() / sizeof(CryptoTag); 126 *out_len = it->second.size() / sizeof(QuicTag);
128 return ret; 127 return ret;
129 } 128 }
130 129
131 bool CryptoHandshakeMessage::GetStringPiece(CryptoTag tag, 130 bool CryptoHandshakeMessage::GetStringPiece(QuicTag tag,
132 StringPiece* out) const { 131 StringPiece* out) const {
133 CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag); 132 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
134 if (it == tag_value_map_.end()) { 133 if (it == tag_value_map_.end()) {
135 return false; 134 return false;
136 } 135 }
137 *out = it->second; 136 *out = it->second;
138 return true; 137 return true;
139 } 138 }
140 139
141 QuicErrorCode CryptoHandshakeMessage::GetNthValue16(CryptoTag tag, 140 QuicErrorCode CryptoHandshakeMessage::GetNthValue24(QuicTag tag,
142 unsigned index, 141 unsigned index,
143 StringPiece* out) const { 142 StringPiece* out) const {
144 StringPiece value; 143 StringPiece value;
145 if (!GetStringPiece(tag, &value)) { 144 if (!GetStringPiece(tag, &value)) {
146 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 145 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
147 } 146 }
148 147
149 for (unsigned i = 0;; i++) { 148 for (unsigned i = 0;; i++) {
150 if (value.empty()) { 149 if (value.empty()) {
151 return QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND; 150 return QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND;
152 } 151 }
153 if (value.size() < 2) { 152 if (value.size() < 3) {
154 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 153 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
155 } 154 }
156 155
157 const unsigned char* data = 156 const unsigned char* data =
158 reinterpret_cast<const unsigned char*>(value.data()); 157 reinterpret_cast<const unsigned char*>(value.data());
159 size_t size = static_cast<size_t>(data[0]) | 158 size_t size = static_cast<size_t>(data[0]) |
160 (static_cast<size_t>(data[1]) << 8); 159 (static_cast<size_t>(data[1]) << 8) |
161 value.remove_prefix(2); 160 (static_cast<size_t>(data[2]) << 16);
161 value.remove_prefix(3);
162 162
163 if (value.size() < size) { 163 if (value.size() < size) {
164 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 164 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
165 } 165 }
166 166
167 if (i == index) { 167 if (i == index) {
168 *out = StringPiece(value.data(), size); 168 *out = StringPiece(value.data(), size);
169 return QUIC_NO_ERROR; 169 return QUIC_NO_ERROR;
170 } 170 }
171 171
172 value.remove_prefix(size); 172 value.remove_prefix(size);
173 } 173 }
174 } 174 }
175 175
176 bool CryptoHandshakeMessage::GetString(CryptoTag tag, string* out) const { 176 bool CryptoHandshakeMessage::GetString(QuicTag tag, string* out) const {
177 CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag); 177 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
178 if (it == tag_value_map_.end()) { 178 if (it == tag_value_map_.end()) {
179 return false; 179 return false;
180 } 180 }
181 *out = it->second; 181 *out = it->second;
182 return true; 182 return true;
183 } 183 }
184 184
185 QuicErrorCode CryptoHandshakeMessage::GetUint16(CryptoTag tag, 185 QuicErrorCode CryptoHandshakeMessage::GetUint16(QuicTag tag,
186 uint16* out) const { 186 uint16* out) const {
187 return GetPOD(tag, out, sizeof(uint16)); 187 return GetPOD(tag, out, sizeof(uint16));
188 } 188 }
189 189
190 QuicErrorCode CryptoHandshakeMessage::GetUint32(CryptoTag tag, 190 QuicErrorCode CryptoHandshakeMessage::GetUint32(QuicTag tag,
191 uint32* out) const { 191 uint32* out) const {
192 return GetPOD(tag, out, sizeof(uint32)); 192 return GetPOD(tag, out, sizeof(uint32));
193 } 193 }
194 194
195 QuicErrorCode CryptoHandshakeMessage::GetUint64(QuicTag tag,
196 uint64* out) const {
197 return GetPOD(tag, out, sizeof(uint64));
198 }
199
195 string CryptoHandshakeMessage::DebugString() const { 200 string CryptoHandshakeMessage::DebugString() const {
196 return DebugStringInternal(0); 201 return DebugStringInternal(0);
197 } 202 }
198 203
199 QuicErrorCode CryptoHandshakeMessage::GetPOD( 204 QuicErrorCode CryptoHandshakeMessage::GetPOD(
200 CryptoTag tag, void* out, size_t len) const { 205 QuicTag tag, void* out, size_t len) const {
201 CryptoTagValueMap::const_iterator it = tag_value_map_.find(tag); 206 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
202 QuicErrorCode ret = QUIC_NO_ERROR; 207 QuicErrorCode ret = QUIC_NO_ERROR;
203 208
204 if (it == tag_value_map_.end()) { 209 if (it == tag_value_map_.end()) {
205 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 210 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
206 } else if (it->second.size() != len) { 211 } else if (it->second.size() != len) {
207 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 212 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
208 } 213 }
209 214
210 if (ret != QUIC_NO_ERROR) { 215 if (ret != QUIC_NO_ERROR) {
211 memset(out, 0, len); 216 memset(out, 0, len);
212 return ret; 217 return ret;
213 } 218 }
214 219
215 memcpy(out, it->second.data(), len); 220 memcpy(out, it->second.data(), len);
216 return ret; 221 return ret;
217 } 222 }
218 223
219 // TagToString is a utility function for pretty-printing handshake messages 224 // TagToString is a utility function for pretty-printing handshake messages
220 // that converts a tag to a string. It will try to maintain the human friendly 225 // that converts a tag to a string. It will try to maintain the human friendly
221 // name if possible (i.e. kABCD -> "ABCD"), or will just treat it as a number 226 // name if possible (i.e. kABCD -> "ABCD"), or will just treat it as a number
222 // if not. 227 // if not.
223 static string TagToString(CryptoTag tag) { 228 static string TagToString(QuicTag tag) {
224 char chars[4]; 229 char chars[4];
225 bool ascii = true; 230 bool ascii = true;
226 const CryptoTag orig_tag = tag; 231 const QuicTag orig_tag = tag;
227 232
228 for (size_t i = 0; i < sizeof(chars); i++) { 233 for (size_t i = 0; i < sizeof(chars); i++) {
229 chars[i] = tag; 234 chars[i] = tag;
230 if (chars[i] == 0 && i == 3) { 235 if (chars[i] == 0 && i == 3) {
231 chars[i] = ' '; 236 chars[i] = ' ';
232 } 237 }
233 if (!isprint(static_cast<unsigned char>(chars[i]))) { 238 if (!isprint(static_cast<unsigned char>(chars[i]))) {
234 ascii = false; 239 ascii = false;
235 break; 240 break;
236 } 241 }
237 tag >>= 8; 242 tag >>= 8;
238 } 243 }
239 244
240 if (ascii) { 245 if (ascii) {
241 return string(chars, sizeof(chars)); 246 return string(chars, sizeof(chars));
242 } 247 }
243 248
244 return base::UintToString(orig_tag); 249 return base::UintToString(orig_tag);
245 } 250 }
246 251
247 string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const { 252 string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
248 string ret = string(2 * indent, ' ') + TagToString(tag_) + "<\n"; 253 string ret = string(2 * indent, ' ') + TagToString(tag_) + "<\n";
249 ++indent; 254 ++indent;
250 for (CryptoTagValueMap::const_iterator it = tag_value_map_.begin(); 255 for (QuicTagValueMap::const_iterator it = tag_value_map_.begin();
251 it != tag_value_map_.end(); ++it) { 256 it != tag_value_map_.end(); ++it) {
252 ret += string(2 * indent, ' ') + TagToString(it->first) + ": "; 257 ret += string(2 * indent, ' ') + TagToString(it->first) + ": ";
253 258
254 bool done = false; 259 bool done = false;
255 switch (it->first) { 260 switch (it->first) {
256 case kKATO: 261 case kKATO:
257 case kVERS: 262 case kVERS:
258 // uint32 value 263 // uint32 value
259 if (it->second.size() == 4) { 264 if (it->second.size() == 4) {
260 uint32 value; 265 uint32 value;
261 memcpy(&value, it->second.data(), sizeof(value)); 266 memcpy(&value, it->second.data(), sizeof(value));
262 ret += base::UintToString(value); 267 ret += base::UintToString(value);
263 done = true;
264 }
265 break;
266 case kKEXS:
267 case kAEAD:
268 case kCGST:
269 case kPDMD:
270 // tag lists
271 if (it->second.size() % sizeof(CryptoTag) == 0) {
272 for (size_t j = 0; j < it->second.size(); j += sizeof(CryptoTag)) {
273 CryptoTag tag;
274 memcpy(&tag, it->second.data() + j, sizeof(tag));
275 if (j > 0) {
276 ret += ",";
277 }
278 ret += TagToString(tag);
279 }
280 done = true;
281 }
282 break;
283 case kSCFG:
284 // nested messages.
285 if (!it->second.empty()) {
286 scoped_ptr<CryptoHandshakeMessage> msg(
287 CryptoFramer::ParseMessage(it->second));
288 if (msg.get()) {
289 ret += "\n";
290 ret += msg->DebugStringInternal(indent + 1);
291
292 done = true; 268 done = true;
293 } 269 }
294 } 270 break;
295 break; 271 case kKEXS:
272 case kAEAD:
273 case kCGST:
274 case kPDMD:
275 // tag lists
276 if (it->second.size() % sizeof(QuicTag) == 0) {
277 for (size_t j = 0; j < it->second.size(); j += sizeof(QuicTag)) {
278 QuicTag tag;
279 memcpy(&tag, it->second.data() + j, sizeof(tag));
280 if (j > 0) {
281 ret += ",";
282 }
283 ret += TagToString(tag);
284 }
285 done = true;
286 }
287 break;
288 case kSCFG:
289 // nested messages.
290 if (!it->second.empty()) {
291 scoped_ptr<CryptoHandshakeMessage> msg(
292 CryptoFramer::ParseMessage(it->second));
293 if (msg.get()) {
294 ret += "\n";
295 ret += msg->DebugStringInternal(indent + 1);
296
297 done = true;
298 }
299 }
300 break;
296 } 301 }
297 302
298 if (!done) { 303 if (!done) {
299 // If there's no specific format for this tag, or the value is invalid, 304 // If there's no specific format for this tag, or the value is invalid,
300 // then just use hex. 305 // then just use hex.
301 ret += base::HexEncode(it->second.data(), it->second.size()); 306 ret += base::HexEncode(it->second.data(), it->second.size());
302 } 307 }
303 ret += "\n"; 308 ret += "\n";
304 } 309 }
305 --indent; 310 --indent;
306 ret += string(2 * indent, ' ') + ">"; 311 ret += string(2 * indent, ' ') + ">";
307 return ret; 312 return ret;
308 } 313 }
309 314
310 QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters() 315 QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters()
311 : version(0), 316 : version(0),
312 key_exchange(0), 317 key_exchange(0),
313 aead(0) { 318 aead(0) {
314 } 319 }
315 320
316 QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() { 321 QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {}
317 }
318 322
323 CrypterPair::CrypterPair() {}
324 CrypterPair::~CrypterPair() {}
319 325
320 // static 326 // static
321 const char QuicCryptoConfig::kLabel[] = "QUIC key expansion"; 327 const char QuicCryptoConfig::kInitialLabel[] = "QUIC key expansion";
328
329 const char QuicCryptoConfig::kForwardSecureLabel[] =
330 "QUIC forward secure key expansion";
322 331
323 QuicCryptoConfig::QuicCryptoConfig() 332 QuicCryptoConfig::QuicCryptoConfig()
324 : version(0), 333 : version(0),
325 common_cert_set_(new CommonCertSetQUIC) { 334 common_cert_set_(new CommonCertSetsQUIC) {
326 } 335 }
327 336
328 QuicCryptoConfig::~QuicCryptoConfig() {} 337 QuicCryptoConfig::~QuicCryptoConfig() {}
329 338
330 QuicCryptoClientConfig::QuicCryptoClientConfig() {} 339 QuicCryptoClientConfig::QuicCryptoClientConfig() {}
331 340
332 QuicCryptoClientConfig::~QuicCryptoClientConfig() { 341 QuicCryptoClientConfig::~QuicCryptoClientConfig() {
333 STLDeleteValues(&cached_states_); 342 STLDeleteValues(&cached_states_);
334 } 343 }
335 344
(...skipping 12 matching lines...) Expand all
348 return NULL; 357 return NULL;
349 } 358 }
350 359
351 if (!scfg_.get()) { 360 if (!scfg_.get()) {
352 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); 361 scfg_.reset(CryptoFramer::ParseMessage(server_config_));
353 DCHECK(scfg_.get()); 362 DCHECK(scfg_.get());
354 } 363 }
355 return scfg_.get(); 364 return scfg_.get();
356 } 365 }
357 366
358 bool QuicCryptoClientConfig::CachedState::SetServerConfig( 367 bool QuicCryptoClientConfig::CachedState::SetServerConfig(StringPiece scfg) {
359 StringPiece scfg) {
360 scfg_.reset(CryptoFramer::ParseMessage(scfg)); 368 scfg_.reset(CryptoFramer::ParseMessage(scfg));
361 if (!scfg_.get()) { 369 if (!scfg_.get()) {
362 return false; 370 return false;
363 } 371 }
364 server_config_ = scfg.as_string(); 372 server_config_ = scfg.as_string();
365 return true; 373 return true;
366 } 374 }
367 375
368 void QuicCryptoClientConfig::CachedState::SetProof( 376 void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs,
369 const vector<string>& certs, StringPiece signature) { 377 StringPiece signature) {
370 bool has_changed = signature != server_config_sig_; 378 bool has_changed = signature != server_config_sig_;
371 379
372 if (certs_.size() != certs.size()) { 380 if (certs_.size() != certs.size()) {
373 has_changed = true; 381 has_changed = true;
374 } 382 }
375 if (!has_changed) { 383 if (!has_changed) {
376 for (size_t i = 0; i < certs_.size(); i++) { 384 for (size_t i = 0; i < certs_.size(); i++) {
377 if (certs_[i] != certs[i]) { 385 if (certs_[i] != certs[i]) {
378 has_changed = true; 386 has_changed = true;
379 break; 387 break;
380 } 388 }
381 } 389 }
382 } 390 }
383 391
384 if (!has_changed) { 392 if (!has_changed) {
385 return; 393 return;
386 } 394 }
387 395
388 // If the proof has changed then it needs to be revalidated. 396 // If the proof has changed then it needs to be revalidated.
389 server_config_valid_ = false; 397 server_config_valid_ = false;
390 certs_ = certs; 398 certs_ = certs;
391 server_config_sig_ = signature.as_string(); 399 server_config_sig_ = signature.as_string();
392 } 400 }
393 401
394 void QuicCryptoClientConfig::CachedState::SetProofValid() { 402 void QuicCryptoClientConfig::CachedState::SetProofValid() {
395 server_config_valid_ = true; 403 server_config_valid_ = true;
396 } 404 }
397 405
398 const string& 406 const string& QuicCryptoClientConfig::CachedState::server_config() const {
399 QuicCryptoClientConfig::CachedState::server_config() const {
400 return server_config_; 407 return server_config_;
401 } 408 }
402 409
403 const string& 410 const string&
404 QuicCryptoClientConfig::CachedState::source_address_token() const { 411 QuicCryptoClientConfig::CachedState::source_address_token() const {
405 return source_address_token_; 412 return source_address_token_;
406 } 413 }
407 414
408 const vector<string>& QuicCryptoClientConfig::CachedState::certs() const { 415 const vector<string>& QuicCryptoClientConfig::CachedState::certs() const {
409 return certs_; 416 return certs_;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 // Server name indication. 466 // Server name indication.
460 // If server_hostname is not an IP address literal, it is a DNS hostname. 467 // If server_hostname is not an IP address literal, it is a DNS hostname.
461 IPAddressNumber ip; 468 IPAddressNumber ip;
462 if (!server_hostname.empty() && 469 if (!server_hostname.empty() &&
463 !ParseIPLiteralToNumber(server_hostname, &ip)) { 470 !ParseIPLiteralToNumber(server_hostname, &ip)) {
464 out->SetStringPiece(kSNI, server_hostname); 471 out->SetStringPiece(kSNI, server_hostname);
465 } 472 }
466 out->SetValue(kVERS, version); 473 out->SetValue(kVERS, version);
467 474
468 if (!cached->source_address_token().empty()) { 475 if (!cached->source_address_token().empty()) {
469 out->SetStringPiece(kSRCT, cached->source_address_token()); 476 out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
470 } 477 }
471 478
472 out->SetTaglist(kPDMD, kX509, 0); 479 out->SetTaglist(kPDMD, kX509, 0);
473 480
474 if (common_cert_set_.get()) { 481 if (common_cert_set_.get()) {
475 out->SetStringPiece(kCCS, common_cert_set_->GetCommonHashes()); 482 out->SetStringPiece(kCCS, common_cert_set_->GetCommonHashes());
476 } 483 }
477 484
478 const vector<string>& certs = cached->certs(); 485 const vector<string>& certs = cached->certs();
486 out_params->cached_certs = certs;
479 if (!certs.empty()) { 487 if (!certs.empty()) {
480 vector<uint64> hashes; 488 vector<uint64> hashes;
481 hashes.reserve(certs.size()); 489 hashes.reserve(certs.size());
482 for (vector<string>::const_iterator i = certs.begin(); 490 for (vector<string>::const_iterator i = certs.begin();
483 i != certs.end(); ++i) { 491 i != certs.end(); ++i) {
484 hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size())); 492 hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
485 } 493 }
486 out->SetVector(kCCRT, hashes); 494 out->SetVector(kCCRT, hashes);
487 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the 495 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the
488 // client config is being used for multiple connections, another connection 496 // client config is being used for multiple connections, another connection
489 // doesn't update the cached certificates and cause us to be unable to 497 // doesn't update the cached certificates and cause us to be unable to
490 // process the server's compressed certificate chain. 498 // process the server's compressed certificate chain.
491 out_params->cached_certs = certs;
492 } 499 }
493 } 500 }
494 501
495 QuicErrorCode QuicCryptoClientConfig::FillClientHello( 502 QuicErrorCode QuicCryptoClientConfig::FillClientHello(
496 const string& server_hostname, 503 const string& server_hostname,
497 QuicGuid guid, 504 QuicGuid guid,
498 const CachedState* cached, 505 const CachedState* cached,
499 const QuicClock* clock, 506 QuicWallTime now,
500 QuicRandom* rand, 507 QuicRandom* rand,
501 QuicCryptoNegotiatedParameters* out_params, 508 QuicCryptoNegotiatedParameters* out_params,
502 CryptoHandshakeMessage* out, 509 CryptoHandshakeMessage* out,
503 string* error_details) const { 510 string* error_details) const {
504 DCHECK(error_details != NULL); 511 DCHECK(error_details != NULL);
505 512
506 FillInchoateClientHello(server_hostname, cached, out_params, out); 513 FillInchoateClientHello(server_hostname, cached, out_params, out);
507 514
508 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); 515 const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
509 if (!scfg) { 516 if (!scfg) {
510 // This should never happen as our caller should have checked 517 // This should never happen as our caller should have checked
511 // cached->is_complete() before calling this function. 518 // cached->is_complete() before calling this function.
512 *error_details = "Handshake not ready"; 519 *error_details = "Handshake not ready";
513 return QUIC_CRYPTO_INTERNAL_ERROR; 520 return QUIC_CRYPTO_INTERNAL_ERROR;
514 } 521 }
515 522
523 uint64 expiry_seconds;
524 if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
525 *error_details = "SCFG missing EXPY";
526 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
527 }
528
529 if (static_cast<uint64>(now.ToUNIXSeconds()) >= expiry_seconds) {
530 *error_details = "SCFG expired";
531 return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED;
532 }
533
516 StringPiece scid; 534 StringPiece scid;
517 if (!scfg->GetStringPiece(kSCID, &scid)) { 535 if (!scfg->GetStringPiece(kSCID, &scid)) {
518 *error_details = "SCFG missing SCID"; 536 *error_details = "SCFG missing SCID";
519 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 537 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
520 } 538 }
521 out->SetStringPiece(kSCID, scid); 539 out->SetStringPiece(kSCID, scid);
522 540
523 // Calculate the mutual algorithms that the connection is going to use. 541 // Calculate the mutual algorithms that the connection is going to use.
524 if (scfg->GetUint16(kVERS, &out_params->version) != QUIC_NO_ERROR || 542 if (scfg->GetUint16(kVERS, &out_params->version) != QUIC_NO_ERROR ||
525 out_params->version != QuicCryptoConfig::CONFIG_VERSION) { 543 out_params->version != QuicCryptoConfig::CONFIG_VERSION) {
526 *error_details = "Bad version"; 544 *error_details = "Bad version";
527 return QUIC_CRYPTO_VERSION_NOT_SUPPORTED; 545 return QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
528 } 546 }
529 547
530 const CryptoTag* their_aeads; 548 const QuicTag* their_aeads;
531 const CryptoTag* their_key_exchanges; 549 const QuicTag* their_key_exchanges;
532 size_t num_their_aeads, num_their_key_exchanges; 550 size_t num_their_aeads, num_their_key_exchanges;
533 if (scfg->GetTaglist(kAEAD, &their_aeads, 551 if (scfg->GetTaglist(kAEAD, &their_aeads,
534 &num_their_aeads) != QUIC_NO_ERROR || 552 &num_their_aeads) != QUIC_NO_ERROR ||
535 scfg->GetTaglist(kKEXS, &their_key_exchanges, 553 scfg->GetTaglist(kKEXS, &their_key_exchanges,
536 &num_their_key_exchanges) != QUIC_NO_ERROR) { 554 &num_their_key_exchanges) != QUIC_NO_ERROR) {
537 *error_details = "Missing AEAD or KEXS"; 555 *error_details = "Missing AEAD or KEXS";
538 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 556 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
539 } 557 }
540 558
541 size_t key_exchange_index; 559 size_t key_exchange_index;
542 if (!CryptoUtils::FindMutualTag(aead, 560 if (!CryptoUtils::FindMutualTag(aead, their_aeads, num_their_aeads,
543 their_aeads, num_their_aeads, 561 CryptoUtils::PEER_PRIORITY, &out_params->aead,
544 CryptoUtils::PEER_PRIORITY,
545 &out_params->aead,
546 NULL) || 562 NULL) ||
547 !CryptoUtils::FindMutualTag(kexs, 563 !CryptoUtils::FindMutualTag(
548 their_key_exchanges, num_their_key_exchanges, 564 kexs, their_key_exchanges, num_their_key_exchanges,
549 CryptoUtils::PEER_PRIORITY, 565 CryptoUtils::PEER_PRIORITY, &out_params->key_exchange,
550 &out_params->key_exchange, 566 &key_exchange_index)) {
551 &key_exchange_index)) {
552 *error_details = "Unsupported AEAD or KEXS"; 567 *error_details = "Unsupported AEAD or KEXS";
553 return QUIC_CRYPTO_NO_SUPPORT; 568 return QUIC_CRYPTO_NO_SUPPORT;
554 } 569 }
555 out->SetTaglist(kAEAD, out_params->aead, 0); 570 out->SetTaglist(kAEAD, out_params->aead, 0);
556 out->SetTaglist(kKEXS, out_params->key_exchange, 0); 571 out->SetTaglist(kKEXS, out_params->key_exchange, 0);
557 572
558 StringPiece public_value; 573 StringPiece public_value;
559 if (scfg->GetNthValue16(kPUBS, key_exchange_index, &public_value) != 574 if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) !=
560 QUIC_NO_ERROR) { 575 QUIC_NO_ERROR) {
561 *error_details = "Missing public value"; 576 *error_details = "Missing public value";
562 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 577 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
563 } 578 }
564 579
565 StringPiece orbit; 580 StringPiece orbit;
566 if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) { 581 if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) {
567 *error_details = "SCFG missing OBIT"; 582 *error_details = "SCFG missing OBIT";
568 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 583 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
569 } 584 }
570 585
571 string nonce; 586 CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce);
572 CryptoUtils::GenerateNonce(clock->NowAsDeltaSinceUnixEpoch(), rand, orbit, 587 out->SetStringPiece(kNONC, out_params->client_nonce);
573 &nonce); 588 if (!out_params->server_nonce.empty()) {
574 out->SetStringPiece(kNONC, nonce); 589 out->SetStringPiece(kServerNonceTag, out_params->server_nonce);
575
576 scoped_ptr<KeyExchange> key_exchange;
577 switch (out_params->key_exchange) {
578 case kC255:
579 key_exchange.reset(Curve25519KeyExchange::New(
580 Curve25519KeyExchange::NewPrivateKey(rand)));
581 break;
582 case kP256:
583 key_exchange.reset(P256KeyExchange::New(
584 P256KeyExchange::NewPrivateKey()));
585 break;
586 default:
587 DCHECK(false);
588 *error_details = "Configured to support an unknown key exchange";
589 return QUIC_CRYPTO_INTERNAL_ERROR;
590 } 590 }
591 591
592 if (!key_exchange->CalculateSharedKey(public_value, 592 switch (out_params->key_exchange) {
593 &out_params->premaster_secret)) { 593 case kC255:
594 out_params->client_key_exchange.reset(Curve25519KeyExchange::New(
595 Curve25519KeyExchange::NewPrivateKey(rand)));
596 break;
597 case kP256:
598 out_params->client_key_exchange
599 .reset(P256KeyExchange::New(P256KeyExchange::NewPrivateKey()));
600 break;
601 default:
602 DCHECK(false);
603 *error_details = "Configured to support an unknown key exchange";
604 return QUIC_CRYPTO_INTERNAL_ERROR;
605 }
606
607 if (!out_params->client_key_exchange->CalculateSharedKey(
608 public_value, &out_params->initial_premaster_secret)) {
594 *error_details = "Key exchange failure"; 609 *error_details = "Key exchange failure";
595 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 610 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
596 } 611 }
597 out->SetStringPiece(kPUBS, key_exchange->public_value()); 612 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value());
598 613
599 string hkdf_input(QuicCryptoConfig::kLabel, 614 out_params->hkdf_input_suffix.clear();
600 strlen(QuicCryptoConfig::kLabel) + 1); 615 out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&guid),
601 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid)); 616 sizeof(guid));
617 const QuicData& client_hello_serialized = out->GetSerialized();
618 out_params->hkdf_input_suffix.append(client_hello_serialized.data(),
619 client_hello_serialized.length());
620 out_params->hkdf_input_suffix.append(cached->server_config());
602 621
603 const QuicData& client_hello_serialized = out->GetSerialized(); 622 string hkdf_input;
604 hkdf_input.append(client_hello_serialized.data(), 623 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
605 client_hello_serialized.length()); 624 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
606 hkdf_input.append(cached->server_config()); 625 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
626 hkdf_input.append(out_params->hkdf_input_suffix);
607 627
608 CryptoUtils::DeriveKeys(out_params, nonce, hkdf_input, CryptoUtils::CLIENT); 628 CryptoUtils::DeriveKeys(out_params->initial_premaster_secret,
629 out_params->aead, out_params->client_nonce,
630 out_params->server_nonce, hkdf_input,
631 CryptoUtils::CLIENT, &out_params->initial_crypters);
609 632
610 return QUIC_NO_ERROR; 633 return QUIC_NO_ERROR;
611 } 634 }
612 635
613 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( 636 QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
614 CachedState* cached, 637 CachedState* cached,
615 const CryptoHandshakeMessage& rej, 638 const CryptoHandshakeMessage& rej,
616 QuicCryptoNegotiatedParameters* out_params, 639 QuicCryptoNegotiatedParameters* out_params,
617 string* error_details) { 640 string* error_details) {
618 DCHECK(error_details != NULL); 641 DCHECK(error_details != NULL);
619 642
620 StringPiece scfg; 643 StringPiece scfg;
621 if (!rej.GetStringPiece(kSCFG, &scfg)) { 644 if (!rej.GetStringPiece(kSCFG, &scfg)) {
622 *error_details = "Missing SCFG"; 645 *error_details = "Missing SCFG";
623 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 646 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
624 } 647 }
625 648
626 if (!cached->SetServerConfig(scfg)) { 649 if (!cached->SetServerConfig(scfg)) {
627 *error_details = "Invalid SCFG"; 650 *error_details = "Invalid SCFG";
628 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 651 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
629 } 652 }
630 653
631 StringPiece token; 654 StringPiece token;
632 if (rej.GetStringPiece(kSRCT, &token)) { 655 if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) {
633 cached->set_source_address_token(token); 656 cached->set_source_address_token(token);
634 } 657 }
635 658
636 StringPiece nonce; 659 StringPiece nonce;
637 if (rej.GetStringPiece(kNONC, &nonce) && 660 if (rej.GetStringPiece(kServerNonceTag, &nonce) && nonce.size() ==
638 nonce.size() == kNonceSize) { 661 kNonceSize) {
639 out_params->server_nonce = nonce.as_string(); 662 out_params->server_nonce = nonce.as_string();
640 } 663 }
641 664
642 StringPiece proof, cert_bytes; 665 StringPiece proof, cert_bytes;
643 if (rej.GetStringPiece(kPROF, &proof) && 666 if (rej.GetStringPiece(kPROF, &proof) &&
644 rej.GetStringPiece(kCERT, &cert_bytes)) { 667 rej.GetStringPiece(kCertificateTag, &cert_bytes)) {
645 vector<string> certs; 668 vector<string> certs;
646 if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs, 669 if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs,
647 common_cert_set_.get(), &certs)) { 670 common_cert_set_.get(), &certs)) {
648 *error_details = "Certificate data invalid"; 671 *error_details = "Certificate data invalid";
649 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 672 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
650 } 673 }
651 674
652 cached->SetProof(certs, proof); 675 cached->SetProof(certs, proof);
653 } 676 }
654 677
655 return QUIC_NO_ERROR; 678 return QUIC_NO_ERROR;
656 } 679 }
657 680
658 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( 681 QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
659 const CryptoHandshakeMessage& server_hello, 682 const CryptoHandshakeMessage& server_hello,
660 const string& nonce, 683 QuicGuid guid,
661 QuicCryptoNegotiatedParameters* out_params, 684 QuicCryptoNegotiatedParameters* out_params,
662 string* error_details) { 685 string* error_details) {
663 DCHECK(error_details != NULL); 686 DCHECK(error_details != NULL);
664 687
665 if (server_hello.tag() != kSHLO) { 688 if (server_hello.tag() != kSHLO) {
666 *error_details = "Bad tag"; 689 *error_details = "Bad tag";
667 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; 690 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
668 } 691 }
669 692
670 // TODO(agl): 693 // TODO(agl):
671 // learn about updated SCFGs. 694 // learn about updated SCFGs.
672 // read ephemeral public value for forward-secret keys. 695
696 StringPiece public_value;
697 if (!server_hello.GetStringPiece(kPUBS, &public_value)) {
698 *error_details = "server hello missing forward secure public value";
699 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
700 }
701
702 if (!out_params->client_key_exchange->CalculateSharedKey(
703 public_value, &out_params->forward_secure_premaster_secret)) {
704 *error_details = "Key exchange failure";
705 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
706 }
707
708 string hkdf_input;
709 const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
710 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
711 hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len);
712 hkdf_input.append(out_params->hkdf_input_suffix);
713
714 CryptoUtils::DeriveKeys(
715 out_params->forward_secure_premaster_secret, out_params->aead,
716 out_params->client_nonce, out_params->server_nonce, hkdf_input,
717 CryptoUtils::CLIENT, &out_params->forward_secure_crypters);
673 718
674 return QUIC_NO_ERROR; 719 return QUIC_NO_ERROR;
675 } 720 }
676 721
677 const ProofVerifier* QuicCryptoClientConfig::proof_verifier() const { 722 const ProofVerifier* QuicCryptoClientConfig::proof_verifier() const {
678 return proof_verifier_.get(); 723 return proof_verifier_.get();
679 } 724 }
680 725
681 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) { 726 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) {
682 proof_verifier_.reset(verifier); 727 proof_verifier_.reset(verifier);
683 } 728 }
684 729
685 } // namespace net 730 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/crypto/crypto_handshake.h ('k') | net/quic/crypto/crypto_handshake_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698