/*
* TLS Extensions
* (C) 2011,2012,2015,2016 Jack Lloyd
*     2016 Juraj Somorovsky
*     2021 Elektrobit Automotive GmbH
*     2022 René Meusel, Hannes Rantzsch - neXenio GmbH
*     2023 Mateusz Berezecki
*     2023 Fabian Albert, René Meusel - Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/tls_extensions.h>

#include <botan/dns_name.h>
#include <botan/ipv4_address.h>
#include <botan/ipv6_address.h>
#include <botan/tls_exceptn.h>
#include <botan/tls_policy.h>
#include <botan/internal/fmt.h>
#include <botan/internal/parsing.h>
#include <botan/internal/stl_util.h>
#include <botan/internal/tls_reader.h>
#include <algorithm>
#include <unordered_set>

#if defined(BOTAN_HAS_TLS_13)
   #include <botan/tls_extensions_13.h>
#endif

#if defined(BOTAN_HAS_TLS_12)
   #include <botan/tls_extensions_12.h>
#endif

namespace Botan::TLS {

namespace {

std::unique_ptr<Extension> make_extension(TLS_Data_Reader& reader,
                                          Extension_Code code,
                                          const Connection_Side from,
                                          const Handshake_Type message_type) {
   // This cast is safe because we read exactly a 16 bit length field for
   // the extension in Extensions::deserialize
   const uint16_t size = static_cast<uint16_t>(reader.remaining_bytes());
   switch(code) {
      case Extension_Code::ServerNameIndication:
         return std::make_unique<Server_Name_Indicator>(reader, size, from);

      case Extension_Code::SupportedGroups:
         return std::make_unique<Supported_Groups>(reader, size);

      case Extension_Code::CertificateStatusRequest:
         return std::make_unique<Certificate_Status_Request>(reader, size, message_type, from);

      case Extension_Code::SignatureAlgorithms:
         return std::make_unique<Signature_Algorithms>(reader, size);

      case Extension_Code::CertSignatureAlgorithms:
         return std::make_unique<Signature_Algorithms_Cert>(reader, size);

      case Extension_Code::UseSrtp:
         return std::make_unique<SRTP_Protection_Profiles>(reader, size);

      case Extension_Code::ApplicationLayerProtocolNegotiation:
         return std::make_unique<Application_Layer_Protocol_Notification>(reader, size, from);

      case Extension_Code::ClientCertificateType:
         return std::make_unique<Client_Certificate_Type>(reader, size, from);

      case Extension_Code::ServerCertificateType:
         return std::make_unique<Server_Certificate_Type>(reader, size, from);

      case Extension_Code::RecordSizeLimit:
         return std::make_unique<Record_Size_Limit>(reader, size, from);

      case Extension_Code::SupportedVersions:
         return std::make_unique<Supported_Versions>(reader, size, from);

      case Extension_Code::Padding:
         break;  // RFC 7685, recognized but not implemented; falls through to Unknown_Extension

#if defined(BOTAN_HAS_TLS_12)
      case Extension_Code::EcPointFormats:
         return std::make_unique<Supported_Point_Formats>(reader, size);

      case Extension_Code::SafeRenegotiation:
         return std::make_unique<Renegotiation_Extension>(reader, size);

      case Extension_Code::ExtendedMasterSecret:
         return std::make_unique<Extended_Master_Secret>(reader, size);

      case Extension_Code::EncryptThenMac:
         return std::make_unique<Encrypt_then_MAC>(reader, size);

      case Extension_Code::SessionTicket:
         return std::make_unique<Session_Ticket_Extension>(reader, size, from);
#else
      case Extension_Code::EcPointFormats:
      case Extension_Code::SafeRenegotiation:
      case Extension_Code::ExtendedMasterSecret:
      case Extension_Code::EncryptThenMac:
      case Extension_Code::SessionTicket:
         break;  // considered as 'unknown extension'
#endif

#if defined(BOTAN_HAS_TLS_13)
      case Extension_Code::PresharedKey:
         return std::make_unique<PSK>(reader, size, message_type);

      case Extension_Code::EarlyData:
         return std::make_unique<EarlyDataIndication>(reader, size, message_type);

      case Extension_Code::Cookie:
         return std::make_unique<Cookie>(reader, size);

      case Extension_Code::PskKeyExchangeModes:
         return std::make_unique<PSK_Key_Exchange_Modes>(reader, size);

      case Extension_Code::CertificateAuthorities:
         return std::make_unique<Certificate_Authorities>(reader, size);

      case Extension_Code::KeyShare:
         return std::make_unique<Key_Share>(reader, size, message_type);
#else
      case Extension_Code::PresharedKey:
      case Extension_Code::EarlyData:
      case Extension_Code::Cookie:
      case Extension_Code::PskKeyExchangeModes:
      case Extension_Code::CertificateAuthorities:
      case Extension_Code::KeyShare:
         break;  // considered as 'unknown extension'
#endif
   }

   return std::make_unique<Unknown_Extension>(code, reader, size);
}

}  // namespace

Extensions::~Extensions() = default;

bool Extensions::has(Extension_Code type) const {
   return m_extensions.contains(type);
}

Extension* Extensions::get(Extension_Code type) const {
   const auto i = m_extensions.find(type);

   if(i == m_extensions.end()) {
      return nullptr;
   } else {
      return i->second.get();
   }
}

void Extensions::add(std::unique_ptr<Extension> extn) {
   const auto type = extn->type();
   if(has(type)) {
      throw Invalid_Argument("cannot add the same extension twice: " + std::to_string(static_cast<uint16_t>(type)));
   }

   m_extension_codes.push_back(type);
   m_extensions.emplace(type, std::move(extn));
}

void Extensions::deserialize(TLS_Data_Reader& reader, const Connection_Side from, const Handshake_Type message_type) {
   if(reader.has_remaining()) {
      const uint16_t all_extn_size = reader.get_uint16_t();

      if(reader.remaining_bytes() != all_extn_size) {
         throw Decoding_Error("Bad extension size");
      }

      while(reader.has_remaining()) {
         const uint16_t extension_code = reader.get_uint16_t();
         const uint16_t extension_size = reader.get_uint16_t();

         const auto type = static_cast<Extension_Code>(extension_code);

         if(this->has(type)) {
            throw TLS_Exception(TLS::Alert::DecodeError, "Peer sent duplicated extensions");
         }

         // TODO offer a function on reader that returns a byte range as a reference
         // to avoid this copy of the extension data
         const std::vector<uint8_t> extn_data = reader.get_fixed<uint8_t>(extension_size);
         m_raw_extension_data[type] = extn_data;
         TLS_Data_Reader extn_reader("Extension", extn_data);
         this->add(make_extension(extn_reader, type, from, message_type));
         extn_reader.assert_done();
      }
   }
}

bool Extensions::contains_other_than(const std::set<Extension_Code>& allowed_extensions,
                                     const bool allow_unknown_extensions) const {
   const auto found = extension_types();

   std::vector<Extension_Code> diff;
   std::set_difference(
      found.cbegin(), found.end(), allowed_extensions.cbegin(), allowed_extensions.cend(), std::back_inserter(diff));

   if(allow_unknown_extensions) {
      // Go through the found unexpected extensions whether any of those
      // is known to this TLS implementation.
      const auto itr = std::find_if(diff.cbegin(), diff.cend(), [this](const auto ext_type) {
         const auto ext = get(ext_type);
         return ext && ext->is_implemented();
      });

      // ... if yes, `contains_other_than` is true
      return itr != diff.cend();
   }

   return !diff.empty();
}

bool Extensions::remove_extension(Extension_Code type) {
   auto i = m_extensions.find(type);

   if(i == m_extensions.end()) {
      return false;
   } else {
      m_extensions.erase(i);
      std::erase(m_extension_codes, type);
      m_raw_extension_data.erase(type);
      return true;
   }
}

std::vector<uint8_t> Extensions::serialize(Connection_Side whoami) const {
   std::vector<uint8_t> buf(2);  // 2 bytes for length field

   // Serialize in the order extensions were added, which matters for TLS 1.3
   for(const auto extn_type : m_extension_codes) {
      const auto& extn = m_extensions.at(extn_type);

      if(extn->empty()) {
         continue;
      }

      const uint16_t extn_code = static_cast<uint16_t>(extn_type);

      const std::vector<uint8_t> extn_val = extn->serialize(whoami);

      // Each extension carries a uint16 length prefix.
      BOTAN_ASSERT_NOMSG(extn_val.size() <= 0xFFFF);

      buf.push_back(get_byte<0>(extn_code));
      buf.push_back(get_byte<1>(extn_code));

      buf.push_back(get_byte<0>(static_cast<uint16_t>(extn_val.size())));
      buf.push_back(get_byte<1>(static_cast<uint16_t>(extn_val.size())));

      buf += extn_val;
   }

   // The outer extensions block is itself uint16-length-prefixed.
   BOTAN_ASSERT_NOMSG(buf.size() - 2 <= 0xFFFF);
   const uint16_t extn_size = static_cast<uint16_t>(buf.size() - 2);

   buf[0] = get_byte<0>(extn_size);
   buf[1] = get_byte<1>(extn_size);

   // avoid sending a completely empty extensions block
   if(buf.size() == 2) {
      return std::vector<uint8_t>();
   }

   return buf;
}

std::set<Extension_Code> Extensions::extension_types() const {
   std::set<Extension_Code> offers;
   for(const auto& [extn_type, extn] : m_extensions) {
      // Consistent with serialize(): empty extensions are not placed on
      // the wire so they must not appear in the "offered" set either.
      if(!extn->empty()) {
         offers.insert(extn_type);
      }
   }
   return offers;
}

void Extensions::reorder(std::span<const Extension_Code> order) {
   const std::set<Extension_Code> in_order(order.begin(), order.end());

   std::vector<Extension_Code> new_codes;
   new_codes.reserve(m_extension_codes.size());

   // First: extensions not mentioned in the order (preserving their relative order)
   for(auto code : m_extension_codes) {
      if(!in_order.contains(code)) {
         new_codes.push_back(code);
      }
   }

   // Then: extensions in the specified order. Deduplicate so a caller that
   // accidentally lists the same code twice doesn't cause it to be
   // serialized twice (which would also break peers that reject duplicate
   // extension codes per RFC 8446 4.2 / RFC 5246 7.4.1.4).
   std::unordered_set<Extension_Code> already_pushed;
   for(auto code : order) {
      if(m_extensions.contains(code) && already_pushed.insert(code).second) {
         new_codes.push_back(code);
      }
   }

   m_extension_codes = std::move(new_codes);
}

Unknown_Extension::Unknown_Extension(Extension_Code type, TLS_Data_Reader& reader, uint16_t extension_size) :
      m_type(type), m_value(reader.get_fixed<uint8_t>(extension_size)) {}

std::vector<uint8_t> Unknown_Extension::serialize(Connection_Side /*whoami*/) const {
   return m_value;
}

Server_Name_Indicator::Server_Name_Indicator(TLS_Data_Reader& reader, uint16_t extension_size, Connection_Side from) {
   /*
   RFC 6066 Section 3

      A server that receives a client hello containing the "server_name"
      extension MAY use the information contained in the extension to guide
      its selection of an appropriate certificate to return to the client,
      and/or other aspects of security policy.  In this event, the server
      SHALL include an extension of type "server_name" in the (extended)
      server hello.  The "extension_data" field of this extension SHALL be
      empty.
   */
   if(from == Connection_Side::Server) {
      if(extension_size != 0) {
         throw TLS_Exception(Alert::IllegalParameter, "Server sent non-empty SNI extension");
      }
   } else {
      // Clients are required to send at least one name in the SNI
      if(extension_size == 0) {
         throw TLS_Exception(Alert::IllegalParameter, "Client sent empty SNI extension");
      }

      const uint16_t name_bytes = reader.get_uint16_t();

      // RFC 6066 3: a ServerName carrying a host_name (the only NameType
      // currently defined and the only one this implementation acts on)
      // requires at least 1 byte name_type + 2 byte length + 1 byte HostName.
      if(name_bytes + 2 != extension_size || name_bytes < 4) {
         throw Decoding_Error("Bad encoding of SNI extension");
      }

      BOTAN_ASSERT_NOMSG(reader.remaining_bytes() == name_bytes);

      while(reader.has_remaining()) {
         const uint8_t name_type = reader.get_byte();

         if(name_type == 0) {
            /*
            RFC 6066 Section 3
               The ServerNameList MUST NOT contain more than one name of the same name_type.
            */
            if(!m_sni_host_name.empty()) {
               throw Decoding_Error("TLS ServerNameIndicator contains more than one host_name");
            }
            m_sni_host_name = reader.get_string(2, 1, 65535);
         } else {
            /*
            Unknown name type - skip its length-prefixed value and continue

            RFC 6066 Section 3
               For backward compatibility, all future data structures associated
               with new NameTypes MUST begin with a 16-bit length field.
            */
            const uint16_t unknown_name_len = reader.get_uint16_t();
            reader.discard_next(unknown_name_len);
         }
      }
   }
}

std::vector<uint8_t> Server_Name_Indicator::serialize(Connection_Side whoami) const {
   // RFC 6066
   //    [...] the server SHALL include an extension of type "server_name" in
   //    the (extended) server hello. The "extension_data" field of this
   //    extension SHALL be empty.
   if(whoami == Connection_Side::Server) {
      return {};
   }

   std::vector<uint8_t> buf;

   const size_t name_len = m_sni_host_name.size();

   // RFC 6066 3: HostName<1..2^16-1>; the outer ServerNameList wraps a
   // 1-byte name_type and a 2-byte length so the whole entry must fit in
   // a uint16_t too.
   BOTAN_ASSERT_NOMSG(name_len + 3 <= 0xFFFF);

   buf.push_back(get_byte<0>(static_cast<uint16_t>(name_len + 3)));
   buf.push_back(get_byte<1>(static_cast<uint16_t>(name_len + 3)));
   buf.push_back(0);  // DNS

   buf.push_back(get_byte<0>(static_cast<uint16_t>(name_len)));
   buf.push_back(get_byte<1>(static_cast<uint16_t>(name_len)));

   buf += as_span_of_bytes(m_sni_host_name);

   return buf;
}

bool Server_Name_Indicator::hostname_acceptable_for_sni(std::string_view hostname) {
   // Avoid sending an IPv4/IPv6 address in SNI as this is prohibited

   if(hostname.empty() || hostname.size() > 255) {
      return false;
   }

   if(auto ipv4 = IPv4Address::from_string(hostname)) {
      return false;
   }

   if(auto ipv6 = IPv6Address::from_string(hostname)) {
      return false;
   }

   if(auto dns = DNSName::from_string(hostname)) {
      return true;
   } else {
      return false;
   }
}

Application_Layer_Protocol_Notification::Application_Layer_Protocol_Notification(std::string_view protocol) {
   BOTAN_ARG_CHECK(!protocol.empty(), "ALPN protocol name must not be empty");
   BOTAN_ARG_CHECK(protocol.size() < 256, "ALPN protocol name too long");
   m_protocols.emplace_back(protocol);
}

Application_Layer_Protocol_Notification::Application_Layer_Protocol_Notification(std::vector<std::string> protocols) :
      m_protocols(std::move(protocols)) {
   for(const auto& protocol : m_protocols) {
      BOTAN_ARG_CHECK(!protocol.empty(), "ALPN protocol name must not be empty");
      BOTAN_ARG_CHECK(protocol.size() < 256, "ALPN protocol name too long");
   }
}

Application_Layer_Protocol_Notification::Application_Layer_Protocol_Notification(TLS_Data_Reader& reader,
                                                                                 uint16_t extension_size,
                                                                                 Connection_Side from) {
   if(extension_size < 2) {
      throw Decoding_Error("ALPN extension cannot be empty");
   }

   const uint16_t name_bytes = reader.get_uint16_t();

   size_t bytes_remaining = extension_size - 2;

   if(name_bytes != bytes_remaining) {
      throw Decoding_Error("Bad encoding of ALPN extension, bad length field");
   }

   // RFC 7301 3.1: ProtocolName protocol_name_list<2..2^16-1>
   if(name_bytes == 0) {
      throw Decoding_Error("Empty ALPN protocol_name_list not allowed");
   }

   while(bytes_remaining > 0) {
      const std::string p = reader.get_string(1, 0, 255);

      if(bytes_remaining < p.size() + 1) {
         throw Decoding_Error("Bad encoding of ALPN, length field too long");
      }

      if(p.empty()) {
         throw Decoding_Error("Empty ALPN protocol not allowed");
      }

      bytes_remaining -= (p.size() + 1);

      m_protocols.push_back(p);
   }

   // RFC 7301 3.1
   //    The "extension_data" field of the [...] extension is structured the
   //    same as described above for the client "extension_data", except that
   //    the "ProtocolNameList" MUST contain exactly one "ProtocolName".
   if(from == Connection_Side::Server && m_protocols.size() != 1) {
      throw TLS_Exception(
         Alert::DecodeError,
         "Server sent " + std::to_string(m_protocols.size()) + " protocols in ALPN extension response");
   }
}

std::string Application_Layer_Protocol_Notification::single_protocol() const {
   BOTAN_STATE_CHECK(m_protocols.size() == 1);
   return m_protocols.front();
}

std::vector<uint8_t> Application_Layer_Protocol_Notification::serialize(Connection_Side /*whoami*/) const {
   std::vector<uint8_t> buf(2);

   for(auto&& proto : m_protocols) {
      if(proto.length() >= 256) {
         throw TLS_Exception(Alert::InternalError, "ALPN name too long");
      }
      if(!proto.empty()) {
         append_tls_length_value(buf, proto, 1);
      }
   }

   // RFC 7301 3.1: ProtocolName protocol_name_list<2..2^16-1>;
   BOTAN_ASSERT_NOMSG(buf.size() - 2 <= 0xFFFF);
   buf[0] = get_byte<0>(static_cast<uint16_t>(buf.size() - 2));
   buf[1] = get_byte<1>(static_cast<uint16_t>(buf.size() - 2));

   return buf;
}

Certificate_Type_Base::Certificate_Type_Base(std::vector<Certificate_Type> supported_cert_types) :
      m_certificate_types(std::move(supported_cert_types)), m_from(Connection_Side::Client) {
   BOTAN_ARG_CHECK(!m_certificate_types.empty(), "at least one certificate type must be supported");
}

Client_Certificate_Type::Client_Certificate_Type(const Client_Certificate_Type& cct, const Policy& policy) :
      Certificate_Type_Base(cct, policy.accepted_client_certificate_types()) {}

Server_Certificate_Type::Server_Certificate_Type(const Server_Certificate_Type& sct, const Policy& policy) :
      Certificate_Type_Base(sct, policy.accepted_server_certificate_types()) {}

Certificate_Type_Base::Certificate_Type_Base(const Certificate_Type_Base& certificate_type_from_client,
                                             std::span<const Certificate_Type> server_preference) :
      m_from(Connection_Side::Server) {
   // RFC 7250 4.2
   //    The server_certificate_type extension in the client hello indicates the
   //    types of certificates the client is able to process when provided by
   //    the server in a subsequent certificate payload. [...] With the
   //    server_certificate_type extension in the server hello, the TLS server
   //    indicates the certificate type carried in the Certificate payload.
   for(const auto server_supported_cert_type : server_preference) {
      if(value_exists(certificate_type_from_client.m_certificate_types, server_supported_cert_type)) {
         m_certificate_types.push_back(server_supported_cert_type);
         return;
      }
   }

   // RFC 7250 4.2 (2.)
   //    The server supports the extension defined in this document, but
   //    it does not have any certificate type in common with the client.
   //    Then, the server terminates the session with a fatal alert of
   //    type "unsupported_certificate".
   throw TLS_Exception(Alert::UnsupportedCertificate, "Failed to agree on certificate_type");
}

Certificate_Type_Base::Certificate_Type_Base(TLS_Data_Reader& reader, uint16_t extension_size, Connection_Side from) :
      m_from(from) {
   if(extension_size == 0) {
      throw Decoding_Error("Certificate type extension cannot be empty");
   }

   if(from == Connection_Side::Client) {
      const auto type_bytes = reader.get_tls_length_value(1);
      if(static_cast<size_t>(extension_size) != type_bytes.size() + 1) {
         throw Decoding_Error("certificate type extension had inconsistent length");
      }
      // RFC 7250 4: {client,server}_certificate_types<1..2^8-1> so must be non-empty
      if(type_bytes.empty()) {
         throw Decoding_Error("Certificate type extension contains no types");
      }
      std::transform(
         type_bytes.begin(), type_bytes.end(), std::back_inserter(m_certificate_types), [](const auto type_byte) {
            return static_cast<Certificate_Type>(type_byte);
         });
   } else {
      // RFC 7250 4.2
      //    Note that only a single value is permitted in the
      //    server_certificate_type extension when carried in the server hello.
      if(extension_size != 1) {
         throw Decoding_Error("Server's certificate type extension must be of length 1");
      }
      const auto type_byte = reader.get_byte();
      m_certificate_types.push_back(static_cast<Certificate_Type>(type_byte));
   }
}

std::vector<uint8_t> Certificate_Type_Base::serialize(Connection_Side whoami) const {
   std::vector<uint8_t> result;
   if(whoami == Connection_Side::Client) {
      std::vector<uint8_t> type_bytes;
      std::transform(
         m_certificate_types.begin(), m_certificate_types.end(), std::back_inserter(type_bytes), [](const auto type) {
            return static_cast<uint8_t>(type);
         });
      append_tls_length_value(result, type_bytes, 1);
   } else {
      BOTAN_ASSERT_NOMSG(m_certificate_types.size() == 1);
      result.push_back(static_cast<uint8_t>(m_certificate_types.front()));
   }
   return result;
}

void Certificate_Type_Base::validate_selection(const Certificate_Type_Base& from_server) const {
   BOTAN_ASSERT_NOMSG(m_from == Connection_Side::Client);
   BOTAN_ASSERT_NOMSG(from_server.m_from == Connection_Side::Server);

   // RFC 7250 4.2
   //    The value conveyed in the [client_]certificate_type extension MUST be
   //    selected from one of the values provided in the [client_]certificate_type
   //    extension sent in the client hello.
   if(!value_exists(m_certificate_types, from_server.selected_certificate_type())) {
      throw TLS_Exception(Alert::IllegalParameter,
                          Botan::fmt("Selected certificate type was not offered: {}",
                                     certificate_type_to_string(from_server.selected_certificate_type())));
   }
}

Certificate_Type Certificate_Type_Base::selected_certificate_type() const {
   BOTAN_ASSERT_NOMSG(m_from == Connection_Side::Server);
   BOTAN_ASSERT_NOMSG(m_certificate_types.size() == 1);
   return m_certificate_types.front();
}

Supported_Groups::Supported_Groups(std::vector<Group_Params> groups) : m_groups(std::move(groups)) {}

const std::vector<Group_Params>& Supported_Groups::groups() const {
   return m_groups;
}

std::vector<Group_Params> Supported_Groups::ec_groups() const {
   std::vector<Group_Params> ec;
   for(auto g : m_groups) {
      if(g.is_pure_ecc_group()) {
         ec.push_back(g);
      }
   }
   return ec;
}

std::vector<Group_Params> Supported_Groups::dh_groups() const {
   std::vector<Group_Params> dh;
   for(auto g : m_groups) {
      if(g.is_in_ffdhe_range()) {
         dh.push_back(g);
      }
   }
   return dh;
}

std::vector<uint8_t> Supported_Groups::serialize(Connection_Side /*whoami*/) const {
   std::vector<uint8_t> buf(2);

   for(auto g : m_groups) {
      const uint16_t id = g.wire_code();

      if(id > 0) {
         buf.push_back(get_byte<0>(id));
         buf.push_back(get_byte<1>(id));
      }
   }

   // RFC 8446 4.2.7: NamedGroup named_group_list<2..2^16-1>;
   BOTAN_ASSERT_NOMSG(buf.size() - 2 <= 0xFFFF);
   buf[0] = get_byte<0>(static_cast<uint16_t>(buf.size() - 2));
   buf[1] = get_byte<1>(static_cast<uint16_t>(buf.size() - 2));

   return buf;
}

Supported_Groups::Supported_Groups(TLS_Data_Reader& reader, uint16_t extension_size) {
   const uint16_t len = reader.get_uint16_t();

   if(len + 2 != extension_size) {
      throw Decoding_Error("Inconsistent length field in supported groups list");
   }

   // RFC 8446 4.2.7: NamedGroup named_group_list<2..2^16-1>;
   if(len == 0) {
      throw Decoding_Error("Empty supported groups list");
   }

   if(len % 2 == 1) {
      throw Decoding_Error("Supported groups list of strange size");
   }

   const size_t elems = len / 2;

   std::unordered_set<uint16_t> seen;
   for(size_t i = 0; i != elems; ++i) {
      const auto group = static_cast<Group_Params>(reader.get_uint16_t());
      // Note: RFC 8446 does not explicitly enforce that groups must be unique.
      if(seen.insert(group.wire_code()).second) {
         m_groups.push_back(group);
      }
   }
}

namespace {

std::vector<uint8_t> serialize_signature_algorithms(const std::vector<Signature_Scheme>& schemes) {
   BOTAN_ASSERT(schemes.size() < 256, "Too many signature schemes");

   std::vector<uint8_t> buf;

   const uint16_t len = static_cast<uint16_t>(schemes.size() * 2);

   buf.push_back(get_byte<0>(len));
   buf.push_back(get_byte<1>(len));

   for(const Signature_Scheme scheme : schemes) {
      buf.push_back(get_byte<0>(scheme.wire_code()));
      buf.push_back(get_byte<1>(scheme.wire_code()));
   }

   return buf;
}

std::vector<Signature_Scheme> parse_signature_algorithms(TLS_Data_Reader& reader, uint16_t extension_size) {
   uint16_t len = reader.get_uint16_t();

   if(len + 2 != extension_size || len % 2 == 1 || len == 0) {
      throw Decoding_Error("Bad encoding on signature algorithms extension");
   }

   std::vector<Signature_Scheme> schemes;
   schemes.reserve(len / 2);
   while(len > 0) {
      schemes.emplace_back(reader.get_uint16_t());
      len -= 2;
   }

   return schemes;
}

}  // namespace

std::vector<uint8_t> Signature_Algorithms::serialize(Connection_Side /*whoami*/) const {
   return serialize_signature_algorithms(m_schemes);
}

Signature_Algorithms::Signature_Algorithms(TLS_Data_Reader& reader, uint16_t extension_size) :
      m_schemes(parse_signature_algorithms(reader, extension_size)) {}

std::vector<uint8_t> Signature_Algorithms_Cert::serialize(Connection_Side /*whoami*/) const {
   return serialize_signature_algorithms(m_schemes);
}

Signature_Algorithms_Cert::Signature_Algorithms_Cert(TLS_Data_Reader& reader, uint16_t extension_size) :
      m_schemes(parse_signature_algorithms(reader, extension_size)) {}

SRTP_Protection_Profiles::SRTP_Protection_Profiles(TLS_Data_Reader& reader, uint16_t extension_size) {
   // RFC 5764 4.1.1: UseSRTPData consists of
   //    SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
   //    opaque srtp_mki<0..255>;
   // for a wire size of 2 (profiles len) + 2*N + 1 (mki len) + mki_bytes,
   // with N >= 1.
   if(extension_size < 5) {
      throw Decoding_Error("Truncated SRTP protection extension");
   }
   const size_t max_profile_pairs = (static_cast<size_t>(extension_size) - 3) / 2;
   m_pp = reader.get_range<uint16_t>(2, 1, max_profile_pairs);
   const std::vector<uint8_t> mki = reader.get_range<uint8_t>(1, 0, 255);

   if(m_pp.size() * 2 + mki.size() + 3 != extension_size) {
      throw Decoding_Error("Bad encoding for SRTP protection extension");
   }

   if(!mki.empty()) {
      throw Decoding_Error("Unhandled non-empty MKI for SRTP protection extension");
   }
}

std::vector<uint8_t> SRTP_Protection_Profiles::serialize(Connection_Side /*whoami*/) const {
   std::vector<uint8_t> buf;

   const uint16_t pp_len = static_cast<uint16_t>(m_pp.size() * 2);
   buf.push_back(get_byte<0>(pp_len));
   buf.push_back(get_byte<1>(pp_len));

   for(const uint16_t pp : m_pp) {
      buf.push_back(get_byte<0>(pp));
      buf.push_back(get_byte<1>(pp));
   }

   buf.push_back(0);  // srtp_mki, always empty here

   return buf;
}

std::vector<uint8_t> Supported_Versions::serialize(Connection_Side whoami) const {
   std::vector<uint8_t> buf;

   if(whoami == Connection_Side::Server) {
      BOTAN_ASSERT_NOMSG(m_versions.size() == 1);
      buf.push_back(m_versions[0].major_version());
      buf.push_back(m_versions[0].minor_version());
   } else {
      // RFC 8446 4.2.1: ProtocolVersion versions<2..254>; - up to 127 entries.
      BOTAN_ASSERT_NOMSG(!m_versions.empty());
      BOTAN_ASSERT_NOMSG(m_versions.size() <= 127);
      const uint8_t len = static_cast<uint8_t>(m_versions.size() * 2);

      buf.push_back(len);

      for(const Protocol_Version version : m_versions) {
         buf.push_back(version.major_version());
         buf.push_back(version.minor_version());
      }
   }

   return buf;
}

Supported_Versions::Supported_Versions(Protocol_Version offer, const Policy& policy) {
   // RFC 8446 4.2.1
   //    The extension contains a list of supported versions in preference order,
   //    with the most preferred version first. Implementations [...] MUST send
   //    this extension in the ClientHello containing all versions of TLS which
   //    they are prepared to negotiate.
   //
   // We simply assume that we always want the newest available TLS version.
#if defined(BOTAN_HAS_TLS_13)
   if(!offer.is_datagram_protocol()) {
      if(offer >= Protocol_Version::TLS_V13 && policy.allow_tls13()) {
         m_versions.push_back(Protocol_Version::TLS_V13);
      }
   }
#endif

#if defined(BOTAN_HAS_TLS_12)
   if(offer.is_datagram_protocol()) {
      if(offer >= Protocol_Version::DTLS_V12 && policy.allow_dtls12()) {
         m_versions.push_back(Protocol_Version::DTLS_V12);
      }
   } else {
      if(offer >= Protocol_Version::TLS_V12 && policy.allow_tls12()) {
         m_versions.push_back(Protocol_Version::TLS_V12);
      }
   }
#endif

   // if no versions are supported, the input variables are not used
   BOTAN_UNUSED(offer, policy);
}

Supported_Versions::Supported_Versions(TLS_Data_Reader& reader, uint16_t extension_size, Connection_Side from) {
   if(from == Connection_Side::Server) {
      if(extension_size != 2) {
         throw Decoding_Error("Server sent invalid supported_versions extension");
      }
      m_versions.push_back(Protocol_Version(reader.get_uint16_t()));
   } else {
      auto versions = reader.get_range<uint16_t>(1, 1, 127);

      for(auto v : versions) {
         m_versions.push_back(Protocol_Version(v));
      }

      if(extension_size != 1 + 2 * versions.size()) {
         throw Decoding_Error("Client sent invalid supported_versions extension");
      }
   }
}

bool Supported_Versions::supports(Protocol_Version version) const {
   for(auto v : m_versions) {
      if(version == v) {
         return true;
      }
   }
   return false;
}

Record_Size_Limit::Record_Size_Limit(const uint16_t limit) : m_limit(limit) {
   BOTAN_ARG_CHECK(limit >= 64, "RFC 8449 does not allow record size limits smaller than 64 bytes");
   BOTAN_ARG_CHECK(limit <= MAX_PLAINTEXT_SIZE + 1 /* encrypted content type byte */,
                   "RFC 8449 does not allow record size limits larger than 2^14+1");
}

Record_Size_Limit::Record_Size_Limit(TLS_Data_Reader& reader, uint16_t extension_size, Connection_Side from) {
   if(extension_size != 2) {
      throw TLS_Exception(Alert::DecodeError, "invalid record_size_limit extension");
   }

   m_limit = reader.get_uint16_t();

   // RFC 8449 4.
   //    This value is the length of the plaintext of a protected record.
   //    The value includes the content type and padding added in TLS 1.3 (that
   //    is, the complete length of TLSInnerPlaintext).
   //
   //    A server MUST NOT enforce this restriction; a client might advertise
   //    a higher limit that is enabled by an extension or version the server
   //    does not understand. A client MAY abort the handshake with an
   //    "illegal_parameter" alert.
   //
   // Note: We are currently supporting this extension in TLS 1.3 only, hence
   //       we check for the TLS 1.3 limit. The TLS 1.2 limit would not include
   //       the "content type byte" and hence be one byte less!
   if(m_limit > MAX_PLAINTEXT_SIZE + 1 /* encrypted content type byte */ && from == Connection_Side::Server) {
      throw TLS_Exception(Alert::IllegalParameter,
                          "Server requested a record size limit larger than the protocol's maximum");
   }

   // RFC 8449 4.
   //    Endpoints MUST NOT send a "record_size_limit" extension with a value
   //    smaller than 64.  An endpoint MUST treat receipt of a smaller value
   //    as a fatal error and generate an "illegal_parameter" alert.
   if(m_limit < 64) {
      throw TLS_Exception(Alert::IllegalParameter, "Received a record size limit smaller than 64 bytes");
   }
}

std::vector<uint8_t> Record_Size_Limit::serialize(Connection_Side /*whoami*/) const {
   std::vector<uint8_t> buf;

   buf.push_back(get_byte<0>(m_limit));
   buf.push_back(get_byte<1>(m_limit));

   return buf;
}

}  // namespace Botan::TLS
