/src/botan/src/lib/tls/tls12/tls_server_impl_12.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * TLS Server |
3 | | * (C) 2004-2011,2012,2016 Jack Lloyd |
4 | | * 2016 Matthias Gierlings |
5 | | * |
6 | | * Botan is released under the Simplified BSD License (see license.txt) |
7 | | */ |
8 | | |
9 | | #include <botan/internal/tls_server_impl_12.h> |
10 | | |
11 | | #include <botan/ocsp.h> |
12 | | #include <botan/tls_magic.h> |
13 | | #include <botan/tls_messages.h> |
14 | | #include <botan/tls_server.h> |
15 | | #include <botan/tls_version.h> |
16 | | #include <botan/internal/stl_util.h> |
17 | | #include <botan/internal/tls_handshake_state.h> |
18 | | |
19 | | namespace Botan::TLS { |
20 | | |
21 | | class Server_Handshake_State final : public Handshake_State { |
22 | | public: |
23 | 24.8k | Server_Handshake_State(std::unique_ptr<Handshake_IO> io, Callbacks& cb) : Handshake_State(std::move(io), cb) {} |
24 | | |
25 | 6.49k | Private_Key* server_rsa_kex_key() { return m_server_rsa_kex_key.get(); } |
26 | | |
27 | 0 | void set_server_rsa_kex_key(std::shared_ptr<Private_Key> key) { m_server_rsa_kex_key = std::move(key); } |
28 | | |
29 | 21.4k | bool allow_session_resumption() const { return m_allow_session_resumption; } |
30 | | |
31 | 0 | void set_allow_session_resumption(bool allow_session_resumption) { |
32 | 0 | m_allow_session_resumption = allow_session_resumption; |
33 | 0 | } |
34 | | |
35 | 244 | const std::vector<X509_Certificate>& resume_peer_certs() const { return m_resume_peer_certs; } |
36 | | |
37 | 0 | void set_resume_certs(const std::vector<X509_Certificate>& certs) { m_resume_peer_certs = certs; } |
38 | | |
39 | 0 | void mark_as_resumption() { m_is_a_resumption = true; } |
40 | | |
41 | 245 | bool is_a_resumption() const { return m_is_a_resumption; } |
42 | | |
43 | | private: |
44 | | // Used by the server only, in case of RSA key exchange. |
45 | | std::shared_ptr<Private_Key> m_server_rsa_kex_key; |
46 | | |
47 | | /* |
48 | | * Used by the server to know if resumption should be allowed on |
49 | | * a server-initiated renegotiation |
50 | | */ |
51 | | bool m_allow_session_resumption = true; |
52 | | |
53 | | bool m_is_a_resumption = false; |
54 | | |
55 | | std::vector<X509_Certificate> m_resume_peer_certs; |
56 | | }; |
57 | | |
58 | | namespace { |
59 | | |
60 | | std::optional<Session> check_for_resume(const Session_Handle& handle_to_resume, |
61 | | Session_Manager& session_manager, |
62 | | Callbacks& cb, |
63 | | const Policy& policy, |
64 | 5.33k | const Client_Hello_12* client_hello) { |
65 | 5.33k | auto session = session_manager.retrieve(handle_to_resume, cb, policy); |
66 | 5.33k | if(!session.has_value()) { |
67 | 5.33k | return std::nullopt; |
68 | 5.33k | } |
69 | | |
70 | | // wrong version |
71 | 0 | if(client_hello->legacy_version() != session->version()) { |
72 | 0 | return std::nullopt; |
73 | 0 | } |
74 | | |
75 | | // client didn't send original ciphersuite |
76 | 0 | if(!value_exists(client_hello->ciphersuites(), session->ciphersuite_code())) { |
77 | 0 | return std::nullopt; |
78 | 0 | } |
79 | | |
80 | | // client sent a different SNI hostname |
81 | 0 | if(!client_hello->sni_hostname().empty() && client_hello->sni_hostname() != session->server_info().hostname()) { |
82 | 0 | return std::nullopt; |
83 | 0 | } |
84 | | |
85 | | // Checking extended_master_secret on resume (RFC 7627 section 5.3) |
86 | 0 | if(client_hello->supports_extended_master_secret() != session->supports_extended_master_secret()) { |
87 | 0 | if(!session->supports_extended_master_secret()) { |
88 | 0 | return std::nullopt; // force new handshake with extended master secret |
89 | 0 | } else { |
90 | | /* |
91 | | Client previously negotiated session with extended master secret, |
92 | | but has now attempted to resume without the extension: abort |
93 | | */ |
94 | 0 | throw TLS_Exception(Alert::HandshakeFailure, "Client resumed extended ms session without sending extension"); |
95 | 0 | } |
96 | 0 | } |
97 | | |
98 | | // Checking encrypt_then_mac on resume (RFC 7366 section 3.1) |
99 | 0 | if(!client_hello->supports_encrypt_then_mac() && session->supports_encrypt_then_mac()) { |
100 | | /* |
101 | | Client previously negotiated session with Encrypt-then-MAC, |
102 | | but has now attempted to resume without the extension: abort |
103 | | */ |
104 | 0 | throw TLS_Exception(Alert::HandshakeFailure, "Client resumed Encrypt-then-MAC session without sending extension"); |
105 | 0 | } |
106 | | |
107 | 0 | return session; |
108 | 0 | } |
109 | | |
110 | | /* |
111 | | * Choose which ciphersuite to use |
112 | | */ |
113 | | uint16_t choose_ciphersuite(const Policy& policy, |
114 | | Protocol_Version version, |
115 | | const std::map<std::string, std::vector<X509_Certificate>>& cert_chains, |
116 | 21.4k | const Client_Hello_12& client_hello) { |
117 | 21.4k | const bool our_choice = policy.server_uses_own_ciphersuite_preferences(); |
118 | 21.4k | const std::vector<uint16_t>& client_suites = client_hello.ciphersuites(); |
119 | 21.4k | const std::vector<uint16_t> server_suites = policy.ciphersuite_list(version); |
120 | | |
121 | 21.4k | if(server_suites.empty()) { |
122 | 0 | throw TLS_Exception(Alert::HandshakeFailure, "Policy forbids us from negotiating any ciphersuite"); |
123 | 0 | } |
124 | | |
125 | 21.4k | const bool have_shared_ecc_curve = |
126 | 21.4k | (policy.choose_key_exchange_group(client_hello.supported_ecc_curves(), {}) != Group_Params::NONE); |
127 | | |
128 | 21.4k | const bool client_supports_ffdhe_groups = !client_hello.supported_dh_groups().empty(); |
129 | | |
130 | 21.4k | const bool have_shared_dh_group = |
131 | 21.4k | (policy.choose_key_exchange_group(client_hello.supported_dh_groups(), {}) != Group_Params::NONE); |
132 | | |
133 | | /* |
134 | | Walk down one list in preference order |
135 | | */ |
136 | 21.4k | std::vector<uint16_t> pref_list = server_suites; |
137 | 21.4k | std::vector<uint16_t> other_list = client_suites; |
138 | | |
139 | 21.4k | if(!our_choice) { |
140 | 0 | std::swap(pref_list, other_list); |
141 | 0 | } |
142 | | |
143 | 1.21M | for(auto suite_id : pref_list) { |
144 | 1.21M | if(!value_exists(other_list, suite_id)) { |
145 | 1.18M | continue; |
146 | 1.18M | } |
147 | | |
148 | 22.2k | const auto suite = Ciphersuite::by_id(suite_id); |
149 | | |
150 | 22.2k | if(!suite.has_value() || !suite->valid()) { |
151 | 0 | continue; |
152 | 0 | } |
153 | | |
154 | 22.2k | if(have_shared_ecc_curve == false && suite->ecc_ciphersuite()) { |
155 | 743 | continue; |
156 | 743 | } |
157 | | |
158 | 21.5k | if(suite->kex_method() == Kex_Algo::DH && client_supports_ffdhe_groups && !have_shared_dh_group) { |
159 | 4 | continue; |
160 | 4 | } |
161 | | |
162 | | // For non-anon ciphersuites |
163 | 21.5k | if(suite->signature_used()) { |
164 | 319 | const std::string sig_algo = suite->sig_algo(); |
165 | | |
166 | | // Do we have any certificates for this sig? |
167 | 319 | if(!cert_chains.contains(sig_algo)) { |
168 | 293 | continue; |
169 | 293 | } |
170 | | |
171 | 26 | const std::vector<Signature_Scheme> allowed = policy.allowed_signature_schemes(); |
172 | | |
173 | 26 | std::vector<Signature_Scheme> client_sig_methods = client_hello.signature_schemes(); |
174 | | |
175 | | /* |
176 | | Contrary to the wording of draft-ietf-tls-md5-sha1-deprecate we do |
177 | | not enforce that clients do not offer support SHA-1 or MD5 |
178 | | signatures; we just ignore it. |
179 | | */ |
180 | 26 | bool we_support_some_hash_by_client = false; |
181 | | |
182 | 76 | for(Signature_Scheme scheme : client_sig_methods) { |
183 | 76 | if(!scheme.is_available()) { |
184 | 49 | continue; |
185 | 49 | } |
186 | | |
187 | 27 | if(scheme.algorithm_name() == suite->sig_algo() && |
188 | 27 | policy.allowed_signature_hash(scheme.hash_function_name())) { |
189 | 13 | we_support_some_hash_by_client = true; |
190 | 13 | } |
191 | 27 | } |
192 | | |
193 | 26 | if(we_support_some_hash_by_client == false) { |
194 | 17 | throw TLS_Exception(Alert::HandshakeFailure, |
195 | 17 | "Policy does not accept any hash function supported by client"); |
196 | 17 | } |
197 | 26 | } |
198 | | |
199 | 21.2k | return suite_id; |
200 | 21.5k | } |
201 | | |
202 | | // RFC 7919 Section 4. |
203 | | // If the [Supported Groups] extension is present |
204 | | // with FFDHE groups, none of the client’s offered groups are acceptable |
205 | | // by the server, and none of the client’s proposed non-FFDHE cipher |
206 | | // suites are acceptable to the server, the server MUST end the |
207 | | // connection with a fatal TLS alert of type insufficient_security(71). |
208 | 209 | if(client_supports_ffdhe_groups && !have_shared_dh_group) { |
209 | 21 | throw TLS_Exception(Alert::InsufficientSecurity, "Can't agree on a sufficiently strong ciphersuite with client"); |
210 | 21 | } |
211 | | |
212 | 188 | throw TLS_Exception(Alert::HandshakeFailure, "Can't agree on a ciphersuite with client"); |
213 | 209 | } |
214 | | |
215 | | std::map<std::string, std::vector<X509_Certificate>> get_server_certs( |
216 | 21.4k | std::string_view hostname, const std::vector<Signature_Scheme>& cert_sig_schemes, Credentials_Manager& creds) { |
217 | 21.4k | const char* cert_types[] = {"RSA", "ECDSA", "DSA", nullptr}; |
218 | | |
219 | 21.4k | std::map<std::string, std::vector<X509_Certificate>> cert_chains; |
220 | | |
221 | 85.7k | for(size_t i = 0; cert_types[i]; ++i) { |
222 | 64.2k | const std::vector<X509_Certificate> certs = creds.cert_chain_single_type( |
223 | 64.2k | cert_types[i], to_algorithm_identifiers(cert_sig_schemes), "tls-server", std::string(hostname)); |
224 | | |
225 | 64.2k | if(!certs.empty()) { |
226 | 21.4k | cert_chains[cert_types[i]] = certs; |
227 | 21.4k | } |
228 | 64.2k | } |
229 | | |
230 | 21.4k | return cert_chains; |
231 | 21.4k | } |
232 | | |
233 | | } // namespace |
234 | | |
235 | | Server_Impl_12::Server_Impl_12(const std::shared_ptr<Callbacks>& callbacks, |
236 | | const std::shared_ptr<Session_Manager>& session_manager, |
237 | | const std::shared_ptr<Credentials_Manager>& creds, |
238 | | const std::shared_ptr<const Policy>& policy, |
239 | | const std::shared_ptr<RandomNumberGenerator>& rng, |
240 | | bool is_datagram, |
241 | | size_t io_buf_sz) : |
242 | 991 | Channel_Impl_12(callbacks, session_manager, rng, policy, true, is_datagram, io_buf_sz), m_creds(creds) { |
243 | 991 | BOTAN_ASSERT_NONNULL(m_creds); |
244 | 991 | } |
245 | | |
246 | | Server_Impl_12::Server_Impl_12(const Channel_Impl::Downgrade_Information& downgrade_info) : |
247 | 3.72k | Channel_Impl_12(downgrade_info.callbacks, |
248 | 3.72k | downgrade_info.session_manager, |
249 | 3.72k | downgrade_info.rng, |
250 | 3.72k | downgrade_info.policy, |
251 | 3.72k | true /* is_server*/, |
252 | 3.72k | false /* TLS 1.3 does not support DTLS yet */, |
253 | 3.72k | downgrade_info.io_buffer_size), |
254 | 3.72k | m_creds(downgrade_info.creds) {} |
255 | | |
256 | 24.8k | std::unique_ptr<Handshake_State> Server_Impl_12::new_handshake_state(std::unique_ptr<Handshake_IO> io) { |
257 | 24.8k | auto state = std::make_unique<Server_Handshake_State>(std::move(io), callbacks()); |
258 | 24.8k | state->set_expected_next(Handshake_Type::ClientHello); |
259 | 24.8k | return state; |
260 | 24.8k | } |
261 | | |
262 | 244 | std::vector<X509_Certificate> Server_Impl_12::get_peer_cert_chain(const Handshake_State& state_base) const { |
263 | 244 | const Server_Handshake_State& state = dynamic_cast<const Server_Handshake_State&>(state_base); |
264 | 244 | if(!state.resume_peer_certs().empty()) { |
265 | 0 | return state.resume_peer_certs(); |
266 | 0 | } |
267 | | |
268 | 244 | if(state.client_certs()) { |
269 | 0 | return state.client_certs()->cert_chain(); |
270 | 0 | } |
271 | 244 | return std::vector<X509_Certificate>(); |
272 | 244 | } |
273 | | |
274 | | /* |
275 | | * Send a hello request to the client |
276 | | */ |
277 | 0 | void Server_Impl_12::initiate_handshake(Handshake_State& state, bool force_full_renegotiation) { |
278 | 0 | dynamic_cast<Server_Handshake_State&>(state).set_allow_session_resumption(!force_full_renegotiation); |
279 | |
|
280 | 0 | Hello_Request hello_req(state.handshake_io()); |
281 | 0 | } |
282 | | |
283 | | namespace { |
284 | | |
285 | | Protocol_Version select_version(const TLS::Policy& policy, |
286 | | Protocol_Version client_offer, |
287 | | Protocol_Version active_version, |
288 | 26.7k | const std::vector<Protocol_Version>& supported_versions) { |
289 | 26.7k | const bool is_datagram = client_offer.is_datagram_protocol(); |
290 | 26.7k | const bool initial_handshake = (active_version.valid() == false); |
291 | | |
292 | 26.7k | if(!supported_versions.empty()) { |
293 | 411 | if(is_datagram) { |
294 | 385 | if(policy.allow_dtls12() && value_exists(supported_versions, Protocol_Version(Protocol_Version::DTLS_V12))) { |
295 | 354 | return Protocol_Version::DTLS_V12; |
296 | 354 | } |
297 | 31 | throw TLS_Exception(Alert::ProtocolVersion, "No shared DTLS version"); |
298 | 385 | } else { |
299 | 26 | if(policy.allow_tls12() && value_exists(supported_versions, Protocol_Version(Protocol_Version::TLS_V12))) { |
300 | 8 | return Protocol_Version::TLS_V12; |
301 | 8 | } |
302 | 18 | throw TLS_Exception(Alert::ProtocolVersion, "No shared TLS version"); |
303 | 26 | } |
304 | 411 | } |
305 | | |
306 | 26.3k | if(!initial_handshake) { |
307 | | /* |
308 | | * If this is a renegotiation, and the client has offered a |
309 | | * later version than what it initially negotiated, negotiate |
310 | | * the old version. This matches OpenSSL's behavior. If the |
311 | | * client is offering a version earlier than what it initially |
312 | | * negotiated, reject as a probable attack. |
313 | | */ |
314 | 0 | if(active_version > client_offer) { |
315 | 0 | throw TLS_Exception( |
316 | 0 | Alert::ProtocolVersion, |
317 | 0 | "Client negotiated " + active_version.to_string() + " then renegotiated with " + client_offer.to_string()); |
318 | 0 | } else { |
319 | 0 | return active_version; |
320 | 0 | } |
321 | 0 | } |
322 | | |
323 | 26.3k | if(is_datagram) { |
324 | 4.90k | if(policy.allow_dtls12() && client_offer >= Protocol_Version::DTLS_V12) { |
325 | 4.89k | return Protocol_Version::DTLS_V12; |
326 | 4.89k | } |
327 | 21.4k | } else { |
328 | 21.4k | if(policy.allow_tls12() && client_offer >= Protocol_Version::TLS_V12) { |
329 | 21.4k | return Protocol_Version::TLS_V12; |
330 | 21.4k | } |
331 | 21.4k | } |
332 | | |
333 | 5 | throw TLS_Exception(Alert::ProtocolVersion, |
334 | 5 | "Client version " + client_offer.to_string() + " is unacceptable by policy"); |
335 | 26.3k | } |
336 | | } // namespace |
337 | | |
338 | | /* |
339 | | * Process a Client Hello Message |
340 | | */ |
341 | | void Server_Impl_12::process_client_hello_msg(const Handshake_State* active_state, |
342 | | Server_Handshake_State& pending_state, |
343 | | const std::vector<uint8_t>& contents, |
344 | 26.9k | bool epoch0_restart) { |
345 | 26.9k | BOTAN_ASSERT_IMPLICATION(epoch0_restart, active_state != nullptr, "Can't restart with a dead connection"); |
346 | | |
347 | 26.9k | const bool initial_handshake = epoch0_restart || !active_state; |
348 | | |
349 | 26.9k | if(initial_handshake == false && policy().allow_client_initiated_renegotiation() == false) { |
350 | 0 | if(policy().abort_connection_on_undesired_renegotiation()) { |
351 | 0 | throw TLS_Exception(Alert::NoRenegotiation, "Server policy prohibits renegotiation"); |
352 | 0 | } else { |
353 | 0 | send_warning_alert(Alert::NoRenegotiation); |
354 | 0 | } |
355 | 0 | return; |
356 | 0 | } |
357 | | |
358 | 26.9k | if(!policy().allow_insecure_renegotiation() && !(initial_handshake || secure_renegotiation_supported())) { |
359 | 0 | send_warning_alert(Alert::NoRenegotiation); |
360 | 0 | return; |
361 | 0 | } |
362 | | |
363 | 26.9k | if(pending_state.handshake_io().have_more_data()) { |
364 | 16 | throw TLS_Exception(Alert::UnexpectedMessage, "Have data remaining in buffer after ClientHello"); |
365 | 16 | } |
366 | | |
367 | 26.9k | pending_state.client_hello(new Client_Hello_12(contents)); |
368 | 26.9k | const Protocol_Version client_offer = pending_state.client_hello()->legacy_version(); |
369 | 26.9k | const bool datagram = client_offer.is_datagram_protocol(); |
370 | | |
371 | 26.9k | if(datagram) { |
372 | 5.29k | if(client_offer.major_version() == 0xFF) { |
373 | 6 | throw TLS_Exception(Alert::ProtocolVersion, "Client offered DTLS version with major version 0xFF"); |
374 | 6 | } |
375 | 21.6k | } else { |
376 | 21.6k | if(client_offer.major_version() < 3) { |
377 | 9 | throw TLS_Exception(Alert::ProtocolVersion, "Client offered TLS version with major version under 3"); |
378 | 9 | } |
379 | 21.6k | if(client_offer.major_version() == 3 && client_offer.minor_version() == 0) { |
380 | 2 | throw TLS_Exception(Alert::ProtocolVersion, "Client offered SSLv3 which is not supported"); |
381 | 2 | } |
382 | 21.6k | } |
383 | | |
384 | | /* |
385 | | * BoGo test suite expects that we will send the hello verify with a record |
386 | | * version matching the version that is eventually negotiated. This is wrong |
387 | | * but harmless, so go with it. Also doing the version negotiation step first |
388 | | * allows to immediately close the connection with an alert if the client has |
389 | | * offered a version that we are not going to negotiate anyway, instead of |
390 | | * making them first do the cookie exchange and then telling them no. |
391 | | * |
392 | | * There is no issue with amplification here, since the alert is just 2 bytes. |
393 | | */ |
394 | 26.8k | const Protocol_Version negotiated_version = |
395 | 26.8k | select_version(policy(), |
396 | 26.8k | client_offer, |
397 | 26.8k | active_state ? active_state->version() : Protocol_Version(), |
398 | 26.8k | pending_state.client_hello()->supported_versions()); |
399 | | |
400 | 26.8k | pending_state.set_version(negotiated_version); |
401 | | |
402 | 26.8k | const auto compression_methods = pending_state.client_hello()->compression_methods(); |
403 | 26.8k | if(!value_exists(compression_methods, uint8_t(0))) { |
404 | 53 | throw TLS_Exception(Alert::IllegalParameter, "Client did not offer NULL compression"); |
405 | 53 | } |
406 | | |
407 | 26.8k | if(initial_handshake && datagram) { |
408 | 5.23k | SymmetricKey cookie_secret; |
409 | | |
410 | 5.23k | try { |
411 | 5.23k | cookie_secret = m_creds->psk("tls-server", "dtls-cookie-secret", ""); |
412 | 5.23k | } catch(...) {} |
413 | | |
414 | 5.23k | if(!cookie_secret.empty()) { |
415 | 5.23k | const std::string client_identity = callbacks().tls_peer_network_identity(); |
416 | 5.23k | Hello_Verify_Request verify(pending_state.client_hello()->cookie_input_data(), client_identity, cookie_secret); |
417 | | |
418 | 5.23k | if(pending_state.client_hello()->cookie() != verify.cookie()) { |
419 | 5.23k | if(epoch0_restart) { |
420 | 0 | pending_state.handshake_io().send_under_epoch(verify, 0); |
421 | 5.23k | } else { |
422 | 5.23k | pending_state.handshake_io().send(verify); |
423 | 5.23k | } |
424 | | |
425 | 5.23k | pending_state.client_hello(static_cast<Client_Hello_12*>(nullptr)); |
426 | 5.23k | pending_state.set_expected_next(Handshake_Type::ClientHello); |
427 | 5.23k | return; |
428 | 5.23k | } |
429 | 5.23k | } else if(epoch0_restart) { |
430 | 0 | throw TLS_Exception(Alert::HandshakeFailure, "Reuse of DTLS association requires DTLS cookie secret be set"); |
431 | 0 | } |
432 | 5.23k | } |
433 | | |
434 | 21.6k | if(epoch0_restart) { |
435 | | // If we reached here then we were able to verify the cookie |
436 | 0 | reset_active_association_state(); |
437 | 0 | } |
438 | | |
439 | 21.6k | secure_renegotiation_check(pending_state.client_hello()); |
440 | | |
441 | 21.6k | callbacks().tls_examine_extensions( |
442 | 21.6k | pending_state.client_hello()->extensions(), Connection_Side::Client, Handshake_Type::ClientHello); |
443 | | |
444 | 21.6k | const auto session_handle = pending_state.client_hello()->session_handle(); |
445 | | |
446 | 21.6k | std::optional<Session> session_info; |
447 | 21.6k | if(pending_state.allow_session_resumption() && session_handle.has_value()) { |
448 | 5.33k | session_info = check_for_resume( |
449 | 5.33k | session_handle.value(), session_manager(), callbacks(), policy(), pending_state.client_hello()); |
450 | 5.33k | } |
451 | | |
452 | 21.6k | m_next_protocol = ""; |
453 | 21.6k | if(pending_state.client_hello()->supports_alpn()) { |
454 | 4.41k | m_next_protocol = callbacks().tls_server_choose_app_protocol(pending_state.client_hello()->next_protocols()); |
455 | 4.41k | } |
456 | | |
457 | 21.6k | if(session_info.has_value()) { |
458 | 0 | this->session_resume(pending_state, {session_info.value(), session_handle.value()}); |
459 | 21.6k | } else { |
460 | | // new session |
461 | 21.6k | this->session_create(pending_state); |
462 | 21.6k | } |
463 | 21.6k | } |
464 | | |
465 | | void Server_Impl_12::process_certificate_msg(Server_Handshake_State& pending_state, |
466 | 0 | const std::vector<uint8_t>& contents) { |
467 | 0 | pending_state.client_certs(new Certificate_12(contents, policy())); |
468 | | |
469 | | // CERTIFICATE_REQUIRED would make more sense but BoGo expects handshake failure alert |
470 | 0 | if(pending_state.client_certs()->empty() && policy().require_client_certificate_authentication()) { |
471 | 0 | throw TLS_Exception(Alert::HandshakeFailure, "Policy requires client send a certificate, but it did not"); |
472 | 0 | } |
473 | | |
474 | 0 | pending_state.set_expected_next(Handshake_Type::ClientKeyExchange); |
475 | 0 | } |
476 | | |
477 | | void Server_Impl_12::process_client_key_exchange_msg(Server_Handshake_State& pending_state, |
478 | 6.49k | const std::vector<uint8_t>& contents) { |
479 | 6.49k | if(pending_state.received_handshake_msg(Handshake_Type::Certificate) && !pending_state.client_certs()->empty()) { |
480 | 0 | pending_state.set_expected_next(Handshake_Type::CertificateVerify); |
481 | 6.49k | } else { |
482 | 6.49k | pending_state.set_expected_next(Handshake_Type::HandshakeCCS); |
483 | 6.49k | } |
484 | | |
485 | 6.49k | pending_state.client_kex( |
486 | 6.49k | new Client_Key_Exchange(contents, pending_state, pending_state.server_rsa_kex_key(), *m_creds, policy(), rng())); |
487 | | |
488 | 6.49k | pending_state.compute_session_keys(); |
489 | 6.49k | if(policy().allow_ssl_key_log_file()) { |
490 | | // draft-thomson-tls-keylogfile-00 Section 3.2 |
491 | | // An implementation of TLS 1.2 (and also earlier versions) use |
492 | | // the label "CLIENT_RANDOM" to identify the "master" secret for |
493 | | // the connection. |
494 | 0 | callbacks().tls_ssl_key_log_data( |
495 | 0 | "CLIENT_RANDOM", pending_state.client_hello()->random(), pending_state.session_keys().master_secret()); |
496 | 0 | } |
497 | 6.49k | } |
498 | | |
499 | 498 | void Server_Impl_12::process_change_cipher_spec_msg(Server_Handshake_State& pending_state) { |
500 | 498 | pending_state.set_expected_next(Handshake_Type::Finished); |
501 | 498 | change_cipher_spec_reader(Connection_Side::Server); |
502 | 498 | } |
503 | | |
504 | | void Server_Impl_12::process_certificate_verify_msg(Server_Handshake_State& pending_state, |
505 | | Handshake_Type type, |
506 | 0 | const std::vector<uint8_t>& contents) { |
507 | 0 | pending_state.client_verify(new Certificate_Verify_12(contents)); |
508 | |
|
509 | 0 | const std::vector<X509_Certificate>& client_certs = pending_state.client_certs()->cert_chain(); |
510 | |
|
511 | 0 | if(client_certs.empty()) { |
512 | 0 | throw TLS_Exception(Alert::DecodeError, "No client certificate sent"); |
513 | 0 | } |
514 | | |
515 | 0 | if(!client_certs[0].allowed_usage(Key_Constraints::DigitalSignature)) { |
516 | 0 | throw TLS_Exception(Alert::BadCertificate, "Client certificate does not support signing"); |
517 | 0 | } |
518 | | |
519 | 0 | const bool sig_valid = pending_state.client_verify()->verify(client_certs[0], pending_state, policy()); |
520 | |
|
521 | 0 | pending_state.hash().update(pending_state.handshake_io().format(contents, type)); |
522 | | |
523 | | /* |
524 | | * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for |
525 | | * "A handshake cryptographic operation failed, including being |
526 | | * unable to correctly verify a signature, ..." |
527 | | */ |
528 | 0 | if(!sig_valid) { |
529 | 0 | throw TLS_Exception(Alert::DecryptError, "Client cert verify failed"); |
530 | 0 | } |
531 | | |
532 | 0 | try { |
533 | 0 | const std::string sni_hostname = pending_state.client_hello()->sni_hostname(); |
534 | 0 | auto trusted_CAs = m_creds->trusted_certificate_authorities("tls-server", sni_hostname); |
535 | |
|
536 | 0 | callbacks().tls_verify_cert_chain(client_certs, |
537 | 0 | {}, // ocsp |
538 | 0 | trusted_CAs, |
539 | 0 | Usage_Type::TLS_CLIENT_AUTH, |
540 | 0 | sni_hostname, |
541 | 0 | policy()); |
542 | 0 | } catch(std::exception& e) { |
543 | 0 | throw TLS_Exception(Alert::BadCertificate, e.what()); |
544 | 0 | } |
545 | | |
546 | 0 | pending_state.set_expected_next(Handshake_Type::HandshakeCCS); |
547 | 0 | } |
548 | | |
549 | | void Server_Impl_12::process_finished_msg(Server_Handshake_State& pending_state, |
550 | | Handshake_Type type, |
551 | 247 | const std::vector<uint8_t>& contents) { |
552 | 247 | pending_state.set_expected_next(Handshake_Type::None); |
553 | | |
554 | 247 | if(pending_state.handshake_io().have_more_data()) { |
555 | 3 | throw TLS_Exception(Alert::UnexpectedMessage, "Have data remaining in buffer after Finished"); |
556 | 3 | } |
557 | | |
558 | 244 | pending_state.client_finished(new Finished_12(contents)); |
559 | | |
560 | 244 | if(!pending_state.client_finished()->verify(pending_state, Connection_Side::Client)) { |
561 | 0 | throw TLS_Exception(Alert::DecryptError, "Finished message didn't verify"); |
562 | 0 | } |
563 | | |
564 | 244 | if(!pending_state.server_finished()) { |
565 | | // already sent finished if resuming, so this is a new session |
566 | | |
567 | 244 | pending_state.hash().update(pending_state.handshake_io().format(contents, type)); |
568 | | |
569 | 244 | Session session_info(pending_state.session_keys().master_secret(), |
570 | 244 | pending_state.server_hello()->legacy_version(), |
571 | 244 | pending_state.server_hello()->ciphersuite(), |
572 | 244 | Connection_Side::Server, |
573 | 244 | pending_state.server_hello()->supports_extended_master_secret(), |
574 | 244 | pending_state.server_hello()->supports_encrypt_then_mac(), |
575 | 244 | get_peer_cert_chain(pending_state), |
576 | 244 | Server_Information(pending_state.client_hello()->sni_hostname()), |
577 | 244 | pending_state.server_hello()->srtp_profile(), |
578 | 244 | callbacks().tls_current_timestamp()); |
579 | | |
580 | | // Give the application a chance for a final veto before fully |
581 | | // establishing the connection. |
582 | 244 | callbacks().tls_session_established([&, this] { |
583 | 244 | Session_Summary summary(session_info, pending_state.is_a_resumption(), external_psk_identity()); |
584 | 244 | summary.set_session_id(pending_state.server_hello()->session_id()); |
585 | 244 | return summary; |
586 | 244 | }()); |
587 | | |
588 | 244 | if(callbacks().tls_should_persist_resumption_information(session_info)) { |
589 | 244 | auto handle = session_manager().establish(session_info, |
590 | 244 | pending_state.server_hello()->session_id(), |
591 | 244 | !pending_state.server_hello()->supports_session_ticket()); |
592 | | |
593 | 244 | if(pending_state.server_hello()->supports_session_ticket() && handle.has_value() && handle->is_ticket()) { |
594 | 0 | pending_state.new_session_ticket(new New_Session_Ticket_12(pending_state.handshake_io(), |
595 | 0 | pending_state.hash(), |
596 | 0 | handle->ticket().value(), |
597 | 0 | policy().session_ticket_lifetime())); |
598 | 0 | } |
599 | 244 | } |
600 | | |
601 | 244 | if(!pending_state.new_session_ticket() && pending_state.server_hello()->supports_session_ticket()) { |
602 | 0 | pending_state.new_session_ticket( |
603 | 0 | new New_Session_Ticket_12(pending_state.handshake_io(), pending_state.hash())); |
604 | 0 | } |
605 | | |
606 | 244 | pending_state.handshake_io().send(Change_Cipher_Spec()); |
607 | | |
608 | 244 | change_cipher_spec_writer(Connection_Side::Server); |
609 | | |
610 | 244 | pending_state.server_finished( |
611 | 244 | new Finished_12(pending_state.handshake_io(), pending_state, Connection_Side::Server)); |
612 | 244 | } |
613 | | |
614 | 244 | activate_session(); |
615 | 244 | } |
616 | | |
617 | | /* |
618 | | * Process a handshake message |
619 | | */ |
620 | | void Server_Impl_12::process_handshake_msg(const Handshake_State* active_state, |
621 | | Handshake_State& state_base, |
622 | | Handshake_Type type, |
623 | | const std::vector<uint8_t>& contents, |
624 | 34.3k | bool epoch0_restart) { |
625 | 34.3k | Server_Handshake_State& state = dynamic_cast<Server_Handshake_State&>(state_base); |
626 | 34.3k | state.confirm_transition_to(type); |
627 | | |
628 | | /* |
629 | | * The change cipher spec message isn't technically a handshake |
630 | | * message so it's not included in the hash. The finished and |
631 | | * certificate verify messages are verified based on the current |
632 | | * state of the hash *before* this message so we delay adding them |
633 | | * to the hash computation until we've processed them below. |
634 | | */ |
635 | 34.3k | if(type != Handshake_Type::HandshakeCCS && type != Handshake_Type::Finished && |
636 | 34.3k | type != Handshake_Type::CertificateVerify) { |
637 | 33.4k | state.hash().update(state.handshake_io().format(contents, type)); |
638 | 33.4k | } |
639 | | |
640 | 34.3k | switch(type) { |
641 | 26.9k | case Handshake_Type::ClientHello: |
642 | 26.9k | return this->process_client_hello_msg(active_state, state, contents, epoch0_restart); |
643 | | |
644 | 0 | case Handshake_Type::Certificate: |
645 | 0 | return this->process_certificate_msg(state, contents); |
646 | | |
647 | 6.49k | case Handshake_Type::ClientKeyExchange: |
648 | 6.49k | return this->process_client_key_exchange_msg(state, contents); |
649 | | |
650 | 0 | case Handshake_Type::CertificateVerify: |
651 | 0 | return this->process_certificate_verify_msg(state, type, contents); |
652 | | |
653 | 498 | case Handshake_Type::HandshakeCCS: |
654 | 498 | return this->process_change_cipher_spec_msg(state); |
655 | | |
656 | 247 | case Handshake_Type::Finished: |
657 | 247 | return this->process_finished_msg(state, type, contents); |
658 | | |
659 | 0 | default: |
660 | 0 | throw Unexpected_Message("Unknown handshake message received"); |
661 | 34.3k | } |
662 | 34.3k | } |
663 | | |
664 | 0 | void Server_Impl_12::session_resume(Server_Handshake_State& pending_state, const Session_with_Handle& session) { |
665 | | // Only offer a resuming client a new ticket if they didn't send one this time, |
666 | | // ie, resumed via server-side resumption. TODO: also send one if expiring soon? |
667 | |
|
668 | 0 | const bool offer_new_session_ticket = pending_state.client_hello()->supports_session_ticket() && |
669 | 0 | pending_state.client_hello()->session_ticket().empty() && |
670 | 0 | session_manager().emits_session_tickets(); |
671 | |
|
672 | 0 | pending_state.server_hello(new Server_Hello_12(pending_state.handshake_io(), |
673 | 0 | pending_state.hash(), |
674 | 0 | policy(), |
675 | 0 | callbacks(), |
676 | 0 | rng(), |
677 | 0 | secure_renegotiation_data_for_server_hello(), |
678 | 0 | *pending_state.client_hello(), |
679 | 0 | session.session, |
680 | 0 | offer_new_session_ticket, |
681 | 0 | m_next_protocol)); |
682 | |
|
683 | 0 | secure_renegotiation_check(pending_state.server_hello()); |
684 | |
|
685 | 0 | pending_state.mark_as_resumption(); |
686 | 0 | pending_state.compute_session_keys(session.session.master_secret()); |
687 | 0 | if(policy().allow_ssl_key_log_file()) { |
688 | | // draft-thomson-tls-keylogfile-00 Section 3.2 |
689 | | // An implementation of TLS 1.2 (and also earlier versions) use |
690 | | // the label "CLIENT_RANDOM" to identify the "master" secret for |
691 | | // the connection. |
692 | 0 | callbacks().tls_ssl_key_log_data( |
693 | 0 | "CLIENT_RANDOM", pending_state.client_hello()->random(), pending_state.session_keys().master_secret()); |
694 | 0 | } |
695 | 0 | pending_state.set_resume_certs(session.session.peer_certs()); |
696 | | |
697 | | // Give the application a chance for a final veto before fully |
698 | | // establishing the connection. |
699 | 0 | callbacks().tls_session_established([&, this] { |
700 | 0 | Session_Summary summary(session.session, pending_state.is_a_resumption(), external_psk_identity()); |
701 | 0 | summary.set_session_id(pending_state.server_hello()->session_id()); |
702 | 0 | if(auto ticket = session.handle.ticket()) { |
703 | 0 | summary.set_session_ticket(std::move(ticket.value())); |
704 | 0 | } |
705 | 0 | return summary; |
706 | 0 | }()); |
707 | |
|
708 | 0 | auto new_handle = [&, this]() -> std::optional<Session_Handle> { |
709 | 0 | if(!callbacks().tls_should_persist_resumption_information(session.session)) { |
710 | 0 | session_manager().remove(session.handle); |
711 | 0 | return std::nullopt; |
712 | 0 | } else { |
713 | 0 | return session_manager().establish(session.session, session.handle.id()); |
714 | 0 | } |
715 | 0 | }(); |
716 | |
|
717 | 0 | if(pending_state.server_hello()->supports_session_ticket()) { |
718 | 0 | if(new_handle.has_value() && new_handle->is_ticket()) { |
719 | 0 | pending_state.new_session_ticket(new New_Session_Ticket_12(pending_state.handshake_io(), |
720 | 0 | pending_state.hash(), |
721 | 0 | new_handle->ticket().value(), |
722 | 0 | policy().session_ticket_lifetime())); |
723 | 0 | } else { |
724 | 0 | pending_state.new_session_ticket( |
725 | 0 | new New_Session_Ticket_12(pending_state.handshake_io(), pending_state.hash())); |
726 | 0 | } |
727 | 0 | } |
728 | |
|
729 | 0 | pending_state.handshake_io().send(Change_Cipher_Spec()); |
730 | |
|
731 | 0 | change_cipher_spec_writer(Connection_Side::Server); |
732 | |
|
733 | 0 | pending_state.server_finished(new Finished_12(pending_state.handshake_io(), pending_state, Connection_Side::Server)); |
734 | 0 | pending_state.set_expected_next(Handshake_Type::HandshakeCCS); |
735 | 0 | } |
736 | | |
737 | 21.4k | void Server_Impl_12::session_create(Server_Handshake_State& pending_state) { |
738 | 21.4k | std::map<std::string, std::vector<X509_Certificate>> cert_chains; |
739 | | |
740 | 21.4k | const std::string sni_hostname = pending_state.client_hello()->sni_hostname(); |
741 | | |
742 | | // RFC 8446 1.3 |
743 | | // The "signature_algorithms_cert" extension allows a client to indicate |
744 | | // which signature algorithms it can validate in X.509 certificates. |
745 | | // |
746 | | // RFC 8446 4.2.3 |
747 | | // TLS 1.2 implementations SHOULD also process this extension. |
748 | 21.4k | const auto cert_signature_schemes = pending_state.client_hello()->certificate_signature_schemes(); |
749 | 21.4k | cert_chains = get_server_certs(sni_hostname, cert_signature_schemes, *m_creds); |
750 | | |
751 | 21.4k | if(!sni_hostname.empty() && cert_chains.empty()) { |
752 | 0 | cert_chains = get_server_certs("", cert_signature_schemes, *m_creds); |
753 | | |
754 | | /* |
755 | | * Only send the unrecognized_name alert if we couldn't |
756 | | * find any certs for the requested name but did find at |
757 | | * least one cert to use in general. That avoids sending an |
758 | | * unrecognized_name when a server is configured for purely |
759 | | * anonymous/PSK operation. |
760 | | */ |
761 | 0 | if(!cert_chains.empty()) { |
762 | 0 | send_warning_alert(Alert::UnrecognizedName); |
763 | 0 | } |
764 | 0 | } |
765 | | |
766 | 21.4k | const uint16_t ciphersuite = |
767 | 21.4k | choose_ciphersuite(policy(), pending_state.version(), cert_chains, *pending_state.client_hello()); |
768 | | |
769 | 21.4k | Server_Hello_12::Settings srv_settings(Session_ID(make_hello_random(rng(), callbacks(), policy())), |
770 | 21.4k | pending_state.version(), |
771 | 21.4k | ciphersuite, |
772 | 21.4k | session_manager().emits_session_tickets()); |
773 | | |
774 | 21.4k | pending_state.server_hello(new Server_Hello_12(pending_state.handshake_io(), |
775 | 21.4k | pending_state.hash(), |
776 | 21.4k | policy(), |
777 | 21.4k | callbacks(), |
778 | 21.4k | rng(), |
779 | 21.4k | secure_renegotiation_data_for_server_hello(), |
780 | 21.4k | *pending_state.client_hello(), |
781 | 21.4k | srv_settings, |
782 | 21.4k | m_next_protocol)); |
783 | | |
784 | 21.4k | secure_renegotiation_check(pending_state.server_hello()); |
785 | | |
786 | 21.4k | const Ciphersuite& pending_suite = pending_state.ciphersuite(); |
787 | | |
788 | 21.4k | std::shared_ptr<Private_Key> private_key; |
789 | | |
790 | 21.4k | if(pending_suite.signature_used() || pending_suite.kex_method() == Kex_Algo::STATIC_RSA) { |
791 | 75 | const std::string algo_used = pending_suite.signature_used() ? pending_suite.sig_algo() : "RSA"; |
792 | | |
793 | 75 | BOTAN_ASSERT(!cert_chains[algo_used].empty(), "Attempting to send empty certificate chain"); |
794 | | |
795 | 75 | pending_state.server_certs( |
796 | 75 | new Certificate_12(pending_state.handshake_io(), pending_state.hash(), cert_chains[algo_used])); |
797 | | |
798 | 75 | if(pending_state.client_hello()->supports_cert_status_message() && pending_state.is_a_resumption() == false) { |
799 | 1 | auto* csr = pending_state.client_hello()->extensions().get<Certificate_Status_Request>(); |
800 | | // csr is non-null if client_hello()->supports_cert_status_message() |
801 | 1 | BOTAN_ASSERT_NOMSG(csr != nullptr); |
802 | 1 | const auto resp_bytes = callbacks().tls_provide_cert_status(cert_chains[algo_used], *csr); |
803 | 1 | if(!resp_bytes.empty()) { |
804 | 0 | pending_state.server_cert_status( |
805 | 0 | new Certificate_Status(pending_state.handshake_io(), pending_state.hash(), resp_bytes)); |
806 | 0 | } |
807 | 1 | } |
808 | | |
809 | 75 | private_key = m_creds->private_key_for(pending_state.server_certs()->cert_chain()[0], "tls-server", sni_hostname); |
810 | | |
811 | 75 | if(!private_key) { |
812 | 9 | throw Internal_Error("No private key located for associated server cert"); |
813 | 9 | } |
814 | 75 | } |
815 | | |
816 | 21.4k | if(pending_suite.kex_method() == Kex_Algo::STATIC_RSA) { |
817 | 0 | pending_state.set_server_rsa_kex_key(private_key); |
818 | 21.4k | } else { |
819 | 21.4k | pending_state.server_kex(new Server_Key_Exchange( |
820 | 21.4k | pending_state.handshake_io(), pending_state, policy(), *m_creds, rng(), private_key.get())); |
821 | 21.4k | } |
822 | | |
823 | 21.4k | auto trusted_CAs = m_creds->trusted_certificate_authorities("tls-server", sni_hostname); |
824 | | |
825 | 21.4k | std::vector<X509_DN> client_auth_CAs; |
826 | | |
827 | 21.4k | for(auto* store : trusted_CAs) { |
828 | 0 | auto subjects = store->all_subjects(); |
829 | 0 | client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end()); |
830 | 0 | } |
831 | | |
832 | 21.4k | const bool request_cert = (client_auth_CAs.empty() == false) || policy().request_client_certificate_authentication(); |
833 | | |
834 | 21.4k | if(request_cert && pending_state.ciphersuite().signature_used()) { |
835 | 0 | pending_state.cert_req( |
836 | 0 | new Certificate_Request_12(pending_state.handshake_io(), pending_state.hash(), policy(), client_auth_CAs)); |
837 | | |
838 | | /* |
839 | | SSLv3 allowed clients to skip the Certificate message entirely |
840 | | if they wanted. In TLS v1.0 and later clients must send a |
841 | | (possibly empty) Certificate message |
842 | | */ |
843 | 0 | pending_state.set_expected_next(Handshake_Type::Certificate); |
844 | 21.4k | } else { |
845 | 21.4k | pending_state.set_expected_next(Handshake_Type::ClientKeyExchange); |
846 | 21.4k | } |
847 | | |
848 | 21.4k | pending_state.server_hello_done(new Server_Hello_Done(pending_state.handshake_io(), pending_state.hash())); |
849 | 21.4k | } |
850 | | } // namespace Botan::TLS |