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

randombit / botan / 22045650098

16 Feb 2026 12:06AM UTC coverage: 90.042% (-0.001%) from 90.043%
22045650098

Pull #5343

github

web-flow
Merge 497a2bc56 into c5489e013
Pull Request #5343: Avoid using <algorithm> in tls_session_id.h

102324 of 113640 relevant lines covered (90.04%)

11427682.81 hits per line

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

93.44
/src/lib/tls/msg_client_hello.cpp
1
/*
2
* TLS 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
*     2026 René Meusel - Rohde & Schwarz Cybersecurity GmbH
9
*
10
* Botan is released under the Simplified BSD License (see license.txt)
11
*/
12

13
#include <botan/tls_messages.h>
14
#include <botan/internal/tls_messages_internal.h>
15

16
#include <botan/hash.h>
17
#include <botan/rng.h>
18
#include <botan/tls_callbacks.h>
19
#include <botan/tls_policy.h>
20
#include <botan/internal/tls_reader.h>
21
#include <algorithm>
22

23
namespace Botan::TLS {
24

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

28
   if(policy.hash_hello_random()) {
6,962✔
29
      auto sha256 = HashFunction::create_or_throw("SHA-256");
6,947✔
30
      sha256->update(buf);
6,947✔
31
      sha256->final(buf);
6,947✔
32
   }
6,947✔
33

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

40
      store_be(time32, buf.data());
6,939✔
41
   }
42

43
   return buf;
6,962✔
44
}
×
45

46
Client_Hello_Internal::Client_Hello_Internal(const std::vector<uint8_t>& buf) {
3,901✔
47
   if(buf.size() < 41) {
3,901✔
48
      throw Decoding_Error("Client_Hello: Packet corrupted");
45✔
49
   }
50

51
   TLS_Data_Reader reader("ClientHello", buf);
3,856✔
52

53
   const uint8_t major_version = reader.get_byte();
3,856✔
54
   const uint8_t minor_version = reader.get_byte();
3,856✔
55

56
   m_legacy_version = Protocol_Version(major_version, minor_version);
3,856✔
57
   m_random = reader.get_fixed<uint8_t>(32);
3,856✔
58
   m_session_id = Session_ID(reader.get_range<uint8_t>(1, 0, 32));
3,856✔
59

60
   if(m_legacy_version.is_datagram_protocol()) {
3,017✔
61
      auto sha256 = HashFunction::create_or_throw("SHA-256");
796✔
62
      sha256->update(reader.get_data_read_so_far());
796✔
63

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

66
      sha256->update(reader.get_remaining());
796✔
67
      m_cookie_input_bits = sha256->final_stdvec();
796✔
68
   }
796✔
69

70
   m_suites = reader.get_range_vector<uint16_t>(2, 1, 32767);
3,017✔
71
   m_comp_methods = reader.get_range_vector<uint8_t>(1, 1, 255);
2,891✔
72

73
   m_extensions.deserialize(reader, Connection_Side::Client, Handshake_Type::ClientHello);
2,891✔
74
}
5,997✔
75

76
Protocol_Version Client_Hello_Internal::version() const {
978✔
77
   // RFC 8446 4.2.1
78
   //    If [the "supported_versions"] extension is not present, servers
79
   //    which are compliant with this specification and which also support
80
   //    TLS 1.2 MUST negotiate TLS 1.2 or prior as specified in [RFC5246],
81
   //    even if ClientHello.legacy_version is 0x0304 or later.
82
   //
83
   // RFC 8446 4.2.1
84
   //    Servers MUST be prepared to receive ClientHellos that include
85
   //    [the supported_versions] extension but do not include 0x0304 in
86
   //    the list of versions.
87
   //
88
   // RFC 8446 4.1.2
89
   //    TLS 1.3 ClientHellos are identified as having a legacy_version of
90
   //    0x0303 and a supported_versions extension present with 0x0304 as
91
   //    the highest version indicated therein.
92
   if(!extensions().has<Supported_Versions>() ||
1,461✔
93
      !extensions().get<Supported_Versions>()->supports(Protocol_Version::TLS_V13)) {
483✔
94
      // The exact legacy_version is ignored we just inspect it to
95
      // distinguish TLS and DTLS.
96
      return (m_legacy_version.is_datagram_protocol()) ? Protocol_Version::DTLS_V12 : Protocol_Version::TLS_V12;
1,026✔
97
   }
98

99
   // Note: The Client_Hello_13 class will make sure that legacy_version
100
   //       is exactly 0x0303 (aka ossified TLS 1.2)
101
   return Protocol_Version::TLS_V13;
465✔
102
}
103

104
Client_Hello::Client_Hello(Client_Hello&&) noexcept = default;
10,494✔
105
Client_Hello& Client_Hello::operator=(Client_Hello&&) noexcept = default;
43✔
106

107
Client_Hello::~Client_Hello() = default;
17,023✔
108

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

111
/*
112
* Read a counterparty client hello
113
*/
114
Client_Hello::Client_Hello(std::unique_ptr<Client_Hello_Internal> data) : m_data(std::move(data)) {
2,862✔
115
   BOTAN_ASSERT_NONNULL(m_data);
2,862✔
116
}
2,862✔
117

118
Handshake_Type Client_Hello::type() const {
16,308✔
119
   return Handshake_Type::ClientHello;
16,308✔
120
}
121

122
Protocol_Version Client_Hello::legacy_version() const {
8,243✔
123
   return m_data->legacy_version();
8,243✔
124
}
125

126
const std::vector<uint8_t>& Client_Hello::random() const {
3,844✔
127
   return m_data->random();
3,844✔
128
}
129

130
const Session_ID& Client_Hello::session_id() const {
3,322✔
131
   return m_data->session_id();
3,322✔
132
}
133

134
const std::vector<uint8_t>& Client_Hello::compression_methods() const {
1,383✔
135
   return m_data->comp_methods();
1,383✔
136
}
137

138
const std::vector<uint16_t>& Client_Hello::ciphersuites() const {
1,430✔
139
   return m_data->ciphersuites();
1,430✔
140
}
141

142
std::set<Extension_Code> Client_Hello::extension_types() const {
3,256✔
143
   return m_data->extensions().extension_types();
3,256✔
144
}
145

146
const Extensions& Client_Hello::extensions() const {
9,825✔
147
   return m_data->extensions();
9,825✔
148
}
149

150
/*
151
* Serialize a Client Hello message
152
*/
153
std::vector<uint8_t> Client_Hello::serialize() const {
4,347✔
154
   std::vector<uint8_t> buf;
4,347✔
155
   buf.reserve(1024);  // working around GCC warning
4,347✔
156

157
   buf.push_back(m_data->legacy_version().major_version());
4,347✔
158
   buf.push_back(m_data->legacy_version().minor_version());
4,347✔
159
   buf += m_data->random();
4,347✔
160

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

163
   if(m_data->legacy_version().is_datagram_protocol()) {
4,347✔
164
      append_tls_length_value(buf, m_data->hello_cookie(), 1);
951✔
165
   }
166

167
   append_tls_length_value(buf, m_data->ciphersuites(), 2);
4,347✔
168
   append_tls_length_value(buf, m_data->comp_methods(), 1);
4,347✔
169

170
   /*
171
   * May not want to send extensions at all in some cases. If so,
172
   * should include SCSV value (if reneg info is empty, if not we are
173
   * renegotiating with a modern server)
174
   */
175

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

178
   return buf;
4,347✔
179
}
×
180

181
std::vector<uint8_t> Client_Hello::cookie_input_data() const {
790✔
182
   BOTAN_STATE_CHECK(!m_data->hello_cookie_input_bits().empty());
790✔
183

184
   return m_data->hello_cookie_input_bits();
790✔
185
}
186

187
/*
188
* Check if we offered this ciphersuite
189
*/
190
bool Client_Hello::offered_suite(uint16_t ciphersuite) const {
4,772✔
191
   return std::find(m_data->ciphersuites().cbegin(), m_data->ciphersuites().cend(), ciphersuite) !=
4,772✔
192
          m_data->ciphersuites().cend();
4,772✔
193
}
194

195
std::vector<Signature_Scheme> Client_Hello::signature_schemes() const {
4,122✔
196
   if(const Signature_Algorithms* sigs = m_data->extensions().get<Signature_Algorithms>()) {
4,122✔
197
      return sigs->supported_schemes();
4,120✔
198
   }
199
   return {};
2✔
200
}
201

202
std::vector<Signature_Scheme> Client_Hello::certificate_signature_schemes() const {
1,022✔
203
   // RFC 8446 4.2.3
204
   //   If no "signature_algorithms_cert" extension is present, then the
205
   //   "signature_algorithms" extension also applies to signatures appearing
206
   //   in certificates.
207
   if(const Signature_Algorithms_Cert* sigs = m_data->extensions().get<Signature_Algorithms_Cert>()) {
1,022✔
208
      return sigs->supported_schemes();
×
209
   } else {
210
      return signature_schemes();
1,022✔
211
   }
212
}
213

214
std::vector<Group_Params> Client_Hello::supported_ecc_curves() const {
1,371✔
215
   if(const Supported_Groups* groups = m_data->extensions().get<Supported_Groups>()) {
1,371✔
216
      return groups->ec_groups();
1,368✔
217
   }
218
   return {};
3✔
219
}
220

221
std::vector<Group_Params> Client_Hello::supported_dh_groups() const {
1,518✔
222
   if(const Supported_Groups* groups = m_data->extensions().get<Supported_Groups>()) {
1,518✔
223
      return groups->dh_groups();
1,512✔
224
   }
225
   return std::vector<Group_Params>();
6✔
226
}
227

228
std::string Client_Hello::sni_hostname() const {
4,228✔
229
   if(const Server_Name_Indicator* sni = m_data->extensions().get<Server_Name_Indicator>()) {
4,228✔
230
      return sni->host_name();
4,098✔
231
   }
232
   return "";
130✔
233
}
234

235
std::vector<Protocol_Version> Client_Hello::supported_versions() const {
1,385✔
236
   if(const Supported_Versions* versions = m_data->extensions().get<Supported_Versions>()) {
1,385✔
237
      return versions->versions();
303✔
238
   }
239
   return {};
1,082✔
240
}
241

242
bool Client_Hello::supports_alpn() const {
1,127✔
243
   return m_data->extensions().has<Application_Layer_Protocol_Notification>();
1,127✔
244
}
245

246
bool Client_Hello::sent_signature_algorithms() const {
×
247
   return m_data->extensions().has<Signature_Algorithms>();
×
248
}
249

250
std::vector<std::string> Client_Hello::next_protocols() const {
149✔
251
   if(auto* alpn = m_data->extensions().get<Application_Layer_Protocol_Notification>()) {
149✔
252
      return alpn->protocols();
149✔
253
   }
254
   return {};
×
255
}
256

257
std::vector<uint16_t> Client_Hello::srtp_profiles() const {
295✔
258
   if(const SRTP_Protection_Profiles* srtp = m_data->extensions().get<SRTP_Protection_Profiles>()) {
295✔
259
      return srtp->profiles();
4✔
260
   }
261
   return {};
291✔
262
}
263

264
const std::vector<uint8_t>& Client_Hello::cookie() const {
790✔
265
   return m_data->hello_cookie();
790✔
266
}
267

268
Client_Hello_12_Shim::Client_Hello_12_Shim(std::unique_ptr<Client_Hello_Internal> data) :
2,397✔
269
      Client_Hello(std::move(data)) {}
2,397✔
270

271
Client_Hello_12_Shim::Client_Hello_12_Shim(const std::vector<uint8_t>& buf) :
×
272
      Client_Hello_12_Shim(std::make_unique<Client_Hello_Internal>(buf)) {}
×
273

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