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 3 // found in the LICENSE file. 4 5 #include "net/quic/crypto/crypto_handshake.h" 6 7 #include <ctype.h> 8 9 #include "base/memory/scoped_ptr.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_split.h" 13 #include "crypto/secure_hash.h" 14 #include "net/base/net_util.h" 15 #include "net/quic/crypto/common_cert_set.h" 16 #include "net/quic/crypto/crypto_framer.h" 17 #include "net/quic/crypto/key_exchange.h" 18 #include "net/quic/crypto/quic_decrypter.h" 19 #include "net/quic/crypto/quic_encrypter.h" 20 #include "net/quic/crypto/quic_random.h" 21 #include "net/quic/quic_protocol.h" 22 #include "net/quic/quic_utils.h" 23 24 using base::StringPiece; 25 using base::StringPrintf; 26 using std::string; 27 using std::vector; 28 29 namespace net { 30 31 CryptoHandshakeMessage::CryptoHandshakeMessage() 32 : tag_(0), 33 minimum_size_(0) {} 34 35 CryptoHandshakeMessage::CryptoHandshakeMessage( 36 const CryptoHandshakeMessage& other) 37 : tag_(other.tag_), 38 tag_value_map_(other.tag_value_map_), 39 minimum_size_(other.minimum_size_) { 40 // Don't copy serialized_. scoped_ptr doesn't have a copy constructor. 41 // The new object can lazily reconstruct serialized_. 42 } 43 44 CryptoHandshakeMessage::~CryptoHandshakeMessage() {} 45 46 CryptoHandshakeMessage& CryptoHandshakeMessage::operator=( 47 const CryptoHandshakeMessage& other) { 48 tag_ = other.tag_; 49 tag_value_map_ = other.tag_value_map_; 50 // Don't copy serialized_. scoped_ptr doesn't have an assignment operator. 51 // However, invalidate serialized_. 52 serialized_.reset(); 53 minimum_size_ = other.minimum_size_; 54 return *this; 55 } 56 57 void CryptoHandshakeMessage::Clear() { 58 tag_ = 0; 59 tag_value_map_.clear(); 60 minimum_size_ = 0; 61 serialized_.reset(); 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::MarkDirty() { 72 serialized_.reset(); 73 } 74 75 void CryptoHandshakeMessage::SetTaglist(QuicTag tag, ...) { 76 // Warning, if sizeof(QuicTag) > sizeof(int) then this function will break 77 // because the terminating 0 will only be promoted to int. 78 COMPILE_ASSERT(sizeof(QuicTag) <= sizeof(int), 79 crypto_tag_may_not_be_larger_than_int_or_varargs_will_break); 80 81 vector<QuicTag> tags; 82 va_list ap; 83 84 va_start(ap, tag); 85 for (;;) { 86 QuicTag list_item = va_arg(ap, QuicTag); 87 if (list_item == 0) { 88 break; 89 } 90 tags.push_back(list_item); 91 } 92 93 // Because of the way that we keep tags in memory, we can copy the contents 94 // of the vector and get the correct bytes in wire format. See 95 // crypto_protocol.h. This assumes that the system is little-endian. 96 SetVector(tag, tags); 97 98 va_end(ap); 99 } 100 101 void CryptoHandshakeMessage::SetStringPiece(QuicTag tag, StringPiece value) { 102 tag_value_map_[tag] = value.as_string(); 103 } 104 105 void CryptoHandshakeMessage::Erase(QuicTag tag) { 106 tag_value_map_.erase(tag); 107 } 108 109 QuicErrorCode CryptoHandshakeMessage::GetTaglist(QuicTag tag, 110 const QuicTag** out_tags, 111 size_t* out_len) const { 112 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag); 113 QuicErrorCode ret = QUIC_NO_ERROR; 114 115 if (it == tag_value_map_.end()) { 116 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 117 } else if (it->second.size() % sizeof(QuicTag) != 0) { 118 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 119 } 120 121 if (ret != QUIC_NO_ERROR) { 122 *out_tags = NULL; 123 *out_len = 0; 124 return ret; 125 } 126 127 *out_tags = reinterpret_cast<const QuicTag*>(it->second.data()); 128 *out_len = it->second.size() / sizeof(QuicTag); 129 return ret; 130 } 131 132 bool CryptoHandshakeMessage::GetStringPiece(QuicTag tag, 133 StringPiece* out) const { 134 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag); 135 if (it == tag_value_map_.end()) { 136 return false; 137 } 138 *out = it->second; 139 return true; 140 } 141 142 QuicErrorCode CryptoHandshakeMessage::GetNthValue24(QuicTag tag, 143 unsigned index, 144 StringPiece* out) const { 145 StringPiece value; 146 if (!GetStringPiece(tag, &value)) { 147 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 148 } 149 150 for (unsigned i = 0;; i++) { 151 if (value.empty()) { 152 return QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND; 153 } 154 if (value.size() < 3) { 155 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 156 } 157 158 const unsigned char* data = 159 reinterpret_cast<const unsigned char*>(value.data()); 160 size_t size = static_cast<size_t>(data[0]) | 161 (static_cast<size_t>(data[1]) << 8) | 162 (static_cast<size_t>(data[2]) << 16); 163 value.remove_prefix(3); 164 165 if (value.size() < size) { 166 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 167 } 168 169 if (i == index) { 170 *out = StringPiece(value.data(), size); 171 return QUIC_NO_ERROR; 172 } 173 174 value.remove_prefix(size); 175 } 176 } 177 178 QuicErrorCode CryptoHandshakeMessage::GetUint16(QuicTag tag, 179 uint16* out) const { 180 return GetPOD(tag, out, sizeof(uint16)); 181 } 182 183 QuicErrorCode CryptoHandshakeMessage::GetUint32(QuicTag tag, 184 uint32* out) const { 185 return GetPOD(tag, out, sizeof(uint32)); 186 } 187 188 QuicErrorCode CryptoHandshakeMessage::GetUint64(QuicTag tag, 189 uint64* out) const { 190 return GetPOD(tag, out, sizeof(uint64)); 191 } 192 193 size_t CryptoHandshakeMessage::size() const { 194 size_t ret = sizeof(QuicTag) + 195 sizeof(uint16) /* number of entries */ + 196 sizeof(uint16) /* padding */; 197 ret += (sizeof(QuicTag) + sizeof(uint32) /* end offset */) * 198 tag_value_map_.size(); 199 for (QuicTagValueMap::const_iterator i = tag_value_map_.begin(); 200 i != tag_value_map_.end(); ++i) { 201 ret += i->second.size(); 202 } 203 204 return ret; 205 } 206 207 void CryptoHandshakeMessage::set_minimum_size(size_t min_bytes) { 208 if (min_bytes == minimum_size_) { 209 return; 210 } 211 serialized_.reset(); 212 minimum_size_ = min_bytes; 213 } 214 215 size_t CryptoHandshakeMessage::minimum_size() const { 216 return minimum_size_; 217 } 218 219 string CryptoHandshakeMessage::DebugString() const { 220 return DebugStringInternal(0); 221 } 222 223 QuicErrorCode CryptoHandshakeMessage::GetPOD( 224 QuicTag tag, void* out, size_t len) const { 225 QuicTagValueMap::const_iterator it = tag_value_map_.find(tag); 226 QuicErrorCode ret = QUIC_NO_ERROR; 227 228 if (it == tag_value_map_.end()) { 229 ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 230 } else if (it->second.size() != len) { 231 ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 232 } 233 234 if (ret != QUIC_NO_ERROR) { 235 memset(out, 0, len); 236 return ret; 237 } 238 239 memcpy(out, it->second.data(), len); 240 return ret; 241 } 242 243 string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const { 244 string ret = string(2 * indent, ' ') + QuicUtils::TagToString(tag_) + "<\n"; 245 ++indent; 246 for (QuicTagValueMap::const_iterator it = tag_value_map_.begin(); 247 it != tag_value_map_.end(); ++it) { 248 ret += string(2 * indent, ' ') + QuicUtils::TagToString(it->first) + ": "; 249 250 bool done = false; 251 switch (it->first) { 252 case kICSL: 253 case kIRTT: 254 case kKATO: 255 case kMSPC: 256 case kSWND: 257 // uint32 value 258 if (it->second.size() == 4) { 259 uint32 value; 260 memcpy(&value, it->second.data(), sizeof(value)); 261 ret += base::UintToString(value); 262 done = true; 263 } 264 break; 265 case kVERS: 266 // uint16 value 267 if (it->second.size() == 2) { 268 uint16 value; 269 memcpy(&value, it->second.data(), sizeof(value)); 270 ret += base::UintToString(value); 271 done = true; 272 } 273 break; 274 case kKEXS: 275 case kAEAD: 276 case kCGST: 277 case kPDMD: 278 case kVER: 279 // tag lists 280 if (it->second.size() % sizeof(QuicTag) == 0) { 281 for (size_t j = 0; j < it->second.size(); j += sizeof(QuicTag)) { 282 QuicTag tag; 283 memcpy(&tag, it->second.data() + j, sizeof(tag)); 284 if (j > 0) { 285 ret += ","; 286 } 287 ret += "'" + QuicUtils::TagToString(tag) + "'"; 288 } 289 done = true; 290 } 291 break; 292 case kSCFG: 293 // nested messages. 294 if (!it->second.empty()) { 295 scoped_ptr<CryptoHandshakeMessage> msg( 296 CryptoFramer::ParseMessage(it->second)); 297 if (msg.get()) { 298 ret += "\n"; 299 ret += msg->DebugStringInternal(indent + 1); 300 301 done = true; 302 } 303 } 304 break; 305 case kPAD: 306 ret += StringPrintf("(%d bytes of padding)", 307 static_cast<int>(it->second.size())); 308 done = true; 309 break; 310 } 311 312 if (!done) { 313 // If there's no specific format for this tag, or the value is invalid, 314 // then just use hex. 315 ret += "0x" + base::HexEncode(it->second.data(), it->second.size()); 316 } 317 ret += "\n"; 318 } 319 --indent; 320 ret += string(2 * indent, ' ') + ">"; 321 return ret; 322 } 323 324 QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters() 325 : key_exchange(0), 326 aead(0) { 327 } 328 329 QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {} 330 331 CrypterPair::CrypterPair() {} 332 333 CrypterPair::~CrypterPair() {} 334 335 // static 336 const char QuicCryptoConfig::kInitialLabel[] = "QUIC key expansion"; 337 338 // static 339 const char QuicCryptoConfig::kCETVLabel[] = "QUIC CETV block"; 340 341 // static 342 const char QuicCryptoConfig::kForwardSecureLabel[] = 343 "QUIC forward secure key expansion"; 344 345 QuicCryptoConfig::QuicCryptoConfig() 346 : common_cert_sets(CommonCertSets::GetInstanceQUIC()) { 347 } 348 349 QuicCryptoConfig::~QuicCryptoConfig() {} 350 351 } // namespace net 352