Botan 2.19.0
Crypto and TLS for C&
msg_client_hello.cpp
Go to the documentation of this file.
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*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#include <botan/tls_messages.h>
11#include <botan/tls_alert.h>
12#include <botan/tls_exceptn.h>
13#include <botan/tls_callbacks.h>
14#include <botan/rng.h>
15#include <botan/hash.h>
16
17#include <botan/internal/tls_reader.h>
18#include <botan/internal/tls_session_key.h>
19#include <botan/internal/tls_handshake_io.h>
20#include <botan/internal/tls_handshake_hash.h>
21#include <botan/internal/stl_util.h>
22#include <chrono>
23
24namespace Botan {
25
26namespace TLS {
27
28enum {
30 TLS_FALLBACK_SCSV = 0x5600
31};
32
33std::vector<uint8_t> make_hello_random(RandomNumberGenerator& rng,
34 const Policy& policy)
35 {
36 std::vector<uint8_t> buf(32);
37 rng.randomize(buf.data(), buf.size());
38
39 std::unique_ptr<HashFunction> sha256 = HashFunction::create_or_throw("SHA-256");
40 sha256->update(buf);
41 sha256->final(buf);
42
44 {
45 const uint32_t time32 = static_cast<uint32_t>(
46 std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
47
48 store_be(time32, buf.data());
49 }
50
51 return buf;
52 }
53
54/*
55* Create a new Hello Request message
56*/
58 {
59 io.send(*this);
60 }
61
62/*
63* Deserialize a Hello Request message
64*/
65Hello_Request::Hello_Request(const std::vector<uint8_t>& buf)
66 {
67 if(buf.size())
68 throw Decoding_Error("Bad Hello_Request, has non-zero size");
69 }
70
71/*
72* Serialize a Hello Request message
73*/
74std::vector<uint8_t> Hello_Request::serialize() const
75 {
76 return std::vector<uint8_t>();
77 }
78
79/*
80* Create a new Client Hello message
81*/
84 const Policy& policy,
85 Callbacks& cb,
87 const std::vector<uint8_t>& reneg_info,
88 const Client_Hello::Settings& client_settings,
89 const std::vector<std::string>& next_protocols) :
90 m_version(client_settings.protocol_version()),
91 m_random(make_hello_random(rng, policy)),
92 m_suites(policy.ciphersuite_list(m_version, !client_settings.srp_identifier().empty())),
93 m_comp_methods(1)
94 {
95 if(!policy.acceptable_protocol_version(m_version))
96 throw Internal_Error("Offering " + m_version.to_string() +
97 " but our own policy does not accept it");
98
99 /*
100 * Place all empty extensions in front to avoid a bug in some systems
101 * which reject hellos when the last extension in the list is empty.
102 */
103 m_extensions.add(new Extended_Master_Secret);
104 m_extensions.add(new Session_Ticket());
105
106 if(policy.negotiate_encrypt_then_mac())
107 m_extensions.add(new Encrypt_then_MAC);
108
109 m_extensions.add(new Renegotiation_Extension(reneg_info));
110
111 m_extensions.add(new Supported_Versions(m_version, policy));
112
113 if(client_settings.hostname() != "")
114 m_extensions.add(new Server_Name_Indicator(client_settings.hostname()));
115
116 if(policy.support_cert_status_message())
117 m_extensions.add(new Certificate_Status_Request({}, {}));
118
119 if(reneg_info.empty() && !next_protocols.empty())
121
123 m_extensions.add(new Signature_Algorithms(policy.allowed_signature_schemes()));
124
125 if(m_version.is_datagram_protocol())
126 m_extensions.add(new SRTP_Protection_Profiles(policy.srtp_profiles()));
127
128#if defined(BOTAN_HAS_SRP6)
129 m_extensions.add(new SRP_Identifier(client_settings.srp_identifier()));
130#else
131 if(!client_settings.srp_identifier().empty())
132 {
133 throw Invalid_State("Attempting to initiate SRP session but TLS-SRP support disabled");
134 }
135#endif
136
137 std::unique_ptr<Supported_Groups> supported_groups(new Supported_Groups(policy.key_exchange_groups()));
138
139 if(supported_groups->ec_groups().size() > 0)
140 {
141 m_extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
142 }
143
144 m_extensions.add(supported_groups.release());
145
146 cb.tls_modify_extensions(m_extensions, CLIENT);
147
148 if(policy.send_fallback_scsv(client_settings.protocol_version()))
149 m_suites.push_back(TLS_FALLBACK_SCSV);
150
151 hash.update(io.send(*this));
152 }
153
154/*
155* Create a new Client Hello message (session resumption case)
156*/
159 const Policy& policy,
160 Callbacks& cb,
162 const std::vector<uint8_t>& reneg_info,
163 const Session& session,
164 const std::vector<std::string>& next_protocols) :
165 m_version(session.version()),
166 m_session_id(session.session_id()),
167 m_random(make_hello_random(rng, policy)),
168 m_suites(policy.ciphersuite_list(m_version, (session.srp_identifier() != ""))),
169 m_comp_methods(1)
170 {
171 if(!policy.acceptable_protocol_version(m_version))
172 throw Internal_Error("Offering " + m_version.to_string() +
173 " but our own policy does not accept it");
174
175 if(!value_exists(m_suites, session.ciphersuite_code()))
176 m_suites.push_back(session.ciphersuite_code());
177
178 /*
179 We always add the EMS extension, even if not used in the original session.
180 If the server understands it and follows the RFC it should reject our resume
181 attempt and upgrade us to a new session with the EMS protection.
182 */
183 m_extensions.add(new Extended_Master_Secret);
184
185 m_extensions.add(new Renegotiation_Extension(reneg_info));
186 m_extensions.add(new Server_Name_Indicator(session.server_info().hostname()));
187 m_extensions.add(new Session_Ticket(session.session_ticket()));
188
189 if(policy.support_cert_status_message())
190 m_extensions.add(new Certificate_Status_Request({}, {}));
191
192 std::unique_ptr<Supported_Groups> supported_groups(new Supported_Groups(policy.key_exchange_groups()));
193
194 if(supported_groups->ec_groups().size() > 0)
195 {
196 m_extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
197 }
198
199 m_extensions.add(supported_groups.release());
200
201 if(session.supports_encrypt_then_mac())
202 m_extensions.add(new Encrypt_then_MAC);
203
204#if defined(BOTAN_HAS_SRP6)
205 m_extensions.add(new SRP_Identifier(session.srp_identifier()));
206#else
207 if(!session.srp_identifier().empty())
208 {
209 throw Invalid_State("Attempting to resume SRP session but TLS-SRP support disabled");
210 }
211#endif
212
214 m_extensions.add(new Signature_Algorithms(policy.allowed_signature_schemes()));
215
216 if(reneg_info.empty() && !next_protocols.empty())
218
219 cb.tls_modify_extensions(m_extensions, CLIENT);
220
221 hash.update(io.send(*this));
222 }
223
225 {
226 if(!m_version.is_datagram_protocol())
227 throw Invalid_State("Cannot use hello cookie with stream protocol");
228
229 m_hello_cookie = hello_verify.cookie();
230 }
231
232/*
233* Serialize a Client Hello message
234*/
235std::vector<uint8_t> Client_Hello::serialize() const
236 {
237 std::vector<uint8_t> buf;
238
239 buf.push_back(m_version.major_version());
240 buf.push_back(m_version.minor_version());
241 buf += m_random;
242
243 append_tls_length_value(buf, m_session_id, 1);
244
245 if(m_version.is_datagram_protocol())
246 append_tls_length_value(buf, m_hello_cookie, 1);
247
248 append_tls_length_value(buf, m_suites, 2);
249 append_tls_length_value(buf, m_comp_methods, 1);
250
251 /*
252 * May not want to send extensions at all in some cases. If so,
253 * should include SCSV value (if reneg info is empty, if not we are
254 * renegotiating with a modern server)
255 */
256
257 buf += m_extensions.serialize(Connection_Side::CLIENT);
258
259 return buf;
260 }
261
262std::vector<uint8_t> Client_Hello::cookie_input_data() const
263 {
264 std::vector<uint8_t> buf;
265
266 buf.push_back(m_version.major_version());
267 buf.push_back(m_version.minor_version());
268 buf += m_random;
269
270 append_tls_length_value(buf, m_session_id, 1);
271
272 append_tls_length_value(buf, m_suites, 2);
273 append_tls_length_value(buf, m_comp_methods, 1);
274
275 // Here we don't serialize the extensions since the client extensions
276 // may contain values we don't know how to serialize back.
277
278 return buf;
279 }
280
281/*
282* Read a counterparty client hello
283*/
284Client_Hello::Client_Hello(const std::vector<uint8_t>& buf)
285 {
286 if(buf.size() < 41)
287 throw Decoding_Error("Client_Hello: Packet corrupted");
288
289 TLS_Data_Reader reader("ClientHello", buf);
290
291 const uint8_t major_version = reader.get_byte();
292 const uint8_t minor_version = reader.get_byte();
293
294 m_version = Protocol_Version(major_version, minor_version);
295
296 m_random = reader.get_fixed<uint8_t>(32);
297
298 m_session_id = reader.get_range<uint8_t>(1, 0, 32);
299
300 if(m_version.is_datagram_protocol())
301 m_hello_cookie = reader.get_range<uint8_t>(1, 0, 255);
302
303 m_suites = reader.get_range_vector<uint16_t>(2, 1, 32767);
304
305 m_comp_methods = reader.get_range_vector<uint8_t>(1, 1, 255);
306
307 m_extensions.deserialize(reader, Connection_Side::CLIENT);
308
309 if(offered_suite(static_cast<uint16_t>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
310 {
311 if(Renegotiation_Extension* reneg = m_extensions.get<Renegotiation_Extension>())
312 {
313 if(!reneg->renegotiation_info().empty())
315 "Client sent renegotiation SCSV and non-empty extension");
316 }
317 else
318 {
319 // add fake extension
320 m_extensions.add(new Renegotiation_Extension());
321 }
322 }
323 }
324
326 {
327 return offered_suite(static_cast<uint16_t>(TLS_FALLBACK_SCSV));
328 }
329
330/*
331* Check if we offered this ciphersuite
332*/
333bool Client_Hello::offered_suite(uint16_t ciphersuite) const
334 {
335 for(size_t i = 0; i != m_suites.size(); ++i)
336 if(m_suites[i] == ciphersuite)
337 return true;
338 return false;
339 }
340
341std::vector<Signature_Scheme> Client_Hello::signature_schemes() const
342 {
343 std::vector<Signature_Scheme> schemes;
344
345 if(Signature_Algorithms* sigs = m_extensions.get<Signature_Algorithms>())
346 {
347 schemes = sigs->supported_schemes();
348 }
349
350 return schemes;
351 }
352
353std::vector<Group_Params> Client_Hello::supported_ecc_curves() const
354 {
355 if(Supported_Groups* groups = m_extensions.get<Supported_Groups>())
356 return groups->ec_groups();
357 return std::vector<Group_Params>();
358 }
359
360std::vector<Group_Params> Client_Hello::supported_dh_groups() const
361 {
362 if(Supported_Groups* groups = m_extensions.get<Supported_Groups>())
363 return groups->dh_groups();
364 return std::vector<Group_Params>();
365 }
366
368 {
369 if(Supported_Point_Formats* ecc_formats = m_extensions.get<Supported_Point_Formats>())
370 {
371 return ecc_formats->prefers_compressed();
372 }
373 return false;
374 }
375
376std::string Client_Hello::sni_hostname() const
377 {
378 if(Server_Name_Indicator* sni = m_extensions.get<Server_Name_Indicator>())
379 return sni->host_name();
380 return "";
381 }
382
383#if defined(BOTAN_HAS_SRP6)
384std::string Client_Hello::srp_identifier() const
385 {
386 if(SRP_Identifier* srp = m_extensions.get<SRP_Identifier>())
387 return srp->identifier();
388 return "";
389 }
390#endif
391
393 {
394 return m_extensions.has<Renegotiation_Extension>();
395 }
396
397std::vector<uint8_t> Client_Hello::renegotiation_info() const
398 {
399 if(Renegotiation_Extension* reneg = m_extensions.get<Renegotiation_Extension>())
400 return reneg->renegotiation_info();
401 return std::vector<uint8_t>();
402 }
403
404std::vector<Protocol_Version> Client_Hello::supported_versions() const
405 {
406 if(Supported_Versions* versions = m_extensions.get<Supported_Versions>())
407 return versions->versions();
408 return {};
409 }
410
412 {
413 return m_extensions.has<Session_Ticket>();
414 }
415
416std::vector<uint8_t> Client_Hello::session_ticket() const
417 {
418 if(Session_Ticket* ticket = m_extensions.get<Session_Ticket>())
419 return ticket->contents();
420 return std::vector<uint8_t>();
421 }
422
424 {
425 return m_extensions.has<Application_Layer_Protocol_Notification>();
426 }
427
429 {
430 return m_extensions.has<Extended_Master_Secret>();
431 }
432
434 {
435 return m_extensions.has<Certificate_Status_Request>();
436 }
437
439 {
440 return m_extensions.has<Encrypt_then_MAC>();
441 }
442
444 {
445 return m_extensions.has<Signature_Algorithms>();
446 }
447
448std::vector<std::string> Client_Hello::next_protocols() const
449 {
450 if(auto alpn = m_extensions.get<Application_Layer_Protocol_Notification>())
451 return alpn->protocols();
452 return std::vector<std::string>();
453 }
454
455std::vector<uint16_t> Client_Hello::srtp_profiles() const
456 {
457 if(SRTP_Protection_Profiles* srtp = m_extensions.get<SRTP_Protection_Profiles>())
458 return srtp->profiles();
459 return std::vector<uint16_t>();
460 }
461
462
463}
464
465}
static std::unique_ptr< HashFunction > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: hash.cpp:344
virtual void randomize(uint8_t output[], size_t length)=0
virtual void tls_modify_extensions(Extensions &extn, Connection_Side which_side)
const std::string & srp_identifier() const
Definition: tls_messages.h:85
const Protocol_Version protocol_version() const
Definition: tls_messages.h:83
const std::string & hostname() const
Definition: tls_messages.h:84
std::string sni_hostname() const
std::vector< Signature_Scheme > signature_schemes() const
Client_Hello(Handshake_IO &io, Handshake_Hash &hash, const Policy &policy, Callbacks &cb, RandomNumberGenerator &rng, const std::vector< uint8_t > &reneg_info, const Client_Hello::Settings &client_settings, const std::vector< std::string > &next_protocols)
bool offered_suite(uint16_t ciphersuite) const
bool sent_signature_algorithms() const
std::vector< Group_Params > supported_ecc_curves() const
std::vector< uint8_t > cookie_input_data() const
bool supports_cert_status_message() const
std::vector< Group_Params > supported_dh_groups() const
std::vector< uint8_t > session_ticket() const
std::vector< std::string > next_protocols() const
void update_hello_cookie(const Hello_Verify_Request &hello_verify)
std::vector< uint8_t > renegotiation_info() const
bool supports_extended_master_secret() const
bool supports_encrypt_then_mac() const
std::vector< uint16_t > srtp_profiles() const
bool prefers_compressed_ec_points() const
std::vector< Protocol_Version > supported_versions() const
void add(Extension *extn)
std::vector< uint8_t > serialize(Connection_Side whoami) const
void deserialize(TLS_Data_Reader &reader, Connection_Side from)
virtual std::vector< uint8_t > send(const Handshake_Message &msg)=0
Hello_Request(Handshake_IO &io)
const std::vector< uint8_t > & cookie() const
Definition: tls_messages.h:56
virtual bool include_time_in_hello_random() const
Definition: tls_policy.cpp:340
virtual std::vector< Signature_Scheme > allowed_signature_schemes() const
Definition: tls_policy.cpp:22
virtual std::vector< Group_Params > key_exchange_groups() const
Definition: tls_policy.cpp:162
virtual bool negotiate_encrypt_then_mac() const
Definition: tls_policy.cpp:343
virtual bool acceptable_protocol_version(Protocol_Version version) const
Definition: tls_policy.cpp:278
virtual std::vector< uint16_t > srtp_profiles() const
Definition: tls_policy.cpp:364
virtual bool support_cert_status_message() const
Definition: tls_policy.cpp:344
virtual bool use_ecc_point_compression() const
Definition: tls_policy.cpp:127
virtual bool send_fallback_scsv(Protocol_Version version) const
Definition: tls_policy.cpp:273
bool supports_negotiable_signature_algorithms() const
Definition: tls_version.cpp:60
std::string to_string() const
Definition: tls_version.cpp:15
uint8_t major_version() const
Definition: tls_version.h:79
uint8_t minor_version() const
Definition: tls_version.h:84
std::string hostname() const
const Server_Information & server_info() const
Definition: tls_session.h:183
bool supports_encrypt_then_mac() const
Definition: tls_session.h:158
const std::vector< uint8_t > & session_ticket() const
Definition: tls_session.h:178
uint16_t ciphersuite_code() const
Definition: tls_session.h:123
const std::string & srp_identifier() const
Definition: tls_session.h:139
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:94
std::vector< T > get_fixed(size_t size)
Definition: tls_reader.h:126
std::vector< T > get_range_vector(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:105
void append_tls_length_value(std::vector< uint8_t, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
Definition: tls_reader.h:185
std::vector< uint8_t > make_hello_random(RandomNumberGenerator &rng, const Policy &policy)
@ TLS_EMPTY_RENEGOTIATION_INFO_SCSV
Definition: alg_id.cpp:13
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:438
bool value_exists(const std::vector< T > &vec, const T &val)
Definition: stl_util.h:86
MechanismType hash