10#include <botan/internal/tls_record.h>
12#include <botan/aead.h>
13#include <botan/block_cipher.h>
16#include <botan/tls_ciphersuite.h>
17#include <botan/tls_exceptn.h>
18#include <botan/internal/fmt.h>
19#include <botan/internal/loadstor.h>
20#include <botan/internal/tls_seq_numbers.h>
21#include <botan/internal/tls_session_key.h>
23#if defined(BOTAN_HAS_TLS_CBC)
24 #include <botan/internal/tls_cbc.h>
27#if defined(BOTAN_HAS_TLS_NULL)
28 #include <botan/internal/tls_null.h>
40 bool uses_encrypt_then_mac) {
47 m_nonce = keys.
nonce(side);
53#if defined(BOTAN_HAS_TLS_CBC)
59 m_aead = std::make_unique<TLS_CBC_HMAC_AEAD_Encryption>(std::move(cipher),
64 uses_encrypt_then_mac);
66 m_aead = std::make_unique<TLS_CBC_HMAC_AEAD_Decryption>(std::move(cipher),
71 uses_encrypt_then_mac);
76 throw Internal_Error(
"Negotiated disabled TLS CBC+HMAC ciphersuite");
79#if defined(BOTAN_HAS_TLS_NULL)
83 m_aead = std::make_unique<TLS_NULL_HMAC_AEAD_Encryption>(std::move(mac), suite.
mac_keylen());
85 m_aead = std::make_unique<TLS_NULL_HMAC_AEAD_Decryption>(std::move(mac), suite.
mac_keylen());
95 m_aead->set_key(aead_key);
99 switch(m_nonce_format) {
101 return std::vector<uint8_t>{};
104 if(!m_nonce.empty()) {
105 std::vector<uint8_t> nonce;
110 rng.
randomize(nonce.data(), nonce.size());
114 std::vector<uint8_t> nonce(12);
116 xor_buf(nonce, m_nonce.data(), m_nonce.size());
121 std::vector<uint8_t> nonce(12);
122 copy_mem(&nonce[0], m_nonce.data(), 4);
132 switch(m_nonce_format) {
134 return std::vector<uint8_t>{};
138 std::vector<uint8_t> nonce;
149 std::vector<uint8_t> nonce(12);
151 xor_buf(nonce, m_nonce.data(), m_nonce.size());
157 throw Decoding_Error(
"Invalid AEAD packet too short to be valid");
159 std::vector<uint8_t> nonce(12);
160 copy_mem(&nonce[0], m_nonce.data(), 4);
172 uint16_t msg_length) {
173 std::vector<uint8_t> ad(13);
176 ad[8] =
static_cast<uint8_t
>(msg_type);
188 const uint16_t len16 =
static_cast<uint16_t
>(len_field);
196 Protocol_Version version,
197 uint64_t record_sequence) {
200 output.push_back(
static_cast<uint8_t
>(record_type));
201 output.push_back(version.major_version());
202 output.push_back(version.minor_version());
204 if(version.is_datagram_protocol()) {
205 for(
size_t i = 0; i != 8; ++i) {
216 uint64_t record_sequence,
217 const uint8_t* message,
218 size_t message_len) {
220 throw Internal_Error(
"Writing an unencrypted TLS application data record");
222 write_record_header(output, record_type, version, record_sequence);
223 append_u16_len(output, message_len);
224 output.insert(output.end(), message, message + message_len);
230 uint64_t record_sequence,
231 const uint8_t* message,
235 write_record_header(output, record_type, version, record_sequence);
238 std::vector<uint8_t> aad = cs.
format_ad(record_sequence, record_type, version,
static_cast<uint16_t
>(message_len));
246 const std::vector<uint8_t> nonce = cs.
aead_nonce(record_sequence, rng);
248 append_u16_len(output, rec_size);
258 const size_t header_size = output.size();
259 output += std::make_pair(message, message_len);
262 aead.
finish(output, header_size);
269size_t fill_buffer_to(
270 secure_vector<uint8_t>& readbuf,
const uint8_t*& input,
size_t& input_size,
size_t& input_consumed,
size_t desired) {
271 if(readbuf.size() >= desired) {
275 const size_t taken = std::min(input_size, desired - readbuf.size());
277 readbuf.insert(readbuf.end(), input, input + taken);
278 input_consumed += taken;
282 return (desired - readbuf.size());
286 uint8_t record_contents[],
288 uint64_t record_sequence,
292 AEAD_Mode& aead = cs.aead();
294 const std::vector<uint8_t> nonce = cs.aead_nonce(record_contents, record_len, record_sequence);
295 const uint8_t* msg = &record_contents[cs.nonce_bytes_from_record()];
296 const size_t msg_length = record_len - cs.nonce_bytes_from_record();
305 if(msg_length < aead.minimum_final_size()) {
306 throw TLS_Exception(Alert::BadRecordMac,
"AEAD packet is shorter than the tag");
309 const size_t ptext_size = aead.output_length(msg_length);
311 aead.set_associated_data(
312 cs.format_ad(record_sequence, record_type, record_version,
static_cast<uint16_t
>(ptext_size)));
316 output.assign(msg, msg + msg_length);
317 aead.finish(output, 0);
321 const uint8_t input[],
329 if(
const size_t needed = fill_buffer_to(readbuf, input, input_len, consumed,
TLS_HEADER_SIZE)) {
348 const bool bad_record_type = readbuf[0] < 20 || readbuf[0] > 23;
349 const bool bad_record_version = readbuf[1] != 3 || readbuf[2] >= 4;
351 if(bad_record_type || bad_record_version) {
353 const std::string first5 = std::string(
reinterpret_cast<const char*
>(readbuf.data()), 5);
355 if(first5 ==
"GET /" || first5 ==
"PUT /" || first5 ==
"POST " || first5 ==
"HEAD ") {
356 throw TLS_Exception(Alert::ProtocolVersion,
"Client sent plaintext HTTP request instead of TLS handshake");
359 if(first5 ==
"CONNE") {
361 "Client sent plaintext HTTP proxy CONNECT request instead of TLS handshake");
364 if(bad_record_type) {
368 throw TLS_Exception(Alert::UnexpectedMessage,
"TLS record type had unexpected value");
370 throw TLS_Exception(Alert::ProtocolVersion,
"TLS record version had unexpected value");
375 if(version.is_datagram_protocol()) {
376 throw TLS_Exception(Alert::ProtocolVersion,
"Expected TLS but got a record with DTLS version");
382 throw TLS_Exception(Alert::RecordOverflow,
"Received a record that exceeds maximum size");
385 if(record_size == 0) {
386 throw TLS_Exception(Alert::DecodeError,
"Received a completely empty record");
389 if(
const size_t needed = fill_buffer_to(readbuf, input, input_len, consumed,
TLS_HEADER_SIZE + record_size)) {
399 uint64_t sequence = 0;
400 if(sequence_numbers !=
nullptr) {
401 sequence = sequence_numbers->next_read_sequence();
402 epoch = sequence_numbers->current_read_epoch();
416 auto cs = get_cipherstate(epoch);
420 decrypt_record(recbuf, &readbuf[
TLS_HEADER_SIZE], record_size, sequence, version, type, *cs);
422 if(sequence_numbers !=
nullptr) {
423 sequence_numbers->read_accept(sequence);
431 const uint8_t input[],
437 bool allow_epoch0_restart) {
440 if(fill_buffer_to(readbuf, input, input_len, consumed,
DTLS_HEADER_SIZE) != 0) {
450 if(version.is_datagram_protocol() ==
false) {
463 if(fill_buffer_to(readbuf, input, input_len, consumed,
DTLS_HEADER_SIZE + record_size) != 0) {
474 const uint16_t epoch = (sequence >> 48);
476 const bool already_seen = sequence_numbers !=
nullptr && sequence_numbers->already_seen(sequence);
478 if(already_seen && !(epoch == 0 && allow_epoch0_restart)) {
487 if(sequence_numbers !=
nullptr) {
488 sequence_numbers->read_accept(sequence);
495 auto cs = get_cipherstate(epoch);
499 decrypt_record(recbuf, &readbuf[
DTLS_HEADER_SIZE], record_size, sequence, version, type, *cs);
500 }
catch(std::exception&) {
505 if(sequence_numbers !=
nullptr) {
506 sequence_numbers->read_accept(sequence);
517 const uint8_t input[],
523 bool allow_epoch0_restart) {
525 return read_dtls_record(
526 readbuf, input, input_len, consumed, recbuf, sequence_numbers, get_cipherstate, allow_epoch0_restart);
528 return read_tls_record(readbuf, input, input_len, consumed, recbuf, sequence_numbers, get_cipherstate);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
#define BOTAN_ASSERT(expr, assertion_made)
void set_associated_data(std::span< const uint8_t > ad)
static std::unique_ptr< AEAD_Mode > create_or_throw(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
static std::unique_ptr< BlockCipher > create_or_throw(std::string_view algo_spec, std::string_view provider="")
void start(std::span< const uint8_t > nonce)
void finish(secure_vector< uint8_t > &final_block, size_t offset=0)
virtual size_t output_length(size_t input_length) const =0
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(std::string_view algo_spec, std::string_view provider="")
void randomize(std::span< uint8_t > output)
size_t nonce_bytes_from_record(Protocol_Version version) const
Nonce_Format nonce_format() const
size_t mac_keylen() const
size_t cipher_keylen() const
size_t nonce_bytes_from_handshake() const
std::string mac_algo() const
std::string cipher_algo() const
size_t nonce_bytes_from_record() const
Nonce_Format nonce_format() const
size_t nonce_bytes_from_handshake() const
~Connection_Cipher_State()
Connection_Cipher_State(Protocol_Version version, Connection_Side which_side, bool is_our_side, const Ciphersuite &suite, const Session_Keys &keys, bool uses_encrypt_then_mac)
std::vector< uint8_t > aead_nonce(uint64_t seq, RandomNumberGenerator &rng)
std::vector< uint8_t > format_ad(uint64_t seq, Record_Type type, Protocol_Version version, uint16_t ptext_length)
uint8_t major_version() const
uint8_t minor_version() const
const std::vector< uint8_t > & nonce(Connection_Side side) const
const secure_vector< uint8_t > & aead_key(Connection_Side side) const
Record_Header read_record(bool is_datagram, secure_vector< uint8_t > &readbuf, const uint8_t input[], size_t input_len, size_t &consumed, secure_vector< uint8_t > &recbuf, Connection_Sequence_Numbers *sequence_numbers, const get_cipherstate_fn &get_cipherstate, bool allow_epoch0_restart)
void write_unencrypted_record(secure_vector< uint8_t > &output, Record_Type record_type, Protocol_Version version, uint64_t record_sequence, const uint8_t *message, size_t message_len)
std::function< std::shared_ptr< Connection_Cipher_State >(uint16_t)> get_cipherstate_fn
void write_record(secure_vector< uint8_t > &output, Record_Type record_type, Protocol_Version version, uint64_t record_sequence, const uint8_t *message, size_t message_len, Connection_Cipher_State &cs, RandomNumberGenerator &rng)
constexpr uint8_t get_byte(T input)
constexpr void copy_mem(T *out, const T *in, size_t n)
std::string fmt(std::string_view format, const T &... args)
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
std::vector< T, secure_allocator< T > > secure_vector
constexpr uint8_t get_byte_var(size_t byte_num, T input)
constexpr auto store_be(ParamTs &&... params)
constexpr auto load_be(ParamTs &&... params)
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)