/* * TLS 1.3 Specific 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 * 2026 René Meusel - Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #include #include #include namespace Botan::TLS { Cookie::Cookie(const std::vector& cookie) : m_cookie(cookie) {} Cookie::Cookie(TLS_Data_Reader& reader, uint16_t extension_size) { if(extension_size == 0) { return; } const uint16_t len = reader.get_uint16_t(); if(len == 0) { // Based on RFC 8446 4.2.2, len of the Cookie buffer must be at least 1 throw Decoding_Error("Cookie length must be at least 1 byte"); } if(len > reader.remaining_bytes()) { throw Decoding_Error("Not enough bytes in the buffer to decode Cookie"); } for(size_t i = 0; i < len; ++i) { m_cookie.push_back(reader.get_byte()); } } std::vector Cookie::serialize(Connection_Side /*whoami*/) const { std::vector buf; const uint16_t len = static_cast(m_cookie.size()); buf.push_back(get_byte<0>(len)); buf.push_back(get_byte<1>(len)); for(const auto& cookie_byte : m_cookie) { buf.push_back(cookie_byte); } return buf; } std::vector PSK_Key_Exchange_Modes::serialize(Connection_Side /*whoami*/) const { std::vector buf; BOTAN_ASSERT_NOMSG(m_modes.size() < 256); buf.push_back(static_cast(m_modes.size())); for(const auto& mode : m_modes) { buf.push_back(static_cast(mode)); } return buf; } PSK_Key_Exchange_Modes::PSK_Key_Exchange_Modes(TLS_Data_Reader& reader, uint16_t extension_size) { if(extension_size < 2) { throw Decoding_Error("Empty psk_key_exchange_modes extension is illegal"); } const auto mode_count = reader.get_byte(); for(uint16_t i = 0; i < mode_count; ++i) { const auto mode = static_cast(reader.get_byte()); if(mode == PSK_Key_Exchange_Mode::PSK_KE || mode == PSK_Key_Exchange_Mode::PSK_DHE_KE) { m_modes.push_back(mode); } } } std::vector Certificate_Authorities::serialize(Connection_Side /*whoami*/) const { std::vector out; std::vector dn_list; for(const auto& dn : m_distinguished_names) { std::vector encoded_dn; auto encoder = DER_Encoder(encoded_dn); dn.encode_into(encoder); append_tls_length_value(dn_list, encoded_dn, 2); } append_tls_length_value(out, dn_list, 2); return out; } Certificate_Authorities::Certificate_Authorities(TLS_Data_Reader& reader, uint16_t extension_size) { if(extension_size < 2) { throw Decoding_Error("Empty certificate_authorities extension is illegal"); } const uint16_t purported_size = reader.get_uint16_t(); if(reader.remaining_bytes() != purported_size) { throw Decoding_Error("Inconsistent length in certificate_authorities extension"); } while(reader.has_remaining()) { std::vector name_bits = reader.get_tls_length_value(2); BER_Decoder decoder(name_bits.data(), name_bits.size()); m_distinguished_names.emplace_back(); decoder.decode(m_distinguished_names.back()); } } Certificate_Authorities::Certificate_Authorities(std::vector acceptable_DNs) : m_distinguished_names(std::move(acceptable_DNs)) {} std::vector EarlyDataIndication::serialize(Connection_Side /*whoami*/) const { std::vector result; if(m_max_early_data_size.has_value()) { const auto max_data = m_max_early_data_size.value(); result.push_back(get_byte<0>(max_data)); result.push_back(get_byte<1>(max_data)); result.push_back(get_byte<2>(max_data)); result.push_back(get_byte<3>(max_data)); } return result; } EarlyDataIndication::EarlyDataIndication(TLS_Data_Reader& reader, uint16_t extension_size, Handshake_Type message_type) { if(message_type == Handshake_Type::NewSessionTicket) { if(extension_size != 4) { throw TLS_Exception(Alert::DecodeError, "Received an early_data extension in a NewSessionTicket message " "without maximum early data size indication"); } m_max_early_data_size = reader.get_uint32_t(); } else if(extension_size != 0) { throw TLS_Exception(Alert::DecodeError, "Received an early_data extension containing an unexpected data " "size indication"); } } bool EarlyDataIndication::empty() const { // This extension may be empty by definition but still carry information return false; } } // namespace Botan::TLS