| OLD | NEW |
| 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/stringprintf.h" | 11 #include "base/stringprintf.h" |
| 12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
| 14 #include "crypto/secure_hash.h" | 14 #include "crypto/secure_hash.h" |
| 15 #include "net/base/net_util.h" | 15 #include "net/base/net_util.h" |
| 16 #include "net/quic/crypto/cert_compressor.h" | 16 #include "net/quic/crypto/cert_compressor.h" |
| 17 #include "net/quic/crypto/channel_id.h" |
| 17 #include "net/quic/crypto/common_cert_set.h" | 18 #include "net/quic/crypto/common_cert_set.h" |
| 18 #include "net/quic/crypto/crypto_framer.h" | 19 #include "net/quic/crypto/crypto_framer.h" |
| 19 #include "net/quic/crypto/crypto_utils.h" | 20 #include "net/quic/crypto/crypto_utils.h" |
| 20 #include "net/quic/crypto/curve25519_key_exchange.h" | 21 #include "net/quic/crypto/curve25519_key_exchange.h" |
| 21 #include "net/quic/crypto/key_exchange.h" | 22 #include "net/quic/crypto/key_exchange.h" |
| 22 #include "net/quic/crypto/p256_key_exchange.h" | 23 #include "net/quic/crypto/p256_key_exchange.h" |
| 23 #include "net/quic/crypto/proof_verifier.h" | 24 #include "net/quic/crypto/proof_verifier.h" |
| 24 #include "net/quic/crypto/quic_decrypter.h" | 25 #include "net/quic/crypto/quic_decrypter.h" |
| 25 #include "net/quic/crypto/quic_encrypter.h" | 26 #include "net/quic/crypto/quic_encrypter.h" |
| 26 #include "net/quic/crypto/quic_random.h" | 27 #include "net/quic/crypto/quic_random.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 38 CryptoHandshakeMessage::CryptoHandshakeMessage() | 39 CryptoHandshakeMessage::CryptoHandshakeMessage() |
| 39 : tag_(0), | 40 : tag_(0), |
| 40 minimum_size_(0) {} | 41 minimum_size_(0) {} |
| 41 | 42 |
| 42 CryptoHandshakeMessage::CryptoHandshakeMessage( | 43 CryptoHandshakeMessage::CryptoHandshakeMessage( |
| 43 const CryptoHandshakeMessage& other) | 44 const CryptoHandshakeMessage& other) |
| 44 : tag_(other.tag_), | 45 : tag_(other.tag_), |
| 45 tag_value_map_(other.tag_value_map_), | 46 tag_value_map_(other.tag_value_map_), |
| 46 minimum_size_(other.minimum_size_) { | 47 minimum_size_(other.minimum_size_) { |
| 47 // Don't copy serialized_. scoped_ptr doesn't have a copy constructor. | 48 // Don't copy serialized_. scoped_ptr doesn't have a copy constructor. |
| 48 // The new object can reconstruct serialized_ lazily. | 49 // The new object can lazily reconstruct serialized_. |
| 49 } | 50 } |
| 50 | 51 |
| 51 CryptoHandshakeMessage::~CryptoHandshakeMessage() {} | 52 CryptoHandshakeMessage::~CryptoHandshakeMessage() {} |
| 52 | 53 |
| 53 CryptoHandshakeMessage& CryptoHandshakeMessage::operator=( | 54 CryptoHandshakeMessage& CryptoHandshakeMessage::operator=( |
| 54 const CryptoHandshakeMessage& other) { | 55 const CryptoHandshakeMessage& other) { |
| 55 tag_ = other.tag_; | 56 tag_ = other.tag_; |
| 56 tag_value_map_ = other.tag_value_map_; | 57 tag_value_map_ = other.tag_value_map_; |
| 57 // Don't copy serialized_. scoped_ptr doesn't have an assignment operator. | 58 // Don't copy serialized_. scoped_ptr doesn't have an assignment operator. |
| 58 // However, invalidate serialized_. | 59 // However, invalidate serialized_. |
| 59 serialized_.reset(); | 60 serialized_.reset(); |
| 60 minimum_size_ = other.minimum_size_; | 61 minimum_size_ = other.minimum_size_; |
| 61 return *this; | 62 return *this; |
| 62 } | 63 } |
| 63 | 64 |
| 64 void CryptoHandshakeMessage::Clear() { | 65 void CryptoHandshakeMessage::Clear() { |
| 65 tag_ = 0; | 66 tag_ = 0; |
| 66 tag_value_map_.clear(); | 67 tag_value_map_.clear(); |
| 67 minimum_size_ = 0; | 68 minimum_size_ = 0; |
| 68 serialized_.reset(); | 69 serialized_.reset(); |
| 69 } | 70 } |
| 70 | 71 |
| 71 const QuicData& CryptoHandshakeMessage::GetSerialized() const { | 72 const QuicData& CryptoHandshakeMessage::GetSerialized() const { |
| 72 if (!serialized_.get()) { | 73 if (!serialized_.get()) { |
| 73 serialized_.reset(CryptoFramer::ConstructHandshakeMessage(*this)); | 74 serialized_.reset(CryptoFramer::ConstructHandshakeMessage(*this)); |
| 74 } | 75 } |
| 75 return *serialized_.get(); | 76 return *serialized_.get(); |
| 76 } | 77 } |
| 77 | 78 |
| 79 void CryptoHandshakeMessage::MarkDirty() { |
| 80 serialized_.reset(); |
| 81 } |
| 82 |
| 78 void CryptoHandshakeMessage::Insert(QuicTagValueMap::const_iterator begin, | 83 void CryptoHandshakeMessage::Insert(QuicTagValueMap::const_iterator begin, |
| 79 QuicTagValueMap::const_iterator end) { | 84 QuicTagValueMap::const_iterator end) { |
| 80 tag_value_map_.insert(begin, end); | 85 tag_value_map_.insert(begin, end); |
| 81 } | 86 } |
| 82 | 87 |
| 83 void CryptoHandshakeMessage::SetTaglist(QuicTag tag, ...) { | 88 void CryptoHandshakeMessage::SetTaglist(QuicTag tag, ...) { |
| 84 // Warning, if sizeof(QuicTag) > sizeof(int) then this function will break | 89 // Warning, if sizeof(QuicTag) > sizeof(int) then this function will break |
| 85 // because the terminating 0 will only be promoted to int. | 90 // because the terminating 0 will only be promoted to int. |
| 86 COMPILE_ASSERT(sizeof(QuicTag) <= sizeof(int), | 91 COMPILE_ASSERT(sizeof(QuicTag) <= sizeof(int), |
| 87 crypto_tag_not_be_larger_than_int_or_varargs_will_break); | 92 crypto_tag_may_not_be_larger_than_int_or_varargs_will_break); |
| 88 | 93 |
| 89 vector<QuicTag> tags; | 94 vector<QuicTag> tags; |
| 90 va_list ap; | 95 va_list ap; |
| 91 | 96 |
| 92 va_start(ap, tag); | 97 va_start(ap, tag); |
| 93 for (;;) { | 98 for (;;) { |
| 94 QuicTag list_item = va_arg(ap, QuicTag); | 99 QuicTag list_item = va_arg(ap, QuicTag); |
| 95 if (list_item == 0) { | 100 if (list_item == 0) { |
| 96 break; | 101 break; |
| 97 } | 102 } |
| 98 tags.push_back(list_item); | 103 tags.push_back(list_item); |
| 99 } | 104 } |
| 100 | 105 |
| 101 // Because of the way that we keep tags in memory, we can copy the contents | 106 // Because of the way that we keep tags in memory, we can copy the contents |
| 102 // of the vector and get the correct bytes in wire format. See | 107 // of the vector and get the correct bytes in wire format. See |
| 103 // crypto_protocol.h. This assumes that the system is little-endian. | 108 // crypto_protocol.h. This assumes that the system is little-endian. |
| 104 SetVector(tag, tags); | 109 SetVector(tag, tags); |
| 105 | 110 |
| 106 va_end(ap); | 111 va_end(ap); |
| 107 } | 112 } |
| 108 | 113 |
| 109 void CryptoHandshakeMessage::SetStringPiece(QuicTag tag, StringPiece value) { | 114 void CryptoHandshakeMessage::SetStringPiece(QuicTag tag, StringPiece value) { |
| 110 tag_value_map_[tag] = value.as_string(); | 115 tag_value_map_[tag] = value.as_string(); |
| 111 } | 116 } |
| 112 | 117 |
| 118 void CryptoHandshakeMessage::Erase(QuicTag tag) { |
| 119 tag_value_map_.erase(tag); |
| 120 } |
| 121 |
| 113 QuicErrorCode CryptoHandshakeMessage::GetTaglist(QuicTag tag, | 122 QuicErrorCode CryptoHandshakeMessage::GetTaglist(QuicTag tag, |
| 114 const QuicTag** out_tags, | 123 const QuicTag** out_tags, |
| 115 size_t* out_len) const { | 124 size_t* out_len) const { |
| 116 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag); | 125 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag); |
| 117 QuicErrorCode ret = QUIC_NO_ERROR; | 126 QuicErrorCode ret = QUIC_NO_ERROR; |
| 118 | 127 |
| 119 if (it == tag_value_map_.end()) { | 128 if (it == tag_value_map_.end()) { |
| 120 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | 129 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; |
| 121 } else if (it->second.size() % sizeof(QuicTag) != 0) { | 130 } else if (it->second.size() % sizeof(QuicTag) != 0) { |
| 122 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 131 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 | 181 |
| 173 if (i == index) { | 182 if (i == index) { |
| 174 *out = StringPiece(value.data(), size); | 183 *out = StringPiece(value.data(), size); |
| 175 return QUIC_NO_ERROR; | 184 return QUIC_NO_ERROR; |
| 176 } | 185 } |
| 177 | 186 |
| 178 value.remove_prefix(size); | 187 value.remove_prefix(size); |
| 179 } | 188 } |
| 180 } | 189 } |
| 181 | 190 |
| 182 bool CryptoHandshakeMessage::GetString(QuicTag tag, string* out) const { | |
| 183 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag); | |
| 184 if (it == tag_value_map_.end()) { | |
| 185 return false; | |
| 186 } | |
| 187 *out = it->second; | |
| 188 return true; | |
| 189 } | |
| 190 | |
| 191 QuicErrorCode CryptoHandshakeMessage::GetUint16(QuicTag tag, | 191 QuicErrorCode CryptoHandshakeMessage::GetUint16(QuicTag tag, |
| 192 uint16* out) const { | 192 uint16* out) const { |
| 193 return GetPOD(tag, out, sizeof(uint16)); | 193 return GetPOD(tag, out, sizeof(uint16)); |
| 194 } | 194 } |
| 195 | 195 |
| 196 QuicErrorCode CryptoHandshakeMessage::GetUint32(QuicTag tag, | 196 QuicErrorCode CryptoHandshakeMessage::GetUint32(QuicTag tag, |
| 197 uint32* out) const { | 197 uint32* out) const { |
| 198 return GetPOD(tag, out, sizeof(uint32)); | 198 return GetPOD(tag, out, sizeof(uint32)); |
| 199 } | 199 } |
| 200 | 200 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 211 tag_value_map_.size(); | 211 tag_value_map_.size(); |
| 212 for (QuicTagValueMap::const_iterator i = tag_value_map_.begin(); | 212 for (QuicTagValueMap::const_iterator i = tag_value_map_.begin(); |
| 213 i != tag_value_map_.end(); ++i) { | 213 i != tag_value_map_.end(); ++i) { |
| 214 ret += i->second.size(); | 214 ret += i->second.size(); |
| 215 } | 215 } |
| 216 | 216 |
| 217 return ret; | 217 return ret; |
| 218 } | 218 } |
| 219 | 219 |
| 220 void CryptoHandshakeMessage::set_minimum_size(size_t min_bytes) { | 220 void CryptoHandshakeMessage::set_minimum_size(size_t min_bytes) { |
| 221 if (min_bytes == minimum_size_) { |
| 222 return; |
| 223 } |
| 221 serialized_.reset(); | 224 serialized_.reset(); |
| 222 minimum_size_ = min_bytes; | 225 minimum_size_ = min_bytes; |
| 223 } | 226 } |
| 224 | 227 |
| 225 size_t CryptoHandshakeMessage::minimum_size() const { | 228 size_t CryptoHandshakeMessage::minimum_size() const { |
| 226 return minimum_size_; | 229 return minimum_size_; |
| 227 } | 230 } |
| 228 | 231 |
| 229 string CryptoHandshakeMessage::DebugString() const { | 232 string CryptoHandshakeMessage::DebugString() const { |
| 230 return DebugStringInternal(0); | 233 return DebugStringInternal(0); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 | 323 |
| 321 QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters() | 324 QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters() |
| 322 : version(0), | 325 : version(0), |
| 323 key_exchange(0), | 326 key_exchange(0), |
| 324 aead(0) { | 327 aead(0) { |
| 325 } | 328 } |
| 326 | 329 |
| 327 QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {} | 330 QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {} |
| 328 | 331 |
| 329 CrypterPair::CrypterPair() {} | 332 CrypterPair::CrypterPair() {} |
| 333 |
| 330 CrypterPair::~CrypterPair() {} | 334 CrypterPair::~CrypterPair() {} |
| 331 | 335 |
| 332 // static | 336 // static |
| 333 const char QuicCryptoConfig::kInitialLabel[] = "QUIC key expansion"; | 337 const char QuicCryptoConfig::kInitialLabel[] = "QUIC key expansion"; |
| 334 | 338 |
| 339 // static |
| 340 const char QuicCryptoConfig::kCETVLabel[] = "QUIC CETV block"; |
| 341 |
| 342 // static |
| 335 const char QuicCryptoConfig::kForwardSecureLabel[] = | 343 const char QuicCryptoConfig::kForwardSecureLabel[] = |
| 336 "QUIC forward secure key expansion"; | 344 "QUIC forward secure key expansion"; |
| 337 | 345 |
| 338 QuicCryptoConfig::QuicCryptoConfig() | 346 QuicCryptoConfig::QuicCryptoConfig() |
| 339 : version(0), | 347 : version(0), |
| 340 common_cert_sets(new CommonCertSetsQUIC) { | 348 common_cert_sets(CommonCertSets::GetInstanceQUIC()) { |
| 341 } | 349 } |
| 342 | 350 |
| 343 QuicCryptoConfig::~QuicCryptoConfig() {} | 351 QuicCryptoConfig::~QuicCryptoConfig() {} |
| 344 | 352 |
| 345 QuicCryptoClientConfig::QuicCryptoClientConfig() {} | 353 QuicCryptoClientConfig::QuicCryptoClientConfig() {} |
| 346 | 354 |
| 347 QuicCryptoClientConfig::~QuicCryptoClientConfig() { | 355 QuicCryptoClientConfig::~QuicCryptoClientConfig() { |
| 348 STLDeleteValues(&cached_states_); | 356 STLDeleteValues(&cached_states_); |
| 349 } | 357 } |
| 350 | 358 |
| 351 QuicCryptoClientConfig::CachedState::CachedState() | 359 QuicCryptoClientConfig::CachedState::CachedState() |
| 352 : server_config_valid_(false) {} | 360 : server_config_valid_(false) {} |
| 353 | 361 |
| 354 QuicCryptoClientConfig::CachedState::~CachedState() {} | 362 QuicCryptoClientConfig::CachedState::~CachedState() {} |
| 355 | 363 |
| 356 bool QuicCryptoClientConfig::CachedState::is_complete() const { | 364 bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const { |
| 357 return !server_config_.empty() && server_config_valid_; | 365 if (server_config_.empty() || !server_config_valid_) { |
| 366 return false; |
| 367 } |
| 368 |
| 369 const CryptoHandshakeMessage* scfg = GetServerConfig(); |
| 370 if (!scfg) { |
| 371 // Should be impossible short of cache corruption. |
| 372 DCHECK(false); |
| 373 return false; |
| 374 } |
| 375 |
| 376 uint64 expiry_seconds; |
| 377 if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR || |
| 378 now.ToUNIXSeconds() >= expiry_seconds) { |
| 379 return false; |
| 380 } |
| 381 |
| 382 return true; |
| 358 } | 383 } |
| 359 | 384 |
| 360 const CryptoHandshakeMessage* | 385 const CryptoHandshakeMessage* |
| 361 QuicCryptoClientConfig::CachedState::GetServerConfig() const { | 386 QuicCryptoClientConfig::CachedState::GetServerConfig() const { |
| 362 if (server_config_.empty()) { | 387 if (server_config_.empty()) { |
| 363 return NULL; | 388 return NULL; |
| 364 } | 389 } |
| 365 | 390 |
| 366 if (!scfg_.get()) { | 391 if (!scfg_.get()) { |
| 367 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); | 392 scfg_.reset(CryptoFramer::ParseMessage(server_config_)); |
| 368 DCHECK(scfg_.get()); | 393 DCHECK(scfg_.get()); |
| 369 } | 394 } |
| 370 return scfg_.get(); | 395 return scfg_.get(); |
| 371 } | 396 } |
| 372 | 397 |
| 373 bool QuicCryptoClientConfig::CachedState::SetServerConfig(StringPiece scfg) { | 398 QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig( |
| 374 if (scfg == server_config_) { | 399 StringPiece server_config, QuicWallTime now, string* error_details) { |
| 375 return true; | 400 const bool matches_existing = server_config == server_config_; |
| 401 |
| 402 // Even if the new server config matches the existing one, we still wish to |
| 403 // reject it if it has expired. |
| 404 scoped_ptr<CryptoHandshakeMessage> new_scfg_storage; |
| 405 const CryptoHandshakeMessage* new_scfg; |
| 406 |
| 407 if (!matches_existing) { |
| 408 new_scfg_storage.reset(CryptoFramer::ParseMessage(server_config)); |
| 409 new_scfg = new_scfg_storage.get(); |
| 410 } else { |
| 411 new_scfg = GetServerConfig(); |
| 376 } | 412 } |
| 377 | 413 |
| 378 scfg_.reset(CryptoFramer::ParseMessage(scfg)); | 414 if (!new_scfg) { |
| 379 if (!scfg_.get()) { | 415 *error_details = "SCFG invalid"; |
| 380 return false; | 416 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 381 } | 417 } |
| 382 server_config_ = scfg.as_string(); | 418 |
| 419 uint64 expiry_seconds; |
| 420 if (new_scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) { |
| 421 *error_details = "SCFG missing EXPY"; |
| 422 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 423 } |
| 424 |
| 425 if (now.ToUNIXSeconds() >= expiry_seconds) { |
| 426 *error_details = "SCFG has expired"; |
| 427 return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED; |
| 428 } |
| 429 |
| 430 if (!matches_existing) { |
| 431 server_config_ = server_config.as_string(); |
| 432 server_config_valid_ = false; |
| 433 scfg_.reset(new_scfg_storage.release()); |
| 434 } |
| 435 return QUIC_NO_ERROR; |
| 436 } |
| 437 |
| 438 void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() { |
| 439 server_config_.clear(); |
| 440 scfg_.reset(); |
| 383 server_config_valid_ = false; | 441 server_config_valid_ = false; |
| 384 return true; | |
| 385 } | 442 } |
| 386 | 443 |
| 387 void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs, | 444 void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs, |
| 388 StringPiece signature) { | 445 StringPiece signature) { |
| 389 bool has_changed = signature != server_config_sig_; | 446 bool has_changed = |
| 447 signature != server_config_sig_ || certs_.size() != certs.size(); |
| 390 | 448 |
| 391 if (certs_.size() != certs.size()) { | |
| 392 has_changed = true; | |
| 393 } | |
| 394 if (!has_changed) { | 449 if (!has_changed) { |
| 395 for (size_t i = 0; i < certs_.size(); i++) { | 450 for (size_t i = 0; i < certs_.size(); i++) { |
| 396 if (certs_[i] != certs[i]) { | 451 if (certs_[i] != certs[i]) { |
| 397 has_changed = true; | 452 has_changed = true; |
| 398 break; | 453 break; |
| 399 } | 454 } |
| 400 } | 455 } |
| 401 } | 456 } |
| 402 | 457 |
| 403 if (!has_changed) { | 458 if (!has_changed) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 return server_config_valid_; | 490 return server_config_valid_; |
| 436 } | 491 } |
| 437 | 492 |
| 438 void QuicCryptoClientConfig::CachedState::set_source_address_token( | 493 void QuicCryptoClientConfig::CachedState::set_source_address_token( |
| 439 StringPiece token) { | 494 StringPiece token) { |
| 440 source_address_token_ = token.as_string(); | 495 source_address_token_ = token.as_string(); |
| 441 } | 496 } |
| 442 | 497 |
| 443 void QuicCryptoClientConfig::SetDefaults() { | 498 void QuicCryptoClientConfig::SetDefaults() { |
| 444 // Version must be 0. | 499 // Version must be 0. |
| 500 // TODO(agl): this version stuff is obsolete now. |
| 445 version = QuicCryptoConfig::CONFIG_VERSION; | 501 version = QuicCryptoConfig::CONFIG_VERSION; |
| 446 | 502 |
| 447 // Key exchange methods. | 503 // Key exchange methods. |
| 448 kexs.resize(2); | 504 kexs.resize(2); |
| 449 kexs[0] = kC255; | 505 kexs[0] = kC255; |
| 450 kexs[1] = kP256; | 506 kexs[1] = kP256; |
| 451 | 507 |
| 452 // Authenticated encryption algorithms. | 508 // Authenticated encryption algorithms. |
| 453 aead.resize(1); | 509 aead.resize(1); |
| 454 aead[0] = kAESG; | 510 aead[0] = kAESG; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 483 out->SetValue(kVERS, version); | 539 out->SetValue(kVERS, version); |
| 484 | 540 |
| 485 if (!cached->source_address_token().empty()) { | 541 if (!cached->source_address_token().empty()) { |
| 486 out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token()); | 542 out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token()); |
| 487 } | 543 } |
| 488 | 544 |
| 489 if (proof_verifier_.get()) { | 545 if (proof_verifier_.get()) { |
| 490 out->SetTaglist(kPDMD, kX509, 0); | 546 out->SetTaglist(kPDMD, kX509, 0); |
| 491 } | 547 } |
| 492 | 548 |
| 493 if (common_cert_sets.get()) { | 549 if (common_cert_sets) { |
| 494 out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes()); | 550 out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes()); |
| 495 } | 551 } |
| 496 | 552 |
| 497 const vector<string>& certs = cached->certs(); | 553 const vector<string>& certs = cached->certs(); |
| 498 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the | 554 // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the |
| 499 // client config is being used for multiple connections, another connection | 555 // client config is being used for multiple connections, another connection |
| 500 // doesn't update the cached certificates and cause us to be unable to | 556 // doesn't update the cached certificates and cause us to be unable to |
| 501 // process the server's compressed certificate chain. | 557 // process the server's compressed certificate chain. |
| 502 out_params->cached_certs = certs; | 558 out_params->cached_certs = certs; |
| 503 if (!certs.empty()) { | 559 if (!certs.empty()) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 520 QuicCryptoNegotiatedParameters* out_params, | 576 QuicCryptoNegotiatedParameters* out_params, |
| 521 CryptoHandshakeMessage* out, | 577 CryptoHandshakeMessage* out, |
| 522 string* error_details) const { | 578 string* error_details) const { |
| 523 DCHECK(error_details != NULL); | 579 DCHECK(error_details != NULL); |
| 524 | 580 |
| 525 FillInchoateClientHello(server_hostname, cached, out_params, out); | 581 FillInchoateClientHello(server_hostname, cached, out_params, out); |
| 526 | 582 |
| 527 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); | 583 const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); |
| 528 if (!scfg) { | 584 if (!scfg) { |
| 529 // This should never happen as our caller should have checked | 585 // This should never happen as our caller should have checked |
| 530 // cached->is_complete() before calling this function. | 586 // cached->IsComplete() before calling this function. |
| 531 *error_details = "Handshake not ready"; | 587 *error_details = "Handshake not ready"; |
| 532 return QUIC_CRYPTO_INTERNAL_ERROR; | 588 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 533 } | 589 } |
| 534 | 590 |
| 535 uint64 expiry_seconds; | |
| 536 if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) { | |
| 537 *error_details = "SCFG missing EXPY"; | |
| 538 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | |
| 539 } | |
| 540 | |
| 541 if (static_cast<uint64>(now.ToUNIXSeconds()) >= expiry_seconds) { | |
| 542 *error_details = "SCFG expired"; | |
| 543 return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED; | |
| 544 } | |
| 545 | |
| 546 StringPiece scid; | 591 StringPiece scid; |
| 547 if (!scfg->GetStringPiece(kSCID, &scid)) { | 592 if (!scfg->GetStringPiece(kSCID, &scid)) { |
| 548 *error_details = "SCFG missing SCID"; | 593 *error_details = "SCFG missing SCID"; |
| 549 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 594 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 550 } | 595 } |
| 551 out->SetStringPiece(kSCID, scid); | 596 out->SetStringPiece(kSCID, scid); |
| 552 | 597 |
| 553 // Calculate the mutual algorithms that the connection is going to use. | |
| 554 if (scfg->GetUint16(kVERS, &out_params->version) != QUIC_NO_ERROR || | |
| 555 out_params->version != QuicCryptoConfig::CONFIG_VERSION) { | |
| 556 *error_details = "Bad version"; | |
| 557 return QUIC_CRYPTO_VERSION_NOT_SUPPORTED; | |
| 558 } | |
| 559 | |
| 560 const QuicTag* their_aeads; | 598 const QuicTag* their_aeads; |
| 561 const QuicTag* their_key_exchanges; | 599 const QuicTag* their_key_exchanges; |
| 562 size_t num_their_aeads, num_their_key_exchanges; | 600 size_t num_their_aeads, num_their_key_exchanges; |
| 563 if (scfg->GetTaglist(kAEAD, &their_aeads, | 601 if (scfg->GetTaglist(kAEAD, &their_aeads, |
| 564 &num_their_aeads) != QUIC_NO_ERROR || | 602 &num_their_aeads) != QUIC_NO_ERROR || |
| 565 scfg->GetTaglist(kKEXS, &their_key_exchanges, | 603 scfg->GetTaglist(kKEXS, &their_key_exchanges, |
| 566 &num_their_key_exchanges) != QUIC_NO_ERROR) { | 604 &num_their_key_exchanges) != QUIC_NO_ERROR) { |
| 567 *error_details = "Missing AEAD or KEXS"; | 605 *error_details = "Missing AEAD or KEXS"; |
| 568 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 606 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 569 } | 607 } |
| 570 | 608 |
| 571 size_t key_exchange_index; | 609 size_t key_exchange_index; |
| 572 if (!QuicUtils::FindMutualTag(aead, their_aeads, num_their_aeads, | 610 if (!QuicUtils::FindMutualTag( |
| 573 QuicUtils::PEER_PRIORITY, &out_params->aead, | 611 aead, their_aeads, num_their_aeads, QuicUtils::PEER_PRIORITY, |
| 574 NULL) || | 612 &out_params->aead, NULL) || |
| 575 !QuicUtils::FindMutualTag( | 613 !QuicUtils::FindMutualTag( |
| 576 kexs, their_key_exchanges, num_their_key_exchanges, | 614 kexs, their_key_exchanges, num_their_key_exchanges, |
| 577 QuicUtils::PEER_PRIORITY, &out_params->key_exchange, | 615 QuicUtils::PEER_PRIORITY, &out_params->key_exchange, |
| 578 &key_exchange_index)) { | 616 &key_exchange_index)) { |
| 579 *error_details = "Unsupported AEAD or KEXS"; | 617 *error_details = "Unsupported AEAD or KEXS"; |
| 580 return QUIC_CRYPTO_NO_SUPPORT; | 618 return QUIC_CRYPTO_NO_SUPPORT; |
| 581 } | 619 } |
| 582 out->SetTaglist(kAEAD, out_params->aead, 0); | 620 out->SetTaglist(kAEAD, out_params->aead, 0); |
| 583 out->SetTaglist(kKEXS, out_params->key_exchange, 0); | 621 out->SetTaglist(kKEXS, out_params->key_exchange, 0); |
| 584 | 622 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 600 if (!out_params->server_nonce.empty()) { | 638 if (!out_params->server_nonce.empty()) { |
| 601 out->SetStringPiece(kServerNonceTag, out_params->server_nonce); | 639 out->SetStringPiece(kServerNonceTag, out_params->server_nonce); |
| 602 } | 640 } |
| 603 | 641 |
| 604 switch (out_params->key_exchange) { | 642 switch (out_params->key_exchange) { |
| 605 case kC255: | 643 case kC255: |
| 606 out_params->client_key_exchange.reset(Curve25519KeyExchange::New( | 644 out_params->client_key_exchange.reset(Curve25519KeyExchange::New( |
| 607 Curve25519KeyExchange::NewPrivateKey(rand))); | 645 Curve25519KeyExchange::NewPrivateKey(rand))); |
| 608 break; | 646 break; |
| 609 case kP256: | 647 case kP256: |
| 610 out_params->client_key_exchange | 648 out_params->client_key_exchange.reset(P256KeyExchange::New( |
| 611 .reset(P256KeyExchange::New(P256KeyExchange::NewPrivateKey())); | 649 P256KeyExchange::NewPrivateKey())); |
| 612 break; | 650 break; |
| 613 default: | 651 default: |
| 614 DCHECK(false); | 652 DCHECK(false); |
| 615 *error_details = "Configured to support an unknown key exchange"; | 653 *error_details = "Configured to support an unknown key exchange"; |
| 616 return QUIC_CRYPTO_INTERNAL_ERROR; | 654 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 617 } | 655 } |
| 618 | 656 |
| 619 if (!out_params->client_key_exchange->CalculateSharedKey( | 657 if (!out_params->client_key_exchange->CalculateSharedKey( |
| 620 public_value, &out_params->initial_premaster_secret)) { | 658 public_value, &out_params->initial_premaster_secret)) { |
| 621 *error_details = "Key exchange failure"; | 659 *error_details = "Key exchange failure"; |
| 622 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 660 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 623 } | 661 } |
| 624 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); | 662 out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); |
| 625 | 663 |
| 664 bool do_channel_id = false; |
| 665 if (channel_id_signer_.get()) { |
| 666 const QuicTag* their_proof_demands; |
| 667 size_t num_their_proof_demands; |
| 668 if (scfg->GetTaglist(kPDMD, &their_proof_demands, |
| 669 &num_their_proof_demands) == QUIC_NO_ERROR) { |
| 670 for (size_t i = 0; i < num_their_proof_demands; i++) { |
| 671 if (their_proof_demands[i] == kCHID) { |
| 672 do_channel_id = true; |
| 673 break; |
| 674 } |
| 675 } |
| 676 } |
| 677 } |
| 678 |
| 679 if (do_channel_id) { |
| 680 // In order to calculate the encryption key for the CETV block we need to |
| 681 // serialise the client hello as it currently is (i.e. without the CETV |
| 682 // block). For this, the client hello is serialized without padding. |
| 683 const size_t orig_min_size = out->minimum_size(); |
| 684 out->set_minimum_size(0); |
| 685 |
| 686 CryptoHandshakeMessage cetv; |
| 687 cetv.set_tag(kCETV); |
| 688 |
| 689 string hkdf_input; |
| 690 const QuicData& client_hello_serialized = out->GetSerialized(); |
| 691 hkdf_input.append(QuicCryptoConfig::kCETVLabel, |
| 692 strlen(QuicCryptoConfig::kCETVLabel) + 1); |
| 693 hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid)); |
| 694 hkdf_input.append(client_hello_serialized.data(), |
| 695 client_hello_serialized.length()); |
| 696 hkdf_input.append(cached->server_config()); |
| 697 |
| 698 string key, signature; |
| 699 if (!channel_id_signer_->Sign(server_hostname, hkdf_input, |
| 700 &key, &signature)) { |
| 701 *error_details = "Channel ID signature failed"; |
| 702 return QUIC_INTERNAL_ERROR; |
| 703 } |
| 704 |
| 705 cetv.SetStringPiece(kCIDK, key); |
| 706 cetv.SetStringPiece(kCIDS, signature); |
| 707 |
| 708 CrypterPair crypters; |
| 709 CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, |
| 710 out_params->aead, out_params->client_nonce, |
| 711 out_params->server_nonce, hkdf_input, |
| 712 CryptoUtils::CLIENT, &crypters); |
| 713 |
| 714 const QuicData& cetv_plaintext = cetv.GetSerialized(); |
| 715 scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket( |
| 716 0 /* sequence number */, |
| 717 StringPiece() /* associated data */, |
| 718 cetv_plaintext.AsStringPiece())); |
| 719 |
| 720 out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece()); |
| 721 out->MarkDirty(); |
| 722 |
| 723 out->set_minimum_size(orig_min_size); |
| 724 } |
| 725 |
| 626 out_params->hkdf_input_suffix.clear(); | 726 out_params->hkdf_input_suffix.clear(); |
| 627 out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&guid), | 727 out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&guid), |
| 628 sizeof(guid)); | 728 sizeof(guid)); |
| 629 const QuicData& client_hello_serialized = out->GetSerialized(); | 729 const QuicData& client_hello_serialized = out->GetSerialized(); |
| 630 out_params->hkdf_input_suffix.append(client_hello_serialized.data(), | 730 out_params->hkdf_input_suffix.append(client_hello_serialized.data(), |
| 631 client_hello_serialized.length()); | 731 client_hello_serialized.length()); |
| 632 out_params->hkdf_input_suffix.append(cached->server_config()); | 732 out_params->hkdf_input_suffix.append(cached->server_config()); |
| 633 | 733 |
| 634 string hkdf_input; | 734 string hkdf_input; |
| 635 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; | 735 const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; |
| 636 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); | 736 hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); |
| 637 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); | 737 hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); |
| 638 hkdf_input.append(out_params->hkdf_input_suffix); | 738 hkdf_input.append(out_params->hkdf_input_suffix); |
| 639 | 739 |
| 640 CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, | 740 CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, |
| 641 out_params->aead, out_params->client_nonce, | 741 out_params->aead, out_params->client_nonce, |
| 642 out_params->server_nonce, hkdf_input, | 742 out_params->server_nonce, hkdf_input, |
| 643 CryptoUtils::CLIENT, &out_params->initial_crypters); | 743 CryptoUtils::CLIENT, &out_params->initial_crypters); |
| 644 | 744 |
| 645 return QUIC_NO_ERROR; | 745 return QUIC_NO_ERROR; |
| 646 } | 746 } |
| 647 | 747 |
| 648 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( | 748 QuicErrorCode QuicCryptoClientConfig::ProcessRejection( |
| 649 CachedState* cached, | 749 CachedState* cached, |
| 650 const CryptoHandshakeMessage& rej, | 750 const CryptoHandshakeMessage& rej, |
| 751 QuicWallTime now, |
| 651 QuicCryptoNegotiatedParameters* out_params, | 752 QuicCryptoNegotiatedParameters* out_params, |
| 652 string* error_details) { | 753 string* error_details) { |
| 653 DCHECK(error_details != NULL); | 754 DCHECK(error_details != NULL); |
| 654 | 755 |
| 756 if (rej.tag() != kREJ) { |
| 757 *error_details = "Message is not REJ"; |
| 758 return QUIC_CRYPTO_INTERNAL_ERROR; |
| 759 } |
| 760 |
| 655 StringPiece scfg; | 761 StringPiece scfg; |
| 656 if (!rej.GetStringPiece(kSCFG, &scfg)) { | 762 if (!rej.GetStringPiece(kSCFG, &scfg)) { |
| 657 *error_details = "Missing SCFG"; | 763 *error_details = "Missing SCFG"; |
| 658 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; | 764 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; |
| 659 } | 765 } |
| 660 | 766 |
| 661 if (!cached->SetServerConfig(scfg)) { | 767 QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details); |
| 662 *error_details = "Invalid SCFG"; | 768 if (error != QUIC_NO_ERROR) { |
| 663 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 769 return error; |
| 664 } | 770 } |
| 665 | 771 |
| 666 StringPiece token; | 772 StringPiece token; |
| 667 if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) { | 773 if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) { |
| 668 cached->set_source_address_token(token); | 774 cached->set_source_address_token(token); |
| 669 } | 775 } |
| 670 | 776 |
| 671 StringPiece nonce; | 777 StringPiece nonce; |
| 672 if (rej.GetStringPiece(kServerNonceTag, &nonce) && nonce.size() == | 778 if (rej.GetStringPiece(kServerNonceTag, &nonce)) { |
| 673 kNonceSize) { | |
| 674 out_params->server_nonce = nonce.as_string(); | 779 out_params->server_nonce = nonce.as_string(); |
| 675 } | 780 } |
| 676 | 781 |
| 677 StringPiece proof, cert_bytes; | 782 StringPiece proof, cert_bytes; |
| 678 if (rej.GetStringPiece(kPROF, &proof) && | 783 if (rej.GetStringPiece(kPROF, &proof) && |
| 679 rej.GetStringPiece(kCertificateTag, &cert_bytes)) { | 784 rej.GetStringPiece(kCertificateTag, &cert_bytes)) { |
| 680 vector<string> certs; | 785 vector<string> certs; |
| 681 if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs, | 786 if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs, |
| 682 common_cert_sets.get(), &certs)) { | 787 common_cert_sets, &certs)) { |
| 683 *error_details = "Certificate data invalid"; | 788 *error_details = "Certificate data invalid"; |
| 684 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; | 789 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; |
| 685 } | 790 } |
| 686 | 791 |
| 687 cached->SetProof(certs, proof); | 792 cached->SetProof(certs, proof); |
| 688 } | 793 } |
| 689 | 794 |
| 690 return QUIC_NO_ERROR; | 795 return QUIC_NO_ERROR; |
| 691 } | 796 } |
| 692 | 797 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 } | 837 } |
| 733 | 838 |
| 734 const ProofVerifier* QuicCryptoClientConfig::proof_verifier() const { | 839 const ProofVerifier* QuicCryptoClientConfig::proof_verifier() const { |
| 735 return proof_verifier_.get(); | 840 return proof_verifier_.get(); |
| 736 } | 841 } |
| 737 | 842 |
| 738 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) { | 843 void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) { |
| 739 proof_verifier_.reset(verifier); | 844 proof_verifier_.reset(verifier); |
| 740 } | 845 } |
| 741 | 846 |
| 847 void QuicCryptoClientConfig::SetChannelIDSigner(ChannelIDSigner* signer) { |
| 848 channel_id_signer_.reset(signer); |
| 849 } |
| 850 |
| 742 } // namespace net | 851 } // namespace net |
| OLD | NEW |