Botan 3.13.0
Crypto and TLS for C&
tls_channel_impl.h
Go to the documentation of this file.
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/assert.h>
15#include <botan/tls_channel.h>
16#include <botan/tls_magic.h>
17#include <botan/tls_session.h> // TODO remove this dep
18#include <botan/tls_session_manager.h>
19#include <botan/tls_version.h>
20#include <memory>
21#include <utility>
22#include <vector>
23
24#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
25 #include <botan/tls_messages_13.h>
26#endif
27
28namespace Botan {
29
32
33namespace TLS {
34
35class Client;
36class Server;
37
39 public:
40 virtual ~Channel_Impl() = default;
41
42 Channel_Impl(const Channel_Impl& other) = delete;
43 Channel_Impl(Channel_Impl&& other) = default;
44 Channel_Impl& operator=(const Channel_Impl& other) = delete;
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)); }
71
72 /**
73 * Send a fatal alert
74 */
75 void send_fatal_alert(Alert::Type type) { send_alert(Alert(type, true)); }
76
77 /**
78 * Send a close notification alert
79 */
80 void close() { send_warning_alert(Alert::CloseNotify); }
81
82 /**
83 * @return true iff the TLS handshake has finished successfully
84 */
85 virtual bool is_handshake_complete() const = 0;
86
87 /**
88 * @return true iff the connection is active for sending application data
89 */
90 virtual bool is_active() const = 0;
91
92 virtual std::optional<std::chrono::milliseconds> next_retransmission_timeout() const { return std::nullopt; }
93
94 /**
95 * @return true iff the connection has been definitely closed
96 */
97 virtual bool is_closed() const = 0;
98
99 /**
100 * @return true iff the connection is active for sending application data
101 */
102 virtual bool is_closed_for_reading() const = 0;
103
104 /**
105 * @return true iff the connection has been definitely closed
106 */
107 virtual bool is_closed_for_writing() const = 0;
108
109 /**
110 * @return certificate chain of the peer (may be empty)
111 */
112 virtual std::vector<X509_Certificate> peer_cert_chain() const = 0;
113
114 /**
115 * @return raw public key of the peer (may be nullptr)
116 */
117 virtual std::shared_ptr<const Public_Key> peer_raw_public_key() const = 0;
118
119 /**
120 * @return identity of the PSK used for this connection
121 * or std::nullopt if no PSK was used.
122 */
123 virtual std::optional<std::string> external_psk_identity() const = 0;
124
125 /**
126 * Key material export (RFC 5705)
127 * @param label a disambiguating label string
128 * @param context a per-association context value
129 * @param length the length of the desired key in bytes
130 * @return key of length bytes
131 */
132 virtual SymmetricKey key_material_export(std::string_view label,
133 std::string_view context,
134 size_t length) const = 0;
135
136 /**
137 * Attempt to renegotiate the session
138 * @param force_full_renegotiation if true, require a full renegotiation,
139 * otherwise allow session resumption
140 */
141 virtual void renegotiate(bool force_full_renegotiation = false) = 0;
142
143 /**
144 * @return true if this channel can issue TLS 1.3 style session tickets.
145 */
146 virtual bool new_session_ticket_supported() const { return false; }
147
148 /**
149 * Send @p tickets new session tickets to the peer. This is only supported
150 * on TLS 1.3 servers.
151 *
152 * If the server's Session_Manager does not accept the generated Session
153 * objects, the server implementation won't be able to send new tickets.
154 * Additionally, anything but TLS 1.3 servers will return 0 (because they
155 * don't support sending such session tickets).
156 *
157 * @returns the number of session tickets successfully sent to the client
158 */
159 virtual size_t send_new_session_tickets(const size_t /* tickets */) { return 0; }
160
161 /**
162 * Attempt to update the session's traffic key material
163 * Note that this is possible with a TLS 1.3 channel, only.
164 *
165 * @param request_peer_update if true, require a reciprocal key update
166 */
167 virtual void update_traffic_keys(bool request_peer_update = false) = 0;
168
169 /**
170 * @return true iff the counterparty supports the secure
171 * renegotiation extensions.
172 */
173 virtual bool secure_renegotiation_supported() const = 0;
174
175 /**
176 * Perform a handshake timeout check. This does nothing unless this is a
177 * DTLS channel with a handshake in progress.
178 */
179 virtual bool timeout_check() = 0;
180
181 /**
182 * Return the protocol notification set for this connection, if any (ALPN).
183 * This value is not tied to the session and a later renegotiation of the
184 * same session can choose a new protocol.
185 */
186 virtual std::string application_protocol() const = 0;
187
188 protected:
189 Channel_Impl() = default;
190
191#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
192
193 /**
194 * This struct collect all information required to perform a downgrade from TLS 1.3 to TLS 1.2.
195 *
196 * The downgrade process is (currently) triggered when a TLS 1.3 client receives a downgrade request
197 * in the server hello message (@sa `Client_Impl_13::handle(Server_Hello_12)`). As a result,
198 * `Client::received_data` should detect this condition and replace its `Channel_Impl_13` member by a
199 * `Channel_Impl_12`.
200 *
201 * Note that the downgrade process for the server implementation will likely differ.
202 */
203 struct Downgrade_Information {
204 /// The client hello message including the handshake header bytes as transferred to the peer.
205 std::optional<Client_Hello_13> client_hello;
206
207 /// The full data transcript received from the peer. This will contain the server hello message that forced us to downgrade.
208 std::vector<uint8_t> peer_transcript;
209
210 /// The TLS 1.2 session information found by a TLS 1.3 client that
211 /// caused it to initiate a downgrade before even sending a client hello.
212 std::optional<Session_with_Handle> tls12_session;
213
214 Server_Information server_info;
215 std::vector<std::string> next_protocols;
216 size_t io_buffer_size;
217
218 std::shared_ptr<Callbacks> callbacks;
219 std::shared_ptr<Session_Manager> session_manager;
220 std::shared_ptr<Credentials_Manager> creds;
221 std::shared_ptr<RandomNumberGenerator> rng;
222 std::shared_ptr<const Policy> policy;
223
224 bool received_tls_13_error_alert;
225 bool will_downgrade;
226 };
227
228 std::unique_ptr<Downgrade_Information> m_downgrade_info; // NOLINT(*non-private-member-variable*)
229
230 void preserve_peer_transcript(std::span<const uint8_t> input) {
231 BOTAN_STATE_CHECK(m_downgrade_info);
232 m_downgrade_info->peer_transcript.insert(m_downgrade_info->peer_transcript.end(), input.begin(), input.end());
233 }
234
235 void preserve_client_hello(Client_Hello_13 client_hello) {
236 BOTAN_STATE_CHECK(m_downgrade_info);
237 m_downgrade_info->client_hello.emplace(std::move(client_hello));
238 }
239
240 friend class Client;
241 friend class Server;
242
243 void set_io_buffer_size(size_t io_buf_sz) {
244 BOTAN_STATE_CHECK(m_downgrade_info);
245 m_downgrade_info->io_buffer_size = io_buf_sz;
246 }
247
248 /**
249 * Implementations use this to signal that the peer indicated a protocol
250 * version downgrade. After calling `request_downgrade()` no further
251 * state changes must be performed by the implementation. Particularly, no
252 * further handshake messages must be emitted. Instead, they must yield
253 * control flow back to the underlying Channel implementation to perform
254 * the protocol version downgrade.
255 */
256 void request_downgrade() {
257 BOTAN_STATE_CHECK(m_downgrade_info && !m_downgrade_info->will_downgrade);
258 m_downgrade_info->will_downgrade = true;
259 }
260
261 void request_downgrade_for_resumption(Session_with_Handle session) {
262 BOTAN_STATE_CHECK(m_downgrade_info && !m_downgrade_info->client_hello.has_value() &&
263 m_downgrade_info->peer_transcript.empty() && !m_downgrade_info->tls12_session.has_value());
264 BOTAN_ASSERT_NOMSG(session.session.version().is_pre_tls_13());
265 m_downgrade_info->tls12_session = std::move(session);
266 request_downgrade();
267 }
268
269 public:
270 /**
271 * @sa Downgrade_Information
272 */
273 std::unique_ptr<Downgrade_Information> extract_downgrade_info() { return std::exchange(m_downgrade_info, {}); }
274
275#endif
276
277 /**
278 * Indicates whether a downgrade to TLS 1.2 or lower is in progress
279 *
280 * @sa Downgrade_Information
281 */
282 bool is_downgrading() const {
283#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
284 return m_downgrade_info && m_downgrade_info->will_downgrade;
285#else
286 return false;
287#endif
288 }
289
290 bool expects_downgrade() const {
291#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
292 return m_downgrade_info != nullptr;
293#else
294 return false;
295#endif
296 }
297};
298
299} // namespace TLS
300
301} // namespace Botan
302
303#endif
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
AlertType Type
Definition tls_alert.h:72
virtual std::optional< std::string > external_psk_identity() const =0
virtual SymmetricKey key_material_export(std::string_view label, std::string_view context, size_t length) const =0
virtual bool is_active() const =0
virtual std::string application_protocol() const =0
Channel_Impl(Channel_Impl &&other)=default
virtual bool new_session_ticket_supported() const
virtual ~Channel_Impl()=default
virtual size_t from_peer(std::span< const uint8_t > data)=0
Channel_Impl & operator=(Channel_Impl &&other)=delete
virtual bool timeout_check()=0
virtual std::optional< std::chrono::milliseconds > next_retransmission_timeout() const
virtual bool is_closed_for_reading() const =0
virtual void update_traffic_keys(bool request_peer_update=false)=0
virtual void send_alert(const Alert &alert)=0
virtual void to_peer(std::span< const uint8_t > data)=0
virtual bool is_closed() const =0
void send_warning_alert(Alert::Type type)
virtual bool secure_renegotiation_supported() const =0
virtual bool is_closed_for_writing() const =0
virtual std::shared_ptr< const Public_Key > peer_raw_public_key() const =0
void send_fatal_alert(Alert::Type type)
virtual void renegotiate(bool force_full_renegotiation=false)=0
virtual std::vector< X509_Certificate > peer_cert_chain() const =0
Channel_Impl(const Channel_Impl &other)=delete
virtual bool is_handshake_complete() const =0
virtual size_t send_new_session_tickets(const size_t)
Channel_Impl & operator=(const Channel_Impl &other)=delete
OctetString SymmetricKey
Definition symkey.h:153