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