/src/botan/src/lib/tls/tls12/tls_handshake_state.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
16 | | namespace Botan::TLS { |
17 | | |
18 | | std::string Handshake_Message::type_string() const |
19 | 0 | { |
20 | 0 | return handshake_type_to_string(type()); |
21 | 0 | } |
22 | | |
23 | | const char* handshake_type_to_string(Handshake_Type type) |
24 | 438 | { |
25 | 438 | switch(type) |
26 | 438 | { |
27 | 6 | case HELLO_VERIFY_REQUEST: |
28 | 6 | return "hello_verify_request"; |
29 | | |
30 | 61 | case HELLO_REQUEST: |
31 | 61 | return "hello_request"; |
32 | | |
33 | 134 | case CLIENT_HELLO: |
34 | 134 | return "client_hello"; |
35 | | |
36 | 60 | case SERVER_HELLO: |
37 | 60 | return "server_hello"; |
38 | | |
39 | 11 | case HELLO_RETRY_REQUEST: |
40 | 11 | return "hello_retry_request"; |
41 | | |
42 | 7 | case CERTIFICATE: |
43 | 7 | return "certificate"; |
44 | | |
45 | 5 | case CERTIFICATE_URL: |
46 | 5 | return "certificate_url"; |
47 | | |
48 | 8 | case CERTIFICATE_STATUS: |
49 | 8 | return "certificate_status"; |
50 | | |
51 | 6 | case SERVER_KEX: |
52 | 6 | return "server_key_exchange"; |
53 | | |
54 | 5 | case CERTIFICATE_REQUEST: |
55 | 5 | return "certificate_request"; |
56 | | |
57 | 4 | case SERVER_HELLO_DONE: |
58 | 4 | return "server_hello_done"; |
59 | | |
60 | 4 | case CERTIFICATE_VERIFY: |
61 | 4 | return "certificate_verify"; |
62 | | |
63 | 47 | case CLIENT_KEX: |
64 | 47 | return "client_key_exchange"; |
65 | | |
66 | 6 | case NEW_SESSION_TICKET: |
67 | 6 | return "new_session_ticket"; |
68 | | |
69 | 41 | case HANDSHAKE_CCS: |
70 | 41 | return "change_cipher_spec"; |
71 | | |
72 | 13 | case FINISHED: |
73 | 13 | return "finished"; |
74 | | |
75 | 6 | case END_OF_EARLY_DATA: |
76 | 6 | return "end_of_early_data"; |
77 | | |
78 | 10 | case ENCRYPTED_EXTENSIONS: |
79 | 10 | return "encrypted_extensions"; |
80 | | |
81 | 4 | case KEY_UPDATE: |
82 | 4 | return "key_update"; |
83 | | |
84 | 0 | case HANDSHAKE_NONE: |
85 | 0 | return "invalid"; |
86 | 438 | } |
87 | | |
88 | 0 | throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, |
89 | 0 | "Unknown TLS handshake message type " + std::to_string(type)); |
90 | 438 | } |
91 | | |
92 | | |
93 | | /* |
94 | | * Initialize the SSL/TLS Handshake State |
95 | | */ |
96 | 27.6k | Handshake_State::~Handshake_State() = default; |
97 | | |
98 | | Handshake_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 | 27.6k | { |
103 | 27.6k | } |
104 | | |
105 | | void Handshake_State::note_message(const Handshake_Message& msg) |
106 | 104k | { |
107 | 104k | m_callbacks.tls_inspect_handshake_msg(msg); |
108 | 104k | } |
109 | | |
110 | | void Handshake_State::hello_verify_request(const Hello_Verify_Request& hello_verify) |
111 | 0 | { |
112 | 0 | note_message(hello_verify); |
113 | |
|
114 | 0 | m_client_hello->update_hello_cookie(hello_verify); |
115 | 0 | hash().reset(); |
116 | 0 | hash().update(handshake_io().send(*m_client_hello)); |
117 | 0 | note_message(*m_client_hello); |
118 | 0 | } |
119 | | |
120 | | void Handshake_State::client_hello(Client_Hello_12* client_hello) |
121 | 28.4k | { |
122 | 28.4k | if(client_hello == nullptr) |
123 | 2.39k | { |
124 | 2.39k | m_client_hello.reset(); |
125 | 2.39k | hash().reset(); |
126 | 2.39k | } |
127 | 26.0k | else |
128 | 26.0k | { |
129 | 26.0k | m_client_hello.reset(client_hello); |
130 | 26.0k | note_message(*m_client_hello); |
131 | 26.0k | } |
132 | 28.4k | } |
133 | | |
134 | | void Handshake_State::server_hello(Server_Hello_12* server_hello) |
135 | 21.0k | { |
136 | 21.0k | m_server_hello.reset(server_hello); |
137 | 21.0k | m_ciphersuite = Ciphersuite::by_id(m_server_hello->ciphersuite()); |
138 | 21.0k | note_message(*m_server_hello); |
139 | 21.0k | } |
140 | | |
141 | | void Handshake_State::server_certs(Certificate_12* server_certs) |
142 | 134 | { |
143 | 134 | m_server_certs.reset(server_certs); |
144 | 134 | note_message(*m_server_certs); |
145 | 134 | } |
146 | | |
147 | | void Handshake_State::server_cert_status(Certificate_Status* server_cert_status) |
148 | 0 | { |
149 | 0 | m_server_cert_status.reset(server_cert_status); |
150 | 0 | note_message(*m_server_cert_status); |
151 | 0 | } |
152 | | |
153 | | void Handshake_State::server_kex(Server_Key_Exchange* server_kex) |
154 | 20.8k | { |
155 | 20.8k | m_server_kex.reset(server_kex); |
156 | 20.8k | note_message(*m_server_kex); |
157 | 20.8k | } |
158 | | |
159 | | void Handshake_State::cert_req(Certificate_Request_12* cert_req) |
160 | 0 | { |
161 | 0 | m_cert_req.reset(cert_req); |
162 | 0 | note_message(*m_cert_req); |
163 | 0 | } |
164 | | |
165 | | void Handshake_State::server_hello_done(Server_Hello_Done* server_hello_done) |
166 | 20.8k | { |
167 | 20.8k | m_server_hello_done.reset(server_hello_done); |
168 | 20.8k | note_message(*m_server_hello_done); |
169 | 20.8k | } |
170 | | |
171 | | void Handshake_State::client_certs(Certificate_12* client_certs) |
172 | 0 | { |
173 | 0 | m_client_certs.reset(client_certs); |
174 | 0 | note_message(*m_client_certs); |
175 | 0 | } |
176 | | |
177 | | void Handshake_State::client_kex(Client_Key_Exchange* client_kex) |
178 | 14.2k | { |
179 | 14.2k | m_client_kex.reset(client_kex); |
180 | 14.2k | note_message(*m_client_kex); |
181 | 14.2k | } |
182 | | |
183 | | void Handshake_State::client_verify(Certificate_Verify_12* client_verify) |
184 | 0 | { |
185 | 0 | m_client_verify.reset(client_verify); |
186 | 0 | note_message(*m_client_verify); |
187 | 0 | } |
188 | | |
189 | | void Handshake_State::server_verify(Certificate_Verify_12* server_verify) |
190 | 0 | { |
191 | 0 | m_server_verify.reset(server_verify); |
192 | 0 | note_message(*m_server_verify); |
193 | 0 | } |
194 | | |
195 | | void Handshake_State::new_session_ticket(New_Session_Ticket_12* new_session_ticket) |
196 | 201 | { |
197 | 201 | m_new_session_ticket.reset(new_session_ticket); |
198 | 201 | note_message(*m_new_session_ticket); |
199 | 201 | } |
200 | | |
201 | | void Handshake_State::server_finished(Finished_12* server_finished) |
202 | 355 | { |
203 | 355 | m_server_finished.reset(server_finished); |
204 | 355 | note_message(*m_server_finished); |
205 | 355 | } |
206 | | |
207 | | void Handshake_State::client_finished(Finished_12* client_finished) |
208 | 355 | { |
209 | 355 | m_client_finished.reset(client_finished); |
210 | 355 | note_message(*m_client_finished); |
211 | 355 | } |
212 | | |
213 | | const Ciphersuite& Handshake_State::ciphersuite() const |
214 | 138k | { |
215 | 138k | if(!m_ciphersuite.has_value()) |
216 | 0 | { |
217 | 0 | throw Invalid_State("Cipher suite is not set"); |
218 | 0 | } |
219 | 138k | return m_ciphersuite.value(); |
220 | 138k | } |
221 | | |
222 | | void Handshake_State::set_version(const Protocol_Version& version) |
223 | 23.5k | { |
224 | 23.5k | m_version = version; |
225 | 23.5k | } |
226 | | |
227 | | void Handshake_State::compute_session_keys() |
228 | 14.2k | { |
229 | 14.2k | m_session_keys = Session_Keys(this, client_kex()->pre_master_secret(), false); |
230 | 14.2k | } |
231 | | |
232 | | void Handshake_State::compute_session_keys(const secure_vector<uint8_t>& resume_master_secret) |
233 | 0 | { |
234 | 0 | m_session_keys = Session_Keys(this, resume_master_secret, true); |
235 | 0 | } |
236 | | |
237 | | void Handshake_State::confirm_transition_to(Handshake_Type handshake_msg) |
238 | 42.7k | { |
239 | 42.7k | m_transitions.confirm_transition_to(handshake_msg); |
240 | 42.7k | } |
241 | | |
242 | | void Handshake_State::set_expected_next(Handshake_Type handshake_msg) |
243 | 65.6k | { |
244 | 65.6k | m_transitions.set_expected_next(handshake_msg); |
245 | 65.6k | } |
246 | | |
247 | | bool Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const |
248 | 14.9k | { |
249 | 14.9k | return m_transitions.received_handshake_msg(handshake_msg); |
250 | 14.9k | } |
251 | | |
252 | | std::pair<Handshake_Type, std::vector<uint8_t>> |
253 | | Handshake_State::get_next_handshake_msg() |
254 | 87.8k | { |
255 | 87.8k | return m_handshake_io->get_next_record(m_transitions.change_cipher_spec_expected()); |
256 | 87.8k | } |
257 | | |
258 | | std::vector<uint8_t> Handshake_State::session_ticket() const |
259 | 0 | { |
260 | 0 | if(new_session_ticket() && !new_session_ticket()->ticket().empty()) |
261 | 0 | { return new_session_ticket()->ticket(); } |
262 | | |
263 | 0 | return client_hello()->session_ticket(); |
264 | 0 | } |
265 | | |
266 | | std::unique_ptr<KDF> Handshake_State::protocol_specific_prf() const |
267 | 14.9k | { |
268 | 14.9k | const std::string prf_algo = ciphersuite().prf_algo(); |
269 | | |
270 | 14.9k | if(prf_algo == "MD5" || prf_algo == "SHA-1") |
271 | 8.19k | { return KDF::create_or_throw("TLS-12-PRF(SHA-256)"); } |
272 | | |
273 | 6.74k | return KDF::create_or_throw("TLS-12-PRF(" + prf_algo + ")"); |
274 | 14.9k | } |
275 | | |
276 | | std::pair<std::string, Signature_Format> |
277 | | Handshake_State::choose_sig_format(const Private_Key& key, |
278 | | Signature_Scheme& chosen_scheme, |
279 | | bool for_client_auth, |
280 | | const Policy& policy) const |
281 | 0 | { |
282 | 0 | const std::string sig_algo = key.algo_name(); |
283 | |
|
284 | 0 | const std::vector<Signature_Scheme> allowed = policy.allowed_signature_schemes(); |
285 | |
|
286 | 0 | std::vector<Signature_Scheme> requested = |
287 | 0 | (for_client_auth) ? cert_req()->signature_schemes() : client_hello()->signature_schemes(); |
288 | |
|
289 | 0 | for(Signature_Scheme scheme : allowed) |
290 | 0 | { |
291 | 0 | if(!scheme.is_available()) |
292 | 0 | { |
293 | 0 | continue; |
294 | 0 | } |
295 | | |
296 | 0 | if(scheme.algorithm_name() == sig_algo) |
297 | 0 | { |
298 | 0 | if(std::find(requested.begin(), requested.end(), scheme) != requested.end()) |
299 | 0 | { |
300 | 0 | chosen_scheme = scheme; |
301 | 0 | break; |
302 | 0 | } |
303 | 0 | } |
304 | 0 | } |
305 | |
|
306 | 0 | const std::string hash = chosen_scheme.hash_function_name(); |
307 | |
|
308 | 0 | if(!policy.allowed_signature_hash(hash)) |
309 | 0 | { |
310 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
311 | 0 | "Policy refuses to accept signing with any hash supported by peer"); |
312 | 0 | } |
313 | | |
314 | 0 | if(!chosen_scheme.format().has_value()) |
315 | 0 | { throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures"); } |
316 | | |
317 | 0 | return std::make_pair(chosen_scheme.padding_string(), chosen_scheme.format().value()); |
318 | 0 | } |
319 | | |
320 | | namespace { |
321 | | |
322 | | bool supported_algos_include( |
323 | | const std::vector<Signature_Scheme>& schemes, |
324 | | const std::string& key_type, |
325 | | const std::string& hash_type) |
326 | 0 | { |
327 | 0 | for(Signature_Scheme scheme : schemes) |
328 | 0 | { |
329 | 0 | if(scheme.is_available() && |
330 | 0 | hash_type == scheme.hash_function_name() && |
331 | 0 | key_type == scheme.algorithm_name()) |
332 | 0 | { |
333 | 0 | return true; |
334 | 0 | } |
335 | 0 | } |
336 | | |
337 | 0 | return false; |
338 | 0 | } |
339 | | |
340 | | } |
341 | | |
342 | | std::pair<std::string, Signature_Format> |
343 | | Handshake_State::parse_sig_format(const Public_Key& key, |
344 | | Signature_Scheme scheme, |
345 | | const std::vector<Signature_Scheme>& offered_schemes, |
346 | | bool for_client_auth, |
347 | | const Policy& policy) const |
348 | 0 | { |
349 | 0 | const std::string key_type = key.algo_name(); |
350 | |
|
351 | 0 | if(!policy.allowed_signature_method(key_type)) |
352 | 0 | { |
353 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
354 | 0 | "Rejecting " + key_type + " signature"); |
355 | 0 | } |
356 | | |
357 | 0 | if(!scheme.is_available()) |
358 | 0 | { |
359 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
360 | 0 | "Peer sent unknown signature scheme"); |
361 | 0 | } |
362 | | |
363 | 0 | if(key_type != scheme.algorithm_name()) |
364 | 0 | { throw Decoding_Error("Counterparty sent inconsistent key and sig types"); } |
365 | | |
366 | 0 | if(for_client_auth && !cert_req()) |
367 | 0 | { |
368 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
369 | 0 | "No certificate verify set"); |
370 | 0 | } |
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 | 0 | const std::vector<Signature_Scheme> supported_algos = |
378 | 0 | for_client_auth ? cert_req()->signature_schemes() : |
379 | 0 | offered_schemes; |
380 | |
|
381 | 0 | const std::string hash_algo = scheme.hash_function_name(); |
382 | |
|
383 | 0 | if(!scheme.is_compatible_with(Protocol_Version::TLS_V12)) |
384 | 0 | { throw TLS_Exception(Alert::ILLEGAL_PARAMETER, "Peer sent unexceptable signature scheme"); } |
385 | | |
386 | 0 | if(!supported_algos_include(supported_algos, key_type, hash_algo)) |
387 | 0 | { |
388 | 0 | throw TLS_Exception(Alert::ILLEGAL_PARAMETER, |
389 | 0 | "TLS signature extension did not allow for " + |
390 | 0 | key_type + "/" + hash_algo + " signature"); |
391 | 0 | } |
392 | | |
393 | 0 | if(!scheme.format().has_value()) |
394 | 0 | { throw Invalid_Argument(key_type + " is invalid/unknown for TLS signatures"); } |
395 | | |
396 | 0 | return std::make_pair(scheme.padding_string(), scheme.format().value()); |
397 | 0 | } |
398 | | |
399 | | } |