Botan 3.4.0
Crypto and TLS for C&
tls_client_impl_12.cpp
Go to the documentation of this file.
1/*
2* TLS Client
3* (C) 2004-2011,2012,2015,2016 Jack Lloyd
4* 2016 Matthias Gierlings
5* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#include <botan/internal/tls_client_impl_12.h>
11
12#include <botan/ocsp.h>
13#include <botan/tls_client.h>
14#include <botan/tls_messages.h>
15#include <botan/internal/stl_util.h>
16#include <botan/internal/tls_handshake_state.h>
17
18#include <optional>
19#include <sstream>
20#include <utility>
21
22namespace Botan::TLS {
23
24namespace {
25
26class Client_Handshake_State_12 final : public Handshake_State {
27 public:
28 Client_Handshake_State_12(std::unique_ptr<Handshake_IO> io, Callbacks& cb) :
29 Handshake_State(std::move(io), cb), m_is_reneg(false) {}
30
31 const Public_Key& server_public_key() const {
32 BOTAN_ASSERT(m_server_public_key, "Server sent us a certificate");
33 return *m_server_public_key;
34 }
35
36 const Public_Key* maybe_server_public_key() const { return m_server_public_key.get(); }
37
38 void record_server_public_key(std::unique_ptr<Public_Key> spk) {
39 BOTAN_STATE_CHECK(!m_server_public_key);
40 m_server_public_key = std::move(spk);
41 }
42
43 bool is_a_resumption() const { return m_resumed_session.has_value(); }
44
45 void discard_resumption_state() { m_resumed_session.reset(); }
46
47 void record_resumption_info(std::optional<Session> session_info) {
48 BOTAN_STATE_CHECK(!m_resumed_session.has_value());
49 m_resumed_session = std::move(session_info);
50 }
51
52 bool is_a_renegotiation() const { return m_is_reneg; }
53
54 void mark_as_renegotiation() { m_is_reneg = true; }
55
56 const secure_vector<uint8_t>& resume_master_secret() const {
57 BOTAN_STATE_CHECK(is_a_resumption());
58 return m_resumed_session->master_secret();
59 }
60
61 const std::vector<X509_Certificate>& resume_peer_certs() const {
62 BOTAN_STATE_CHECK(is_a_resumption());
63 return m_resumed_session->peer_certs();
64 }
65
66 bool resumed_session_supports_extended_master_secret() const {
67 BOTAN_STATE_CHECK(is_a_resumption());
68 return m_resumed_session->supports_extended_master_secret();
69 }
70
71 private:
72 std::unique_ptr<Public_Key> m_server_public_key;
73
74 // Used during session resumption
75 std::optional<Session> m_resumed_session;
76 bool m_is_reneg = false;
77};
78
79} // namespace
80
81/*
82* TLS 1.2 Client Constructor
83*/
84Client_Impl_12::Client_Impl_12(const std::shared_ptr<Callbacks>& callbacks,
85 const std::shared_ptr<Session_Manager>& session_manager,
86 const std::shared_ptr<Credentials_Manager>& creds,
87 const std::shared_ptr<const Policy>& policy,
88 const std::shared_ptr<RandomNumberGenerator>& rng,
90 bool datagram,
91 const std::vector<std::string>& next_protocols,
92 size_t io_buf_sz) :
93 Channel_Impl_12(callbacks, session_manager, rng, policy, false, datagram, io_buf_sz),
94 m_creds(creds),
95 m_info(std::move(info)) {
96 BOTAN_ASSERT_NONNULL(m_creds);
97 const auto version = datagram ? Protocol_Version::DTLS_V12 : Protocol_Version::TLS_V12;
99 send_client_hello(state, false, version, std::nullopt /* no a-priori session to resume */, next_protocols);
100}
101
103 Channel_Impl_12(downgrade_info.callbacks,
104 downgrade_info.session_manager,
105 downgrade_info.rng,
106 downgrade_info.policy,
107 false /* is_server */,
108 false /* datagram -- not supported by Botan in TLS 1.3 */,
109 downgrade_info.io_buffer_size),
110 m_creds(downgrade_info.creds),
111 m_info(downgrade_info.server_info) {
112 Handshake_State& state = create_handshake_state(Protocol_Version::TLS_V12);
113
114 if(!downgrade_info.client_hello_message.empty()) {
115 // Downgrade detected after receiving a TLS 1.2 server hello. We need to
116 // recreate the state as if this implementation issued the client hello.
117 std::vector<uint8_t> client_hello_msg(
118 downgrade_info.client_hello_message.begin() + 4 /* handshake header length */,
119 downgrade_info.client_hello_message.end());
120
121 state.client_hello(new Client_Hello_12(client_hello_msg));
122 state.hash().update(downgrade_info.client_hello_message);
123
126 } else {
127 // Downgrade initiated after a TLS 1.2 session was found. No communication
128 // has happened yet but the found session should be used for resumption.
129 BOTAN_ASSERT_NOMSG(downgrade_info.tls12_session.has_value() &&
130 downgrade_info.tls12_session->session.version().is_pre_tls_13());
131 send_client_hello(state,
132 false,
133 downgrade_info.tls12_session->session.version(),
134 downgrade_info.tls12_session,
135 downgrade_info.next_protocols);
136 }
137}
138
139std::unique_ptr<Handshake_State> Client_Impl_12::new_handshake_state(std::unique_ptr<Handshake_IO> io) {
140 return std::make_unique<Client_Handshake_State_12>(std::move(io), callbacks());
141}
142
143std::vector<X509_Certificate> Client_Impl_12::get_peer_cert_chain(const Handshake_State& state) const {
144 const Client_Handshake_State_12& cstate = dynamic_cast<const Client_Handshake_State_12&>(state);
145
146 if(cstate.is_a_resumption()) {
147 return cstate.resume_peer_certs();
148 }
149
150 if(state.server_certs()) {
151 return state.server_certs()->cert_chain();
152 }
153 return std::vector<X509_Certificate>();
154}
155
156/*
157* Send a new client hello to renegotiate
158*/
159void Client_Impl_12::initiate_handshake(Handshake_State& state, bool force_full_renegotiation) {
160 // we don't support TLS < 1.2 anymore and TLS 1.3 should not use this client impl
161 const auto version = state.version().is_datagram_protocol() ? Protocol_Version::DTLS_V12 : Protocol_Version::TLS_V12;
162 send_client_hello(state, force_full_renegotiation, version);
163}
164
165void Client_Impl_12::send_client_hello(Handshake_State& state_base,
166 bool force_full_renegotiation,
167 Protocol_Version version,
168 std::optional<Session_with_Handle> session_and_handle,
169 const std::vector<std::string>& next_protocols) {
170 Client_Handshake_State_12& state = dynamic_cast<Client_Handshake_State_12&>(state_base);
171
172 if(state.version().is_datagram_protocol()) {
173 state.set_expected_next(Handshake_Type::HelloVerifyRequest); // optional
174 }
175 state.set_expected_next(Handshake_Type::ServerHello);
176
177 if(!force_full_renegotiation) {
178 // if no session is provided, we need to try and find one opportunistically
179 if(!session_and_handle.has_value() && !m_info.empty()) {
180 if(auto sessions = session_manager().find(m_info, callbacks(), policy()); !sessions.empty()) {
181 session_and_handle = std::move(sessions.front());
182 }
183 }
184
185 if(session_and_handle.has_value()) {
186 /*
187 Ensure that the session protocol cipher and version are acceptable
188 If not skip the resume and establish a new session
189 */
190 auto& session_info = session_and_handle->session;
191 const bool exact_version = session_info.version() == version;
192 const bool ok_version = (session_info.version().is_datagram_protocol() == version.is_datagram_protocol()) &&
193 policy().acceptable_protocol_version(session_info.version());
194
195 const bool session_version_ok = policy().only_resume_with_exact_version() ? exact_version : ok_version;
196
197 if(policy().acceptable_ciphersuite(session_info.ciphersuite()) && session_version_ok) {
198 state.client_hello(new Client_Hello_12(state.handshake_io(),
199 state.hash(),
200 policy(),
201 callbacks(),
202 rng(),
204 session_and_handle.value(),
205 next_protocols));
206
207 state.record_resumption_info(std::move(session_info));
208 }
209 }
210 }
211
212 if(!state.client_hello()) // not resuming
213 {
214 Client_Hello_12::Settings client_settings(version, m_info.hostname());
215 state.client_hello(new Client_Hello_12(state.handshake_io(),
216 state.hash(),
217 policy(),
218 callbacks(),
219 rng(),
221 client_settings,
222 next_protocols));
223 }
224
225 secure_renegotiation_check(state.client_hello());
226}
227
228namespace {
229
230bool key_usage_matches_ciphersuite(Key_Constraints usage, const Ciphersuite& suite) {
231 if(usage == Key_Constraints::None) {
232 return true; // anything goes ...
233 }
234
235 if(suite.kex_method() == Kex_Algo::STATIC_RSA) {
237 } else {
239 }
240}
241
242} // namespace
243
244/*
245* Process a handshake message
246*/
247void Client_Impl_12::process_handshake_msg(const Handshake_State* active_state,
248 Handshake_State& state_base,
249 Handshake_Type type,
250 const std::vector<uint8_t>& contents,
251 bool epoch0_restart) {
252 BOTAN_ASSERT_NOMSG(epoch0_restart == false); // only happens on server side
253
254 Client_Handshake_State_12& state = dynamic_cast<Client_Handshake_State_12&>(state_base);
255
256 if(type == Handshake_Type::HelloRequest && active_state) {
257 Hello_Request hello_request(contents);
258
259 if(state.client_hello()) {
260 throw TLS_Exception(Alert::HandshakeFailure, "Cannot renegotiate during a handshake");
261 }
262
263 if(policy().allow_server_initiated_renegotiation()) {
264 if(secure_renegotiation_supported() || policy().allow_insecure_renegotiation()) {
265 state.mark_as_renegotiation();
266 initiate_handshake(state, true /* force_full_renegotiation */);
267 } else {
268 throw TLS_Exception(Alert::HandshakeFailure, "Client policy prohibits insecure renegotiation");
269 }
270 } else {
271 if(policy().abort_connection_on_undesired_renegotiation()) {
272 throw TLS_Exception(Alert::NoRenegotiation, "Client policy prohibits renegotiation");
273 } else {
274 // RFC 5746 section 4.2
275 send_warning_alert(Alert::NoRenegotiation);
276 }
277 }
278
279 return;
280 }
281
282 state.confirm_transition_to(type);
283
286 state.hash().update(state.handshake_io().format(contents, type));
287 }
288
290 state.set_expected_next(Handshake_Type::ServerHello);
291 state.set_expected_next(Handshake_Type::HelloVerifyRequest); // might get it again
292
293 Hello_Verify_Request hello_verify_request(contents);
294 state.hello_verify_request(hello_verify_request);
295 } else if(type == Handshake_Type::ServerHello) {
296 state.server_hello(new Server_Hello_12(contents));
297
298 if(!state.server_hello()->legacy_version().valid()) {
299 throw TLS_Exception(Alert::ProtocolVersion, "Server replied with an invalid version");
300 }
301
302 if(!state.client_hello()->offered_suite(state.server_hello()->ciphersuite())) {
303 throw TLS_Exception(Alert::HandshakeFailure, "Server replied with ciphersuite we didn't send");
304 }
305
306 const auto suite = Ciphersuite::by_id(state.server_hello()->ciphersuite());
307 if(!suite || !suite->usable_in_version(state.server_hello()->legacy_version())) {
308 throw TLS_Exception(Alert::HandshakeFailure,
309 "Server replied using a ciphersuite not allowed in version it offered");
310 }
311
312 // RFC 7366 3.:
313 // If a server receives an encrypt-then-MAC request extension from a client
314 // and then selects a stream or Authenticated Encryption with Associated
315 // Data (AEAD) ciphersuite, it MUST NOT send an encrypt-then-MAC
316 // response extension back to the client.
317 if(suite->aead_ciphersuite() && state.server_hello()->supports_encrypt_then_mac()) {
318 throw TLS_Exception(Alert::IllegalParameter,
319 "Server replied using an AEAD ciphersuite and an encrypt-then-MAC response extension");
320 }
321
322 if(Ciphersuite::is_scsv(state.server_hello()->ciphersuite())) {
323 throw TLS_Exception(Alert::HandshakeFailure, "Server replied with a signaling ciphersuite");
324 }
325
326 if(state.server_hello()->compression_method() != 0) {
327 throw TLS_Exception(Alert::IllegalParameter, "Server replied with non-null compression method");
328 }
329
330 if(state.client_hello()->legacy_version() > state.server_hello()->legacy_version()) {
331 // check for downgrade attacks
332 //
333 // RFC 8446 4.1.3.:
334 // TLS 1.2 clients SHOULD also check that the last 8 bytes are
335 // not equal to the [magic value DOWNGRADE_TLS11] if the ServerHello
336 // indicates TLS 1.1 or below. If a match is found, the client MUST
337 // abort the handshake with an "illegal_parameter" alert.
338 //
339 // TLS 1.3 servers will still set the magic string to DOWNGRADE_TLS12. Don't abort in this case.
340 if(auto requested = state.server_hello()->random_signals_downgrade();
341 requested.has_value() && requested.value() <= Protocol_Version::TLS_V11) {
342 throw TLS_Exception(Alert::IllegalParameter, "Downgrade attack detected");
343 }
344 }
345
346 auto client_extn = state.client_hello()->extension_types();
347 auto server_extn = state.server_hello()->extension_types();
348
349 std::vector<Extension_Code> diff;
350
351 std::set_difference(
352 server_extn.begin(), server_extn.end(), client_extn.begin(), client_extn.end(), std::back_inserter(diff));
353
354 if(!diff.empty()) {
355 // Server sent us back an extension we did not send!
356
357 std::ostringstream msg;
358 msg << "Server replied with unsupported extensions:";
359 for(auto&& d : diff) {
360 msg << " " << static_cast<int>(d);
361 }
362 throw TLS_Exception(Alert::UnsupportedExtension, msg.str());
363 }
364
365 if(uint16_t srtp = state.server_hello()->srtp_profile()) {
366 if(!value_exists(state.client_hello()->srtp_profiles(), srtp)) {
367 throw TLS_Exception(Alert::HandshakeFailure, "Server replied with DTLS-SRTP alg we did not send");
368 }
369 }
370
372 state.server_hello()->extensions(), Connection_Side::Server, Handshake_Type::ServerHello);
373
374 state.set_version(state.server_hello()->legacy_version());
375 m_application_protocol = state.server_hello()->next_protocol();
376
377 secure_renegotiation_check(state.server_hello());
378
379 const bool server_returned_same_session_id =
380 !state.server_hello()->session_id().empty() &&
381 (state.server_hello()->session_id() == state.client_hello()->session_id());
382
383 if(server_returned_same_session_id) {
384 // successful resumption
385 BOTAN_ASSERT_NOMSG(state.is_a_resumption());
386
387 /*
388 * In this case, we offered the version used in the original
389 * session, and the server must resume with the same version.
390 */
391 if(state.server_hello()->legacy_version() != state.client_hello()->legacy_version()) {
392 throw TLS_Exception(Alert::HandshakeFailure, "Server resumed session but with wrong version");
393 }
394
395 if(state.server_hello()->supports_extended_master_secret() &&
396 !state.resumed_session_supports_extended_master_secret()) {
397 throw TLS_Exception(Alert::HandshakeFailure, "Server resumed session but added extended master secret");
398 }
399
400 if(!state.server_hello()->supports_extended_master_secret() &&
401 state.resumed_session_supports_extended_master_secret()) {
402 throw TLS_Exception(Alert::HandshakeFailure, "Server resumed session and removed extended master secret");
403 }
404
405 state.compute_session_keys(state.resume_master_secret());
406
407 if(state.server_hello()->supports_session_ticket()) {
408 state.set_expected_next(Handshake_Type::NewSessionTicket);
409 } else {
410 state.set_expected_next(Handshake_Type::HandshakeCCS);
411 }
412 } else {
413 // new session
414
415 if(active_state) {
416 // Here we are testing things that should not change during a renegotation,
417 // even if the server creates a new session. Howerver they might change
418 // in a resumption scenario.
419
420 if(active_state->version() != state.server_hello()->legacy_version()) {
421 throw TLS_Exception(Alert::ProtocolVersion, "Server changed version after renegotiation");
422 }
423
424 if(state.server_hello()->supports_extended_master_secret() !=
425 active_state->server_hello()->supports_extended_master_secret()) {
426 throw TLS_Exception(Alert::HandshakeFailure, "Server changed its mind about extended master secret");
427 }
428 }
429
430 state.discard_resumption_state();
431
432 if(state.client_hello()->legacy_version().is_datagram_protocol() !=
433 state.server_hello()->legacy_version().is_datagram_protocol()) {
434 throw TLS_Exception(Alert::ProtocolVersion, "Server replied with different protocol type than we offered");
435 }
436
437 if(state.version() > state.client_hello()->legacy_version()) {
438 throw TLS_Exception(Alert::HandshakeFailure, "Server replied with later version than client offered");
439 }
440
441 if(state.version().major_version() == 3 && state.version().minor_version() == 0) {
442 throw TLS_Exception(Alert::ProtocolVersion, "Server attempting to negotiate SSLv3 which is not supported");
443 }
444
445 if(!policy().acceptable_protocol_version(state.version())) {
446 throw TLS_Exception(Alert::ProtocolVersion,
447 "Server version " + state.version().to_string() + " is unacceptable by policy");
448 }
449
450 if(state.ciphersuite().signature_used() || state.ciphersuite().kex_method() == Kex_Algo::STATIC_RSA) {
451 state.set_expected_next(Handshake_Type::Certificate);
452 } else if(state.ciphersuite().kex_method() == Kex_Algo::PSK) {
453 /* PSK is anonymous so no certificate/cert req message is
454 ever sent. The server may or may not send a server kex,
455 depending on if it has an identity hint for us.
456
457 (EC)DHE_PSK always sends a server key exchange for the
458 DH exchange portion, and is covered by block below
459 */
460
461 state.set_expected_next(Handshake_Type::ServerKeyExchange);
462 state.set_expected_next(Handshake_Type::ServerHelloDone);
463 } else if(state.ciphersuite().kex_method() != Kex_Algo::STATIC_RSA) {
464 state.set_expected_next(Handshake_Type::ServerKeyExchange);
465 } else {
466 state.set_expected_next(Handshake_Type::CertificateRequest); // optional
467 state.set_expected_next(Handshake_Type::ServerHelloDone);
468 }
469 }
470 } else if(type == Handshake_Type::Certificate) {
471 state.server_certs(new Certificate_12(contents, policy()));
472
473 const std::vector<X509_Certificate>& server_certs = state.server_certs()->cert_chain();
474
475 if(server_certs.empty()) {
476 throw TLS_Exception(Alert::HandshakeFailure, "Client: No certificates sent by server");
477 }
478
479 /*
480 If the server supports certificate status messages,
481 certificate verification happens after we receive the server hello done,
482 in case an OCSP response was also available
483 */
484
485 X509_Certificate server_cert = server_certs[0];
486
487 if(active_state && active_state->server_certs()) {
488 X509_Certificate current_cert = active_state->server_certs()->cert_chain().at(0);
489
490 if(current_cert != server_cert) {
491 throw TLS_Exception(Alert::BadCertificate, "Server certificate changed during renegotiation");
492 }
493 }
494
495 auto peer_key = server_cert.subject_public_key();
496
497 const std::string expected_key_type =
498 state.ciphersuite().signature_used() ? state.ciphersuite().sig_algo() : "RSA";
499
500 if(peer_key->algo_name() != expected_key_type) {
501 throw TLS_Exception(Alert::IllegalParameter, "Certificate key type did not match ciphersuite");
502 }
503
504 if(!key_usage_matches_ciphersuite(server_cert.constraints(), state.ciphersuite())) {
505 throw TLS_Exception(Alert::BadCertificate, "Certificate usage constraints do not allow this ciphersuite");
506 }
507
508 state.record_server_public_key(std::move(peer_key));
509
510 if(state.ciphersuite().kex_method() != Kex_Algo::STATIC_RSA) {
511 state.set_expected_next(Handshake_Type::ServerKeyExchange);
512 } else {
513 state.set_expected_next(Handshake_Type::CertificateRequest); // optional
514 state.set_expected_next(Handshake_Type::ServerHelloDone);
515 }
516
517 if(state.server_hello()->supports_certificate_status_message()) {
518 state.set_expected_next(Handshake_Type::CertificateStatus); // optional
519 } else {
520 try {
521 auto trusted_CAs = m_creds->trusted_certificate_authorities("tls-client", m_info.hostname());
522
524 server_certs, {}, trusted_CAs, Usage_Type::TLS_SERVER_AUTH, m_info.hostname(), policy());
525 } catch(TLS_Exception&) {
526 throw;
527 } catch(std::exception& e) {
528 throw TLS_Exception(Alert::InternalError, e.what());
529 }
530 }
531 } else if(type == Handshake_Type::CertificateStatus) {
532 state.server_cert_status(new Certificate_Status(contents, Connection_Side::Server));
533
534 if(state.ciphersuite().kex_method() != Kex_Algo::STATIC_RSA) {
535 state.set_expected_next(Handshake_Type::ServerKeyExchange);
536 } else {
537 state.set_expected_next(Handshake_Type::CertificateRequest); // optional
538 state.set_expected_next(Handshake_Type::ServerHelloDone);
539 }
540 } else if(type == Handshake_Type::ServerKeyExchange) {
541 if(state.ciphersuite().psk_ciphersuite() == false) {
542 state.set_expected_next(Handshake_Type::CertificateRequest); // optional
543 }
544 state.set_expected_next(Handshake_Type::ServerHelloDone);
545
546 state.server_kex(new Server_Key_Exchange(
547 contents, state.ciphersuite().kex_method(), state.ciphersuite().auth_method(), state.version()));
548
549 if(state.ciphersuite().signature_used()) {
550 const Public_Key& server_key = state.server_public_key();
551
552 if(!state.server_kex()->verify(server_key, state, policy())) {
553 throw TLS_Exception(Alert::DecryptError, "Bad signature on server key exchange");
554 }
555 }
556 } else if(type == Handshake_Type::CertificateRequest) {
557 state.set_expected_next(Handshake_Type::ServerHelloDone);
558 state.cert_req(new Certificate_Request_12(contents));
559 } else if(type == Handshake_Type::ServerHelloDone) {
560 state.server_hello_done(new Server_Hello_Done(contents));
561
562 if(state.handshake_io().have_more_data()) {
563 throw TLS_Exception(Alert::UnexpectedMessage, "Have data remaining in buffer after ServerHelloDone");
564 }
565
566 if(state.server_certs() != nullptr && state.server_hello()->supports_certificate_status_message()) {
567 try {
568 auto trusted_CAs = m_creds->trusted_certificate_authorities("tls-client", m_info.hostname());
569
570 std::vector<std::optional<OCSP::Response>> ocsp;
571 if(state.server_cert_status() != nullptr) {
572 ocsp.emplace_back(callbacks().tls_parse_ocsp_response(state.server_cert_status()->response()));
573 }
574
575 callbacks().tls_verify_cert_chain(state.server_certs()->cert_chain(),
576 ocsp,
577 trusted_CAs,
579 m_info.hostname(),
580 policy());
581 } catch(TLS_Exception&) {
582 throw;
583 } catch(std::exception& e) {
584 throw TLS_Exception(Alert::InternalError, e.what());
585 }
586 }
587
588 if(state.received_handshake_msg(Handshake_Type::CertificateRequest)) {
589 const auto& types = state.cert_req()->acceptable_cert_types();
590
591 std::vector<X509_Certificate> client_certs =
592 m_creds->find_cert_chain(types, {}, state.cert_req()->acceptable_CAs(), "tls-client", m_info.hostname());
593
594 state.client_certs(new Certificate_12(state.handshake_io(), state.hash(), client_certs));
595 }
596
597 state.client_kex(new Client_Key_Exchange(
598 state.handshake_io(), state, policy(), *m_creds, state.maybe_server_public_key(), m_info.hostname(), rng()));
599
600 state.compute_session_keys();
601
602 if(state.received_handshake_msg(Handshake_Type::CertificateRequest) && !state.client_certs()->empty()) {
603 auto private_key =
604 m_creds->private_key_for(state.client_certs()->cert_chain()[0], "tls-client", m_info.hostname());
605
606 if(!private_key) {
607 throw TLS_Exception(Alert::InternalError, "Failed to get private key for signing");
608 }
609
610 state.client_verify(
611 new Certificate_Verify_12(state.handshake_io(), state, policy(), rng(), private_key.get()));
612 }
613
614 state.handshake_io().send(Change_Cipher_Spec());
615
617
618 state.client_finished(new Finished_12(state.handshake_io(), state, Connection_Side::Client));
619
620 if(state.server_hello()->supports_session_ticket()) {
621 state.set_expected_next(Handshake_Type::NewSessionTicket);
622 } else {
623 state.set_expected_next(Handshake_Type::HandshakeCCS);
624 }
625 } else if(type == Handshake_Type::NewSessionTicket) {
626 state.new_session_ticket(new New_Session_Ticket_12(contents));
627
628 state.set_expected_next(Handshake_Type::HandshakeCCS);
629 } else if(type == Handshake_Type::HandshakeCCS) {
630 state.set_expected_next(Handshake_Type::Finished);
631
633 } else if(type == Handshake_Type::Finished) {
634 if(state.handshake_io().have_more_data()) {
635 throw TLS_Exception(Alert::UnexpectedMessage, "Have data remaining in buffer after Finished");
636 }
637
638 state.server_finished(new Finished_12(contents));
639
640 if(!state.server_finished()->verify(state, Connection_Side::Server)) {
641 throw TLS_Exception(Alert::DecryptError, "Finished message didn't verify");
642 }
643
644 state.hash().update(state.handshake_io().format(contents, type));
645
646 if(!state.client_finished()) {
647 // session resume case
648 state.handshake_io().send(Change_Cipher_Spec());
650 state.client_finished(new Finished_12(state.handshake_io(), state, Connection_Side::Client));
651 }
652
653 Session session_info(state.session_keys().master_secret(),
654 state.server_hello()->legacy_version(),
655 state.server_hello()->ciphersuite(),
657 state.server_hello()->supports_extended_master_secret(),
658 state.server_hello()->supports_encrypt_then_mac(),
659 get_peer_cert_chain(state),
660 m_info,
661 state.server_hello()->srtp_profile(),
662 callbacks().tls_current_timestamp(),
663
664 // Session Tickets (as defined in RFC 5077) contain a lifetime_hint,
665 // sessions identified via a Session_ID do not.
666 ((state.new_session_ticket()) ? state.new_session_ticket()->ticket_lifetime_hint()
667 : std::chrono::seconds::max()));
668
669 // RFC 5077 3.4
670 // If the client receives a session ticket from the server, then it
671 // discards any Session ID that was sent in the ServerHello.
672 const auto handle = [&]() -> std::optional<Session_Handle> {
673 if(const auto& session_ticket = state.session_ticket(); !session_ticket.empty()) {
674 return session_ticket;
675 } else if(const auto& session_id = state.server_hello()->session_id(); !session_id.empty()) {
676 return session_id;
677 } else {
678 return std::nullopt;
679 }
680 }();
681
682 // Give the application a chance for a final veto before fully
683 // establishing the connection.
685 Session_Summary summary(session_info, state.is_a_resumption(), external_psk_identity());
686 summary.set_session_id(state.server_hello()->session_id());
687 if(auto nst = state.new_session_ticket()) {
688 summary.set_session_ticket(nst->ticket());
689 }
690 return summary;
691 }());
692
693 if(handle.has_value()) {
694 const bool should_save = callbacks().tls_should_persist_resumption_information(session_info);
695
696 // RFC 5077 3.3
697 // If the server successfully verifies the client's ticket, then it
698 // MAY renew the ticket by including a NewSessionTicket handshake
699 // message after the ServerHello in the abbreviated handshake. The
700 // client should start using the new ticket as soon as possible
701 // after it verifies the server's Finished message for new
702 // connections.
703 if(state.is_a_resumption() && !state.client_hello()->session_ticket().empty() && handle->is_ticket() &&
704 should_save) {
705 // renew the session ticket by removing the one we used to establish
706 // this connection and replace it with the one we just received
707 session_manager().remove(state.client_hello()->session_ticket());
708 session_manager().store(session_info, handle.value());
709 }
710
711 if(!state.is_a_resumption()) {
712 if(should_save) {
713 session_manager().store(session_info, handle.value());
714 } else {
715 session_manager().remove(handle.value());
716 }
717 }
718 }
719
721 } else {
722 throw Unexpected_Message("Unknown handshake message received");
723 }
724}
725
726} // namespace Botan::TLS
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#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
virtual void tls_session_established(const Session_Summary &session)
virtual void tls_examine_extensions(const Extensions &extn, Connection_Side which_side, Handshake_Type which_message)
virtual bool tls_should_persist_resumption_information(const Session &session)
virtual void tls_verify_cert_chain(const std::vector< X509_Certificate > &cert_chain, const std::vector< std::optional< OCSP::Response > > &ocsp_responses, const std::vector< Certificate_Store * > &trusted_roots, Usage_Type usage, std::string_view hostname, const TLS::Policy &policy)
RandomNumberGenerator & rng()
void change_cipher_spec_reader(Connection_Side side)
Handshake_State & create_handshake_state(Protocol_Version version)
void secure_renegotiation_check(const Client_Hello_12 *client_hello)
Session_Manager & session_manager()
const Policy & policy() const
void change_cipher_spec_writer(Connection_Side side)
std::vector< uint8_t > secure_renegotiation_data_for_client_hello() const
std::optional< std::string > external_psk_identity() const override
bool secure_renegotiation_supported() const override
void send_warning_alert(Alert::Type type)
static bool is_scsv(uint16_t suite)
static std::optional< Ciphersuite > by_id(uint16_t suite)
Client_Impl_12(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(), bool datagram=false, const std::vector< std::string > &next_protocols={}, size_t reserved_io_buffer_size=TLS::Channel::IO_BUF_DEFAULT_SIZE)
void update(const uint8_t in[], size_t length)
void set_expected_next(Handshake_Type msg_type)
void client_hello(Client_Hello_12 *client_hello)
virtual bool only_resume_with_exact_version() const
virtual bool acceptable_protocol_version(Protocol_Version version) const
virtual size_t remove(const Session_Handle &handle)=0
virtual void store(const Session &session, const Session_Handle &handle)=0
Save a Session under a Session_Handle (TLS Client)
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.
int(* final)(unsigned char *, CTX *)
bool value_exists(const std::vector< T > &vec, const OT &val)
Definition stl_util.h:118
std::vector< uint8_t > client_hello_message
The client hello message including the handshake header bytes as transferred to the peer.
std::optional< Session_with_Handle > tls12_session