/src/botan/build/include/public/botan/tls_messages.h
Line | Count | Source |
1 | | /* |
2 | | * TLS Messages |
3 | | * (C) 2004-2011,2015 Jack Lloyd |
4 | | * 2016 Matthias Gierlings |
5 | | * |
6 | | * Botan is released under the Simplified BSD License (see license.txt) |
7 | | */ |
8 | | |
9 | | #ifndef BOTAN_TLS_MESSAGES_H_ |
10 | | #define BOTAN_TLS_MESSAGES_H_ |
11 | | |
12 | | #include <botan/strong_type.h> |
13 | | #include <botan/tls_ciphersuite.h> |
14 | | #include <botan/tls_extensions.h> |
15 | | #include <botan/tls_handshake_msg.h> |
16 | | #include <botan/tls_session.h> |
17 | | #include <chrono> |
18 | | #include <memory> |
19 | | #include <optional> |
20 | | #include <set> |
21 | | #include <string> |
22 | | #include <variant> |
23 | | #include <vector> |
24 | | |
25 | | namespace Botan { |
26 | | |
27 | | class Public_Key; |
28 | | class Credentials_Manager; |
29 | | class X509_Certificate; |
30 | | |
31 | | namespace OCSP { |
32 | | class Response; |
33 | | } |
34 | | |
35 | | namespace TLS { |
36 | | |
37 | | class Session_Manager; |
38 | | class Handshake_IO; |
39 | | class Handshake_State; |
40 | | class Hello_Retry_Request; |
41 | | class Callbacks; |
42 | | class Cipher_State; |
43 | | class Policy; |
44 | | |
45 | | std::vector<uint8_t> make_hello_random(RandomNumberGenerator& rng, Callbacks& cb, const Policy& policy); |
46 | | |
47 | | /** |
48 | | * DTLS Hello Verify Request |
49 | | */ |
50 | | class BOTAN_UNSTABLE_API Hello_Verify_Request final : public Handshake_Message { |
51 | | public: |
52 | | std::vector<uint8_t> serialize() const override; |
53 | | |
54 | 11.5k | Handshake_Type type() const override { return Handshake_Type::HelloVerifyRequest; } |
55 | | |
56 | 5.80k | const std::vector<uint8_t>& cookie() const { return m_cookie; } |
57 | | |
58 | | explicit Hello_Verify_Request(const std::vector<uint8_t>& buf); |
59 | | |
60 | | Hello_Verify_Request(const std::vector<uint8_t>& client_hello_bits, |
61 | | std::string_view client_identity, |
62 | | const SymmetricKey& secret_key); |
63 | | |
64 | | private: |
65 | | std::vector<uint8_t> m_cookie; |
66 | | }; |
67 | | |
68 | | class Client_Hello_Internal; |
69 | | |
70 | | /** |
71 | | * Client Hello Message |
72 | | */ |
73 | | class BOTAN_UNSTABLE_API Client_Hello : public Handshake_Message { |
74 | | public: |
75 | | Client_Hello(const Client_Hello&) = delete; |
76 | | Client_Hello& operator=(const Client_Hello&) = delete; |
77 | | Client_Hello(Client_Hello&&) noexcept; |
78 | | Client_Hello& operator=(Client_Hello&&) noexcept; |
79 | | |
80 | | ~Client_Hello() override; |
81 | | |
82 | | Handshake_Type type() const override; |
83 | | |
84 | | /** |
85 | | * Return the version indicated in the ClientHello. |
86 | | * This may differ from the version indicated in the supported_versions extension. |
87 | | * |
88 | | * See RFC 8446 4.1.2: |
89 | | * TLS 1.3, the client indicates its version preferences in the |
90 | | * "supported_versions" extension (Section 4.2.1) and the |
91 | | * legacy_version field MUST be set to 0x0303, which is the version |
92 | | * number for TLS 1.2. |
93 | | */ |
94 | | Protocol_Version legacy_version() const; |
95 | | |
96 | | const std::vector<uint8_t>& random() const; |
97 | | |
98 | | const Session_ID& session_id() const; |
99 | | |
100 | | const std::vector<uint16_t>& ciphersuites() const; |
101 | | |
102 | | bool offered_suite(uint16_t ciphersuite) const; |
103 | | |
104 | | std::vector<Signature_Scheme> signature_schemes() const; |
105 | | std::vector<Signature_Scheme> certificate_signature_schemes() const; |
106 | | |
107 | | std::vector<Group_Params> supported_ecc_curves() const; |
108 | | |
109 | | // This returns any groups in the FFDHE range |
110 | | std::vector<Group_Params> supported_dh_groups() const; |
111 | | |
112 | | std::vector<Protocol_Version> supported_versions() const; |
113 | | |
114 | | std::string sni_hostname() const; |
115 | | |
116 | | bool supports_alpn() const; |
117 | | |
118 | | bool sent_signature_algorithms() const; |
119 | | |
120 | | std::vector<std::string> next_protocols() const; |
121 | | |
122 | | std::vector<uint16_t> srtp_profiles() const; |
123 | | |
124 | | std::vector<uint8_t> serialize() const override; |
125 | | |
126 | | const std::vector<uint8_t>& cookie() const; |
127 | | |
128 | | std::vector<uint8_t> cookie_input_data() const; |
129 | | |
130 | | std::set<Extension_Code> extension_types() const; |
131 | | |
132 | | const Extensions& extensions() const; |
133 | | |
134 | | protected: |
135 | | Client_Hello(); |
136 | | explicit Client_Hello(std::unique_ptr<Client_Hello_Internal> data); |
137 | | |
138 | | const std::vector<uint8_t>& compression_methods() const; |
139 | | |
140 | | protected: |
141 | | std::unique_ptr<Client_Hello_Internal> m_data; // NOLINT(*non-private-member-variable*) |
142 | | }; |
143 | | |
144 | | class BOTAN_UNSTABLE_API Client_Hello_12 final : public Client_Hello { |
145 | | public: |
146 | | class Settings final { |
147 | | public: |
148 | | explicit Settings(const Protocol_Version version, std::string_view hostname = "") : |
149 | 7.59k | m_new_session_version(version), m_hostname(hostname) {} |
150 | | |
151 | 15.1k | Protocol_Version protocol_version() const { return m_new_session_version; } |
152 | | |
153 | 15.1k | const std::string& hostname() const { return m_hostname; } |
154 | | |
155 | | private: |
156 | | const Protocol_Version m_new_session_version; |
157 | | const std::string m_hostname; |
158 | | }; |
159 | | |
160 | | public: |
161 | | explicit Client_Hello_12(const std::vector<uint8_t>& buf); |
162 | | |
163 | | Client_Hello_12(Handshake_IO& io, |
164 | | Handshake_Hash& hash, |
165 | | const Policy& policy, |
166 | | Callbacks& cb, |
167 | | RandomNumberGenerator& rng, |
168 | | const std::vector<uint8_t>& reneg_info, |
169 | | const Settings& client_settings, |
170 | | const std::vector<std::string>& next_protocols); |
171 | | |
172 | | Client_Hello_12(Handshake_IO& io, |
173 | | Handshake_Hash& hash, |
174 | | const Policy& policy, |
175 | | Callbacks& cb, |
176 | | RandomNumberGenerator& rng, |
177 | | const std::vector<uint8_t>& reneg_info, |
178 | | const Session_with_Handle& session_and_handle, |
179 | | const std::vector<std::string>& next_protocols); |
180 | | |
181 | | protected: |
182 | | friend class Client_Hello_13; // to allow construction by Client_Hello_13::parse() |
183 | | explicit Client_Hello_12(std::unique_ptr<Client_Hello_Internal> data); |
184 | | |
185 | | public: |
186 | | using Client_Hello::compression_methods; |
187 | | using Client_Hello::random; |
188 | | |
189 | | bool prefers_compressed_ec_points() const; |
190 | | |
191 | | bool secure_renegotiation() const; |
192 | | |
193 | | std::vector<uint8_t> renegotiation_info() const; |
194 | | |
195 | | bool supports_session_ticket() const; |
196 | | |
197 | | Session_Ticket session_ticket() const; |
198 | | |
199 | | std::optional<Session_Handle> session_handle() const; |
200 | | |
201 | | bool supports_extended_master_secret() const; |
202 | | |
203 | | bool supports_cert_status_message() const; |
204 | | |
205 | | bool supports_encrypt_then_mac() const; |
206 | | |
207 | | void update_hello_cookie(const Hello_Verify_Request& hello_verify); |
208 | | |
209 | | private: |
210 | | void add_tls12_supported_groups_extensions(const Policy& policy); |
211 | | }; |
212 | | |
213 | | #if defined(BOTAN_HAS_TLS_13) |
214 | | |
215 | | class BOTAN_UNSTABLE_API Client_Hello_13 final : public Client_Hello { |
216 | | public: |
217 | | /** |
218 | | * Creates a client hello which might optionally use the passed-in |
219 | | * @p session for resumption. In that case, this will "extract" the |
220 | | * master secret from the passed-in @p session. |
221 | | */ |
222 | | Client_Hello_13(const Policy& policy, |
223 | | Callbacks& cb, |
224 | | RandomNumberGenerator& rng, |
225 | | std::string_view hostname, |
226 | | const std::vector<std::string>& next_protocols, |
227 | | std::optional<Session_with_Handle>& session, |
228 | | std::vector<ExternalPSK> psks); |
229 | | |
230 | | static std::variant<Client_Hello_13, Client_Hello_12> parse(const std::vector<uint8_t>& buf); |
231 | | |
232 | | void retry(const Hello_Retry_Request& hrr, |
233 | | const Transcript_Hash_State& transcript_hash_state, |
234 | | Callbacks& cb, |
235 | | RandomNumberGenerator& rng); |
236 | | |
237 | | /** |
238 | | * Select the highest protocol version from the list of versions |
239 | | * supported by the client. If no such version can be determined this |
240 | | * returns std::nullopt. |
241 | | */ |
242 | | std::optional<Protocol_Version> highest_supported_version(const Policy& policy) const; |
243 | | |
244 | | /** |
245 | | * This validates that a Client Hello received after sending a Hello |
246 | | * Retry Request was updated in accordance with RFC 8446 4.1.2. If issues |
247 | | * are found, this method throws accordingly. |
248 | | */ |
249 | | void validate_updates(const Client_Hello_13& new_ch); |
250 | | |
251 | | private: |
252 | | explicit Client_Hello_13(std::unique_ptr<Client_Hello_Internal> data); |
253 | | |
254 | | /** |
255 | | * If the Client Hello contains a PSK extensions with identities this will |
256 | | * generate the PSK binders as described in RFC 8446 4.2.11.2. |
257 | | * Note that the passed in \p transcript_hash_state might be virgin for |
258 | | * the initial Client Hello and should be primed with ClientHello1 and |
259 | | * HelloRetryRequest for an updated Client Hello. |
260 | | */ |
261 | | void calculate_psk_binders(Transcript_Hash_State transcript_hash_state); |
262 | | }; |
263 | | |
264 | | #endif // BOTAN_HAS_TLS_13 |
265 | | |
266 | | class Server_Hello_Internal; |
267 | | |
268 | | /** |
269 | | * Server Hello Message |
270 | | */ |
271 | | class BOTAN_UNSTABLE_API Server_Hello : public Handshake_Message { |
272 | | public: |
273 | | Server_Hello(const Server_Hello&) = delete; |
274 | | Server_Hello& operator=(const Server_Hello&) = delete; |
275 | | Server_Hello(Server_Hello&&) noexcept; |
276 | | Server_Hello& operator=(Server_Hello&&) noexcept; |
277 | | |
278 | | ~Server_Hello() override; |
279 | | |
280 | | std::vector<uint8_t> serialize() const override; |
281 | | |
282 | | Handshake_Type type() const override; |
283 | | |
284 | | // methods available in both subclasses' interface |
285 | | uint16_t ciphersuite() const; |
286 | | const Extensions& extensions() const; |
287 | | const Session_ID& session_id() const; |
288 | | |
289 | | virtual Protocol_Version selected_version() const = 0; |
290 | | |
291 | | protected: |
292 | | explicit Server_Hello(std::unique_ptr<Server_Hello_Internal> data); |
293 | | |
294 | | // methods used internally and potentially exposed by one of the subclasses |
295 | | std::set<Extension_Code> extension_types() const; |
296 | | const std::vector<uint8_t>& random() const; |
297 | | uint8_t compression_method() const; |
298 | | Protocol_Version legacy_version() const; |
299 | | |
300 | | protected: |
301 | | std::unique_ptr<Server_Hello_Internal> m_data; // NOLINT(*non-private-member-variable*) |
302 | | }; |
303 | | |
304 | | class BOTAN_UNSTABLE_API Server_Hello_12 final : public Server_Hello { |
305 | | public: |
306 | | class Settings final { |
307 | | public: |
308 | | Settings(Session_ID new_session_id, |
309 | | Protocol_Version new_session_version, |
310 | | uint16_t ciphersuite, |
311 | | bool offer_session_ticket) : |
312 | 23.2k | m_new_session_id(std::move(new_session_id)), |
313 | 23.2k | m_new_session_version(new_session_version), |
314 | 23.2k | m_ciphersuite(ciphersuite), |
315 | 23.2k | m_offer_session_ticket(offer_session_ticket) {} |
316 | | |
317 | 23.2k | const Session_ID& session_id() const { return m_new_session_id; } |
318 | | |
319 | 46.4k | Protocol_Version protocol_version() const { return m_new_session_version; } |
320 | | |
321 | 23.2k | uint16_t ciphersuite() const { return m_ciphersuite; } |
322 | | |
323 | 3.80k | bool offer_session_ticket() const { return m_offer_session_ticket; } |
324 | | |
325 | | private: |
326 | | const Session_ID m_new_session_id; |
327 | | Protocol_Version m_new_session_version; |
328 | | uint16_t m_ciphersuite; |
329 | | bool m_offer_session_ticket; |
330 | | }; |
331 | | |
332 | | Server_Hello_12(Handshake_IO& io, |
333 | | Handshake_Hash& hash, |
334 | | const Policy& policy, |
335 | | Callbacks& cb, |
336 | | RandomNumberGenerator& rng, |
337 | | const std::vector<uint8_t>& secure_reneg_info, |
338 | | const Client_Hello_12& client_hello, |
339 | | const Settings& settings, |
340 | | std::string_view next_protocol); |
341 | | |
342 | | Server_Hello_12(Handshake_IO& io, |
343 | | Handshake_Hash& hash, |
344 | | const Policy& policy, |
345 | | Callbacks& cb, |
346 | | RandomNumberGenerator& rng, |
347 | | const std::vector<uint8_t>& secure_reneg_info, |
348 | | const Client_Hello_12& client_hello, |
349 | | const Session& resumed_session, |
350 | | bool offer_session_ticket, |
351 | | std::string_view next_protocol); |
352 | | |
353 | | explicit Server_Hello_12(const std::vector<uint8_t>& buf); |
354 | | |
355 | | protected: |
356 | | friend class Server_Hello_13; // to allow construction by Server_Hello_13::parse() |
357 | | explicit Server_Hello_12(std::unique_ptr<Server_Hello_Internal> data); |
358 | | |
359 | | public: |
360 | | using Server_Hello::compression_method; |
361 | | using Server_Hello::extension_types; |
362 | | using Server_Hello::legacy_version; |
363 | | using Server_Hello::random; |
364 | | |
365 | | /** |
366 | | * @returns the selected version as indicated in the legacy_version field |
367 | | */ |
368 | | Protocol_Version selected_version() const override; |
369 | | |
370 | | bool secure_renegotiation() const; |
371 | | |
372 | | std::vector<uint8_t> renegotiation_info() const; |
373 | | |
374 | | std::string next_protocol() const; |
375 | | |
376 | | bool supports_extended_master_secret() const; |
377 | | |
378 | | bool supports_encrypt_then_mac() const; |
379 | | |
380 | | bool supports_certificate_status_message() const; |
381 | | |
382 | | bool supports_session_ticket() const; |
383 | | |
384 | | uint16_t srtp_profile() const; |
385 | | bool prefers_compressed_ec_points() const; |
386 | | |
387 | | /** |
388 | | * Return desired downgrade version indicated by hello random, if any. |
389 | | */ |
390 | | std::optional<Protocol_Version> random_signals_downgrade() const; |
391 | | }; |
392 | | |
393 | | #if defined(BOTAN_HAS_TLS_13) |
394 | | |
395 | | class Hello_Retry_Request; |
396 | | |
397 | | class BOTAN_UNSTABLE_API Server_Hello_13 : public Server_Hello { |
398 | | protected: |
399 | | static const struct Server_Hello_Tag { |
400 | | } as_server_hello; |
401 | | |
402 | | static const struct Hello_Retry_Request_Tag { |
403 | | } as_hello_retry_request; |
404 | | |
405 | | static const struct Hello_Retry_Request_Creation_Tag { |
406 | | } as_new_hello_retry_request; |
407 | | |
408 | | // These constructors are meant for instantiating Server Hellos |
409 | | // after parsing a peer's message. They perform basic validation |
410 | | // and are therefore not suitable for constructing a message to |
411 | | // be sent to a client. |
412 | | explicit Server_Hello_13(std::unique_ptr<Server_Hello_Internal> data, Server_Hello_Tag tag = as_server_hello); |
413 | | explicit Server_Hello_13(std::unique_ptr<Server_Hello_Internal> data, Hello_Retry_Request_Tag tag); |
414 | | void basic_validation() const; |
415 | | |
416 | | // Instantiate a Server Hello as response to a client's Client Hello |
417 | | // (called from Server_Hello_13::create()) |
418 | | Server_Hello_13(const Client_Hello_13& ch, |
419 | | std::optional<Named_Group> key_exchange_group, |
420 | | Session_Manager& session_mgr, |
421 | | Credentials_Manager& credentials_mgr, |
422 | | RandomNumberGenerator& rng, |
423 | | Callbacks& cb, |
424 | | const Policy& policy); |
425 | | |
426 | | explicit Server_Hello_13(std::unique_ptr<Server_Hello_Internal> data, Hello_Retry_Request_Creation_Tag tag); |
427 | | |
428 | | public: |
429 | | static std::variant<Hello_Retry_Request, Server_Hello_13> create(const Client_Hello_13& ch, |
430 | | bool hello_retry_request_allowed, |
431 | | Session_Manager& session_mgr, |
432 | | Credentials_Manager& credentials_mgr, |
433 | | RandomNumberGenerator& rng, |
434 | | const Policy& policy, |
435 | | Callbacks& cb); |
436 | | |
437 | | static std::variant<Hello_Retry_Request, Server_Hello_13, Server_Hello_12> parse(const std::vector<uint8_t>& buf); |
438 | | |
439 | | /** |
440 | | * Return desired downgrade version indicated by hello random, if any. |
441 | | */ |
442 | | std::optional<Protocol_Version> random_signals_downgrade() const; |
443 | | |
444 | | /** |
445 | | * @returns the selected version as indicated by the supported_versions extension |
446 | | */ |
447 | | Protocol_Version selected_version() const final; |
448 | | }; |
449 | | |
450 | | class BOTAN_UNSTABLE_API Hello_Retry_Request final : public Server_Hello_13 { |
451 | | protected: |
452 | | friend class Server_Hello_13; // to allow construction by Server_Hello_13::parse() and ::create() |
453 | | explicit Hello_Retry_Request(std::unique_ptr<Server_Hello_Internal> data); |
454 | | Hello_Retry_Request(const Client_Hello_13& ch, Named_Group selected_group, const Policy& policy, Callbacks& cb); |
455 | | |
456 | | public: |
457 | 0 | Handshake_Type type() const override { return Handshake_Type::HelloRetryRequest; } |
458 | | |
459 | 0 | Handshake_Type wire_type() const override { return Handshake_Type::ServerHello; } |
460 | | }; |
461 | | |
462 | | class BOTAN_UNSTABLE_API Encrypted_Extensions final : public Handshake_Message { |
463 | | public: |
464 | | explicit Encrypted_Extensions(const std::vector<uint8_t>& buf); |
465 | | Encrypted_Extensions(const Client_Hello_13& client_hello, const Policy& policy, Callbacks& cb); |
466 | | |
467 | 8.70k | Handshake_Type type() const override { return Handshake_Type::EncryptedExtensions; } |
468 | | |
469 | 0 | const Extensions& extensions() const { return m_extensions; } |
470 | | |
471 | | std::vector<uint8_t> serialize() const override; |
472 | | |
473 | | private: |
474 | | Extensions m_extensions; |
475 | | }; |
476 | | |
477 | | #endif // BOTAN_HAS_TLS_13 |
478 | | |
479 | | /** |
480 | | * Client Key Exchange Message |
481 | | */ |
482 | | class BOTAN_UNSTABLE_API Client_Key_Exchange final : public Handshake_Message { |
483 | | public: |
484 | 2.18k | Handshake_Type type() const override { return Handshake_Type::ClientKeyExchange; } |
485 | | |
486 | 10.7k | const secure_vector<uint8_t>& pre_master_secret() const { return m_pre_master; } |
487 | | |
488 | | /** |
489 | | * @returns the agreed upon PSK identity or std::nullopt if not applicable |
490 | | */ |
491 | 360 | const std::optional<std::string>& psk_identity() const { return m_psk_identity; } |
492 | | |
493 | | Client_Key_Exchange(Handshake_IO& io, |
494 | | Handshake_State& state, |
495 | | const Policy& policy, |
496 | | Credentials_Manager& creds, |
497 | | const Public_Key* server_public_key, |
498 | | std::string_view hostname, |
499 | | RandomNumberGenerator& rng); |
500 | | |
501 | | Client_Key_Exchange(const std::vector<uint8_t>& buf, |
502 | | const Handshake_State& state, |
503 | | const Private_Key* server_rsa_kex_key, |
504 | | Credentials_Manager& creds, |
505 | | const Policy& policy, |
506 | | RandomNumberGenerator& rng); |
507 | | |
508 | | private: |
509 | 1.09k | std::vector<uint8_t> serialize() const override { return m_key_material; } |
510 | | |
511 | | std::vector<uint8_t> m_key_material; |
512 | | secure_vector<uint8_t> m_pre_master; |
513 | | std::optional<std::string> m_psk_identity; |
514 | | }; |
515 | | |
516 | | /** |
517 | | * Certificate Message of TLS 1.2 |
518 | | */ |
519 | | class BOTAN_UNSTABLE_API Certificate_12 final : public Handshake_Message { |
520 | | public: |
521 | 114 | Handshake_Type type() const override { return Handshake_Type::Certificate; } |
522 | | |
523 | 3.13k | const std::vector<X509_Certificate>& cert_chain() const { return m_certs; } |
524 | | |
525 | 0 | size_t count() const { return m_certs.size(); } |
526 | | |
527 | 0 | bool empty() const { return m_certs.empty(); } |
528 | | |
529 | | Certificate_12(Handshake_IO& io, Handshake_Hash& hash, const std::vector<X509_Certificate>& certs); |
530 | | |
531 | | Certificate_12(const std::vector<uint8_t>& buf, const Policy& policy); |
532 | | |
533 | | std::vector<uint8_t> serialize() const override; |
534 | | |
535 | | private: |
536 | | std::vector<X509_Certificate> m_certs; |
537 | | }; |
538 | | |
539 | | #if defined(BOTAN_HAS_TLS_13) |
540 | | |
541 | | class Certificate_Request_13; |
542 | | |
543 | | /** |
544 | | * Certificate Message of TLS 1.3 |
545 | | */ |
546 | | class BOTAN_UNSTABLE_API Certificate_13 final : public Handshake_Message { |
547 | | public: |
548 | | class Certificate_Entry { |
549 | | public: |
550 | | Certificate_Entry(TLS_Data_Reader& reader, Connection_Side side, Certificate_Type cert_type); |
551 | | explicit Certificate_Entry(const X509_Certificate& cert); |
552 | | explicit Certificate_Entry(std::shared_ptr<Public_Key> raw_public_key); |
553 | | |
554 | 0 | bool has_certificate() const { return m_certificate.has_value(); } |
555 | | |
556 | | const X509_Certificate& certificate() const; |
557 | | std::shared_ptr<const Public_Key> public_key() const; |
558 | | |
559 | | std::vector<uint8_t> serialize() const; |
560 | | |
561 | 0 | Extensions& extensions() { return m_extensions; } |
562 | | |
563 | 0 | const Extensions& extensions() const { return m_extensions; } |
564 | | |
565 | | private: |
566 | | std::optional<X509_Certificate> m_certificate; |
567 | | std::shared_ptr<Public_Key> m_raw_public_key; |
568 | | Extensions m_extensions; |
569 | | }; |
570 | | |
571 | | public: |
572 | 2 | Handshake_Type type() const override { return Handshake_Type::Certificate; } |
573 | | |
574 | | std::vector<X509_Certificate> cert_chain() const; |
575 | | |
576 | | bool has_certificate_chain() const; |
577 | | bool is_raw_public_key() const; |
578 | | |
579 | 0 | size_t count() const { return m_entries.size(); } |
580 | | |
581 | 0 | bool empty() const { return m_entries.empty(); } |
582 | | |
583 | | std::shared_ptr<const Public_Key> public_key() const; |
584 | | const X509_Certificate& leaf() const; |
585 | | |
586 | 0 | const std::vector<uint8_t>& request_context() const { return m_request_context; } |
587 | | |
588 | | /** |
589 | | * Create a Client Certificate message |
590 | | * ... in response to a Certificate Request message. |
591 | | */ |
592 | | Certificate_13(const Certificate_Request_13& cert_request, |
593 | | std::string_view hostname, |
594 | | Credentials_Manager& credentials_manager, |
595 | | Callbacks& callbacks, |
596 | | Certificate_Type cert_type); |
597 | | |
598 | | /** |
599 | | * Create a Server Certificate message |
600 | | * ... in response to a Client Hello indicating the need to authenticate |
601 | | * with a server certificate. |
602 | | */ |
603 | | Certificate_13(const Client_Hello_13& client_hello, |
604 | | Credentials_Manager& credentials_manager, |
605 | | Callbacks& callbacks, |
606 | | Certificate_Type cert_type); |
607 | | |
608 | | /** |
609 | | * Deserialize a Certificate message |
610 | | * @param buf the serialized message |
611 | | * @param policy the TLS policy |
612 | | * @param side is this a Connection_Side::Server or Connection_Side::Client certificate message |
613 | | * @param cert_type is the certificate type that was negotiated during the handshake |
614 | | */ |
615 | | Certificate_13(const std::vector<uint8_t>& buf, |
616 | | const Policy& policy, |
617 | | Connection_Side side, |
618 | | Certificate_Type cert_type); |
619 | | |
620 | | /** |
621 | | * Validate a Certificate message regarding what extensions are expected based on |
622 | | * previous handshake messages. Also call the tls_examine_extensions() callback |
623 | | * for each entry. |
624 | | * |
625 | | * @param requested_extensions Extensions of Client_Hello or Certificate_Request messages |
626 | | * @param cb Callback that will be called for each extension. |
627 | | */ |
628 | | void validate_extensions(const std::set<Extension_Code>& requested_extensions, Callbacks& cb) const; |
629 | | |
630 | | /** |
631 | | * Verify the certificate chain |
632 | | * |
633 | | * @throws if verification fails. |
634 | | */ |
635 | | void verify(Callbacks& callbacks, |
636 | | const Policy& policy, |
637 | | Credentials_Manager& creds, |
638 | | std::string_view hostname, |
639 | | bool use_ocsp) const; |
640 | | |
641 | | std::vector<uint8_t> serialize() const override; |
642 | | |
643 | | private: |
644 | | void setup_entries(std::vector<X509_Certificate> cert_chain, |
645 | | const Certificate_Status_Request* csr, |
646 | | Callbacks& callbacks); |
647 | | void setup_entry(std::shared_ptr<Public_Key> raw_public_key, Callbacks& callbacks); |
648 | | |
649 | | void verify_certificate_chain(Callbacks& callbacks, |
650 | | const Policy& policy, |
651 | | Credentials_Manager& creds, |
652 | | std::string_view hostname, |
653 | | bool use_ocsp, |
654 | | Usage_Type usage_type) const; |
655 | | |
656 | | private: |
657 | | std::vector<uint8_t> m_request_context; |
658 | | std::vector<Certificate_Entry> m_entries; |
659 | | Connection_Side m_side; |
660 | | }; |
661 | | |
662 | | #endif // BOTAN_HAS_TLS_13 |
663 | | |
664 | | /** |
665 | | * Certificate Status (RFC 6066) |
666 | | */ |
667 | | class BOTAN_UNSTABLE_API Certificate_Status final : public Handshake_Message { |
668 | | public: |
669 | 0 | Handshake_Type type() const override { return Handshake_Type::CertificateStatus; } |
670 | | |
671 | | //std::shared_ptr<const OCSP::Response> response() const { return m_response; } |
672 | | |
673 | 0 | const std::vector<uint8_t>& response() const { return m_response; } |
674 | | |
675 | | explicit Certificate_Status(const std::vector<uint8_t>& buf, Connection_Side from); |
676 | | |
677 | | Certificate_Status(Handshake_IO& io, Handshake_Hash& hash, const OCSP::Response& response); |
678 | | |
679 | | /* |
680 | | * Create a Certificate_Status message using an already DER encoded OCSP response. |
681 | | */ |
682 | | Certificate_Status(Handshake_IO& io, Handshake_Hash& hash, std::vector<uint8_t> raw_response_bytes); |
683 | | |
684 | | explicit Certificate_Status(std::vector<uint8_t> raw_response_bytes); |
685 | | |
686 | | std::vector<uint8_t> serialize() const override; |
687 | | |
688 | | private: |
689 | | std::vector<uint8_t> m_response; |
690 | | }; |
691 | | |
692 | | /** |
693 | | * Certificate Request Message (TLS 1.2) |
694 | | */ |
695 | | class BOTAN_UNSTABLE_API Certificate_Request_12 final : public Handshake_Message { |
696 | | public: |
697 | | Handshake_Type type() const override; |
698 | | |
699 | | const std::vector<std::string>& acceptable_cert_types() const; |
700 | | |
701 | | const std::vector<X509_DN>& acceptable_CAs() const; |
702 | | |
703 | | const std::vector<Signature_Scheme>& signature_schemes() const; |
704 | | |
705 | | Certificate_Request_12(Handshake_IO& io, |
706 | | Handshake_Hash& hash, |
707 | | const Policy& policy, |
708 | | const std::vector<X509_DN>& allowed_cas); |
709 | | |
710 | | explicit Certificate_Request_12(const std::vector<uint8_t>& buf); |
711 | | |
712 | | std::vector<uint8_t> serialize() const override; |
713 | | |
714 | | private: |
715 | | std::vector<X509_DN> m_names; |
716 | | std::vector<std::string> m_cert_key_types; |
717 | | std::vector<Signature_Scheme> m_schemes; |
718 | | }; |
719 | | |
720 | | #if defined(BOTAN_HAS_TLS_13) |
721 | | |
722 | | class BOTAN_UNSTABLE_API Certificate_Request_13 final : public Handshake_Message { |
723 | | public: |
724 | | Handshake_Type type() const override; |
725 | | |
726 | | Certificate_Request_13(const std::vector<uint8_t>& buf, Connection_Side side); |
727 | | |
728 | | //! Creates a Certificate_Request message if it is required by the configuration |
729 | | //! @return std::nullopt if configuration does not require client authentication |
730 | | static std::optional<Certificate_Request_13> maybe_create(const Client_Hello_13& sni_hostname, |
731 | | Credentials_Manager& cred_mgr, |
732 | | Callbacks& callbacks, |
733 | | const Policy& policy); |
734 | | |
735 | | std::vector<X509_DN> acceptable_CAs() const; |
736 | | const std::vector<Signature_Scheme>& signature_schemes() const; |
737 | | const std::vector<Signature_Scheme>& certificate_signature_schemes() const; |
738 | | |
739 | 0 | const Extensions& extensions() const { return m_extensions; } |
740 | | |
741 | | std::vector<uint8_t> serialize() const override; |
742 | | |
743 | 0 | const std::vector<uint8_t>& context() const { return m_context; } |
744 | | |
745 | | private: |
746 | | Certificate_Request_13(std::vector<X509_DN> acceptable_CAs, const Policy& policy, Callbacks& callbacks); |
747 | | |
748 | | private: |
749 | | std::vector<uint8_t> m_context; |
750 | | Extensions m_extensions; |
751 | | }; |
752 | | |
753 | | #endif |
754 | | |
755 | | class BOTAN_UNSTABLE_API Certificate_Verify : public Handshake_Message { |
756 | | public: |
757 | 6 | Handshake_Type type() const override { return Handshake_Type::CertificateVerify; } |
758 | | |
759 | 0 | Signature_Scheme signature_scheme() const { return m_scheme; } |
760 | | |
761 | | explicit Certificate_Verify(const std::vector<uint8_t>& buf); |
762 | 0 | Certificate_Verify() = default; |
763 | | |
764 | | std::vector<uint8_t> serialize() const override; |
765 | | |
766 | | protected: |
767 | | std::vector<uint8_t> m_signature; // NOLINT(*non-private-member-variable*) |
768 | | Signature_Scheme m_scheme; // NOLINT(*non-private-member-variable*) |
769 | | }; |
770 | | |
771 | | /** |
772 | | * Certificate Verify Message |
773 | | */ |
774 | | class BOTAN_UNSTABLE_API Certificate_Verify_12 final : public Certificate_Verify { |
775 | | public: |
776 | | using Certificate_Verify::Certificate_Verify; |
777 | | |
778 | | Certificate_Verify_12(Handshake_IO& io, |
779 | | Handshake_State& state, |
780 | | const Policy& policy, |
781 | | RandomNumberGenerator& rng, |
782 | | const Private_Key* key); |
783 | | |
784 | | /** |
785 | | * Check the signature on a certificate verify message |
786 | | * @param cert the purported certificate |
787 | | * @param state the handshake state |
788 | | * @param policy the TLS policy |
789 | | */ |
790 | | bool verify(const X509_Certificate& cert, const Handshake_State& state, const Policy& policy) const; |
791 | | }; |
792 | | |
793 | | #if defined(BOTAN_HAS_TLS_13) |
794 | | |
795 | | /** |
796 | | * Certificate Verify Message |
797 | | */ |
798 | | class BOTAN_UNSTABLE_API Certificate_Verify_13 final : public Certificate_Verify { |
799 | | public: |
800 | | /** |
801 | | * Deserialize a Certificate message |
802 | | * @param buf the serialized message |
803 | | * @param side is this a Connection_Side::Server or Connection_Side::Client certificate message |
804 | | */ |
805 | | Certificate_Verify_13(const std::vector<uint8_t>& buf, Connection_Side side); |
806 | | |
807 | | Certificate_Verify_13(const Certificate_13& certificate_message, |
808 | | const std::vector<Signature_Scheme>& peer_allowed_schemes, |
809 | | std::string_view hostname, |
810 | | const Transcript_Hash& hash, |
811 | | Connection_Side whoami, |
812 | | Credentials_Manager& creds_mgr, |
813 | | const Policy& policy, |
814 | | Callbacks& callbacks, |
815 | | RandomNumberGenerator& rng); |
816 | | |
817 | | bool verify(const Public_Key& public_key, Callbacks& callbacks, const Transcript_Hash& transcript_hash) const; |
818 | | |
819 | | private: |
820 | | Connection_Side m_side; |
821 | | }; |
822 | | |
823 | | #endif |
824 | | |
825 | | /** |
826 | | * Finished Message |
827 | | */ |
828 | | class BOTAN_UNSTABLE_API Finished : public Handshake_Message { |
829 | | public: |
830 | | explicit Finished(const std::vector<uint8_t>& buf); |
831 | | |
832 | 2.78k | Handshake_Type type() const override { return Handshake_Type::Finished; } |
833 | | |
834 | | std::vector<uint8_t> verify_data() const; |
835 | | |
836 | | std::vector<uint8_t> serialize() const override; |
837 | | |
838 | | protected: |
839 | | using Handshake_Message::Handshake_Message; |
840 | | std::vector<uint8_t> m_verification_data; // NOLINT(*non-private-member-variable*) |
841 | | }; |
842 | | |
843 | | class BOTAN_UNSTABLE_API Finished_12 final : public Finished { |
844 | | public: |
845 | | using Finished::Finished; |
846 | | Finished_12(Handshake_IO& io, Handshake_State& state, Connection_Side side); |
847 | | |
848 | | bool verify(const Handshake_State& state, Connection_Side side) const; |
849 | | }; |
850 | | |
851 | | #if defined(BOTAN_HAS_TLS_13) |
852 | | class BOTAN_UNSTABLE_API Finished_13 final : public Finished { |
853 | | public: |
854 | | using Finished::Finished; |
855 | | Finished_13(Cipher_State* cipher_state, const Transcript_Hash& transcript_hash); |
856 | | |
857 | | bool verify(Cipher_State* cipher_state, const Transcript_Hash& transcript_hash) const; |
858 | | }; |
859 | | #endif |
860 | | |
861 | | /** |
862 | | * Hello Request Message |
863 | | */ |
864 | | class BOTAN_UNSTABLE_API Hello_Request final : public Handshake_Message { |
865 | | public: |
866 | 0 | Handshake_Type type() const override { return Handshake_Type::HelloRequest; } |
867 | | |
868 | | explicit Hello_Request(Handshake_IO& io); |
869 | | explicit Hello_Request(const std::vector<uint8_t>& buf); |
870 | | |
871 | | private: |
872 | | std::vector<uint8_t> serialize() const override; |
873 | | }; |
874 | | |
875 | | /** |
876 | | * Server Key Exchange Message |
877 | | */ |
878 | | class BOTAN_UNSTABLE_API Server_Key_Exchange final : public Handshake_Message { |
879 | | public: |
880 | 46.2k | Handshake_Type type() const override { return Handshake_Type::ServerKeyExchange; } |
881 | | |
882 | 24.7k | const std::vector<uint8_t>& params() const { return m_params; } |
883 | | |
884 | | bool verify(const Public_Key& server_key, const Handshake_State& state, const Policy& policy) const; |
885 | | |
886 | | // Only valid for certain kex types |
887 | | const PK_Key_Agreement_Key& server_kex_key() const; |
888 | | |
889 | | /** |
890 | | * @returns the agreed upon KEX group or std::nullopt if the KEX type does |
891 | | * not depend on a group |
892 | | */ |
893 | 7.22k | const std::optional<Group_Params>& shared_group() const { return m_shared_group; } |
894 | | |
895 | | Server_Key_Exchange(Handshake_IO& io, |
896 | | Handshake_State& state, |
897 | | const Policy& policy, |
898 | | Credentials_Manager& creds, |
899 | | RandomNumberGenerator& rng, |
900 | | const Private_Key* signing_key = nullptr); |
901 | | |
902 | | Server_Key_Exchange(const std::vector<uint8_t>& buf, |
903 | | Kex_Algo kex_alg, |
904 | | Auth_Method sig_alg, |
905 | | Protocol_Version version); |
906 | | |
907 | | private: |
908 | | std::vector<uint8_t> serialize() const override; |
909 | | |
910 | | std::unique_ptr<PK_Key_Agreement_Key> m_kex_key; |
911 | | std::optional<Group_Params> m_shared_group; |
912 | | |
913 | | std::vector<uint8_t> m_params; |
914 | | |
915 | | std::vector<uint8_t> m_signature; |
916 | | Signature_Scheme m_scheme; |
917 | | }; |
918 | | |
919 | | /** |
920 | | * Server Hello Done Message |
921 | | */ |
922 | | class BOTAN_UNSTABLE_API Server_Hello_Done final : public Handshake_Message { |
923 | | public: |
924 | 46.2k | Handshake_Type type() const override { return Handshake_Type::ServerHelloDone; } |
925 | | |
926 | | explicit Server_Hello_Done(Handshake_IO& io, Handshake_Hash& hash); |
927 | | explicit Server_Hello_Done(const std::vector<uint8_t>& buf); |
928 | | |
929 | | private: |
930 | | std::vector<uint8_t> serialize() const override; |
931 | | }; |
932 | | |
933 | | /** |
934 | | * New Session Ticket Message |
935 | | */ |
936 | | class BOTAN_UNSTABLE_API New_Session_Ticket_12 final : public Handshake_Message { |
937 | | public: |
938 | 0 | Handshake_Type type() const override { return Handshake_Type::NewSessionTicket; } |
939 | | |
940 | 32 | std::chrono::seconds ticket_lifetime_hint() const { return m_ticket_lifetime_hint; } |
941 | | |
942 | 64 | const Session_Ticket& ticket() const { return m_ticket; } |
943 | | |
944 | | New_Session_Ticket_12(Handshake_IO& io, |
945 | | Handshake_Hash& hash, |
946 | | Session_Ticket ticket, |
947 | | std::chrono::seconds lifetime); |
948 | | |
949 | | New_Session_Ticket_12(Handshake_IO& io, Handshake_Hash& hash); |
950 | | |
951 | | explicit New_Session_Ticket_12(const std::vector<uint8_t>& buf); |
952 | | |
953 | | std::vector<uint8_t> serialize() const override; |
954 | | |
955 | | private: |
956 | | std::chrono::seconds m_ticket_lifetime_hint{}; |
957 | | Session_Ticket m_ticket; |
958 | | }; |
959 | | |
960 | | #if defined(BOTAN_HAS_TLS_13) |
961 | | |
962 | | /// @brief Used to derive the ticket's PSK from the resumption_master_secret |
963 | | using Ticket_Nonce = Strong<std::vector<uint8_t>, struct Ticket_Nonce_>; |
964 | | |
965 | | class BOTAN_UNSTABLE_API New_Session_Ticket_13 final : public Handshake_Message { |
966 | | public: |
967 | 0 | Handshake_Type type() const override { return Handshake_Type::NewSessionTicket; } |
968 | | |
969 | | New_Session_Ticket_13(Ticket_Nonce nonce, |
970 | | const Session& session, |
971 | | const Session_Handle& handle, |
972 | | Callbacks& callbacks); |
973 | | |
974 | | New_Session_Ticket_13(const std::vector<uint8_t>& buf, Connection_Side from); |
975 | | |
976 | | std::vector<uint8_t> serialize() const override; |
977 | | |
978 | 0 | const Extensions& extensions() const { return m_extensions; } |
979 | | |
980 | 0 | const Opaque_Session_Handle& handle() const { return m_handle; } |
981 | | |
982 | 0 | const Ticket_Nonce& nonce() const { return m_ticket_nonce; } |
983 | | |
984 | 0 | uint32_t ticket_age_add() const { return m_ticket_age_add; } |
985 | | |
986 | 0 | std::chrono::seconds lifetime_hint() const { return m_ticket_lifetime_hint; } |
987 | | |
988 | | /** |
989 | | * @return the number of bytes allowed for early data or std::nullopt |
990 | | * when early data is not allowed at all |
991 | | */ |
992 | | std::optional<uint32_t> early_data_byte_limit() const; |
993 | | |
994 | | private: |
995 | | // RFC 8446 4.6.1 |
996 | | // Clients MUST NOT cache tickets for longer than 7 days, regardless of |
997 | | // the ticket_lifetime, and MAY delete tickets earlier based on local |
998 | | // policy. A server MAY treat a ticket as valid for a shorter period |
999 | | // of time than what is stated in the ticket_lifetime. |
1000 | | // |
1001 | | // ... hence we call it 'lifetime hint'. |
1002 | | std::chrono::seconds m_ticket_lifetime_hint{}; |
1003 | | uint32_t m_ticket_age_add; |
1004 | | Ticket_Nonce m_ticket_nonce; |
1005 | | Opaque_Session_Handle m_handle; |
1006 | | Extensions m_extensions; |
1007 | | }; |
1008 | | |
1009 | | #endif |
1010 | | |
1011 | | /** |
1012 | | * Change Cipher Spec |
1013 | | */ |
1014 | | class BOTAN_UNSTABLE_API Change_Cipher_Spec final : public Handshake_Message { |
1015 | | public: |
1016 | 1.38k | Handshake_Type type() const override { return Handshake_Type::HandshakeCCS; } |
1017 | | |
1018 | 1.38k | std::vector<uint8_t> serialize() const override { return std::vector<uint8_t>(1, 1); } |
1019 | | }; |
1020 | | |
1021 | | #if defined(BOTAN_HAS_TLS_13) |
1022 | | |
1023 | | class BOTAN_UNSTABLE_API Key_Update final : public Handshake_Message { |
1024 | | public: |
1025 | 0 | Handshake_Type type() const override { return Handshake_Type::KeyUpdate; } |
1026 | | |
1027 | | explicit Key_Update(bool request_peer_update); |
1028 | | explicit Key_Update(const std::vector<uint8_t>& buf); |
1029 | | |
1030 | | std::vector<uint8_t> serialize() const override; |
1031 | | |
1032 | 0 | bool expects_reciprocation() const { return m_update_requested; } |
1033 | | |
1034 | | private: |
1035 | | bool m_update_requested; |
1036 | | }; |
1037 | | |
1038 | | namespace detail { |
1039 | | template <typename T> |
1040 | | struct as_wrapped_references {}; |
1041 | | |
1042 | | template <typename... AlternativeTs> |
1043 | | struct as_wrapped_references<std::variant<AlternativeTs...>> { |
1044 | | using type = std::variant<std::reference_wrapper<AlternativeTs>...>; |
1045 | | }; |
1046 | | |
1047 | | template <typename T> |
1048 | | using as_wrapped_references_t = typename as_wrapped_references<T>::type; |
1049 | | } // namespace detail |
1050 | | |
1051 | | // Handshake message types from RFC 8446 4. |
1052 | | using Handshake_Message_13 = std::variant<Client_Hello_13, |
1053 | | Client_Hello_12, |
1054 | | Server_Hello_13, |
1055 | | Server_Hello_12, |
1056 | | Hello_Retry_Request, |
1057 | | // End_Of_Early_Data, |
1058 | | Encrypted_Extensions, |
1059 | | Certificate_13, |
1060 | | Certificate_Request_13, |
1061 | | Certificate_Verify_13, |
1062 | | Finished_13>; |
1063 | | using Handshake_Message_13_Ref = detail::as_wrapped_references_t<Handshake_Message_13>; |
1064 | | |
1065 | | using Post_Handshake_Message_13 = std::variant<New_Session_Ticket_13, Key_Update>; |
1066 | | |
1067 | | // Key_Update is handled generically by the Channel. The messages assigned |
1068 | | // to those variants are the ones that need to be handled by the specific |
1069 | | // client and/or server implementations. |
1070 | | using Server_Post_Handshake_13_Message = std::variant<New_Session_Ticket_13, Key_Update>; |
1071 | | using Client_Post_Handshake_13_Message = std::variant<Key_Update>; |
1072 | | |
1073 | | using Server_Handshake_13_Message = std::variant<Server_Hello_13, |
1074 | | Server_Hello_12, // indicates a TLS version downgrade |
1075 | | Hello_Retry_Request, |
1076 | | Encrypted_Extensions, |
1077 | | Certificate_13, |
1078 | | Certificate_Request_13, |
1079 | | Certificate_Verify_13, |
1080 | | Finished_13>; |
1081 | | using Server_Handshake_13_Message_Ref = detail::as_wrapped_references_t<Server_Handshake_13_Message>; |
1082 | | |
1083 | | using Client_Handshake_13_Message = std::variant<Client_Hello_13, |
1084 | | Client_Hello_12, // indicates a TLS peer that does not offer TLS 1.3 |
1085 | | Certificate_13, |
1086 | | Certificate_Verify_13, |
1087 | | Finished_13>; |
1088 | | using Client_Handshake_13_Message_Ref = detail::as_wrapped_references_t<Client_Handshake_13_Message>; |
1089 | | |
1090 | | #endif // BOTAN_HAS_TLS_13 |
1091 | | |
1092 | | } // namespace TLS |
1093 | | |
1094 | | } // namespace Botan |
1095 | | |
1096 | | #endif |