Botan 3.9.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/hash.h>
13#include <botan/tls_messages.h>
14#include <botan/internal/stl_util.h>
15#include <botan/internal/tls_cipher_state.h>
16#include <botan/internal/tls_handshake_state.h>
17#include <botan/internal/tls_record.h>
18#include <botan/internal/tls_seq_numbers.h>
19
20#include <array>
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),
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);
63 BOTAN_ASSERT_NONNULL(m_policy);
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(expects_downgrade()) {
80 }
81
82 m_record_layer.copy_data(data);
83
84 while(true) {
85 // RFC 8446 6.1
86 // Any data received after a closure alert has been received MUST be ignored.
87 //
88 // ... this data might already be in the record layer's read buffer.
89 if(!m_can_read) {
90 return 0;
91 }
92
93 auto result = m_record_layer.next_record(m_cipher_state.get());
94
95 if(std::holds_alternative<BytesNeeded>(result)) {
96 return std::get<BytesNeeded>(result);
97 }
98
99 const auto& record = std::get<Record>(result);
100
101 // RFC 8446 5.1
102 // Handshake messages MUST NOT be interleaved with other record types.
103 if(record.type != Record_Type::Handshake && m_handshake_layer.has_pending_data()) {
104 throw Unexpected_Message("Expected remainder of a handshake message");
105 }
106
107 if(record.type == Record_Type::Handshake) {
108 m_handshake_layer.copy_data(record.fragment);
109
110 if(!is_handshake_complete()) {
111 while(auto handshake_msg = m_handshake_layer.next_message(policy(), m_transcript_hash)) {
112 // RFC 8446 5.1
113 // Handshake messages MUST NOT span key changes. Implementations
114 // MUST verify that all messages immediately preceding a key change
115 // align with a record boundary; if not, then they MUST terminate the
116 // connection with an "unexpected_message" alert. Because the
117 // ClientHello, EndOfEarlyData, ServerHello, Finished, and KeyUpdate
118 // messages can immediately precede a key change, implementations
119 // MUST send these messages in alignment with a record boundary.
120 //
121 // Note: Hello_Retry_Request was added to the list below although it cannot immediately precede a key change.
122 // However, there cannot be any further sensible messages in the record after HRR.
123 //
124 // Note: Server_Hello_12 was deliberately not included in the check below because in TLS 1.2 Server Hello and
125 // other handshake messages can be legally coalesced in a single record.
126 //
128 Client_Hello_13 /*, EndOfEarlyData,*/,
131 Finished_13>(handshake_msg.value()) &&
132 m_handshake_layer.has_pending_data()) {
133 throw Unexpected_Message("Unexpected additional handshake message data found in record");
134 }
135
136 process_handshake_msg(std::move(handshake_msg.value()));
137
138 if(is_downgrading()) {
139 // Downgrade to TLS 1.2 was detected. Stop everything we do and await being replaced by a 1.2 implementation.
140 return 0;
141 } else if(m_downgrade_info != nullptr) {
142 // We received a TLS 1.3 error alert that could have been a TLS 1.2 warning alert.
143 // Now that we know that we are talking to a TLS 1.3 server, shut down.
144 if(m_downgrade_info->received_tls_13_error_alert) {
145 shutdown();
146 }
147
148 // Downgrade can only be indicated in the first received peer message. This was not the case.
149 m_downgrade_info.reset();
150 }
151
152 // After the initial handshake message is received, the record
153 // layer must be more restrictive.
154 // See RFC 8446 5.1 regarding "legacy_record_version"
155 if(!m_first_message_received) {
156 m_record_layer.disable_receiving_compat_mode();
157 m_first_message_received = true;
158 }
159 }
160 } else {
161 while(auto handshake_msg = m_handshake_layer.next_post_handshake_message(policy())) {
162 process_post_handshake_msg(std::move(handshake_msg.value()));
163 }
164 }
165 } else if(record.type == Record_Type::ChangeCipherSpec) {
167 } else if(record.type == Record_Type::ApplicationData) {
169 if(!m_cipher_state->can_decrypt_application_traffic()) {
170 throw Unexpected_Message("Application data received before handshake completion");
171 }
172 BOTAN_ASSERT(record.seq_no.has_value(), "decrypted application traffic had a sequence number");
173 callbacks().tls_record_received(record.seq_no.value(), record.fragment);
174 } else if(record.type == Record_Type::Alert) {
175 process_alert(record.fragment);
176 } else {
177 throw Unexpected_Message("Unexpected record type " + std::to_string(static_cast<size_t>(record.type)) +
178 " from counterparty");
179 }
180 }
181 } catch(TLS_Exception& e) {
183 throw;
185 // RFC 8446 5.2
186 // If the decryption fails, the receiver MUST terminate the connection
187 // with a "bad_record_mac" alert.
188 send_fatal_alert(Alert::BadRecordMac);
189 throw;
190 } catch(Decoding_Error&) {
191 send_fatal_alert(Alert::DecodeError);
192 throw;
193 } catch(...) {
194 send_fatal_alert(Alert::InternalError);
195 throw;
196 }
197}
198
199void Channel_Impl_13::handle(const Key_Update& key_update) {
200 // make sure Key_Update appears only at the end of a record; see description above
201 if(m_handshake_layer.has_pending_data()) {
202 throw Unexpected_Message("Unexpected additional post-handshake message data found in record");
203 }
204
205 m_cipher_state->update_read_keys(*this);
206
207 // TODO: introduce some kind of rate limit of key updates, otherwise we
208 // might be forced into an endless loop of key updates.
209
210 // RFC 8446 4.6.3
211 // If the request_update field is set to "update_requested", then the
212 // receiver MUST send a KeyUpdate of its own with request_update set to
213 // "update_not_requested" prior to sending its next Application Data
214 // record.
215 if(key_update.expects_reciprocation()) {
216 // RFC 8446 4.6.3
217 // This mechanism allows either side to force an update to the
218 // multiple KeyUpdates while it is silent to respond with a single
219 // update.
221 }
222}
223
226
228 Handshake_Layer& handshake_layer,
229 Transcript_Hash_State& transcript_hash) :
230 AggregatedMessages(channel, handshake_layer), m_transcript_hash(transcript_hash) {}
231
233 const Handshake_Message_13_Ref message) {
234 std::visit([&](const auto msg) { m_channel.callbacks().tls_inspect_handshake_msg(msg.get()); }, message);
235 m_message_buffer += m_handshake_layer.prepare_message(message, m_transcript_hash);
236 return *this;
237}
238
241 std::visit([&](const auto& msg) { m_channel.callbacks().tls_inspect_handshake_msg(msg); }, message);
242 m_message_buffer += m_handshake_layer.prepare_post_handshake_message(message);
243 return *this;
244}
245
249 return std::exchange(m_message_buffer, {});
250}
251
253 // RFC 8446 5.
254 // The change_cipher_spec record is used only for compatibility purposes
255 // (see Appendix D.4).
256 //
257 // The only allowed CCS message content is 0x01, all other CCS records MUST
258 // be rejected by TLS 1.3 implementations.
259 send_record(Record_Type::ChangeCipherSpec, {0x01});
260}
261
262void Channel_Impl_13::to_peer(std::span<const uint8_t> data) {
263 if(!is_active()) {
264 throw Invalid_State("Data cannot be sent on inactive TLS connection");
265 }
266
267 // RFC 8446 4.6.3
268 // If the request_update field [of a received KeyUpdate] is set to
269 // "update_requested", then the receiver MUST send a KeyUpdate of its own
270 // with request_update set to "update_not_requested" prior to sending its
271 // next Application Data record.
272 // This mechanism allows either side to force an update to the entire
273 // connection, but causes an implementation which receives multiple
274 // KeyUpdates while it is silent to respond with a single update.
275 if(m_opportunistic_key_update) {
276 update_traffic_keys(false /* update_requested */);
277 m_opportunistic_key_update = false;
278 }
279
280 send_record(Record_Type::ApplicationData, {data.begin(), data.end()});
281}
282
284 if(alert.is_valid() && m_can_write) {
285 try {
286 send_record(Record_Type::Alert, alert.serialize());
287 } catch(...) { /* swallow it */
288 }
289 }
290
291 // Note: In TLS 1.3 sending a CloseNotify must not immediately lead to closing the reading end.
292 // RFC 8446 6.1
293 // Each party MUST send a "close_notify" alert before closing its write
294 // side of the connection, unless it has already sent some error alert.
295 // This does not have any effect on its read side of the connection.
296 if(is_close_notify_alert(alert) && m_can_write) {
297 m_can_write = false;
298 if(m_cipher_state) {
299 m_cipher_state->clear_write_keys();
300 }
301 }
302
303 if(is_error_alert(alert)) {
304 shutdown();
305 }
306}
307
309 return m_cipher_state != nullptr && m_cipher_state->can_encrypt_application_traffic() // handshake done
310 && m_can_write; // close() hasn't been called
311}
312
314 std::string_view context,
315 size_t length) const {
317 BOTAN_STATE_CHECK(m_cipher_state != nullptr && m_cipher_state->can_export_keys());
318 return SymmetricKey(m_cipher_state->export_key(label, context, length));
319}
320
328
329void Channel_Impl_13::send_record(Record_Type type, const std::vector<uint8_t>& record) {
331 BOTAN_STATE_CHECK(m_can_write);
332
333 auto to_write = m_record_layer.prepare_records(type, record, m_cipher_state.get());
334
335 // After the initial handshake message is sent, the record layer must
336 // adhere to a more strict record specification. Note that for the
337 // server case this is a NOOP.
338 // See (RFC 8446 5.1. regarding "legacy_record_version")
339 if(!m_first_message_sent && type == Record_Type::Handshake) {
340 m_record_layer.disable_sending_compat_mode();
341 m_first_message_sent = true;
342 }
343
344 // The dummy CCS must not be prepended if the following record is
345 // an unprotected Alert record.
346 if(prepend_ccs() && (m_cipher_state || type != Record_Type::Alert)) {
347 std::array<uint8_t, 1> ccs_content = {0x01};
348 const auto ccs = m_record_layer.prepare_records(Record_Type::ChangeCipherSpec, ccs_content, m_cipher_state.get());
349 to_write = concat(ccs, to_write);
350 }
351
352 callbacks().tls_emit_data(to_write);
353}
354
355void Channel_Impl_13::process_alert(const secure_vector<uint8_t>& record) {
356 Alert alert(record);
357
358 if(is_close_notify_alert(alert)) {
359 m_can_read = false;
360 if(m_cipher_state) {
361 m_cipher_state->clear_read_keys();
362 }
363 m_record_layer.clear_read_buffer();
364 }
365
366 // user canceled alerts are ignored
367
368 // RFC 8446 5.
369 // All the alerts listed in Section 6.2 MUST be sent with
370 // AlertLevel=fatal and MUST be treated as error alerts when received
371 // regardless of the AlertLevel in the message. Unknown Alert types
372 // MUST be treated as error alerts.
373 if(is_error_alert(alert) && !alert.is_fatal()) {
374 // In TLS 1.2 error alerts might be marked as 'warnings' and would not
375 // demand an immediate shutdown. Until we are sure to talk to a TLS 1.3
376 // peer we must defer the shutdown and refrain from raising a decode
377 // error.
378 if(expects_downgrade()) {
379 m_downgrade_info->received_tls_13_error_alert = true;
380 } else {
381 throw TLS_Exception(Alert::DecodeError, "Error alert not marked fatal"); // will shutdown in send_alert
382 }
383 }
384
385 if(alert.is_fatal()) {
386 shutdown();
387 }
388
389 callbacks().tls_alert(alert);
390
391 // Respond with our "close_notify" if the application requests us to.
392 if(is_close_notify_alert(alert) && callbacks().tls_peer_closed_connection()) {
393 close();
394 }
395}
396
397void Channel_Impl_13::shutdown() {
398 // RFC 8446 6.2
399 // Upon transmission or receipt of a fatal alert message, both
400 // parties MUST immediately close the connection.
401 m_can_read = false;
402 m_can_write = false;
403 m_cipher_state.reset();
404}
405
407 const std::vector<std::string>& next_protocols) {
409 {},
410 {},
411 {},
412 server_info,
413 next_protocols,
415 m_callbacks,
416 m_session_manager,
417 m_credentials_manager,
418 m_rng,
419 m_policy,
420 false, // received_tls_13_error_alert
421 false // will_downgrade
422 };
423 m_downgrade_info = std::make_unique<Downgrade_Information>(std::move(di));
424}
425
426void Channel_Impl_13::set_record_size_limits(const uint16_t outgoing_limit, const uint16_t incoming_limit) {
427 m_record_layer.set_record_size_limits(outgoing_limit, incoming_limit);
428}
429
431 m_handshake_layer.set_selected_certificate_type(cert_type);
432}
433
434} // 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:285
constexpr auto concat(Rs &&... ranges)
Definition stl_util.h:255
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69