Botan  2.1.0
Crypto and TLS for C++11
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 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/tls_messages.h>
10 #include <botan/tls_alert.h>
11 #include <botan/tls_exceptn.h>
12 #include <botan/internal/tls_reader.h>
13 #include <botan/internal/tls_session_key.h>
14 #include <botan/internal/tls_handshake_io.h>
15 #include <botan/internal/tls_handshake_hash.h>
16 #include <botan/internal/stl_util.h>
17 #include <chrono>
18 
19 namespace Botan {
20 
21 namespace TLS {
22 
23 enum {
26 };
27 
28 std::vector<uint8_t> make_hello_random(RandomNumberGenerator& rng,
29  const Policy& policy)
30  {
31  std::vector<uint8_t> buf(32);
32  rng.randomize(buf.data(), buf.size());
33 
34  if(policy.include_time_in_hello_random())
35  {
36  const uint32_t time32 = static_cast<uint32_t>(
37  std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
38 
39  store_be(time32, buf.data());
40  }
41 
42  return buf;
43  }
44 
45 /*
46 * Create a new Hello Request message
47 */
49  {
50  io.send(*this);
51  }
52 
53 /*
54 * Deserialize a Hello Request message
55 */
56 Hello_Request::Hello_Request(const std::vector<uint8_t>& buf)
57  {
58  if(buf.size())
59  throw Decoding_Error("Bad Hello_Request, has non-zero size");
60  }
61 
62 /*
63 * Serialize a Hello Request message
64 */
65 std::vector<uint8_t> Hello_Request::serialize() const
66  {
67  return std::vector<uint8_t>();
68  }
69 
70 /*
71 * Create a new Client Hello message
72 */
75  const Policy& policy,
77  const std::vector<uint8_t>& reneg_info,
78  const Client_Hello::Settings& client_settings,
79  const std::vector<std::string>& next_protocols) :
80  m_version(client_settings.protocol_version()),
81  m_random(make_hello_random(rng, policy)),
82  m_suites(policy.ciphersuite_list(m_version, !client_settings.srp_identifier().empty())),
83  m_comp_methods(policy.compression())
84  {
86  "Our policy accepts the version we are offering");
87 
88  /*
89  * Place all empty extensions in front to avoid a bug in some systems
90  * which reject hellos when the last extension in the list is empty.
91  */
92  m_extensions.add(new Extended_Master_Secret);
93  m_extensions.add(new Session_Ticket());
94  m_extensions.add(new Certificate_Status_Request);
95 
96  if(policy.negotiate_encrypt_then_mac())
97  m_extensions.add(new Encrypt_then_MAC);
98 
99  m_extensions.add(new Renegotiation_Extension(reneg_info));
100  m_extensions.add(new Server_Name_Indicator(client_settings.hostname()));
101 
102  m_extensions.add(new Certificate_Status_Request({}, {}));
103 
104  if(reneg_info.empty() && !next_protocols.empty())
105  m_extensions.add(new Application_Layer_Protocol_Notification(next_protocols));
106 
108  m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(),
109  policy.allowed_signature_methods()));
110 
111  if(m_version.is_datagram_protocol())
112  m_extensions.add(new SRTP_Protection_Profiles(policy.srtp_profiles()));
113 
114 #if defined(BOTAN_HAS_SRP6)
115  m_extensions.add(new SRP_Identifier(client_settings.srp_identifier()));
116 #else
117  if(!client_settings.srp_identifier().empty())
118  {
119  throw Invalid_State("Attempting to initiate SRP session but TLS-SRP support disabled");
120  }
121 #endif
122 
123  m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves()));
124 
125  if(!policy.allowed_ecc_curves().empty())
126  {
127  m_extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
128  }
129 
131  m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(),
132  policy.allowed_signature_methods()));
133 
134  if(policy.send_fallback_scsv(client_settings.protocol_version()))
135  m_suites.push_back(TLS_FALLBACK_SCSV);
136 
137  hash.update(io.send(*this));
138  }
139 
140 /*
141 * Create a new Client Hello message (session resumption case)
142 */
145  const Policy& policy,
147  const std::vector<uint8_t>& reneg_info,
148  const Session& session,
149  const std::vector<std::string>& next_protocols) :
150  m_version(session.version()),
151  m_session_id(session.session_id()),
152  m_random(make_hello_random(rng, policy)),
153  m_suites(policy.ciphersuite_list(m_version, (session.srp_identifier() != ""))),
154  m_comp_methods(policy.compression())
155  {
156  if(!value_exists(m_suites, session.ciphersuite_code()))
157  m_suites.push_back(session.ciphersuite_code());
158 
159  if(!value_exists(m_comp_methods, session.compression_method()))
160  m_comp_methods.push_back(session.compression_method());
161 
162  /*
163  We always add the EMS extension, even if not used in the original session.
164  If the server understands it and follows the RFC it should reject our resume
165  attempt and upgrade us to a new session with the EMS protection.
166  */
167  m_extensions.add(new Extended_Master_Secret);
168  m_extensions.add(new Certificate_Status_Request);
169 
170  m_extensions.add(new Renegotiation_Extension(reneg_info));
171  m_extensions.add(new Server_Name_Indicator(session.server_info().hostname()));
172  m_extensions.add(new Session_Ticket(session.session_ticket()));
173  m_extensions.add(new Supported_Elliptic_Curves(policy.allowed_ecc_curves()));
174 
175  if(!policy.allowed_ecc_curves().empty())
176  {
177  m_extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
178  }
179 
180  if(session.supports_encrypt_then_mac())
181  m_extensions.add(new Encrypt_then_MAC);
182 
183 #if defined(BOTAN_HAS_SRP6)
184  m_extensions.add(new SRP_Identifier(session.srp_identifier()));
185 #else
186  if(!session.srp_identifier().empty())
187  {
188  throw Invalid_State("Attempting to resume SRP session but TLS-SRP support disabled");
189  }
190 #endif
191 
193  m_extensions.add(new Signature_Algorithms(policy.allowed_signature_hashes(),
194  policy.allowed_signature_methods()));
195 
196  if(reneg_info.empty() && !next_protocols.empty())
197  m_extensions.add(new Application_Layer_Protocol_Notification(next_protocols));
198 
199  hash.update(io.send(*this));
200  }
201 
203  {
204  if(!m_version.is_datagram_protocol())
205  throw Exception("Cannot use hello cookie with stream protocol");
206 
207  m_hello_cookie = hello_verify.cookie();
208  }
209 
210 /*
211 * Serialize a Client Hello message
212 */
213 std::vector<uint8_t> Client_Hello::serialize() const
214  {
215  std::vector<uint8_t> buf;
216 
217  buf.push_back(m_version.major_version());
218  buf.push_back(m_version.minor_version());
219  buf += m_random;
220 
221  append_tls_length_value(buf, m_session_id, 1);
222 
223  if(m_version.is_datagram_protocol())
224  append_tls_length_value(buf, m_hello_cookie, 1);
225 
226  append_tls_length_value(buf, m_suites, 2);
227  append_tls_length_value(buf, m_comp_methods, 1);
228 
229  /*
230  * May not want to send extensions at all in some cases. If so,
231  * should include SCSV value (if reneg info is empty, if not we are
232  * renegotiating with a modern server)
233  */
234 
235  buf += m_extensions.serialize();
236 
237  return buf;
238  }
239 
240 /*
241 * Read a counterparty client hello
242 */
243 Client_Hello::Client_Hello(const std::vector<uint8_t>& buf)
244  {
245  if(buf.size() < 41)
246  throw Decoding_Error("Client_Hello: Packet corrupted");
247 
248  TLS_Data_Reader reader("ClientHello", buf);
249 
250  const uint8_t major_version = reader.get_byte();
251  const uint8_t minor_version = reader.get_byte();
252 
253  m_version = Protocol_Version(major_version, minor_version);
254 
255  m_random = reader.get_fixed<uint8_t>(32);
256 
257  m_session_id = reader.get_range<uint8_t>(1, 0, 32);
258 
259  if(m_version.is_datagram_protocol())
260  m_hello_cookie = reader.get_range<uint8_t>(1, 0, 255);
261 
262  m_suites = reader.get_range_vector<uint16_t>(2, 1, 32767);
263 
264  m_comp_methods = reader.get_range_vector<uint8_t>(1, 1, 255);
265 
266  m_extensions.deserialize(reader);
267 
268  if(offered_suite(static_cast<uint16_t>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
269  {
270  if(Renegotiation_Extension* reneg = m_extensions.get<Renegotiation_Extension>())
271  {
272  if(!reneg->renegotiation_info().empty())
274  "Client sent renegotiation SCSV and non-empty extension");
275  }
276  else
277  {
278  // add fake extension
279  m_extensions.add(new Renegotiation_Extension());
280  }
281  }
282 
283  // Parsing complete, now any additional decoding checks
284 
285  if(m_version.supports_negotiable_signature_algorithms() == false)
286  {
287  if(m_extensions.has<Signature_Algorithms>())
289  "Client sent signature_algorithms extension in version that doesn't support it");
290  }
291  }
292 
294  {
295  return offered_suite(static_cast<uint16_t>(TLS_FALLBACK_SCSV));
296  }
297 
298 /*
299 * Check if we offered this ciphersuite
300 */
301 bool Client_Hello::offered_suite(uint16_t ciphersuite) const
302  {
303  for(size_t i = 0; i != m_suites.size(); ++i)
304  if(m_suites[i] == ciphersuite)
305  return true;
306  return false;
307  }
308 
309 }
310 
311 }
Client_Hello(Handshake_IO &io, Handshake_Hash &hash, const Policy &policy, RandomNumberGenerator &rng, const std::vector< uint8_t > &reneg_info, const Client_Hello::Settings &client_settings, const std::vector< std::string > &next_protocols)
std::vector< uint8_t > serialize() const
std::vector< T > get_fixed(size_t size)
Definition: tls_reader.h:126
virtual std::vector< uint8_t > send(const Handshake_Message &msg)=0
uint8_t minor_version() const
Definition: tls_version.h:82
uint16_t ciphersuite_code() const
Definition: tls_session.h:125
virtual std::vector< std::string > allowed_ecc_curves() const
Definition: tls_policy.cpp:96
uint8_t compression_method() const
Definition: tls_session.h:135
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:441
virtual void randomize(uint8_t output[], size_t length)=0
virtual bool send_fallback_scsv(Protocol_Version version) const
Definition: tls_policy.cpp:236
virtual std::vector< uint16_t > srtp_profiles() const
Definition: tls_policy.cpp:291
virtual std::vector< std::string > allowed_signature_methods() const
Definition: tls_policy.cpp:81
void add(Extension *extn)
void update_hello_cookie(const Hello_Verify_Request &hello_verify)
const Server_Information & server_info() const
Definition: tls_session.h:190
const std::vector< uint8_t > & session_ticket() const
Definition: tls_session.h:185
std::string hostname() const
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
Hello_Request(Handshake_IO &io)
std::vector< T > get_range_vector(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:105
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:94
void update(const uint8_t in[], size_t length)
uint8_t major_version() const
Definition: tls_version.h:77
std::vector< uint8_t > cookie() const
Definition: tls_messages.h:53
virtual std::vector< std::string > allowed_signature_hashes() const
Definition: tls_policy.cpp:42
virtual bool acceptable_protocol_version(Protocol_Version version) const
Definition: tls_policy.cpp:241
Definition: alg_id.cpp:13
std::vector< uint8_t > make_hello_random(RandomNumberGenerator &rng, const Policy &policy)
virtual bool use_ecc_point_compression() const
Definition: tls_policy.cpp:116
bool offered_suite(uint16_t ciphersuite) const
bool value_exists(const std::vector< T > &vec, const T &val)
Definition: stl_util.h:86
const std::string & srp_identifier() const
Definition: tls_session.h:146
const Protocol_Version protocol_version() const
Definition: tls_messages.h:80
bool supports_encrypt_then_mac() const
Definition: tls_session.h:165
bool supports_negotiable_signature_algorithms() const
Definition: tls_version.cpp:61
void deserialize(TLS_Data_Reader &reader)
virtual bool include_time_in_hello_random() const
Definition: tls_policy.cpp:276
bool is_datagram_protocol() const
Definition: tls_version.cpp:34
MechanismType hash
const std::string & srp_identifier() const
Definition: tls_messages.h:82
virtual bool negotiate_encrypt_then_mac() const
Definition: tls_policy.cpp:279
const std::string & hostname() const
Definition: tls_messages.h:81
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