/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 | | |
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 | | |
17 | | namespace Botan::TLS { |
18 | | |
19 | 0 | std::string Handshake_Message::type_string() const { |
20 | 0 | return handshake_type_to_string(type()); |
21 | 0 | } |
22 | | |
23 | 605 | const char* handshake_type_to_string(Handshake_Type type) { |
24 | 605 | switch(type) { |
25 | 7 | case Handshake_Type::HelloVerifyRequest: |
26 | 7 | return "hello_verify_request"; |
27 | | |
28 | 78 | case Handshake_Type::HelloRequest: |
29 | 78 | return "hello_request"; |
30 | | |
31 | 177 | case Handshake_Type::ClientHello: |
32 | 177 | return "client_hello"; |
33 | | |
34 | 62 | case Handshake_Type::ServerHello: |
35 | 62 | return "server_hello"; |
36 | | |
37 | 7 | case Handshake_Type::HelloRetryRequest: |
38 | 7 | return "hello_retry_request"; |
39 | | |
40 | 9 | case Handshake_Type::Certificate: |
41 | 9 | return "certificate"; |
42 | | |
43 | 6 | case Handshake_Type::CertificateUrl: |
44 | 6 | return "certificate_url"; |
45 | | |
46 | 5 | case Handshake_Type::CertificateStatus: |
47 | 5 | return "certificate_status"; |
48 | | |
49 | 12 | case Handshake_Type::ServerKeyExchange: |
50 | 12 | return "server_key_exchange"; |
51 | | |
52 | 11 | case Handshake_Type::CertificateRequest: |
53 | 11 | return "certificate_request"; |
54 | | |
55 | 8 | case Handshake_Type::ServerHelloDone: |
56 | 8 | return "server_hello_done"; |
57 | | |
58 | 4 | case Handshake_Type::CertificateVerify: |
59 | 4 | return "certificate_verify"; |
60 | | |
61 | 81 | case Handshake_Type::ClientKeyExchange: |
62 | 81 | return "client_key_exchange"; |
63 | | |
64 | 23 | case Handshake_Type::NewSessionTicket: |
65 | 23 | return "new_session_ticket"; |
66 | | |
67 | 80 | case Handshake_Type::HandshakeCCS: |
68 | 80 | return "change_cipher_spec"; |
69 | | |
70 | 15 | case Handshake_Type::Finished: |
71 | 15 | return "finished"; |
72 | | |
73 | 7 | case Handshake_Type::EndOfEarlyData: |
74 | 7 | return "end_of_early_data"; |
75 | | |
76 | 9 | case Handshake_Type::EncryptedExtensions: |
77 | 9 | return "encrypted_extensions"; |
78 | | |
79 | 4 | case Handshake_Type::KeyUpdate: |
80 | 4 | return "key_update"; |
81 | | |
82 | 0 | case Handshake_Type::None: |
83 | 0 | return "invalid"; |
84 | 605 | } |
85 | | |
86 | 0 | throw TLS_Exception(Alert::UnexpectedMessage, |
87 | 0 | "Unknown TLS handshake message type " + std::to_string(static_cast<size_t>(type))); |
88 | 605 | } |
89 | | |
90 | | /* |
91 | | * Initialize the SSL/TLS Handshake State |
92 | | */ |
93 | 28.0k | Handshake_State::~Handshake_State() = default; |
94 | | |
95 | | Handshake_State::Handshake_State(std::unique_ptr<Handshake_IO> io, Callbacks& cb) : |
96 | 28.0k | m_callbacks(cb), m_handshake_io(std::move(io)), m_version(m_handshake_io->initial_record_version()) {} |
97 | | |
98 | 105k | void Handshake_State::note_message(const Handshake_Message& msg) { |
99 | 105k | m_callbacks.tls_inspect_handshake_msg(msg); |
100 | 105k | } |
101 | | |
102 | 0 | void Handshake_State::hello_verify_request(const Hello_Verify_Request& hello_verify) { |
103 | 0 | note_message(hello_verify); |
104 | |
|
105 | 0 | m_client_hello->update_hello_cookie(hello_verify); |
106 | 0 | hash().reset(); |
107 | 0 | hash().update(handshake_io().send(*m_client_hello)); |
108 | 0 | note_message(*m_client_hello); |
109 | 0 | } |
110 | | |
111 | 31.8k | void Handshake_State::client_hello(Client_Hello_12* client_hello) { |
112 | 31.8k | if(client_hello == nullptr) { |
113 | 4.03k | m_client_hello.reset(); |
114 | 4.03k | hash().reset(); |
115 | 27.8k | } else { |
116 | 27.8k | m_client_hello.reset(client_hello); |
117 | 27.8k | note_message(*m_client_hello); |
118 | 27.8k | } |
119 | 31.8k | } |
120 | | |
121 | 21.1k | void Handshake_State::server_hello(Server_Hello_12* server_hello) { |
122 | 21.1k | m_server_hello.reset(server_hello); |
123 | 21.1k | m_ciphersuite = Ciphersuite::by_id(m_server_hello->ciphersuite()); |
124 | 21.1k | note_message(*m_server_hello); |
125 | 21.1k | } |
126 | | |
127 | 179 | void Handshake_State::server_certs(Certificate_12* server_certs) { |
128 | 179 | m_server_certs.reset(server_certs); |
129 | 179 | note_message(*m_server_certs); |
130 | 179 | } |
131 | | |
132 | 0 | void Handshake_State::server_cert_status(Certificate_Status* server_cert_status) { |
133 | 0 | m_server_cert_status.reset(server_cert_status); |
134 | 0 | note_message(*m_server_cert_status); |
135 | 0 | } |
136 | | |
137 | 20.8k | void Handshake_State::server_kex(Server_Key_Exchange* server_kex) { |
138 | 20.8k | m_server_kex.reset(server_kex); |
139 | 20.8k | note_message(*m_server_kex); |
140 | 20.8k | } |
141 | | |
142 | 0 | void Handshake_State::cert_req(Certificate_Request_12* cert_req) { |
143 | 0 | m_cert_req.reset(cert_req); |
144 | 0 | note_message(*m_cert_req); |
145 | 0 | } |
146 | | |
147 | 20.8k | void Handshake_State::server_hello_done(Server_Hello_Done* server_hello_done) { |
148 | 20.8k | m_server_hello_done.reset(server_hello_done); |
149 | 20.8k | note_message(*m_server_hello_done); |
150 | 20.8k | } |
151 | | |
152 | 0 | void Handshake_State::client_certs(Certificate_12* client_certs) { |
153 | 0 | m_client_certs.reset(client_certs); |
154 | 0 | note_message(*m_client_certs); |
155 | 0 | } |
156 | | |
157 | 14.1k | void Handshake_State::client_kex(Client_Key_Exchange* client_kex) { |
158 | 14.1k | m_client_kex.reset(client_kex); |
159 | 14.1k | note_message(*m_client_kex); |
160 | 14.1k | } |
161 | | |
162 | 0 | void Handshake_State::client_verify(Certificate_Verify_12* client_verify) { |
163 | 0 | m_client_verify.reset(client_verify); |
164 | 0 | note_message(*m_client_verify); |
165 | 0 | } |
166 | | |
167 | 0 | void Handshake_State::server_verify(Certificate_Verify_12* server_verify) { |
168 | 0 | m_server_verify.reset(server_verify); |
169 | 0 | note_message(*m_server_verify); |
170 | 0 | } |
171 | | |
172 | 0 | void Handshake_State::new_session_ticket(New_Session_Ticket_12* new_session_ticket) { |
173 | 0 | m_new_session_ticket.reset(new_session_ticket); |
174 | 0 | note_message(*m_new_session_ticket); |
175 | 0 | } |
176 | | |
177 | 207 | void Handshake_State::server_finished(Finished_12* server_finished) { |
178 | 207 | m_server_finished.reset(server_finished); |
179 | 207 | note_message(*m_server_finished); |
180 | 207 | } |
181 | | |
182 | 207 | void Handshake_State::client_finished(Finished_12* client_finished) { |
183 | 207 | m_client_finished.reset(client_finished); |
184 | 207 | note_message(*m_client_finished); |
185 | 207 | } |
186 | | |
187 | 144k | const Ciphersuite& Handshake_State::ciphersuite() const { |
188 | 144k | if(!m_ciphersuite.has_value()) { |
189 | 0 | throw Invalid_State("Cipher suite is not set"); |
190 | 0 | } |
191 | 144k | return m_ciphersuite.value(); |
192 | 144k | } |
193 | | |
194 | 207 | std::optional<std::string> Handshake_State::psk_identity() const { |
195 | 207 | if(!m_client_kex) { |
196 | 0 | return std::nullopt; |
197 | 0 | } |
198 | 207 | return m_client_kex->psk_identity(); |
199 | 207 | } |
200 | | |
201 | 25.2k | void Handshake_State::set_version(const Protocol_Version& version) { |
202 | 25.2k | m_version = version; |
203 | 25.2k | } |
204 | | |
205 | 14.1k | void Handshake_State::compute_session_keys() { |
206 | 14.1k | m_session_keys = Session_Keys(this, client_kex()->pre_master_secret(), false); |
207 | 14.1k | } |
208 | | |
209 | 0 | void Handshake_State::compute_session_keys(const secure_vector<uint8_t>& resume_master_secret) { |
210 | 0 | m_session_keys = Session_Keys(this, resume_master_secret, true); |
211 | 0 | } |
212 | | |
213 | 43.9k | void Handshake_State::confirm_transition_to(Handshake_Type handshake_msg) { |
214 | 43.9k | m_transitions.confirm_transition_to(handshake_msg); |
215 | 43.9k | } |
216 | | |
217 | 67.0k | void Handshake_State::set_expected_next(Handshake_Type handshake_msg) { |
218 | 67.0k | m_transitions.set_expected_next(handshake_msg); |
219 | 67.0k | } |
220 | | |
221 | 14.7k | bool Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const { |
222 | 14.7k | return m_transitions.received_handshake_msg(handshake_msg); |
223 | 14.7k | } |
224 | | |
225 | 89.8k | std::pair<Handshake_Type, std::vector<uint8_t>> Handshake_State::get_next_handshake_msg() { |
226 | 89.8k | return m_handshake_io->get_next_record(m_transitions.change_cipher_spec_expected()); |
227 | 89.8k | } |
228 | | |
229 | 0 | Session_Ticket Handshake_State::session_ticket() const { |
230 | 0 | if(new_session_ticket() && !new_session_ticket()->ticket().empty()) { |
231 | 0 | return new_session_ticket()->ticket(); |
232 | 0 | } |
233 | | |
234 | 0 | return client_hello()->session_ticket(); |
235 | 0 | } |
236 | | |
237 | 14.5k | std::unique_ptr<KDF> Handshake_State::protocol_specific_prf() const { |
238 | 14.5k | const std::string prf_algo = ciphersuite().prf_algo(); |
239 | | |
240 | 14.5k | if(prf_algo == "MD5" || prf_algo == "SHA-1") { |
241 | 1.82k | return KDF::create_or_throw("TLS-12-PRF(SHA-256)"); |
242 | 1.82k | } |
243 | | |
244 | 12.7k | return KDF::create_or_throw("TLS-12-PRF(" + prf_algo + ")"); |
245 | 14.5k | } |
246 | | |
247 | | std::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 | 0 | const Policy& policy) const { |
251 | 0 | const std::string sig_algo = key.algo_name(); |
252 | |
|
253 | 0 | const std::vector<Signature_Scheme> allowed = policy.allowed_signature_schemes(); |
254 | |
|
255 | 0 | std::vector<Signature_Scheme> requested = |
256 | 0 | (for_client_auth) ? cert_req()->signature_schemes() : client_hello()->signature_schemes(); |
257 | |
|
258 | 0 | for(Signature_Scheme scheme : allowed) { |
259 | 0 | if(!scheme.is_available()) { |
260 | 0 | continue; |
261 | 0 | } |
262 | | |
263 | 0 | if(scheme.algorithm_name() == sig_algo) { |
264 | 0 | if(std::find(requested.begin(), requested.end(), scheme) != requested.end()) { |
265 | 0 | chosen_scheme = scheme; |
266 | 0 | break; |
267 | 0 | } |
268 | 0 | } |
269 | 0 | } |
270 | |
|
271 | 0 | const std::string hash = chosen_scheme.hash_function_name(); |
272 | |
|
273 | 0 | if(!policy.allowed_signature_hash(hash)) { |
274 | 0 | throw TLS_Exception(Alert::HandshakeFailure, "Policy refuses to accept signing with any hash supported by peer"); |
275 | 0 | } |
276 | | |
277 | 0 | if(!chosen_scheme.format().has_value()) { |
278 | 0 | throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures"); |
279 | 0 | } |
280 | | |
281 | 0 | return std::make_pair(chosen_scheme.padding_string(), chosen_scheme.format().value()); |
282 | 0 | } |
283 | | |
284 | | namespace { |
285 | | |
286 | | bool supported_algos_include(const std::vector<Signature_Scheme>& schemes, |
287 | | std::string_view key_type, |
288 | 0 | std::string_view hash_type) { |
289 | 0 | for(Signature_Scheme scheme : schemes) { |
290 | 0 | if(scheme.is_available() && hash_type == scheme.hash_function_name() && key_type == scheme.algorithm_name()) { |
291 | 0 | return true; |
292 | 0 | } |
293 | 0 | } |
294 | | |
295 | 0 | return false; |
296 | 0 | } |
297 | | |
298 | | } // namespace |
299 | | |
300 | | std::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 | 0 | const Policy& policy) const { |
306 | 0 | const std::string key_type = key.algo_name(); |
307 | |
|
308 | 0 | if(!policy.allowed_signature_method(key_type)) { |
309 | 0 | throw TLS_Exception(Alert::HandshakeFailure, "Rejecting " + key_type + " signature"); |
310 | 0 | } |
311 | | |
312 | 0 | if(!scheme.is_available()) { |
313 | 0 | throw TLS_Exception(Alert::HandshakeFailure, "Peer sent unknown signature scheme"); |
314 | 0 | } |
315 | | |
316 | 0 | if(key_type != scheme.algorithm_name()) { |
317 | 0 | throw Decoding_Error("Counterparty sent inconsistent key and sig types"); |
318 | 0 | } |
319 | | |
320 | 0 | if(for_client_auth && !cert_req()) { |
321 | 0 | throw TLS_Exception(Alert::HandshakeFailure, "No certificate verify set"); |
322 | 0 | } |
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 | 0 | const std::vector<Signature_Scheme> supported_algos = |
330 | 0 | for_client_auth ? cert_req()->signature_schemes() : offered_schemes; |
331 | |
|
332 | 0 | const std::string hash_algo = scheme.hash_function_name(); |
333 | |
|
334 | 0 | if(!scheme.is_compatible_with(Protocol_Version::TLS_V12)) { |
335 | 0 | throw TLS_Exception(Alert::IllegalParameter, "Peer sent unexceptable signature scheme"); |
336 | 0 | } |
337 | | |
338 | 0 | if(!supported_algos_include(supported_algos, key_type, hash_algo)) { |
339 | 0 | throw TLS_Exception(Alert::IllegalParameter, |
340 | 0 | "TLS signature extension did not allow for " + key_type + "/" + hash_algo + " signature"); |
341 | 0 | } |
342 | | |
343 | 0 | if(!scheme.format().has_value()) { |
344 | 0 | throw Invalid_Argument(key_type + " is invalid/unknown for TLS signatures"); |
345 | 0 | } |
346 | | |
347 | 0 | return std::make_pair(scheme.padding_string(), scheme.format().value()); |
348 | 0 | } |
349 | | |
350 | | } // namespace Botan::TLS |