Coverage Report

Created: 2025-04-11 06:34

/src/botan/build/include/internal/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 <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
21
namespace Botan::TLS {
22
23
class 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
*/
44
class Handshake_IO {
45
   public:
46
      virtual Protocol_Version initial_record_version() const = 0;
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
29.4k
      Handshake_IO() = default;
70
71
      Handshake_IO(const Handshake_IO&) = delete;
72
73
      Handshake_IO& operator=(const Handshake_IO&) = delete;
74
75
29.4k
      virtual ~Handshake_IO() = default;
76
};
77
78
/**
79
* Handshake IO for stream-based handshakes
80
*/
81
class Stream_Handshake_IO final : public Handshake_IO {
82
   public:
83
      typedef std::function<void(Record_Type, const std::vector<uint8_t>&)> writer_fn;
84
85
28.6k
      explicit Stream_Handshake_IO(writer_fn writer) : m_send_hs(writer) {}
86
87
      Protocol_Version initial_record_version() const override;
88
89
0
      bool timeout_check() override { return false; }
90
91
27.1k
      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
*/
112
class Datagram_Handshake_IO final : public Handshake_IO {
113
   public:
114
      typedef std::function<void(uint16_t, Record_Type, const std::vector<uint8_t>&)> writer_fn;
115
116
      Datagram_Handshake_IO(writer_fn writer,
117
                            class Connection_Sequence_Numbers& seq,
118
                            uint16_t mtu,
119
                            uint64_t initial_timeout_ms,
120
                            uint64_t max_timeout_ms) :
121
805
            m_seqs(seq),
122
805
            m_flights(1),
123
805
            m_initial_timeout(initial_timeout_ms),
124
805
            m_max_timeout(max_timeout_ms),
125
805
            m_send_hs(writer),
126
805
            m_mtu(mtu) {}
127
128
      Protocol_Version initial_record_version() const override;
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
0
            uint16_t epoch() const { return m_epoch; }
177
178
            std::pair<Handshake_Type, std::vector<uint8_t>> message() const;
179
180
         private:
181
            Handshake_Type m_msg_type = Handshake_Type::None;
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
37
                  epoch(e), msg_type(mt), msg_bits(msg) {}
194
195
37
            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