/* * TLS Handshake Serialization * (C) 2012,2014 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_TLS_HANDSHAKE_IO_H_ #define BOTAN_TLS_HANDSHAKE_IO_H_ #include #include #include #include #include #include #include #include namespace Botan { namespace TLS { class Handshake_Message; /** * Handshake IO Interface */ class Handshake_IO { public: virtual Protocol_Version initial_record_version() const = 0; virtual std::vector send(const Handshake_Message& msg) = 0; virtual std::vector send_under_epoch(const Handshake_Message& msg, uint16_t epoch) = 0; virtual bool timeout_check() = 0; virtual std::vector format( const std::vector& handshake_msg, Handshake_Type handshake_type) const = 0; virtual void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) = 0; /** * Returns (HANDSHAKE_NONE, std::vector<>()) if no message currently available */ virtual std::pair> get_next_record(bool expecting_ccs) = 0; Handshake_IO() = default; Handshake_IO(const Handshake_IO&) = delete; Handshake_IO& operator=(const Handshake_IO&) = delete; virtual ~Handshake_IO() = default; }; /** * Handshake IO for stream-based handshakes */ class Stream_Handshake_IO final : public Handshake_IO { public: typedef std::function&)> writer_fn; explicit Stream_Handshake_IO(writer_fn writer) : m_send_hs(writer) {} Protocol_Version initial_record_version() const override; bool timeout_check() override { return false; } std::vector send(const Handshake_Message& msg) override; std::vector send_under_epoch(const Handshake_Message& msg, uint16_t epoch) override; std::vector format( const std::vector& handshake_msg, Handshake_Type handshake_type) const override; void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override; std::pair> get_next_record(bool expecting_ccs) override; private: std::deque m_queue; writer_fn m_send_hs; }; /** * Handshake IO for datagram-based handshakes */ class Datagram_Handshake_IO final : public Handshake_IO { public: typedef std::function&)> writer_fn; Datagram_Handshake_IO(writer_fn writer, class Connection_Sequence_Numbers& seq, uint16_t mtu, uint64_t initial_timeout_ms, uint64_t max_timeout_ms) : m_seqs(seq), m_flights(1), m_initial_timeout(initial_timeout_ms), m_max_timeout(max_timeout_ms), m_send_hs(writer), m_mtu(mtu) {} Protocol_Version initial_record_version() const override; bool timeout_check() override; std::vector send(const Handshake_Message& msg) override; std::vector send_under_epoch(const Handshake_Message& msg, uint16_t epoch) override; std::vector format( const std::vector& handshake_msg, Handshake_Type handshake_type) const override; void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override; std::pair> get_next_record(bool expecting_ccs) override; private: void retransmit_flight(size_t flight); void retransmit_last_flight(); std::vector format_fragment( const uint8_t fragment[], size_t fragment_len, uint16_t frag_offset, uint16_t msg_len, Handshake_Type type, uint16_t msg_sequence) const; std::vector format_w_seq( const std::vector& handshake_msg, Handshake_Type handshake_type, uint16_t msg_sequence) const; std::vector send_message(uint16_t msg_seq, uint16_t epoch, Handshake_Type msg_type, const std::vector& msg); class Handshake_Reassembly final { public: void add_fragment(const uint8_t fragment[], size_t fragment_length, size_t fragment_offset, uint16_t epoch, uint8_t msg_type, size_t msg_length); bool complete() const; uint16_t epoch() const { return m_epoch; } std::pair> message() const; private: uint8_t m_msg_type = HANDSHAKE_NONE; size_t m_msg_length = 0; uint16_t m_epoch = 0; // vector m_seen; // vector m_fragments std::map m_fragments; std::vector m_message; }; struct Message_Info final { Message_Info(uint16_t e, Handshake_Type mt, const std::vector& msg) : epoch(e), msg_type(mt), msg_bits(msg) {} Message_Info() : epoch(0xFFFF), msg_type(HANDSHAKE_NONE) {} uint16_t epoch; Handshake_Type msg_type; std::vector msg_bits; }; class Connection_Sequence_Numbers& m_seqs; std::map m_messages; std::set m_ccs_epochs; std::vector> m_flights; std::map m_flight_data; uint64_t m_initial_timeout = 0; uint64_t m_max_timeout = 0; uint64_t m_last_write = 0; uint64_t m_next_timeout = 0; uint16_t m_in_message_seq = 0; uint16_t m_out_message_seq = 0; writer_fn m_send_hs; uint16_t m_mtu; }; } } #endif