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