Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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 {
24 TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
25 TLS_FALLBACK_SCSV = 0x5600
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 */
48 Hello_Request::Hello_Request(Handshake_IO& io)
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 */
73 Client_Hello::Client_Hello(Handshake_IO& io,
74 Handshake_Hash& hash,
75 const Policy& policy,
76 RandomNumberGenerator& rng,
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 {
85 BOTAN_ASSERT(policy.acceptable_protocol_version(client_settings.protocol_version()),
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
107 if(m_version.supports_negotiable_signature_algorithms())
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
130 if(m_version.supports_negotiable_signature_algorithms())
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 */
143 Client_Hello::Client_Hello(Handshake_IO& io,
144 Handshake_Hash& hash,
145 const Policy& policy,
146 RandomNumberGenerator& rng,
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
192 if(m_version.supports_negotiable_signature_algorithms())
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
202 void Client_Hello::update_hello_cookie(const Hello_Verify_Request& hello_verify)
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())
273 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
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>())
288 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
289 "Client sent signature_algorithms extension in version that doesn't support it");
290 }
291 }
292
293 bool Client_Hello::sent_fallback_scsv() const
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 }
Botan::TLS::Client_Hello::Client_Hello
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)
Definition: msg_client_hello.cpp:73
Botan::TLS::Extensions::serialize
std::vector< uint8_t > serialize() const
Definition: tls_extensions.cpp:93
Botan::TLS::TLS_Data_Reader::get_fixed
std::vector< T > get_fixed(size_t size)
Definition: tls_reader.h:126
Botan::TLS::Handshake_IO::send
virtual std::vector< uint8_t > send(const Handshake_Message &msg)=0
Botan::TLS::Protocol_Version::minor_version
uint8_t minor_version() const
Definition: tls_version.h:82
Botan::TLS::Session
Definition: tls_session.h:27
Botan::TLS::Session::ciphersuite_code
uint16_t ciphersuite_code() const
Definition: tls_session.h:125
Botan::TLS::Policy::allowed_ecc_curves
virtual std::vector< std::string > allowed_ecc_curves() const
Definition: tls_policy.cpp:96
Botan::Exception
Definition: exceptn.h:21
Botan::TLS::Hello_Verify_Request
Definition: tls_messages.h:47
Botan::TLS::Session::compression_method
uint8_t compression_method() const
Definition: tls_session.h:135
Botan::TLS::Encrypt_then_MAC
Definition: tls_extensions.h:380
Botan::RandomNumberGenerator
Definition: rng.h:25
Botan::store_be
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:441
Botan::RandomNumberGenerator::randomize
virtual void randomize(uint8_t output[], size_t length)=0
Botan::TLS::Extensions::has
bool has() const
Definition: tls_extensions.h:448
Botan::TLS::Policy::send_fallback_scsv
virtual bool send_fallback_scsv(Protocol_Version version) const
Definition: tls_policy.cpp:236
Botan::TLS::Policy::srtp_profiles
virtual std::vector< uint16_t > srtp_profiles() const
Definition: tls_policy.cpp:291
Botan::TLS::Policy::allowed_signature_methods
virtual std::vector< std::string > allowed_signature_methods() const
Definition: tls_policy.cpp:81
Botan::TLS::Extensions::add
void add(Extension *extn)
Definition: tls_extensions.h:453
Botan::TLS::Renegotiation_Extension
Definition: tls_extensions.h:128
Botan::TLS::Client_Hello::update_hello_cookie
void update_hello_cookie(const Hello_Verify_Request &hello_verify)
Definition: msg_client_hello.cpp:202
Botan::TLS::Session::server_info
const Server_Information & server_info() const
Definition: tls_session.h:190
Botan::Invalid_State
Definition: exceptn.h:61
Botan::TLS::Application_Layer_Protocol_Notification
Definition: tls_extensions.h:157
Botan::TLS::Handshake_Hash
Definition: tls_handshake_hash.h:22
Botan::TLS::Session_Ticket
Definition: tls_extensions.h:193
Botan::TLS::Protocol_Version
Definition: tls_version.h:21
Botan::TLS::Session::session_ticket
const std::vector< uint8_t > & session_ticket() const
Definition: tls_session.h:185
Botan::TLS::Server_Information::hostname
std::string hostname() const
Definition: tls_server_info.h:53
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
Botan::TLS::Supported_Point_Formats
Definition: tls_extensions.h:261
Botan::TLS::Client_Hello::Settings
Definition: tls_messages.h:70
Botan::TLS::SRTP_Protection_Profiles
Definition: tls_extensions.h:334
Botan::TLS::Alert::HANDSHAKE_FAILURE
Definition: tls_alert.h:34
Botan::TLS::Extensions::get
T * get() const
Definition: tls_extensions.h:436
Botan::TLS::TLS_Data_Reader::get_byte
uint8_t get_byte()
Definition: tls_reader.h:70
Botan::TLS::Hello_Request::Hello_Request
Hello_Request(Handshake_IO &io)
Definition: msg_client_hello.cpp:48
Botan::TLS::Extended_Master_Secret
Definition: tls_extensions.h:360
Botan::TLS::TLS_FALLBACK_SCSV
Definition: msg_client_hello.cpp:25
Botan::TLS::TLS_Data_Reader::get_range_vector
std::vector< T > get_range_vector(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:105
Botan::TLS::TLS_Data_Reader::get_range
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:94
Botan::TLS::Handshake_Hash::update
void update(const uint8_t in[], size_t length)
Definition: tls_handshake_hash.h:25
Botan::TLS::Protocol_Version::major_version
uint8_t major_version() const
Definition: tls_version.h:77
Botan::TLS::Hello_Verify_Request::cookie
std::vector< uint8_t > cookie() const
Definition: tls_messages.h:53
Botan::TLS::Policy::allowed_signature_hashes
virtual std::vector< std::string > allowed_signature_hashes() const
Definition: tls_policy.cpp:42
Botan::Decoding_Error
Definition: exceptn.h:189
Botan::TLS::Policy::acceptable_protocol_version
virtual bool acceptable_protocol_version(Protocol_Version version) const
Definition: tls_policy.cpp:241
Botan::TLS::Handshake_IO
Definition: tls_handshake_io.h:30
Botan
Definition: alg_id.cpp:13
Botan::TLS::make_hello_random
std::vector< uint8_t > make_hello_random(RandomNumberGenerator &rng, const Policy &policy)
Definition: msg_client_hello.cpp:28
Botan::TLS::Policy::use_ecc_point_compression
virtual bool use_ecc_point_compression() const
Definition: tls_policy.cpp:116
Botan::TLS::Server_Name_Indicator
Definition: tls_extensions.h:74
Botan::TLS::Policy
Definition: tls_policy.h:26
Botan::TLS::TLS_Data_Reader
Definition: tls_reader.h:24
Botan::TLS::Client_Hello::offered_suite
bool offered_suite(uint16_t ciphersuite) const
Definition: msg_client_hello.cpp:301
Botan::value_exists
bool value_exists(const std::vector< T > &vec, const T &val)
Definition: stl_util.h:86
Botan::TLS::Session::srp_identifier
const std::string & srp_identifier() const
Definition: tls_session.h:146
Botan::TLS::Client_Hello::Settings::protocol_version
const Protocol_Version protocol_version() const
Definition: tls_messages.h:80
Botan::TLS::Supported_Elliptic_Curves
Definition: tls_extensions.h:232
Botan::TLS::Signature_Algorithms
Definition: tls_extensions.h:294
Botan::TLS::Certificate_Status_Request
Definition: tls_extensions.h:400
Botan::TLS::Client_Hello::sent_fallback_scsv
bool sent_fallback_scsv() const
Definition: msg_client_hello.cpp:293
Botan::TLS::Session::supports_encrypt_then_mac
bool supports_encrypt_then_mac() const
Definition: tls_session.h:165
Botan::TLS::Protocol_Version::supports_negotiable_signature_algorithms
bool supports_negotiable_signature_algorithms() const
Definition: tls_version.cpp:61
Botan::TLS::Extensions::deserialize
void deserialize(TLS_Data_Reader &reader)
Definition: tls_extensions.cpp:67
Botan::TLS::Policy::include_time_in_hello_random
virtual bool include_time_in_hello_random() const
Definition: tls_policy.cpp:276
Botan::TLS::TLS_EMPTY_RENEGOTIATION_INFO_SCSV
Definition: msg_client_hello.cpp:24
Botan::TLS::Protocol_Version::is_datagram_protocol
bool is_datagram_protocol() const
Definition: tls_version.cpp:34
hash
MechanismType hash
Definition: p11_mechanism.cpp:63
Botan::TLS::TLS_Exception
Definition: tls_exceptn.h:21
Botan::TLS::Client_Hello::Settings::srp_identifier
const std::string & srp_identifier() const
Definition: tls_messages.h:82
Botan::TLS::Policy::negotiate_encrypt_then_mac
virtual bool negotiate_encrypt_then_mac() const
Definition: tls_policy.cpp:279
Botan::TLS::Client_Hello::Settings::hostname
const std::string & hostname() const
Definition: tls_messages.h:81
Botan::TLS::append_tls_length_value
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