QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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 <vector> |
| 12 | |
| 13 | #include "net/third_party/quiche/src/quic/core/quic_packets.h" |
| 14 | #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
| 15 | #include "net/third_party/quiche/src/quic/platform/api/quic_string.h" |
| 16 | #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" |
| 17 | #include "net/third_party/quiche/src/quic/platform/api/quic_uint128.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> |
| 46 | void SetValue(QuicTag tag, const T& v) { |
| 47 | tag_value_map_[tag] = |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame^] | 48 | std::string(reinterpret_cast<const char*>(&v), sizeof(v)); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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> |
| 54 | void SetVector(QuicTag tag, const std::vector<T>& v) { |
| 55 | if (v.empty()) { |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame^] | 56 | tag_value_map_[tag] = std::string(); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 57 | } else { |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame^] | 58 | tag_value_map_[tag] = std::string(reinterpret_cast<const char*>(&v[0]), |
| 59 | v.size() * sizeof(T)); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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. |
| 72 | QuicTag tag() const { return tag_; } |
| 73 | // Sets the message tag. |
| 74 | void set_tag(QuicTag tag) { tag_ = tag; } |
| 75 | |
| 76 | const QuicTagValueMap& tag_value_map() const { return tag_value_map_; } |
| 77 | |
| 78 | void SetStringPiece(QuicTag tag, QuicStringPiece 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, QuicStringPiece* 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 | QuicStringPiece* 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. |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame^] | 129 | std::string DebugString() const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame^] | 141 | std::string DebugStringInternal(size_t indent) const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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_ |