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

randombit / botan / 21848380424

10 Feb 2026 01:47AM UTC coverage: 91.634% (+1.6%) from 90.069%
21848380424

push

github

web-flow
Merge pull request #5296 from randombit/jack/tls-header-patrol

Various changes to reduce header dependencies in TLS

104002 of 113497 relevant lines covered (91.63%)

11230277.53 hits per line

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

91.67
/src/lib/tls/msg_client_hello.cpp
1
/*
2
* TLS Hello Request and Client Hello Messages
3
* (C) 2004-2011,2015,2016 Jack Lloyd
4
*     2016 Matthias Gierlings
5
*     2017 Harry Reimann, Rohde & Schwarz Cybersecurity
6
*     2021 Elektrobit Automotive GmbH
7
*     2022 René Meusel, Hannes Rantzsch - neXenio GmbH
8
*
9
* Botan is released under the Simplified BSD License (see license.txt)
10
*/
11

12
#include <botan/tls_messages_12.h>
13

14
#include <botan/hash.h>
15
#include <botan/rng.h>
16
#include <botan/tls_callbacks.h>
17
#include <botan/tls_exceptn.h>
18
#include <botan/tls_extensions.h>
19
#include <botan/tls_policy.h>
20
#include <botan/tls_session.h>
21
#include <botan/tls_version.h>
22
#include <botan/internal/parsing.h>
23
#include <botan/internal/stl_util.h>
24
#include <botan/internal/tls_handshake_hash.h>
25
#include <botan/internal/tls_handshake_io.h>
26
#include <botan/internal/tls_reader.h>
27

28
#ifdef BOTAN_HAS_TLS_13
29
   #include <botan/tls_messages_13.h>
30
   #include <botan/internal/tls_handshake_layer_13.h>
31
   #include <botan/internal/tls_transcript_hash_13.h>
32
#endif
33

34
#include <chrono>
35
#include <iterator>
36

37
namespace Botan::TLS {
38

39
std::vector<uint8_t> make_hello_random(RandomNumberGenerator& rng, Callbacks& cb, const Policy& policy) {
6,962✔
40
   auto buf = rng.random_vec<std::vector<uint8_t>>(32);
6,962✔
41

42
   if(policy.hash_hello_random()) {
6,962✔
43
      auto sha256 = HashFunction::create_or_throw("SHA-256");
6,947✔
44
      sha256->update(buf);
6,947✔
45
      sha256->final(buf);
6,947✔
46
   }
6,947✔
47

48
   // TLS 1.3 does not require the insertion of a timestamp in the client hello
49
   // random. When offering both TLS 1.2 and 1.3 we nevertheless comply with the
50
   // legacy specification.
51
   if(policy.include_time_in_hello_random() && (policy.allow_tls12() || policy.allow_dtls12())) {
6,962✔
52
      const uint32_t time32 = static_cast<uint32_t>(std::chrono::system_clock::to_time_t(cb.tls_current_timestamp()));
6,939✔
53

54
      store_be(time32, buf.data());
6,939✔
55
   }
56

57
   return buf;
6,962✔
58
}
×
59

60
/**
61
 * Version-agnostic internal client hello data container that allows
62
 * parsing Client_Hello messages without prior knowledge of the contained
63
 * protocol version.
64
 */
65
class Client_Hello_Internal {
66
   public:
67
      Client_Hello_Internal() : m_comp_methods({0}) {}
3,684✔
68

69
      explicit Client_Hello_Internal(const std::vector<uint8_t>& buf) {
3,900✔
70
         if(buf.size() < 41) {
3,900✔
71
            throw Decoding_Error("Client_Hello: Packet corrupted");
45✔
72
         }
73

74
         TLS_Data_Reader reader("ClientHello", buf);
3,855✔
75

76
         const uint8_t major_version = reader.get_byte();
3,855✔
77
         const uint8_t minor_version = reader.get_byte();
3,855✔
78

79
         m_legacy_version = Protocol_Version(major_version, minor_version);
3,855✔
80
         m_random = reader.get_fixed<uint8_t>(32);
3,855✔
81
         m_session_id = Session_ID(reader.get_range<uint8_t>(1, 0, 32));
3,855✔
82

83
         if(m_legacy_version.is_datagram_protocol()) {
3,019✔
84
            auto sha256 = HashFunction::create_or_throw("SHA-256");
796✔
85
            sha256->update(reader.get_data_read_so_far());
796✔
86

87
            m_hello_cookie = reader.get_range<uint8_t>(1, 0, 255);
796✔
88

89
            sha256->update(reader.get_remaining());
796✔
90
            m_cookie_input_bits = sha256->final_stdvec();
796✔
91
         }
796✔
92

93
         m_suites = reader.get_range_vector<uint16_t>(2, 1, 32767);
3,019✔
94
         m_comp_methods = reader.get_range_vector<uint8_t>(1, 1, 255);
2,890✔
95

96
         m_extensions.deserialize(reader, Connection_Side::Client, Handshake_Type::ClientHello);
2,890✔
97
      }
9,124✔
98

99
      /**
100
       * This distinguishes between a TLS 1.3 compliant Client Hello (containing
101
       * the "supported_version" extension) and legacy Client Hello messages.
102
       *
103
       * @return TLS 1.3 if the Client Hello contains "supported_versions", or
104
       *         the content of the "legacy_version" version field if it
105
       *         indicates (D)TLS 1.2 or older, or
106
       *         (D)TLS 1.2 if the "legacy_version" was some other odd value.
107
       */
108
      Protocol_Version version() const {
978✔
109
         // RFC 8446 4.2.1
110
         //    If [the "supported_versions"] extension is not present, servers
111
         //    which are compliant with this specification and which also support
112
         //    TLS 1.2 MUST negotiate TLS 1.2 or prior as specified in [RFC5246],
113
         //    even if ClientHello.legacy_version is 0x0304 or later.
114
         //
115
         // RFC 8446 4.2.1
116
         //    Servers MUST be prepared to receive ClientHellos that include
117
         //    [the supported_versions] extension but do not include 0x0304 in
118
         //    the list of versions.
119
         //
120
         // RFC 8446 4.1.2
121
         //    TLS 1.3 ClientHellos are identified as having a legacy_version of
122
         //    0x0303 and a supported_versions extension present with 0x0304 as
123
         //    the highest version indicated therein.
124
         if(!extensions().has<Supported_Versions>() ||
1,461✔
125
            !extensions().get<Supported_Versions>()->supports(Protocol_Version::TLS_V13)) {
483✔
126
            // The exact legacy_version is ignored we just inspect it to
127
            // distinguish TLS and DTLS.
128
            return (m_legacy_version.is_datagram_protocol()) ? Protocol_Version::DTLS_V12 : Protocol_Version::TLS_V12;
1,026✔
129
         }
130

131
         // Note: The Client_Hello_13 class will make sure that legacy_version
132
         //       is exactly 0x0303 (aka ossified TLS 1.2)
133
         return Protocol_Version::TLS_V13;
465✔
134
      }
135

136
      Protocol_Version legacy_version() const { return m_legacy_version; }
17,278✔
137

138
      const Session_ID& session_id() const { return m_session_id; }
44✔
139

140
      const std::vector<uint8_t>& random() const { return m_random; }
4,391✔
141

142
      const std::vector<uint16_t>& ciphersuites() const { return m_suites; }
4,565✔
143

144
      const std::vector<uint8_t>& comp_methods() const { return m_comp_methods; }
4,811✔
145

146
      const std::vector<uint8_t>& hello_cookie() const { return m_hello_cookie; }
951✔
147

148
      const std::vector<uint8_t>& hello_cookie_input_bits() const { return m_cookie_input_bits; }
790✔
149

150
      const Extensions& extensions() const { return m_extensions; }
978✔
151

152
      Extensions& extensions() { return m_extensions; }
84,353✔
153

154
   public:
155
      Protocol_Version m_legacy_version;    // NOLINT(*-non-private-member-variable*)
156
      Session_ID m_session_id;              // NOLINT(*-non-private-member-variable*)
157
      std::vector<uint8_t> m_random;        // NOLINT(*-non-private-member-variable*)
158
      std::vector<uint16_t> m_suites;       // NOLINT(*-non-private-member-variable*)
159
      std::vector<uint8_t> m_comp_methods;  // NOLINT(*-non-private-member-variable*)
160
      Extensions m_extensions;              // NOLINT(*-non-private-member-variable*)
161

162
      // These fields are only for DTLS:
163
      std::vector<uint8_t> m_hello_cookie;       // NOLINT(*-non-private-member-variable*)
164
      std::vector<uint8_t> m_cookie_input_bits;  // NOLINT(*-non-private-member-variable*)
165
};
166

167
Client_Hello::Client_Hello(Client_Hello&&) noexcept = default;
10,492✔
168
Client_Hello& Client_Hello::operator=(Client_Hello&&) noexcept = default;
43✔
169

170
Client_Hello::~Client_Hello() = default;
17,020✔
171

172
Client_Hello::Client_Hello() : m_data(std::make_unique<Client_Hello_Internal>()) {}
3,684✔
173

174
/*
175
* Read a counterparty client hello
176
*/
177
Client_Hello::Client_Hello(std::unique_ptr<Client_Hello_Internal> data) : m_data(std::move(data)) {
2,861✔
178
   BOTAN_ASSERT_NONNULL(m_data);
2,861✔
179
}
2,861✔
180

181
Handshake_Type Client_Hello::type() const {
16,308✔
182
   return Handshake_Type::ClientHello;
16,308✔
183
}
184

185
Protocol_Version Client_Hello::legacy_version() const {
8,240✔
186
   return m_data->legacy_version();
8,240✔
187
}
188

189
const std::vector<uint8_t>& Client_Hello::random() const {
3,838✔
190
   return m_data->random();
3,838✔
191
}
192

193
const Session_ID& Client_Hello::session_id() const {
3,328✔
194
   return m_data->session_id();
3,328✔
195
}
196

197
const std::vector<uint8_t>& Client_Hello::compression_methods() const {
1,383✔
198
   return m_data->comp_methods();
1,383✔
199
}
200

201
const std::vector<uint16_t>& Client_Hello::ciphersuites() const {
1,430✔
202
   return m_data->ciphersuites();
1,430✔
203
}
204

205
std::set<Extension_Code> Client_Hello::extension_types() const {
3,252✔
206
   return m_data->extensions().extension_types();
3,252✔
207
}
208

209
const Extensions& Client_Hello::extensions() const {
9,818✔
210
   return m_data->extensions();
9,818✔
211
}
212

213
void Client_Hello_12::update_hello_cookie(const Hello_Verify_Request& hello_verify) {
467✔
214
   BOTAN_STATE_CHECK(m_data->legacy_version().is_datagram_protocol());
467✔
215

216
   m_data->m_hello_cookie = hello_verify.cookie();
467✔
217
}
467✔
218

219
/*
220
* Serialize a Client Hello message
221
*/
222
std::vector<uint8_t> Client_Hello::serialize() const {
4,347✔
223
   std::vector<uint8_t> buf;
4,347✔
224
   buf.reserve(1024);  // working around GCC warning
4,347✔
225

226
   buf.push_back(m_data->legacy_version().major_version());
4,347✔
227
   buf.push_back(m_data->legacy_version().minor_version());
4,347✔
228
   buf += m_data->random();
4,347✔
229

230
   append_tls_length_value(buf, m_data->session_id().get(), 1);
4,347✔
231

232
   if(m_data->legacy_version().is_datagram_protocol()) {
4,347✔
233
      append_tls_length_value(buf, m_data->hello_cookie(), 1);
951✔
234
   }
235

236
   append_tls_length_value(buf, m_data->ciphersuites(), 2);
4,347✔
237
   append_tls_length_value(buf, m_data->comp_methods(), 1);
4,347✔
238

239
   /*
240
   * May not want to send extensions at all in some cases. If so,
241
   * should include SCSV value (if reneg info is empty, if not we are
242
   * renegotiating with a modern server)
243
   */
244

245
   buf += m_data->extensions().serialize(Connection_Side::Client);
4,347✔
246

247
   return buf;
4,347✔
248
}
×
249

250
std::vector<uint8_t> Client_Hello::cookie_input_data() const {
790✔
251
   BOTAN_STATE_CHECK(!m_data->hello_cookie_input_bits().empty());
790✔
252

253
   return m_data->hello_cookie_input_bits();
790✔
254
}
255

256
/*
257
* Check if we offered this ciphersuite
258
*/
259
bool Client_Hello::offered_suite(uint16_t ciphersuite) const {
5,283✔
260
   return std::find(m_data->ciphersuites().cbegin(), m_data->ciphersuites().cend(), ciphersuite) !=
5,283✔
261
          m_data->ciphersuites().cend();
5,283✔
262
}
263

264
std::vector<Signature_Scheme> Client_Hello::signature_schemes() const {
4,106✔
265
   if(const Signature_Algorithms* sigs = m_data->extensions().get<Signature_Algorithms>()) {
4,106✔
266
      return sigs->supported_schemes();
4,104✔
267
   }
268
   return {};
2✔
269
}
270

271
std::vector<Signature_Scheme> Client_Hello::certificate_signature_schemes() const {
1,015✔
272
   // RFC 8446 4.2.3
273
   //   If no "signature_algorithms_cert" extension is present, then the
274
   //   "signature_algorithms" extension also applies to signatures appearing
275
   //   in certificates.
276
   if(const Signature_Algorithms_Cert* sigs = m_data->extensions().get<Signature_Algorithms_Cert>()) {
1,015✔
277
      return sigs->supported_schemes();
×
278
   } else {
279
      return signature_schemes();
1,015✔
280
   }
281
}
282

283
std::vector<Group_Params> Client_Hello::supported_ecc_curves() const {
1,361✔
284
   if(const Supported_Groups* groups = m_data->extensions().get<Supported_Groups>()) {
1,361✔
285
      return groups->ec_groups();
1,358✔
286
   }
287
   return {};
3✔
288
}
289

290
std::vector<Group_Params> Client_Hello::supported_dh_groups() const {
1,502✔
291
   if(const Supported_Groups* groups = m_data->extensions().get<Supported_Groups>()) {
1,502✔
292
      return groups->dh_groups();
1,496✔
293
   }
294
   return std::vector<Group_Params>();
6✔
295
}
296

297
bool Client_Hello_12::prefers_compressed_ec_points() const {
28✔
298
   if(const Supported_Point_Formats* ecc_formats = m_data->extensions().get<Supported_Point_Formats>()) {
28✔
299
      return ecc_formats->prefers_compressed();
28✔
300
   }
301
   return false;
302
}
303

304
std::string Client_Hello::sni_hostname() const {
4,219✔
305
   if(const Server_Name_Indicator* sni = m_data->extensions().get<Server_Name_Indicator>()) {
4,219✔
306
      return sni->host_name();
4,089✔
307
   }
308
   return "";
130✔
309
}
310

311
bool Client_Hello_12::secure_renegotiation() const {
5,171✔
312
   return m_data->extensions().has<Renegotiation_Extension>();
5,171✔
313
}
314

315
std::vector<uint8_t> Client_Hello_12::renegotiation_info() const {
4,167✔
316
   if(const Renegotiation_Extension* reneg = m_data->extensions().get<Renegotiation_Extension>()) {
4,167✔
317
      return reneg->renegotiation_info();
4,167✔
318
   }
319
   return {};
×
320
}
321

322
std::vector<Protocol_Version> Client_Hello::supported_versions() const {
1,385✔
323
   if(const Supported_Versions* versions = m_data->extensions().get<Supported_Versions>()) {
1,385✔
324
      return versions->versions();
292✔
325
   }
326
   return {};
1,093✔
327
}
328

329
bool Client_Hello_12::supports_session_ticket() const {
1,203✔
330
   return m_data->extensions().has<Session_Ticket_Extension>();
1,203✔
331
}
332

333
Session_Ticket Client_Hello_12::session_ticket() const {
1,916✔
334
   if(auto* ticket = m_data->extensions().get<Session_Ticket_Extension>()) {
1,916✔
335
      return ticket->contents();
1,766✔
336
   }
337
   return {};
150✔
338
}
339

340
std::optional<Session_Handle> Client_Hello_12::session_handle() const {
987✔
341
   // RFC 5077 3.4
342
   //    If a ticket is presented by the client, the server MUST NOT attempt
343
   //    to use the Session ID in the ClientHello for stateful session
344
   //    resumption.
345
   if(auto ticket = session_ticket(); !ticket.empty()) {
987✔
346
      return Session_Handle(ticket);
808✔
347
   } else if(const auto& id = session_id(); !id.empty()) {
785✔
348
      return Session_Handle(id);
400✔
349
   } else {
350
      return std::nullopt;
685✔
351
   }
987✔
352
}
353

354
bool Client_Hello::supports_alpn() const {
1,127✔
355
   return m_data->extensions().has<Application_Layer_Protocol_Notification>();
1,127✔
356
}
357

358
bool Client_Hello_12::supports_extended_master_secret() const {
1,205✔
359
   return m_data->extensions().has<Extended_Master_Secret>();
1,205✔
360
}
361

362
bool Client_Hello_12::supports_cert_status_message() const {
1,421✔
363
   return m_data->extensions().has<Certificate_Status_Request>();
1,421✔
364
}
365

366
bool Client_Hello_12::supports_encrypt_then_mac() const {
547✔
367
   return m_data->extensions().has<Encrypt_then_MAC>();
547✔
368
}
369

370
bool Client_Hello::sent_signature_algorithms() const {
×
371
   return m_data->extensions().has<Signature_Algorithms>();
×
372
}
373

374
std::vector<std::string> Client_Hello::next_protocols() const {
149✔
375
   if(auto* alpn = m_data->extensions().get<Application_Layer_Protocol_Notification>()) {
149✔
376
      return alpn->protocols();
149✔
377
   }
378
   return {};
×
379
}
380

381
std::vector<uint16_t> Client_Hello::srtp_profiles() const {
291✔
382
   if(const SRTP_Protection_Profiles* srtp = m_data->extensions().get<SRTP_Protection_Profiles>()) {
291✔
383
      return srtp->profiles();
4✔
384
   }
385
   return {};
287✔
386
}
387

388
const std::vector<uint8_t>& Client_Hello::cookie() const {
790✔
389
   return m_data->hello_cookie();
790✔
390
}
391

392
/*
393
* Create a new Hello Request message
394
*/
395
Hello_Request::Hello_Request(Handshake_IO& io) {
×
396
   io.send(*this);
×
397
}
×
398

399
/*
400
* Deserialize a Hello Request message
401
*/
402
Hello_Request::Hello_Request(const std::vector<uint8_t>& buf) {
42✔
403
   if(!buf.empty()) {
42✔
404
      throw Decoding_Error("Bad Hello_Request, has non-zero size");
2✔
405
   }
406
}
40✔
407

408
/*
409
* Serialize a Hello Request message
410
*/
411
std::vector<uint8_t> Hello_Request::serialize() const {
×
412
   return std::vector<uint8_t>();
×
413
}
414

415
void Client_Hello_12::add_tls12_supported_groups_extensions(const Policy& policy) {
2,696✔
416
   // RFC 7919 3.
417
   //    A client that offers a group MUST be able and willing to perform a DH
418
   //    key exchange using that group.
419
   //
420
   // We don't support hybrid key exchange in TLS 1.2
421

422
   std::vector<Group_Params> compatible_kex_groups;
2,696✔
423
   for(const auto& group : policy.key_exchange_groups()) {
37,319✔
424
      if(!group.is_post_quantum()) {
34,623✔
425
         compatible_kex_groups.push_back(group);
26,642✔
426
      }
427
   }
×
428

429
   auto supported_groups = std::make_unique<Supported_Groups>(std::move(compatible_kex_groups));
2,696✔
430

431
   if(!supported_groups->ec_groups().empty()) {
5,384✔
432
      // NOLINTNEXTLINE(*-owning-memory)
433
      m_data->extensions().add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
2,688✔
434
   }
435

436
   m_data->extensions().add(std::move(supported_groups));
2,696✔
437
}
5,392✔
438

439
Client_Hello_12::Client_Hello_12(std::unique_ptr<Client_Hello_Internal> data) : Client_Hello(std::move(data)) {
2,396✔
440
   const uint16_t TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
2,396✔
441

442
   if(offered_suite(static_cast<uint16_t>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV))) {
2,396✔
443
      if(const Renegotiation_Extension* reneg = m_data->extensions().get<Renegotiation_Extension>()) {
12✔
444
         if(!reneg->renegotiation_info().empty()) {
×
445
            throw TLS_Exception(Alert::HandshakeFailure, "Client sent renegotiation SCSV and non-empty extension");
×
446
         }
447
      } else {
448
         // add fake extension
449
         m_data->extensions().add(new Renegotiation_Extension());  // NOLINT(*-owning-memory)
12✔
450
      }
451
   }
452
}
2,396✔
453

454
namespace {
455

456
// Avoid sending an IPv4/IPv6 address in SNI as this is prohibited
457
bool hostname_acceptable_for_sni(std::string_view hostname) {
3,684✔
458
   if(hostname.empty()) {
3,684✔
459
      return false;
460
   }
461

462
   if(string_to_ipv4(hostname).has_value()) {
3,637✔
463
      return false;
464
   }
465

466
   // IPv6? Anyway ':' is not valid in DNS
467
   if(hostname.find(':') != std::string_view::npos) {
3,637✔
468
      return false;
469
   }
470

471
   return true;
472
}
473

474
}  // namespace
475

476
// Note: This delegates to the Client_Hello_12 constructor to take advantage
477
//       of the sanity checks there.
478
Client_Hello_12::Client_Hello_12(const std::vector<uint8_t>& buf) :
2,896✔
479
      Client_Hello_12(std::make_unique<Client_Hello_Internal>(buf)) {}
2,896✔
480

481
/*
482
* Create a new Client Hello message
483
*/
484
Client_Hello_12::Client_Hello_12(Handshake_IO& io,
2,478✔
485
                                 Handshake_Hash& hash,
486
                                 const Policy& policy,
487
                                 Callbacks& cb,
488
                                 RandomNumberGenerator& rng,
489
                                 const std::vector<uint8_t>& reneg_info,
490
                                 const Client_Hello_12::Settings& client_settings,
491
                                 const std::vector<std::string>& next_protocols) {
2,478✔
492
   m_data->m_legacy_version = client_settings.protocol_version();
2,478✔
493
   m_data->m_random = make_hello_random(rng, cb, policy);
2,478✔
494
   m_data->m_suites = policy.ciphersuite_list(client_settings.protocol_version());
2,478✔
495

496
   if(!policy.acceptable_protocol_version(m_data->legacy_version())) {
2,478✔
497
      throw Internal_Error("Offering " + m_data->legacy_version().to_string() +
×
498
                           " but our own policy does not accept it");
×
499
   }
500

501
   /*
502
   * Place all empty extensions in front to avoid a bug in some systems
503
   * which reject hellos when the last extension in the list is empty.
504
   */
505

506
   // NOLINTBEGIN(*-owning-memory)
507

508
   // EMS must always be used with TLS 1.2, regardless of the policy used.
509

510
   m_data->extensions().add(new Extended_Master_Secret);
2,478✔
511

512
   if(policy.negotiate_encrypt_then_mac()) {
2,478✔
513
      m_data->extensions().add(new Encrypt_then_MAC);
2,465✔
514
   }
515

516
   m_data->extensions().add(new Session_Ticket_Extension());
2,478✔
517

518
   m_data->extensions().add(new Renegotiation_Extension(reneg_info));
2,478✔
519

520
   m_data->extensions().add(new Supported_Versions(m_data->legacy_version(), policy));
2,478✔
521

522
   if(hostname_acceptable_for_sni(client_settings.hostname())) {
2,478✔
523
      m_data->extensions().add(new Server_Name_Indicator(client_settings.hostname()));
2,455✔
524
   }
525

526
   if(policy.support_cert_status_message()) {
2,478✔
527
      m_data->extensions().add(new Certificate_Status_Request({}, {}));
2,159✔
528
   }
529

530
   add_tls12_supported_groups_extensions(policy);
2,478✔
531

532
   m_data->extensions().add(new Signature_Algorithms(policy.acceptable_signature_schemes()));
2,478✔
533
   if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) {
2,478✔
534
      // RFC 8446 4.2.3
535
      //    TLS 1.2 implementations SHOULD also process this extension.
536
      //    Implementations which have the same policy in both cases MAY omit
537
      //    the "signature_algorithms_cert" extension.
538
      m_data->extensions().add(new Signature_Algorithms_Cert(std::move(cert_signing_prefs.value())));
×
539
   }
×
540

541
   if(reneg_info.empty() && !next_protocols.empty()) {
2,478✔
542
      m_data->extensions().add(new Application_Layer_Protocol_Notification(next_protocols));
119✔
543
   }
544

545
   if(m_data->legacy_version().is_datagram_protocol()) {
2,478✔
546
      m_data->extensions().add(new SRTP_Protection_Profiles(policy.srtp_profiles()));
1,191✔
547
   }
548

549
   // NOLINTEND(*-owning-memory)
550

551
   cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Client, type());
2,478✔
552

553
   hash.update(io.send(*this));
4,956✔
554
}
2,478✔
555

556
/*
557
* Create a new Client Hello message (session resumption case)
558
*/
559
Client_Hello_12::Client_Hello_12(Handshake_IO& io,
218✔
560
                                 Handshake_Hash& hash,
561
                                 const Policy& policy,
562
                                 Callbacks& cb,
563
                                 RandomNumberGenerator& rng,
564
                                 const std::vector<uint8_t>& reneg_info,
565
                                 const Session_with_Handle& session,
566
                                 const std::vector<std::string>& next_protocols) {
218✔
567
   m_data->m_legacy_version = session.session.version();
218✔
568
   m_data->m_random = make_hello_random(rng, cb, policy);
218✔
569

570
   // RFC 5077 3.4
571
   //    When presenting a ticket, the client MAY generate and include a
572
   //    Session ID in the TLS ClientHello. [...] If a ticket is presented by
573
   //    the client, the server MUST NOT attempt to use the Session ID in the
574
   //    ClientHello for stateful session resumption.
575
   m_data->m_session_id = session.handle.id().value_or(Session_ID(make_hello_random(rng, cb, policy)));
436✔
576
   m_data->m_suites = policy.ciphersuite_list(m_data->legacy_version());
218✔
577

578
   if(!policy.acceptable_protocol_version(session.session.version())) {
218✔
579
      throw Internal_Error("Offering " + m_data->legacy_version().to_string() +
×
580
                           " but our own policy does not accept it");
×
581
   }
582

583
   if(!value_exists(m_data->ciphersuites(), session.session.ciphersuite_code())) {
436✔
584
      m_data->m_suites.push_back(session.session.ciphersuite_code());
8✔
585
   }
586

587
   /*
588
   * As EMS must always be used with TLS 1.2, add it even if it wasn't used
589
   * in the original session. If the server understands it and follows the
590
   * RFC it should reject our resume attempt and upgrade us to a new session
591
   * with the EMS protection.
592
   */
593
   // NOLINTBEGIN(*-owning-memory)
594
   m_data->extensions().add(new Extended_Master_Secret);
218✔
595

596
   if(session.session.supports_encrypt_then_mac()) {
218✔
597
      m_data->extensions().add(new Encrypt_then_MAC);
5✔
598
   }
599

600
   if(session.handle.is_ticket()) {
218✔
601
      m_data->extensions().add(new Session_Ticket_Extension(session.handle.ticket().value()));
720✔
602
   }
603

604
   m_data->extensions().add(new Renegotiation_Extension(reneg_info));
218✔
605

606
   const std::string hostname = session.session.server_info().hostname();
218✔
607

608
   if(hostname_acceptable_for_sni(hostname)) {
218✔
609
      m_data->extensions().add(new Server_Name_Indicator(hostname));
218✔
610
   }
611

612
   if(policy.support_cert_status_message()) {
218✔
613
      m_data->extensions().add(new Certificate_Status_Request({}, {}));
37✔
614
   }
615

616
   add_tls12_supported_groups_extensions(policy);
218✔
617

618
   m_data->extensions().add(new Signature_Algorithms(policy.acceptable_signature_schemes()));
218✔
619
   if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) {
218✔
620
      // RFC 8446 4.2.3
621
      //    TLS 1.2 implementations SHOULD also process this extension.
622
      //    Implementations which have the same policy in both cases MAY omit
623
      //    the "signature_algorithms_cert" extension.
624
      m_data->extensions().add(new Signature_Algorithms_Cert(std::move(cert_signing_prefs.value())));
×
625
   }
×
626

627
   if(reneg_info.empty() && !next_protocols.empty()) {
218✔
628
      m_data->extensions().add(new Application_Layer_Protocol_Notification(next_protocols));
22✔
629
   }
630
   // NOLINTEND(*-owning-memory)
631

632
   cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Client, type());
218✔
633

634
   hash.update(io.send(*this));
436✔
635
}
218✔
636

637
#if defined(BOTAN_HAS_TLS_13)
638

639
Client_Hello_13::Client_Hello_13(std::unique_ptr<Client_Hello_Internal> data) : Client_Hello(std::move(data)) {
465✔
640
   const auto& exts = m_data->extensions();
465✔
641

642
   // RFC 8446 4.1.2
643
   //    TLS 1.3 ClientHellos are identified as having a legacy_version of
644
   //    0x0303 and a "supported_versions" extension present with 0x0304 as the
645
   //    highest version indicated therein.
646
   //
647
   // Note that we already checked for "supported_versions" before entering this
648
   // c'tor in `Client_Hello_13::parse()`. This is just to be doubly sure.
649
   BOTAN_ASSERT_NOMSG(exts.has<Supported_Versions>());
465✔
650

651
   // RFC 8446 4.2.1
652
   //    Servers MAY abort the handshake upon receiving a ClientHello with
653
   //    legacy_version 0x0304 or later.
654
   if(m_data->legacy_version().is_tls_13_or_later()) {
465✔
655
      throw TLS_Exception(Alert::DecodeError, "TLS 1.3 Client Hello has invalid legacy_version");
1✔
656
   }
657

658
   // RFC 8446 4.1.2
659
   //    For every TLS 1.3 ClientHello, [the compression method] MUST contain
660
   //    exactly one byte, set to zero, [...].  If a TLS 1.3 ClientHello is
661
   //    received with any other value in this field, the server MUST abort the
662
   //    handshake with an "illegal_parameter" alert.
663
   if(m_data->comp_methods().size() != 1 || m_data->comp_methods().front() != 0) {
464✔
664
      throw TLS_Exception(Alert::IllegalParameter, "Client did not offer NULL compression");
4✔
665
   }
666

667
   // RFC 8446 4.2.9
668
   //    A client MUST provide a "psk_key_exchange_modes" extension if it
669
   //    offers a "pre_shared_key" extension. If clients offer "pre_shared_key"
670
   //    without a "psk_key_exchange_modes" extension, servers MUST abort
671
   //    the handshake.
672
   if(exts.has<PSK>()) {
460✔
673
      if(!exts.has<PSK_Key_Exchange_Modes>()) {
116✔
674
         throw TLS_Exception(Alert::MissingExtension,
1✔
675
                             "Client Hello offered a PSK without a psk_key_exchange_modes extension");
1✔
676
      }
677

678
      // RFC 8446 4.2.11
679
      //     The "pre_shared_key" extension MUST be the last extension in the
680
      //     ClientHello [...]. Servers MUST check that it is the last extension
681
      //     and otherwise fail the handshake with an "illegal_parameter" alert.
682
      if(exts.all().back()->type() != Extension_Code::PresharedKey) {
115✔
683
         throw TLS_Exception(Alert::IllegalParameter, "PSK extension was not at the very end of the Client Hello");
2✔
684
      }
685
   }
686

687
   // RFC 8446 9.2
688
   //    [A TLS 1.3 ClientHello] message MUST meet the following requirements:
689
   //
690
   //     -  If not containing a "pre_shared_key" extension, it MUST contain
691
   //        both a "signature_algorithms" extension and a "supported_groups"
692
   //        extension.
693
   //
694
   //     -  If containing a "supported_groups" extension, it MUST also contain
695
   //        a "key_share" extension, and vice versa.  An empty
696
   //        KeyShare.client_shares vector is permitted.
697
   //
698
   //    Servers receiving a ClientHello which does not conform to these
699
   //    requirements MUST abort the handshake with a "missing_extension"
700
   //    alert.
701
   if(!exts.has<PSK>()) {
457✔
702
      if(!exts.has<Supported_Groups>() || !exts.has<Signature_Algorithms>()) {
687✔
703
         throw TLS_Exception(
2✔
704
            Alert::MissingExtension,
705
            "Non-PSK Client Hello did not contain supported_groups and signature_algorithms extensions");
2✔
706
      }
707
   }
708
   if(exts.has<Supported_Groups>() != exts.has<Key_Share>()) {
455✔
709
      throw TLS_Exception(Alert::MissingExtension,
2✔
710
                          "Client Hello must either contain both key_share and supported_groups extensions or neither");
2✔
711
   }
712

713
   if(exts.has<Key_Share>()) {
453✔
714
      auto* const supported_ext = exts.get<Supported_Groups>();
453✔
715
      BOTAN_ASSERT_NONNULL(supported_ext);
453✔
716
      const auto supports = supported_ext->groups();
453✔
717
      const auto offers = exts.get<Key_Share>()->offered_groups();
453✔
718

719
      // RFC 8446 4.2.8
720
      //    Each KeyShareEntry value MUST correspond to a group offered in the
721
      //    "supported_groups" extension and MUST appear in the same order.
722
      //    [...]
723
      //    Clients MUST NOT offer any KeyShareEntry values for groups not
724
      //    listed in the client's "supported_groups" extension.
725
      //
726
      // Note: We can assume that both `offers` and `supports` are unique lists
727
      //       as this is ensured in the parsing code of the extensions.
728
      auto found_in_supported_groups = [&supports, support_offset = -1](auto group) mutable {
2,363✔
729
         const auto i = std::find(supports.begin(), supports.end(), group);
1,910✔
730
         if(i == supports.end()) {
1,910✔
731
            return false;
732
         }
733

734
         const auto found_at = std::distance(supports.begin(), i);
1,910✔
735
         if(found_at <= support_offset) {
1,910✔
736
            return false;  // The order that groups appear in "key_share" and
737
                           // "supported_groups" must be the same
738
         }
739

740
         support_offset = static_cast<decltype(support_offset)>(found_at);
1,910✔
741
         return true;
1,910✔
742
      };
453✔
743

744
      for(const auto offered : offers) {
2,363✔
745
         // RFC 8446 4.2.8
746
         //    Servers MAY check for violations of these rules and abort the
747
         //    handshake with an "illegal_parameter" alert if one is violated.
748
         if(!found_in_supported_groups(offered)) {
1,910✔
749
            throw TLS_Exception(Alert::IllegalParameter,
×
750
                                "Offered key exchange groups do not align with claimed supported groups");
×
751
         }
752
      }
753
   }
906✔
754

755
   // TODO: Reject oid_filters extension if found (which is the only known extension that
756
   //       must not occur in the TLS 1.3 client hello.
757
   // RFC 8446 4.2.5
758
   //    [The oid_filters extension] MUST only be sent in the CertificateRequest message.
759
}
465✔
760

761
/*
762
* Create a new Client Hello message
763
*/
764
Client_Hello_13::Client_Hello_13(const Policy& policy,
988✔
765
                                 Callbacks& cb,
766
                                 RandomNumberGenerator& rng,
767
                                 std::string_view hostname,
768
                                 const std::vector<std::string>& next_protocols,
769
                                 std::optional<Session_with_Handle>& session,
770
                                 std::vector<ExternalPSK> psks) {
988✔
771
   // RFC 8446 4.1.2
772
   //    In TLS 1.3, the client indicates its version preferences in the
773
   //    "supported_versions" extension (Section 4.2.1) and the
774
   //    legacy_version field MUST be set to 0x0303, which is the version
775
   //    number for TLS 1.2.
776
   m_data->m_legacy_version = Protocol_Version::TLS_V12;
988✔
777
   m_data->m_random = make_hello_random(rng, cb, policy);
988✔
778
   m_data->m_suites = policy.ciphersuite_list(Protocol_Version::TLS_V13);
988✔
779

780
   if(policy.allow_tls12()) {
988✔
781
      // Note: DTLS 1.3 is NYI, hence dtls_12 is not checked
782
      const auto legacy_suites = policy.ciphersuite_list(Protocol_Version::TLS_V12);
959✔
783
      m_data->m_suites.insert(m_data->m_suites.end(), legacy_suites.cbegin(), legacy_suites.cend());
959✔
784
   }
959✔
785

786
   if(policy.tls_13_middlebox_compatibility_mode()) {
988✔
787
      // RFC 8446 4.1.2
788
      //    In compatibility mode (see Appendix D.4), this field MUST be non-empty,
789
      //    so a client not offering a pre-TLS 1.3 session MUST generate a new
790
      //    32-byte value.
791
      //
792
      // Note: we won't ever offer a TLS 1.2 session. In such a case we would
793
      //       have instantiated a TLS 1.2 client in the first place.
794
      m_data->m_session_id = Session_ID(make_hello_random(rng, cb, policy));
975✔
795
   }
796

797
   // NOLINTBEGIN(*-owning-memory)
798
   if(hostname_acceptable_for_sni(hostname)) {
988✔
799
      m_data->extensions().add(new Server_Name_Indicator(hostname));
964✔
800
   }
801

802
   m_data->extensions().add(new Supported_Groups(policy.key_exchange_groups()));
988✔
803

804
   m_data->extensions().add(new Key_Share(policy, cb, rng));
988✔
805

806
   m_data->extensions().add(new Supported_Versions(Protocol_Version::TLS_V13, policy));
988✔
807

808
   m_data->extensions().add(new Signature_Algorithms(policy.acceptable_signature_schemes()));
988✔
809
   if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) {
988✔
810
      // RFC 8446 4.2.3
811
      //    Implementations which have the same policy in both cases MAY omit
812
      //    the "signature_algorithms_cert" extension.
813
      m_data->extensions().add(new Signature_Algorithms_Cert(std::move(cert_signing_prefs.value())));
×
814
   }
×
815

816
   // TODO: Support for PSK-only mode without a key exchange.
817
   //       This should be configurable in TLS::Policy and should allow no PSK
818
   //       support at all (e.g. to disable support for session resumption).
819
   m_data->extensions().add(new PSK_Key_Exchange_Modes({PSK_Key_Exchange_Mode::PSK_DHE_KE}));
988✔
820

821
   if(policy.support_cert_status_message()) {
988✔
822
      m_data->extensions().add(new Certificate_Status_Request({}, {}));
106✔
823
   }
824

825
   // We currently support "record_size_limit" for TLS 1.3 exclusively. Hence,
826
   // when TLS 1.2 is advertised as a supported protocol, we must not offer this
827
   // extension.
828
   if(policy.record_size_limit().has_value() && !policy.allow_tls12()) {
988✔
829
      m_data->extensions().add(new Record_Size_Limit(policy.record_size_limit().value()));
16✔
830
   }
831

832
   if(!next_protocols.empty()) {
988✔
833
      m_data->extensions().add(new Application_Layer_Protocol_Notification(next_protocols));
11✔
834
   }
835

836
   // RFC 7250 4.1
837
   //    In order to indicate the support of raw public keys, clients include
838
   //    the client_certificate_type and/or the server_certificate_type
839
   //    extensions in an extended client hello message.
840
   m_data->extensions().add(new Client_Certificate_Type(policy.accepted_client_certificate_types()));
1,976✔
841
   m_data->extensions().add(new Server_Certificate_Type(policy.accepted_server_certificate_types()));
1,976✔
842

843
   if(policy.allow_tls12()) {
988✔
844
      m_data->extensions().add(new Renegotiation_Extension());
959✔
845
      m_data->extensions().add(new Session_Ticket_Extension());
959✔
846

847
      // EMS must always be used with TLS 1.2, regardless of the policy
848
      m_data->extensions().add(new Extended_Master_Secret);
959✔
849

850
      if(policy.negotiate_encrypt_then_mac()) {
959✔
851
         m_data->extensions().add(new Encrypt_then_MAC);
959✔
852
      }
853

854
      if(m_data->extensions().has<Supported_Groups>() &&
1,918✔
855
         !m_data->extensions().get<Supported_Groups>()->ec_groups().empty()) {
1,918✔
856
         m_data->extensions().add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
957✔
857
      }
858
   }
859

860
   if(session.has_value() || !psks.empty()) {
988✔
861
      m_data->extensions().add(new PSK(session, std::move(psks), cb));
108✔
862
   }
863
   // NOLINTEND(*-owning-memory)
864

865
   cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Client, type());
988✔
866

867
   if(m_data->extensions().has<PSK>()) {
988✔
868
      // RFC 8446 4.2.11
869
      //    The "pre_shared_key" extension MUST be the last extension in the
870
      //    ClientHello (this facilitates implementation [...]).
871
      if(m_data->extensions().all().back()->type() != Extension_Code::PresharedKey) {
108✔
872
         throw TLS_Exception(Alert::InternalError,
×
873
                             "Application modified extensions of Client Hello, PSK is not last anymore");
×
874
      }
875
      calculate_psk_binders({});
108✔
876
   }
877
}
988✔
878

879
std::variant<Client_Hello_13, Client_Hello_12> Client_Hello_13::parse(const std::vector<uint8_t>& buf) {
1,004✔
880
   auto data = std::make_unique<Client_Hello_Internal>(buf);
1,004✔
881
   const auto version = data->version();
978✔
882

883
   if(version.is_pre_tls_13()) {
978✔
884
      return Client_Hello_12(std::move(data));
1,026✔
885
   } else {
886
      return Client_Hello_13(std::move(data));
918✔
887
   }
888
}
978✔
889

890
void Client_Hello_13::retry(const Hello_Retry_Request& hrr,
61✔
891
                            const Transcript_Hash_State& transcript_hash_state,
892
                            Callbacks& cb,
893
                            RandomNumberGenerator& rng) {
894
   BOTAN_STATE_CHECK(m_data->extensions().has<Supported_Groups>());
61✔
895
   BOTAN_STATE_CHECK(m_data->extensions().has<Key_Share>());
61✔
896

897
   auto* hrr_ks = hrr.extensions().get<Key_Share>();
61✔
898
   const auto& supported_groups = m_data->extensions().get<Supported_Groups>()->groups();
61✔
899

900
   if(hrr.extensions().has<Key_Share>()) {
61✔
901
      m_data->extensions().get<Key_Share>()->retry_offer(*hrr_ks, supported_groups, cb, rng);
60✔
902
   }
903

904
   // RFC 8446 4.2.2
905
   //    When sending the new ClientHello, the client MUST copy
906
   //    the contents of the extension received in the HelloRetryRequest into
907
   //    a "cookie" extension in the new ClientHello.
908
   //
909
   // RFC 8446 4.2.2
910
   //    Clients MUST NOT use cookies in their initial ClientHello in subsequent
911
   //    connections.
912
   if(hrr.extensions().has<Cookie>()) {
58✔
913
      BOTAN_STATE_CHECK(!m_data->extensions().has<Cookie>());
3✔
914
      m_data->extensions().add(new Cookie(hrr.extensions().get<Cookie>()->get_cookie()));  // NOLINT(*-owning-memory)
3✔
915
   }
916

917
   // Note: the consumer of the TLS implementation won't be able to distinguish
918
   //       invocations to this callback due to the first Client_Hello or the
919
   //       retried Client_Hello after receiving a Hello_Retry_Request. We assume
920
   //       that the user keeps and detects this state themselves.
921
   cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Client, type());
58✔
922

923
   auto* psk = m_data->extensions().get<PSK>();
58✔
924
   if(psk != nullptr) {
58✔
925
      // Cipher suite should always be a known suite as this is checked upstream
926
      const auto cipher = Ciphersuite::by_id(hrr.ciphersuite());
11✔
927
      BOTAN_ASSERT_NOMSG(cipher.has_value());
11✔
928

929
      // RFC 8446 4.1.4
930
      //    In [...] its updated ClientHello, the client SHOULD NOT offer
931
      //    any pre-shared keys associated with a hash other than that of the
932
      //    selected cipher suite.
933
      psk->filter(cipher.value());
11✔
934

935
      // RFC 8446 4.2.11.2
936
      //    If the server responds with a HelloRetryRequest and the client
937
      //    then sends ClientHello2, its binder will be computed over: [...].
938
      calculate_psk_binders(transcript_hash_state.clone());
11✔
939
   }
940
}
58✔
941

942
void Client_Hello_13::validate_updates(const Client_Hello_13& new_ch) {
44✔
943
   // RFC 8446 4.1.2
944
   //    The client will also send a ClientHello when the server has responded
945
   //    to its ClientHello with a HelloRetryRequest. In that case, the client
946
   //    MUST send the same ClientHello without modification, except as follows:
947

948
   if(m_data->session_id() != new_ch.m_data->session_id() || m_data->random() != new_ch.m_data->random() ||
44✔
949
      m_data->ciphersuites() != new_ch.m_data->ciphersuites() ||
88✔
950
      m_data->comp_methods() != new_ch.m_data->comp_methods()) {
44✔
951
      throw TLS_Exception(Alert::IllegalParameter, "Client Hello core values changed after Hello Retry Request");
×
952
   }
953

954
   const auto oldexts = extension_types();
44✔
955
   const auto newexts = new_ch.extension_types();
44✔
956

957
   // Check that extension omissions are justified
958
   for(const auto oldext : oldexts) {
502✔
959
      if(!newexts.contains(oldext)) {
918✔
960
         auto* const ext = extensions().get(oldext);
1✔
961

962
         // We don't make any assumptions about unimplemented extensions.
963
         if(!ext->is_implemented()) {
1✔
964
            continue;
×
965
         }
966

967
         // RFC 8446 4.1.2
968
         //    Removing the "early_data" extension (Section 4.2.10) if one was
969
         //    present.  Early data is not permitted after a HelloRetryRequest.
970
         if(oldext == EarlyDataIndication::static_type()) {
1✔
971
            continue;
×
972
         }
973

974
         // RFC 8446 4.1.2
975
         //    Optionally adding, removing, or changing the length of the
976
         //    "padding" extension.
977
         //
978
         // TODO: implement the Padding extension
979
         // if(oldext == Padding::static_type())
980
         //    continue;
981

982
         throw TLS_Exception(Alert::IllegalParameter, "Extension removed in updated Client Hello");
1✔
983
      }
984
   }
985

986
   // Check that extension additions are justified
987
   for(const auto newext : newexts) {
495✔
988
      if(!oldexts.contains(newext)) {
904✔
989
         auto* const ext = new_ch.extensions().get(newext);
2✔
990

991
         // We don't make any assumptions about unimplemented extensions.
992
         if(!ext->is_implemented()) {
2✔
993
            continue;
1✔
994
         }
995

996
         // RFC 8446 4.1.2
997
         //    Including a "cookie" extension if one was provided in the
998
         //    HelloRetryRequest.
999
         if(newext == Cookie::static_type()) {
1✔
1000
            continue;
1✔
1001
         }
1002

1003
         // RFC 8446 4.1.2
1004
         //    Optionally adding, removing, or changing the length of the
1005
         //    "padding" extension.
1006
         //
1007
         // TODO: implement the Padding extension
1008
         // if(newext == Padding::static_type())
1009
         //    continue;
1010

1011
         throw TLS_Exception(Alert::UnsupportedExtension, "Added an extension in updated Client Hello");
×
1012
      }
1013
   }
1014

1015
   // RFC 8446 4.1.2
1016
   //    Removing the "early_data" extension (Section 4.2.10) if one was
1017
   //    present.  Early data is not permitted after a HelloRetryRequest.
1018
   if(new_ch.extensions().has<EarlyDataIndication>()) {
43✔
1019
      throw TLS_Exception(Alert::IllegalParameter, "Updated Client Hello indicates early data");
×
1020
   }
1021

1022
   // TODO: Contents of extensions are not checked for update compatibility, see:
1023
   //
1024
   // RFC 8446 4.1.2
1025
   //    If a "key_share" extension was supplied in the HelloRetryRequest,
1026
   //    replacing the list of shares with a list containing a single
1027
   //    KeyShareEntry from the indicated group.
1028
   //
1029
   //    Updating the "pre_shared_key" extension if present by recomputing
1030
   //    the "obfuscated_ticket_age" and binder values and (optionally)
1031
   //    removing any PSKs which are incompatible with the server's
1032
   //    indicated cipher suite.
1033
   //
1034
   //    Optionally adding, removing, or changing the length of the
1035
   //    "padding" extension.
1036
}
44✔
1037

1038
void Client_Hello_13::calculate_psk_binders(Transcript_Hash_State transcript_hash) {
119✔
1039
   auto* psk = m_data->extensions().get<PSK>();
119✔
1040
   if(psk == nullptr || psk->empty()) {
119✔
1041
      return;
1✔
1042
   }
1043

1044
   // RFC 8446 4.2.11.2
1045
   //    Each entry in the binders list is computed as an HMAC over a
1046
   //    transcript hash (see Section 4.4.1) containing a partial ClientHello
1047
   //    [...].
1048
   //
1049
   // Therefore we marshal the entire message prematurely to obtain the
1050
   // (truncated) transcript hash, calculate the PSK binders with it, update
1051
   // the Client Hello thus finalizing the message. Down the road, it will be
1052
   // re-marshalled with the correct binders and sent over the wire.
1053
   Handshake_Layer::prepare_message(*this, transcript_hash);
118✔
1054
   psk->calculate_binders(transcript_hash);
118✔
1055
}
1056

1057
std::optional<Protocol_Version> Client_Hello_13::highest_supported_version(const Policy& policy) const {
390✔
1058
   // RFC 8446 4.2.1
1059
   //    The "supported_versions" extension is used by the client to indicate
1060
   //    which versions of TLS it supports and by the server to indicate which
1061
   //    version it is using. The extension contains a list of supported
1062
   //    versions in preference order, with the most preferred version first.
1063
   auto* const supvers = m_data->extensions().get<Supported_Versions>();
390✔
1064
   BOTAN_ASSERT_NONNULL(supvers);
390✔
1065

1066
   std::optional<Protocol_Version> result;
390✔
1067

1068
   for(const auto& v : supvers->versions()) {
1,977✔
1069
      // RFC 8446 4.2.1
1070
      //    Servers MUST only select a version of TLS present in that extension
1071
      //    and MUST ignore any unknown versions that are present in that
1072
      //    extension.
1073
      if(!v.known_version() || !policy.acceptable_protocol_version(v)) {
1,587✔
1074
         continue;
899✔
1075
      }
1076

1077
      result = (result.has_value()) ? std::optional(std::max(result.value(), v)) : std::optional(v);
986✔
1078
   }
1079

1080
   return result;
390✔
1081
}
1082

1083
#endif  // BOTAN_HAS_TLS_13
1084

1085
}  // 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