Botan 3.13.0
Crypto and TLS for C&
tls_handshake_state_13.h
Go to the documentation of this file.
1/*
2* TLS handshake state (machine) implementation for TLS 1.3
3* (C) 2022 Jack Lloyd
4* 2022 Hannes Rantzsch, René Meusel - neXenio GmbH
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#ifndef BOTAN_TLS_HANDSHAKE_STATE_13_H_
10#define BOTAN_TLS_HANDSHAKE_STATE_13_H_
11
12#include <botan/tls_exceptn.h>
13#include <botan/tls_magic.h>
14#include <botan/tls_messages_13.h>
15#include <botan/internal/stl_util.h>
16#include <optional>
17#include <utility>
18#include <variant>
19
20namespace Botan::TLS {
21
22namespace Internal {
24 public:
25 bool has_client_hello() const { return m_client_hello.has_value(); }
26
27 bool has_server_hello() const { return m_server_hello.has_value(); }
28
29 bool has_server_certificate_msg() const { return m_server_certificate.has_value(); }
30
31 bool has_client_certificate_msg() const { return m_client_certificate.has_value(); }
32
33 bool has_hello_retry_request() const { return m_hello_retry_request.has_value(); }
34
35 bool has_certificate_request() const { return m_certificate_request.has_value(); }
36
37 bool has_server_finished() const { return m_server_finished.has_value(); }
38
39 bool has_client_finished() const { return m_client_finished.has_value(); }
40
41 bool handshake_finished() const {
42 return has_server_finished() && has_client_finished() && m_peer_finished_verified;
43 }
44
45 /**
46 * Once the implementation has successfully verified the peer's Finished
47 * message, the handshake is considered complete and successful.
48 */
49 void confirm_peer_finished_verified() { m_peer_finished_verified = true; }
50
51 // Client_Hello_13 cannot be const because it might need modification due to a Hello_Retry_Request
52 Client_Hello_13& client_hello() { return get(m_client_hello); }
53
54 const Client_Hello_13& client_hello() const { return get(m_client_hello); }
55
56 const Server_Hello_13& server_hello() const { return get(m_server_hello); }
57
58 const Hello_Retry_Request& hello_retry_request() const { return get(m_hello_retry_request); }
59
60 const Encrypted_Extensions& encrypted_extensions() const { return get(m_encrypted_extensions); }
61
62 const Certificate_Request_13& certificate_request() const { return get(m_certificate_request); }
63
64 const Certificate_13& server_certificate() const { return get(m_server_certificate); }
65
66 const Certificate_13& client_certificate() const { return get(m_client_certificate); }
67
68 const Certificate_Verify_13& server_certificate_verify() const { return get(m_server_certificate_verify); }
69
70 const Certificate_Verify_13& client_certificate_verify() const { return get(m_client_certificate_verify); }
71
72 const Finished_13& server_finished() const { return get(m_server_finished); }
73
74 const Finished_13& client_finished() const { return get(m_client_finished); }
75
76#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
77 /**
78 * This extracts the Client Hello object from the handshake state. This is
79 * a destructive operation that should only be used for protocol
80 * downgrades, where the Client Hello is transferred to the other
81 * implementation.
82 */
83 Client_Hello_13 take_client_hello() {
84 BOTAN_STATE_CHECK(m_client_hello.has_value());
85 return std::exchange(m_client_hello, {}).value();
86 }
87#endif
88
89 protected:
90 explicit Handshake_State_13_Base(Connection_Side whoami) : m_side(whoami) {}
91
92 Client_Hello_13& store(Client_Hello_13 client_hello, bool from_peer);
93 Client_Hello_12_Shim& store(Client_Hello_12_Shim client_hello, bool from_peer);
94 Server_Hello_13& store(Server_Hello_13 server_hello, bool from_peer);
95 Server_Hello_12_Shim& store(Server_Hello_12_Shim server_hello, bool from_peer);
96 Hello_Retry_Request& store(Hello_Retry_Request hello_retry_request, bool from_peer);
97 Encrypted_Extensions& store(Encrypted_Extensions encrypted_extensions, bool from_peer);
98 Certificate_Request_13& store(Certificate_Request_13 certificate_request, bool from_peer);
99 Certificate_13& store(Certificate_13 certificate, bool from_peer);
100 Certificate_Verify_13& store(Certificate_Verify_13 certificate_verify, bool from_peer);
101 Finished_13& store(Finished_13 finished, bool from_peer);
102
103 private:
104 template <typename MessageT>
105 const MessageT& get(const std::optional<MessageT>& opt) const {
106 if(!opt.has_value()) {
107 throw Invalid_State("TLS handshake message not set");
108 }
109 return opt.value();
110 }
111
112 template <typename MessageT>
113 MessageT& get(std::optional<MessageT>& opt) {
114 if(!opt.has_value()) {
115 throw Invalid_State("TLS handshake message not set");
116 }
117 return opt.value();
118 }
119
120 Connection_Side m_side;
121 bool m_peer_finished_verified = false;
122
123 std::optional<Client_Hello_13> m_client_hello;
124 std::optional<Client_Hello_12_Shim> m_client_hello_12;
125 std::optional<Server_Hello_13> m_server_hello;
126 std::optional<Server_Hello_12_Shim> m_server_hello_12;
127 std::optional<Hello_Retry_Request> m_hello_retry_request;
128 std::optional<Encrypted_Extensions> m_encrypted_extensions;
129 std::optional<Certificate_Request_13> m_certificate_request;
130 std::optional<Certificate_13> m_server_certificate;
131 std::optional<Certificate_13> m_client_certificate;
132 std::optional<Certificate_Verify_13> m_server_certificate_verify;
133 std::optional<Certificate_Verify_13> m_client_certificate_verify;
134 std::optional<Finished_13> m_server_finished;
135 std::optional<Finished_13> m_client_finished;
136};
137} // namespace Internal
138
139/**
140 * Place to store TLS handshake messages
141 *
142 * This class is used to keep all handshake messages that have been received from and sent to
143 * the peer as part of the TLS 1.3 handshake. Getters are provided for all message types.
144 * Specializations for the client and server side provide specific setters in the form of
145 * `sent` and `received` that only allow those types of handshake messages that are sensible
146 * for the respective connection side.
147 *
148 * The handshake state machine as described in RFC 8446 Appendix A is NOT validated here.
149 */
150template <Connection_Side whoami,
151 typename Outbound_Message_T,
152 typename Inbound_Message_T,
153 typename Inbound_Post_Handshake_Message_T>
155 public:
157
158 template <typename MsgT>
159 std::reference_wrapper<MsgT> sending(MsgT msg)
160 requires(std::is_constructible_v<Outbound_Message_T, MsgT>)
161 {
162 return std::reference_wrapper<decltype(msg)>(store(std::move(msg), false));
163 }
164
165 template <typename... MsgTs>
166 decltype(auto) sending(std::variant<MsgTs...> message)
168 {
169 return std::visit(
170 [&](auto msg) -> detail::as_wrapped_references_t<std::variant<MsgTs...>> {
171 return sending(std::move(msg));
172 },
173 std::move(message));
174 }
175
176 decltype(auto) received(Handshake_Message_13 message) {
177 return std::visit(
179 if constexpr(std::is_constructible_v<Inbound_Message_T, decltype(msg)>) {
180 return std::reference_wrapper<decltype(msg)>(store(std::move(msg), true));
181 } else {
182 throw TLS_Exception(AlertType::UnexpectedMessage, "received an illegal handshake message");
183 }
184 },
185 std::move(message));
186 }
187
188 decltype(auto) received(Post_Handshake_Message_13 message) {
189 return std::visit(
190 [](auto msg) -> Inbound_Post_Handshake_Message_T {
191 if constexpr(std::is_constructible_v<Inbound_Post_Handshake_Message_T, decltype(msg)>) {
192 return msg;
193 } else {
194 throw TLS_Exception(AlertType::UnexpectedMessage, "received an unexpected post-handshake message");
195 }
196 },
197 std::move(message));
198 }
199};
200
205
210} // namespace Botan::TLS
211
212#endif
#define BOTAN_TEST_API
Definition api.h:41
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
std::reference_wrapper< MsgT > sending(MsgT msg)
decltype(auto) received(Handshake_Message_13 message)
decltype(auto) sending(std::variant< MsgTs... > message)
decltype(auto) received(Post_Handshake_Message_13 message)
const Hello_Retry_Request & hello_retry_request() const
const Certificate_Verify_13 & client_certificate_verify() const
const Certificate_Request_13 & certificate_request() const
const Encrypted_Extensions & encrypted_extensions() const
const Certificate_Verify_13 & server_certificate_verify() const
typename as_wrapped_references< T >::type as_wrapped_references_t
Handshake_State_13< Connection_Side::Server, Server_Handshake_13_Message, Client_Handshake_13_Message, Client_Post_Handshake_13_Message > Server_Handshake_State_13
std::variant< Server_Hello_13, Server_Hello_12_Shim, Hello_Retry_Request, Encrypted_Extensions, Certificate_13, Certificate_Request_13, Certificate_Verify_13, Finished_13 > Server_Handshake_13_Message
Handshake_State_13< Connection_Side::Client, Client_Handshake_13_Message, Server_Handshake_13_Message, Server_Post_Handshake_13_Message > Client_Handshake_State_13
std::variant< Key_Update > Client_Post_Handshake_13_Message
std::variant< Client_Hello_13, Client_Hello_12_Shim, Certificate_13, Certificate_Verify_13, Finished_13 > Client_Handshake_13_Message
std::variant< Client_Hello_13, Client_Hello_12_Shim, Server_Hello_13, Server_Hello_12_Shim, Hello_Retry_Request, Encrypted_Extensions, Certificate_13, Certificate_Request_13, Certificate_Verify_13, Finished_13 > Handshake_Message_13
std::variant< New_Session_Ticket_13, Key_Update > Post_Handshake_Message_13
std::variant< New_Session_Ticket_13, Key_Update > Server_Post_Handshake_13_Message
constexpr bool is_generalizable_to(const SpecialT &) noexcept
Definition stl_util.h:71