• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/src/lib/tls/tls12/tls_handshake_io.h
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 {
22

23
namespace TLS {
24

25
class Handshake_Message;
26

27
/**
28
* Handshake IO Interface
29
*
30
* This interface abstracts over stream and datagram processing of handshake
31
* messages. It receives individual records from the channel via `add_record` and provides a
32
* sending interface via a callback function provided by the channel.
33
*
34
* Handshake message headers are parsed and removed in `get_next_record`. The
35
* result is provided back to the channel via
36
* `Handshake_State::get_next_handshake_msg`.
37
*
38
* `send` is used by individual handshake message implementations, which send
39
* themselves, as well as both client and server to dispatch CCS messaged (and
40
* Hello_Verify_Request in the server case). Before calling the `writer_fn`,
41
* `format` is called to add the handshake message header (except for CCS).
42
*
43
* The buffer returned by `send` is used to update the transcript record hash
44
* (where desired).
45
*/
46
class Handshake_IO {
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(const std::vector<uint8_t>& handshake_msg,
59
                                          Handshake_Type handshake_type) const = 0;
60

61
      virtual void add_record(const uint8_t record[],
62
                              size_t record_len,
63
                              Record_Type type,
64
                              uint64_t sequence_number) = 0;
65

66
      /**
67
      * Returns (HANDSHAKE_NONE, std::vector<>()) if no message currently available
68
      */
69
      virtual std::pair<Handshake_Type, std::vector<uint8_t>> get_next_record(bool expecting_ccs) = 0;
70

71
      Handshake_IO() = default;
4,042✔
72

73
      Handshake_IO(const Handshake_IO&) = delete;
74

75
      Handshake_IO& operator=(const Handshake_IO&) = delete;
76

77
      virtual ~Handshake_IO() = default;
78
};
79

80
/**
81
* Handshake IO for stream-based handshakes
82
*/
83
class Stream_Handshake_IO final : public Handshake_IO {
×
84
   public:
85
      typedef std::function<void(Record_Type, const std::vector<uint8_t>&)> writer_fn;
86

87
      explicit Stream_Handshake_IO(writer_fn writer) : m_send_hs(writer) {}
3,227✔
88

89
      Protocol_Version initial_record_version() const override;
90

91
      bool timeout_check() override { return false; }
7✔
92

93
      bool have_more_data() const override { return m_queue.empty() == false; }
2,072✔
94

95
      std::vector<uint8_t> send(const Handshake_Message& msg) override;
96

97
      std::vector<uint8_t> send_under_epoch(const Handshake_Message& msg, uint16_t epoch) override;
98

99
      std::vector<uint8_t> format(const std::vector<uint8_t>& handshake_msg,
100
                                  Handshake_Type handshake_type) const override;
101

102
      void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override;
103

104
      std::pair<Handshake_Type, std::vector<uint8_t>> get_next_record(bool expecting_ccs) override;
105

106
   private:
107
      std::deque<uint8_t> m_queue;
108
      writer_fn m_send_hs;
109
};
110

111
/**
112
* Handshake IO for datagram-based handshakes
113
*/
114
class Datagram_Handshake_IO final : public Handshake_IO {
×
115
   public:
116
      typedef std::function<void(uint16_t, Record_Type, const std::vector<uint8_t>&)> writer_fn;
117

118
      Datagram_Handshake_IO(writer_fn writer,
815✔
119
                            class Connection_Sequence_Numbers& seq,
120
                            uint16_t mtu,
121
                            uint64_t initial_timeout_ms,
122
                            uint64_t max_timeout_ms) :
815✔
123
            m_seqs(seq),
815✔
124
            m_flights(1),
815✔
125
            m_initial_timeout(initial_timeout_ms),
815✔
126
            m_max_timeout(max_timeout_ms),
815✔
127
            m_send_hs(writer),
815✔
128
            m_mtu(mtu) {}
815✔
129

130
      Protocol_Version initial_record_version() const override;
131

132
      bool timeout_check() override;
133

134
      bool have_more_data() const override;
135

136
      std::vector<uint8_t> send(const Handshake_Message& msg) override;
137

138
      std::vector<uint8_t> send_under_epoch(const Handshake_Message& msg, uint16_t epoch) override;
139

140
      std::vector<uint8_t> format(const std::vector<uint8_t>& handshake_msg,
141
                                  Handshake_Type handshake_type) const override;
142

143
      void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override;
144

145
      std::pair<Handshake_Type, std::vector<uint8_t>> get_next_record(bool expecting_ccs) override;
146

147
   private:
148
      void retransmit_flight(size_t flight);
149
      void retransmit_last_flight();
150

151
      std::vector<uint8_t> format_fragment(const uint8_t fragment[],
152
                                           size_t fragment_len,
153
                                           uint16_t frag_offset,
154
                                           uint16_t msg_len,
155
                                           Handshake_Type type,
156
                                           uint16_t msg_sequence) const;
157

158
      std::vector<uint8_t> format_w_seq(const std::vector<uint8_t>& handshake_msg,
159
                                        Handshake_Type handshake_type,
160
                                        uint16_t msg_sequence) const;
161

162
      std::vector<uint8_t> send_message(uint16_t msg_seq,
163
                                        uint16_t epoch,
164
                                        Handshake_Type msg_type,
165
                                        const std::vector<uint8_t>& msg);
166

167
      class Handshake_Reassembly final {
3,894✔
168
         public:
169
            void add_fragment(const uint8_t fragment[],
170
                              size_t fragment_length,
171
                              size_t fragment_offset,
172
                              uint16_t epoch,
173
                              Handshake_Type msg_type,
174
                              size_t msg_length);
175

176
            bool complete() const;
177

178
            uint16_t epoch() const { return m_epoch; }
1,578✔
179

180
            std::pair<Handshake_Type, std::vector<uint8_t>> message() const;
181

182
         private:
183
            Handshake_Type m_msg_type = Handshake_Type::None;
184
            size_t m_msg_length = 0;
185
            uint16_t m_epoch = 0;
186

187
            // vector<bool> m_seen;
188
            // vector<uint8_t> m_fragments
189
            std::map<size_t, uint8_t> m_fragments;
190
            std::vector<uint8_t> m_message;
191
      };
192

193
      struct Message_Info final {
9,654✔
194
            Message_Info(uint16_t e, Handshake_Type mt, const std::vector<uint8_t>& msg) :
3,308✔
195
                  epoch(e), msg_type(mt), msg_bits(msg) {}
3,308✔
196

197
            Message_Info() : epoch(0xFFFF), msg_type(Handshake_Type::None) {}
3,308✔
198

199
            uint16_t epoch;
200
            Handshake_Type msg_type;
201
            std::vector<uint8_t> msg_bits;
202
      };
203

204
      class Connection_Sequence_Numbers& m_seqs;
205
      std::map<uint16_t, Handshake_Reassembly> m_messages;
206
      std::set<uint16_t> m_ccs_epochs;
207
      std::vector<std::vector<uint16_t>> m_flights;
208
      std::map<uint16_t, Message_Info> m_flight_data;
209

210
      uint64_t m_initial_timeout = 0;
211
      uint64_t m_max_timeout = 0;
212

213
      uint64_t m_last_write = 0;
214
      uint64_t m_next_timeout = 0;
215

216
      uint16_t m_in_message_seq = 0;
217
      uint16_t m_out_message_seq = 0;
218

219
      writer_fn m_send_hs;
220
      uint16_t m_mtu;
221
};
222

223
}
224

225
}
226

227
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc