Botan 3.4.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) :
46 m_side(is_server ? Connection_Side::Server : Connection_Side::Client),
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) {
168 BOTAN_ASSERT(record.seq_no.has_value(), "decrypted application traffic had a sequence number");
169 callbacks().tls_record_received(record.seq_no.value(), record.fragment);
170 } else if(record.type == Record_Type::Alert) {
171 process_alert(record.fragment);
172 } else {
173 throw Unexpected_Message("Unexpected record type " + std::to_string(static_cast<size_t>(record.type)) +
174 " from counterparty");
175 }
176 }
177 } catch(TLS_Exception& e) {
179 throw;
181 // RFC 8446 5.2
182 // If the decryption fails, the receiver MUST terminate the connection
183 // with a "bad_record_mac" alert.
184 send_fatal_alert(Alert::BadRecordMac);
185 throw;
186 } catch(Decoding_Error&) {
187 send_fatal_alert(Alert::DecodeError);
188 throw;
189 } catch(...) {
190 send_fatal_alert(Alert::InternalError);
191 throw;
192 }
193}
194
195void Channel_Impl_13::handle(const Key_Update& key_update) {
196 // make sure Key_Update appears only at the end of a record; see description above
197 if(m_handshake_layer.has_pending_data()) {
198 throw Unexpected_Message("Unexpected additional post-handshake message data found in record");
199 }
200
201 m_cipher_state->update_read_keys();
202
203 // TODO: introduce some kind of rate limit of key updates, otherwise we
204 // might be forced into an endless loop of key updates.
205
206 // RFC 8446 4.6.3
207 // If the request_update field is set to "update_requested", then the
208 // receiver MUST send a KeyUpdate of its own with request_update set to
209 // "update_not_requested" prior to sending its next Application Data
210 // record.
211 if(key_update.expects_reciprocation()) {
212 // RFC 8446 4.6.3
213 // This mechanism allows either side to force an update to the
214 // multiple KeyUpdates while it is silent to respond with a single
215 // update.
217 }
218}
219
221 m_channel(channel), m_handshake_layer(handshake_layer) {}
222
224 Handshake_Layer& handshake_layer,
225 Transcript_Hash_State& transcript_hash) :
226 AggregatedMessages(channel, handshake_layer), m_transcript_hash(transcript_hash) {}
227
229 const Handshake_Message_13_Ref message) {
230 std::visit([&](const auto msg) { m_channel.callbacks().tls_inspect_handshake_msg(msg.get()); }, message);
231 m_message_buffer += m_handshake_layer.prepare_message(message, m_transcript_hash);
232 return *this;
233}
234
237 std::visit([&](const auto& msg) { m_channel.callbacks().tls_inspect_handshake_msg(msg); }, message);
238 m_message_buffer += m_handshake_layer.prepare_post_handshake_message(message);
239 return *this;
240}
241
243 BOTAN_STATE_CHECK(contains_messages());
244 m_channel.send_record(Record_Type::Handshake, m_message_buffer);
245 return std::exchange(m_message_buffer, {});
246}
247
249 // RFC 8446 5.
250 // The change_cipher_spec record is used only for compatibility purposes
251 // (see Appendix D.4).
252 //
253 // The only allowed CCS message content is 0x01, all other CCS records MUST
254 // be rejected by TLS 1.3 implementations.
255 send_record(Record_Type::ChangeCipherSpec, {0x01});
256}
257
258void Channel_Impl_13::to_peer(std::span<const uint8_t> data) {
259 if(!is_active()) {
260 throw Invalid_State("Data cannot be sent on inactive TLS connection");
261 }
262
263 // RFC 8446 4.6.3
264 // If the request_update field [of a received KeyUpdate] is set to
265 // "update_requested", then the receiver MUST send a KeyUpdate of its own
266 // with request_update set to "update_not_requested" prior to sending its
267 // next Application Data record.
268 // This mechanism allows either side to force an update to the entire
269 // connection, but causes an implementation which receives multiple
270 // KeyUpdates while it is silent to respond with a single update.
271 if(m_opportunistic_key_update) {
272 update_traffic_keys(false /* update_requested */);
273 m_opportunistic_key_update = false;
274 }
275
276 send_record(Record_Type::ApplicationData, {data.begin(), data.end()});
277}
278
280 if(alert.is_valid() && m_can_write) {
281 try {
282 send_record(Record_Type::Alert, alert.serialize());
283 } catch(...) { /* swallow it */
284 }
285 }
286
287 // Note: In TLS 1.3 sending a CloseNotify must not immediately lead to closing the reading end.
288 // RFC 8446 6.1
289 // Each party MUST send a "close_notify" alert before closing its write
290 // side of the connection, unless it has already sent some error alert.
291 // This does not have any effect on its read side of the connection.
292 if(is_close_notify_alert(alert) && m_can_write) {
293 m_can_write = false;
294 if(m_cipher_state) {
295 m_cipher_state->clear_write_keys();
296 }
297 }
298
299 if(is_error_alert(alert)) {
300 shutdown();
301 }
302}
303
305 return m_cipher_state != nullptr && m_cipher_state->can_encrypt_application_traffic() // handshake done
306 && m_can_write; // close() hasn't been called
307}
308
310 std::string_view context,
311 size_t length) const {
313 BOTAN_STATE_CHECK(m_cipher_state != nullptr && m_cipher_state->can_export_keys());
314 return SymmetricKey(m_cipher_state->export_key(label, context, length));
315}
316
324
325void Channel_Impl_13::send_record(Record_Type record_type, const std::vector<uint8_t>& record) {
327 BOTAN_STATE_CHECK(m_can_write);
328
329 const auto type = static_cast<Record_Type>(record_type);
330 auto to_write = m_record_layer.prepare_records(type, record, m_cipher_state.get());
331
332 // After the initial handshake message is sent, the record layer must
333 // adhere to a more strict record specification. Note that for the
334 // server case this is a NOOP.
335 // See (RFC 8446 5.1. regarding "legacy_record_version")
336 if(!m_first_message_sent && type == Record_Type::Handshake) {
337 m_record_layer.disable_sending_compat_mode();
338 m_first_message_sent = true;
339 }
340
341 // The dummy CCS must not be prepended if the following record is
342 // an unprotected Alert record.
343 if(prepend_ccs() && (m_cipher_state || record_type != Record_Type::Alert)) {
344 std::array<uint8_t, 1> ccs_content = {0x01};
345 const auto ccs = m_record_layer.prepare_records(Record_Type::ChangeCipherSpec, ccs_content, m_cipher_state.get());
346 to_write = concat(ccs, to_write);
347 }
348
349 callbacks().tls_emit_data(to_write);
350}
351
352void Channel_Impl_13::process_alert(const secure_vector<uint8_t>& record) {
353 Alert alert(record);
354
355 if(is_close_notify_alert(alert)) {
356 m_can_read = false;
357 if(m_cipher_state) {
358 m_cipher_state->clear_read_keys();
359 }
360 m_record_layer.clear_read_buffer();
361 }
362
363 // user canceled alerts are ignored
364
365 // RFC 8446 5.
366 // All the alerts listed in Section 6.2 MUST be sent with
367 // AlertLevel=fatal and MUST be treated as error alerts when received
368 // regardless of the AlertLevel in the message. Unknown Alert types
369 // MUST be treated as error alerts.
370 if(is_error_alert(alert) && !alert.is_fatal()) {
371 // In TLS 1.2 error alerts might be marked as 'warnings' and would not
372 // demand an immediate shutdown. Until we are sure to talk to a TLS 1.3
373 // peer we must defer the shutdown and refrain from raising a decode
374 // error.
375 if(expects_downgrade()) {
376 m_downgrade_info->received_tls_13_error_alert = true;
377 } else {
378 throw TLS_Exception(Alert::DecodeError, "Error alert not marked fatal"); // will shutdown in send_alert
379 }
380 }
381
382 if(alert.is_fatal()) {
383 shutdown();
384 }
385
386 callbacks().tls_alert(alert);
387
388 // Respond with our "close_notify" if the application requests us to.
389 if(is_close_notify_alert(alert) && callbacks().tls_peer_closed_connection()) {
390 close();
391 }
392}
393
394void Channel_Impl_13::shutdown() {
395 // RFC 8446 6.2
396 // Upon transmission or receipt of a fatal alert message, both
397 // parties MUST immediately close the connection.
398 m_can_read = false;
399 m_can_write = false;
400 m_cipher_state.reset();
401}
402
404 const std::vector<std::string>& next_protocols) {
406 {},
407 {},
408 {},
409 server_info,
410 next_protocols,
412 m_callbacks,
413 m_session_manager,
414 m_credentials_manager,
415 m_rng,
416 m_policy,
417 false, // received_tls_13_error_alert
418 false // will_downgrade
419 };
420 m_downgrade_info = std::make_unique<Downgrade_Information>(std::move(di));
421}
422
423void Channel_Impl_13::set_record_size_limits(const uint16_t outgoing_limit, const uint16_t incoming_limit) {
424 m_record_layer.set_record_size_limits(outgoing_limit, incoming_limit);
425}
426
428 m_handshake_layer.set_selected_certificate_type(cert_type);
429}
430
431} // namespace Botan::TLS
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:41
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:86
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
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:88
Type type() const
Definition tls_alert.h:93
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)
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
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
static std::vector< uint8_t > prepare_message(Handshake_Message_13_Ref message, Transcript_Hash_State &transcript_hash)
std::optional< Handshake_Message_13 > next_message(const Policy &policy, Transcript_Hash_State &transcript_hash)
std::optional< Post_Handshake_Message_13 > next_post_handshake_message(const Policy &policy)
static std::vector< uint8_t > prepare_post_handshake_message(const Post_Handshake_Message_13 &message)
void copy_data(std::span< const uint8_t > data_from_peer)
void set_selected_certificate_type(Certificate_Type cert_type)
bool expects_reciprocation() const
void copy_data(std::span< const uint8_t > data_from_peer)
std::vector< uint8_t > prepare_records(Record_Type type, std::span< const uint8_t > data, Cipher_State *cipher_state=nullptr) const
void set_record_size_limits(uint16_t outgoing_limit, uint16_t incoming_limit)
ReadResult< Record > next_record(Cipher_State *cipher_state=nullptr)
Alert::Type type() const
Definition tls_exceptn.h:21
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:141
constexpr bool holds_any_of(const std::variant< Ts... > &v) noexcept
Definition stl_util.h:279
decltype(auto) concat(Ts &&... buffers)
Definition stl_util.h:258