Botan 3.11.0
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/pkix_types.h>
13#include <botan/tls_callbacks.h>
14#include <botan/tls_messages_12.h>
15#include <botan/tls_policy.h>
16#include <botan/tls_signature_scheme.h>
17#include <botan/internal/tls_record.h>
18
19namespace Botan::TLS {
20
21std::string Handshake_Message::type_string() const {
23}
24
25/*
26* Initialize the SSL/TLS Handshake State
27*/
29
30Handshake_State::Handshake_State(std::unique_ptr<Handshake_IO> io, Callbacks& cb) :
31 m_callbacks(cb), m_handshake_io(std::move(io)), m_version(m_handshake_io->initial_record_version()) {}
32
34 m_callbacks.tls_inspect_handshake_msg(msg);
35}
36
38 note_message(hello_verify);
39
40 BOTAN_ASSERT_NONNULL(m_client_hello);
41 m_client_hello->update_hello_cookie(hello_verify);
42 hash().reset();
43 hash().update(handshake_io().send(*m_client_hello));
44 note_message(*m_client_hello);
45}
46
47void Handshake_State::client_hello(std::unique_ptr<Client_Hello_12> client_hello) {
48 // Legacy behavior (exception to the rule): Allow client_hello to be nullptr to reset state.
49 if(client_hello == nullptr) {
50 m_client_hello.reset();
51 hash().reset();
52 } else {
53 m_client_hello = std::move(client_hello);
54 note_message(*m_client_hello);
55 }
56}
57
58void Handshake_State::server_hello(std::unique_ptr<Server_Hello_12> server_hello) {
60 m_server_hello = std::move(server_hello);
61 m_ciphersuite = Ciphersuite::by_id(m_server_hello->ciphersuite());
62 note_message(*m_server_hello);
63}
64
65void Handshake_State::server_certs(std::unique_ptr<Certificate_12> server_certs) {
67 m_server_certs = std::move(server_certs);
68 note_message(*m_server_certs);
69}
70
71void Handshake_State::server_cert_status(std::unique_ptr<Certificate_Status> server_cert_status) {
73 m_server_cert_status = std::move(server_cert_status);
74 note_message(*m_server_cert_status);
75}
76
77void Handshake_State::server_kex(std::unique_ptr<Server_Key_Exchange> server_kex) {
79 m_server_kex = std::move(server_kex);
80 note_message(*m_server_kex);
81}
82
83void Handshake_State::cert_req(std::unique_ptr<Certificate_Request_12> cert_req) {
85 m_cert_req = std::move(cert_req);
86 note_message(*m_cert_req);
87}
88
89void Handshake_State::server_hello_done(std::unique_ptr<Server_Hello_Done> server_hello_done) {
91 m_server_hello_done = std::move(server_hello_done);
92 note_message(*m_server_hello_done);
93}
94
95void Handshake_State::client_certs(std::unique_ptr<Certificate_12> client_certs) {
97 m_client_certs = std::move(client_certs);
98 note_message(*m_client_certs);
99}
100
101void Handshake_State::client_kex(std::unique_ptr<Client_Key_Exchange> client_kex) {
103 m_client_kex = std::move(client_kex);
104 note_message(*m_client_kex);
105}
106
107void Handshake_State::client_verify(std::unique_ptr<Certificate_Verify_12> client_verify) {
109 m_client_verify = std::move(client_verify);
110 note_message(*m_client_verify);
111}
112
113void Handshake_State::server_verify(std::unique_ptr<Certificate_Verify_12> server_verify) {
115 m_server_verify = std::move(server_verify);
116 note_message(*m_server_verify);
117}
118
119void Handshake_State::new_session_ticket(std::unique_ptr<New_Session_Ticket_12> new_session_ticket) {
121 m_new_session_ticket = std::move(new_session_ticket);
122 note_message(*m_new_session_ticket);
123}
124
125void Handshake_State::server_finished(std::unique_ptr<Finished_12> server_finished) {
127 m_server_finished = std::move(server_finished);
128 note_message(*m_server_finished);
129}
130
131void Handshake_State::client_finished(std::unique_ptr<Finished_12> client_finished) {
133 m_client_finished = std::move(client_finished);
134 note_message(*m_client_finished);
135}
136
138 if(!m_ciphersuite.has_value()) {
139 throw Invalid_State("Cipher suite is not set");
140 }
141 return m_ciphersuite.value();
142}
143
144std::optional<std::string> Handshake_State::psk_identity() const {
145 if(!m_client_kex) {
146 return std::nullopt;
147 }
148 return m_client_kex->psk_identity();
149}
150
154
157 m_session_keys = Session_Keys(this, client_kex()->pre_master_secret(), false);
158}
159
161 m_session_keys = Session_Keys(this, resume_master_secret, true);
162}
163
165 m_transitions.confirm_transition_to(handshake_msg);
166}
167
169 m_transitions.set_expected_next(handshake_msg);
170}
171
173 return m_transitions.received_handshake_msg(handshake_msg);
174}
175
176std::pair<Handshake_Type, std::vector<uint8_t>> Handshake_State::get_next_handshake_msg() {
177 return m_handshake_io->get_next_record(m_transitions.change_cipher_spec_expected());
178}
179
181 if(const auto* nst = new_session_ticket()) {
182 const auto& ticket = nst->ticket();
183 if(!ticket.empty()) {
184 return ticket;
185 }
186 }
187
189 return client_hello()->session_ticket();
190}
191
192std::unique_ptr<KDF> Handshake_State::protocol_specific_prf() const {
193 return m_callbacks.tls12_protocol_specific_kdf(ciphersuite().prf_algo());
194}
195
196std::pair<std::string, Signature_Format> Handshake_State::choose_sig_format(const Private_Key& key,
197 Signature_Scheme& chosen_scheme,
198 bool for_client_auth,
199 const Policy& policy) const {
200 const std::string sig_algo = key.algo_name();
201
202 const std::vector<Signature_Scheme> allowed = policy.allowed_signature_schemes();
203
204 if(for_client_auth) {
206 } else {
208 }
209
210 std::vector<Signature_Scheme> requested =
211 (for_client_auth) ? cert_req()->signature_schemes() : client_hello()->signature_schemes();
212
213 for(const Signature_Scheme scheme : allowed) {
214 if(!scheme.is_available()) {
215 continue;
216 }
217
218 if(scheme.algorithm_name() == sig_algo) {
219 if(std::find(requested.begin(), requested.end(), scheme) != requested.end()) {
220 chosen_scheme = scheme;
221 break;
222 }
223 }
224 }
225
226 const std::string hash = chosen_scheme.hash_function_name();
227
228 if(!policy.allowed_signature_hash(hash)) {
229 throw TLS_Exception(Alert::HandshakeFailure, "Policy refuses to accept signing with any hash supported by peer");
230 }
231
232 if(!chosen_scheme.format().has_value()) {
233 throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures");
234 }
235
236 return std::make_pair(chosen_scheme.padding_string(), chosen_scheme.format().value());
237}
238
239namespace {
240
241bool supported_algos_include(const std::vector<Signature_Scheme>& schemes,
242 std::string_view key_type,
243 std::string_view hash_type) {
244 for(const Signature_Scheme scheme : schemes) {
245 if(scheme.is_available() && hash_type == scheme.hash_function_name() && key_type == scheme.algorithm_name()) {
246 return true;
247 }
248 }
249
250 return false;
251}
252
253} // namespace
254
255std::pair<std::string, Signature_Format> Handshake_State::parse_sig_format(
256 const Public_Key& key,
257 Signature_Scheme scheme,
258 const std::vector<Signature_Scheme>& offered_schemes,
259 bool for_client_auth,
260 const Policy& policy) const {
261 const std::string key_type = key.algo_name();
262
263 if(!policy.allowed_signature_method(key_type)) {
264 throw TLS_Exception(Alert::HandshakeFailure, "Rejecting " + key_type + " signature");
265 }
266
267 if(!scheme.is_available()) {
268 throw TLS_Exception(Alert::IllegalParameter, "Peer sent unknown signature scheme");
269 }
270
271 if(key_type != scheme.algorithm_name()) {
272 throw Decoding_Error("Counterparty sent inconsistent key and sig types");
273 }
274
275 if(for_client_auth && cert_req() == nullptr) {
276 throw TLS_Exception(Alert::HandshakeFailure, "No CertificateVerify message received");
277 }
278
279 /*
280 Confirm the signature type we just received against the
281 supported_algos list that we sent; it better be there.
282 */
283
284 const std::vector<Signature_Scheme> supported_algos =
285 for_client_auth ? cert_req()->signature_schemes() : offered_schemes;
286
287 const std::string hash_algo = scheme.hash_function_name();
288
289 if(!scheme.is_compatible_with(Protocol_Version::TLS_V12)) {
290 throw TLS_Exception(Alert::IllegalParameter, "Peer sent unexceptable signature scheme");
291 }
292
293 if(!supported_algos_include(supported_algos, key_type, hash_algo)) {
294 throw TLS_Exception(Alert::IllegalParameter,
295 "TLS signature extension did not allow for " + key_type + "/" + hash_algo + " signature");
296 }
297
298 if(!scheme.format().has_value()) {
299 throw Invalid_Argument(key_type + " is invalid/unknown for TLS signatures");
300 }
301
302 return std::make_pair(scheme.padding_string(), scheme.format().value());
303}
304
305} // namespace Botan::TLS
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
virtual std::string algo_name() const =0
const std::vector< Signature_Scheme > & signature_schemes() const
static std::optional< Ciphersuite > by_id(uint16_t suite)
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
void server_finished(std::unique_ptr< Finished_12 > server_finished)
void client_hello(std::unique_ptr< Client_Hello_12 > client_hello)
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)
void server_verify(std::unique_ptr< Certificate_Verify_12 > server_verify)
void new_session_ticket(std::unique_ptr< New_Session_Ticket_12 > new_session_ticket)
void client_certs(std::unique_ptr< Certificate_12 > client_certs)
void client_kex(std::unique_ptr< Client_Key_Exchange > client_kex)
const Certificate_Verify_12 * client_verify() const
const Finished_12 * server_finished() const
void server_hello_done(std::unique_ptr< Server_Hello_Done > server_hello_done)
const Client_Hello_12 * client_hello() const
const Client_Key_Exchange * client_kex() const
void cert_req(std::unique_ptr< Certificate_Request_12 > cert_req)
void server_cert_status(std::unique_ptr< Certificate_Status > server_cert_status)
void server_hello(std::unique_ptr< Server_Hello_12 > server_hello)
void confirm_transition_to(Handshake_Type msg_type)
void set_version(const Protocol_Version &version)
void client_finished(std::unique_ptr< Finished_12 > client_finished)
std::optional< std::string > psk_identity() const
const Certificate_12 * server_certs() const
const Certificate_12 * client_certs() const
void client_verify(std::unique_ptr< Certificate_Verify_12 > client_verify)
const Finished_12 * client_finished() const
const Certificate_Request_12 * cert_req() const
const Ciphersuite & ciphersuite() const
Session_Ticket session_ticket() const
void server_kex(std::unique_ptr< Server_Key_Exchange > server_kex)
const Server_Hello_12 * server_hello() const
bool received_handshake_msg(Handshake_Type msg_type) const
void server_certs(std::unique_ptr< Certificate_12 > server_certs)
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
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)
Definition tls_magic.cpp:15
Strong< std::vector< uint8_t >, struct Session_Ticket_ > Session_Ticket
holds a TLS 1.2 session ticket for stateless resumption
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68