• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 19012754211

02 Nov 2025 01:10PM UTC coverage: 90.677% (+0.006%) from 90.671%
19012754211

push

github

web-flow
Merge pull request #5137 from randombit/jack/clang-tidy-includes

Remove various unused includes flagged by clang-tidy misc-include-cleaner

100457 of 110786 relevant lines covered (90.68%)

12189873.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.85
/src/lib/tls/tls13/tls_server_impl_13.cpp
1
/*
2
* TLS Server - implementation for TLS 1.3
3
* (C) 2022 Jack Lloyd
4
*     2022 René Meusel - Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include <botan/internal/tls_server_impl_13.h>
10

11
#include <botan/credentials_manager.h>
12
#include <botan/rng.h>
13
#include <botan/internal/stl_util.h>
14
#include <botan/internal/tls_cipher_state.h>
15

16
namespace Botan::TLS {
17

18
Server_Impl_13::Server_Impl_13(const std::shared_ptr<Callbacks>& callbacks,
2,036✔
19
                               const std::shared_ptr<Session_Manager>& session_manager,
20
                               const std::shared_ptr<Credentials_Manager>& credentials_manager,
21
                               const std::shared_ptr<const Policy>& policy,
22
                               const std::shared_ptr<RandomNumberGenerator>& rng) :
2,036✔
23
      Channel_Impl_13(callbacks, session_manager, credentials_manager, rng, policy, true /* is_server */) {
2,036✔
24
#if defined(BOTAN_HAS_TLS_12)
25
   if(policy->allow_tls12()) {
2,036✔
26
      expect_downgrade({}, {});
4,028✔
27
   }
28
#endif
29

30
   m_transitions.set_expected_next(Handshake_Type::ClientHello);
2,036✔
31
}
2,036✔
32

33
std::string Server_Impl_13::application_protocol() const {
266✔
34
   if(is_handshake_complete()) {
266✔
35
      const auto& eee = m_handshake_state.encrypted_extensions().extensions();
266✔
36
      if(auto* const alpn = eee.get<Application_Layer_Protocol_Notification>()) {
266✔
37
         return alpn->single_protocol();
4✔
38
      }
39
   }
40

41
   return "";
262✔
42
}
43

44
std::vector<X509_Certificate> Server_Impl_13::peer_cert_chain() const {
579✔
45
   if(m_handshake_state.has_client_certificate_msg() &&
684✔
46
      m_handshake_state.client_certificate().has_certificate_chain()) {
105✔
47
      return m_handshake_state.client_certificate().cert_chain();
86✔
48
   }
49

50
   if(m_resumed_session.has_value()) {
493✔
51
      return m_resumed_session->peer_certs();
172✔
52
   }
53

54
   return {};
321✔
55
}
56

57
std::shared_ptr<const Public_Key> Server_Impl_13::peer_raw_public_key() const {
577✔
58
   if(m_handshake_state.has_client_certificate_msg() && m_handshake_state.client_certificate().is_raw_public_key()) {
577✔
59
      return m_handshake_state.client_certificate().public_key();
2✔
60
   }
61

62
   if(m_resumed_session.has_value()) {
575✔
63
      return m_resumed_session->peer_raw_public_key();
172✔
64
   }
65

66
   return nullptr;
403✔
67
}
68

69
std::optional<std::string> Server_Impl_13::external_psk_identity() const {
×
70
   return m_psk_identity;
×
71
}
72

73
bool Server_Impl_13::new_session_ticket_supported() const {
292✔
74
   // RFC 8446 4.2.9
75
   //    This extension also restricts the modes for use with PSK resumption.
76
   //    Servers SHOULD NOT send NewSessionTicket with tickets that are not
77
   //    compatible with the advertised modes; however, if a server does so,
78
   //    the impact will just be that the client's attempts at resumption fail.
79
   //
80
   // Note: Applications can overrule this by calling send_new_session_tickets()
81
   //       regardless of this method indicating no support for tickets.
82
   //
83
   // TODO: Implement other PSK KE modes than PSK_DHE_KE
84
   return is_handshake_complete() && m_handshake_state.client_hello().extensions().has<PSK_Key_Exchange_Modes>() &&
292✔
85
          value_exists(m_handshake_state.client_hello().extensions().get<PSK_Key_Exchange_Modes>()->modes(),
584✔
86
                       PSK_Key_Exchange_Mode::PSK_DHE_KE);
292✔
87
}
88

89
size_t Server_Impl_13::send_new_session_tickets(const size_t tickets) {
291✔
90
   BOTAN_STATE_CHECK(is_handshake_complete());
291✔
91

92
   if(tickets == 0) {
291✔
93
      return 0;
94
   }
95

96
   auto flight = aggregate_post_handshake_messages();
284✔
97
   size_t tickets_created = 0;
98

99
   for(size_t i = 0; i < tickets; ++i) {
568✔
100
      auto nonce = m_cipher_state->next_ticket_nonce();
284✔
101
      const Session session(m_cipher_state->psk(nonce),
×
102
                            std::nullopt,  // early data not yet implemented
103
                            policy().session_ticket_lifetime(),
284✔
104
                            peer_cert_chain(),
568✔
105
                            peer_raw_public_key(),
×
106
                            m_handshake_state.client_hello(),
284✔
107
                            m_handshake_state.server_hello(),
108
                            callbacks(),
109
                            rng());
852✔
110

111
      if(callbacks().tls_should_persist_resumption_information(session)) {
284✔
112
         if(auto handle = session_manager().establish(session)) {
568✔
113
            flight.add(New_Session_Ticket_13(std::move(nonce), session, handle.value(), callbacks()));
550✔
114
            ++tickets_created;
275✔
115
         }
284✔
116
      }
117
   }
293✔
118

119
   if(flight.contains_messages()) {
284✔
120
      flight.send();
550✔
121
   }
122

123
   return tickets_created;
284✔
124
}
284✔
125

126
void Server_Impl_13::process_handshake_msg(Handshake_Message_13 message) {
1,386✔
127
   std::visit(
2,689✔
128
      [&](auto msg) {
2,769✔
129
         // first verify that the message was expected by the state machine...
130
         m_transitions.confirm_transition_to(msg.get().type());
1,383✔
131

132
         // ... then allow the library user to abort on their discretion
133
         callbacks().tls_inspect_handshake_msg(msg.get());
1,381✔
134

135
         // ... finally handle the message
136
         handle(msg.get());
1,377✔
137
      },
1,303✔
138
      m_handshake_state.received(std::move(message)));
1,386✔
139
}
1,303✔
140

141
void Server_Impl_13::process_post_handshake_msg(Post_Handshake_Message_13 message) {
1✔
142
   BOTAN_STATE_CHECK(is_handshake_complete());
1✔
143

144
   std::visit([&](auto msg) { handle(msg); }, m_handshake_state.received(std::move(message)));
3✔
145
}
1✔
146

147
void Server_Impl_13::process_dummy_change_cipher_spec() {
337✔
148
   // RFC 8446 5.
149
   //    If an implementation detects a change_cipher_spec record received before
150
   //    the first ClientHello message or after the peer's Finished message, it MUST be
151
   //    treated as an unexpected record type [("unexpected_message" alert)].
152
   if(!m_handshake_state.has_client_hello() || m_handshake_state.has_client_finished()) {
337✔
153
      throw TLS_Exception(Alert::UnexpectedMessage, "Received an unexpected dummy Change Cipher Spec");
×
154
   }
155

156
   // RFC 8446 5.
157
   //    An implementation may receive an unencrypted record of type change_cipher_spec [...]
158
   //    at any time after the first ClientHello message has been sent or received
159
   //    and before the peer's Finished message has been received [...]
160
   //    and MUST simply drop it without further processing.
161
   //
162
   // ... no further processing.
163
}
337✔
164

165
bool Server_Impl_13::is_handshake_complete() const {
150,694✔
166
   return m_handshake_state.handshake_finished();
150,694✔
167
}
168

169
void Server_Impl_13::maybe_log_secret(std::string_view label, std::span<const uint8_t> secret) const {
1,847✔
170
   if(policy().allow_ssl_key_log_file()) {
1,847✔
171
      callbacks().tls_ssl_key_log_data(label, m_handshake_state.client_hello().random(), secret);
×
172
   }
173
}
1,847✔
174

175
void Server_Impl_13::downgrade() {
503✔
176
   BOTAN_ASSERT_NOMSG(expects_downgrade());
503✔
177

178
   request_downgrade();
503✔
179

180
   // After this, no further messages are expected here because this instance
181
   // will be replaced by a Server_Impl_12.
182
   m_transitions.set_expected_next({});
503✔
183
}
503✔
184

185
void Server_Impl_13::maybe_handle_compatibility_mode() {
412✔
186
   BOTAN_ASSERT_NOMSG(m_handshake_state.has_client_hello());
412✔
187
   BOTAN_ASSERT_NOMSG(m_handshake_state.has_hello_retry_request() || m_handshake_state.has_server_hello());
412✔
188

189
   // RFC 8446 Appendix D.4  (Middlebox Compatibility Mode)
190
   //    The server sends a dummy change_cipher_spec record immediately after
191
   //    its first handshake message. This may either be after a ServerHello or
192
   //    a HelloRetryRequest.
193
   //
194
   //    This "compatibility mode" is partially negotiated: the client can opt
195
   //    to provide a session ID or not, and the server has to echo it. Either
196
   //    side can send change_cipher_spec at any time during the handshake, as
197
   //    they must be ignored by the peer, but if the client sends a non-empty
198
   //    session ID, the server MUST send the change_cipher_spec as described
199
   //    [above].
200
   //
201
   // Technically, the usage of compatibility mode is fully up to the client
202
   // sending a non-empty session ID. Nevertheless, when the policy requests
203
   // it we send a CCS regardless. Note that this is perfectly legal and also
204
   // satisfies some BoGo tests that expect this behaviour.
205
   //
206
   // Send a CCS immediately after the _first_ handshake message. I.e. either
207
   // after Hello Retry Request (exclusively) or after a Server Hello that was
208
   // not preseded by a Hello Retry Request.
209
   const bool just_after_first_handshake_message =
412✔
210
      m_handshake_state.has_hello_retry_request() ^ m_handshake_state.has_server_hello();
412✔
211
   const bool client_requested_compatibility_mode = !m_handshake_state.client_hello().session_id().empty();
412✔
212

213
   if(just_after_first_handshake_message &&
784✔
214
      (policy().tls_13_middlebox_compatibility_mode() || client_requested_compatibility_mode)) {
379✔
215
      send_dummy_change_cipher_spec();
366✔
216
   }
217
}
412✔
218

219
void Server_Impl_13::handle_reply_to_client_hello(Server_Hello_13 server_hello) {
367✔
220
   const auto& client_hello = m_handshake_state.client_hello();
367✔
221
   const auto& exts = client_hello.extensions();
367✔
222

223
   const bool uses_psk = server_hello.extensions().has<PSK>();
367✔
224

225
   const auto cipher_opt = Ciphersuite::by_id(server_hello.ciphersuite());
367✔
226
   BOTAN_ASSERT_NOMSG(cipher_opt.has_value());
367✔
227
   const auto& cipher = cipher_opt.value();
367✔
228
   m_transcript_hash.set_algorithm(cipher.prf_algo());
367✔
229

230
   std::unique_ptr<Cipher_State> psk_cipher_state;
367✔
231
   if(uses_psk) {
367✔
232
      auto* psk_extension = server_hello.extensions().get<PSK>();
94✔
233

234
      psk_cipher_state =
94✔
235
         std::visit(overloaded{[&, this](Session session) {
188✔
236
                                  m_resumed_session = std::move(session);
92✔
237
                                  return Cipher_State::init_with_psk(Connection_Side::Server,
92✔
238
                                                                     Cipher_State::PSK_Type::Resumption,
239
                                                                     m_resumed_session->extract_master_secret(),
184✔
240
                                                                     cipher.prf_algo());
184✔
241
                               },
242
                               [&, this](ExternalPSK psk) {
2✔
243
                                  m_psk_identity = psk.identity();
2✔
244
                                  return Cipher_State::init_with_psk(Connection_Side::Server,
2✔
245
                                                                     Cipher_State::PSK_Type::External,
246
                                                                     psk.extract_master_secret(),
4✔
247
                                                                     cipher.prf_algo());
4✔
248
                               }},
249
                    psk_extension->take_session_to_resume_or_psk());
188✔
250

251
      // RFC 8446 4.2.11
252
      //    Prior to accepting PSK key establishment, the server MUST validate
253
      //    the corresponding binder value (see Section 4.2.11.2 below). If this
254
      //    value is not present or does not validate, the server MUST abort the
255
      //    handshake.
256
      //    Servers SHOULD NOT attempt to validate multiple binders; rather,
257
      //    they SHOULD select a single PSK and validate solely the binder that
258
      //    corresponds to that PSK.
259
      //
260
      // Note: PSK selection was performed earlier, resulting in the existence
261
      //       of this extension in the first place.
262
      if(!exts.get<PSK>()->validate_binder(*psk_extension,
188✔
263
                                           psk_cipher_state->psk_binder_mac(m_transcript_hash.truncated()))) {
188✔
264
         throw TLS_Exception(Alert::DecryptError, "PSK binder does not check out");
4✔
265
      }
266

267
      // RFC 8446 4.2.10
268
      //   For PSKs provisioned via NewSessionTicket, a server MUST validate
269
      //   that the ticket age for the selected PSK identity [...] is within a
270
      //   small tolerance of the time since the ticket was issued. If it is
271
      //   not, the server SHOULD proceed with the handshake but reject 0-RTT,
272
      //   and SHOULD NOT take any other action that assumes that this
273
      //   ClientHello is fresh.
274
      //
275
      // TODO: When implementing Early Data (0-RTT) we should take the above
276
      //       paragraph into account. Note that there are BoGo tests that
277
      //       validate this behaviour. Namely: TLS13-TicketAgeSkew-*
278
   }
279

280
   // This sends the server_hello to the peer.
281
   // NOTE: the server_hello variable is moved into the handshake state. Later
282
   //       references to the Server Hello will need to consult the handshake
283
   //       state object!
284
   send_handshake_message(m_handshake_state.sending(std::move(server_hello)));
726✔
285
   maybe_handle_compatibility_mode();
363✔
286

287
   // Setup encryption for all the remaining handshake messages
288
   m_cipher_state = [&] {
1,113✔
289
      // Currently, PSK without DHE is not implemented...
290
      auto* const my_keyshare = m_handshake_state.server_hello().extensions().get<Key_Share>();
363✔
291
      BOTAN_ASSERT_NONNULL(my_keyshare);
363✔
292

293
      if(uses_psk) {
363✔
294
         BOTAN_ASSERT_NONNULL(psk_cipher_state);
90✔
295
         psk_cipher_state->advance_with_client_hello(m_transcript_hash.previous(), *this);
90✔
296
         psk_cipher_state->advance_with_server_hello(
180✔
297
            cipher, my_keyshare->take_shared_secret(), m_transcript_hash.current(), *this);
90✔
298

299
         return std::move(psk_cipher_state);
90✔
300
      } else {
301
         return Cipher_State::init_with_server_hello(
273✔
302
            m_side, my_keyshare->take_shared_secret(), cipher, m_transcript_hash.current(), *this);
546✔
303
      }
304
   }();
363✔
305

306
   auto flight = aggregate_handshake_messages();
363✔
307
   flight.add(m_handshake_state.sending(Encrypted_Extensions(client_hello, policy(), callbacks())));
363✔
308

309
   if(!uses_psk) {
362✔
310
      // RFC 8446 4.3.2
311
      //    A server which is authenticating with a certificate MAY optionally
312
      //    request a certificate from the client. This message, if sent, MUST
313
      //    follow EncryptedExtensions.
314
      if(auto certificate_request =
544✔
315
            Certificate_Request_13::maybe_create(client_hello, credentials_manager(), callbacks(), policy())) {
272✔
316
         flight.add(m_handshake_state.sending(std::move(certificate_request.value())));
97✔
317
      }
×
318

319
      const auto& enc_exts = m_handshake_state.encrypted_extensions().extensions();
272✔
320

321
      // RFC 7250 4.2
322
      //   This client_certificate_type extension in the server hello then
323
      //   indicates the type of certificates the client is requested to provide
324
      //   in a subsequent certificate payload.
325
      //
326
      // Note: TLS 1.3 carries this extension in the Encrypted Extensions
327
      //       message instead of the Server Hello.
328
      if(auto* client_cert_type = enc_exts.get<Client_Certificate_Type>()) {
272✔
329
         set_selected_certificate_type(client_cert_type->selected_certificate_type());
1✔
330
      }
331

332
      // RFC 8446 4.4.2
333
      //    If the corresponding certificate type extension [...]  was not
334
      //    negotiated in EncryptedExtensions, or the X.509 certificate type
335
      //    was negotiated, then each CertificateEntry contains a DER-encoded
336
      //    X.509 certificate.
337
      const auto cert_type = [&] {
836✔
338
         if(auto* server_cert_type = enc_exts.get<Server_Certificate_Type>()) {
272✔
339
            return server_cert_type->selected_certificate_type();
1✔
340
         } else {
341
            return Certificate_Type::X509;
342
         }
343
      }();
272✔
344

345
      flight.add(m_handshake_state.sending(Certificate_13(client_hello, credentials_manager(), callbacks(), cert_type)))
525✔
346
         .add(m_handshake_state.sending(Certificate_Verify_13(m_handshake_state.server_certificate(),
512✔
347
                                                              client_hello.signature_schemes(),
515✔
348
                                                              client_hello.sni_hostname(),
512✔
349
                                                              m_transcript_hash.current(),
350
                                                              Connection_Side::Server,
351
                                                              credentials_manager(),
352
                                                              policy(),
353
                                                              callbacks(),
354
                                                              rng())));
355
   }
356

357
   flight.add(m_handshake_state.sending(Finished_13(m_cipher_state.get(), m_transcript_hash.current())));
343✔
358

359
   if(client_hello.extensions().has<Record_Size_Limit>() &&
343✔
360
      m_handshake_state.encrypted_extensions().extensions().has<Record_Size_Limit>()) {
8✔
361
      // RFC 8449 4.
362
      //    When the "record_size_limit" extension is negotiated, an endpoint
363
      //    MUST NOT generate a protected record with plaintext that is larger
364
      //    than the RecordSizeLimit value it receives from its peer.
365
      //    Unprotected messages are not subject to this limit.
366
      //
367
      // Hence, the limit is set just before we start sending encrypted records.
368
      //
369
      // RFC 8449 4.
370
      //     The record size limit only applies to records sent toward the
371
      //     endpoint that advertises the limit.  An endpoint can send records
372
      //     that are larger than the limit it advertises as its own limit.
373
      //
374
      // Hence, the "outgoing" limit is what the client requested and the
375
      // "incoming" limit is what we will request in the Encrypted Extensions.
376
      auto* const outgoing_limit = client_hello.extensions().get<Record_Size_Limit>();
8✔
377
      auto* const incoming_limit = m_handshake_state.encrypted_extensions().extensions().get<Record_Size_Limit>();
8✔
378
      set_record_size_limits(outgoing_limit->limit(), incoming_limit->limit());
8✔
379
   }
380

381
   flight.send();
363✔
382

383
   m_cipher_state->advance_with_server_finished(m_transcript_hash.current(), *this);
343✔
384

385
   if(m_handshake_state.has_certificate_request()) {
343✔
386
      // RFC 8446 4.4.2
387
      //    The client MUST send a Certificate message if and only if the server
388
      //    has requested client authentication via a CertificateRequest message
389
      //    [...]. If the server requests client authentication but no
390
      //    suitable certificate is available, the client MUST send a Certificate
391
      //    message containing no certificates [...].
392
      m_transitions.set_expected_next(Handshake_Type::Certificate);
96✔
393
   } else {
394
      m_transitions.set_expected_next(Handshake_Type::Finished);
247✔
395
   }
396
}
367✔
397

398
void Server_Impl_13::handle_reply_to_client_hello(Hello_Retry_Request hello_retry_request) {
49✔
399
   auto cipher = Ciphersuite::by_id(hello_retry_request.ciphersuite());
49✔
400
   BOTAN_ASSERT_NOMSG(cipher.has_value());  // should work, since we chose that suite
49✔
401

402
   send_handshake_message(m_handshake_state.sending(std::move(hello_retry_request)));
98✔
403
   maybe_handle_compatibility_mode();
49✔
404

405
   m_transcript_hash = Transcript_Hash_State::recreate_after_hello_retry_request(cipher->prf_algo(), m_transcript_hash);
49✔
406

407
   m_transitions.set_expected_next(Handshake_Type::ClientHello);
49✔
408
}
49✔
409

410
void Server_Impl_13::handle(const Client_Hello_12& ch) {
505✔
411
   // The detailed handling of the TLS 1.2 compliant Client Hello is left to
412
   // the TLS 1.2 server implementation.
413
   BOTAN_UNUSED(ch);
505✔
414

415
   // After we sent a Hello Retry Request we must not accept a downgrade.
416
   if(m_handshake_state.has_hello_retry_request()) {
505✔
417
      throw TLS_Exception(Alert::UnexpectedMessage, "Received a TLS 1.2 Client Hello after Hello Retry Request");
×
418
   }
419

420
   // RFC 8446 Appendix D.2
421
   //    If the "supported_versions" extension is absent and the server only
422
   //    supports versions greater than ClientHello.legacy_version, the server
423
   //    MUST abort the handshake with a "protocol_version" alert.
424
   //
425
   // If we're not expecting a downgrade, we only support TLS 1.3.
426
   if(!expects_downgrade()) {
505✔
427
      throw TLS_Exception(Alert::ProtocolVersion, "Received a legacy Client Hello");
2✔
428
   }
429

430
   downgrade();
503✔
431
}
503✔
432

433
void Server_Impl_13::handle(const Client_Hello_13& client_hello) {
433✔
434
   const auto& exts = client_hello.extensions();
433✔
435

436
   const bool is_initial_client_hello = !m_handshake_state.has_hello_retry_request();
433✔
437

438
   if(is_initial_client_hello) {
433✔
439
      const auto preferred_version = client_hello.highest_supported_version(policy());
390✔
440
      if(!preferred_version) {
390✔
441
         throw TLS_Exception(Alert::ProtocolVersion, "No shared TLS version");
×
442
      }
443

444
      // RFC 8446 4.2.2
445
      //   Clients MUST NOT use cookies in their initial ClientHello in subsequent
446
      //   connections.
447
      if(exts.has<Cookie>()) {
390✔
448
         throw TLS_Exception(Alert::IllegalParameter, "Received a Cookie in the initial client hello");
×
449
      }
450
   }
451

452
   // TODO: Implement support for PSK. For now, we ignore any such extensions
453
   //       and always revert to a standard key exchange.
454
   if(!exts.has<Supported_Groups>()) {
433✔
455
      throw Not_Implemented("PSK-only handshake NYI");
×
456
   }
457

458
   // RFC 8446 9.2
459
   //    If containing a "supported_groups" extension, [Client Hello] MUST
460
   //    also contain a "key_share" extension, and vice versa.
461
   //
462
   // This was validated before in the Client_Hello_13 constructor.
463
   BOTAN_ASSERT_NOMSG(exts.has<Key_Share>());
433✔
464

465
   if(!is_initial_client_hello) {
433✔
466
      const auto& hrr_exts = m_handshake_state.hello_retry_request().extensions();
43✔
467
      const auto offered_groups = exts.get<Key_Share>()->offered_groups();
43✔
468
      const auto selected_group = hrr_exts.get<Key_Share>()->selected_group();
43✔
469
      if(offered_groups.size() != 1 || offered_groups.at(0) != selected_group) {
43✔
470
         throw TLS_Exception(Alert::IllegalParameter, "Client did not comply with the requested key exchange group");
1✔
471
      }
472
   }
43✔
473

474
   callbacks().tls_examine_extensions(exts, Connection_Side::Client, client_hello.type());
432✔
475
   std::visit([this](auto msg) { handle_reply_to_client_hello(std::move(msg)); },
1,224✔
476
              Server_Hello_13::create(client_hello,
432✔
477
                                      is_initial_client_hello,
478
                                      session_manager(),
479
                                      credentials_manager(),
480
                                      rng(),
481
                                      policy(),
482
                                      callbacks()));
483
}
392✔
484

485
void Server_Impl_13::handle(const Certificate_13& certificate_msg) {
92✔
486
   // RFC 8446 4.3.2
487
   //    certificate_request_context:  [...] This field SHALL be zero length
488
   //    unless used for the post-handshake authentication exchanges [...].
489
   if(!is_handshake_complete() && !certificate_msg.request_context().empty()) {
92✔
490
      throw TLS_Exception(Alert::DecodeError, "Received a client certificate message with non-empty request context");
×
491
   }
492

493
   // RFC 8446 4.4.2
494
   //    Extensions in the Certificate message from the client MUST correspond
495
   //    to extensions in the CertificateRequest message from the server.
496
   certificate_msg.validate_extensions(m_handshake_state.certificate_request().extensions().extension_types(),
93✔
497
                                       callbacks());
498

499
   // RFC 8446 4.4.2.4
500
   //   If the client does not send any certificates (i.e., it sends an empty
501
   //   Certificate message), the server MAY at its discretion either continue
502
   //   the handshake without client authentication or abort the handshake with
503
   //   a "certificate_required" alert.
504
   if(certificate_msg.empty()) {
91✔
505
      if(policy().require_client_certificate_authentication()) {
10✔
506
         throw TLS_Exception(Alert::CertificateRequired, "Policy requires client send a certificate, but it did not");
1✔
507
      }
508

509
      // RFC 8446 4.4.2
510
      //    A Finished message MUST be sent regardless of whether the
511
      //    Certificate message is empty.
512
      m_transitions.set_expected_next(Handshake_Type::Finished);
9✔
513
   } else {
514
      // RFC 8446 4.4.2.4
515
      //    [...], if some aspect of the certificate chain was unacceptable
516
      //    (e.g., it was not signed by a known, trusted CA), the server MAY at
517
      //    its discretion either continue the handshake (considering the client
518
      //    unauthenticated) or abort the handshake.
519
      //
520
      // TODO: We could make this dependent on Policy::require_client_auth().
521
      //       Though, apps may also override Callbacks::tls_verify_cert_chain()
522
      //       and 'ignore' validation issues to a certain extent.
523
      certificate_msg.verify(callbacks(),
81✔
524
                             policy(),
525
                             credentials_manager(),
526
                             m_handshake_state.client_hello().sni_hostname(),
81✔
527
                             m_handshake_state.client_hello().extensions().has<Certificate_Status_Request>());
81✔
528

529
      // RFC 8446 4.4.3
530
      //    Clients MUST send this message whenever authenticating via a
531
      //    certificate (i.e., when the Certificate message
532
      //    is non-empty). When sent, this message MUST appear immediately after
533
      //    the Certificate message [...].
534
      m_transitions.set_expected_next(Handshake_Type::CertificateVerify);
63✔
535
   }
536
}
72✔
537

538
void Server_Impl_13::handle(const Certificate_Verify_13& certificate_verify_msg) {
53✔
539
   // RFC 8446 4.4.3
540
   //    If sent by a client, the signature algorithm used in the signature
541
   //    MUST be one of those present in the supported_signature_algorithms
542
   //    field of the "signature_algorithms" extension in the
543
   //    CertificateRequest message.
544
   const auto offered = m_handshake_state.certificate_request().signature_schemes();
53✔
545
   if(!value_exists(offered, certificate_verify_msg.signature_scheme())) {
106✔
546
      throw TLS_Exception(Alert::IllegalParameter,
×
547
                          "We did not offer the usage of " + certificate_verify_msg.signature_scheme().to_string() +
×
548
                             " as a signature scheme");
×
549
   }
550

551
   BOTAN_ASSERT_NOMSG(m_handshake_state.has_client_certificate_msg() &&
53✔
552
                      !m_handshake_state.client_certificate().empty());
553
   bool sig_valid = certificate_verify_msg.verify(
103✔
554
      *m_handshake_state.client_certificate().public_key(), callbacks(), m_transcript_hash.previous());
56✔
555

556
   // RFC 8446 4.4.3
557
   //   If the verification fails, the receiver MUST terminate the handshake
558
   //   with a "decrypt_error" alert.
559
   if(!sig_valid) {
50✔
560
      throw TLS_Exception(Alert::DecryptError, "Client certificate verification failed");
6✔
561
   }
562

563
   m_transitions.set_expected_next(Handshake_Type::Finished);
44✔
564
}
53✔
565

566
void Server_Impl_13::handle(const Finished_13& finished_msg) {
294✔
567
   // RFC 8446 4.4.4
568
   //    Recipients of Finished messages MUST verify that the contents are
569
   //    correct and if incorrect MUST terminate the connection with a
570
   //    "decrypt_error" alert.
571
   if(!finished_msg.verify(m_cipher_state.get(), m_transcript_hash.previous())) {
294✔
572
      throw TLS_Exception(Alert::DecryptError, "Finished message didn't verify");
2✔
573
   }
574

575
   // Give the application a chance for a final veto before fully
576
   // establishing the connection.
577
   callbacks().tls_session_established(
584✔
578
      Session_Summary(m_handshake_state.server_hello(),
876✔
579
                      Connection_Side::Server,
580
                      peer_cert_chain(),
584✔
581
                      peer_raw_public_key(),
584✔
582
                      m_psk_identity,
292✔
583
                      m_resumed_session.has_value(),
292✔
584
                      Server_Information(m_handshake_state.client_hello().sni_hostname()),
584✔
585
                      callbacks().tls_current_timestamp()));
292✔
586

587
   m_cipher_state->advance_with_client_finished(m_transcript_hash.current());
292✔
588

589
   // no more handshake messages expected
590
   m_transitions.set_expected_next({});
292✔
591

592
   callbacks().tls_session_activated();
292✔
593

594
   if(new_session_ticket_supported()) {
292✔
595
      send_new_session_tickets(policy().new_session_tickets_upon_handshake_success());
290✔
596
   }
597
}
292✔
598

599
}  // namespace Botan::TLS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc