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