Botan 3.10.0
Crypto and TLS for C&
tls_channel_impl_13.cpp
Go to the documentation of this file.
1/*
2* TLS Channel - implementation for TLS 1.3
3* (C) 2022 Jack Lloyd
4* 2021 Elektrobit Automotive GmbH
5* 2022 Hannes Rantzsch, René Meusel - neXenio GmbH
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#include <botan/internal/tls_channel_impl_13.h>
11
12#include <botan/tls_messages.h>
13#include <botan/internal/stl_util.h>
14#include <botan/internal/tls_cipher_state.h>
15#include <botan/internal/tls_handshake_state.h>
16#include <botan/internal/tls_record.h>
17
18#include <array>
19
20namespace {
21bool is_user_canceled_alert(const Botan::TLS::Alert& alert) {
22 return alert.type() == Botan::TLS::Alert::UserCanceled;
23}
24
25bool is_close_notify_alert(const Botan::TLS::Alert& alert) {
26 return alert.type() == Botan::TLS::Alert::CloseNotify;
27}
28
29bool is_error_alert(const Botan::TLS::Alert& alert) {
30 // In TLS 1.3 all alerts except for closure alerts are considered error alerts.
31 // (RFC 8446 6.)
32 return !is_close_notify_alert(alert) && !is_user_canceled_alert(alert);
33}
34} // namespace
35
36namespace Botan::TLS {
37
38Channel_Impl_13::Channel_Impl_13(const std::shared_ptr<Callbacks>& callbacks,
39 const std::shared_ptr<Session_Manager>& session_manager,
40 const std::shared_ptr<Credentials_Manager>& credentials_manager,
41 const std::shared_ptr<RandomNumberGenerator>& rng,
42 const std::shared_ptr<const Policy>& policy,
43 bool is_server) :
45 m_callbacks(callbacks),
46 m_session_manager(session_manager),
47 m_credentials_manager(credentials_manager),
48 m_rng(rng),
49 m_policy(policy),
50 m_record_layer(m_side),
51 m_handshake_layer(m_side),
52 m_can_read(true),
53 m_can_write(true),
54 m_opportunistic_key_update(false),
55 m_first_message_sent(false),
56 m_first_message_received(false) {
57 BOTAN_ASSERT_NONNULL(m_callbacks);
58 BOTAN_ASSERT_NONNULL(m_session_manager);
59 BOTAN_ASSERT_NONNULL(m_credentials_manager);
62}
63
65
66size_t Channel_Impl_13::from_peer(std::span<const uint8_t> data) {
68
69 // RFC 8446 6.1
70 // Any data received after a closure alert has been received MUST be ignored.
71 if(!m_can_read) {
72 return 0;
73 }
74
75 try {
76 if(expects_downgrade()) {
78 }
79
80 m_record_layer.copy_data(data);
81
82 while(true) {
83 // RFC 8446 6.1
84 // Any data received after a closure alert has been received MUST be ignored.
85 //
86 // ... this data might already be in the record layer's read buffer.
87 if(!m_can_read) {
88 return 0;
89 }
90
91 auto result = m_record_layer.next_record(m_cipher_state.get());
92
93 if(std::holds_alternative<BytesNeeded>(result)) {
94 return std::get<BytesNeeded>(result);
95 }
96
97 const auto& record = std::get<Record>(result);
98
99 // RFC 8446 5.1
100 // Handshake messages MUST NOT be interleaved with other record types.
101 if(record.type != Record_Type::Handshake && m_handshake_layer.has_pending_data()) {
102 throw Unexpected_Message("Expected remainder of a handshake message");
103 }
104
105 if(record.type == Record_Type::Handshake) {
106 m_handshake_layer.copy_data(record.fragment);
107
108 if(!is_handshake_complete()) {
109 while(auto handshake_msg = m_handshake_layer.next_message(policy(), m_transcript_hash)) {
110 // RFC 8446 5.1
111 // Handshake messages MUST NOT span key changes. Implementations
112 // MUST verify that all messages immediately preceding a key change
113 // align with a record boundary; if not, then they MUST terminate the
114 // connection with an "unexpected_message" alert. Because the
115 // ClientHello, EndOfEarlyData, ServerHello, Finished, and KeyUpdate
116 // messages can immediately precede a key change, implementations
117 // MUST send these messages in alignment with a record boundary.
118 //
119 // Note: Hello_Retry_Request was added to the list below although it cannot immediately precede a key change.
120 // However, there cannot be any further sensible messages in the record after HRR.
121 //
122 // Note: Server_Hello_12 was deliberately not included in the check below because in TLS 1.2 Server Hello and
123 // other handshake messages can be legally coalesced in a single record.
124 //
126 Client_Hello_13 /*, EndOfEarlyData,*/,
129 Finished_13>(handshake_msg.value()) &&
130 m_handshake_layer.has_pending_data()) {
131 throw Unexpected_Message("Unexpected additional handshake message data found in record");
132 }
133
134 process_handshake_msg(std::move(handshake_msg.value()));
135
136 if(is_downgrading()) {
137 // Downgrade to TLS 1.2 was detected. Stop everything we do and await being replaced by a 1.2 implementation.
138 return 0;
139 } else if(m_downgrade_info != nullptr) {
140 // We received a TLS 1.3 error alert that could have been a TLS 1.2 warning alert.
141 // Now that we know that we are talking to a TLS 1.3 server, shut down.
142 if(m_downgrade_info->received_tls_13_error_alert) {
143 shutdown();
144 }
145
146 // Downgrade can only be indicated in the first received peer message. This was not the case.
147 m_downgrade_info.reset();
148 }
149
150 // After the initial handshake message is received, the record
151 // layer must be more restrictive.
152 // See RFC 8446 5.1 regarding "legacy_record_version"
153 if(!m_first_message_received) {
154 m_record_layer.disable_receiving_compat_mode();
155 m_first_message_received = true;
156 }
157 }
158 } else {
159 while(auto handshake_msg = m_handshake_layer.next_post_handshake_message(policy())) {
160 process_post_handshake_msg(std::move(handshake_msg.value()));
161 }
162 }
163 } else if(record.type == Record_Type::ChangeCipherSpec) {
165 } else if(record.type == Record_Type::ApplicationData) {
166 BOTAN_ASSERT(record.seq_no.has_value(), "decrypted application traffic had a sequence number");
167 callbacks().tls_record_received(record.seq_no.value(), record.fragment);
168 } else if(record.type == Record_Type::Alert) {
169 process_alert(record.fragment);
170 } else {
171 throw Unexpected_Message("Unexpected record type " + std::to_string(static_cast<size_t>(record.type)) +
172 " from counterparty");
173 }
174 }
175 } catch(TLS_Exception& e) {
177 throw;
179 // RFC 8446 5.2
180 // If the decryption fails, the receiver MUST terminate the connection
181 // with a "bad_record_mac" alert.
182 send_fatal_alert(Alert::BadRecordMac);
183 throw;
184 } catch(Decoding_Error&) {
185 send_fatal_alert(Alert::DecodeError);
186 throw;
187 } catch(...) {
188 send_fatal_alert(Alert::InternalError);
189 throw;
190 }
191}
192
193void Channel_Impl_13::handle(const Key_Update& key_update) {
194 // make sure Key_Update appears only at the end of a record; see description above
195 if(m_handshake_layer.has_pending_data()) {
196 throw Unexpected_Message("Unexpected additional post-handshake message data found in record");
197 }
198
199 m_cipher_state->update_read_keys(*this);
200
201 // TODO: introduce some kind of rate limit of key updates, otherwise we
202 // might be forced into an endless loop of key updates.
203
204 // RFC 8446 4.6.3
205 // If the request_update field is set to "update_requested", then the
206 // receiver MUST send a KeyUpdate of its own with request_update set to
207 // "update_not_requested" prior to sending its next Application Data
208 // record.
209 if(key_update.expects_reciprocation()) {
210 // RFC 8446 4.6.3
211 // This mechanism allows either side to force an update to the
212 // multiple KeyUpdates while it is silent to respond with a single
213 // update.
215 }
216}
217
220
222 Handshake_Layer& handshake_layer,
223 Transcript_Hash_State& transcript_hash) :
224 AggregatedMessages(channel, handshake_layer), m_transcript_hash(transcript_hash) {}
225
227 const Handshake_Message_13_Ref message) {
228 std::visit([&](const auto msg) { m_channel.callbacks().tls_inspect_handshake_msg(msg.get()); }, message);
229 m_message_buffer += m_handshake_layer.prepare_message(message, m_transcript_hash);
230 return *this;
231}
232
235 std::visit([&](const auto& msg) { m_channel.callbacks().tls_inspect_handshake_msg(msg); }, message);
236 m_message_buffer += m_handshake_layer.prepare_post_handshake_message(message);
237 return *this;
238}
239
243 return std::exchange(m_message_buffer, {});
244}
245
247 // RFC 8446 5.
248 // The change_cipher_spec record is used only for compatibility purposes
249 // (see Appendix D.4).
250 //
251 // The only allowed CCS message content is 0x01, all other CCS records MUST
252 // be rejected by TLS 1.3 implementations.
253 send_record(Record_Type::ChangeCipherSpec, {0x01});
254}
255
256void Channel_Impl_13::to_peer(std::span<const uint8_t> data) {
257 if(!is_active()) {
258 throw Invalid_State("Data cannot be sent on inactive TLS connection");
259 }
260
261 // RFC 8446 4.6.3
262 // If the request_update field [of a received KeyUpdate] is set to
263 // "update_requested", then the receiver MUST send a KeyUpdate of its own
264 // with request_update set to "update_not_requested" prior to sending its
265 // next Application Data record.
266 // This mechanism allows either side to force an update to the entire
267 // connection, but causes an implementation which receives multiple
268 // KeyUpdates while it is silent to respond with a single update.
269 if(m_opportunistic_key_update) {
270 update_traffic_keys(false /* update_requested */);
271 m_opportunistic_key_update = false;
272 }
273
274 send_record(Record_Type::ApplicationData, {data.begin(), data.end()});
275}
276
278 if(alert.is_valid() && m_can_write) {
279 try {
280 send_record(Record_Type::Alert, alert.serialize());
281 } catch(...) { /* swallow it */
282 }
283 }
284
285 // Note: In TLS 1.3 sending a CloseNotify must not immediately lead to closing the reading end.
286 // RFC 8446 6.1
287 // Each party MUST send a "close_notify" alert before closing its write
288 // side of the connection, unless it has already sent some error alert.
289 // This does not have any effect on its read side of the connection.
290 if(is_close_notify_alert(alert) && m_can_write) {
291 m_can_write = false;
292 if(m_cipher_state) {
293 m_cipher_state->clear_write_keys();
294 }
295 }
296
297 if(is_error_alert(alert)) {
298 shutdown();
299 }
300}
301
303 return m_cipher_state != nullptr && m_cipher_state->can_encrypt_application_traffic() // handshake done
304 && m_can_write; // close() hasn't been called
305}
306
308 std::string_view context,
309 size_t length) const {
311 BOTAN_STATE_CHECK(m_cipher_state != nullptr && m_cipher_state->can_export_keys());
312 return SymmetricKey(m_cipher_state->export_key(label, context, length));
313}
314
322
323void Channel_Impl_13::send_record(Record_Type type, const std::vector<uint8_t>& record) {
325 BOTAN_STATE_CHECK(m_can_write);
326
327 auto to_write = m_record_layer.prepare_records(type, record, m_cipher_state.get());
328
329 // After the initial handshake message is sent, the record layer must
330 // adhere to a more strict record specification. Note that for the
331 // server case this is a NOOP.
332 // See (RFC 8446 5.1. regarding "legacy_record_version")
333 if(!m_first_message_sent && type == Record_Type::Handshake) {
334 m_record_layer.disable_sending_compat_mode();
335 m_first_message_sent = true;
336 }
337
338 // The dummy CCS must not be prepended if the following record is
339 // an unprotected Alert record.
340 if(prepend_ccs() && (m_cipher_state || type != Record_Type::Alert)) {
341 std::array<uint8_t, 1> ccs_content = {0x01};
342 const auto ccs = m_record_layer.prepare_records(Record_Type::ChangeCipherSpec, ccs_content, m_cipher_state.get());
343 to_write = concat(ccs, to_write);
344 }
345
346 callbacks().tls_emit_data(to_write);
347}
348
349void Channel_Impl_13::process_alert(const secure_vector<uint8_t>& record) {
350 Alert alert(record);
351
352 if(is_close_notify_alert(alert)) {
353 m_can_read = false;
354 if(m_cipher_state) {
355 m_cipher_state->clear_read_keys();
356 }
357 m_record_layer.clear_read_buffer();
358 }
359
360 // user canceled alerts are ignored
361
362 // RFC 8446 5.
363 // All the alerts listed in Section 6.2 MUST be sent with
364 // AlertLevel=fatal and MUST be treated as error alerts when received
365 // regardless of the AlertLevel in the message. Unknown Alert types
366 // MUST be treated as error alerts.
367 if(is_error_alert(alert) && !alert.is_fatal()) {
368 // In TLS 1.2 error alerts might be marked as 'warnings' and would not
369 // demand an immediate shutdown. Until we are sure to talk to a TLS 1.3
370 // peer we must defer the shutdown and refrain from raising a decode
371 // error.
372 if(expects_downgrade()) {
373 m_downgrade_info->received_tls_13_error_alert = true;
374 } else {
375 throw TLS_Exception(Alert::DecodeError, "Error alert not marked fatal"); // will shutdown in send_alert
376 }
377 }
378
379 if(alert.is_fatal()) {
380 shutdown();
381 }
382
383 callbacks().tls_alert(alert);
384
385 // Respond with our "close_notify" if the application requests us to.
386 if(is_close_notify_alert(alert) && callbacks().tls_peer_closed_connection()) {
387 close();
388 }
389}
390
391void Channel_Impl_13::shutdown() {
392 // RFC 8446 6.2
393 // Upon transmission or receipt of a fatal alert message, both
394 // parties MUST immediately close the connection.
395 m_can_read = false;
396 m_can_write = false;
397 m_cipher_state.reset();
398}
399
401 const std::vector<std::string>& next_protocols) {
403 {},
404 {},
405 {},
406 server_info,
407 next_protocols,
409 m_callbacks,
410 m_session_manager,
411 m_credentials_manager,
412 m_rng,
413 m_policy,
414 false, // received_tls_13_error_alert
415 false // will_downgrade
416 };
417 m_downgrade_info = std::make_unique<Downgrade_Information>(std::move(di));
418}
419
420void Channel_Impl_13::set_record_size_limits(const uint16_t outgoing_limit, const uint16_t incoming_limit) {
421 m_record_layer.set_record_size_limits(outgoing_limit, incoming_limit);
422}
423
425 m_handshake_layer.set_selected_certificate_type(cert_type);
426}
427
428} // namespace Botan::TLS
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
bool is_valid() const
Definition tls_alert.h:77
std::vector< uint8_t > serialize() const
Definition tls_alert.cpp:32
bool is_fatal() const
Definition tls_alert.h:92
Type type() const
Definition tls_alert.h:99
virtual void tls_record_received(uint64_t seq_no, std::span< const uint8_t > data)=0
virtual void tls_alert(Alert alert)=0
virtual void tls_emit_data(std::span< const uint8_t > data)=0
AggregatedHandshakeMessages & add(Handshake_Message_13_Ref message)
AggregatedHandshakeMessages(Channel_Impl_13 &channel, Handshake_Layer &handshake_layer, Transcript_Hash_State &transcript_hash)
AggregatedMessages(Channel_Impl_13 &channel, Handshake_Layer &handshake_layer)
AggregatedPostHandshakeMessages & add(Post_Handshake_Message_13 message)
const Policy & policy() const
void expect_downgrade(const Server_Information &server_info, const std::vector< std::string > &next_protocols)
SymmetricKey key_material_export(std::string_view label, std::string_view context, size_t length) const override
void handle(const Key_Update &key_update)
std::vector< uint8_t > send_post_handshake_message(Post_Handshake_Message_13 message)
Credentials_Manager & credentials_manager()
RandomNumberGenerator & rng()
void to_peer(std::span< const uint8_t > data) override
Transcript_Hash_State m_transcript_hash
virtual void process_post_handshake_msg(Post_Handshake_Message_13 msg)=0
virtual void process_handshake_msg(Handshake_Message_13 msg)=0
Channel_Impl_13(const std::shared_ptr< Callbacks > &callbacks, const std::shared_ptr< Session_Manager > &session_manager, const std::shared_ptr< Credentials_Manager > &credentials_manager, const std::shared_ptr< RandomNumberGenerator > &rng, const std::shared_ptr< const Policy > &policy, bool is_server)
void send_alert(const Alert &alert) override
size_t from_peer(std::span< const uint8_t > data) override
void update_traffic_keys(bool request_peer_update=false) override
virtual void process_dummy_change_cipher_spec()=0
Session_Manager & session_manager()
std::unique_ptr< Cipher_State > m_cipher_state
void set_selected_certificate_type(Certificate_Type cert_type)
void set_record_size_limits(uint16_t outgoing_limit, uint16_t incoming_limit)
void preserve_peer_transcript(std::span< const uint8_t > input)
void send_fatal_alert(Alert::Type type)
std::unique_ptr< Downgrade_Information > m_downgrade_info
virtual bool is_handshake_complete() const =0
static constexpr size_t IO_BUF_DEFAULT_SIZE
Definition tls_channel.h:32
bool expects_reciprocation() const
std::vector< uint8_t > prepare_records(Record_Type type, std::span< const uint8_t > data, Cipher_State *cipher_state=nullptr) const
Alert::Type type() const
Definition tls_exceptn.h:21
detail::as_wrapped_references_t< Handshake_Message_13 > Handshake_Message_13_Ref
std::variant< New_Session_Ticket_13, Key_Update > Post_Handshake_Message_13
OctetString SymmetricKey
Definition symkey.h:140
constexpr bool holds_any_of(const std::variant< Ts... > &v) noexcept
Definition stl_util.h:284
constexpr auto concat(Rs &&... ranges)
Definition stl_util.h:254
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69