Botan 3.13.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_callbacks.h>
13#include <botan/tls_exceptn.h>
14#include <botan/tls_messages_13.h>
15#include <botan/tls_policy.h>
16#include <botan/internal/concat_util.h>
17#include <botan/internal/tls_cipher_state.h>
18
19#include <array>
20#include <chrono>
21
22namespace {
23bool is_user_canceled_alert(const Botan::TLS::Alert& alert) {
24 return alert.type() == Botan::TLS::Alert::UserCanceled;
25}
26
27bool is_close_notify_alert(const Botan::TLS::Alert& alert) {
28 return alert.type() == Botan::TLS::Alert::CloseNotify;
29}
30
31bool is_error_alert(const Botan::TLS::Alert& alert) {
32 // In TLS 1.3 all alerts except for closure alerts are considered error alerts.
33 // (RFC 8446 6.)
34 return !is_close_notify_alert(alert) && !is_user_canceled_alert(alert);
35}
36} // namespace
37
38namespace Botan::TLS {
39
40Channel_Impl_13::Channel_Impl_13(const std::shared_ptr<Callbacks>& callbacks,
41 const std::shared_ptr<Session_Manager>& session_manager,
42 const std::shared_ptr<Credentials_Manager>& credentials_manager,
43 const std::shared_ptr<RandomNumberGenerator>& rng,
44 const std::shared_ptr<const Policy>& policy,
45 bool is_server) :
47 m_callbacks(callbacks),
48 m_session_manager(session_manager),
49 m_credentials_manager(credentials_manager),
50 m_rng(rng),
51 m_policy(policy),
52 m_record_layer(m_side, m_policy),
53 m_handshake_layer(m_side),
54 m_can_read(true),
55 m_can_write(true),
56 m_opportunistic_key_update(false),
57 m_first_message_sent(false),
58 m_first_message_received(false) {
59 BOTAN_ASSERT_NONNULL(m_callbacks);
60 BOTAN_ASSERT_NONNULL(m_session_manager);
61 BOTAN_ASSERT_NONNULL(m_credentials_manager);
64}
65
67
68size_t Channel_Impl_13::from_peer(std::span<const uint8_t> data) {
70
71 // RFC 8446 6.1
72 // Any data received after a closure alert has been received MUST be ignored.
73 if(!m_can_read) {
74 return 0;
75 }
76
77 try {
78#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
79 if(expects_downgrade()) {
80 preserve_peer_transcript(data);
81 }
82#endif
83
84 m_record_layer.copy_data(data);
85
86 while(true) {
87 // RFC 8446 6.1
88 // Any data received after a closure alert has been received MUST be ignored.
89 //
90 // ... this data might already be in the record layer's read buffer.
91 if(!m_can_read) {
92 return 0;
93 }
94
95 auto result = m_record_layer.next_record(m_cipher_state.get());
96
97 if(std::holds_alternative<BytesNeeded>(result)) {
98 return std::get<BytesNeeded>(result);
99 }
100
101 const auto& record = std::get<Record>(result);
102
103 // RFC 8446 5.1
104 // Handshake messages MUST NOT be interleaved with other record types.
105 if(record.type != Record_Type::Handshake && m_handshake_layer.has_pending_data()) {
106 throw Unexpected_Message("Expected remainder of a handshake message");
107 }
108
109 if(record.type == Record_Type::Handshake) {
110 m_handshake_layer.copy_data(record.fragment);
111
112 if(!is_handshake_complete()) {
113 while(auto handshake_msg = m_handshake_layer.next_message(policy(), m_transcript_hash)) {
114 // RFC 8446 5.1
115 // Handshake messages MUST NOT span key changes. Implementations
116 // MUST verify that all messages immediately preceding a key change
117 // align with a record boundary; if not, then they MUST terminate the
118 // connection with an "unexpected_message" alert. Because the
119 // ClientHello, EndOfEarlyData, ServerHello, Finished, and KeyUpdate
120 // messages can immediately precede a key change, implementations
121 // MUST send these messages in alignment with a record boundary.
122 //
123 // Note: Hello_Retry_Request was added to the list below although it cannot immediately precede a key change.
124 // However, there cannot be any further sensible messages in the record after HRR.
125 //
126 // Note: Server_Hello_12 was deliberately not included in the check below because in TLS 1.2 Server Hello and
127 // other handshake messages can be legally coalesced in a single record.
128 //
130 Client_Hello_13 /*, EndOfEarlyData,*/,
133 Finished_13>(handshake_msg.value()) &&
134 m_handshake_layer.has_pending_data()) {
135 throw Unexpected_Message("Unexpected additional handshake message data found in record");
136 }
137
138 process_handshake_msg(std::move(handshake_msg.value()));
139
140#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
141 if(is_downgrading()) {
142 // Downgrade to TLS 1.2 was detected. Stop everything we do and await being replaced by a 1.2 implementation.
143 return 0;
144 } else if(m_downgrade_info != nullptr) {
145 // We received a TLS 1.3 error alert that could have been a TLS 1.2 warning alert.
146 // Now that we know that we are talking to a TLS 1.3 server, shut down.
147 if(m_downgrade_info->received_tls_13_error_alert) {
148 shutdown();
149 }
150
151 // Downgrade can only be indicated in the first received peer message. This was not the case.
152 m_downgrade_info.reset();
153 }
154#endif
155
156 // After the initial handshake message is received, the record
157 // layer must be more restrictive.
158 // See RFC 8446 5.1 regarding "legacy_record_version"
159 if(!m_first_message_received) {
160 m_record_layer.disable_receiving_compat_mode();
161 m_first_message_received = true;
162 }
163 }
164 } else {
165 while(auto handshake_msg = m_handshake_layer.next_post_handshake_message(policy())) {
166 process_post_handshake_msg(std::move(handshake_msg.value()));
167 }
168 }
169 } else if(record.type == Record_Type::ChangeCipherSpec) {
171 } else if(record.type == Record_Type::ApplicationData) {
173 if(!m_cipher_state->can_decrypt_application_traffic()) {
174 throw Unexpected_Message("Application data received before handshake completion");
175 }
176 /*
177 The record sequence number is set in Record_Layer::next_record only when
178 the record contents are decrypted under the current set of traffic keys
179 */
180 if(!record.seq_no.has_value()) {
181 throw Unexpected_Message("Application data must have a sequence number");
182 }
183 callbacks().tls_record_received(record.seq_no.value(), record.fragment);
184 } else if(record.type == Record_Type::Alert) {
185 process_alert(record.fragment);
186 } else {
187 throw Unexpected_Message("Unexpected record type " + std::to_string(static_cast<size_t>(record.type)) +
188 " from counterparty");
189 }
190 }
191 } catch(TLS_Exception& e) {
193 throw;
195 // RFC 8446 5.2
196 // If the decryption fails, the receiver MUST terminate the connection
197 // with a "bad_record_mac" alert.
198 send_fatal_alert(Alert::BadRecordMac);
199 throw;
200 } catch(Decoding_Error&) {
201 send_fatal_alert(Alert::DecodeError);
202 throw;
203 } catch(...) {
204 send_fatal_alert(Alert::InternalError);
205 throw;
206 }
207}
208
209void Channel_Impl_13::handle(const Key_Update& key_update) {
210 // make sure Key_Update appears only at the end of a record; see description above
211 if(m_handshake_layer.has_pending_data()) {
212 throw Unexpected_Message("Unexpected additional post-handshake message data found in record");
213 }
214
215 if(const uint64_t min_interval = policy().minimum_key_update_interval_ms(); min_interval > 0) {
216 const uint64_t now =
217 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch())
218 .count();
219
220 if(m_last_key_update_ms != 0 && (now - m_last_key_update_ms) < min_interval) {
221 throw TLS_Exception(Alert::UnexpectedMessage, "Peer is requesting KeyUpdates too frequently");
222 }
223
224 m_last_key_update_ms = now;
225 }
226
228 m_cipher_state->update_read_keys(*this);
229
230 // RFC 8446 4.6.3
231 // If the request_update field is set to "update_requested", then the
232 // receiver MUST send a KeyUpdate of its own with request_update set to
233 // "update_not_requested" prior to sending its next Application Data
234 // record.
235 if(key_update.expects_reciprocation()) {
236 // RFC 8446 4.6.3
237 // This mechanism allows either side to force an update to the
238 // multiple KeyUpdates while it is silent to respond with a single
239 // update.
241 }
242}
243
246
248 Handshake_Layer& handshake_layer,
249 Transcript_Hash_State& transcript_hash) :
250 AggregatedMessages(channel, handshake_layer), m_transcript_hash(transcript_hash) {}
251
253 const Handshake_Message_13_Ref message) {
254 std::visit([&](const auto msg) { m_channel.callbacks().tls_inspect_handshake_msg(msg.get()); }, message);
255 m_message_buffer += m_handshake_layer.prepare_message(message, m_transcript_hash);
256 return *this;
257}
258
261 std::visit([&](const auto& msg) { m_channel.callbacks().tls_inspect_handshake_msg(msg); }, message);
262 m_message_buffer += m_handshake_layer.prepare_post_handshake_message(message);
263 return *this;
264}
265
270
272 // RFC 9846 5.
273 // The change_cipher_spec record is used only for compatibility purposes
274 // (see Appendix E.4).
275 //
276 // An implementation may receive an unencrypted record of type
277 // change_cipher_spec consisting of the single byte value 0x01 at any time
278 // after the first ClientHello message has been sent or received and
279 // before the peer's Finished message has been received.
281
282 send_record(Record_Type::ChangeCipherSpec, {0x01});
283}
284
285void Channel_Impl_13::to_peer(std::span<const uint8_t> data) {
286 if(!is_active()) {
287 throw Invalid_State("Data cannot be sent on inactive TLS connection");
288 }
289
290 // RFC 8446 4.6.3
291 // If the request_update field [of a received KeyUpdate] is set to
292 // "update_requested", then the receiver MUST send a KeyUpdate of its own
293 // with request_update set to "update_not_requested" prior to sending its
294 // next Application Data record.
295 // This mechanism allows either side to force an update to the entire
296 // connection, but causes an implementation which receives multiple
297 // KeyUpdates while it is silent to respond with a single update.
298 if(m_opportunistic_key_update) {
299 update_traffic_keys(false /* update_requested */);
300 m_opportunistic_key_update = false;
301 }
302
303 send_record(Record_Type::ApplicationData, {data.begin(), data.end()});
304}
305
307 if(alert.is_valid() && m_can_write) {
308 try {
310 send_record(Record_Type::Alert, alert.serialize());
311 } catch(...) { /* swallow it */
312 }
313 }
314
315 // Note: In TLS 1.3 sending a CloseNotify must not immediately lead to closing the reading end.
316 // RFC 8446 6.1
317 // Each party MUST send a "close_notify" alert before closing its write
318 // side of the connection, unless it has already sent some error alert.
319 // This does not have any effect on its read side of the connection.
320 if(is_close_notify_alert(alert) && m_can_write) {
321 m_can_write = false;
322 if(m_cipher_state) {
323 m_cipher_state->clear_write_keys();
324 }
325 }
326
327 if(is_error_alert(alert)) {
328 shutdown();
329 }
330}
331
333 return m_cipher_state != nullptr && m_cipher_state->can_encrypt_application_traffic() // handshake done
334 && m_can_write; // close() hasn't been called
335}
336
338 std::string_view context,
339 size_t length) const {
341 BOTAN_STATE_CHECK(m_cipher_state != nullptr && m_cipher_state->can_export_keys());
342 return SymmetricKey(m_cipher_state->export_key(label, context, length));
343}
344
345void Channel_Impl_13::update_traffic_keys(bool request_peer_update) {
348 send_post_handshake_message(Key_Update(request_peer_update));
349 m_cipher_state->update_write_keys(*this);
350}
351
352void Channel_Impl_13::send_record(Record_Type type, const std::vector<uint8_t>& record) {
354 BOTAN_STATE_CHECK(m_can_write);
355
356 // RFC 9846 5.
357 // An implementation which [...] receives a protected change_cipher_spec
358 // record MUST abort the handshake [...].
359 //
360 // I.e. Change Cipher Spec records must always be sent unprotected, even if
361 // the cipher state is already set up for handshake message encryption.
362 auto* cipher_state = (type != Record_Type::ChangeCipherSpec) ? m_cipher_state.get() : nullptr;
363
364 auto to_write = m_record_layer.prepare_records(type, record, cipher_state);
365
366 // After the initial handshake message is sent, the record layer must
367 // adhere to a more strict record specification. Note that for the
368 // server case this is a NOOP.
369 // See (RFC 8446 5.1. regarding "legacy_record_version")
370 if(!m_first_message_sent && type == Record_Type::Handshake) {
371 m_record_layer.disable_sending_compat_mode();
372 m_first_message_sent = true;
373 }
374
375 callbacks().tls_emit_data(to_write);
376}
377
378void Channel_Impl_13::process_alert(const secure_vector<uint8_t>& record) {
379 const Alert alert(record);
380
381 if(is_close_notify_alert(alert)) {
382 m_can_read = false;
383 if(m_cipher_state) {
384 m_cipher_state->clear_read_keys();
385 }
386 m_record_layer.clear_read_buffer();
387 }
388
389 // user canceled alerts are ignored
390
391 // RFC 8446 5.
392 // All the alerts listed in Section 6.2 MUST be sent with
393 // AlertLevel=fatal and MUST be treated as error alerts when received
394 // regardless of the AlertLevel in the message. Unknown Alert types
395 // MUST be treated as error alerts.
396 if(is_error_alert(alert) && !alert.is_fatal()) {
397 if(!expects_downgrade()) {
398 throw TLS_Exception(Alert::DecodeError, "Error alert not marked fatal");
399 }
400
401#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
403
404 // In TLS 1.2 error alerts might be marked as 'warnings' and would not
405 // demand an immediate shutdown. Until we are sure to talk to a TLS 1.3
406 // peer we must defer the shutdown and refrain from raising a decode
407 // error.
408 m_downgrade_info->received_tls_13_error_alert = true;
409#endif
410 }
411
412 if(alert.is_fatal()) {
413 shutdown();
414 }
415
416 callbacks().tls_alert(alert);
417
418 // Respond with our "close_notify" if the application requests us to.
419 if(is_close_notify_alert(alert) && callbacks().tls_peer_closed_connection()) {
420 close();
421 }
422}
423
424void Channel_Impl_13::shutdown() {
425 // RFC 8446 6.2
426 // Upon transmission or receipt of a fatal alert message, both
427 // parties MUST immediately close the connection.
428 m_can_read = false;
429 m_can_write = false;
430 m_cipher_state.reset();
431 m_active_state.reset();
432}
433
434#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
435
436void Channel_Impl_13::expect_downgrade(const Server_Information& server_info,
437 const std::vector<std::string>& next_protocols) {
438 Downgrade_Information di{
439 {},
440 {},
441 {},
442 server_info,
443 next_protocols,
445 m_callbacks,
446 m_session_manager,
447 m_credentials_manager,
448 m_rng,
449 m_policy,
450 false, // received_tls_13_error_alert
451 false // will_downgrade
452 };
453 m_downgrade_info = std::make_unique<Downgrade_Information>(std::move(di));
454}
455
456#endif
457
458void Channel_Impl_13::set_record_size_limits(const uint16_t outgoing_limit, const uint16_t incoming_limit) {
459 m_record_layer.set_record_size_limits(outgoing_limit, incoming_limit);
460}
461
463 m_handshake_layer.set_selected_certificate_type(cert_type);
464}
465
466} // namespace Botan::TLS
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
bool is_valid() const
Definition tls_alert.h:78
std::vector< uint8_t > serialize() const
Definition tls_alert.cpp:32
bool is_fatal() const
Definition tls_alert.h:93
Type type() const
Definition tls_alert.h:100
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)
virtual void maybe_handle_compatibility_mode(Compat_Mode_Situation situation)=0
const Policy & policy() const
SymmetricKey key_material_export(std::string_view label, std::string_view context, size_t length) const override
void handle(const Key_Update &key_update)
Credentials_Manager & credentials_manager()
void send_post_handshake_message(Post_Handshake_Message_13 message)
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
std::optional< Active_Connection_State_13 > m_active_state
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 send_fatal_alert(Alert::Type type)
virtual bool is_handshake_complete() const =0
static constexpr size_t IO_BUF_DEFAULT_SIZE
Definition tls_channel.h:38
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:153
constexpr bool holds_any_of(const std::variant< Ts... > &v) noexcept
Definition stl_util.h:66
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128