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