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 #ifndef NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_ 6 #define NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/memory/scoped_ptr.h" 13 #include "base/strings/string_piece.h" 14 #include "net/base/net_export.h" 15 #include "net/cert/cert_verify_result.h" 16 #include "net/cert/x509_certificate.h" 17 #include "net/quic/crypto/crypto_protocol.h" 18 #include "net/quic/crypto/proof_verifier.h" 19 #include "net/quic/quic_protocol.h" 20 21 namespace net { 22 23 class ChannelIDSigner; 24 class CommonCertSets; 25 class KeyExchange; 26 class ProofVerifier; 27 class QuicDecrypter; 28 class QuicEncrypter; 29 class QuicRandom; 30 31 // An intermediate format of a handshake message that's convenient for a 32 // CryptoFramer to serialize from or parse into. 33 class NET_EXPORT_PRIVATE CryptoHandshakeMessage { 34 public: 35 CryptoHandshakeMessage(); 36 CryptoHandshakeMessage(const CryptoHandshakeMessage& other); 37 ~CryptoHandshakeMessage(); 38 39 CryptoHandshakeMessage& operator=(const CryptoHandshakeMessage& other); 40 41 // Clears state. 42 void Clear(); 43 44 // GetSerialized returns the serialized form of this message and caches the 45 // result. Subsequently altering the message does not invalidate the cache. 46 const QuicData& GetSerialized() const; 47 48 // MarkDirty invalidates the cache created by |GetSerialized|. 49 void MarkDirty(); 50 51 // SetValue sets an element with the given tag to the raw, memory contents of 52 // |v|. 53 template<class T> void SetValue(QuicTag tag, const T& v) { 54 tag_value_map_[tag] = 55 std::string(reinterpret_cast<const char*>(&v), sizeof(v)); 56 } 57 58 // SetVector sets an element with the given tag to the raw contents of an 59 // array of elements in |v|. 60 template<class T> void SetVector(QuicTag tag, const std::vector<T>& v) { 61 if (v.empty()) { 62 tag_value_map_[tag] = std::string(); 63 } else { 64 tag_value_map_[tag] = std::string(reinterpret_cast<const char*>(&v[0]), 65 v.size() * sizeof(T)); 66 } 67 } 68 69 // Returns the message tag. 70 QuicTag tag() const { return tag_; } 71 // Sets the message tag. 72 void set_tag(QuicTag tag) { tag_ = tag; } 73 74 const QuicTagValueMap& tag_value_map() const { return tag_value_map_; } 75 76 void Insert(QuicTagValueMap::const_iterator begin, 77 QuicTagValueMap::const_iterator end); 78 79 // SetTaglist sets an element with the given tag to contain a list of tags, 80 // passed as varargs. The argument list must be terminated with a 0 element. 81 void SetTaglist(QuicTag tag, ...); 82 83 void SetStringPiece(QuicTag tag, base::StringPiece value); 84 85 // Erase removes a tag/value, if present, from the message. 86 void Erase(QuicTag tag); 87 88 // GetTaglist finds an element with the given tag containing zero or more 89 // tags. If such a tag doesn't exist, it returns false. Otherwise it sets 90 // |out_tags| and |out_len| to point to the array of tags and returns true. 91 // The array points into the CryptoHandshakeMessage and is valid only for as 92 // long as the CryptoHandshakeMessage exists and is not modified. 93 QuicErrorCode GetTaglist(QuicTag tag, const QuicTag** out_tags, 94 size_t* out_len) const; 95 96 bool GetStringPiece(QuicTag tag, base::StringPiece* out) const; 97 98 // GetNthValue24 interprets the value with the given tag to be a series of 99 // 24-bit, length prefixed values and it returns the subvalue with the given 100 // index. 101 QuicErrorCode GetNthValue24(QuicTag tag, 102 unsigned index, 103 base::StringPiece* out) const; 104 QuicErrorCode GetUint16(QuicTag tag, uint16* out) const; 105 QuicErrorCode GetUint32(QuicTag tag, uint32* out) const; 106 QuicErrorCode GetUint64(QuicTag tag, uint64* out) const; 107 108 // size returns 4 (message tag) + 2 (uint16, number of entries) + 109 // (4 (tag) + 4 (end offset))*tag_value_map_.size() + value sizes. 110 size_t size() const; 111 112 // set_minimum_size sets the minimum number of bytes that the message should 113 // consume. The CryptoFramer will add a PAD tag as needed when serializing in 114 // order to ensure this. Setting a value of 0 disables padding. 115 // 116 // Padding is useful in order to ensure that messages are a minimum size. A 117 // QUIC server can require a minimum size in order to reduce the 118 // amplification factor of any mirror DoS attack. 119 void set_minimum_size(size_t min_bytes); 120 121 size_t minimum_size() const; 122 123 // DebugString returns a multi-line, string representation of the message 124 // suitable for including in debug output. 125 std::string DebugString() const; 126 127 private: 128 // GetPOD is a utility function for extracting a plain-old-data value. If 129 // |tag| exists in the message, and has a value of exactly |len| bytes then 130 // it copies |len| bytes of data into |out|. Otherwise |len| bytes at |out| 131 // are zeroed out. 132 // 133 // If used to copy integers then this assumes that the machine is 134 // little-endian. 135 QuicErrorCode GetPOD(QuicTag tag, void* out, size_t len) const; 136 137 std::string DebugStringInternal(size_t indent) const; 138 139 QuicTag tag_; 140 QuicTagValueMap tag_value_map_; 141 142 size_t minimum_size_; 143 144 // The serialized form of the handshake message. This member is constructed 145 // lasily. 146 mutable scoped_ptr<QuicData> serialized_; 147 }; 148 149 // A CrypterPair contains the encrypter and decrypter for an encryption level. 150 struct NET_EXPORT_PRIVATE CrypterPair { 151 CrypterPair(); 152 ~CrypterPair(); 153 scoped_ptr<QuicEncrypter> encrypter; 154 scoped_ptr<QuicDecrypter> decrypter; 155 }; 156 157 // Parameters negotiated by the crypto handshake. 158 struct NET_EXPORT_PRIVATE QuicCryptoNegotiatedParameters { 159 // Initializes the members to 0 or empty values. 160 QuicCryptoNegotiatedParameters(); 161 ~QuicCryptoNegotiatedParameters(); 162 163 uint16 version; 164 QuicTag key_exchange; 165 QuicTag aead; 166 std::string initial_premaster_secret; 167 std::string forward_secure_premaster_secret; 168 CrypterPair initial_crypters; 169 CrypterPair forward_secure_crypters; 170 // Normalized SNI: converted to lower case and trailing '.' removed. 171 std::string sni; 172 std::string client_nonce; 173 std::string server_nonce; 174 // hkdf_input_suffix contains the HKDF input following the label: the GUID, 175 // client hello and server config. This is only populated in the client 176 // because only the client needs to derive the forward secure keys at a later 177 // time from the initial keys. 178 std::string hkdf_input_suffix; 179 // cached_certs contains the cached certificates that a client used when 180 // sending a client hello. 181 std::vector<std::string> cached_certs; 182 // client_key_exchange is used by clients to store the ephemeral KeyExchange 183 // for the connection. 184 scoped_ptr<KeyExchange> client_key_exchange; 185 // channel_id is set by servers to a ChannelID key when the client correctly 186 // proves possession of the corresponding private key. It consists of 32 187 // bytes of x coordinate, followed by 32 bytes of y coordinate. Both values 188 // are big-endian and the pair is a P-256 public key. 189 std::string channel_id; 190 }; 191 192 // QuicCryptoConfig contains common configuration between clients and servers. 193 class NET_EXPORT_PRIVATE QuicCryptoConfig { 194 public: 195 enum { 196 // CONFIG_VERSION is the one (and, for the moment, only) version number that 197 // we implement. 198 CONFIG_VERSION = 0, 199 }; 200 201 // kInitialLabel is a constant that is used when deriving the initial 202 // (non-forward secure) keys for the connection in order to tie the resulting 203 // key to this protocol. 204 static const char kInitialLabel[]; 205 206 // kCETVLabel is a constant that is used when deriving the keys for the 207 // encrypted tag/value block in the client hello. 208 static const char kCETVLabel[]; 209 210 // kForwardSecureLabel is a constant that is used when deriving the forward 211 // secure keys for the connection in order to tie the resulting key to this 212 // protocol. 213 static const char kForwardSecureLabel[]; 214 215 QuicCryptoConfig(); 216 ~QuicCryptoConfig(); 217 218 // Protocol version 219 uint16 version; 220 // Key exchange methods. The following two members' values correspond by 221 // index. 222 QuicTagVector kexs; 223 // Authenticated encryption with associated data (AEAD) algorithms. 224 QuicTagVector aead; 225 226 const CommonCertSets* common_cert_sets; 227 228 private: 229 DISALLOW_COPY_AND_ASSIGN(QuicCryptoConfig); 230 }; 231 232 // QuicCryptoClientConfig contains crypto-related configuration settings for a 233 // client. Note that this object isn't thread-safe. It's designed to be used on 234 // a single thread at a time. 235 class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig { 236 public: 237 // A CachedState contains the information that the client needs in order to 238 // perform a 0-RTT handshake with a server. This information can be reused 239 // over several connections to the same server. 240 class CachedState { 241 public: 242 CachedState(); 243 ~CachedState(); 244 245 // IsComplete returns true if this object contains enough information to 246 // perform a handshake with the server. |now| is used to judge whether any 247 // cached server config has expired. 248 bool IsComplete(QuicWallTime now) const; 249 250 // GetServerConfig returns the parsed contents of |server_config|, or NULL 251 // if |server_config| is empty. The return value is owned by this object 252 // and is destroyed when this object is. 253 const CryptoHandshakeMessage* GetServerConfig() const; 254 255 // SetServerConfig checks that |server_config| parses correctly and stores 256 // it in |server_config_|. |now| is used to judge whether |server_config| 257 // has expired. 258 QuicErrorCode SetServerConfig(base::StringPiece server_config, 259 QuicWallTime now, 260 std::string* error_details); 261 262 // InvalidateServerConfig clears the cached server config (if any). 263 void InvalidateServerConfig(); 264 265 // SetProof stores a certificate chain and signature. 266 void SetProof(const std::vector<std::string>& certs, 267 base::StringPiece signature); 268 269 // SetProofValid records that the certificate chain and signature have been 270 // validated and that it's safe to assume that the server is legitimate. 271 // (Note: this does not check the chain or signature.) 272 void SetProofValid(); 273 274 // If the server config or the proof has changed then it needs to be 275 // revalidated. Helper function to keep server_config_valid_ and 276 // generation_counter_ in sync. 277 void SetProofInvalid(); 278 279 const std::string& server_config() const; 280 const std::string& source_address_token() const; 281 const std::vector<std::string>& certs() const; 282 const std::string& signature() const; 283 bool proof_valid() const; 284 uint64 generation_counter() const; 285 const ProofVerifyDetails* proof_verify_details() const; 286 287 void set_source_address_token(base::StringPiece token); 288 289 // SetProofVerifyDetails takes ownership of |details|. 290 void SetProofVerifyDetails(ProofVerifyDetails* details); 291 292 private: 293 std::string server_config_id_; // An opaque id from the server. 294 std::string server_config_; // A serialized handshake message. 295 std::string source_address_token_; // An opaque proof of IP ownership. 296 std::vector<std::string> certs_; // A list of certificates in leaf-first 297 // order. 298 std::string server_config_sig_; // A signature of |server_config_|. 299 bool server_config_valid_; // True if |server_config_| is correctly 300 // signed and |certs_| has been 301 // validated. 302 // Generation counter associated with the |server_config_|, |certs_| and 303 // |server_config_sig_| combination. It is incremented whenever we set 304 // server_config_valid_ to false. 305 uint64 generation_counter_; 306 307 scoped_ptr<ProofVerifyDetails> proof_verify_details_; 308 309 // scfg contains the cached, parsed value of |server_config|. 310 mutable scoped_ptr<CryptoHandshakeMessage> scfg_; 311 }; 312 313 QuicCryptoClientConfig(); 314 ~QuicCryptoClientConfig(); 315 316 // Sets the members to reasonable, default values. 317 void SetDefaults(); 318 319 // LookupOrCreate returns a CachedState for the given hostname. If no such 320 // CachedState currently exists, it will be created and cached. 321 CachedState* LookupOrCreate(const std::string& server_hostname); 322 323 // FillInchoateClientHello sets |out| to be a CHLO message that elicits a 324 // source-address token or SCFG from a server. If |cached| is non-NULL, the 325 // source-address token will be taken from it. |out_params| is used in order 326 // to store the cached certs that were sent as hints to the server in 327 // |out_params->cached_certs|. 328 void FillInchoateClientHello(const std::string& server_hostname, 329 const CachedState* cached, 330 QuicCryptoNegotiatedParameters* out_params, 331 CryptoHandshakeMessage* out) const; 332 333 // FillClientHello sets |out| to be a CHLO message based on the configuration 334 // of this object. This object must have cached enough information about 335 // |server_hostname| in order to perform a handshake. This can be checked 336 // with the |IsComplete| member of |CachedState|. 337 // 338 // |clock| and |rand| are used to generate the nonce and |out_params| is 339 // filled with the results of the handshake that the server is expected to 340 // accept. 341 QuicErrorCode FillClientHello(const std::string& server_hostname, 342 QuicGuid guid, 343 const CachedState* cached, 344 QuicWallTime now, 345 QuicRandom* rand, 346 QuicCryptoNegotiatedParameters* out_params, 347 CryptoHandshakeMessage* out, 348 std::string* error_details) const; 349 350 // ProcessRejection processes a REJ message from a server and updates the 351 // cached information about that server. After this, |IsComplete| may return 352 // true for that server's CachedState. If the rejection message contains 353 // state about a future handshake (i.e. an nonce value from the server), then 354 // it will be saved in |out_params|. |now| is used to judge whether the 355 // server config in the rejection message has expired. 356 QuicErrorCode ProcessRejection(CachedState* cached, 357 const CryptoHandshakeMessage& rej, 358 QuicWallTime now, 359 QuicCryptoNegotiatedParameters* out_params, 360 std::string* error_details); 361 362 // ProcessServerHello processes the message in |server_hello|, writes the 363 // negotiated parameters to |out_params| and returns QUIC_NO_ERROR. If 364 // |server_hello| is unacceptable then it puts an error message in 365 // |error_details| and returns an error code. 366 QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello, 367 QuicGuid guid, 368 QuicCryptoNegotiatedParameters* out_params, 369 std::string* error_details); 370 371 ProofVerifier* proof_verifier() const; 372 373 // SetProofVerifier takes ownership of a |ProofVerifier| that clients are 374 // free to use in order to verify certificate chains from servers. If a 375 // ProofVerifier is set then the client will request a certificate chain from 376 // the server. 377 void SetProofVerifier(ProofVerifier* verifier); 378 379 ChannelIDSigner* channel_id_signer() const; 380 381 // SetChannelIDSigner sets a ChannelIDSigner that will be called when the 382 // server supports channel IDs to sign a message proving possession of the 383 // given ChannelID. This object takes ownership of |signer|. 384 void SetChannelIDSigner(ChannelIDSigner* signer); 385 386 private: 387 // cached_states_ maps from the server hostname to the cached information 388 // about that server. 389 std::map<std::string, CachedState*> cached_states_; 390 391 scoped_ptr<ProofVerifier> proof_verifier_; 392 scoped_ptr<ChannelIDSigner> channel_id_signer_; 393 394 DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientConfig); 395 }; 396 397 } // namespace net 398 399 #endif // NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_ 400