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

randombit / botan / 5587580523

18 Jul 2023 12:45PM UTC coverage: 91.72% (+0.03%) from 91.691%
5587580523

Pull #3618

github

web-flow
Merge b6d23d19e into 65b754862
Pull Request #3618: [TLS 1.3] PSK Support

78438 of 85519 relevant lines covered (91.72%)

12184016.91 hits per line

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

93.75
/src/lib/tls/tls_channel_impl.h
1
/*
2
* TLS Channel
3
* (C) 2011,2012,2014,2015 Jack Lloyd
4
*     2016 Matthias Gierlings
5
*     2021 Elektrobit Automotive GmbH
6
*     2022 René Meusel, Hannes Rantzsch - neXenio GmbH
7
*
8
* Botan is released under the Simplified BSD License (see license.txt)
9
*/
10

11
#ifndef BOTAN_TLS_CHANNEL_IMPL_H_
12
#define BOTAN_TLS_CHANNEL_IMPL_H_
13

14
#include <botan/tls_channel.h>
15
#include <botan/tls_magic.h>
16
#include <botan/tls_version.h>
17

18
#include <memory>
19
#include <utility>
20
#include <vector>
21

22
namespace Botan {
23

24
class Credentials_Manager;
25
class X509_Certificate;
26

27
namespace TLS {
28

29
class Client;
30
class Server;
31

32
enum class Record_Type : uint8_t {
33
   Invalid = 0,  // RFC 8446 (TLS 1.3)
34

35
   ChangeCipherSpec = 20,
36
   Alert = 21,
37
   Handshake = 22,
38
   ApplicationData = 23,
39

40
   Heartbeat = 24,  // RFC 6520 (TLS 1.3)
41
};
42

43
class Channel_Impl {
7,093✔
44
   public:
45
      virtual ~Channel_Impl() = default;
7,075✔
46

47
      /**
48
      * Inject TLS traffic received from counterparty
49
      * @return a hint as the how many more bytes we need to q the
50
      *         current record (this may be 0 if on a record boundary)
51
      */
52
      virtual size_t from_peer(std::span<const uint8_t> data) = 0;
53

54
      /**
55
      * Inject plaintext intended for counterparty
56
      * Throws an exception if is_active() is false
57
      */
58
      virtual void to_peer(std::span<const uint8_t> data) = 0;
59

60
      /**
61
      * Send a TLS alert message. If the alert is fatal, the internal
62
      * state (keys, etc) will be reset.
63
      * @param alert the Alert to send
64
      */
65
      virtual void send_alert(const Alert& alert) = 0;
66

67
      /**
68
      * Send a warning alert
69
      */
70
      void send_warning_alert(Alert::Type type) { send_alert(Alert(type, false)); }
2,861✔
71

72
      /**
73
      * Send a fatal alert
74
      */
75
      void send_fatal_alert(Alert::Type type) { send_alert(Alert(type, true)); }
3,819✔
76

77
      /**
78
      * Send a close notification alert
79
      */
80
      void close() { send_warning_alert(Alert::CloseNotify); }
758✔
81

82
      /**
83
      * @return true iff the connection is active for sending application data
84
      */
85
      virtual bool is_active() const = 0;
86

87
      /**
88
      * @return true iff the connection has been definitely closed
89
      */
90
      virtual bool is_closed() const = 0;
91

92
      /**
93
      * @return true iff the connection is active for sending application data
94
      */
95
      virtual bool is_closed_for_reading() const = 0;
96

97
      /**
98
      * @return true iff the connection has been definitely closed
99
      */
100
      virtual bool is_closed_for_writing() const = 0;
101

102
      /**
103
      * @return certificate chain of the peer (may be empty)
104
      */
105
      virtual std::vector<X509_Certificate> peer_cert_chain() const = 0;
106

107
      /**
108
       * @return identity of the PSK used for this connection
109
       *         or std::nullopt if no PSK was used.
110
       */
111
      virtual std::optional<std::string> external_psk_identity() const = 0;
112

113
      /**
114
      * Key material export (RFC 5705)
115
      * @param label a disambiguating label string
116
      * @param context a per-association context value
117
      * @param length the length of the desired key in bytes
118
      * @return key of length bytes
119
      */
120
      virtual SymmetricKey key_material_export(std::string_view label,
121
                                               std::string_view context,
122
                                               size_t length) const = 0;
123

124
      /**
125
      * Attempt to renegotiate the session
126
      * @param force_full_renegotiation if true, require a full renegotiation,
127
      * otherwise allow session resumption
128
      */
129
      virtual void renegotiate(bool force_full_renegotiation = false) = 0;
130

131
      /**
132
      * @return true if this channel can issue TLS 1.3 style session tickets.
133
      */
134
      virtual bool new_session_ticket_supported() const { return false; }
×
135

136
      /**
137
      * Send @p tickets new session tickets to the peer. This is only supported
138
      * on TLS 1.3 servers.
139
      *
140
      * If the server's Session_Manager does not accept the generated Session
141
      * objects, the server implementation won't be able to send new tickets.
142
      * Additionally, anything but TLS 1.3 servers will return 0 (because they
143
      * don't support sending such session tickets).
144
      *
145
      * @returns the number of session tickets successfully sent to the client
146
      */
147
      virtual size_t send_new_session_tickets(const size_t /* tickets */) { return 0; }
×
148

149
      /**
150
      * Attempt to update the session's traffic key material
151
      * Note that this is possible with a TLS 1.3 channel, only.
152
      *
153
      * @param request_peer_update if true, require a reciprocal key update
154
      */
155
      virtual void update_traffic_keys(bool request_peer_update = false) = 0;
156

157
      /**
158
      * @return true iff the counterparty supports the secure
159
      * renegotiation extensions.
160
      */
161
      virtual bool secure_renegotiation_supported() const = 0;
162

163
      /**
164
      * Perform a handshake timeout check. This does nothing unless
165
      * this is a DTLS channel with a pending handshake state, in
166
      * which case we check for timeout and potentially retransmit
167
      * handshake packets.
168
      */
169
      virtual bool timeout_check() = 0;
170

171
      /**
172
      * Return the protocol notification set for this connection, if any (ALPN).
173
      * This value is not tied to the session and a later renegotiation of the
174
      * same session can choose a new protocol.
175
      */
176
      virtual std::string application_protocol() const = 0;
177

178
   protected:
179
      /**
180
       * This struct collect all information required to perform a downgrade from TLS 1.3 to TLS 1.2.
181
       *
182
       * The downgrade process is (currently) triggered when a TLS 1.3 client receives a downgrade request
183
       * in the server hello message (@sa `Client_Impl_13::handle(Server_Hello_12)`). As a result,
184
       * `Client::received_data` should detect this condition and replace its `Channel_Impl_13` member by a
185
       * `Channel_Impl_12`.
186
       *
187
       * Note that the downgrade process for the server implementation will likely differ.
188
       */
189
      struct Downgrade_Information {
190
            /// The client hello message including the handshake header bytes as transferred to the peer.
191
            std::vector<uint8_t> client_hello_message;
192

193
            /// The full data transcript received from the peer. This will contain the server hello message that forced us to downgrade.
194
            std::vector<uint8_t> peer_transcript;
195

196
            /// The TLS 1.2 session information found by a TLS 1.3 client that
197
            /// caused it to initiate a downgrade before even sending a client hello.
198
            std::optional<Session_with_Handle> tls12_session;
199

200
            Server_Information server_info;
201
            std::vector<std::string> next_protocols;
202
            size_t io_buffer_size;
203

204
            std::shared_ptr<Callbacks> callbacks;
205
            std::shared_ptr<Session_Manager> session_manager;
206
            std::shared_ptr<Credentials_Manager> creds;
207
            std::shared_ptr<RandomNumberGenerator> rng;
208
            std::shared_ptr<const Policy> policy;
209

210
            bool received_tls_13_error_alert;
211
            bool will_downgrade;
212
      };
213

214
      std::unique_ptr<Downgrade_Information> m_downgrade_info;
215

216
      void preserve_peer_transcript(std::span<const uint8_t> input) {
16,175✔
217
         BOTAN_STATE_CHECK(m_downgrade_info);
16,175✔
218
         m_downgrade_info->peer_transcript.insert(m_downgrade_info->peer_transcript.end(), input.begin(), input.end());
16,175✔
219
      }
16,175✔
220

221
      void preserve_client_hello(std::span<const uint8_t> msg) {
933✔
222
         BOTAN_STATE_CHECK(m_downgrade_info);
933✔
223
         m_downgrade_info->client_hello_message.assign(msg.begin(), msg.end());
933✔
224
      }
933✔
225

226
      friend class Client;
227
      friend class Server;
228

229
      void set_io_buffer_size(size_t io_buf_sz) {
1,923✔
230
         BOTAN_STATE_CHECK(m_downgrade_info);
1,923✔
231
         m_downgrade_info->io_buffer_size = io_buf_sz;
1,923✔
232
      }
1,923✔
233

234
      /**
235
       * Implementations use this to signal that the peer indicated a protocol
236
       * version downgrade. After calling `request_downgrade()` no further
237
       * state changes must be perfomed by the implementation. Particularly, no
238
       * further handshake messages must be emitted. Instead, they must yield
239
       * control flow back to the underlying Channel implementation to perform
240
       * the protocol version downgrade.
241
       */
242
      void request_downgrade() {
1,048✔
243
         BOTAN_STATE_CHECK(m_downgrade_info && !m_downgrade_info->will_downgrade);
1,048✔
244
         m_downgrade_info->will_downgrade = true;
1,048✔
245
      }
1,048✔
246

247
      void request_downgrade_for_resumption(Session_with_Handle session) {
116✔
248
         BOTAN_STATE_CHECK(m_downgrade_info && m_downgrade_info->client_hello_message.empty() &&
116✔
249
                           m_downgrade_info->peer_transcript.empty() && !m_downgrade_info->tls12_session.has_value());
250
         BOTAN_ASSERT_NOMSG(session.session.version().is_pre_tls_13());
116✔
251
         m_downgrade_info->tls12_session = std::move(session);
116✔
252
         request_downgrade();
116✔
253
      }
116✔
254

255
   public:
256
      /**
257
       * Indicates whether a downgrade to TLS 1.2 or lower is in progress
258
       *
259
       * @sa Downgrade_Information
260
       */
261
      bool is_downgrading() const { return m_downgrade_info && m_downgrade_info->will_downgrade; }
183,714✔
262

263
      /**
264
       * @sa Downgrade_Information
265
       */
266
      std::unique_ptr<Downgrade_Information> extract_downgrade_info() { return std::exchange(m_downgrade_info, {}); }
1,048✔
267

268
      bool expects_downgrade() const { return m_downgrade_info != nullptr; }
23,757✔
269
};
270

271
}  // namespace TLS
272

273
}  // namespace Botan
274

275
#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