Botan 3.6.1
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
11#include <botan/kdf.h>
12#include <botan/tls_messages.h>
13#include <botan/tls_signature_scheme.h>
14#include <botan/internal/tls_record.h>
15#include <sstream>
16
17namespace Botan::TLS {
18
19std::string Handshake_Message::type_string() const {
21}
22
24 switch(type) {
26 return "hello_verify_request";
27
29 return "hello_request";
30
32 return "client_hello";
33
35 return "server_hello";
36
38 return "hello_retry_request";
39
41 return "certificate";
42
44 return "certificate_url";
45
47 return "certificate_status";
48
50 return "server_key_exchange";
51
53 return "certificate_request";
54
56 return "server_hello_done";
57
59 return "certificate_verify";
60
62 return "client_key_exchange";
63
65 return "new_session_ticket";
66
68 return "change_cipher_spec";
69
71 return "finished";
72
74 return "end_of_early_data";
75
77 return "encrypted_extensions";
78
80 return "key_update";
81
83 return "invalid";
84 }
85
86 throw TLS_Exception(Alert::UnexpectedMessage,
87 "Unknown TLS handshake message type " + std::to_string(static_cast<size_t>(type)));
88}
89
90/*
91* Initialize the SSL/TLS Handshake State
92*/
94
95Handshake_State::Handshake_State(std::unique_ptr<Handshake_IO> io, Callbacks& cb) :
96 m_callbacks(cb), m_handshake_io(std::move(io)), m_version(m_handshake_io->initial_record_version()) {}
97
101
103 note_message(hello_verify);
104
105 m_client_hello->update_hello_cookie(hello_verify);
106 hash().reset();
107 hash().update(handshake_io().send(*m_client_hello));
108 note_message(*m_client_hello);
109}
110
112 if(client_hello == nullptr) {
113 m_client_hello.reset();
114 hash().reset();
115 } else {
116 m_client_hello.reset(client_hello);
117 note_message(*m_client_hello);
118 }
119}
120
122 m_server_hello.reset(server_hello);
123 m_ciphersuite = Ciphersuite::by_id(m_server_hello->ciphersuite());
124 note_message(*m_server_hello);
125}
126
128 m_server_certs.reset(server_certs);
129 note_message(*m_server_certs);
130}
131
133 m_server_cert_status.reset(server_cert_status);
134 note_message(*m_server_cert_status);
135}
136
138 m_server_kex.reset(server_kex);
139 note_message(*m_server_kex);
140}
141
143 m_cert_req.reset(cert_req);
144 note_message(*m_cert_req);
145}
146
148 m_server_hello_done.reset(server_hello_done);
149 note_message(*m_server_hello_done);
150}
151
153 m_client_certs.reset(client_certs);
154 note_message(*m_client_certs);
155}
156
158 m_client_kex.reset(client_kex);
159 note_message(*m_client_kex);
160}
161
163 m_client_verify.reset(client_verify);
164 note_message(*m_client_verify);
165}
166
168 m_server_verify.reset(server_verify);
169 note_message(*m_server_verify);
170}
171
173 m_new_session_ticket.reset(new_session_ticket);
174 note_message(*m_new_session_ticket);
175}
176
178 m_server_finished.reset(server_finished);
179 note_message(*m_server_finished);
180}
181
183 m_client_finished.reset(client_finished);
184 note_message(*m_client_finished);
185}
186
188 if(!m_ciphersuite.has_value()) {
189 throw Invalid_State("Cipher suite is not set");
190 }
191 return m_ciphersuite.value();
192}
193
194std::optional<std::string> Handshake_State::psk_identity() const {
195 if(!m_client_kex) {
196 return std::nullopt;
197 }
198 return m_client_kex->psk_identity();
199}
200
202 m_version = version;
203}
204
206 m_session_keys = Session_Keys(this, client_kex()->pre_master_secret(), false);
207}
208
210 m_session_keys = Session_Keys(this, resume_master_secret, true);
211}
212
214 m_transitions.confirm_transition_to(handshake_msg);
215}
216
218 m_transitions.set_expected_next(handshake_msg);
219}
220
222 return m_transitions.received_handshake_msg(handshake_msg);
223}
224
225std::pair<Handshake_Type, std::vector<uint8_t>> Handshake_State::get_next_handshake_msg() {
226 return m_handshake_io->get_next_record(m_transitions.change_cipher_spec_expected());
227}
228
230 if(new_session_ticket() && !new_session_ticket()->ticket().empty()) {
231 return new_session_ticket()->ticket();
232 }
233
234 return client_hello()->session_ticket();
235}
236
237std::unique_ptr<KDF> Handshake_State::protocol_specific_prf() const {
238 const std::string prf_algo = ciphersuite().prf_algo();
239
240 if(prf_algo == "MD5" || prf_algo == "SHA-1") {
241 return KDF::create_or_throw("TLS-12-PRF(SHA-256)");
242 }
243
244 return KDF::create_or_throw("TLS-12-PRF(" + prf_algo + ")");
245}
246
247std::pair<std::string, Signature_Format> Handshake_State::choose_sig_format(const Private_Key& key,
248 Signature_Scheme& chosen_scheme,
249 bool for_client_auth,
250 const Policy& policy) const {
251 const std::string sig_algo = key.algo_name();
252
253 const std::vector<Signature_Scheme> allowed = policy.allowed_signature_schemes();
254
255 std::vector<Signature_Scheme> requested =
256 (for_client_auth) ? cert_req()->signature_schemes() : client_hello()->signature_schemes();
257
258 for(Signature_Scheme scheme : allowed) {
259 if(!scheme.is_available()) {
260 continue;
261 }
262
263 if(scheme.algorithm_name() == sig_algo) {
264 if(std::find(requested.begin(), requested.end(), scheme) != requested.end()) {
265 chosen_scheme = scheme;
266 break;
267 }
268 }
269 }
270
271 const std::string hash = chosen_scheme.hash_function_name();
272
273 if(!policy.allowed_signature_hash(hash)) {
274 throw TLS_Exception(Alert::HandshakeFailure, "Policy refuses to accept signing with any hash supported by peer");
275 }
276
277 if(!chosen_scheme.format().has_value()) {
278 throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures");
279 }
280
281 return std::make_pair(chosen_scheme.padding_string(), chosen_scheme.format().value());
282}
283
284namespace {
285
286bool supported_algos_include(const std::vector<Signature_Scheme>& schemes,
287 std::string_view key_type,
288 std::string_view hash_type) {
289 for(Signature_Scheme scheme : schemes) {
290 if(scheme.is_available() && hash_type == scheme.hash_function_name() && key_type == scheme.algorithm_name()) {
291 return true;
292 }
293 }
294
295 return false;
296}
297
298} // namespace
299
300std::pair<std::string, Signature_Format> Handshake_State::parse_sig_format(
301 const Public_Key& key,
302 Signature_Scheme scheme,
303 const std::vector<Signature_Scheme>& offered_schemes,
304 bool for_client_auth,
305 const Policy& policy) const {
306 const std::string key_type = key.algo_name();
307
308 if(!policy.allowed_signature_method(key_type)) {
309 throw TLS_Exception(Alert::HandshakeFailure, "Rejecting " + key_type + " signature");
310 }
311
312 if(!scheme.is_available()) {
313 throw TLS_Exception(Alert::IllegalParameter, "Peer sent unknown signature scheme");
314 }
315
316 if(key_type != scheme.algorithm_name()) {
317 throw Decoding_Error("Counterparty sent inconsistent key and sig types");
318 }
319
320 if(for_client_auth && !cert_req()) {
321 throw TLS_Exception(Alert::HandshakeFailure, "No certificate verify set");
322 }
323
324 /*
325 Confirm the signature type we just received against the
326 supported_algos list that we sent; it better be there.
327 */
328
329 const std::vector<Signature_Scheme> supported_algos =
330 for_client_auth ? cert_req()->signature_schemes() : offered_schemes;
331
332 const std::string hash_algo = scheme.hash_function_name();
333
334 if(!scheme.is_compatible_with(Protocol_Version::TLS_V12)) {
335 throw TLS_Exception(Alert::IllegalParameter, "Peer sent unexceptable signature scheme");
336 }
337
338 if(!supported_algos_include(supported_algos, key_type, hash_algo)) {
339 throw TLS_Exception(Alert::IllegalParameter,
340 "TLS signature extension did not allow for " + key_type + "/" + hash_algo + " signature");
341 }
342
343 if(!scheme.format().has_value()) {
344 throw Invalid_Argument(key_type + " is invalid/unknown for TLS signatures");
345 }
346
347 return std::make_pair(scheme.padding_string(), scheme.format().value());
348}
349
350} // namespace Botan::TLS
virtual std::string algo_name() const =0
static std::unique_ptr< KDF > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition kdf.cpp:199
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
Session_Ticket 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
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)
std::optional< std::string > psk_identity() const
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
Session_Ticket session_ticket() 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 Session_Ticket & ticket() const
virtual std::vector< Signature_Scheme > allowed_signature_schemes() const
bool allowed_signature_method(std::string_view sig_method) const
bool allowed_signature_hash(std::string_view hash) const
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
std::string algorithm_name() const noexcept
const char * handshake_type_to_string(Handshake_Type type)
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61