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