/* * TLS Record Handling * (C) 2004-2012 Jack Lloyd * 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_TLS_RECORDS_H_ #define BOTAN_TLS_RECORDS_H_ #include #include #include #include #include #include namespace Botan { namespace TLS { class Ciphersuite; class Session_Keys; class Connection_Sequence_Numbers; /** * TLS Cipher State */ class Connection_Cipher_State final { public: /** * Initialize a new 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); AEAD_Mode* aead() { return m_aead.get(); } std::vector aead_nonce(uint64_t seq, RandomNumberGenerator& rng); std::vector aead_nonce(const uint8_t record[], size_t record_len, uint64_t seq); std::vector format_ad(uint64_t seq, uint8_t type, Protocol_Version version, uint16_t ptext_length); size_t nonce_bytes_from_handshake() const { return m_nonce_bytes_from_handshake; } size_t nonce_bytes_from_record() const { return m_nonce_bytes_from_record; } bool cbc_nonce() const { return m_cbc_nonce; } std::chrono::seconds age() const { return std::chrono::duration_cast( std::chrono::system_clock::now() - m_start_time); } private: std::chrono::system_clock::time_point m_start_time; std::unique_ptr m_aead; std::vector m_nonce; size_t m_nonce_bytes_from_handshake; size_t m_nonce_bytes_from_record; bool m_cbc_nonce; }; class Record final { public: Record(secure_vector& data, uint64_t* sequence, Protocol_Version* protocol_version, Record_Type* type) : m_data(data), m_sequence(sequence), m_protocol_version(protocol_version), m_type(type), m_size(data.size()) {} secure_vector& get_data() { return m_data; } Protocol_Version* get_protocol_version() { return m_protocol_version; } uint64_t* get_sequence() { return m_sequence; } Record_Type* get_type() { return m_type; } size_t& get_size() { return m_size; } private: secure_vector& m_data; uint64_t* m_sequence; Protocol_Version* m_protocol_version; Record_Type* m_type; size_t m_size; }; class Record_Message final { public: Record_Message(const uint8_t* data, size_t size) : m_type(0), m_sequence(0), m_data(data), m_size(size) {} Record_Message(uint8_t type, uint64_t sequence, const uint8_t* data, size_t size) : m_type(type), m_sequence(sequence), m_data(data), m_size(size) {} uint8_t& get_type() { return m_type; } uint64_t& get_sequence() { return m_sequence; } const uint8_t* get_data() { return m_data; } size_t& get_size() { return m_size; } private: uint8_t m_type; uint64_t m_sequence; const uint8_t* m_data; size_t m_size; }; class Record_Raw_Input final { public: Record_Raw_Input(const uint8_t* data, size_t size, size_t& consumed, bool is_datagram) : m_data(data), m_size(size), m_consumed(consumed), m_is_datagram(is_datagram) {} const uint8_t*& get_data() { return m_data; } size_t& get_size() { return m_size; } size_t& get_consumed() { return m_consumed; } void set_consumed(size_t consumed) { m_consumed = consumed; } bool is_datagram() { return m_is_datagram; } private: const uint8_t* m_data; size_t m_size; size_t& m_consumed; bool m_is_datagram; }; /** * Create a TLS record * @param write_buffer the output record is placed here * @param rec_msg is the plaintext message * @param version is the protocol version * @param msg_sequence is the sequence number * @param cipherstate is the writing cipher state * @param rng is a random number generator */ void write_record(secure_vector& write_buffer, Record_Message rec_msg, Protocol_Version version, uint64_t msg_sequence, Connection_Cipher_State* cipherstate, RandomNumberGenerator& rng); // epoch -> cipher state typedef std::function (uint16_t)> get_cipherstate_fn; /** * Decode a TLS record * @return zero if full message, else number of bytes still needed */ size_t read_record(secure_vector& read_buffer, Record_Raw_Input& raw_input, Record& rec, Connection_Sequence_Numbers* sequence_numbers, get_cipherstate_fn get_cipherstate); } } #endif