Botan 3.4.0
Crypto and TLS for C&
Public Member Functions | List of all members
Botan::TLS::Extensions Class Referencefinal

#include <tls_extensions.h>

Public Member Functions

void add (Extension *extn)
 
void add (std::unique_ptr< Extension > extn)
 
const std::vector< std::unique_ptr< Extension > > & all () const
 
bool contains_implemented_extensions_other_than (const std::set< Extension_Code > &allowed_extensions) const
 
bool contains_other_than (const std::set< Extension_Code > &allowed_extensions, bool allow_unknown_extensions=false) const
 
void deserialize (TLS_Data_Reader &reader, Connection_Side from, Handshake_Type message_type)
 
bool empty () const
 
std::set< Extension_Codeextension_types () const
 
 Extensions ()=default
 
 Extensions (const Extensions &)=delete
 
 Extensions (Extensions &&)=default
 
 Extensions (TLS_Data_Reader &reader, Connection_Side side, Handshake_Type message_type)
 
template<typename T >
Tget () const
 
Extensionget (Extension_Code type) const
 
template<typename T >
bool has () const
 
bool has (Extension_Code type) const
 
Extensionsoperator= (const Extensions &)=delete
 
Extensionsoperator= (Extensions &&)=default
 
bool remove_extension (Extension_Code type)
 
std::vector< uint8_t > serialize (Connection_Side whoami) const
 
size_t size () const
 
template<typename T >
decltype(auto) take ()
 
std::unique_ptr< Extensiontake (Extension_Code type)
 

Detailed Description

Represents a block of extensions in a hello message

Definition at line 908 of file tls_extensions.h.

Constructor & Destructor Documentation

◆ Extensions() [1/4]

Botan::TLS::Extensions::Extensions ( )
default

◆ Extensions() [2/4]

Botan::TLS::Extensions::Extensions ( const Extensions & )
delete

◆ Extensions() [3/4]

Botan::TLS::Extensions::Extensions ( Extensions && )
default

◆ Extensions() [4/4]

Botan::TLS::Extensions::Extensions ( TLS_Data_Reader & reader,
Connection_Side side,
Handshake_Type message_type )
inline

Definition at line 1001 of file tls_extensions.h.

1001 {
1002 deserialize(reader, side, message_type);
1003 }
void deserialize(TLS_Data_Reader &reader, Connection_Side from, Handshake_Type message_type)

Member Function Documentation

◆ add() [1/2]

void Botan::TLS::Extensions::add ( Extension * extn)
inline

Definition at line 932 of file tls_extensions.h.

932{ add(std::unique_ptr<Extension>(extn)); }
void add(std::unique_ptr< Extension > extn)

References add().

Referenced by add().

◆ add() [2/2]

void Botan::TLS::Extensions::add ( std::unique_ptr< Extension > extn)

Definition at line 110 of file tls_extensions.cpp.

110 {
111 if(has(extn->type())) {
112 throw Invalid_Argument("cannot add the same extension twice: " +
113 std::to_string(static_cast<uint16_t>(extn->type())));
114 }
115
116 m_extensions.emplace_back(extn.release());
117}

References has().

Referenced by deserialize(), Botan::TLS::Encrypted_Extensions::Encrypted_Extensions(), Botan::TLS::Server_Hello_12::Server_Hello_12(), Botan::TLS::Server_Hello_12::Server_Hello_12(), and Botan::TLS::Server_Hello_13::Server_Hello_13().

◆ all()

const std::vector< std::unique_ptr< Extension > > & Botan::TLS::Extensions::all ( ) const
inline

Definition at line 912 of file tls_extensions.h.

912{ return m_extensions; }

◆ contains_implemented_extensions_other_than()

bool Botan::TLS::Extensions::contains_implemented_extensions_other_than ( const std::set< Extension_Code > & allowed_extensions) const
inline
Parameters
allowed_extensionsextension types that are allowed
Returns
true if this contains any extensions implemented by Botan that are not contained in allowed_extensions.

Definition at line 958 of file tls_extensions.h.

958 {
959 return contains_other_than(allowed_extensions, true);
960 }
bool contains_other_than(const std::set< Extension_Code > &allowed_extensions, bool allow_unknown_extensions=false) const

Referenced by Botan::TLS::Certificate_13::Certificate_Entry::Certificate_Entry(), Botan::TLS::Certificate_Request_13::Certificate_Request_13(), Botan::TLS::Encrypted_Extensions::Encrypted_Extensions(), and Botan::TLS::New_Session_Ticket_13::New_Session_Ticket_13().

◆ contains_other_than()

bool Botan::TLS::Extensions::contains_other_than ( const std::set< Extension_Code > & allowed_extensions,
bool allow_unknown_extensions = false ) const
Parameters
allowed_extensionsextension types that are allowed
allow_unknown_extensionsif true, ignores unrecognized extensions
Returns
true if this contains any extensions that are not contained in allowed_extensions.

Definition at line 147 of file tls_extensions.cpp.

148 {
149 const auto found = extension_types();
150
151 std::vector<Extension_Code> diff;
152 std::set_difference(
153 found.cbegin(), found.end(), allowed_extensions.cbegin(), allowed_extensions.cend(), std::back_inserter(diff));
154
155 if(allow_unknown_extensions) {
156 // Go through the found unexpected extensions whether any of those
157 // is known to this TLS implementation.
158 const auto itr = std::find_if(diff.cbegin(), diff.cend(), [this](const auto ext_type) {
159 const auto ext = get(ext_type);
160 return ext && ext->is_implemented();
161 });
162
163 // ... if yes, `contains_other_than` is true
164 return itr != diff.cend();
165 }
166
167 return !diff.empty();
168}
std::set< Extension_Code > extension_types() const

References extension_types().

◆ deserialize()

void Botan::TLS::Extensions::deserialize ( TLS_Data_Reader & reader,
Connection_Side from,
Handshake_Type message_type )

Definition at line 119 of file tls_extensions.cpp.

119 {
120 if(reader.has_remaining()) {
121 const uint16_t all_extn_size = reader.get_uint16_t();
122
123 if(reader.remaining_bytes() != all_extn_size) {
124 throw Decoding_Error("Bad extension size");
125 }
126
127 while(reader.has_remaining()) {
128 const uint16_t extension_code = reader.get_uint16_t();
129 const uint16_t extension_size = reader.get_uint16_t();
130
131 const auto type = static_cast<Extension_Code>(extension_code);
132
133 if(this->has(type)) {
134 throw TLS_Exception(TLS::Alert::DecodeError, "Peer sent duplicated extensions");
135 }
136
137 // TODO offer a function on reader that returns a byte range as a reference
138 // to avoid this copy of the extension data
139 const std::vector<uint8_t> extn_data = reader.get_fixed<uint8_t>(extension_size);
140 TLS_Data_Reader extn_reader("Extension", extn_data);
141 this->add(make_extension(extn_reader, type, from, message_type));
142 extn_reader.assert_done();
143 }
144 }
145}

References add(), Botan::TLS::TLS_Data_Reader::get_fixed(), Botan::TLS::TLS_Data_Reader::get_uint16_t(), has(), Botan::TLS::TLS_Data_Reader::has_remaining(), and Botan::TLS::TLS_Data_Reader::remaining_bytes().

Referenced by Botan::TLS::Certificate_13::Certificate_Entry::Certificate_Entry(), Botan::TLS::Certificate_Request_13::Certificate_Request_13(), Botan::TLS::Encrypted_Extensions::Encrypted_Extensions(), and Botan::TLS::New_Session_Ticket_13::New_Session_Ticket_13().

◆ empty()

bool Botan::TLS::Extensions::empty ( ) const
inline

Definition at line 928 of file tls_extensions.h.

928{ return m_extensions.empty(); }

Referenced by Botan::TLS::New_Session_Ticket_13::serialize().

◆ extension_types()

std::set< Extension_Code > Botan::TLS::Extensions::extension_types ( ) const

Definition at line 217 of file tls_extensions.cpp.

217 {
218 std::set<Extension_Code> offers;
219 std::transform(
220 m_extensions.cbegin(), m_extensions.cend(), std::inserter(offers, offers.begin()), [](const auto& ext) {
221 return ext->type();
222 });
223 return offers;
224}

Referenced by contains_other_than().

◆ get() [1/2]

template<typename T >
T * Botan::TLS::Extensions::get ( ) const
inline

◆ get() [2/2]

Extension * Botan::TLS::Extensions::get ( Extension_Code type) const
inline

Definition at line 934 of file tls_extensions.h.

934 {
935 const auto i = std::find_if(
936 m_extensions.cbegin(), m_extensions.cend(), [type](const auto& ext) { return ext->type() == type; });
937
938 return (i != m_extensions.end()) ? i->get() : nullptr;
939 }

◆ has() [1/2]

template<typename T >
bool Botan::TLS::Extensions::has ( ) const
inline

◆ has() [2/2]

bool Botan::TLS::Extensions::has ( Extension_Code type) const
inline

Definition at line 924 of file tls_extensions.h.

924{ return get(type) != nullptr; }

◆ operator=() [1/2]

Extensions & Botan::TLS::Extensions::operator= ( const Extensions & )
delete

◆ operator=() [2/2]

Extensions & Botan::TLS::Extensions::operator= ( Extensions && )
default

◆ remove_extension()

bool Botan::TLS::Extensions::remove_extension ( Extension_Code type)
inline

Remove an extension from this extensions object, if it exists. Returns true if the extension existed (and thus is now removed), otherwise false (the extension wasn't set in the first place).

Note: not used internally, might be used in Callbacks::tls_modify_extensions()

Definition at line 993 of file tls_extensions.h.

993{ return take(type) != nullptr; }
decltype(auto) take()

◆ serialize()

std::vector< uint8_t > Botan::TLS::Extensions::serialize ( Connection_Side whoami) const

Definition at line 183 of file tls_extensions.cpp.

183 {
184 std::vector<uint8_t> buf(2); // 2 bytes for length field
185
186 for(const auto& extn : m_extensions) {
187 if(extn->empty()) {
188 continue;
189 }
190
191 const uint16_t extn_code = static_cast<uint16_t>(extn->type());
192
193 const std::vector<uint8_t> extn_val = extn->serialize(whoami);
194
195 buf.push_back(get_byte<0>(extn_code));
196 buf.push_back(get_byte<1>(extn_code));
197
198 buf.push_back(get_byte<0>(static_cast<uint16_t>(extn_val.size())));
199 buf.push_back(get_byte<1>(static_cast<uint16_t>(extn_val.size())));
200
201 buf += extn_val;
202 }
203
204 const uint16_t extn_size = static_cast<uint16_t>(buf.size() - 2);
205
206 buf[0] = get_byte<0>(extn_size);
207 buf[1] = get_byte<1>(extn_size);
208
209 // avoid sending a completely empty extensions block
210 if(buf.size() == 2) {
211 return std::vector<uint8_t>();
212 }
213
214 return buf;
215}

Referenced by Botan::TLS::Encrypted_Extensions::serialize(), Botan::TLS::Certificate_Request_13::serialize(), and Botan::TLS::New_Session_Ticket_13::serialize().

◆ size()

size_t Botan::TLS::Extensions::size ( ) const
inline

Definition at line 926 of file tls_extensions.h.

926{ return m_extensions.size(); }

◆ take() [1/2]

template<typename T >
decltype(auto) Botan::TLS::Extensions::take ( )
inline

Take the extension with the given type out of the extensions list. Returns a nullptr if the extension didn't exist.

Definition at line 967 of file tls_extensions.h.

967 {
968 std::unique_ptr<T> out_ptr;
969
970 auto ext = take(T::static_type());
971 if(ext != nullptr) {
972 out_ptr.reset(dynamic_cast<T*>(ext.get()));
973 BOTAN_ASSERT_NOMSG(out_ptr != nullptr);
974 ext.release();
975 }
976
977 return out_ptr;
978 }
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59

References BOTAN_ASSERT_NOMSG, and T.

◆ take() [2/2]

std::unique_ptr< Extension > Botan::TLS::Extensions::take ( Extension_Code type)

Take the extension with the given type out of the extensions list. Returns a nullptr if the extension didn't exist.

Definition at line 170 of file tls_extensions.cpp.

170 {
171 const auto i =
172 std::find_if(m_extensions.begin(), m_extensions.end(), [type](const auto& ext) { return ext->type() == type; });
173
174 std::unique_ptr<Extension> result;
175 if(i != m_extensions.end()) {
176 std::swap(result, *i);
177 m_extensions.erase(i);
178 }
179
180 return result;
181}

The documentation for this class was generated from the following files: