10#include <botan/internal/tls_record_layer_13.h>
12#include <botan/tls_alert.h>
13#include <botan/tls_exceptn.h>
14#include <botan/tls_policy.h>
15#include <botan/tls_version.h>
16#include <botan/internal/ct_utils.h>
17#include <botan/internal/loadstor.h>
18#include <botan/internal/tls_cipher_state.h>
25template <
typename IteratorT>
26bool verify_change_cipher_spec(
const IteratorT data,
const size_t size) {
33 const size_t expected_fragment_length = 1;
34 const uint8_t expected_fragment_byte = 0x01;
35 return (size == expected_fragment_length && *data == expected_fragment_byte);
38Record_Type read_record_type(
const uint8_t type_byte) {
46 throw TLS_Exception(Alert::UnexpectedMessage,
"TLS record type had unexpected value");
55class TLSPlaintext_Header final {
57 TLSPlaintext_Header(std::vector<uint8_t> hdr,
const bool check_tls13_version) {
59 m_type = read_record_type(hdr[0]);
60 m_legacy_version = Protocol_Version(
make_uint16(hdr[1], hdr[2]));
62 m_serialized = std::move(hdr);
67 if(m_legacy_version.major_version() != 0x03) {
68 throw TLS_Exception(Alert::IllegalParameter,
"Received unexpected record version");
74 if(check_tls13_version && m_legacy_version.version_code() != 0x0303) {
75 throw TLS_Exception(Alert::IllegalParameter,
"Received unexpected record version");
85 throw TLS_Exception(Alert::DecodeError,
"empty record received");
99 throw TLS_Exception(Alert::RecordOverflow,
"Received an encrypted record that exceeds maximum size");
112 throw TLS_Exception(Alert::RecordOverflow,
"Received a record that exceeds maximum size");
118 const size_t frgmnt_length,
119 const bool use_compatibility_version) :
121 m_legacy_version(use_compatibility_version ? 0x0301 : 0x0303)
123 m_fragment_length(static_cast<uint16_t>(frgmnt_length)),
125 static_cast<uint8_t
>(m_type),
126 m_legacy_version.major_version(),
127 m_legacy_version.minor_version(),
134 uint16_t fragment_length()
const {
return m_fragment_length; }
136 Protocol_Version legacy_version()
const {
return m_legacy_version; }
138 const std::vector<uint8_t>& serialized()
const {
return m_serialized; }
142 Protocol_Version m_legacy_version;
143 uint16_t m_fragment_length;
144 std::vector<uint8_t> m_serialized;
151 m_policy(std::move(policy)),
175 m_receiving_compat_mode(true) {
182 if(m_read_offset > 0) {
183 m_read_buffer.erase(m_read_buffer.begin(), m_read_buffer.begin() + m_read_offset);
187 m_read_buffer.insert(m_read_buffer.end(), data.begin(), data.end());
191 std::span<const uint8_t> data,
207 "Application Data records MUST NOT be written to the wire unprotected");
214 "zero-length fragments of types other than application data are not allowed");
220 std::vector<uint8_t> output;
224 constexpr size_t content_type_tag_length = 1;
231 const size_t max_plaintext_size =
232 (protect) ? m_outgoing_record_size_limit - content_type_tag_length :
static_cast<uint16_t
>(
MAX_PLAINTEXT_SIZE);
234 const auto records = std::max((data.size() + max_plaintext_size - 1) / max_plaintext_size,
size_t(1));
240 size_t final_record_padding = 0;
247 const auto remaining_bytes = data.size() - ((records - 1) * max_plaintext_size) + content_type_tag_length;
248 final_record_padding = std::min<size_t>(m_policy->record_padding_bytes(remaining_bytes),
249 m_outgoing_record_size_limit - remaining_bytes);
252 output_length += data.size();
254 output.reserve(output_length);
256 size_t pt_offset = 0;
257 size_t to_process = data.size();
265 const size_t pt_size = std::min<size_t>(to_process, max_plaintext_size);
266 const size_t pt_size_with_type = pt_size + content_type_tag_length;
267 const bool final_record = (pt_size == to_process);
268 const size_t pt_size_with_type_and_padding = pt_size_with_type + (final_record ? final_record_padding : 0);
270 pt_size_with_type_and_padding <= m_outgoing_record_size_limit,
271 "Padded record size is within the negotiated record size limit");
273 const size_t ct_size = (!protect) ? pt_size : cipher_state->
encrypt_output_length(pt_size_with_type_and_padding);
280 const auto record_header = TLSPlaintext_Header(pt_type, ct_size, m_sending_compat_mode).serialized();
282 output.insert(output.end(), record_header.cbegin(), record_header.cend());
284 auto pt_fragment = data.subspan(pt_offset, pt_size);
287 fragment.reserve(ct_size);
290 fragment.insert(fragment.end(), pt_fragment.begin(), pt_fragment.end());
291 fragment.push_back(
static_cast<uint8_t
>(type));
297 fragment.insert(fragment.end(), pt_size_with_type_and_padding - pt_size_with_type, 0x00);
302 output.insert(output.end(), fragment.cbegin(), fragment.cend());
304 output.insert(output.end(), pt_fragment.begin(), pt_fragment.end());
307 pt_offset += pt_size;
308 to_process -= pt_size;
309 }
while(to_process > 0);
319 if(m_read_buffer.empty()) {
323 const auto remaining = m_read_buffer.size() - m_read_offset;
329 const auto header_begin = m_read_buffer.cbegin() + m_read_offset;
335 const TLSPlaintext_Header plaintext_header({header_begin, header_end}, !m_receiving_compat_mode);
349 throw TLS_Exception(Alert::UnexpectedMessage,
"unprotected record received where protected traffic was expected");
353 return TLS_HEADER_SIZE + plaintext_header.fragment_length() - remaining;
356 const auto fragment_begin = header_end;
357 const auto fragment_end = fragment_begin + plaintext_header.fragment_length();
360 !verify_change_cipher_spec(fragment_begin, plaintext_header.fragment_length())) {
361 throw TLS_Exception(Alert::UnexpectedMessage,
"malformed change cipher spec record received");
369 if(m_read_offset == m_read_buffer.size()) {
375 if(cipher_state ==
nullptr) {
378 throw TLS_Exception(Alert::UnexpectedMessage,
"premature Application Data received");
382 throw TLS_Exception(Alert::BadRecordMac,
"incomplete record mac received");
386 throw TLS_Exception(Alert::RecordOverflow,
"Received an encrypted record that exceeds maximum plaintext size");
394 uint8_t content_type_byte = 0;
395 size_t content_index = 0;
396 for(
size_t i = record.
fragment.size(); i-- > 0;) {
397 const uint8_t b = record.
fragment[i];
400 const auto first_nonzero = byte_is_nonzero & ~seen_nonzero;
401 content_type_byte = first_nonzero.select(b, content_type_byte);
403 seen_nonzero |= byte_is_nonzero;
406 if(!seen_nonzero.as_bool()) {
411 throw TLS_Exception(Alert::UnexpectedMessage,
"No content type found in encrypted record");
415 record.
type = read_record_type(content_type_byte);
421 throw TLS_Exception(Alert::UnexpectedMessage,
"protected change cipher spec received");
427 record.
fragment.resize(content_index);
436 "Received a protected record with empty TLSInnerPlaintext content");
444 BOTAN_ARG_CHECK(outgoing_limit >= 64,
"Invalid outgoing record size limit");
446 "Invalid incoming record size limit");
452 m_outgoing_record_size_limit = std::min(outgoing_limit,
static_cast<uint16_t
>(
MAX_PLAINTEXT_SIZE + 1));
453 m_incoming_record_size_limit = incoming_limit;
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ASSERT_NONNULL(ptr)
#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg)
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
static constexpr Mask< T > expand(T v)
static constexpr Mask< T > cleared()
uint64_t decrypt_record_fragment(const std::vector< uint8_t > &header, secure_vector< uint8_t > &encrypted_fragment)
size_t minimum_decryption_input_length() const
bool must_expect_unprotected_alert_traffic() const
uint64_t encrypt_record_fragment(const std::vector< uint8_t > &header, secure_vector< uint8_t > &fragment)
size_t encrypt_output_length(size_t input_length) const
size_t decrypt_output_length(size_t input_length) const
std::variant< BytesNeeded, ResT > ReadResult
void copy_data(std::span< const uint8_t > data_from_peer)
Record_Layer(Connection_Side side, std::shared_ptr< const Policy > policy)
std::vector< uint8_t > prepare_records(Record_Type type, std::span< const uint8_t > data, Cipher_State *cipher_state=nullptr) const
void set_record_size_limits(uint16_t outgoing_limit, uint16_t incoming_limit)
ReadResult< Record > next_record(Cipher_State *cipher_state=nullptr)
@ MAX_CIPHERTEXT_SIZE_TLS13
constexpr uint8_t get_byte(T input)
void zap(std::vector< T, Alloc > &vec)
std::vector< T, secure_allocator< T > > secure_vector
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
std::optional< uint64_t > seq_no
secure_vector< uint8_t > fragment