1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef QUICHE_QUIC_CORE_CRYPTO_CRYPTO_HANDSHAKE_MESSAGE_H_
6 #define QUICHE_QUIC_CORE_CRYPTO_CRYPTO_HANDSHAKE_MESSAGE_H_
7 
8 #include <cstddef>
9 #include <cstdint>
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 #include "net/third_party/quiche/src/quic/core/quic_packets.h"
15 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
16 #include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
17 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
18 
19 namespace quic {
20 
21 // An intermediate format of a handshake message that's convenient for a
22 // CryptoFramer to serialize from or parse into.
23 class QUIC_EXPORT_PRIVATE CryptoHandshakeMessage {
24  public:
25   CryptoHandshakeMessage();
26   CryptoHandshakeMessage(const CryptoHandshakeMessage& other);
27   CryptoHandshakeMessage(CryptoHandshakeMessage&& other);
28   ~CryptoHandshakeMessage();
29 
30   CryptoHandshakeMessage& operator=(const CryptoHandshakeMessage& other);
31   CryptoHandshakeMessage& operator=(CryptoHandshakeMessage&& other);
32 
33   // Clears state.
34   void Clear();
35 
36   // GetSerialized returns the serialized form of this message and caches the
37   // result. Subsequently altering the message does not invalidate the cache.
38   const QuicData& GetSerialized() const;
39 
40   // MarkDirty invalidates the cache created by |GetSerialized|.
41   void MarkDirty();
42 
43   // SetValue sets an element with the given tag to the raw, memory contents of
44   // |v|.
45   template <class T>
SetValue(QuicTag tag,const T & v)46   void SetValue(QuicTag tag, const T& v) {
47     tag_value_map_[tag] =
48         std::string(reinterpret_cast<const char*>(&v), sizeof(v));
49   }
50 
51   // SetVector sets an element with the given tag to the raw contents of an
52   // array of elements in |v|.
53   template <class T>
SetVector(QuicTag tag,const std::vector<T> & v)54   void SetVector(QuicTag tag, const std::vector<T>& v) {
55     if (v.empty()) {
56       tag_value_map_[tag] = std::string();
57     } else {
58       tag_value_map_[tag] = std::string(reinterpret_cast<const char*>(&v[0]),
59                                         v.size() * sizeof(T));
60     }
61   }
62 
63   // Sets an element with the given tag to the on-the-wire representation of
64   // |version|.
65   void SetVersion(QuicTag tag, ParsedQuicVersion version);
66 
67   // Sets an element with the given tag to the on-the-wire representation of
68   // the elements in |versions|.
69   void SetVersionVector(QuicTag tag, ParsedQuicVersionVector versions);
70 
71   // Returns the message tag.
tag()72   QuicTag tag() const { return tag_; }
73   // Sets the message tag.
set_tag(QuicTag tag)74   void set_tag(QuicTag tag) { tag_ = tag; }
75 
tag_value_map()76   const QuicTagValueMap& tag_value_map() const { return tag_value_map_; }
77 
78   void SetStringPiece(QuicTag tag, quiche::QuicheStringPiece value);
79 
80   // Erase removes a tag/value, if present, from the message.
81   void Erase(QuicTag tag);
82 
83   // GetTaglist finds an element with the given tag containing zero or more
84   // tags. If such a tag doesn't exist, it returns an error code. Otherwise it
85   // populates |out_tags| with the tags and returns QUIC_NO_ERROR.
86   QuicErrorCode GetTaglist(QuicTag tag, QuicTagVector* out_tags) const;
87 
88   // GetVersionLabelList finds an element with the given tag containing zero or
89   // more version labels. If such a tag doesn't exist, it returns an error code.
90   // Otherwise it populates |out| with the labels and returns QUIC_NO_ERROR.
91   QuicErrorCode GetVersionLabelList(QuicTag tag,
92                                     QuicVersionLabelVector* out) const;
93 
94   // GetVersionLabel finds an element with the given tag containing a single
95   // version label. If such a tag doesn't exist, it returns an error code.
96   // Otherwise it populates |out| with the label and returns QUIC_NO_ERROR.
97   QuicErrorCode GetVersionLabel(QuicTag tag, QuicVersionLabel* out) const;
98 
99   bool GetStringPiece(QuicTag tag, quiche::QuicheStringPiece* out) const;
100   bool HasStringPiece(QuicTag tag) const;
101 
102   // GetNthValue24 interprets the value with the given tag to be a series of
103   // 24-bit, length prefixed values and it returns the subvalue with the given
104   // index.
105   QuicErrorCode GetNthValue24(QuicTag tag,
106                               unsigned index,
107                               quiche::QuicheStringPiece* out) const;
108   QuicErrorCode GetUint32(QuicTag tag, uint32_t* out) const;
109   QuicErrorCode GetUint64(QuicTag tag, uint64_t* out) const;
110   QuicErrorCode GetUint128(QuicTag tag, QuicUint128* out) const;
111 
112   // size returns 4 (message tag) + 2 (uint16_t, number of entries) +
113   // (4 (tag) + 4 (end offset))*tag_value_map_.size() + ∑ value sizes.
114   size_t size() const;
115 
116   // set_minimum_size sets the minimum number of bytes that the message should
117   // consume. The CryptoFramer will add a PAD tag as needed when serializing in
118   // order to ensure this. Setting a value of 0 disables padding.
119   //
120   // Padding is useful in order to ensure that messages are a minimum size. A
121   // QUIC server can require a minimum size in order to reduce the
122   // amplification factor of any mirror DoS attack.
123   void set_minimum_size(size_t min_bytes);
124 
125   size_t minimum_size() const;
126 
127   // DebugString returns a multi-line, string representation of the message
128   // suitable for including in debug output.
129   std::string DebugString() const;
130 
131  private:
132   // GetPOD is a utility function for extracting a plain-old-data value. If
133   // |tag| exists in the message, and has a value of exactly |len| bytes then
134   // it copies |len| bytes of data into |out|. Otherwise |len| bytes at |out|
135   // are zeroed out.
136   //
137   // If used to copy integers then this assumes that the machine is
138   // little-endian.
139   QuicErrorCode GetPOD(QuicTag tag, void* out, size_t len) const;
140 
141   std::string DebugStringInternal(size_t indent) const;
142 
143   QuicTag tag_;
144   QuicTagValueMap tag_value_map_;
145 
146   size_t minimum_size_;
147 
148   // The serialized form of the handshake message. This member is constructed
149   // lazily.
150   mutable std::unique_ptr<QuicData> serialized_;
151 };
152 
153 }  // namespace quic
154 
155 #endif  // QUICHE_QUIC_CORE_CRYPTO_CRYPTO_HANDSHAKE_MESSAGE_H_
156