Botan 3.10.0
Crypto and TLS for C&
tls_client_impl_13.cpp
Go to the documentation of this file.
1/*
2* TLS Client - 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#include <botan/internal/tls_client_impl_13.h>
10
11#include <botan/credentials_manager.h>
12#include <botan/tls_messages.h>
13#include <botan/types.h>
14#include <botan/internal/stl_util.h>
15#include <botan/internal/tls_channel_impl_13.h>
16#include <botan/internal/tls_cipher_state.h>
17
18#include <utility>
19
20namespace Botan::TLS {
21
22Client_Impl_13::Client_Impl_13(const std::shared_ptr<Callbacks>& callbacks,
23 const std::shared_ptr<Session_Manager>& session_manager,
24 const std::shared_ptr<Credentials_Manager>& creds,
25 const std::shared_ptr<const Policy>& policy,
26 const std::shared_ptr<RandomNumberGenerator>& rng,
28 const std::vector<std::string>& next_protocols) :
29 Channel_Impl_13(callbacks, session_manager, creds, rng, policy, false /* is_server */),
30 m_info(std::move(info)),
31 m_should_send_ccs(false) {
32#if defined(BOTAN_HAS_TLS_12)
33 if(policy->allow_tls12()) {
34 expect_downgrade(m_info, next_protocols);
35 }
36#endif
37
38 if(auto session = find_session_for_resumption()) {
39 if(!session->session.version().is_pre_tls_13()) {
40 m_resumed_session = std::move(session);
41 } else if(expects_downgrade()) {
42 // If we found a session that was created with TLS 1.2, we downgrade
43 // the implementation right away, before even issuing a Client Hello.
44 request_downgrade_for_resumption(std::move(session.value()));
45 return;
46 }
47 }
48
49 auto msg = send_handshake_message(m_handshake_state.sending(
51 *callbacks,
52 *rng,
53 m_info.hostname(),
54 next_protocols,
55 m_resumed_session,
56 creds->find_preshared_keys(m_info.hostname(), Connection_Side::Client))));
57
58 if(expects_downgrade()) {
60 }
61
62 // RFC 8446 Appendix D.4
63 // If not offering early data, the client sends a dummy change_cipher_spec
64 // record [...] immediately before its second flight. This may either be before
65 // its second ClientHello or before its encrypted handshake flight.
66 //
67 // TODO: don't schedule ccs here when early data is used
68 if(policy->tls_13_middlebox_compatibility_mode()) {
69 m_should_send_ccs = true;
70 }
71
72 m_transitions.set_expected_next({Handshake_Type::ServerHello, Handshake_Type::HelloRetryRequest});
73}
74
75void Client_Impl_13::process_handshake_msg(Handshake_Message_13 message) {
76 std::visit(
77 [&](auto msg) {
78 // first verify that the message was expected by the state machine...
79 m_transitions.confirm_transition_to(msg.get().type());
80
81 // ... then allow the library user to abort on their discretion
83
84 // ... finally handle the message
85 handle(msg.get());
86 },
87 m_handshake_state.received(std::move(message)));
88}
89
90void Client_Impl_13::process_post_handshake_msg(Post_Handshake_Message_13 message) {
92
93 std::visit([&](auto msg) { handle(msg); }, m_handshake_state.received(std::move(message)));
94}
95
97 // RFC 8446 5.
98 // If an implementation detects a change_cipher_spec record received before
99 // the first ClientHello message or after the peer's Finished message, it MUST be
100 // treated as an unexpected record type [("unexpected_message" alert)].
101 if(!m_handshake_state.has_client_hello() || m_handshake_state.has_server_finished()) {
102 throw TLS_Exception(Alert::UnexpectedMessage, "Received an unexpected dummy Change Cipher Spec");
103 }
104
105 // RFC 8446 5.
106 // An implementation may receive an unencrypted record of type change_cipher_spec [...]
107 // at any time after the first ClientHello message has been sent or received
108 // and before the peer's Finished message has been received [...]
109 // and MUST simply drop it without further processing.
110 //
111 // ... no further processing.
112}
113
115 return m_handshake_state.handshake_finished();
116}
117
118std::optional<Session_with_Handle> Client_Impl_13::find_session_for_resumption() {
119 // RFC 8446 4.6.1
120 // Clients MUST only resume if the new SNI value is valid for the
121 // server certificate presented in the original session and SHOULD only
122 // resume if the SNI value matches the one used in the original session.
123 //
124 // Below we search sessions based on their SNI value. Assuming that a
125 // 3rd party session manager does not lie to the implementation, we don't
126 // explicitly re-check that the SNI values match.
127 //
128 // Also, the default implementation did verify that very same SNI information
129 // against the server's certificate (via Callbacks::tls_verify_cert_chain())
130 // before storing it in the session.
131 //
132 // We therefore assume that the session returned by the `Session_Manager` is
133 // suitable for resumption in this context.
134 auto sessions = session_manager().find(m_info, callbacks(), policy());
135 if(sessions.empty()) {
136 return std::nullopt;
137 }
138
139 // TODO: TLS 1.3 allows sending more than one ticket (for resumption) in a
140 // Client Hello. Currently, we do not support that. The Session_Manager
141 // does imply otherwise with its API, though.
142 auto& session_to_resume = sessions.front();
143
144 return std::move(session_to_resume);
145}
146
147void Client_Impl_13::handle(const Server_Hello_12& server_hello_msg) {
148 if(m_handshake_state.has_hello_retry_request()) {
149 throw TLS_Exception(Alert::UnexpectedMessage, "Version downgrade received after Hello Retry");
150 }
151
152 // RFC 8446 Appendix D.1
153 // If the version chosen by the server is not supported by the client
154 // (or is not acceptable), the client MUST abort the handshake with a
155 // "protocol_version" alert.
156 if(!expects_downgrade()) {
157 throw TLS_Exception(Alert::ProtocolVersion, "Received an unexpected legacy Server Hello");
158 }
159
160 // RFC 8446 4.1.3
161 // TLS 1.3 has a downgrade protection mechanism embedded in the server's
162 // random value. TLS 1.3 servers which negotiate TLS 1.2 or below in
163 // response to a ClientHello MUST set the last 8 bytes of their Random
164 // value specially in their ServerHello.
165 //
166 // TLS 1.3 clients receiving a ServerHello indicating TLS 1.2 or below
167 // MUST check that the [downgrade indication is not set]. [...] If a match
168 // is found, the client MUST abort the handshake with an
169 // "illegal_parameter" alert.
170 if(server_hello_msg.random_signals_downgrade().has_value()) {
171 throw TLS_Exception(Alert::IllegalParameter, "Downgrade attack detected");
172 }
173
174 // RFC 8446 4.2.1
175 // A server which negotiates a version of TLS prior to TLS 1.3 [...]
176 // MUST NOT send the "supported_versions" extension.
177 //
178 // Note that this condition should never happen, as the Server_Hello parsing
179 // code decides to create a Server_Hello_12 based on the absence of this extension.
180 if(server_hello_msg.extensions().has<Supported_Versions>()) {
181 throw TLS_Exception(Alert::IllegalParameter, "Unexpected extension received");
182 }
183
184 // RFC 8446 Appendix D.1
185 // If the version chosen by the server is not supported by the client
186 // (or is not acceptable), the client MUST abort the handshake with a
187 // "protocol_version" alert.
188 const auto& client_hello_exts = m_handshake_state.client_hello().extensions();
189 BOTAN_ASSERT_NOMSG(client_hello_exts.has<Supported_Versions>());
190 if(!client_hello_exts.get<Supported_Versions>()->supports(server_hello_msg.selected_version())) {
191 throw TLS_Exception(Alert::ProtocolVersion, "Protocol version was not offered");
192 }
193
194 if(policy().tls_13_middlebox_compatibility_mode() &&
195 m_handshake_state.client_hello().session_id() == server_hello_msg.session_id()) {
196 // In compatibility mode, the server will reflect the session ID we sent in the client hello.
197 // However, a TLS 1.2 server that wants to downgrade cannot have found the random session ID
198 // we sent. Therefore, we have to consider this as an attack.
199 // (Thanks BoGo test EchoTLS13CompatibilitySessionID!)
200 throw TLS_Exception(Alert::IllegalParameter, "Unexpected session ID during downgrade");
201 }
202
204
205 // After this, no further messages are expected here because this instance will be replaced
206 // by a Client_Impl_12.
207 m_transitions.set_expected_next({});
208}
209
210namespace {
211// validate Server_Hello_13 and Hello_Retry_Request
212void validate_server_hello_ish(const Client_Hello_13& ch, const Server_Hello_13& sh) {
213 // RFC 8446 4.1.3
214 // A client which receives a legacy_session_id_echo field that does not match what
215 // it sent in the ClientHello MUST abort the handshake with an "illegal_parameter" alert.
216 if(ch.session_id() != sh.session_id()) {
217 throw TLS_Exception(Alert::IllegalParameter, "echoed session id did not match");
218 }
219
220 // RFC 8446 4.1.3
221 // A client which receives a cipher suite that was not offered MUST abort the handshake
222 // with an "illegal_parameter" alert.
223 if(!ch.offered_suite(sh.ciphersuite())) {
224 throw TLS_Exception(Alert::IllegalParameter, "Server replied with ciphersuite we didn't send");
225 }
226
227 // RFC 8446 4.2.1
228 // If the "supported_versions" extension in the ServerHello contains a
229 // version not offered by the client or contains a version prior to
230 // TLS 1.3, the client MUST abort the handshake with an "illegal_parameter" alert.
231 //
232 // Note: Server_Hello_13 parsing checks that its selected version is TLS 1.3
233 BOTAN_ASSERT_NOMSG(ch.extensions().has<Supported_Versions>());
234 if(!ch.extensions().get<Supported_Versions>()->supports(sh.selected_version())) {
235 throw TLS_Exception(Alert::IllegalParameter, "Protocol version was not offered");
236 }
237}
238} // namespace
239
240void Client_Impl_13::handle(const Server_Hello_13& sh) {
241 // Note: Basic checks (that do not require contextual information) were already
242 // performed during the construction of the Server_Hello_13 object.
243
244 const auto& ch = m_handshake_state.client_hello();
245
246 validate_server_hello_ish(ch, sh);
247
248 // RFC 8446 4.2
249 // Implementations MUST NOT send extension responses if the remote
250 // endpoint did not send the corresponding extension requests, [...]. Upon
251 // receiving such an extension, an endpoint MUST abort the handshake
252 // with an "unsupported_extension" alert.
253 if(sh.extensions().contains_other_than(ch.extensions().extension_types())) {
254 throw TLS_Exception(Alert::UnsupportedExtension, "Unsupported extension found in Server Hello");
255 }
256
257 if(m_handshake_state.has_hello_retry_request()) {
258 const auto& hrr = m_handshake_state.hello_retry_request();
259
260 // RFC 8446 4.1.4
261 // Upon receiving the ServerHello, clients MUST check that the cipher suite
262 // supplied in the ServerHello is the same as that in the HelloRetryRequest
263 // and otherwise abort the handshake with an "illegal_parameter" alert.
264 if(hrr.ciphersuite() != sh.ciphersuite()) {
265 throw TLS_Exception(Alert::IllegalParameter, "server changed its chosen ciphersuite");
266 }
267
268 // RFC 8446 4.1.4
269 // The value of selected_version in the HelloRetryRequest "supported_versions"
270 // extension MUST be retained in the ServerHello, and a client MUST abort the
271 // handshake with an "illegal_parameter" alert if the value changes.
272 if(hrr.selected_version() != sh.selected_version()) {
273 throw TLS_Exception(Alert::IllegalParameter, "server changed its chosen protocol version");
274 }
275 }
276
277 auto cipher = Ciphersuite::by_id(sh.ciphersuite());
278 BOTAN_ASSERT_NOMSG(cipher.has_value()); // should work, since we offered this suite
279
280 // RFC 8446 Appendix B.4
281 // Although TLS 1.3 uses the same cipher suite space as previous versions
282 // of TLS [...] cipher suites for TLS 1.2 and lower cannot be used with
283 // TLS 1.3.
284 if(!cipher->usable_in_version(Protocol_Version::TLS_V13)) {
285 throw TLS_Exception(Alert::IllegalParameter,
286 "Server replied using a ciphersuite not allowed in version it offered");
287 }
288
289 // RFC 8446 4.2.11
290 // Clients MUST verify that [...] a server "key_share" extension is present
291 // if required by the ClientHello "psk_key_exchange_modes" extension. If
292 // these values are not consistent, the client MUST abort the handshake
293 // with an "illegal_parameter" alert.
294 //
295 // Currently, we don't support PSK-only mode, hence a key share extension is
296 // considered mandatory.
297 //
298 // TODO: Implement PSK-only mode.
299 if(!sh.extensions().has<Key_Share>()) {
300 throw TLS_Exception(Alert::IllegalParameter, "Server Hello did not contain a key share extension");
301 }
302
303 auto* my_keyshare = ch.extensions().get<Key_Share>();
304 auto shared_secret = my_keyshare->decapsulate(*sh.extensions().get<Key_Share>(), policy(), callbacks(), rng());
305
306 m_transcript_hash.set_algorithm(cipher.value().prf_algo());
307
308 if(sh.extensions().has<PSK>()) {
309 std::tie(m_psk_identity, m_cipher_state) =
310 ch.extensions().get<PSK>()->take_selected_psk_info(*sh.extensions().get<PSK>(), cipher.value());
311
312 // If we offered a session for resumption *and* an externally provided PSK
313 // and the latter was chosen by the server over the offered resumption, we
314 // want to invalidate the now-outdated session in m_resumed_session.
315 if(m_psk_identity.has_value() && m_resumed_session.has_value()) {
316 m_resumed_session.reset();
317 }
318
319 // TODO: When implementing early data, `advance_with_client_hello` must
320 // happen _before_ encrypting any early application data.
321 // Same when we want to support early key export.
322 m_cipher_state->advance_with_client_hello(m_transcript_hash.previous(), *this);
323 m_cipher_state->advance_with_server_hello(
324 cipher.value(), std::move(shared_secret), m_transcript_hash.current(), *this);
325 } else {
326 m_resumed_session.reset(); // might have been set if we attempted a resumption
328 m_side, std::move(shared_secret), cipher.value(), m_transcript_hash.current(), *this);
329 }
330
332
333 m_transitions.set_expected_next(Handshake_Type::EncryptedExtensions);
334}
335
336void Client_Impl_13::handle(const Hello_Retry_Request& hrr) {
337 // Note: Basic checks (that do not require contextual information) were already
338 // performed during the construction of the Hello_Retry_Request object as
339 // a subclass of Server_Hello_13.
340
341 auto& ch = m_handshake_state.client_hello();
342
343 validate_server_hello_ish(ch, hrr);
344
345 // RFC 8446 4.1.4.
346 // A HelloRetryRequest MUST NOT contain any
347 // extensions that were not first offered by the client in its
348 // ClientHello, with the exception of optionally the "cookie".
349 auto allowed_exts = ch.extensions().extension_types();
350 allowed_exts.insert(Extension_Code::Cookie);
351 if(hrr.extensions().contains_other_than(allowed_exts)) {
352 throw TLS_Exception(Alert::UnsupportedExtension, "Unsupported extension found in Hello Retry Request");
353 }
354
355 auto cipher = Ciphersuite::by_id(hrr.ciphersuite());
356 BOTAN_ASSERT_NOMSG(cipher.has_value()); // should work, since we offered this suite
357
360
361 ch.retry(hrr, m_transcript_hash, callbacks(), rng());
362
364
365 send_handshake_message(std::reference_wrapper(ch));
366
367 // RFC 8446 4.1.4
368 // If a client receives a second HelloRetryRequest in the same connection [...],
369 // it MUST abort the handshake with an "unexpected_message" alert.
370 m_transitions.set_expected_next(Handshake_Type::ServerHello);
371}
372
373void Client_Impl_13::handle(const Encrypted_Extensions& encrypted_extensions_msg) {
374 const auto& exts = encrypted_extensions_msg.extensions();
375
376 // RFC 8446 4.2
377 // Implementations MUST NOT send extension responses if the remote
378 // endpoint did not send the corresponding extension requests, [...]. Upon
379 // receiving such an extension, an endpoint MUST abort the handshake
380 // with an "unsupported_extension" alert.
381 const auto& requested_exts = m_handshake_state.client_hello().extensions().extension_types();
382 if(exts.contains_other_than(requested_exts)) {
383 throw TLS_Exception(Alert::UnsupportedExtension,
384 "Encrypted Extensions contained an extension that was not offered");
385 }
386
387 // Note: As per RFC 6066 3. we can check for an empty SNI extensions to
388 // determine if the server used the SNI we sent here.
389
390 if(exts.has<Record_Size_Limit>() && m_handshake_state.client_hello().extensions().has<Record_Size_Limit>()) {
391 // RFC 8449 4.
392 // The record size limit only applies to records sent toward the
393 // endpoint that advertises the limit. An endpoint can send records
394 // that are larger than the limit it advertises as its own limit.
395 //
396 // Hence, the "outgoing" limit is what the server requested and the
397 // "incoming" limit is what we requested in the Client Hello.
398 auto* const outgoing_limit = exts.get<Record_Size_Limit>();
399 auto* const incoming_limit = m_handshake_state.client_hello().extensions().get<Record_Size_Limit>();
400 set_record_size_limits(outgoing_limit->limit(), incoming_limit->limit());
401 }
402
403 if(exts.has<Server_Certificate_Type>() &&
404 m_handshake_state.client_hello().extensions().has<Server_Certificate_Type>()) {
405 const auto* server_cert_type = exts.get<Server_Certificate_Type>();
406 const auto* our_server_cert_types = m_handshake_state.client_hello().extensions().get<Server_Certificate_Type>();
407 our_server_cert_types->validate_selection(*server_cert_type);
408
409 // RFC 7250 4.2
410 // With the server_certificate_type extension in the server hello, the
411 // TLS server indicates the certificate type carried in the Certificate
412 // payload.
413 //
414 // Note: TLS 1.3 carries this extension in the Encrypted Extensions
415 // message instead of the Server Hello.
416 set_selected_certificate_type(server_cert_type->selected_certificate_type());
417 }
418
420
421 if(m_handshake_state.server_hello().extensions().has<PSK>()) {
422 // RFC 8446 2.2
423 // As the server is authenticating via a PSK, it does not send a
424 // Certificate or a CertificateVerify message.
425 m_transitions.set_expected_next(Handshake_Type::Finished);
426 } else {
427 m_transitions.set_expected_next({Handshake_Type::Certificate, Handshake_Type::CertificateRequest});
428 }
429}
430
431void Client_Impl_13::handle(const Certificate_Request_13& certificate_request_msg) {
432 // RFC 8446 4.3.2
433 // [The 'context' field] SHALL be zero length unless used for the
434 // post-handshake authentication exchanges described in Section 4.6.2.
435 if(!is_handshake_complete() && !certificate_request_msg.context().empty()) {
436 throw TLS_Exception(Alert::DecodeError, "Certificate_Request context must be empty in the main handshake");
437 }
438
440 certificate_request_msg.extensions(), Connection_Side::Server, Handshake_Type::CertificateRequest);
441 m_transitions.set_expected_next(Handshake_Type::Certificate);
442}
443
444void Client_Impl_13::handle(const Certificate_13& certificate_msg) {
445 // RFC 8446 4.4.2
446 // certificate_request_context: [...] In the case of server authentication,
447 // this field SHALL be zero length.
448 if(!certificate_msg.request_context().empty()) {
449 throw TLS_Exception(Alert::DecodeError, "Received a server certificate message with non-empty request context");
450 }
451
452 // RFC 8446 4.4.2
453 // Extensions in the Certificate message from the server MUST correspond
454 // to ones from the ClientHello message.
455 certificate_msg.validate_extensions(m_handshake_state.client_hello().extensions().extension_types(), callbacks());
456 certificate_msg.verify(callbacks(),
457 policy(),
459 m_info.hostname(),
460 m_handshake_state.client_hello().extensions().has<Certificate_Status_Request>());
461
462 m_transitions.set_expected_next(Handshake_Type::CertificateVerify);
463}
464
465void Client_Impl_13::handle(const Certificate_Verify_13& certificate_verify_msg) {
466 // RFC 8446 4.4.3
467 // If the CertificateVerify message is sent by a server, the signature
468 // algorithm MUST be one offered in the client's "signature_algorithms"
469 // extension unless no valid certificate chain can be produced without
470 // unsupported algorithms.
471 //
472 // Note: if the server failed to produce a certificate chain without using
473 // an unsupported signature scheme, we opt to abort the handshake.
474 const auto offered = m_handshake_state.client_hello().signature_schemes();
475 if(!value_exists(offered, certificate_verify_msg.signature_scheme())) {
476 throw TLS_Exception(Alert::IllegalParameter,
477 "We did not offer the usage of " + certificate_verify_msg.signature_scheme().to_string() +
478 " as a signature scheme");
479 }
480
481 bool sig_valid = certificate_verify_msg.verify(
482 *m_handshake_state.server_certificate().public_key(), callbacks(), m_transcript_hash.previous());
483
484 if(!sig_valid) {
485 throw TLS_Exception(Alert::DecryptError, "Server certificate verification failed");
486 }
487
488 m_transitions.set_expected_next(Handshake_Type::Finished);
489}
490
491void Client_Impl_13::send_client_authentication(Channel_Impl_13::AggregatedHandshakeMessages& flight) {
492 BOTAN_ASSERT_NOMSG(m_handshake_state.has_certificate_request());
493 const auto& cert_request = m_handshake_state.certificate_request();
494
495 const auto cert_type = [&] {
496 const auto& exts = m_handshake_state.encrypted_extensions().extensions();
497 const auto& chexts = m_handshake_state.client_hello().extensions();
498 if(exts.has<Client_Certificate_Type>() && chexts.has<Client_Certificate_Type>()) {
499 const auto* client_cert_type = exts.get<Client_Certificate_Type>();
500 chexts.get<Client_Certificate_Type>()->validate_selection(*client_cert_type);
501
502 // RFC 7250 4.2
503 // This client_certificate_type extension in the server hello then
504 // indicates the type of certificates the client is requested to
505 // provide in a subsequent certificate payload.
506 //
507 // Note: TLS 1.3 carries this extension in the Encrypted Extensions
508 // message instead of the Server Hello.
509 return client_cert_type->selected_certificate_type();
510 } else {
511 // RFC 8446 4.4.2
512 // If the corresponding certificate type extension [...] was not
513 // negotiated in EncryptedExtensions, [...] then each
514 // CertificateEntry contains a DER-encoded X.509 certificate.
516 }
517 }();
518
519 // RFC 8446 4.4.2
520 // certificate_request_context: If this message is in response to a
521 // CertificateRequest, the value of certificate_request_context in
522 // that message.
523 flight.add(m_handshake_state.sending(
524 Certificate_13(cert_request, m_info.hostname(), credentials_manager(), callbacks(), cert_type)));
525
526 // RFC 8446 4.4.2
527 // If the server requests client authentication but no suitable certificate
528 // is available, the client MUST send a Certificate message containing no
529 // certificates.
530 //
531 // In that case, no Certificate Verify message will be sent.
532 if(!m_handshake_state.client_certificate().empty()) {
533 flight.add(m_handshake_state.sending(Certificate_Verify_13(m_handshake_state.client_certificate(),
534 cert_request.signature_schemes(),
535 m_info.hostname(),
536 m_transcript_hash.current(),
539 policy(),
540 callbacks(),
541 rng())));
542 }
543}
544
545void Client_Impl_13::handle(const Finished_13& finished_msg) {
546 // RFC 8446 4.4.4
547 // Recipients of Finished messages MUST verify that the contents are
548 // correct and if incorrect MUST terminate the connection with a
549 // "decrypt_error" alert.
550 if(!finished_msg.verify(m_cipher_state.get(), m_transcript_hash.previous())) {
551 throw TLS_Exception(Alert::DecryptError, "Finished message didn't verify");
552 }
553
554 // Give the application a chance for a final veto before fully
555 // establishing the connection.
556 callbacks().tls_session_established(Session_Summary(m_handshake_state.server_hello(),
561 m_resumed_session.has_value(),
562 m_info,
563 callbacks().tls_current_timestamp()));
564
565 // Derives the secrets for receiving application data but defers
566 // the derivation of sending application data.
567 m_cipher_state->advance_with_server_finished(m_transcript_hash.current(), *this);
568
569 auto flight = aggregate_handshake_messages();
570
571 // RFC 8446 4.4.2
572 // The client MUST send a Certificate message if and only if the server
573 // has requested client authentication via a CertificateRequest message.
574 if(m_handshake_state.has_certificate_request()) {
575 send_client_authentication(flight);
576 }
577
578 // send client finished handshake message (still using handshake traffic secrets)
579 flight.add(m_handshake_state.sending(Finished_13(m_cipher_state.get(), m_transcript_hash.current())));
580
581 flight.send();
582
583 // derives the sending application traffic secrets
584 m_cipher_state->advance_with_client_finished(m_transcript_hash.current());
585
586 // TODO: Create a dummy session object and invoke tls_session_established.
587 // Alternatively, consider changing the expectations described in the
588 // callback's doc string.
589
590 // no more handshake messages expected
591 m_transitions.set_expected_next({});
592
594}
595
596void TLS::Client_Impl_13::handle(const New_Session_Ticket_13& new_session_ticket) {
597 callbacks().tls_examine_extensions(
598 new_session_ticket.extensions(), Connection_Side::Server, Handshake_Type::NewSessionTicket);
599
600 Session session(m_cipher_state->psk(new_session_ticket.nonce()),
601 new_session_ticket.early_data_byte_limit(),
602 new_session_ticket.ticket_age_add(),
603 new_session_ticket.lifetime_hint(),
604 m_handshake_state.server_hello().selected_version(),
605 m_handshake_state.server_hello().ciphersuite(),
607 peer_cert_chain(),
608 peer_raw_public_key(),
609 m_info,
610 callbacks().tls_current_timestamp());
611
612 if(callbacks().tls_should_persist_resumption_information(session)) {
613 session_manager().store(session, Session_Handle(new_session_ticket.handle()));
614 }
615}
616
617std::vector<X509_Certificate> Client_Impl_13::peer_cert_chain() const {
618 if(m_handshake_state.has_server_certificate_msg() &&
619 m_handshake_state.server_certificate().has_certificate_chain()) {
620 return m_handshake_state.server_certificate().cert_chain();
621 }
622
623 if(m_resumed_session.has_value()) {
624 return m_resumed_session->session.peer_certs();
625 }
626
627 return {};
628}
629
630std::shared_ptr<const Public_Key> Client_Impl_13::peer_raw_public_key() const {
631 if(m_handshake_state.has_server_certificate_msg() && m_handshake_state.server_certificate().is_raw_public_key()) {
632 return m_handshake_state.server_certificate().public_key();
633 }
634
635 if(m_resumed_session.has_value()) {
636 return m_resumed_session->session.peer_raw_public_key();
637 }
638
639 return nullptr;
640}
641
642std::optional<std::string> Client_Impl_13::external_psk_identity() const {
643 return m_psk_identity;
644}
645
647 return std::exchange(m_should_send_ccs, false); // test-and-set
648}
649
650void Client_Impl_13::maybe_log_secret(std::string_view label, std::span<const uint8_t> secret) const {
651 if(policy().allow_ssl_key_log_file()) {
652 callbacks().tls_ssl_key_log_data(label, m_handshake_state.client_hello().random(), secret);
653 }
654}
655
658 const auto& eee = m_handshake_state.encrypted_extensions().extensions();
660 return eee.get<Application_Layer_Protocol_Notification>()->single_protocol();
661 }
662 }
663
664 return "";
665}
666
667} // namespace Botan::TLS
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
virtual void tls_session_activated()
virtual void tls_examine_extensions(const Extensions &extn, Connection_Side which_side, Handshake_Type which_message)
virtual void tls_session_established(const Session_Summary &session)
virtual void tls_ssl_key_log_data(std::string_view label, std::span< const uint8_t > client_random, std::span< const uint8_t > secret) const
virtual void tls_inspect_handshake_msg(const Handshake_Message &message)
const Policy & policy() const
AggregatedHandshakeMessages aggregate_handshake_messages()
Credentials_Manager & credentials_manager()
RandomNumberGenerator & rng()
std::vector< uint8_t > send_handshake_message(const std::variant< MsgTs... > &message)
Transcript_Hash_State m_transcript_hash
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)
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 request_downgrade_for_resumption(Session_with_Handle session)
void preserve_client_hello(std::span< const uint8_t > msg)
static std::unique_ptr< Cipher_State > init_with_server_hello(Connection_Side side, secure_vector< uint8_t > &&shared_secret, const Ciphersuite &cipher, const Transcript_Hash &transcript_hash, const Secret_Logger &channel)
static std::optional< Ciphersuite > by_id(uint16_t suite)
const std::vector< uint8_t > & random() const
Client_Impl_13(const std::shared_ptr< Callbacks > &callbacks, const std::shared_ptr< Session_Manager > &session_manager, const std::shared_ptr< Credentials_Manager > &creds, const std::shared_ptr< const Policy > &policy, const std::shared_ptr< RandomNumberGenerator > &rng, Server_Information server_info=Server_Information(), const std::vector< std::string > &next_protocols={})
std::optional< std::string > external_psk_identity() const override
std::string application_protocol() const override
std::shared_ptr< const Public_Key > peer_raw_public_key() const override
bool is_handshake_complete() const override
std::vector< X509_Certificate > peer_cert_chain() const override
decltype(auto) received(Handshake_Message_13 message)
void confirm_transition_to(Handshake_Type msg_type)
Helper class to embody a session handle in all protocol versions.
Definition tls_session.h:63
virtual std::vector< Session_with_Handle > find(const Server_Information &info, Callbacks &callbacks, const Policy &policy)
Find all sessions that match a given server info.
bool supports(Protocol_Version version) const
static Transcript_Hash_State recreate_after_hello_retry_request(std::string_view algo_spec, const Transcript_Hash_State &prev_transcript_hash_state)
std::variant< New_Session_Ticket_13, Key_Update > Post_Handshake_Message_13
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