/src/botan/src/lib/tls/tls12/tls_client_impl_12.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * TLS Client |
3 | | * (C) 2004-2011,2012,2015,2016 Jack Lloyd |
4 | | * 2016 Matthias Gierlings |
5 | | * 2017 Harry Reimann, Rohde & Schwarz Cybersecurity |
6 | | * |
7 | | * Botan is released under the Simplified BSD License (see license.txt) |
8 | | */ |
9 | | |
10 | | #include <botan/tls_client.h> |
11 | | #include <botan/tls_messages.h> |
12 | | #include <botan/ocsp.h> |
13 | | #include <botan/internal/tls_handshake_state.h> |
14 | | #include <botan/internal/stl_util.h> |
15 | | #include <botan/internal/tls_client_impl_12.h> |
16 | | #include <sstream> |
17 | | |
18 | | namespace Botan::TLS { |
19 | | |
20 | | namespace { |
21 | | |
22 | | class Client_Handshake_State_12 final : public Handshake_State |
23 | | { |
24 | | public: |
25 | | Client_Handshake_State_12(std::unique_ptr<Handshake_IO> io, Callbacks& cb) : |
26 | | Handshake_State(std::move(io), cb), |
27 | | m_is_reneg(false) |
28 | 3.56k | {} |
29 | | |
30 | | const Public_Key& get_server_public_key() const |
31 | 0 | { |
32 | 0 | BOTAN_ASSERT(server_public_key, "Server sent us a certificate"); |
33 | 0 | return *server_public_key.get(); |
34 | 0 | } |
35 | | |
36 | 0 | bool is_a_resumption() const { return (resumed_session != nullptr); } |
37 | | |
38 | 0 | bool is_a_renegotiation() const { return m_is_reneg; } |
39 | | |
40 | | const secure_vector<uint8_t>& resume_master_secret() const |
41 | 0 | { |
42 | 0 | BOTAN_STATE_CHECK(is_a_resumption()); |
43 | 0 | return resumed_session->master_secret(); |
44 | 0 | } |
45 | | |
46 | | const std::vector<X509_Certificate>& resume_peer_certs() const |
47 | 0 | { |
48 | 0 | BOTAN_STATE_CHECK(is_a_resumption()); |
49 | 0 | return resumed_session->peer_certs(); |
50 | 0 | } |
51 | | |
52 | | std::unique_ptr<Public_Key> server_public_key; |
53 | | // Used during session resumption |
54 | | std::unique_ptr<Session> resumed_session; |
55 | | bool m_is_reneg = false; |
56 | | }; |
57 | | } |
58 | | |
59 | | /* |
60 | | * TLS 1.2 Client Constructor |
61 | | */ |
62 | | Client_Impl_12::Client_Impl_12(Callbacks& callbacks, |
63 | | Session_Manager& session_manager, |
64 | | Credentials_Manager& creds, |
65 | | const Policy& policy, |
66 | | RandomNumberGenerator& rng, |
67 | | const Server_Information& info, |
68 | | bool datagram, |
69 | | const std::vector<std::string>& next_protocols, |
70 | | size_t io_buf_sz) : |
71 | | Channel_Impl_12(callbacks, session_manager, rng, policy, false, datagram, io_buf_sz), |
72 | | m_creds(creds), |
73 | | m_info(info) |
74 | 2.39k | { |
75 | 2.39k | const auto version = datagram ? Protocol_Version::DTLS_V12 : Protocol_Version::TLS_V12; |
76 | 2.39k | Handshake_State& state = create_handshake_state(version); |
77 | 2.39k | send_client_hello(state, false, version, next_protocols); |
78 | 2.39k | } |
79 | | |
80 | | Client_Impl_12::Client_Impl_12(const Channel_Impl::Downgrade_Information& downgrade_info) : |
81 | | Channel_Impl_12(downgrade_info.callbacks, |
82 | | downgrade_info.session_manager, |
83 | | downgrade_info.rng, |
84 | | downgrade_info.policy, |
85 | | false /* is_server */, |
86 | | false /* datagram -- not supported by Botan in TLS 1.3 */, |
87 | | downgrade_info.io_buffer_size), |
88 | | m_creds(downgrade_info.creds), |
89 | | m_info(downgrade_info.server_info) |
90 | 0 | { |
91 | 0 | Handshake_State& state = create_handshake_state(Protocol_Version::TLS_V12); |
92 | |
|
93 | 0 | std::vector<uint8_t> client_hello_msg(downgrade_info.client_hello_message.begin() + 4 /* handshake header length */, |
94 | 0 | downgrade_info.client_hello_message.end()); |
95 | |
|
96 | 0 | state.client_hello(new Client_Hello_12(client_hello_msg)); |
97 | 0 | state.hash().update(downgrade_info.client_hello_message); |
98 | |
|
99 | 0 | secure_renegotiation_check(state.client_hello()); |
100 | 0 | state.set_expected_next(SERVER_HELLO); |
101 | 0 | } |
102 | | |
103 | | std::unique_ptr<Handshake_State> Client_Impl_12::new_handshake_state(std::unique_ptr<Handshake_IO> io) |
104 | 3.56k | { |
105 | 3.56k | return std::make_unique<Client_Handshake_State_12>(std::move(io), callbacks()); |
106 | 3.56k | } |
107 | | |
108 | | std::vector<X509_Certificate> |
109 | | Client_Impl_12::get_peer_cert_chain(const Handshake_State& state) const |
110 | 0 | { |
111 | 0 | const Client_Handshake_State_12& cstate = dynamic_cast<const Client_Handshake_State_12&>(state); |
112 | |
|
113 | 0 | if(cstate.is_a_resumption()) |
114 | 0 | return cstate.resume_peer_certs(); |
115 | | |
116 | 0 | if(state.server_certs()) |
117 | 0 | return state.server_certs()->cert_chain(); |
118 | 0 | return std::vector<X509_Certificate>(); |
119 | 0 | } |
120 | | |
121 | | /* |
122 | | * Send a new client hello to renegotiate |
123 | | */ |
124 | | void Client_Impl_12::initiate_handshake(Handshake_State& state, |
125 | | bool force_full_renegotiation) |
126 | 0 | { |
127 | | // we don't support TLS < 1.2 anymore and TLS 1.3 should not use this client impl |
128 | 0 | const auto version = state.version().is_datagram_protocol() |
129 | 0 | ? Protocol_Version::DTLS_V12 |
130 | 0 | : Protocol_Version::TLS_V12; |
131 | 0 | send_client_hello(state, force_full_renegotiation, version); |
132 | 0 | } |
133 | | |
134 | | void Client_Impl_12::send_client_hello(Handshake_State& state_base, |
135 | | bool force_full_renegotiation, |
136 | | Protocol_Version version, |
137 | | const std::vector<std::string>& next_protocols) |
138 | 2.39k | { |
139 | 2.39k | Client_Handshake_State_12& state = dynamic_cast<Client_Handshake_State_12&>(state_base); |
140 | | |
141 | 2.39k | if(state.version().is_datagram_protocol()) |
142 | 0 | state.set_expected_next(HELLO_VERIFY_REQUEST); // optional |
143 | 2.39k | state.set_expected_next(SERVER_HELLO); |
144 | | |
145 | 2.39k | if(!force_full_renegotiation && !m_info.empty()) |
146 | 2.39k | { |
147 | 2.39k | auto session_info = std::make_unique<Session>(); |
148 | 2.39k | if(session_manager().load_from_server_info(m_info, *session_info)) |
149 | 0 | { |
150 | | /* |
151 | | Ensure that the session protocol cipher and version are acceptable |
152 | | If not skip the resume and establish a new session |
153 | | */ |
154 | 0 | const bool exact_version = session_info->version() == version; |
155 | 0 | const bool ok_version = |
156 | 0 | (session_info->version().is_datagram_protocol() == version.is_datagram_protocol()) && |
157 | 0 | policy().acceptable_protocol_version(session_info->version()); |
158 | |
|
159 | 0 | const bool session_version_ok = policy().only_resume_with_exact_version() ? exact_version : ok_version; |
160 | |
|
161 | 0 | if(policy().acceptable_ciphersuite(session_info->ciphersuite()) && session_version_ok) |
162 | 0 | { |
163 | 0 | state.client_hello( |
164 | 0 | new Client_Hello_12(state.handshake_io(), |
165 | 0 | state.hash(), |
166 | 0 | policy(), |
167 | 0 | callbacks(), |
168 | 0 | rng(), |
169 | 0 | secure_renegotiation_data_for_client_hello(), |
170 | 0 | *session_info, |
171 | 0 | next_protocols)); |
172 | |
|
173 | 0 | state.resumed_session = std::move(session_info); |
174 | 0 | } |
175 | 0 | } |
176 | 2.39k | } |
177 | | |
178 | 2.39k | if(!state.client_hello()) // not resuming |
179 | 2.39k | { |
180 | 2.39k | Client_Hello_12::Settings client_settings(version, m_info.hostname()); |
181 | 2.39k | state.client_hello(new Client_Hello_12( |
182 | 2.39k | state.handshake_io(), |
183 | 2.39k | state.hash(), |
184 | 2.39k | policy(), |
185 | 2.39k | callbacks(), |
186 | 2.39k | rng(), |
187 | 2.39k | secure_renegotiation_data_for_client_hello(), |
188 | 2.39k | client_settings, |
189 | 2.39k | next_protocols)); |
190 | 2.39k | } |
191 | | |
192 | 2.39k | secure_renegotiation_check(state.client_hello()); |
193 | 2.39k | } |
194 | | |
195 | | namespace { |
196 | | |
197 | | bool key_usage_matches_ciphersuite(Key_Constraints usage, |
198 | | const Ciphersuite& suite) |
199 | 0 | { |
200 | 0 | if(usage == NO_CONSTRAINTS) |
201 | 0 | return true; // anything goes ... |
202 | | |
203 | 0 | if(suite.kex_method() == Kex_Algo::STATIC_RSA) |
204 | 0 | { |
205 | 0 | return (usage & KEY_ENCIPHERMENT) | (usage & DATA_ENCIPHERMENT); |
206 | 0 | } |
207 | 0 | else |
208 | 0 | { |
209 | 0 | return (usage & DIGITAL_SIGNATURE) | (usage & NON_REPUDIATION); |
210 | 0 | } |
211 | 0 | } |
212 | | |
213 | | } |
214 | | |
215 | | /* |
216 | | * Process a handshake message |
217 | | */ |
218 | | void Client_Impl_12::process_handshake_msg(const Handshake_State* active_state, |
219 | | Handshake_State& state_base, |
220 | | Handshake_Type type, |
221 | | const std::vector<uint8_t>& contents, |
222 | | bool epoch0_restart) |
223 | 1.92k | { |
224 | 1.92k | BOTAN_ASSERT_NOMSG(epoch0_restart == false); // only happens on server side |
225 | | |
226 | 1.92k | Client_Handshake_State_12& state = dynamic_cast<Client_Handshake_State_12&>(state_base); |
227 | | |
228 | 1.92k | if(type == HELLO_REQUEST && active_state) |
229 | 0 | { |
230 | 0 | Hello_Request hello_request(contents); |
231 | |
|
232 | 0 | if(state.client_hello()) |
233 | 0 | { |
234 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Cannot renegotiate during a handshake"); |
235 | 0 | } |
236 | | |
237 | 0 | if(policy().allow_server_initiated_renegotiation()) |
238 | 0 | { |
239 | 0 | if(secure_renegotiation_supported() || policy().allow_insecure_renegotiation()) |
240 | 0 | { |
241 | 0 | state.m_is_reneg = true; |
242 | 0 | initiate_handshake(state, true /* force_full_renegotiation */); |
243 | 0 | } |
244 | 0 | else |
245 | 0 | { |
246 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Client policy prohibits insecure renegotiation"); |
247 | 0 | } |
248 | 0 | } |
249 | 0 | else |
250 | 0 | { |
251 | 0 | if(policy().abort_connection_on_undesired_renegotiation()) |
252 | 0 | { |
253 | 0 | throw TLS_Exception(Alert::NO_RENEGOTIATION, "Client policy prohibits renegotiation"); |
254 | 0 | } |
255 | 0 | else |
256 | 0 | { |
257 | | // RFC 5746 section 4.2 |
258 | 0 | send_warning_alert(Alert::NO_RENEGOTIATION); |
259 | 0 | } |
260 | 0 | } |
261 | | |
262 | 0 | return; |
263 | 0 | } |
264 | | |
265 | 1.92k | state.confirm_transition_to(type); |
266 | | |
267 | 1.92k | if(type != HANDSHAKE_CCS && type != FINISHED && type != HELLO_VERIFY_REQUEST) |
268 | 1.85k | state.hash().update(state.handshake_io().format(contents, type)); |
269 | | |
270 | 1.92k | if(type == HELLO_VERIFY_REQUEST) |
271 | 0 | { |
272 | 0 | state.set_expected_next(SERVER_HELLO); |
273 | 0 | state.set_expected_next(HELLO_VERIFY_REQUEST); // might get it again |
274 | |
|
275 | 0 | Hello_Verify_Request hello_verify_request(contents); |
276 | 0 | state.hello_verify_request(hello_verify_request); |
277 | 0 | } |
278 | 1.92k | else if(type == SERVER_HELLO) |
279 | 1.85k | { |
280 | 1.85k | state.server_hello(new Server_Hello_12(contents)); |
281 | | |
282 | 1.85k | if(!state.server_hello()->legacy_version().valid()) |
283 | 89 | { |
284 | 89 | throw TLS_Exception(Alert::PROTOCOL_VERSION, |
285 | 89 | "Server replied with an invalid version"); |
286 | 89 | } |
287 | | |
288 | 1.76k | if(!state.client_hello()->offered_suite(state.server_hello()->ciphersuite())) |
289 | 30 | { |
290 | 30 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
291 | 30 | "Server replied with ciphersuite we didn't send"); |
292 | 30 | } |
293 | | |
294 | 1.73k | if(const auto suite = Ciphersuite::by_id(state.server_hello()->ciphersuite()); |
295 | 1.73k | !suite || !suite->usable_in_version(state.server_hello()->legacy_version())) |
296 | 0 | { |
297 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
298 | 0 | "Server replied using a ciphersuite not allowed in version it offered"); |
299 | 0 | } |
300 | | |
301 | 1.73k | if(Ciphersuite::is_scsv(state.server_hello()->ciphersuite())) |
302 | 0 | { |
303 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
304 | 0 | "Server replied with a signaling ciphersuite"); |
305 | 0 | } |
306 | | |
307 | 1.73k | if(state.server_hello()->compression_method() != 0) |
308 | 0 | { |
309 | 0 | throw TLS_Exception(Alert::ILLEGAL_PARAMETER, |
310 | 0 | "Server replied with non-null compression method"); |
311 | 0 | } |
312 | | |
313 | 1.73k | if(state.client_hello()->legacy_version() > state.server_hello()->legacy_version()) |
314 | 0 | { |
315 | | // check for downgrade attacks |
316 | | // |
317 | | // RFC 8446 4.1.3.: |
318 | | // TLS 1.2 clients SHOULD also check that the last 8 bytes are |
319 | | // not equal to the [magic value DOWNGRADE_TLS11] if the ServerHello |
320 | | // indicates TLS 1.1 or below. If a match is found, the client MUST |
321 | | // abort the handshake with an "illegal_parameter" alert. |
322 | | // |
323 | | // TLS 1.3 servers will still set the magic string to DOWNGRADE_TLS12. Don't abort in this case. |
324 | 0 | if(auto requested = state.server_hello()->random_signals_downgrade(); |
325 | 0 | requested.has_value() && requested.value() <= Protocol_Version::TLS_V11) |
326 | 0 | throw TLS_Exception(Alert::ILLEGAL_PARAMETER, "Downgrade attack detected"); |
327 | 0 | } |
328 | | |
329 | 1.73k | auto client_extn = state.client_hello()->extension_types(); |
330 | 1.73k | auto server_extn = state.server_hello()->extension_types(); |
331 | | |
332 | 1.73k | std::vector<Extension_Code> diff; |
333 | | |
334 | 1.73k | std::set_difference(server_extn.begin(), server_extn.end(), |
335 | 1.73k | client_extn.begin(), client_extn.end(), |
336 | 1.73k | std::back_inserter(diff)); |
337 | | |
338 | 1.73k | if(!diff.empty()) |
339 | 0 | { |
340 | | // Server sent us back an extension we did not send! |
341 | |
|
342 | 0 | std::ostringstream msg; |
343 | 0 | msg << "Server replied with unsupported extensions:"; |
344 | 0 | for(auto&& d : diff) |
345 | 0 | msg << " " << static_cast<int>(d); |
346 | 0 | throw TLS_Exception(Alert::UNSUPPORTED_EXTENSION, msg.str()); |
347 | 0 | } |
348 | | |
349 | 1.73k | if(uint16_t srtp = state.server_hello()->srtp_profile()) |
350 | 0 | { |
351 | 0 | if(!value_exists(state.client_hello()->srtp_profiles(), srtp)) |
352 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
353 | 0 | "Server replied with DTLS-SRTP alg we did not send"); |
354 | 0 | } |
355 | | |
356 | 1.73k | callbacks().tls_examine_extensions(state.server_hello()->extensions(), SERVER, Handshake_Type::SERVER_HELLO); |
357 | | |
358 | 1.73k | state.set_version(state.server_hello()->legacy_version()); |
359 | 1.73k | m_application_protocol = state.server_hello()->next_protocol(); |
360 | | |
361 | 1.73k | secure_renegotiation_check(state.server_hello()); |
362 | | |
363 | 1.73k | const bool server_returned_same_session_id = |
364 | 1.73k | !state.server_hello()->session_id().empty() && |
365 | 1.73k | (state.server_hello()->session_id() == state.client_hello()->session_id()); |
366 | | |
367 | 1.73k | if(server_returned_same_session_id) |
368 | 0 | { |
369 | | // successful resumption |
370 | 0 | BOTAN_ASSERT_NOMSG(state.resumed_session); |
371 | | |
372 | | /* |
373 | | * In this case, we offered the version used in the original |
374 | | * session, and the server must resume with the same version. |
375 | | */ |
376 | 0 | if(state.server_hello()->legacy_version() != state.client_hello()->legacy_version()) |
377 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
378 | 0 | "Server resumed session but with wrong version"); |
379 | | |
380 | 0 | if(state.server_hello()->supports_extended_master_secret() && |
381 | 0 | !state.resumed_session->supports_extended_master_secret()) |
382 | 0 | { |
383 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
384 | 0 | "Server resumed session but added extended master secret"); |
385 | 0 | } |
386 | | |
387 | 0 | if(!state.server_hello()->supports_extended_master_secret() && |
388 | 0 | state.resumed_session->supports_extended_master_secret()) |
389 | 0 | { |
390 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
391 | 0 | "Server resumed session and removed extended master secret"); |
392 | 0 | } |
393 | | |
394 | 0 | state.compute_session_keys(state.resume_master_secret()); |
395 | |
|
396 | 0 | if(state.server_hello()->supports_session_ticket()) |
397 | 0 | { |
398 | 0 | state.set_expected_next(NEW_SESSION_TICKET); |
399 | 0 | } |
400 | 0 | else |
401 | 0 | { |
402 | 0 | state.set_expected_next(HANDSHAKE_CCS); |
403 | 0 | } |
404 | 0 | } |
405 | 1.73k | else |
406 | 1.73k | { |
407 | | // new session |
408 | | |
409 | 1.73k | if(active_state) |
410 | 0 | { |
411 | | // Here we are testing things that should not change during a renegotation, |
412 | | // even if the server creates a new session. Howerver they might change |
413 | | // in a resumption scenario. |
414 | |
|
415 | 0 | if(active_state->version() != state.server_hello()->legacy_version()) |
416 | 0 | throw TLS_Exception(Alert::PROTOCOL_VERSION, |
417 | 0 | "Server changed version after renegotiation"); |
418 | | |
419 | 0 | if(state.server_hello()->supports_extended_master_secret() != |
420 | 0 | active_state->server_hello()->supports_extended_master_secret()) |
421 | 0 | { |
422 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
423 | 0 | "Server changed its mind about extended master secret"); |
424 | 0 | } |
425 | 0 | } |
426 | | |
427 | 1.73k | state.resumed_session.reset(); // non-null if we were attempting a resumption |
428 | | |
429 | 1.73k | if(state.client_hello()->legacy_version().is_datagram_protocol() != |
430 | 1.73k | state.server_hello()->legacy_version().is_datagram_protocol()) |
431 | 0 | { |
432 | 0 | throw TLS_Exception(Alert::PROTOCOL_VERSION, |
433 | 0 | "Server replied with different protocol type than we offered"); |
434 | 0 | } |
435 | | |
436 | 1.73k | if(state.version() > state.client_hello()->legacy_version()) |
437 | 0 | { |
438 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
439 | 0 | "Server replied with later version than client offered"); |
440 | 0 | } |
441 | | |
442 | 1.73k | if(state.version().major_version() == 3 && state.version().minor_version() == 0) |
443 | 0 | { |
444 | 0 | throw TLS_Exception(Alert::PROTOCOL_VERSION, |
445 | 0 | "Server attempting to negotiate SSLv3 which is not supported"); |
446 | 0 | } |
447 | | |
448 | 1.73k | if(!policy().acceptable_protocol_version(state.version())) |
449 | 0 | { |
450 | 0 | throw TLS_Exception(Alert::PROTOCOL_VERSION, |
451 | 0 | "Server version " + state.version().to_string() + |
452 | 0 | " is unacceptable by policy"); |
453 | 0 | } |
454 | | |
455 | 1.73k | if(state.ciphersuite().signature_used() || state.ciphersuite().kex_method() == Kex_Algo::STATIC_RSA) |
456 | 0 | { |
457 | 0 | state.set_expected_next(CERTIFICATE); |
458 | 0 | } |
459 | 1.73k | else if(state.ciphersuite().kex_method() == Kex_Algo::PSK) |
460 | 0 | { |
461 | | /* PSK is anonymous so no certificate/cert req message is |
462 | | ever sent. The server may or may not send a server kex, |
463 | | depending on if it has an identity hint for us. |
464 | | |
465 | | (EC)DHE_PSK always sends a server key exchange for the |
466 | | DH exchange portion, and is covered by block below |
467 | | */ |
468 | |
|
469 | 0 | state.set_expected_next(SERVER_KEX); |
470 | 0 | state.set_expected_next(SERVER_HELLO_DONE); |
471 | 0 | } |
472 | 1.73k | else if(state.ciphersuite().kex_method() != Kex_Algo::STATIC_RSA) |
473 | 0 | { |
474 | 0 | state.set_expected_next(SERVER_KEX); |
475 | 0 | } |
476 | 1.73k | else |
477 | 1.73k | { |
478 | 1.73k | state.set_expected_next(CERTIFICATE_REQUEST); // optional |
479 | 1.73k | state.set_expected_next(SERVER_HELLO_DONE); |
480 | 1.73k | } |
481 | 1.73k | } |
482 | 1.73k | } |
483 | 69 | else if(type == CERTIFICATE) |
484 | 0 | { |
485 | 0 | state.server_certs(new Certificate_12(contents, policy())); |
486 | |
|
487 | 0 | const std::vector<X509_Certificate>& server_certs = |
488 | 0 | state.server_certs()->cert_chain(); |
489 | |
|
490 | 0 | if(server_certs.empty()) |
491 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
492 | 0 | "Client: No certificates sent by server"); |
493 | | |
494 | | /* |
495 | | If the server supports certificate status messages, |
496 | | certificate verification happens after we receive the server hello done, |
497 | | in case an OCSP response was also available |
498 | | */ |
499 | | |
500 | 0 | X509_Certificate server_cert = server_certs[0]; |
501 | |
|
502 | 0 | if(active_state && active_state->server_certs()) |
503 | 0 | { |
504 | 0 | X509_Certificate current_cert = active_state->server_certs()->cert_chain().at(0); |
505 | |
|
506 | 0 | if(current_cert != server_cert) |
507 | 0 | throw TLS_Exception(Alert::BAD_CERTIFICATE, "Server certificate changed during renegotiation"); |
508 | 0 | } |
509 | | |
510 | 0 | std::unique_ptr<Public_Key> peer_key(server_cert.subject_public_key()); |
511 | |
|
512 | 0 | const std::string expected_key_type = |
513 | 0 | state.ciphersuite().signature_used() ? state.ciphersuite().sig_algo() : "RSA"; |
514 | |
|
515 | 0 | if(peer_key->algo_name() != expected_key_type) |
516 | 0 | throw TLS_Exception(Alert::ILLEGAL_PARAMETER, |
517 | 0 | "Certificate key type did not match ciphersuite"); |
518 | | |
519 | 0 | if(!key_usage_matches_ciphersuite(server_cert.constraints(), state.ciphersuite())) |
520 | 0 | throw TLS_Exception(Alert::BAD_CERTIFICATE, |
521 | 0 | "Certificate usage constraints do not allow this ciphersuite"); |
522 | | |
523 | 0 | state.server_public_key.reset(peer_key.release()); |
524 | |
|
525 | 0 | if(state.ciphersuite().kex_method() != Kex_Algo::STATIC_RSA) |
526 | 0 | { |
527 | 0 | state.set_expected_next(SERVER_KEX); |
528 | 0 | } |
529 | 0 | else |
530 | 0 | { |
531 | 0 | state.set_expected_next(CERTIFICATE_REQUEST); // optional |
532 | 0 | state.set_expected_next(SERVER_HELLO_DONE); |
533 | 0 | } |
534 | |
|
535 | 0 | if(state.server_hello()->supports_certificate_status_message()) |
536 | 0 | { |
537 | 0 | state.set_expected_next(CERTIFICATE_STATUS); // optional |
538 | 0 | } |
539 | 0 | else |
540 | 0 | { |
541 | 0 | try |
542 | 0 | { |
543 | 0 | auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-client", m_info.hostname()); |
544 | |
|
545 | 0 | callbacks().tls_verify_cert_chain(server_certs, |
546 | 0 | {}, |
547 | 0 | trusted_CAs, |
548 | 0 | Usage_Type::TLS_SERVER_AUTH, |
549 | 0 | m_info.hostname(), |
550 | 0 | policy()); |
551 | 0 | } |
552 | 0 | catch(TLS_Exception&) |
553 | 0 | { |
554 | 0 | throw; |
555 | 0 | } |
556 | 0 | catch(std::exception& e) |
557 | 0 | { |
558 | 0 | throw TLS_Exception(Alert::INTERNAL_ERROR, e.what()); |
559 | 0 | } |
560 | 0 | } |
561 | 0 | } |
562 | 69 | else if(type == CERTIFICATE_STATUS) |
563 | 0 | { |
564 | 0 | state.server_cert_status(new Certificate_Status(contents, Connection_Side::SERVER)); |
565 | |
|
566 | 0 | if(state.ciphersuite().kex_method() != Kex_Algo::STATIC_RSA) |
567 | 0 | { |
568 | 0 | state.set_expected_next(SERVER_KEX); |
569 | 0 | } |
570 | 0 | else |
571 | 0 | { |
572 | 0 | state.set_expected_next(CERTIFICATE_REQUEST); // optional |
573 | 0 | state.set_expected_next(SERVER_HELLO_DONE); |
574 | 0 | } |
575 | 0 | } |
576 | 69 | else if(type == SERVER_KEX) |
577 | 0 | { |
578 | 0 | if(state.ciphersuite().psk_ciphersuite() == false) |
579 | 0 | state.set_expected_next(CERTIFICATE_REQUEST); // optional |
580 | 0 | state.set_expected_next(SERVER_HELLO_DONE); |
581 | |
|
582 | 0 | state.server_kex( |
583 | 0 | new Server_Key_Exchange(contents, |
584 | 0 | state.ciphersuite().kex_method(), |
585 | 0 | state.ciphersuite().auth_method(), |
586 | 0 | state.version()) |
587 | 0 | ); |
588 | |
|
589 | 0 | if(state.ciphersuite().signature_used()) |
590 | 0 | { |
591 | 0 | const Public_Key& server_key = state.get_server_public_key(); |
592 | |
|
593 | 0 | if(!state.server_kex()->verify(server_key, state, policy())) |
594 | 0 | { |
595 | 0 | throw TLS_Exception(Alert::DECRYPT_ERROR, |
596 | 0 | "Bad signature on server key exchange"); |
597 | 0 | } |
598 | 0 | } |
599 | 0 | } |
600 | 69 | else if(type == CERTIFICATE_REQUEST) |
601 | 0 | { |
602 | 0 | state.set_expected_next(SERVER_HELLO_DONE); |
603 | 0 | state.cert_req(new Certificate_Request_12(contents)); |
604 | 0 | } |
605 | 69 | else if(type == SERVER_HELLO_DONE) |
606 | 0 | { |
607 | 0 | state.server_hello_done(new Server_Hello_Done(contents)); |
608 | |
|
609 | 0 | if(state.handshake_io().have_more_data()) |
610 | 0 | throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, |
611 | 0 | "Have data remaining in buffer after ServerHelloDone"); |
612 | | |
613 | | |
614 | 0 | if(state.server_certs() != nullptr && |
615 | 0 | state.server_hello()->supports_certificate_status_message()) |
616 | 0 | { |
617 | 0 | try |
618 | 0 | { |
619 | 0 | auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-client", m_info.hostname()); |
620 | |
|
621 | 0 | std::vector<std::optional<OCSP::Response>> ocsp; |
622 | 0 | if(state.server_cert_status() != nullptr) |
623 | 0 | { |
624 | 0 | ocsp.emplace_back(callbacks().tls_parse_ocsp_response(state.server_cert_status()->response())); |
625 | 0 | } |
626 | |
|
627 | 0 | callbacks().tls_verify_cert_chain(state.server_certs()->cert_chain(), |
628 | 0 | ocsp, |
629 | 0 | trusted_CAs, |
630 | 0 | Usage_Type::TLS_SERVER_AUTH, |
631 | 0 | m_info.hostname(), |
632 | 0 | policy()); |
633 | 0 | } |
634 | 0 | catch(TLS_Exception&) |
635 | 0 | { |
636 | 0 | throw; |
637 | 0 | } |
638 | 0 | catch(std::exception& e) |
639 | 0 | { |
640 | 0 | throw TLS_Exception(Alert::INTERNAL_ERROR, e.what()); |
641 | 0 | } |
642 | 0 | } |
643 | | |
644 | 0 | if(state.received_handshake_msg(CERTIFICATE_REQUEST)) |
645 | 0 | { |
646 | 0 | const auto& types = state.cert_req()->acceptable_cert_types(); |
647 | |
|
648 | 0 | std::vector<X509_Certificate> client_certs = |
649 | 0 | m_creds.find_cert_chain(types, |
650 | 0 | state.cert_req()->acceptable_CAs(), |
651 | 0 | "tls-client", |
652 | 0 | m_info.hostname()); |
653 | |
|
654 | 0 | state.client_certs(new Certificate_12(state.handshake_io(), |
655 | 0 | state.hash(), |
656 | 0 | client_certs)); |
657 | 0 | } |
658 | |
|
659 | 0 | state.client_kex( |
660 | 0 | new Client_Key_Exchange(state.handshake_io(), |
661 | 0 | state, |
662 | 0 | policy(), |
663 | 0 | m_creds, |
664 | 0 | state.server_public_key.get(), |
665 | 0 | m_info.hostname(), |
666 | 0 | rng()) |
667 | 0 | ); |
668 | |
|
669 | 0 | state.compute_session_keys(); |
670 | |
|
671 | 0 | if(state.received_handshake_msg(CERTIFICATE_REQUEST) && |
672 | 0 | !state.client_certs()->empty()) |
673 | 0 | { |
674 | 0 | Private_Key* private_key = |
675 | 0 | m_creds.private_key_for(state.client_certs()->cert_chain()[0], |
676 | 0 | "tls-client", |
677 | 0 | m_info.hostname()); |
678 | |
|
679 | 0 | state.client_verify( |
680 | 0 | new Certificate_Verify_12(state.handshake_io(), |
681 | 0 | state, |
682 | 0 | policy(), |
683 | 0 | rng(), |
684 | 0 | private_key) |
685 | 0 | ); |
686 | 0 | } |
687 | |
|
688 | 0 | state.handshake_io().send(Change_Cipher_Spec()); |
689 | |
|
690 | 0 | change_cipher_spec_writer(CLIENT); |
691 | |
|
692 | 0 | state.client_finished(new Finished_12(state.handshake_io(), state, CLIENT)); |
693 | |
|
694 | 0 | if(state.server_hello()->supports_session_ticket()) |
695 | 0 | state.set_expected_next(NEW_SESSION_TICKET); |
696 | 0 | else |
697 | 0 | state.set_expected_next(HANDSHAKE_CCS); |
698 | 0 | } |
699 | 69 | else if(type == NEW_SESSION_TICKET) |
700 | 0 | { |
701 | 0 | state.new_session_ticket(new New_Session_Ticket_12(contents)); |
702 | |
|
703 | 0 | state.set_expected_next(HANDSHAKE_CCS); |
704 | 0 | } |
705 | 69 | else if(type == HANDSHAKE_CCS) |
706 | 0 | { |
707 | 0 | state.set_expected_next(FINISHED); |
708 | |
|
709 | 0 | change_cipher_spec_reader(CLIENT); |
710 | 0 | } |
711 | 69 | else if(type == FINISHED) |
712 | 0 | { |
713 | 0 | if(state.handshake_io().have_more_data()) |
714 | 0 | throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, |
715 | 0 | "Have data remaining in buffer after Finished"); |
716 | | |
717 | 0 | state.server_finished(new Finished_12(contents)); |
718 | |
|
719 | 0 | if(!state.server_finished()->verify(state, SERVER)) |
720 | 0 | throw TLS_Exception(Alert::DECRYPT_ERROR, |
721 | 0 | "Finished message didn't verify"); |
722 | | |
723 | 0 | state.hash().update(state.handshake_io().format(contents, type)); |
724 | |
|
725 | 0 | if(!state.client_finished()) |
726 | 0 | { |
727 | | // session resume case |
728 | 0 | state.handshake_io().send(Change_Cipher_Spec()); |
729 | 0 | change_cipher_spec_writer(CLIENT); |
730 | 0 | state.client_finished(new Finished_12(state.handshake_io(), state, CLIENT)); |
731 | 0 | } |
732 | |
|
733 | 0 | std::vector<uint8_t> session_id = state.server_hello()->session_id(); |
734 | |
|
735 | 0 | const std::vector<uint8_t>& session_ticket = state.session_ticket(); |
736 | |
|
737 | 0 | if(session_id.empty() && !session_ticket.empty()) |
738 | 0 | session_id = make_hello_random(rng(), callbacks(), policy()); |
739 | |
|
740 | 0 | Session session_info( |
741 | 0 | session_id, |
742 | 0 | state.session_keys().master_secret(), |
743 | 0 | state.server_hello()->legacy_version(), |
744 | 0 | state.server_hello()->ciphersuite(), |
745 | 0 | CLIENT, |
746 | 0 | state.server_hello()->supports_extended_master_secret(), |
747 | 0 | state.server_hello()->supports_encrypt_then_mac(), |
748 | 0 | get_peer_cert_chain(state), |
749 | 0 | session_ticket, |
750 | 0 | m_info, |
751 | 0 | state.server_hello()->srtp_profile(), |
752 | 0 | callbacks().tls_current_timestamp() |
753 | 0 | ); |
754 | |
|
755 | 0 | const bool should_save = save_session(session_info); |
756 | |
|
757 | 0 | if(!session_id.empty() && state.is_a_resumption() == false) |
758 | 0 | { |
759 | 0 | if(should_save) |
760 | 0 | session_manager().save(session_info); |
761 | 0 | else |
762 | 0 | session_manager().remove_entry(session_info.session_id()); |
763 | 0 | } |
764 | |
|
765 | 0 | activate_session(); |
766 | 0 | } |
767 | 69 | else |
768 | 69 | throw Unexpected_Message("Unknown handshake message received"); |
769 | 1.92k | } |
770 | | |
771 | | } |