/* * TLS Record Handling * (C) 2004-2012 Jack Lloyd * * Released under the terms of the Botan license */ #ifndef BOTAN_TLS_RECORDS_H__ #define BOTAN_TLS_RECORDS_H__ #include #include #include #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 { 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); AEAD_Mode* aead() { return m_aead.get(); } const secure_vector& aead_nonce(u64bit seq); const secure_vector& aead_nonce(const byte record[], size_t record_len); const secure_vector& format_ad(u64bit seq, byte type, Protocol_Version version, u16bit ptext_length); BlockCipher* block_cipher() { return m_block_cipher.get(); } StreamCipher* stream_cipher() { return m_stream_cipher.get(); } MessageAuthenticationCode* mac() { return m_mac.get(); } secure_vector& cbc_state() { return m_block_cipher_cbc_state; } size_t block_size() const { return m_block_size; } size_t mac_size() const { return m_mac->output_length(); } size_t iv_size() const { return m_iv_size; } bool mac_includes_record_version() const { return !m_is_ssl3; } bool cipher_padding_single_byte() const { return m_is_ssl3; } bool cbc_without_explicit_iv() const { return (m_block_size > 0) && (m_iv_size == 0); } 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_block_cipher; secure_vector m_block_cipher_cbc_state; std::unique_ptr m_stream_cipher; std::unique_ptr m_mac; std::unique_ptr m_aead; secure_vector m_nonce, m_ad; size_t m_block_size = 0; size_t m_iv_size = 0; bool m_is_ssl3 = false; }; class Record { public: Record() {} Record(u64bit sequence, Protocol_Version version, Record_Type type, const byte contents[], size_t contents_size) : m_sequence(sequence), m_version(version), m_type(type), m_contents(contents, contents + contents_size) {} Record(u64bit sequence, Protocol_Version version, Record_Type type, std::vector&& contents) : m_sequence(sequence), m_version(version), m_type(type), m_contents(contents) {} bool is_valid() const { return m_type != NO_RECORD; } u64bit sequence() const { return m_sequence; } Record_Type type() const { return m_type; } Protocol_Version version() const { return m_version; } const std::vector& contents() const { return m_contents; } const byte* bits() const { return &m_contents[0]; } size_t size() const { return m_contents.size(); } private: u64bit m_sequence = 0; Protocol_Version m_version = Protocol_Version(); Record_Type m_type = NO_RECORD; std::vector m_contents; }; /** * Create a TLS record * @param write_buffer the output record is placed here * @param msg_type is the type of the message (handshake, alert, ...) * @param msg is the plaintext message * @param msg_length is the length of msg * @param msg_sequence is the sequence number * @param version is the protocol version * @param cipherstate is the writing cipher state * @param rng is a random number generator * @return number of bytes written to write_buffer */ void write_record(secure_vector& write_buffer, byte msg_type, const byte msg[], size_t msg_length, Protocol_Version version, u64bit msg_sequence, Connection_Cipher_State* cipherstate, RandomNumberGenerator& rng); /** * Decode a TLS record * @return zero if full message, else number of bytes still needed */ size_t read_record(secure_vector& read_buffer, const byte input[], size_t input_length, size_t& input_consumed, Record& output_record, Connection_Sequence_Numbers* sequence_numbers, std::function get_cipherstate); } } #endif