Botan 3.10.0
Crypto and TLS for C&
tls_server_impl_13.cpp
Go to the documentation of this file.
1/*
2* TLS Server - implementation for TLS 1.3
3* (C) 2022 Jack Lloyd
4* 2022 René Meusel - Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/internal/tls_server_impl_13.h>
10
11#include <botan/credentials_manager.h>
12#include <botan/rng.h>
13#include <botan/internal/stl_util.h>
14#include <botan/internal/tls_cipher_state.h>
15
16namespace Botan::TLS {
17
18Server_Impl_13::Server_Impl_13(const std::shared_ptr<Callbacks>& callbacks,
19 const std::shared_ptr<Session_Manager>& session_manager,
20 const std::shared_ptr<Credentials_Manager>& credentials_manager,
21 const std::shared_ptr<const Policy>& policy,
22 const std::shared_ptr<RandomNumberGenerator>& rng) :
24#if defined(BOTAN_HAS_TLS_12)
25 if(policy->allow_tls12()) {
26 expect_downgrade({}, {});
27 }
28#endif
29
30 m_transitions.set_expected_next(Handshake_Type::ClientHello);
31}
32
35 const auto& eee = m_handshake_state.encrypted_extensions().extensions();
36 if(auto* const alpn = eee.get<Application_Layer_Protocol_Notification>()) {
37 return alpn->single_protocol();
38 }
39 }
40
41 return "";
42}
43
44std::vector<X509_Certificate> Server_Impl_13::peer_cert_chain() const {
45 if(m_handshake_state.has_client_certificate_msg() &&
46 m_handshake_state.client_certificate().has_certificate_chain()) {
47 return m_handshake_state.client_certificate().cert_chain();
48 }
49
50 if(m_resumed_session.has_value()) {
51 return m_resumed_session->peer_certs();
52 }
53
54 return {};
55}
56
57std::shared_ptr<const Public_Key> Server_Impl_13::peer_raw_public_key() const {
58 if(m_handshake_state.has_client_certificate_msg() && m_handshake_state.client_certificate().is_raw_public_key()) {
59 return m_handshake_state.client_certificate().public_key();
60 }
61
62 if(m_resumed_session.has_value()) {
63 return m_resumed_session->peer_raw_public_key();
64 }
65
66 return nullptr;
67}
68
69std::optional<std::string> Server_Impl_13::external_psk_identity() const {
70 return m_psk_identity;
71}
72
74 // RFC 8446 4.2.9
75 // This extension also restricts the modes for use with PSK resumption.
76 // Servers SHOULD NOT send NewSessionTicket with tickets that are not
77 // compatible with the advertised modes; however, if a server does so,
78 // the impact will just be that the client's attempts at resumption fail.
79 //
80 // Note: Applications can overrule this by calling send_new_session_tickets()
81 // regardless of this method indicating no support for tickets.
82 //
83 // TODO: Implement other PSK KE modes than PSK_DHE_KE
84 return is_handshake_complete() && m_handshake_state.client_hello().extensions().has<PSK_Key_Exchange_Modes>() &&
85 value_exists(m_handshake_state.client_hello().extensions().get<PSK_Key_Exchange_Modes>()->modes(),
87}
88
89size_t Server_Impl_13::send_new_session_tickets(const size_t tickets) {
91
92 if(tickets == 0) {
93 return 0;
94 }
95
97 size_t tickets_created = 0;
98
99 for(size_t i = 0; i < tickets; ++i) {
100 auto nonce = m_cipher_state->next_ticket_nonce();
101 const Session session(m_cipher_state->psk(nonce),
102 std::nullopt, // early data not yet implemented
103 policy().session_ticket_lifetime(),
106 m_handshake_state.client_hello(),
107 m_handshake_state.server_hello(),
108 callbacks(),
109 rng());
110
111 if(callbacks().tls_should_persist_resumption_information(session)) {
112 if(auto handle = session_manager().establish(session)) {
113 flight.add(New_Session_Ticket_13(std::move(nonce), session, handle.value(), callbacks()));
114 ++tickets_created;
115 }
116 }
117 }
118
119 if(flight.contains_messages()) {
120 flight.send();
121 }
122
123 return tickets_created;
124}
125
126void Server_Impl_13::process_handshake_msg(Handshake_Message_13 message) {
127 std::visit(
128 [&](auto msg) {
129 // first verify that the message was expected by the state machine...
130 m_transitions.confirm_transition_to(msg.get().type());
131
132 // ... then allow the library user to abort on their discretion
133 callbacks().tls_inspect_handshake_msg(msg.get());
134
135 // ... finally handle the message
136 handle(msg.get());
137 },
138 m_handshake_state.received(std::move(message)));
139}
140
141void Server_Impl_13::process_post_handshake_msg(Post_Handshake_Message_13 message) {
142 BOTAN_STATE_CHECK(is_handshake_complete());
143
144 std::visit([&](auto msg) { handle(msg); }, m_handshake_state.received(std::move(message)));
145}
146
147void Server_Impl_13::process_dummy_change_cipher_spec() {
148 // RFC 8446 5.
149 // If an implementation detects a change_cipher_spec record received before
150 // the first ClientHello message or after the peer's Finished message, it MUST be
151 // treated as an unexpected record type [("unexpected_message" alert)].
152 if(!m_handshake_state.has_client_hello() || m_handshake_state.has_client_finished()) {
153 throw TLS_Exception(Alert::UnexpectedMessage, "Received an unexpected dummy Change Cipher Spec");
154 }
155
156 // RFC 8446 5.
157 // An implementation may receive an unencrypted record of type change_cipher_spec [...]
158 // at any time after the first ClientHello message has been sent or received
159 // and before the peer's Finished message has been received [...]
160 // and MUST simply drop it without further processing.
161 //
162 // ... no further processing.
163}
164
166 return m_handshake_state.handshake_finished();
167}
168
169void Server_Impl_13::maybe_log_secret(std::string_view label, std::span<const uint8_t> secret) const {
170 if(policy().allow_ssl_key_log_file()) {
171 callbacks().tls_ssl_key_log_data(label, m_handshake_state.client_hello().random(), secret);
172 }
173}
174
175void Server_Impl_13::downgrade() {
176 BOTAN_ASSERT_NOMSG(expects_downgrade());
177
178 request_downgrade();
179
180 // After this, no further messages are expected here because this instance
181 // will be replaced by a Server_Impl_12.
182 m_transitions.set_expected_next({});
183}
184
185void Server_Impl_13::maybe_handle_compatibility_mode() {
186 BOTAN_ASSERT_NOMSG(m_handshake_state.has_client_hello());
187 BOTAN_ASSERT_NOMSG(m_handshake_state.has_hello_retry_request() || m_handshake_state.has_server_hello());
188
189 // RFC 8446 Appendix D.4 (Middlebox Compatibility Mode)
190 // The server sends a dummy change_cipher_spec record immediately after
191 // its first handshake message. This may either be after a ServerHello or
192 // a HelloRetryRequest.
193 //
194 // This "compatibility mode" is partially negotiated: the client can opt
195 // to provide a session ID or not, and the server has to echo it. Either
196 // side can send change_cipher_spec at any time during the handshake, as
197 // they must be ignored by the peer, but if the client sends a non-empty
198 // session ID, the server MUST send the change_cipher_spec as described
199 // [above].
200 //
201 // Technically, the usage of compatibility mode is fully up to the client
202 // sending a non-empty session ID. Nevertheless, when the policy requests
203 // it we send a CCS regardless. Note that this is perfectly legal and also
204 // satisfies some BoGo tests that expect this behaviour.
205 //
206 // Send a CCS immediately after the _first_ handshake message. I.e. either
207 // after Hello Retry Request (exclusively) or after a Server Hello that was
208 // not preseded by a Hello Retry Request.
209 const bool just_after_first_handshake_message =
210 m_handshake_state.has_hello_retry_request() ^ m_handshake_state.has_server_hello();
211 const bool client_requested_compatibility_mode = !m_handshake_state.client_hello().session_id().empty();
212
213 if(just_after_first_handshake_message &&
214 (policy().tls_13_middlebox_compatibility_mode() || client_requested_compatibility_mode)) {
215 send_dummy_change_cipher_spec();
216 }
217}
218
219void Server_Impl_13::handle_reply_to_client_hello(Server_Hello_13 server_hello) {
220 const auto& client_hello = m_handshake_state.client_hello();
221 const auto& exts = client_hello.extensions();
222
223 const bool uses_psk = server_hello.extensions().has<PSK>();
224
225 const auto cipher_opt = Ciphersuite::by_id(server_hello.ciphersuite());
226 BOTAN_ASSERT_NOMSG(cipher_opt.has_value());
227 const auto& cipher = cipher_opt.value();
228 m_transcript_hash.set_algorithm(cipher.prf_algo());
229
230 std::unique_ptr<Cipher_State> psk_cipher_state;
231 if(uses_psk) {
232 auto* psk_extension = server_hello.extensions().get<PSK>();
233
234 psk_cipher_state =
235 std::visit(overloaded{[&, this](Session session) {
236 m_resumed_session = std::move(session);
237 return Cipher_State::init_with_psk(Connection_Side::Server,
238 Cipher_State::PSK_Type::Resumption,
239 m_resumed_session->extract_master_secret(),
240 cipher.prf_algo());
241 },
242 [&, this](ExternalPSK psk) {
243 m_psk_identity = psk.identity();
244 return Cipher_State::init_with_psk(Connection_Side::Server,
245 Cipher_State::PSK_Type::External,
246 psk.extract_master_secret(),
247 cipher.prf_algo());
248 }},
249 psk_extension->take_session_to_resume_or_psk());
250
251 // RFC 8446 4.2.11
252 // Prior to accepting PSK key establishment, the server MUST validate
253 // the corresponding binder value (see Section 4.2.11.2 below). If this
254 // value is not present or does not validate, the server MUST abort the
255 // handshake.
256 // Servers SHOULD NOT attempt to validate multiple binders; rather,
257 // they SHOULD select a single PSK and validate solely the binder that
258 // corresponds to that PSK.
259 //
260 // Note: PSK selection was performed earlier, resulting in the existence
261 // of this extension in the first place.
262 if(!exts.get<PSK>()->validate_binder(*psk_extension,
263 psk_cipher_state->psk_binder_mac(m_transcript_hash.truncated()))) {
264 throw TLS_Exception(Alert::DecryptError, "PSK binder does not check out");
265 }
266
267 // RFC 8446 4.2.10
268 // For PSKs provisioned via NewSessionTicket, a server MUST validate
269 // that the ticket age for the selected PSK identity [...] is within a
270 // small tolerance of the time since the ticket was issued. If it is
271 // not, the server SHOULD proceed with the handshake but reject 0-RTT,
272 // and SHOULD NOT take any other action that assumes that this
273 // ClientHello is fresh.
274 //
275 // TODO: When implementing Early Data (0-RTT) we should take the above
276 // paragraph into account. Note that there are BoGo tests that
277 // validate this behaviour. Namely: TLS13-TicketAgeSkew-*
278 }
279
280 // This sends the server_hello to the peer.
281 // NOTE: the server_hello variable is moved into the handshake state. Later
282 // references to the Server Hello will need to consult the handshake
283 // state object!
284 send_handshake_message(m_handshake_state.sending(std::move(server_hello)));
285 maybe_handle_compatibility_mode();
286
287 // Setup encryption for all the remaining handshake messages
288 m_cipher_state = [&] {
289 // Currently, PSK without DHE is not implemented...
290 auto* const my_keyshare = m_handshake_state.server_hello().extensions().get<Key_Share>();
291 BOTAN_ASSERT_NONNULL(my_keyshare);
292
293 if(uses_psk) {
294 BOTAN_ASSERT_NONNULL(psk_cipher_state);
295 psk_cipher_state->advance_with_client_hello(m_transcript_hash.previous(), *this);
296 psk_cipher_state->advance_with_server_hello(
297 cipher, my_keyshare->take_shared_secret(), m_transcript_hash.current(), *this);
298
299 return std::move(psk_cipher_state);
300 } else {
301 return Cipher_State::init_with_server_hello(
302 m_side, my_keyshare->take_shared_secret(), cipher, m_transcript_hash.current(), *this);
303 }
304 }();
305
306 auto flight = aggregate_handshake_messages();
307 flight.add(m_handshake_state.sending(Encrypted_Extensions(client_hello, policy(), callbacks())));
308
309 if(!uses_psk) {
310 // RFC 8446 4.3.2
311 // A server which is authenticating with a certificate MAY optionally
312 // request a certificate from the client. This message, if sent, MUST
313 // follow EncryptedExtensions.
314 if(auto certificate_request =
315 Certificate_Request_13::maybe_create(client_hello, credentials_manager(), callbacks(), policy())) {
316 flight.add(m_handshake_state.sending(std::move(certificate_request.value())));
317 }
318
319 const auto& enc_exts = m_handshake_state.encrypted_extensions().extensions();
320
321 // RFC 7250 4.2
322 // This client_certificate_type extension in the server hello then
323 // indicates the type of certificates the client is requested to provide
324 // in a subsequent certificate payload.
325 //
326 // Note: TLS 1.3 carries this extension in the Encrypted Extensions
327 // message instead of the Server Hello.
328 if(auto* client_cert_type = enc_exts.get<Client_Certificate_Type>()) {
329 set_selected_certificate_type(client_cert_type->selected_certificate_type());
330 }
331
332 // RFC 8446 4.4.2
333 // If the corresponding certificate type extension [...] was not
334 // negotiated in EncryptedExtensions, or the X.509 certificate type
335 // was negotiated, then each CertificateEntry contains a DER-encoded
336 // X.509 certificate.
337 const auto cert_type = [&] {
338 if(auto* server_cert_type = enc_exts.get<Server_Certificate_Type>()) {
339 return server_cert_type->selected_certificate_type();
340 } else {
341 return Certificate_Type::X509;
342 }
343 }();
344
345 flight.add(m_handshake_state.sending(Certificate_13(client_hello, credentials_manager(), callbacks(), cert_type)))
346 .add(m_handshake_state.sending(Certificate_Verify_13(m_handshake_state.server_certificate(),
347 client_hello.signature_schemes(),
348 client_hello.sni_hostname(),
349 m_transcript_hash.current(),
350 Connection_Side::Server,
351 credentials_manager(),
352 policy(),
353 callbacks(),
354 rng())));
355 }
356
357 flight.add(m_handshake_state.sending(Finished_13(m_cipher_state.get(), m_transcript_hash.current())));
358
359 if(client_hello.extensions().has<Record_Size_Limit>() &&
360 m_handshake_state.encrypted_extensions().extensions().has<Record_Size_Limit>()) {
361 // RFC 8449 4.
362 // When the "record_size_limit" extension is negotiated, an endpoint
363 // MUST NOT generate a protected record with plaintext that is larger
364 // than the RecordSizeLimit value it receives from its peer.
365 // Unprotected messages are not subject to this limit.
366 //
367 // Hence, the limit is set just before we start sending encrypted records.
368 //
369 // RFC 8449 4.
370 // The record size limit only applies to records sent toward the
371 // endpoint that advertises the limit. An endpoint can send records
372 // that are larger than the limit it advertises as its own limit.
373 //
374 // Hence, the "outgoing" limit is what the client requested and the
375 // "incoming" limit is what we will request in the Encrypted Extensions.
376 auto* const outgoing_limit = client_hello.extensions().get<Record_Size_Limit>();
377 auto* const incoming_limit = m_handshake_state.encrypted_extensions().extensions().get<Record_Size_Limit>();
378 set_record_size_limits(outgoing_limit->limit(), incoming_limit->limit());
379 }
380
381 flight.send();
382
383 m_cipher_state->advance_with_server_finished(m_transcript_hash.current(), *this);
384
385 if(m_handshake_state.has_certificate_request()) {
386 // RFC 8446 4.4.2
387 // The client MUST send a Certificate message if and only if the server
388 // has requested client authentication via a CertificateRequest message
389 // [...]. If the server requests client authentication but no
390 // suitable certificate is available, the client MUST send a Certificate
391 // message containing no certificates [...].
392 m_transitions.set_expected_next(Handshake_Type::Certificate);
393 } else {
394 m_transitions.set_expected_next(Handshake_Type::Finished);
395 }
396}
397
398void Server_Impl_13::handle_reply_to_client_hello(Hello_Retry_Request hello_retry_request) {
399 auto cipher = Ciphersuite::by_id(hello_retry_request.ciphersuite());
400 BOTAN_ASSERT_NOMSG(cipher.has_value()); // should work, since we chose that suite
401
402 send_handshake_message(m_handshake_state.sending(std::move(hello_retry_request)));
403 maybe_handle_compatibility_mode();
404
405 m_transcript_hash = Transcript_Hash_State::recreate_after_hello_retry_request(cipher->prf_algo(), m_transcript_hash);
406
407 m_transitions.set_expected_next(Handshake_Type::ClientHello);
408}
409
410void Server_Impl_13::handle(const Client_Hello_12& ch) {
411 // The detailed handling of the TLS 1.2 compliant Client Hello is left to
412 // the TLS 1.2 server implementation.
413 BOTAN_UNUSED(ch);
414
415 // After we sent a Hello Retry Request we must not accept a downgrade.
416 if(m_handshake_state.has_hello_retry_request()) {
417 throw TLS_Exception(Alert::UnexpectedMessage, "Received a TLS 1.2 Client Hello after Hello Retry Request");
418 }
419
420 // RFC 8446 Appendix D.2
421 // If the "supported_versions" extension is absent and the server only
422 // supports versions greater than ClientHello.legacy_version, the server
423 // MUST abort the handshake with a "protocol_version" alert.
424 //
425 // If we're not expecting a downgrade, we only support TLS 1.3.
426 if(!expects_downgrade()) {
427 throw TLS_Exception(Alert::ProtocolVersion, "Received a legacy Client Hello");
428 }
429
430 downgrade();
431}
432
433void Server_Impl_13::handle(const Client_Hello_13& client_hello) {
434 const auto& exts = client_hello.extensions();
435
436 const bool is_initial_client_hello = !m_handshake_state.has_hello_retry_request();
437
438 if(is_initial_client_hello) {
439 const auto preferred_version = client_hello.highest_supported_version(policy());
440 if(!preferred_version) {
441 throw TLS_Exception(Alert::ProtocolVersion, "No shared TLS version");
442 }
443
444 // RFC 8446 4.2.2
445 // Clients MUST NOT use cookies in their initial ClientHello in subsequent
446 // connections.
447 if(exts.has<Cookie>()) {
448 throw TLS_Exception(Alert::IllegalParameter, "Received a Cookie in the initial client hello");
449 }
450 }
451
452 // TODO: Implement support for PSK. For now, we ignore any such extensions
453 // and always revert to a standard key exchange.
454 if(!exts.has<Supported_Groups>()) {
455 throw Not_Implemented("PSK-only handshake NYI");
456 }
457
458 // RFC 8446 9.2
459 // If containing a "supported_groups" extension, [Client Hello] MUST
460 // also contain a "key_share" extension, and vice versa.
461 //
462 // This was validated before in the Client_Hello_13 constructor.
463 BOTAN_ASSERT_NOMSG(exts.has<Key_Share>());
464
465 if(!is_initial_client_hello) {
466 const auto& hrr_exts = m_handshake_state.hello_retry_request().extensions();
467 const auto offered_groups = exts.get<Key_Share>()->offered_groups();
468 const auto selected_group = hrr_exts.get<Key_Share>()->selected_group();
469 if(offered_groups.size() != 1 || offered_groups.at(0) != selected_group) {
470 throw TLS_Exception(Alert::IllegalParameter, "Client did not comply with the requested key exchange group");
471 }
472 }
473
474 callbacks().tls_examine_extensions(exts, Connection_Side::Client, client_hello.type());
475 std::visit([this](auto msg) { handle_reply_to_client_hello(std::move(msg)); },
476 Server_Hello_13::create(client_hello,
477 is_initial_client_hello,
478 session_manager(),
479 credentials_manager(),
480 rng(),
481 policy(),
482 callbacks()));
483}
484
485void Server_Impl_13::handle(const Certificate_13& certificate_msg) {
486 // RFC 8446 4.3.2
487 // certificate_request_context: [...] This field SHALL be zero length
488 // unless used for the post-handshake authentication exchanges [...].
489 if(!is_handshake_complete() && !certificate_msg.request_context().empty()) {
490 throw TLS_Exception(Alert::DecodeError, "Received a client certificate message with non-empty request context");
491 }
492
493 // RFC 8446 4.4.2
494 // Extensions in the Certificate message from the client MUST correspond
495 // to extensions in the CertificateRequest message from the server.
496 certificate_msg.validate_extensions(m_handshake_state.certificate_request().extensions().extension_types(),
497 callbacks());
498
499 // RFC 8446 4.4.2.4
500 // If the client does not send any certificates (i.e., it sends an empty
501 // Certificate message), the server MAY at its discretion either continue
502 // the handshake without client authentication or abort the handshake with
503 // a "certificate_required" alert.
504 if(certificate_msg.empty()) {
505 if(policy().require_client_certificate_authentication()) {
506 throw TLS_Exception(Alert::CertificateRequired, "Policy requires client send a certificate, but it did not");
507 }
508
509 // RFC 8446 4.4.2
510 // A Finished message MUST be sent regardless of whether the
511 // Certificate message is empty.
512 m_transitions.set_expected_next(Handshake_Type::Finished);
513 } else {
514 // RFC 8446 4.4.2.4
515 // [...], if some aspect of the certificate chain was unacceptable
516 // (e.g., it was not signed by a known, trusted CA), the server MAY at
517 // its discretion either continue the handshake (considering the client
518 // unauthenticated) or abort the handshake.
519 //
520 // TODO: We could make this dependent on Policy::require_client_auth().
521 // Though, apps may also override Callbacks::tls_verify_cert_chain()
522 // and 'ignore' validation issues to a certain extent.
523 certificate_msg.verify(callbacks(),
524 policy(),
525 credentials_manager(),
526 m_handshake_state.client_hello().sni_hostname(),
527 m_handshake_state.client_hello().extensions().has<Certificate_Status_Request>());
528
529 // RFC 8446 4.4.3
530 // Clients MUST send this message whenever authenticating via a
531 // certificate (i.e., when the Certificate message
532 // is non-empty). When sent, this message MUST appear immediately after
533 // the Certificate message [...].
534 m_transitions.set_expected_next(Handshake_Type::CertificateVerify);
535 }
536}
537
538void Server_Impl_13::handle(const Certificate_Verify_13& certificate_verify_msg) {
539 // RFC 8446 4.4.3
540 // If sent by a client, the signature algorithm used in the signature
541 // MUST be one of those present in the supported_signature_algorithms
542 // field of the "signature_algorithms" extension in the
543 // CertificateRequest message.
544 const auto offered = m_handshake_state.certificate_request().signature_schemes();
545 if(!value_exists(offered, certificate_verify_msg.signature_scheme())) {
546 throw TLS_Exception(Alert::IllegalParameter,
547 "We did not offer the usage of " + certificate_verify_msg.signature_scheme().to_string() +
548 " as a signature scheme");
549 }
550
551 BOTAN_ASSERT_NOMSG(m_handshake_state.has_client_certificate_msg() &&
552 !m_handshake_state.client_certificate().empty());
553 bool sig_valid = certificate_verify_msg.verify(
554 *m_handshake_state.client_certificate().public_key(), callbacks(), m_transcript_hash.previous());
555
556 // RFC 8446 4.4.3
557 // If the verification fails, the receiver MUST terminate the handshake
558 // with a "decrypt_error" alert.
559 if(!sig_valid) {
560 throw TLS_Exception(Alert::DecryptError, "Client certificate verification failed");
561 }
562
563 m_transitions.set_expected_next(Handshake_Type::Finished);
564}
565
566void Server_Impl_13::handle(const Finished_13& finished_msg) {
567 // RFC 8446 4.4.4
568 // Recipients of Finished messages MUST verify that the contents are
569 // correct and if incorrect MUST terminate the connection with a
570 // "decrypt_error" alert.
571 if(!finished_msg.verify(m_cipher_state.get(), m_transcript_hash.previous())) {
572 throw TLS_Exception(Alert::DecryptError, "Finished message didn't verify");
573 }
574
575 // Give the application a chance for a final veto before fully
576 // establishing the connection.
577 callbacks().tls_session_established(
578 Session_Summary(m_handshake_state.server_hello(),
579 Connection_Side::Server,
580 peer_cert_chain(),
581 peer_raw_public_key(),
582 m_psk_identity,
583 m_resumed_session.has_value(),
584 Server_Information(m_handshake_state.client_hello().sni_hostname()),
585 callbacks().tls_current_timestamp()));
586
587 m_cipher_state->advance_with_client_finished(m_transcript_hash.current());
588
589 // no more handshake messages expected
590 m_transitions.set_expected_next({});
591
592 callbacks().tls_session_activated();
593
594 if(new_session_ticket_supported()) {
595 send_new_session_tickets(policy().new_session_tickets_upon_handshake_success());
596 }
597}
598
599} // namespace Botan::TLS
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
const Policy & policy() const
AggregatedPostHandshakeMessages aggregate_post_handshake_messages()
Credentials_Manager & credentials_manager()
RandomNumberGenerator & rng()
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)
Session_Manager & session_manager()
std::unique_ptr< Cipher_State > m_cipher_state
const std::vector< PSK_Key_Exchange_Mode > & modes() const
std::vector< X509_Certificate > peer_cert_chain() const override
size_t send_new_session_tickets(size_t tickets) override
std::optional< std::string > external_psk_identity() const override
std::shared_ptr< const Public_Key > peer_raw_public_key() const override
bool is_handshake_complete() const override
std::string application_protocol() const override
bool new_session_ticket_supported() const override
Server_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< const Policy > &policy, const std::shared_ptr< RandomNumberGenerator > &rng)
std::variant< Client_Hello_13, Client_Hello_12, Server_Hello_13, Server_Hello_12, Hello_Retry_Request, Encrypted_Extensions, Certificate_13, Certificate_Request_13, Certificate_Verify_13, Finished_13 > Handshake_Message_13
bool value_exists(const std::vector< T > &vec, const V &val)
Definition stl_util.h:51