12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/crypto_handshake.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <ctype.h> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h" 115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_split.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "crypto/secure_hash.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_util.h" 16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/quic/crypto/cert_compressor.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/quic/crypto/channel_id.h" 18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/quic/crypto/common_cert_set.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/crypto_framer.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/crypto_utils.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/curve25519_key_exchange.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/key_exchange.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/crypto/p256_key_exchange.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/crypto/proof_verifier.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/quic_decrypter.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/quic_encrypter.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/quic_random.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_protocol.h" 29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/quic/quic_utils.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_WIN) 32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/win/windows_version.h" 33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif 34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::StringPiece; 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using base::StringPrintf; 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using std::map; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::string; 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::vector; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)CryptoHandshakeMessage::CryptoHandshakeMessage() 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : tag_(0), 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) minimum_size_(0) {} 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CryptoHandshakeMessage::CryptoHandshakeMessage( 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CryptoHandshakeMessage& other) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : tag_(other.tag_), 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) tag_value_map_(other.tag_value_map_), 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) minimum_size_(other.minimum_size_) { 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Don't copy serialized_. scoped_ptr doesn't have a copy constructor. 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The new object can lazily reconstruct serialized_. 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CryptoHandshakeMessage::~CryptoHandshakeMessage() {} 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CryptoHandshakeMessage& CryptoHandshakeMessage::operator=( 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CryptoHandshakeMessage& other) { 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tag_ = other.tag_; 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tag_value_map_ = other.tag_value_map_; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Don't copy serialized_. scoped_ptr doesn't have an assignment operator. 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // However, invalidate serialized_. 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) serialized_.reset(); 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) minimum_size_ = other.minimum_size_; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *this; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CryptoHandshakeMessage::Clear() { 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tag_ = 0; 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tag_value_map_.clear(); 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) minimum_size_ = 0; 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) serialized_.reset(); 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const QuicData& CryptoHandshakeMessage::GetSerialized() const { 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!serialized_.get()) { 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) serialized_.reset(CryptoFramer::ConstructHandshakeMessage(*this)); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return *serialized_.get(); 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CryptoHandshakeMessage::MarkDirty() { 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) serialized_.reset(); 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void CryptoHandshakeMessage::Insert(QuicTagValueMap::const_iterator begin, 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicTagValueMap::const_iterator end) { 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tag_value_map_.insert(begin, end); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 92b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void CryptoHandshakeMessage::SetTaglist(QuicTag tag, ...) { 93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Warning, if sizeof(QuicTag) > sizeof(int) then this function will break 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // because the terminating 0 will only be promoted to int. 95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) COMPILE_ASSERT(sizeof(QuicTag) <= sizeof(int), 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) crypto_tag_may_not_be_larger_than_int_or_varargs_will_break); 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 98b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vector<QuicTag> tags; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) va_list ap; 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) va_start(ap, tag); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (;;) { 103b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicTag list_item = va_arg(ap, QuicTag); 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (list_item == 0) { 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tags.push_back(list_item); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Because of the way that we keep tags in memory, we can copy the contents 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // of the vector and get the correct bytes in wire format. See 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // crypto_protocol.h. This assumes that the system is little-endian. 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetVector(tag, tags); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) va_end(ap); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 118b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void CryptoHandshakeMessage::SetStringPiece(QuicTag tag, StringPiece value) { 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) tag_value_map_[tag] = value.as_string(); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CryptoHandshakeMessage::Erase(QuicTag tag) { 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) tag_value_map_.erase(tag); 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 126b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)QuicErrorCode CryptoHandshakeMessage::GetTaglist(QuicTag tag, 127b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const QuicTag** out_tags, 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t* out_len) const { 129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicTagValueMap::const_iterator it = tag_value_map_.find(tag); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicErrorCode ret = QUIC_NO_ERROR; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (it == tag_value_map_.end()) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else if (it->second.size() % sizeof(QuicTag) != 0) { 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ret != QUIC_NO_ERROR) { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *out_tags = NULL; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *out_len = 0; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *out_tags = reinterpret_cast<const QuicTag*>(it->second.data()); 145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *out_len = it->second.size() / sizeof(QuicTag); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool CryptoHandshakeMessage::GetStringPiece(QuicTag tag, 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StringPiece* out) const { 151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicTagValueMap::const_iterator it = tag_value_map_.find(tag); 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (it == tag_value_map_.end()) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *out = it->second; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 159b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)QuicErrorCode CryptoHandshakeMessage::GetNthValue24(QuicTag tag, 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unsigned index, 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece* out) const { 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StringPiece value; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!GetStringPiece(tag, &value)) { 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (unsigned i = 0;; i++) { 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (value.empty()) { 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND; 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 171b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (value.size() < 3) { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned char* data = 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<const unsigned char*>(value.data()); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t size = static_cast<size_t>(data[0]) | 178b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) (static_cast<size_t>(data[1]) << 8) | 179b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) (static_cast<size_t>(data[2]) << 16); 180b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) value.remove_prefix(3); 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (value.size() < size) { 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i == index) { 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *out = StringPiece(value.data(), size); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return QUIC_NO_ERROR; 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) value.remove_prefix(size); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 195b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)QuicErrorCode CryptoHandshakeMessage::GetUint16(QuicTag tag, 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16* out) const { 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetPOD(tag, out, sizeof(uint16)); 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 200b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)QuicErrorCode CryptoHandshakeMessage::GetUint32(QuicTag tag, 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32* out) const { 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetPOD(tag, out, sizeof(uint32)); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)QuicErrorCode CryptoHandshakeMessage::GetUint64(QuicTag tag, 206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) uint64* out) const { 207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return GetPOD(tag, out, sizeof(uint64)); 208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 209b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t CryptoHandshakeMessage::size() const { 21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t ret = sizeof(QuicTag) + 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sizeof(uint16) /* number of entries */ + 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) sizeof(uint16) /* padding */; 21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret += (sizeof(QuicTag) + sizeof(uint32) /* end offset */) * 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) tag_value_map_.size(); 21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for (QuicTagValueMap::const_iterator i = tag_value_map_.begin(); 21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) i != tag_value_map_.end(); ++i) { 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret += i->second.size(); 21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return ret; 22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CryptoHandshakeMessage::set_minimum_size(size_t min_bytes) { 225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (min_bytes == minimum_size_) { 226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) serialized_.reset(); 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) minimum_size_ = min_bytes; 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t CryptoHandshakeMessage::minimum_size() const { 23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return minimum_size_; 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)string CryptoHandshakeMessage::DebugString() const { 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return DebugStringInternal(0); 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicErrorCode CryptoHandshakeMessage::GetPOD( 241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicTag tag, void* out, size_t len) const { 242b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicTagValueMap::const_iterator it = tag_value_map_.find(tag); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicErrorCode ret = QUIC_NO_ERROR; 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (it == tag_value_map_.end()) { 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (it->second.size() != len) { 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ret != QUIC_NO_ERROR) { 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memset(out, 0, len); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(out, it->second.data(), len); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const { 26190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) string ret = string(2 * indent, ' ') + QuicUtils::TagToString(tag_) + "<\n"; 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ++indent; 263b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (QuicTagValueMap::const_iterator it = tag_value_map_.begin(); 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it != tag_value_map_.end(); ++it) { 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret += string(2 * indent, ' ') + QuicUtils::TagToString(it->first) + ": "; 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool done = false; 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (it->first) { 269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case kKATO: 270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case kVERS: 271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // uint32 value 272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (it->second.size() == 4) { 273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) uint32 value; 274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) memcpy(&value, it->second.data(), sizeof(value)); 275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ret += base::UintToString(value); 276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) done = true; 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case kKEXS: 280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case kAEAD: 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case kCGST: 282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case kPDMD: 283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // tag lists 284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (it->second.size() % sizeof(QuicTag) == 0) { 285b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (size_t j = 0; j < it->second.size(); j += sizeof(QuicTag)) { 286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicTag tag; 287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) memcpy(&tag, it->second.data() + j, sizeof(tag)); 288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (j > 0) { 289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ret += ","; 290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret += QuicUtils::TagToString(tag); 292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) done = true; 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case kSCFG: 297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // nested messages. 298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!it->second.empty()) { 299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) scoped_ptr<CryptoHandshakeMessage> msg( 300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CryptoFramer::ParseMessage(it->second)); 301b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (msg.get()) { 302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ret += "\n"; 303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ret += msg->DebugStringInternal(indent + 1); 304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) done = true; 306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case kPAD: 31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ret += StringPrintf("(%d bytes of padding)", 31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static_cast<int>(it->second.size())); 31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) done = true; 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) break; 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!done) { 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If there's no specific format for this tag, or the value is invalid, 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // then just use hex. 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ret += base::HexEncode(it->second.data(), it->second.size()); 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ret += "\n"; 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) --indent; 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ret += string(2 * indent, ' ') + ">"; 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ret; 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicCryptoNegotiatedParameters::QuicCryptoNegotiatedParameters() 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : version(0), 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) key_exchange(0), 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aead(0) { 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 334b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)QuicCryptoNegotiatedParameters::~QuicCryptoNegotiatedParameters() {} 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)CrypterPair::CrypterPair() {} 337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 338b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)CrypterPair::~CrypterPair() {} 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 341b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char QuicCryptoConfig::kInitialLabel[] = "QUIC key expansion"; 342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char QuicCryptoConfig::kCETVLabel[] = "QUIC CETV block"; 345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 347b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char QuicCryptoConfig::kForwardSecureLabel[] = 348b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) "QUIC forward secure key expansion"; 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicCryptoConfig::QuicCryptoConfig() 351b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) : version(0), 352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) common_cert_sets(CommonCertSets::GetInstanceQUIC()) { 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicCryptoConfig::~QuicCryptoConfig() {} 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicCryptoClientConfig::QuicCryptoClientConfig() {} 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicCryptoClientConfig::~QuicCryptoClientConfig() { 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) STLDeleteValues(&cached_states_); 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicCryptoClientConfig::CachedState::CachedState() 364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : server_config_valid_(false), 365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch generation_counter_(0) {} 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicCryptoClientConfig::CachedState::~CachedState() {} 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const { 370868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (server_config_.empty() || !server_config_valid_) { 371868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const CryptoHandshakeMessage* scfg = GetServerConfig(); 375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!scfg) { 376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Should be impossible short of cache corruption. 377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(false); 378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) uint64 expiry_seconds; 382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR || 383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) now.ToUNIXSeconds() >= expiry_seconds) { 384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 386868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 387868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const CryptoHandshakeMessage* 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicCryptoClientConfig::CachedState::GetServerConfig() const { 392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (server_config_.empty()) { 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return NULL; 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!scfg_.get()) { 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scfg_.reset(CryptoFramer::ParseMessage(server_config_)); 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(scfg_.get()); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return scfg_.get(); 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig( 404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) StringPiece server_config, QuicWallTime now, string* error_details) { 405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const bool matches_existing = server_config == server_config_; 406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Even if the new server config matches the existing one, we still wish to 408868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // reject it if it has expired. 409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<CryptoHandshakeMessage> new_scfg_storage; 410868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const CryptoHandshakeMessage* new_scfg; 411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!matches_existing) { 413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new_scfg_storage.reset(CryptoFramer::ParseMessage(server_config)); 414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new_scfg = new_scfg_storage.get(); 415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new_scfg = GetServerConfig(); 41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 41890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!new_scfg) { 420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *error_details = "SCFG invalid"; 421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 423868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 424868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) uint64 expiry_seconds; 425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (new_scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) { 426868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *error_details = "SCFG missing EXPY"; 427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (now.ToUNIXSeconds() >= expiry_seconds) { 431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *error_details = "SCFG has expired"; 432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED; 433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 434868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 435868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!matches_existing) { 436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) server_config_ = server_config.as_string(); 4377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SetProofInvalid(); 438868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scfg_.reset(new_scfg_storage.release()); 439868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 440868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return QUIC_NO_ERROR; 441868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 442868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 443868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() { 444868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) server_config_.clear(); 445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scfg_.reset(); 4467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SetProofInvalid(); 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs, 450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) StringPiece signature) { 451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool has_changed = 452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) signature != server_config_sig_ || certs_.size() != certs.size(); 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!has_changed) { 455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < certs_.size(); i++) { 456b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (certs_[i] != certs[i]) { 457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) has_changed = true; 458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break; 459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!has_changed) { 464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If the proof has changed then it needs to be revalidated. 4687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SetProofInvalid(); 469b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) certs_ = certs; 470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) server_config_sig_ = signature.as_string(); 471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicCryptoClientConfig::CachedState::SetProofValid() { 474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) server_config_valid_ = true; 475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid QuicCryptoClientConfig::CachedState::SetProofInvalid() { 4787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch server_config_valid_ = false; 4797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ++generation_counter_; 4807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 4817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 482b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const string& QuicCryptoClientConfig::CachedState::server_config() const { 483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return server_config_; 484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const string& 487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicCryptoClientConfig::CachedState::source_address_token() const { 488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return source_address_token_; 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const vector<string>& QuicCryptoClientConfig::CachedState::certs() const { 492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return certs_; 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const string& QuicCryptoClientConfig::CachedState::signature() const { 496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return server_config_sig_; 497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicCryptoClientConfig::CachedState::proof_valid() const { 500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return server_config_valid_; 501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 503eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochuint64 QuicCryptoClientConfig::CachedState::generation_counter() const { 504eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return generation_counter_; 505eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 506eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 507d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochconst ProofVerifyDetails* 508d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochQuicCryptoClientConfig::CachedState::proof_verify_details() const { 509d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch return proof_verify_details_.get(); 5107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 5117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicCryptoClientConfig::CachedState::set_source_address_token( 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece token) { 514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) source_address_token_ = token.as_string(); 515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 517d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid QuicCryptoClientConfig::CachedState::SetProofVerifyDetails( 518d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch ProofVerifyDetails* details) { 519d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch proof_verify_details_.reset(details); 5207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 5217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicCryptoClientConfig::SetDefaults() { 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Version must be 0. 524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(agl): this version stuff is obsolete now. 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) version = QuicCryptoConfig::CONFIG_VERSION; 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Key exchange methods. 528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kexs.resize(2); 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kexs[0] = kC255; 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kexs[1] = kP256; 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Authenticated encryption algorithms. 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aead.resize(1); 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aead[0] = kAESG; 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate( 538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const string& server_hostname) { 539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) map<string, CachedState*>::const_iterator it = 540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cached_states_.find(server_hostname); 541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (it != cached_states_.end()) { 542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return it->second; 543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CachedState* cached = new CachedState; 546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cached_states_.insert(make_pair(server_hostname, cached)); 547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return cached; 548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicCryptoClientConfig::FillInchoateClientHello( 551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const string& server_hostname, 552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CachedState* cached, 553b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicCryptoNegotiatedParameters* out_params, 554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CryptoHandshakeMessage* out) const { 555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) out->set_tag(kCHLO); 55690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) out->set_minimum_size(kClientHelloMinimumSize); 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 55890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Server name indication. We only send SNI if it's a valid domain name, as 55990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // per the spec. 56090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (CryptoUtils::IsValidSNI(server_hostname)) { 561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) out->SetStringPiece(kSNI, server_hostname); 562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) out->SetValue(kVERS, version); 564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!cached->source_address_token().empty()) { 566b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token()); 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (proof_verifier_.get()) { 570a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Don't request ECDSA proofs on platforms that do not support ECDSA 571a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // certificates. 572a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool disableECDSA = false; 5737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#if defined(OS_WIN) 574a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (base::win::GetVersion() < base::win::VERSION_VISTA) 575a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) disableECDSA = true; 5767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#endif 577a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (disableECDSA) { 578a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) out->SetTaglist(kPDMD, kX59R, 0); 579a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 580a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) out->SetTaglist(kPDMD, kX509, 0); 581a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 583a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!cached->proof_valid()) { 584a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // If we are expecting a certificate chain, double the size of the client 585a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // hello so that the response from the server can be larger - hopefully 586a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // including the whole certificate chain. 587a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) out->set_minimum_size(kClientHelloMinimumSize * 2); 588a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 589558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 590558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (common_cert_sets) { 59290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes()); 593b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 594b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 595b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const vector<string>& certs = cached->certs(); 59690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the 59790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // client config is being used for multiple connections, another connection 59890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // doesn't update the cached certificates and cause us to be unable to 59990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // process the server's compressed certificate chain. 600b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->cached_certs = certs; 601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!certs.empty()) { 602b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vector<uint64> hashes; 603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hashes.reserve(certs.size()); 604b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) for (vector<string>::const_iterator i = certs.begin(); 605b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) i != certs.end(); ++i) { 606b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size())); 607b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 608b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out->SetVector(kCCRT, hashes); 609b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicErrorCode QuicCryptoClientConfig::FillClientHello( 613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const string& server_hostname, 614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) QuicGuid guid, 615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CachedState* cached, 616b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicWallTime now, 617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) QuicRandom* rand, 618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) QuicCryptoNegotiatedParameters* out_params, 619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CryptoHandshakeMessage* out, 620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) string* error_details) const { 621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(error_details != NULL); 622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 623b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) FillInchoateClientHello(server_hostname, cached, out_params, out); 624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); 626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!scfg) { 627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This should never happen as our caller should have checked 628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // cached->IsComplete() before calling this function. 629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error_details = "Handshake not ready"; 630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_CRYPTO_INTERNAL_ERROR; 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece scid; 634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!scfg->GetStringPiece(kSCID, &scid)) { 635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error_details = "SCFG missing SCID"; 636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) out->SetStringPiece(kSCID, scid); 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 640b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const QuicTag* their_aeads; 641b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const QuicTag* their_key_exchanges; 642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t num_their_aeads, num_their_key_exchanges; 643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (scfg->GetTaglist(kAEAD, &their_aeads, 644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &num_their_aeads) != QUIC_NO_ERROR || 645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scfg->GetTaglist(kKEXS, &their_key_exchanges, 646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &num_their_key_exchanges) != QUIC_NO_ERROR) { 647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error_details = "Missing AEAD or KEXS"; 6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 651c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t key_exchange_index; 652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!QuicUtils::FindMutualTag( 653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) aead, their_aeads, num_their_aeads, QuicUtils::PEER_PRIORITY, 654868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &out_params->aead, NULL) || 65590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) !QuicUtils::FindMutualTag( 656b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kexs, their_key_exchanges, num_their_key_exchanges, 65790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) QuicUtils::PEER_PRIORITY, &out_params->key_exchange, 658b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) &key_exchange_index)) { 659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error_details = "Unsupported AEAD or KEXS"; 660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_CRYPTO_NO_SUPPORT; 661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) out->SetTaglist(kAEAD, out_params->aead, 0); 663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) out->SetTaglist(kKEXS, out_params->key_exchange, 0); 664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece public_value; 666b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) != 667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) QUIC_NO_ERROR) { 668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error_details = "Missing public value"; 6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece orbit; 673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) { 674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error_details = "SCFG missing OBIT"; 675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 678b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce); 679b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out->SetStringPiece(kNONC, out_params->client_nonce); 680b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!out_params->server_nonce.empty()) { 681b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out->SetStringPiece(kServerNonceTag, out_params->server_nonce); 682b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (out_params->key_exchange) { 685b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case kC255: 686b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->client_key_exchange.reset(Curve25519KeyExchange::New( 687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Curve25519KeyExchange::NewPrivateKey(rand))); 688b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 689b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case kP256: 690868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) out_params->client_key_exchange.reset(P256KeyExchange::New( 691868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) P256KeyExchange::NewPrivateKey())); 692b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 693b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) default: 694b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(false); 695b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *error_details = "Configured to support an unknown key exchange"; 696b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return QUIC_CRYPTO_INTERNAL_ERROR; 697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 699b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!out_params->client_key_exchange->CalculateSharedKey( 700b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) public_value, &out_params->initial_premaster_secret)) { 701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error_details = "Key exchange failure"; 702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 704b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value()); 7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 706868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool do_channel_id = false; 707868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (channel_id_signer_.get()) { 708868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const QuicTag* their_proof_demands; 709868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t num_their_proof_demands; 710868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (scfg->GetTaglist(kPDMD, &their_proof_demands, 711868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &num_their_proof_demands) == QUIC_NO_ERROR) { 712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (size_t i = 0; i < num_their_proof_demands; i++) { 713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (their_proof_demands[i] == kCHID) { 714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) do_channel_id = true; 715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 717868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (do_channel_id) { 722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // In order to calculate the encryption key for the CETV block we need to 723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // serialise the client hello as it currently is (i.e. without the CETV 724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // block). For this, the client hello is serialized without padding. 725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const size_t orig_min_size = out->minimum_size(); 726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) out->set_minimum_size(0); 727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CryptoHandshakeMessage cetv; 729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cetv.set_tag(kCETV); 730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) string hkdf_input; 732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const QuicData& client_hello_serialized = out->GetSerialized(); 733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) hkdf_input.append(QuicCryptoConfig::kCETVLabel, 734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) strlen(QuicCryptoConfig::kCETVLabel) + 1); 735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid)); 736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) hkdf_input.append(client_hello_serialized.data(), 737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) client_hello_serialized.length()); 738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) hkdf_input.append(cached->server_config()); 739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 740868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) string key, signature; 741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!channel_id_signer_->Sign(server_hostname, hkdf_input, 742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &key, &signature)) { 743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *error_details = "Channel ID signature failed"; 744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return QUIC_INTERNAL_ERROR; 745868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 746868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 747868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cetv.SetStringPiece(kCIDK, key); 748868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cetv.SetStringPiece(kCIDS, signature); 749868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 750868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CrypterPair crypters; 751868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, 752868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) out_params->aead, out_params->client_nonce, 753868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) out_params->server_nonce, hkdf_input, 754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CryptoUtils::CLIENT, &crypters); 755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const QuicData& cetv_plaintext = cetv.GetSerialized(); 757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket( 758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 0 /* sequence number */, 759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) StringPiece() /* associated data */, 760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) cetv_plaintext.AsStringPiece())); 761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece()); 763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) out->MarkDirty(); 764868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 765868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) out->set_minimum_size(orig_min_size); 766868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 767868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 768b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->hkdf_input_suffix.clear(); 769b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&guid), 770b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) sizeof(guid)); 771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const QuicData& client_hello_serialized = out->GetSerialized(); 772b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->hkdf_input_suffix.append(client_hello_serialized.data(), 773b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) client_hello_serialized.length()); 774b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->hkdf_input_suffix.append(cached->server_config()); 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 776b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string hkdf_input; 777b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1; 778b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); 779b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len); 780b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hkdf_input.append(out_params->hkdf_input_suffix); 781b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 782b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CryptoUtils::DeriveKeys(out_params->initial_premaster_secret, 783b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->aead, out_params->client_nonce, 784b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->server_nonce, hkdf_input, 785b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CryptoUtils::CLIENT, &out_params->initial_crypters); 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_NO_ERROR; 788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicErrorCode QuicCryptoClientConfig::ProcessRejection( 791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CachedState* cached, 792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CryptoHandshakeMessage& rej, 793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) QuicWallTime now, 794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) QuicCryptoNegotiatedParameters* out_params, 795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) string* error_details) { 796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(error_details != NULL); 7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (rej.tag() != kREJ) { 799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *error_details = "Message is not REJ"; 800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return QUIC_CRYPTO_INTERNAL_ERROR; 801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece scfg; 804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!rej.GetStringPiece(kSCFG, &scfg)) { 805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error_details = "Missing SCFG"; 806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND; 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 809868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details); 810868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (error != QUIC_NO_ERROR) { 811868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return error; 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece token; 815b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) { 816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cached->set_source_address_token(token); 8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece nonce; 820868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (rej.GetStringPiece(kServerNonceTag, &nonce)) { 821c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) out_params->server_nonce = nonce.as_string(); 822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 824c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StringPiece proof, cert_bytes; 825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (rej.GetStringPiece(kPROF, &proof) && 826b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) rej.GetStringPiece(kCertificateTag, &cert_bytes)) { 827b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) vector<string> certs; 828b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs, 829868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) common_cert_sets, &certs)) { 830b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *error_details = "Certificate data invalid"; 831b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cached->SetProof(certs, proof); 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 837c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_NO_ERROR; 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 840c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicErrorCode QuicCryptoClientConfig::ProcessServerHello( 841c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CryptoHandshakeMessage& server_hello, 842b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) QuicGuid guid, 843c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) QuicCryptoNegotiatedParameters* out_params, 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) string* error_details) { 845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(error_details != NULL); 8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (server_hello.tag() != kSHLO) { 848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *error_details = "Bad tag"; 849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_TYPE; 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(agl): 853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // learn about updated SCFGs. 854b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 855b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) StringPiece public_value; 856b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!server_hello.GetStringPiece(kPUBS, &public_value)) { 857b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *error_details = "server hello missing forward secure public value"; 858b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 859b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 860b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 861b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!out_params->client_key_exchange->CalculateSharedKey( 862b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) public_value, &out_params->forward_secure_premaster_secret)) { 863b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) *error_details = "Key exchange failure"; 864b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER; 865b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 866b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 867b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) string hkdf_input; 868b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1; 869b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size()); 870b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len); 871b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) hkdf_input.append(out_params->hkdf_input_suffix); 872b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 873b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CryptoUtils::DeriveKeys( 874b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->forward_secure_premaster_secret, out_params->aead, 875b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) out_params->client_nonce, out_params->server_nonce, hkdf_input, 876b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CryptoUtils::CLIENT, &out_params->forward_secure_crypters); 8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return QUIC_NO_ERROR; 8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 881eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochProofVerifier* QuicCryptoClientConfig::proof_verifier() const { 882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return proof_verifier_.get(); 8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) { 886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) proof_verifier_.reset(verifier); 8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)ChannelIDSigner* QuicCryptoClientConfig::channel_id_signer() const { 8907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return channel_id_signer_.get(); 8917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 8927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 893868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void QuicCryptoClientConfig::SetChannelIDSigner(ChannelIDSigner* signer) { 894868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) channel_id_signer_.reset(signer); 895868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 896868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace net 898