Botan 3.3.0
Crypto and TLS for C&
tls_handshake_io.h
Go to the documentation of this file.
1/*
2* TLS Handshake Serialization
3* (C) 2012,2014 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#ifndef BOTAN_TLS_HANDSHAKE_IO_H_
9#define BOTAN_TLS_HANDSHAKE_IO_H_
10
11#include <botan/tls_magic.h>
12#include <botan/tls_version.h>
13#include <botan/internal/tls_channel_impl.h>
14#include <deque>
15#include <functional>
16#include <map>
17#include <set>
18#include <utility>
19#include <vector>
20
21namespace Botan::TLS {
22
23class Handshake_Message;
24
25/**
26* Handshake IO Interface
27*
28* This interface abstracts over stream and datagram processing of handshake
29* messages. It receives individual records from the channel via `add_record` and provides a
30* sending interface via a callback function provided by the channel.
31*
32* Handshake message headers are parsed and removed in `get_next_record`. The
33* result is provided back to the channel via
34* `Handshake_State::get_next_handshake_msg`.
35*
36* `send` is used by individual handshake message implementations, which send
37* themselves, as well as both client and server to dispatch CCS messaged (and
38* Hello_Verify_Request in the server case). Before calling the `writer_fn`,
39* `format` is called to add the handshake message header (except for CCS).
40*
41* The buffer returned by `send` is used to update the transcript record hash
42* (where desired).
43*/
45 public:
47
48 virtual std::vector<uint8_t> send(const Handshake_Message& msg) = 0;
49
50 virtual std::vector<uint8_t> send_under_epoch(const Handshake_Message& msg, uint16_t epoch) = 0;
51
52 virtual bool timeout_check() = 0;
53
54 virtual bool have_more_data() const = 0;
55
56 virtual std::vector<uint8_t> format(const std::vector<uint8_t>& handshake_msg,
57 Handshake_Type handshake_type) const = 0;
58
59 virtual void add_record(const uint8_t record[],
60 size_t record_len,
61 Record_Type type,
62 uint64_t sequence_number) = 0;
63
64 /**
65 * Returns (HANDSHAKE_NONE, std::vector<>()) if no message currently available
66 */
67 virtual std::pair<Handshake_Type, std::vector<uint8_t>> get_next_record(bool expecting_ccs) = 0;
68
69 Handshake_IO() = default;
70
71 Handshake_IO(const Handshake_IO&) = delete;
72
74
75 virtual ~Handshake_IO() = default;
76};
77
78/**
79* Handshake IO for stream-based handshakes
80*/
82 public:
83 typedef std::function<void(Record_Type, const std::vector<uint8_t>&)> writer_fn;
84
85 explicit Stream_Handshake_IO(writer_fn writer) : m_send_hs(writer) {}
86
88
89 bool timeout_check() override { return false; }
90
91 bool have_more_data() const override { return m_queue.empty() == false; }
92
93 std::vector<uint8_t> send(const Handshake_Message& msg) override;
94
95 std::vector<uint8_t> send_under_epoch(const Handshake_Message& msg, uint16_t epoch) override;
96
97 std::vector<uint8_t> format(const std::vector<uint8_t>& handshake_msg,
98 Handshake_Type handshake_type) const override;
99
100 void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override;
101
102 std::pair<Handshake_Type, std::vector<uint8_t>> get_next_record(bool expecting_ccs) override;
103
104 private:
105 std::deque<uint8_t> m_queue;
106 writer_fn m_send_hs;
107};
108
109/**
110* Handshake IO for datagram-based handshakes
111*/
113 public:
114 typedef std::function<void(uint16_t, Record_Type, const std::vector<uint8_t>&)> writer_fn;
115
118 uint16_t mtu,
119 uint64_t initial_timeout_ms,
120 uint64_t max_timeout_ms) :
121 m_seqs(seq),
122 m_flights(1),
123 m_initial_timeout(initial_timeout_ms),
124 m_max_timeout(max_timeout_ms),
125 m_send_hs(writer),
126 m_mtu(mtu) {}
127
129
130 bool timeout_check() override;
131
132 bool have_more_data() const override;
133
134 std::vector<uint8_t> send(const Handshake_Message& msg) override;
135
136 std::vector<uint8_t> send_under_epoch(const Handshake_Message& msg, uint16_t epoch) override;
137
138 std::vector<uint8_t> format(const std::vector<uint8_t>& handshake_msg,
139 Handshake_Type handshake_type) const override;
140
141 void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override;
142
143 std::pair<Handshake_Type, std::vector<uint8_t>> get_next_record(bool expecting_ccs) override;
144
145 private:
146 void retransmit_flight(size_t flight);
147 void retransmit_last_flight();
148
149 std::vector<uint8_t> format_fragment(const uint8_t fragment[],
150 size_t fragment_len,
151 uint16_t frag_offset,
152 uint16_t msg_len,
153 Handshake_Type type,
154 uint16_t msg_sequence) const;
155
156 std::vector<uint8_t> format_w_seq(const std::vector<uint8_t>& handshake_msg,
157 Handshake_Type handshake_type,
158 uint16_t msg_sequence) const;
159
160 std::vector<uint8_t> send_message(uint16_t msg_seq,
161 uint16_t epoch,
162 Handshake_Type msg_type,
163 const std::vector<uint8_t>& msg);
164
165 class Handshake_Reassembly final {
166 public:
167 void add_fragment(const uint8_t fragment[],
168 size_t fragment_length,
169 size_t fragment_offset,
170 uint16_t epoch,
171 Handshake_Type msg_type,
172 size_t msg_length);
173
174 bool complete() const;
175
176 uint16_t epoch() const { return m_epoch; }
177
178 std::pair<Handshake_Type, std::vector<uint8_t>> message() const;
179
180 private:
182 size_t m_msg_length = 0;
183 uint16_t m_epoch = 0;
184
185 // vector<bool> m_seen;
186 // vector<uint8_t> m_fragments
187 std::map<size_t, uint8_t> m_fragments;
188 std::vector<uint8_t> m_message;
189 };
190
191 struct Message_Info final {
192 Message_Info(uint16_t e, Handshake_Type mt, const std::vector<uint8_t>& msg) :
193 epoch(e), msg_type(mt), msg_bits(msg) {}
194
195 Message_Info() : epoch(0xFFFF), msg_type(Handshake_Type::None) {}
196
197 uint16_t epoch;
198 Handshake_Type msg_type;
199 std::vector<uint8_t> msg_bits;
200 };
201
202 class Connection_Sequence_Numbers& m_seqs;
203 std::map<uint16_t, Handshake_Reassembly> m_messages;
204 std::set<uint16_t> m_ccs_epochs;
205 std::vector<std::vector<uint16_t>> m_flights;
206 std::map<uint16_t, Message_Info> m_flight_data;
207
208 uint64_t m_initial_timeout = 0;
209 uint64_t m_max_timeout = 0;
210
211 uint64_t m_last_write = 0;
212 uint64_t m_next_timeout = 0;
213
214 uint16_t m_in_message_seq = 0;
215 uint16_t m_out_message_seq = 0;
216
217 writer_fn m_send_hs;
218 uint16_t m_mtu;
219};
220
221} // namespace Botan::TLS
222
223#endif
std::vector< uint8_t > send_under_epoch(const Handshake_Message &msg, uint16_t epoch) override
std::function< void(uint16_t, Record_Type, const std::vector< uint8_t > &) writer_fn)
void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override
std::pair< Handshake_Type, std::vector< uint8_t > > get_next_record(bool expecting_ccs) override
std::vector< uint8_t > format(const std::vector< uint8_t > &handshake_msg, Handshake_Type handshake_type) const override
Protocol_Version initial_record_version() const override
std::vector< uint8_t > send(const Handshake_Message &msg) override
Datagram_Handshake_IO(writer_fn writer, class Connection_Sequence_Numbers &seq, uint16_t mtu, uint64_t initial_timeout_ms, uint64_t max_timeout_ms)
virtual std::vector< uint8_t > send_under_epoch(const Handshake_Message &msg, uint16_t epoch)=0
Handshake_IO(const Handshake_IO &)=delete
virtual bool timeout_check()=0
virtual std::vector< uint8_t > send(const Handshake_Message &msg)=0
Handshake_IO & operator=(const Handshake_IO &)=delete
virtual void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number)=0
virtual Protocol_Version initial_record_version() const =0
virtual std::vector< uint8_t > format(const std::vector< uint8_t > &handshake_msg, Handshake_Type handshake_type) const =0
virtual ~Handshake_IO()=default
virtual bool have_more_data() const =0
virtual std::pair< Handshake_Type, std::vector< uint8_t > > get_next_record(bool expecting_ccs)=0
bool have_more_data() const override
std::vector< uint8_t > send_under_epoch(const Handshake_Message &msg, uint16_t epoch) override
std::function< void(Record_Type, const std::vector< uint8_t > &) writer_fn)
std::vector< uint8_t > format(const std::vector< uint8_t > &handshake_msg, Handshake_Type handshake_type) const override
Protocol_Version initial_record_version() const override
std::pair< Handshake_Type, std::vector< uint8_t > > get_next_record(bool expecting_ccs) override
std::vector< uint8_t > send(const Handshake_Message &msg) override
void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override
int(* final)(unsigned char *, CTX *)