/src/botan/src/lib/tls/tls_server.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/tls_server.h> |
10 | | #include <botan/tls_messages.h> |
11 | | #include <botan/internal/tls_handshake_state.h> |
12 | | #include <botan/internal/stl_util.h> |
13 | | #include <botan/tls_magic.h> |
14 | | |
15 | | namespace Botan { |
16 | | |
17 | | namespace TLS { |
18 | | |
19 | | class Server_Handshake_State final : public Handshake_State |
20 | | { |
21 | | public: |
22 | | Server_Handshake_State(Handshake_IO* io, Callbacks& cb) |
23 | 31.1k | : Handshake_State(io, cb) {} |
24 | | |
25 | 13.4k | Private_Key* server_rsa_kex_key() { return m_server_rsa_kex_key; } |
26 | | void set_server_rsa_kex_key(Private_Key* key) |
27 | 0 | { m_server_rsa_kex_key = key; } |
28 | | |
29 | | bool allow_session_resumption() const |
30 | 23.0k | { return m_allow_session_resumption; } |
31 | | void set_allow_session_resumption(bool allow_session_resumption) |
32 | 0 | { m_allow_session_resumption = allow_session_resumption; } |
33 | | |
34 | | const std::vector<X509_Certificate>& resume_peer_certs() const |
35 | 378 | { return m_resume_peer_certs; } |
36 | | |
37 | | void set_resume_certs(const std::vector<X509_Certificate>& certs) |
38 | 0 | { m_resume_peer_certs = certs; } |
39 | | |
40 | 0 | void mark_as_resumption() { m_is_a_resumption = true; } |
41 | | |
42 | 2 | bool is_a_resumption() const { return m_is_a_resumption; } |
43 | | |
44 | | private: |
45 | | // Used by the server only, in case of RSA key exchange. Not owned |
46 | | Private_Key* m_server_rsa_kex_key = nullptr; |
47 | | |
48 | | /* |
49 | | * Used by the server to know if resumption should be allowed on |
50 | | * a server-initiated renegotiation |
51 | | */ |
52 | | bool m_allow_session_resumption = true; |
53 | | |
54 | | bool m_is_a_resumption = false; |
55 | | |
56 | | std::vector<X509_Certificate> m_resume_peer_certs; |
57 | | }; |
58 | | |
59 | | namespace { |
60 | | |
61 | | bool check_for_resume(Session& session_info, |
62 | | Session_Manager& session_manager, |
63 | | Credentials_Manager& credentials, |
64 | | const Client_Hello* client_hello, |
65 | | std::chrono::seconds session_ticket_lifetime) |
66 | 23.0k | { |
67 | 23.0k | const std::vector<uint8_t>& client_session_id = client_hello->session_id(); |
68 | 23.0k | const std::vector<uint8_t>& session_ticket = client_hello->session_ticket(); |
69 | 23.0k | |
70 | 23.0k | if(session_ticket.empty()) |
71 | 22.1k | { |
72 | 22.1k | if(client_session_id.empty()) // not resuming |
73 | 22.0k | return false; |
74 | 130 | |
75 | 130 | // not found |
76 | 130 | if(!session_manager.load_from_session_id(client_session_id, session_info)) |
77 | 130 | return false; |
78 | 824 | } |
79 | 824 | else |
80 | 824 | { |
81 | 824 | // If a session ticket was sent, ignore client session ID |
82 | 824 | try |
83 | 824 | { |
84 | 824 | session_info = Session::decrypt( |
85 | 824 | session_ticket, |
86 | 824 | credentials.psk("tls-server", "session-ticket", "")); |
87 | 824 | |
88 | 824 | if(session_ticket_lifetime != std::chrono::seconds(0) && |
89 | 824 | session_info.session_age() > session_ticket_lifetime) |
90 | 0 | return false; // ticket has expired |
91 | 824 | } |
92 | 824 | catch(...) |
93 | 824 | { |
94 | 824 | return false; |
95 | 824 | } |
96 | 0 | } |
97 | 0 | |
98 | 0 | // wrong version |
99 | 0 | if(client_hello->version() != session_info.version()) |
100 | 0 | return false; |
101 | 0 | |
102 | 0 | // client didn't send original ciphersuite |
103 | 0 | if(!value_exists(client_hello->ciphersuites(), |
104 | 0 | session_info.ciphersuite_code())) |
105 | 0 | return false; |
106 | 0 | |
107 | 0 | #if defined(BOTAN_HAS_SRP6) |
108 | 0 | // client sent a different SRP identity |
109 | 0 | if(client_hello->srp_identifier() != "") |
110 | 0 | { |
111 | 0 | if(client_hello->srp_identifier() != session_info.srp_identifier()) |
112 | 0 | return false; |
113 | 0 | } |
114 | 0 | #endif |
115 | 0 | |
116 | 0 | // client sent a different SNI hostname |
117 | 0 | if(client_hello->sni_hostname() != "") |
118 | 0 | { |
119 | 0 | if(client_hello->sni_hostname() != session_info.server_info().hostname()) |
120 | 0 | return false; |
121 | 0 | } |
122 | 0 | |
123 | 0 | // Checking extended_master_secret on resume (RFC 7627 section 5.3) |
124 | 0 | if(client_hello->supports_extended_master_secret() != session_info.supports_extended_master_secret()) |
125 | 0 | { |
126 | 0 | if(!session_info.supports_extended_master_secret()) |
127 | 0 | { |
128 | 0 | return false; // force new handshake with extended master secret |
129 | 0 | } |
130 | 0 | else |
131 | 0 | { |
132 | 0 | /* |
133 | 0 | Client previously negotiated session with extended master secret, |
134 | 0 | but has now attempted to resume without the extension: abort |
135 | 0 | */ |
136 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
137 | 0 | "Client resumed extended ms session without sending extension"); |
138 | 0 | } |
139 | 0 | } |
140 | 0 | |
141 | 0 | // Checking encrypt_then_mac on resume (RFC 7366 section 3.1) |
142 | 0 | if(!client_hello->supports_encrypt_then_mac() && session_info.supports_encrypt_then_mac()) |
143 | 0 | { |
144 | 0 | /* |
145 | 0 | Client previously negotiated session with Encrypt-then-MAC, |
146 | 0 | but has now attempted to resume without the extension: abort |
147 | 0 | */ |
148 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
149 | 0 | "Client resumed Encrypt-then-MAC session without sending extension"); |
150 | 0 | } |
151 | 0 | |
152 | 0 | return true; |
153 | 0 | } |
154 | | |
155 | | /* |
156 | | * Choose which ciphersuite to use |
157 | | */ |
158 | | uint16_t choose_ciphersuite( |
159 | | const Policy& policy, |
160 | | Protocol_Version version, |
161 | | Credentials_Manager& creds, |
162 | | const std::map<std::string, std::vector<X509_Certificate>>& cert_chains, |
163 | | const Client_Hello& client_hello) |
164 | 23.0k | { |
165 | 23.0k | const bool our_choice = policy.server_uses_own_ciphersuite_preferences(); |
166 | 23.0k | const bool have_srp = creds.attempt_srp("tls-server", client_hello.sni_hostname()); |
167 | 23.0k | const std::vector<uint16_t> client_suites = client_hello.ciphersuites(); |
168 | 23.0k | const std::vector<uint16_t> server_suites = policy.ciphersuite_list(version, have_srp); |
169 | 23.0k | |
170 | 23.0k | if(server_suites.empty()) |
171 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
172 | 0 | "Policy forbids us from negotiating any ciphersuite"); |
173 | 23.0k | |
174 | 23.0k | const bool have_shared_ecc_curve = |
175 | 23.0k | (policy.choose_key_exchange_group(client_hello.supported_ecc_curves()) != Group_Params::NONE); |
176 | 23.0k | |
177 | 23.0k | /* |
178 | 23.0k | Walk down one list in preference order |
179 | 23.0k | */ |
180 | 23.0k | std::vector<uint16_t> pref_list = server_suites; |
181 | 23.0k | std::vector<uint16_t> other_list = client_suites; |
182 | 23.0k | |
183 | 23.0k | if(!our_choice) |
184 | 0 | std::swap(pref_list, other_list); |
185 | 23.0k | |
186 | 23.0k | for(auto suite_id : pref_list) |
187 | 2.48M | { |
188 | 2.48M | if(!value_exists(other_list, suite_id)) |
189 | 2.46M | continue; |
190 | 23.4k | |
191 | 23.4k | const Ciphersuite suite = Ciphersuite::by_id(suite_id); |
192 | 23.4k | |
193 | 23.4k | if(suite.valid() == false) |
194 | 0 | { |
195 | 0 | continue; |
196 | 0 | } |
197 | 23.4k | |
198 | 23.4k | if(have_shared_ecc_curve == false && suite.ecc_ciphersuite()) |
199 | 46 | { |
200 | 46 | continue; |
201 | 46 | } |
202 | 23.4k | |
203 | 23.4k | // For non-anon ciphersuites |
204 | 23.4k | if(suite.signature_used()) |
205 | 733 | { |
206 | 733 | const std::string sig_algo = suite.sig_algo(); |
207 | 733 | |
208 | 733 | // Do we have any certificates for this sig? |
209 | 733 | if(cert_chains.count(sig_algo) == 0) |
210 | 580 | { |
211 | 580 | continue; |
212 | 580 | } |
213 | 153 | |
214 | 153 | if(version.supports_negotiable_signature_algorithms()) |
215 | 153 | { |
216 | 153 | const std::vector<Signature_Scheme> allowed = |
217 | 153 | policy.allowed_signature_schemes(); |
218 | 153 | |
219 | 153 | std::vector<Signature_Scheme> client_sig_methods = |
220 | 153 | client_hello.signature_schemes(); |
221 | 153 | |
222 | 153 | if(client_sig_methods.empty()) |
223 | 38 | { |
224 | 38 | // If empty, then implicit SHA-1 (TLS v1.2 rules) |
225 | 38 | client_sig_methods.push_back(Signature_Scheme::RSA_PKCS1_SHA1); |
226 | 38 | client_sig_methods.push_back(Signature_Scheme::ECDSA_SHA1); |
227 | 38 | client_sig_methods.push_back(Signature_Scheme::DSA_SHA1); |
228 | 38 | } |
229 | 153 | |
230 | 153 | bool we_support_some_hash_by_client = false; |
231 | 153 | |
232 | 153 | for(Signature_Scheme scheme : client_sig_methods) |
233 | 6.91k | { |
234 | 6.91k | if(signature_scheme_is_known(scheme) == false) |
235 | 4.67k | continue; |
236 | 2.24k | |
237 | 2.24k | if(signature_algorithm_of_scheme(scheme) == suite.sig_algo() && |
238 | 2.24k | policy.allowed_signature_hash(hash_function_of_scheme(scheme))) |
239 | 507 | { |
240 | 507 | we_support_some_hash_by_client = true; |
241 | 507 | } |
242 | 2.24k | } |
243 | 153 | |
244 | 153 | if(we_support_some_hash_by_client == false) |
245 | 91 | { |
246 | 91 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
247 | 91 | "Policy does not accept any hash function supported by client"); |
248 | 91 | } |
249 | 22.7k | } |
250 | 153 | } |
251 | 22.7k | |
252 | 22.7k | #if defined(BOTAN_HAS_SRP6) |
253 | 22.7k | /* |
254 | 22.7k | The client may offer SRP cipher suites in the hello message but |
255 | 22.7k | omit the SRP extension. If the server would like to select an |
256 | 22.7k | SRP cipher suite in this case, the server SHOULD return a fatal |
257 | 22.7k | "unknown_psk_identity" alert immediately after processing the |
258 | 22.7k | client hello message. |
259 | 22.7k | - RFC 5054 section 2.5.1.2 |
260 | 22.7k | */ |
261 | 22.7k | if(suite.kex_method() == Kex_Algo::SRP_SHA && client_hello.srp_identifier() == "") |
262 | 0 | throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY, |
263 | 0 | "Client wanted SRP but did not send username"); |
264 | 22.7k | #endif |
265 | 22.7k | |
266 | 22.7k | return suite_id; |
267 | 22.7k | } |
268 | 23.0k | |
269 | 23.0k | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, |
270 | 150 | "Can't agree on a ciphersuite with client"); |
271 | 23.0k | } |
272 | | |
273 | | std::map<std::string, std::vector<X509_Certificate>> |
274 | | get_server_certs(const std::string& hostname, |
275 | | Credentials_Manager& creds) |
276 | 23.0k | { |
277 | 23.0k | const char* cert_types[] = { "RSA", "ECDSA", "DSA", nullptr }; |
278 | 23.0k | |
279 | 23.0k | std::map<std::string, std::vector<X509_Certificate>> cert_chains; |
280 | 23.0k | |
281 | 92.0k | for(size_t i = 0; cert_types[i]; ++i) |
282 | 69.0k | { |
283 | 69.0k | const std::vector<X509_Certificate> certs = |
284 | 69.0k | creds.cert_chain_single_type(cert_types[i], "tls-server", hostname); |
285 | 69.0k | |
286 | 69.0k | if(!certs.empty()) |
287 | 23.0k | cert_chains[cert_types[i]] = certs; |
288 | 69.0k | } |
289 | 23.0k | |
290 | 23.0k | return cert_chains; |
291 | 23.0k | } |
292 | | |
293 | | } |
294 | | |
295 | | /* |
296 | | * TLS Server Constructor |
297 | | */ |
298 | | Server::Server(Callbacks& callbacks, |
299 | | Session_Manager& session_manager, |
300 | | Credentials_Manager& creds, |
301 | | const Policy& policy, |
302 | | RandomNumberGenerator& rng, |
303 | | bool is_datagram, |
304 | | size_t io_buf_sz) : |
305 | | Channel(callbacks, session_manager, rng, policy, |
306 | | true, is_datagram, io_buf_sz), |
307 | | m_creds(creds) |
308 | 4.95k | { |
309 | 4.95k | } |
310 | | |
311 | | Server::Server(output_fn output, |
312 | | data_cb got_data_cb, |
313 | | alert_cb recv_alert_cb, |
314 | | handshake_cb hs_cb, |
315 | | Session_Manager& session_manager, |
316 | | Credentials_Manager& creds, |
317 | | const Policy& policy, |
318 | | RandomNumberGenerator& rng, |
319 | | next_protocol_fn next_proto, |
320 | | bool is_datagram, |
321 | | size_t io_buf_sz) : |
322 | | Channel(output, got_data_cb, recv_alert_cb, hs_cb, |
323 | | Channel::handshake_msg_cb(), session_manager, |
324 | | rng, policy, true, is_datagram, io_buf_sz), |
325 | | m_creds(creds), |
326 | | m_choose_next_protocol(next_proto) |
327 | 0 | { |
328 | 0 | } |
329 | | |
330 | | Server::Server(output_fn output, |
331 | | data_cb got_data_cb, |
332 | | alert_cb recv_alert_cb, |
333 | | handshake_cb hs_cb, |
334 | | handshake_msg_cb hs_msg_cb, |
335 | | Session_Manager& session_manager, |
336 | | Credentials_Manager& creds, |
337 | | const Policy& policy, |
338 | | RandomNumberGenerator& rng, |
339 | | next_protocol_fn next_proto, |
340 | | bool is_datagram) : |
341 | | Channel(output, got_data_cb, recv_alert_cb, hs_cb, hs_msg_cb, |
342 | | session_manager, rng, policy, true, is_datagram), |
343 | | m_creds(creds), |
344 | | m_choose_next_protocol(next_proto) |
345 | 0 | { |
346 | 0 | } |
347 | | |
348 | | Handshake_State* Server::new_handshake_state(Handshake_IO* io) |
349 | 31.1k | { |
350 | 31.1k | std::unique_ptr<Handshake_State> state(new Server_Handshake_State(io, callbacks())); |
351 | 31.1k | |
352 | 31.1k | state->set_expected_next(CLIENT_HELLO); |
353 | 31.1k | return state.release(); |
354 | 31.1k | } |
355 | | |
356 | | std::vector<X509_Certificate> |
357 | | Server::get_peer_cert_chain(const Handshake_State& state_base) const |
358 | 378 | { |
359 | 378 | const Server_Handshake_State& state = dynamic_cast<const Server_Handshake_State&>(state_base); |
360 | 378 | if(state.resume_peer_certs().size() > 0) |
361 | 0 | return state.resume_peer_certs(); |
362 | 378 | |
363 | 378 | if(state.client_certs()) |
364 | 0 | return state.client_certs()->cert_chain(); |
365 | 378 | return std::vector<X509_Certificate>(); |
366 | 378 | } |
367 | | |
368 | | /* |
369 | | * Send a hello request to the client |
370 | | */ |
371 | | void Server::initiate_handshake(Handshake_State& state, |
372 | | bool force_full_renegotiation) |
373 | 0 | { |
374 | 0 | dynamic_cast<Server_Handshake_State&>(state). |
375 | 0 | set_allow_session_resumption(!force_full_renegotiation); |
376 | 0 |
|
377 | 0 | Hello_Request hello_req(state.handshake_io()); |
378 | 0 | } |
379 | | |
380 | | namespace { |
381 | | |
382 | | Protocol_Version select_version(const Botan::TLS::Policy& policy, |
383 | | Protocol_Version client_offer, |
384 | | Protocol_Version active_version, |
385 | | bool is_fallback, |
386 | | const std::vector<Protocol_Version>& supported_versions) |
387 | 29.8k | { |
388 | 29.8k | const bool is_datagram = client_offer.is_datagram_protocol(); |
389 | 29.8k | const bool initial_handshake = (active_version.valid() == false); |
390 | 29.8k | |
391 | 29.8k | const Protocol_Version latest_supported = policy.latest_supported_version(is_datagram); |
392 | 29.8k | |
393 | 29.8k | if(is_fallback) |
394 | 129 | { |
395 | 129 | if(latest_supported > client_offer) |
396 | 1 | throw TLS_Exception(Alert::INAPPROPRIATE_FALLBACK, |
397 | 1 | "Client signalled fallback SCSV, possible attack"); |
398 | 29.8k | } |
399 | 29.8k | |
400 | 29.8k | if(supported_versions.size() > 0) |
401 | 9 | { |
402 | 9 | if(is_datagram) |
403 | 0 | { |
404 | 0 | if(policy.allow_dtls12() && value_exists(supported_versions, Protocol_Version(Protocol_Version::DTLS_V12))) |
405 | 0 | return Protocol_Version::DTLS_V12; |
406 | 0 | #if defined(BOTAN_HAS_TLS_V10) |
407 | 0 | if(policy.allow_dtls10() && value_exists(supported_versions, Protocol_Version(Protocol_Version::DTLS_V10))) |
408 | 0 | return Protocol_Version::DTLS_V10; |
409 | 0 | #endif |
410 | 0 | throw TLS_Exception(Alert::PROTOCOL_VERSION, "No shared DTLS version"); |
411 | 0 | } |
412 | 9 | else |
413 | 9 | { |
414 | 9 | if(policy.allow_tls12() && value_exists(supported_versions, Protocol_Version(Protocol_Version::TLS_V12))) |
415 | 8 | return Protocol_Version::TLS_V12; |
416 | 1 | #if defined(BOTAN_HAS_TLS_V10) |
417 | 1 | if(policy.allow_tls11() && value_exists(supported_versions, Protocol_Version(Protocol_Version::TLS_V11))) |
418 | 0 | return Protocol_Version::TLS_V11; |
419 | 1 | if(policy.allow_tls10() && value_exists(supported_versions, Protocol_Version(Protocol_Version::TLS_V10))) |
420 | 0 | return Protocol_Version::TLS_V10; |
421 | 1 | #endif |
422 | 1 | throw TLS_Exception(Alert::PROTOCOL_VERSION, "No shared TLS version"); |
423 | 1 | } |
424 | 9 | } |
425 | 29.8k | |
426 | 29.8k | const bool client_offer_acceptable = |
427 | 29.8k | client_offer.known_version() && policy.acceptable_protocol_version(client_offer); |
428 | 29.8k | |
429 | 29.8k | if(!initial_handshake) |
430 | 0 | { |
431 | 0 | /* |
432 | 0 | * If this is a renegotiation, and the client has offered a |
433 | 0 | * later version than what it initially negotiated, negotiate |
434 | 0 | * the old version. This matches OpenSSL's behavior. If the |
435 | 0 | * client is offering a version earlier than what it initially |
436 | 0 | * negotiated, reject as a probable attack. |
437 | 0 | */ |
438 | 0 | if(active_version > client_offer) |
439 | 0 | { |
440 | 0 | throw TLS_Exception(Alert::PROTOCOL_VERSION, |
441 | 0 | "Client negotiated " + |
442 | 0 | active_version.to_string() + |
443 | 0 | " then renegotiated with " + |
444 | 0 | client_offer.to_string()); |
445 | 0 | } |
446 | 0 | else |
447 | 0 | { |
448 | 0 | return active_version; |
449 | 0 | } |
450 | 29.8k | } |
451 | 29.8k | else if(client_offer_acceptable) |
452 | 6.52k | { |
453 | 6.52k | return client_offer; |
454 | 6.52k | } |
455 | 23.2k | else if(!client_offer.known_version() || client_offer > latest_supported) |
456 | 23.2k | { |
457 | 23.2k | /* |
458 | 23.2k | The client offered some version newer than the latest we |
459 | 23.2k | support. Offer them the best we know. |
460 | 23.2k | */ |
461 | 23.2k | return latest_supported; |
462 | 23.2k | } |
463 | 6 | else |
464 | 6 | { |
465 | 6 | throw TLS_Exception(Alert::PROTOCOL_VERSION, |
466 | 6 | "Client version " + client_offer.to_string() + |
467 | 6 | " is unacceptable by policy"); |
468 | 6 | } |
469 | 29.8k | } |
470 | | |
471 | | } |
472 | | |
473 | | /* |
474 | | * Process a CLIENT HELLO Message |
475 | | */ |
476 | | void Server::process_client_hello_msg(const Handshake_State* active_state, |
477 | | Server_Handshake_State& pending_state, |
478 | | const std::vector<uint8_t>& contents, |
479 | | bool epoch0_restart) |
480 | 30.4k | { |
481 | 30.4k | BOTAN_ASSERT_IMPLICATION(epoch0_restart, active_state != nullptr, "Can't restart with a dead connection"); |
482 | 30.4k | |
483 | 30.4k | const bool initial_handshake = epoch0_restart || !active_state; |
484 | 30.4k | |
485 | 30.4k | if(initial_handshake == false && policy().allow_client_initiated_renegotiation() == false) |
486 | 0 | { |
487 | 0 | if(policy().abort_connection_on_undesired_renegotiation()) |
488 | 0 | throw TLS_Exception(Alert::NO_RENEGOTIATION, "Server policy prohibits renegotiation"); |
489 | 0 | else |
490 | 0 | send_warning_alert(Alert::NO_RENEGOTIATION); |
491 | 0 | return; |
492 | 30.4k | } |
493 | 30.4k | |
494 | 30.4k | if(!policy().allow_insecure_renegotiation() && |
495 | 30.4k | !(initial_handshake || secure_renegotiation_supported())) |
496 | 0 | { |
497 | 0 | send_warning_alert(Alert::NO_RENEGOTIATION); |
498 | 0 | return; |
499 | 0 | } |
500 | 30.4k | |
501 | 30.4k | pending_state.client_hello(new Client_Hello(contents)); |
502 | 30.4k | const Protocol_Version client_offer = pending_state.client_hello()->version(); |
503 | 30.4k | const bool datagram = client_offer.is_datagram_protocol(); |
504 | 30.4k | |
505 | 30.4k | if(datagram) |
506 | 6.76k | { |
507 | 6.76k | if(client_offer.major_version() == 0xFF) |
508 | 3 | throw TLS_Exception(Alert::PROTOCOL_VERSION, "Client offered DTLS version with major version 0xFF"); |
509 | 23.7k | } |
510 | 23.7k | else |
511 | 23.7k | { |
512 | 23.7k | if(client_offer.major_version() < 3) |
513 | 6 | throw TLS_Exception(Alert::PROTOCOL_VERSION, "Client offered TLS version with major version under 3"); |
514 | 23.7k | if(client_offer.major_version() == 3 && client_offer.minor_version() == 0) |
515 | 1 | throw TLS_Exception(Alert::PROTOCOL_VERSION, "SSLv3 is not supported"); |
516 | 30.4k | } |
517 | 30.4k | |
518 | 30.4k | /* |
519 | 30.4k | * BoGo test suite expects that we will send the hello verify with a record |
520 | 30.4k | * version matching the version that is eventually negotiated. This is wrong |
521 | 30.4k | * but harmless, so go with it. Also doing the version negotiation step first |
522 | 30.4k | * allows to immediately close the connection with an alert if the client has |
523 | 30.4k | * offered a version that we are not going to negotiate anyway, instead of |
524 | 30.4k | * making them first do the cookie exchange and then telling them no. |
525 | 30.4k | * |
526 | 30.4k | * There is no issue with amplification here, since the alert is just 2 bytes. |
527 | 30.4k | */ |
528 | 30.4k | const Protocol_Version negotiated_version = |
529 | 30.4k | select_version(policy(), client_offer, |
530 | 30.4k | active_state ? active_state->version() : Protocol_Version(), |
531 | 30.4k | pending_state.client_hello()->sent_fallback_scsv(), |
532 | 30.4k | pending_state.client_hello()->supported_versions()); |
533 | 30.4k | |
534 | 30.4k | pending_state.set_version(negotiated_version); |
535 | 30.4k | |
536 | 30.4k | const auto compression_methods = pending_state.client_hello()->compression_methods(); |
537 | 30.4k | if(!value_exists(compression_methods, uint8_t(0))) |
538 | 37 | throw TLS_Exception(Alert::ILLEGAL_PARAMETER, "Client did not offer NULL compression"); |
539 | 30.4k | |
540 | 30.4k | if(initial_handshake && datagram) |
541 | 6.75k | { |
542 | 6.75k | SymmetricKey cookie_secret; |
543 | 6.75k | |
544 | 6.75k | try |
545 | 6.75k | { |
546 | 6.75k | cookie_secret = m_creds.psk("tls-server", "dtls-cookie-secret", ""); |
547 | 6.75k | } |
548 | 6.75k | catch(...) {} |
549 | 6.75k | |
550 | 6.75k | if(cookie_secret.size() > 0) |
551 | 6.75k | { |
552 | 6.75k | const std::string client_identity = callbacks().tls_peer_network_identity(); |
553 | 6.75k | Hello_Verify_Request verify(pending_state.client_hello()->cookie_input_data(), client_identity, cookie_secret); |
554 | 6.75k | |
555 | 6.75k | if(pending_state.client_hello()->cookie() != verify.cookie()) |
556 | 6.75k | { |
557 | 6.75k | if(epoch0_restart) |
558 | 0 | pending_state.handshake_io().send_under_epoch(verify, 0); |
559 | 6.75k | else |
560 | 6.75k | pending_state.handshake_io().send(verify); |
561 | 6.75k | |
562 | 6.75k | pending_state.client_hello(nullptr); |
563 | 6.75k | pending_state.set_expected_next(CLIENT_HELLO); |
564 | 6.75k | return; |
565 | 6.75k | } |
566 | 0 | } |
567 | 0 | else if(epoch0_restart) |
568 | 0 | { |
569 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Reuse of DTLS association requires DTLS cookie secret be set"); |
570 | 0 | } |
571 | 23.6k | } |
572 | 23.6k | |
573 | 23.6k | if(epoch0_restart) |
574 | 0 | { |
575 | 0 | // If we reached here then we were able to verify the cookie |
576 | 0 | reset_active_association_state(); |
577 | 0 | } |
578 | 23.6k | |
579 | 23.6k | secure_renegotiation_check(pending_state.client_hello()); |
580 | 23.6k | |
581 | 23.6k | callbacks().tls_examine_extensions(pending_state.client_hello()->extensions(), CLIENT); |
582 | 23.6k | |
583 | 23.6k | Session session_info; |
584 | 23.6k | const bool resuming = |
585 | 23.6k | pending_state.allow_session_resumption() && |
586 | 23.6k | check_for_resume(session_info, |
587 | 23.0k | session_manager(), |
588 | 23.0k | m_creds, |
589 | 23.0k | pending_state.client_hello(), |
590 | 23.0k | std::chrono::seconds(policy().session_ticket_lifetime())); |
591 | 23.6k | |
592 | 23.6k | bool have_session_ticket_key = false; |
593 | 23.6k | |
594 | 23.6k | try |
595 | 23.6k | { |
596 | 23.6k | have_session_ticket_key = |
597 | 23.6k | m_creds.psk("tls-server", "session-ticket", "").length() > 0; |
598 | 23.6k | } |
599 | 23.6k | catch(...) {} |
600 | 23.6k | |
601 | 23.6k | m_next_protocol = ""; |
602 | 23.0k | if(pending_state.client_hello()->supports_alpn()) |
603 | 5.17k | { |
604 | 5.17k | m_next_protocol = callbacks().tls_server_choose_app_protocol(pending_state.client_hello()->next_protocols()); |
605 | 5.17k | |
606 | 5.17k | // if the callback return was empty, fall back to the (deprecated) std::function |
607 | 5.17k | if(m_next_protocol.empty() && m_choose_next_protocol) |
608 | 0 | { |
609 | 0 | m_next_protocol = m_choose_next_protocol(pending_state.client_hello()->next_protocols()); |
610 | 0 | } |
611 | 5.17k | } |
612 | 23.0k | |
613 | 23.0k | if(resuming) |
614 | 0 | { |
615 | 0 | this->session_resume(pending_state, have_session_ticket_key, session_info); |
616 | 0 | } |
617 | 23.0k | else // new session |
618 | 23.0k | { |
619 | 23.0k | this->session_create(pending_state, have_session_ticket_key); |
620 | 23.0k | } |
621 | 23.0k | } |
622 | | |
623 | | void Server::process_certificate_msg(Server_Handshake_State& pending_state, |
624 | | const std::vector<uint8_t>& contents) |
625 | 0 | { |
626 | 0 | pending_state.client_certs(new Certificate(contents, policy())); |
627 | 0 |
|
628 | 0 | // CERTIFICATE_REQUIRED would make more sense but BoGo expects handshake failure alert |
629 | 0 | if(pending_state.client_certs()->empty() && policy().require_client_certificate_authentication()) |
630 | 0 | throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Policy requires client send a certificate, but it did not"); |
631 | 0 | |
632 | 0 | pending_state.set_expected_next(CLIENT_KEX); |
633 | 0 | } |
634 | | |
635 | | void Server::process_client_key_exchange_msg(Server_Handshake_State& pending_state, |
636 | | const std::vector<uint8_t>& contents) |
637 | 13.4k | { |
638 | 13.4k | if(pending_state.received_handshake_msg(CERTIFICATE) && !pending_state.client_certs()->empty()) |
639 | 0 | pending_state.set_expected_next(CERTIFICATE_VERIFY); |
640 | 13.4k | else |
641 | 13.4k | pending_state.set_expected_next(HANDSHAKE_CCS); |
642 | 13.4k | |
643 | 13.4k | pending_state.client_kex(new Client_Key_Exchange(contents, pending_state, |
644 | 13.4k | pending_state.server_rsa_kex_key(), |
645 | 13.4k | m_creds, policy(), rng())); |
646 | 13.4k | |
647 | 13.4k | pending_state.compute_session_keys(); |
648 | 13.4k | } |
649 | | |
650 | | void Server::process_change_cipher_spec_msg(Server_Handshake_State& pending_state) |
651 | 654 | { |
652 | 654 | pending_state.set_expected_next(FINISHED); |
653 | 654 | change_cipher_spec_reader(SERVER); |
654 | 654 | } |
655 | | |
656 | | void Server::process_certificate_verify_msg(Server_Handshake_State& pending_state, |
657 | | Handshake_Type type, |
658 | | const std::vector<uint8_t>& contents) |
659 | 0 | { |
660 | 0 | pending_state.client_verify(new Certificate_Verify(contents, pending_state.version())); |
661 | 0 |
|
662 | 0 | const std::vector<X509_Certificate>& client_certs = |
663 | 0 | pending_state.client_certs()->cert_chain(); |
664 | 0 |
|
665 | 0 | const bool sig_valid = |
666 | 0 | pending_state.client_verify()->verify(client_certs[0], pending_state, policy()); |
667 | 0 |
|
668 | 0 | pending_state.hash().update(pending_state.handshake_io().format(contents, type)); |
669 | 0 |
|
670 | 0 | /* |
671 | 0 | * Using DECRYPT_ERROR looks weird here, but per RFC 4346 is for |
672 | 0 | * "A handshake cryptographic operation failed, including being |
673 | 0 | * unable to correctly verify a signature, ..." |
674 | 0 | */ |
675 | 0 | if(!sig_valid) |
676 | 0 | throw TLS_Exception(Alert::DECRYPT_ERROR, "Client cert verify failed"); |
677 | 0 | |
678 | 0 | try |
679 | 0 | { |
680 | 0 | const std::string sni_hostname = pending_state.client_hello()->sni_hostname(); |
681 | 0 | auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-server", sni_hostname); |
682 | 0 |
|
683 | 0 | callbacks().tls_verify_cert_chain(client_certs, |
684 | 0 | {}, // ocsp |
685 | 0 | trusted_CAs, |
686 | 0 | Usage_Type::TLS_CLIENT_AUTH, |
687 | 0 | sni_hostname, |
688 | 0 | policy()); |
689 | 0 | } |
690 | 0 | catch(std::exception& e) |
691 | 0 | { |
692 | 0 | throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what()); |
693 | 0 | } |
694 | 0 | |
695 | 0 | pending_state.set_expected_next(HANDSHAKE_CCS); |
696 | 0 | } |
697 | | |
698 | | void Server::process_finished_msg(Server_Handshake_State& pending_state, |
699 | | Handshake_Type type, |
700 | | const std::vector<uint8_t>& contents) |
701 | 378 | { |
702 | 378 | pending_state.set_expected_next(HANDSHAKE_NONE); |
703 | 378 | |
704 | 378 | pending_state.client_finished(new Finished(contents)); |
705 | 378 | |
706 | 378 | if(!pending_state.client_finished()->verify(pending_state, CLIENT)) |
707 | 0 | throw TLS_Exception(Alert::DECRYPT_ERROR, |
708 | 0 | "Finished message didn't verify"); |
709 | 378 | |
710 | 378 | if(!pending_state.server_finished()) |
711 | 378 | { |
712 | 378 | // already sent finished if resuming, so this is a new session |
713 | 378 | |
714 | 378 | pending_state.hash().update(pending_state.handshake_io().format(contents, type)); |
715 | 378 | |
716 | 378 | Session session_info( |
717 | 378 | pending_state.server_hello()->session_id(), |
718 | 378 | pending_state.session_keys().master_secret(), |
719 | 378 | pending_state.server_hello()->version(), |
720 | 378 | pending_state.server_hello()->ciphersuite(), |
721 | 378 | SERVER, |
722 | 378 | pending_state.server_hello()->supports_extended_master_secret(), |
723 | 378 | pending_state.server_hello()->supports_encrypt_then_mac(), |
724 | 378 | get_peer_cert_chain(pending_state), |
725 | 378 | std::vector<uint8_t>(), |
726 | 378 | Server_Information(pending_state.client_hello()->sni_hostname()), |
727 | 378 | pending_state.srp_identifier(), |
728 | 378 | pending_state.server_hello()->srtp_profile()); |
729 | 378 | |
730 | 378 | if(save_session(session_info)) |
731 | 378 | { |
732 | 378 | if(pending_state.server_hello()->supports_session_ticket()) |
733 | 258 | { |
734 | 258 | try |
735 | 258 | { |
736 | 258 | const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", ""); |
737 | 258 | |
738 | 258 | pending_state.new_session_ticket( |
739 | 258 | new New_Session_Ticket(pending_state.handshake_io(), |
740 | 258 | pending_state.hash(), |
741 | 258 | session_info.encrypt(ticket_key, rng()), |
742 | 258 | policy().session_ticket_lifetime())); |
743 | 258 | } |
744 | 258 | catch(...) {} |
745 | 258 | } |
746 | 120 | else |
747 | 120 | session_manager().save(session_info); |
748 | 378 | } |
749 | 378 | |
750 | 378 | if(!pending_state.new_session_ticket() && |
751 | 378 | pending_state.server_hello()->supports_session_ticket()) |
752 | 0 | { |
753 | 0 | pending_state.new_session_ticket( |
754 | 0 | new New_Session_Ticket(pending_state.handshake_io(), pending_state.hash())); |
755 | 0 | } |
756 | 378 | |
757 | 378 | pending_state.handshake_io().send(Change_Cipher_Spec()); |
758 | 378 | |
759 | 378 | change_cipher_spec_writer(SERVER); |
760 | 378 | |
761 | 378 | pending_state.server_finished(new Finished(pending_state.handshake_io(), pending_state, SERVER)); |
762 | 378 | } |
763 | 378 | |
764 | 378 | activate_session(); |
765 | 378 | } |
766 | | |
767 | | /* |
768 | | * Process a handshake message |
769 | | */ |
770 | | void Server::process_handshake_msg(const Handshake_State* active_state, |
771 | | Handshake_State& state_base, |
772 | | Handshake_Type type, |
773 | | const std::vector<uint8_t>& contents, |
774 | | bool epoch0_restart) |
775 | 45.1k | { |
776 | 45.1k | Server_Handshake_State& state = dynamic_cast<Server_Handshake_State&>(state_base); |
777 | 45.1k | state.confirm_transition_to(type); |
778 | 45.1k | |
779 | 45.1k | /* |
780 | 45.1k | * The change cipher spec message isn't technically a handshake |
781 | 45.1k | * message so it's not included in the hash. The finished and |
782 | 45.1k | * certificate verify messages are verified based on the current |
783 | 45.1k | * state of the hash *before* this message so we delay adding them |
784 | 45.1k | * to the hash computation until we've processed them below. |
785 | 45.1k | */ |
786 | 45.1k | if(type != HANDSHAKE_CCS && type != FINISHED && type != CERTIFICATE_VERIFY) |
787 | 43.9k | { |
788 | 43.9k | state.hash().update(state.handshake_io().format(contents, type)); |
789 | 43.9k | } |
790 | 45.1k | |
791 | 45.1k | switch(type) |
792 | 45.1k | { |
793 | 30.4k | case CLIENT_HELLO: |
794 | 30.4k | return this->process_client_hello_msg(active_state, state, contents, epoch0_restart); |
795 | 0 | |
796 | 0 | case CERTIFICATE: |
797 | 0 | return this->process_certificate_msg(state, contents); |
798 | 0 | |
799 | 13.4k | case CLIENT_KEX: |
800 | 13.4k | return this->process_client_key_exchange_msg(state, contents); |
801 | 0 | |
802 | 0 | case CERTIFICATE_VERIFY: |
803 | 0 | return this->process_certificate_verify_msg(state, type, contents); |
804 | 0 | |
805 | 654 | case HANDSHAKE_CCS: |
806 | 654 | return this->process_change_cipher_spec_msg(state); |
807 | 0 | |
808 | 378 | case FINISHED: |
809 | 378 | return this->process_finished_msg(state, type, contents); |
810 | 0 | |
811 | 0 | default: |
812 | 0 | throw Unexpected_Message("Unknown handshake message received"); |
813 | 45.1k | } |
814 | 45.1k | } |
815 | | |
816 | | void Server::session_resume(Server_Handshake_State& pending_state, |
817 | | bool have_session_ticket_key, |
818 | | Session& session_info) |
819 | 0 | { |
820 | 0 | // Only offer a resuming client a new ticket if they didn't send one this time, |
821 | 0 | // ie, resumed via server-side resumption. TODO: also send one if expiring soon? |
822 | 0 |
|
823 | 0 | const bool offer_new_session_ticket = |
824 | 0 | (pending_state.client_hello()->supports_session_ticket() && |
825 | 0 | pending_state.client_hello()->session_ticket().empty() && |
826 | 0 | have_session_ticket_key); |
827 | 0 |
|
828 | 0 | pending_state.server_hello(new Server_Hello( |
829 | 0 | pending_state.handshake_io(), |
830 | 0 | pending_state.hash(), |
831 | 0 | policy(), |
832 | 0 | callbacks(), |
833 | 0 | rng(), |
834 | 0 | secure_renegotiation_data_for_server_hello(), |
835 | 0 | *pending_state.client_hello(), |
836 | 0 | session_info, |
837 | 0 | offer_new_session_ticket, |
838 | 0 | m_next_protocol)); |
839 | 0 |
|
840 | 0 | secure_renegotiation_check(pending_state.server_hello()); |
841 | 0 |
|
842 | 0 | pending_state.mark_as_resumption(); |
843 | 0 | pending_state.compute_session_keys(session_info.master_secret()); |
844 | 0 | pending_state.set_resume_certs(session_info.peer_certs()); |
845 | 0 |
|
846 | 0 | if(!save_session(session_info)) |
847 | 0 | { |
848 | 0 | session_manager().remove_entry(session_info.session_id()); |
849 | 0 |
|
850 | 0 | if(pending_state.server_hello()->supports_session_ticket()) // send an empty ticket |
851 | 0 | { |
852 | 0 | pending_state.new_session_ticket( |
853 | 0 | new New_Session_Ticket(pending_state.handshake_io(), |
854 | 0 | pending_state.hash())); |
855 | 0 | } |
856 | 0 | } |
857 | 0 |
|
858 | 0 | if(pending_state.server_hello()->supports_session_ticket() && !pending_state.new_session_ticket()) |
859 | 0 | { |
860 | 0 | try |
861 | 0 | { |
862 | 0 | const SymmetricKey ticket_key = m_creds.psk("tls-server", "session-ticket", ""); |
863 | 0 |
|
864 | 0 | pending_state.new_session_ticket( |
865 | 0 | new New_Session_Ticket(pending_state.handshake_io(), |
866 | 0 | pending_state.hash(), |
867 | 0 | session_info.encrypt(ticket_key, rng()), |
868 | 0 | policy().session_ticket_lifetime())); |
869 | 0 | } |
870 | 0 | catch(...) {} |
871 | 0 |
|
872 | 0 | if(!pending_state.new_session_ticket()) |
873 | 0 | { |
874 | 0 | pending_state.new_session_ticket( |
875 | 0 | new New_Session_Ticket(pending_state.handshake_io(), pending_state.hash())); |
876 | 0 | } |
877 | 0 | } |
878 | 0 |
|
879 | 0 | pending_state.handshake_io().send(Change_Cipher_Spec()); |
880 | 0 |
|
881 | 0 | change_cipher_spec_writer(SERVER); |
882 | 0 |
|
883 | 0 | pending_state.server_finished(new Finished(pending_state.handshake_io(), pending_state, SERVER)); |
884 | 0 | pending_state.set_expected_next(HANDSHAKE_CCS); |
885 | 0 | } |
886 | | |
887 | | void Server::session_create(Server_Handshake_State& pending_state, |
888 | | bool have_session_ticket_key) |
889 | 23.0k | { |
890 | 23.0k | std::map<std::string, std::vector<X509_Certificate>> cert_chains; |
891 | 23.0k | |
892 | 23.0k | const std::string sni_hostname = pending_state.client_hello()->sni_hostname(); |
893 | 23.0k | |
894 | 23.0k | cert_chains = get_server_certs(sni_hostname, m_creds); |
895 | 23.0k | |
896 | 23.0k | if(sni_hostname != "" && cert_chains.empty()) |
897 | 0 | { |
898 | 0 | cert_chains = get_server_certs("", m_creds); |
899 | 0 |
|
900 | 0 | /* |
901 | 0 | * Only send the unrecognized_name alert if we couldn't |
902 | 0 | * find any certs for the requested name but did find at |
903 | 0 | * least one cert to use in general. That avoids sending an |
904 | 0 | * unrecognized_name when a server is configured for purely |
905 | 0 | * anonymous/PSK operation. |
906 | 0 | */ |
907 | 0 | if(!cert_chains.empty()) |
908 | 0 | send_warning_alert(Alert::UNRECOGNIZED_NAME); |
909 | 0 | } |
910 | 23.0k | |
911 | 23.0k | const uint16_t ciphersuite = choose_ciphersuite(policy(), pending_state.version(), |
912 | 23.0k | m_creds, cert_chains, |
913 | 23.0k | *pending_state.client_hello()); |
914 | 23.0k | |
915 | 23.0k | Server_Hello::Settings srv_settings( |
916 | 23.0k | make_hello_random(rng(), policy()), // new session ID |
917 | 23.0k | pending_state.version(), |
918 | 23.0k | ciphersuite, |
919 | 23.0k | have_session_ticket_key); |
920 | 23.0k | |
921 | 23.0k | pending_state.server_hello(new Server_Hello( |
922 | 23.0k | pending_state.handshake_io(), |
923 | 23.0k | pending_state.hash(), |
924 | 23.0k | policy(), |
925 | 23.0k | callbacks(), |
926 | 23.0k | rng(), |
927 | 23.0k | secure_renegotiation_data_for_server_hello(), |
928 | 23.0k | *pending_state.client_hello(), |
929 | 23.0k | srv_settings, |
930 | 23.0k | m_next_protocol)); |
931 | 23.0k | |
932 | 23.0k | secure_renegotiation_check(pending_state.server_hello()); |
933 | 23.0k | |
934 | 23.0k | const Ciphersuite& pending_suite = pending_state.ciphersuite(); |
935 | 23.0k | |
936 | 23.0k | Private_Key* private_key = nullptr; |
937 | 23.0k | |
938 | 23.0k | if(pending_suite.signature_used() || pending_suite.kex_method() == Kex_Algo::STATIC_RSA) |
939 | 136 | { |
940 | 136 | const std::string algo_used = |
941 | 136 | pending_suite.signature_used() ? pending_suite.sig_algo() : "RSA"; |
942 | 136 | |
943 | 136 | BOTAN_ASSERT(!cert_chains[algo_used].empty(), |
944 | 136 | "Attempting to send empty certificate chain"); |
945 | 136 | |
946 | 136 | pending_state.server_certs(new Certificate(pending_state.handshake_io(), |
947 | 136 | pending_state.hash(), |
948 | 136 | cert_chains[algo_used])); |
949 | 136 | |
950 | 136 | if(pending_state.client_hello()->supports_cert_status_message() && pending_state.is_a_resumption() == false) |
951 | 2 | { |
952 | 2 | auto csr = pending_state.client_hello()->extensions().get<Certificate_Status_Request>(); |
953 | 2 | // csr is non-null if client_hello()->supports_cert_status_message() |
954 | 2 | BOTAN_ASSERT_NOMSG(csr != nullptr); |
955 | 2 | const auto resp_bytes = callbacks().tls_provide_cert_status(cert_chains[algo_used], *csr); |
956 | 2 | if(resp_bytes.size() > 0) |
957 | 0 | { |
958 | 0 | pending_state.server_cert_status(new Certificate_Status( |
959 | 0 | pending_state.handshake_io(), |
960 | 0 | pending_state.hash(), |
961 | 0 | resp_bytes |
962 | 0 | )); |
963 | 0 | } |
964 | 2 | } |
965 | 136 | |
966 | 136 | private_key = m_creds.private_key_for( |
967 | 136 | pending_state.server_certs()->cert_chain()[0], |
968 | 136 | "tls-server", |
969 | 136 | sni_hostname); |
970 | 136 | |
971 | 136 | if(!private_key) |
972 | 136 | throw Internal_Error("No private key located for associated server cert"); |
973 | 22.8k | } |
974 | 22.8k | |
975 | 22.8k | if(pending_suite.kex_method() == Kex_Algo::STATIC_RSA) |
976 | 0 | { |
977 | 0 | pending_state.set_server_rsa_kex_key(private_key); |
978 | 0 | } |
979 | 22.8k | else |
980 | 22.8k | { |
981 | 22.8k | pending_state.server_kex(new Server_Key_Exchange(pending_state.handshake_io(), |
982 | 22.8k | pending_state, policy(), |
983 | 22.8k | m_creds, rng(), private_key)); |
984 | 22.8k | } |
985 | 22.8k | |
986 | 22.8k | auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-server", sni_hostname); |
987 | 22.8k | |
988 | 22.8k | std::vector<X509_DN> client_auth_CAs; |
989 | 22.8k | |
990 | 22.8k | for(auto store : trusted_CAs) |
991 | 0 | { |
992 | 0 | auto subjects = store->all_subjects(); |
993 | 0 | client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end()); |
994 | 0 | } |
995 | 22.8k | |
996 | 22.8k | const bool request_cert = |
997 | 22.8k | (client_auth_CAs.empty() == false) || |
998 | 22.8k | policy().request_client_certificate_authentication(); |
999 | 22.8k | |
1000 | 22.8k | if(request_cert && pending_state.ciphersuite().signature_used()) |
1001 | 0 | { |
1002 | 0 | pending_state.cert_req( |
1003 | 0 | new Certificate_Req(pending_state.handshake_io(), |
1004 | 0 | pending_state.hash(), |
1005 | 0 | policy(), |
1006 | 0 | client_auth_CAs, |
1007 | 0 | pending_state.version())); |
1008 | 0 |
|
1009 | 0 | /* |
1010 | 0 | SSLv3 allowed clients to skip the Certificate message entirely |
1011 | 0 | if they wanted. In TLS v1.0 and later clients must send a |
1012 | 0 | (possibly empty) Certificate message |
1013 | 0 | */ |
1014 | 0 | pending_state.set_expected_next(CERTIFICATE); |
1015 | 0 | } |
1016 | 22.8k | else |
1017 | 22.8k | { |
1018 | 22.8k | pending_state.set_expected_next(CLIENT_KEX); |
1019 | 22.8k | } |
1020 | 22.8k | |
1021 | 22.8k | pending_state.server_hello_done(new Server_Hello_Done(pending_state.handshake_io(), pending_state.hash())); |
1022 | 22.8k | } |
1023 | | } |
1024 | | |
1025 | | } |