Botan 3.0.0-alpha0
Crypto and TLS for C&
tls_handshake_state.cpp
Go to the documentation of this file.
1/*
2* TLS Handshaking
3* (C) 2004-2006,2011,2012,2015,2016 Jack Lloyd
4* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/internal/tls_handshake_state.h>
10#include <botan/internal/tls_record.h>
11#include <botan/tls_messages.h>
12#include <botan/tls_signature_scheme.h>
13#include <botan/kdf.h>
14#include <sstream>
15
16namespace Botan::TLS {
17
19 {
21 }
22
24 {
25 switch(type)
26 {
28 return "hello_verify_request";
29
30 case HELLO_REQUEST:
31 return "hello_request";
32
33 case CLIENT_HELLO:
34 return "client_hello";
35
36 case SERVER_HELLO:
37 return "server_hello";
38
40 return "hello_retry_request";
41
42 case CERTIFICATE:
43 return "certificate";
44
45 case CERTIFICATE_URL:
46 return "certificate_url";
47
49 return "certificate_status";
50
51 case SERVER_KEX:
52 return "server_key_exchange";
53
55 return "certificate_request";
56
58 return "server_hello_done";
59
61 return "certificate_verify";
62
63 case CLIENT_KEX:
64 return "client_key_exchange";
65
67 return "new_session_ticket";
68
69 case HANDSHAKE_CCS:
70 return "change_cipher_spec";
71
72 case FINISHED:
73 return "finished";
74
76 return "end_of_early_data";
77
79 return "encrypted_extensions";
80
81 case KEY_UPDATE:
82 return "key_update";
83
84 case HANDSHAKE_NONE:
85 return "invalid";
86 }
87
89 "Unknown TLS handshake message type " + std::to_string(type));
90 }
91
92
93/*
94* Initialize the SSL/TLS Handshake State
95*/
97
98Handshake_State::Handshake_State(std::unique_ptr<Handshake_IO> io, Callbacks& cb) :
99 m_callbacks(cb),
100 m_handshake_io(std::move(io)),
101 m_version(m_handshake_io->initial_record_version())
102 {
103 }
104
106 {
107 m_callbacks.tls_inspect_handshake_msg(msg);
108 }
109
111 {
112 note_message(hello_verify);
113
114 m_client_hello->update_hello_cookie(hello_verify);
115 hash().reset();
116 hash().update(handshake_io().send(*m_client_hello));
117 note_message(*m_client_hello);
118 }
119
121 {
122 if(client_hello == nullptr)
123 {
124 m_client_hello.reset();
125 hash().reset();
126 }
127 else
128 {
129 m_client_hello.reset(client_hello);
130 note_message(*m_client_hello);
131 }
132 }
133
135 {
136 m_server_hello.reset(server_hello);
137 m_ciphersuite = Ciphersuite::by_id(m_server_hello->ciphersuite());
138 note_message(*m_server_hello);
139 }
140
142 {
143 m_server_certs.reset(server_certs);
144 note_message(*m_server_certs);
145 }
146
148 {
149 m_server_cert_status.reset(server_cert_status);
150 note_message(*m_server_cert_status);
151 }
152
154 {
155 m_server_kex.reset(server_kex);
156 note_message(*m_server_kex);
157 }
158
160 {
161 m_cert_req.reset(cert_req);
162 note_message(*m_cert_req);
163 }
164
166 {
167 m_server_hello_done.reset(server_hello_done);
168 note_message(*m_server_hello_done);
169 }
170
172 {
173 m_client_certs.reset(client_certs);
174 note_message(*m_client_certs);
175 }
176
178 {
179 m_client_kex.reset(client_kex);
180 note_message(*m_client_kex);
181 }
182
184 {
185 m_client_verify.reset(client_verify);
186 note_message(*m_client_verify);
187 }
188
190 {
191 m_server_verify.reset(server_verify);
192 note_message(*m_server_verify);
193 }
194
196 {
197 m_new_session_ticket.reset(new_session_ticket);
198 note_message(*m_new_session_ticket);
199 }
200
202 {
203 m_server_finished.reset(server_finished);
204 note_message(*m_server_finished);
205 }
206
208 {
209 m_client_finished.reset(client_finished);
210 note_message(*m_client_finished);
211 }
212
214 {
215 if(!m_ciphersuite.has_value())
216 {
217 throw Invalid_State("Cipher suite is not set");
218 }
219 return m_ciphersuite.value();
220 }
221
223 {
224 m_version = version;
225 }
226
228 {
229 m_session_keys = Session_Keys(this, client_kex()->pre_master_secret(), false);
230 }
231
233 {
234 m_session_keys = Session_Keys(this, resume_master_secret, true);
235 }
236
238 {
239 m_transitions.confirm_transition_to(handshake_msg);
240 }
241
243 {
244 m_transitions.set_expected_next(handshake_msg);
245 }
246
248 {
249 return m_transitions.received_handshake_msg(handshake_msg);
250 }
251
252std::pair<Handshake_Type, std::vector<uint8_t>>
254 {
255 return m_handshake_io->get_next_record(m_transitions.change_cipher_spec_expected());
256 }
257
258std::vector<uint8_t> Handshake_State::session_ticket() const
259 {
260 if(new_session_ticket() && !new_session_ticket()->ticket().empty())
261 { return new_session_ticket()->ticket(); }
262
263 return client_hello()->session_ticket();
264 }
265
266std::unique_ptr<KDF> Handshake_State::protocol_specific_prf() const
267 {
268 const std::string prf_algo = ciphersuite().prf_algo();
269
270 if(prf_algo == "MD5" || prf_algo == "SHA-1")
271 { return KDF::create_or_throw("TLS-12-PRF(SHA-256)"); }
272
273 return KDF::create_or_throw("TLS-12-PRF(" + prf_algo + ")");
274 }
275
276std::pair<std::string, Signature_Format>
278 Signature_Scheme& chosen_scheme,
279 bool for_client_auth,
280 const Policy& policy) const
281 {
282 const std::string sig_algo = key.algo_name();
283
284 const std::vector<Signature_Scheme> allowed = policy.allowed_signature_schemes();
285
286 std::vector<Signature_Scheme> requested =
287 (for_client_auth) ? cert_req()->signature_schemes() : client_hello()->signature_schemes();
288
289 for(Signature_Scheme scheme : allowed)
290 {
291 if(!scheme.is_available())
292 {
293 continue;
294 }
295
296 if(scheme.algorithm_name() == sig_algo)
297 {
298 if(std::find(requested.begin(), requested.end(), scheme) != requested.end())
299 {
300 chosen_scheme = scheme;
301 break;
302 }
303 }
304 }
305
306 const std::string hash = chosen_scheme.hash_function_name();
307
308 if(!policy.allowed_signature_hash(hash))
309 {
311 "Policy refuses to accept signing with any hash supported by peer");
312 }
313
314 if(!chosen_scheme.format().has_value())
315 { throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures"); }
316
317 return std::make_pair(chosen_scheme.padding_string(), chosen_scheme.format().value());
318 }
319
320namespace {
321
322bool supported_algos_include(
323 const std::vector<Signature_Scheme>& schemes,
324 const std::string& key_type,
325 const std::string& hash_type)
326 {
327 for(Signature_Scheme scheme : schemes)
328 {
329 if(scheme.is_available() &&
330 hash_type == scheme.hash_function_name() &&
331 key_type == scheme.algorithm_name())
332 {
333 return true;
334 }
335 }
336
337 return false;
338 }
339
340}
341
342std::pair<std::string, Signature_Format>
344 Signature_Scheme scheme,
345 const std::vector<Signature_Scheme>& offered_schemes,
346 bool for_client_auth,
347 const Policy& policy) const
348 {
349 const std::string key_type = key.algo_name();
350
351 if(!policy.allowed_signature_method(key_type))
352 {
354 "Rejecting " + key_type + " signature");
355 }
356
357 if(!scheme.is_available())
358 {
360 "Peer sent unknown signature scheme");
361 }
362
363 if(key_type != scheme.algorithm_name())
364 { throw Decoding_Error("Counterparty sent inconsistent key and sig types"); }
365
366 if(for_client_auth && !cert_req())
367 {
369 "No certificate verify set");
370 }
371
372 /*
373 Confirm the signature type we just received against the
374 supported_algos list that we sent; it better be there.
375 */
376
377 const std::vector<Signature_Scheme> supported_algos =
378 for_client_auth ? cert_req()->signature_schemes() :
379 offered_schemes;
380
381 const std::string hash_algo = scheme.hash_function_name();
382
384 { throw TLS_Exception(Alert::ILLEGAL_PARAMETER, "Peer sent unexceptable signature scheme"); }
385
386 if(!supported_algos_include(supported_algos, key_type, hash_algo))
387 {
389 "TLS signature extension did not allow for " +
390 key_type + "/" + hash_algo + " signature");
391 }
392
393 if(!scheme.format().has_value())
394 { throw Invalid_Argument(key_type + " is invalid/unknown for TLS signatures"); }
395
396 return std::make_pair(scheme.padding_string(), scheme.format().value());
397 }
398
399}
static std::unique_ptr< KDF > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: kdf.cpp:212
virtual std::string algo_name() const =0
virtual void tls_inspect_handshake_msg(const Handshake_Message &message)
const std::vector< Signature_Scheme > & signature_schemes() const
static std::optional< Ciphersuite > by_id(uint16_t suite)
std::string prf_algo() const
std::vector< uint8_t > session_ticket() const
std::vector< Signature_Scheme > signature_schemes() const
void update(const uint8_t in[], size_t length)
virtual Handshake_Type type() const =0
std::pair< std::string, Signature_Format > parse_sig_format(const Public_Key &key, Signature_Scheme scheme, const std::vector< Signature_Scheme > &offered_schemes, bool for_client_auth, const Policy &policy) const
std::pair< Handshake_Type, std::vector< uint8_t > > get_next_handshake_msg()
const Server_Hello_Done * server_hello_done() const
void hello_verify_request(const Hello_Verify_Request &hello_verify)
void set_expected_next(Handshake_Type msg_type)
void note_message(const Handshake_Message &msg)
const Server_Key_Exchange * server_kex() const
const Certificate_Status * server_cert_status() const
const Certificate_Verify_12 * server_verify() const
Handshake_State(std::unique_ptr< Handshake_IO > io, Callbacks &callbacks)
const Certificate_Verify_12 * client_verify() const
const Finished_12 * server_finished() const
std::vector< uint8_t > session_ticket() const
const Client_Hello_12 * client_hello() const
const Client_Key_Exchange * client_kex() const
void confirm_transition_to(Handshake_Type msg_type)
void set_version(const Protocol_Version &version)
const Certificate_12 * server_certs() const
const Certificate_12 * client_certs() const
const Finished_12 * client_finished() const
const Certificate_Request_12 * cert_req() const
const Ciphersuite & ciphersuite() const
const Server_Hello_12 * server_hello() const
bool received_handshake_msg(Handshake_Type msg_type) const
std::unique_ptr< KDF > protocol_specific_prf() const
const New_Session_Ticket_12 * new_session_ticket() const
std::pair< std::string, Signature_Format > choose_sig_format(const Private_Key &key, Signature_Scheme &scheme, bool for_client_auth, const Policy &policy) const
Protocol_Version version() const
void confirm_transition_to(Handshake_Type msg_type)
bool received_handshake_msg(Handshake_Type msg_type) const
void set_expected_next(Handshake_Type msg_type)
const std::vector< uint8_t > & ticket() const
Definition: tls_messages.h:854
virtual std::vector< Signature_Scheme > allowed_signature_schemes() const
Definition: tls_policy.cpp:22
bool allowed_signature_method(const std::string &sig_method) const
Definition: tls_policy.cpp:112
bool allowed_signature_hash(const std::string &hash) const
Definition: tls_policy.cpp:117
std::string hash_function_name() const noexcept
bool is_compatible_with(const Protocol_Version &protocol_version) const noexcept
std::optional< Signature_Format > format() const noexcept
std::string padding_string() const noexcept
bool is_available() const noexcept
std::string algorithm_name() const noexcept
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:209
@ HELLO_VERIFY_REQUEST
Definition: tls_magic.h:67
@ CLIENT_KEX
Definition: tls_magic.h:78
@ HANDSHAKE_CCS
Definition: tls_magic.h:87
@ ENCRYPTED_EXTENSIONS
Definition: tls_magic.h:71
@ CERTIFICATE_URL
Definition: tls_magic.h:81
@ SERVER_HELLO
Definition: tls_magic.h:66
@ HELLO_RETRY_REQUEST
Definition: tls_magic.h:86
@ NEW_SESSION_TICKET
Definition: tls_magic.h:68
@ END_OF_EARLY_DATA
Definition: tls_magic.h:70
@ KEY_UPDATE
Definition: tls_magic.h:84
@ SERVER_HELLO_DONE
Definition: tls_magic.h:76
@ HELLO_REQUEST
Definition: tls_magic.h:64
@ CERTIFICATE_REQUEST
Definition: tls_magic.h:75
@ CERTIFICATE
Definition: tls_magic.h:73
@ CERTIFICATE_STATUS
Definition: tls_magic.h:82
@ CERTIFICATE_VERIFY
Definition: tls_magic.h:77
@ HANDSHAKE_NONE
Definition: tls_magic.h:88
@ SERVER_KEX
Definition: tls_magic.h:74
@ CLIENT_HELLO
Definition: tls_magic.h:65
const char * handshake_type_to_string(Handshake_Type type)
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
Definition: bigint.h:1077
MechanismType type
AlgorithmIdentifier hash_algo
Definition: x509_obj.cpp:22