Coverage Report

Created: 2023-04-05 14:54

/src/botan/build/include/botan/internal/tls_channel_impl.h
Line
Count
Source (jump to first uncovered line)
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_version.h>
16
#include <botan/tls_magic.h>
17
18
#include <vector>
19
#include <memory>
20
#include <utility>
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
class Channel_Impl
33
   {
34
   public:
35
13.1k
      virtual ~Channel_Impl() = default;
36
37
      /**
38
      * Inject TLS traffic received from counterparty
39
      * @return a hint as the how many more bytes we need to q the
40
      *         current record (this may be 0 if on a record boundary)
41
      */
42
      virtual size_t from_peer(std::span<const uint8_t> data) = 0;
43
44
      /**
45
      * Inject plaintext intended for counterparty
46
      * Throws an exception if is_active() is false
47
      */
48
      virtual void to_peer(std::span<const uint8_t> data) = 0;
49
50
      /**
51
      * Send a TLS alert message. If the alert is fatal, the internal
52
      * state (keys, etc) will be reset.
53
      * @param alert the Alert to send
54
      */
55
      virtual void send_alert(const Alert& alert) = 0;
56
57
      /**
58
      * Send a warning alert
59
      */
60
627
      void send_warning_alert(Alert::Type type) { send_alert(Alert(type, false)); }
61
62
      /**
63
      * Send a fatal alert
64
      */
65
11.7k
      void send_fatal_alert(Alert::Type type) { send_alert(Alert(type, true)); }
66
67
      /**
68
      * Send a close notification alert
69
      */
70
0
      void close() { send_warning_alert(Alert::CloseNotify); }
71
72
      /**
73
      * @return true iff the connection is active for sending application data
74
      */
75
      virtual bool is_active() const = 0;
76
77
      /**
78
      * @return true iff the connection has been definitely closed
79
      */
80
      virtual bool is_closed() const = 0;
81
82
      /**
83
      * @return true iff the connection is active for sending application data
84
      */
85
      virtual bool is_closed_for_reading() const = 0;
86
87
      /**
88
      * @return true iff the connection has been definitely closed
89
      */
90
      virtual bool is_closed_for_writing() const = 0;
91
92
      /**
93
      * @return certificate chain of the peer (may be empty)
94
      */
95
      virtual std::vector<X509_Certificate> peer_cert_chain() const = 0;
96
97
      /**
98
      * Key material export (RFC 5705)
99
      * @param label a disambiguating label string
100
      * @param context a per-association context value
101
      * @param length the length of the desired key in bytes
102
      * @return key of length bytes
103
      */
104
      virtual SymmetricKey key_material_export(const std::string& label,
105
                                       const std::string& context,
106
                                       size_t length) const = 0;
107
108
      /**
109
      * Attempt to renegotiate the session
110
      * @param force_full_renegotiation if true, require a full renegotiation,
111
      * otherwise allow session resumption
112
      */
113
      virtual void renegotiate(bool force_full_renegotiation = false) = 0;
114
115
      /**
116
      * @return true if this channel can issue TLS 1.3 style session tickets.
117
      */
118
0
      virtual bool new_session_ticket_supported() const { return false; }
119
120
      /**
121
      * Send @p tickets new session tickets to the peer. This is only supported
122
      * on TLS 1.3 servers.
123
      *
124
      * If the server's Session_Manager does not accept the generated Session
125
      * objects, the server implementation won't be able to send new tickets.
126
      * Additionally, anything but TLS 1.3 servers will return 0 (because they
127
      * don't support sending such session tickets).
128
      *
129
      * @returns the number of session tickets successfully sent to the client
130
      */
131
0
      virtual size_t send_new_session_tickets(const size_t /* tickets */) { return 0; }
132
133
      /**
134
      * Attempt to update the session's traffic key material
135
      * Note that this is possible with a TLS 1.3 channel, only.
136
      *
137
      * @param request_peer_update if true, require a reciprocal key update
138
      */
139
      virtual void update_traffic_keys(bool request_peer_update = false) = 0;
140
141
      /**
142
      * @return true iff the counterparty supports the secure
143
      * renegotiation extensions.
144
      */
145
      virtual bool secure_renegotiation_supported() const = 0;
146
147
      /**
148
      * Perform a handshake timeout check. This does nothing unless
149
      * this is a DTLS channel with a pending handshake state, in
150
      * which case we check for timeout and potentially retransmit
151
      * handshake packets.
152
      */
153
      virtual bool timeout_check() = 0;
154
155
      /**
156
      * Return the protocol notification set for this connection, if any (ALPN).
157
      * This value is not tied to the session and a later renegotiation of the
158
      * same session can choose a new protocol.
159
      */
160
      virtual std::string application_protocol() const = 0;
161
162
   protected:
163
      /**
164
       * This struct collect all information required to perform a downgrade from TLS 1.3 to TLS 1.2.
165
       *
166
       * The downgrade process is (currently) triggered when a TLS 1.3 client receives a downgrade request
167
       * in the server hello message (@sa `Client_Impl_13::handle(Server_Hello_12)`). As a result,
168
       * `Client::received_data` should detect this condition and replace its `Channel_Impl_13` member by a
169
       * `Channel_Impl_12`.
170
       *
171
       * Note that the downgrade process for the server implementation will likely differ.
172
       */
173
      struct Downgrade_Information
174
         {
175
         /// The client hello message including the handshake header bytes as transferred to the peer.
176
         std::vector<uint8_t> client_hello_message;
177
178
         /// The full data transcript received from the peer. This will contain the server hello message that forced us to downgrade.
179
         std::vector<uint8_t> peer_transcript;
180
181
         /// The TLS 1.2 session information found by a TLS 1.3 client that
182
         /// caused it to initiate a downgrade before even sending a client hello.
183
         std::optional<Session_with_Handle> tls12_session;
184
185
         Server_Information server_info;
186
         std::vector<std::string> next_protocols;
187
         size_t io_buffer_size;
188
189
         std::shared_ptr<Callbacks> callbacks;
190
         std::shared_ptr<Session_Manager> session_manager;
191
         std::shared_ptr<Credentials_Manager> creds;
192
         std::shared_ptr<RandomNumberGenerator> rng;
193
         std::shared_ptr<const Policy> policy;
194
195
         bool received_tls_13_error_alert;
196
         bool will_downgrade;
197
         };
198
199
      std::unique_ptr<Downgrade_Information> m_downgrade_info;
200
201
      void preserve_peer_transcript(std::span<const uint8_t> input)
202
0
         {
203
0
         BOTAN_STATE_CHECK(m_downgrade_info);
204
0
         m_downgrade_info->peer_transcript.insert(m_downgrade_info->peer_transcript.end(),
205
0
                                                  input.begin(), input.end());
206
0
         }
207
208
      void preserve_client_hello(std::span<const uint8_t> msg)
209
0
         {
210
0
         BOTAN_STATE_CHECK(m_downgrade_info);
211
0
         m_downgrade_info->client_hello_message.assign(msg.begin(), msg.end());
212
0
         }
213
214
      friend class Client;
215
      friend class Server;
216
      void set_io_buffer_size(size_t io_buf_sz)
217
0
         {
218
0
         BOTAN_STATE_CHECK(m_downgrade_info);
219
0
         m_downgrade_info->io_buffer_size = io_buf_sz;
220
0
         }
221
222
      /**
223
       * Implementations use this to signal that the peer indicated a protocol
224
       * version downgrade. After calling `request_downgrade()` no further
225
       * state changes must be perfomed by the implementation. Particularly, no
226
       * further handshake messages must be emitted. Instead, they must yield
227
       * control flow back to the underlying Channel implementation to perform
228
       * the protocol version downgrade.
229
       */
230
      void request_downgrade()
231
0
         {
232
0
         BOTAN_STATE_CHECK(m_downgrade_info && !m_downgrade_info->will_downgrade);
233
0
         m_downgrade_info->will_downgrade = true;
234
0
         }
235
236
      void request_downgrade_for_resumption(Session_with_Handle session)
237
0
         {
238
0
         BOTAN_STATE_CHECK(m_downgrade_info &&
239
0
                           m_downgrade_info->client_hello_message.empty() &&
240
0
                           m_downgrade_info->peer_transcript.empty() &&
241
0
                           !m_downgrade_info->tls12_session.has_value());
242
0
         BOTAN_ASSERT_NOMSG(session.session.version().is_pre_tls_13());
243
0
         m_downgrade_info->tls12_session = std::move(session);
244
0
         request_downgrade();
245
0
         }
246
247
   public:
248
      /**
249
       * Indicates whether a downgrade to TLS 1.2 or lower is in progress
250
       *
251
       * @sa Downgrade_Information
252
       */
253
1.48k
      bool is_downgrading() const { return m_downgrade_info && m_downgrade_info->will_downgrade; }
254
255
      /**
256
       * @sa Downgrade_Information
257
       */
258
0
      std::unique_ptr<Downgrade_Information> extract_downgrade_info() { return std::exchange(m_downgrade_info, {}); }
259
260
0
      bool expects_downgrade() const { return m_downgrade_info != nullptr; }
261
   };
262
263
}
264
265
}
266
267
#endif