Botan 3.11.0
Crypto and TLS for C&
msg_client_hello_12.cpp
Go to the documentation of this file.
1/*
2* TLS Hello Request and Client Hello Messages
3* (C) 2004-2011,2015,2016 Jack Lloyd
4* 2016 Matthias Gierlings
5* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#include <botan/tls_messages_12.h>
11
12#include <botan/tls_callbacks.h>
13#include <botan/tls_exceptn.h>
14#include <botan/tls_extensions_12.h>
15#include <botan/tls_policy.h>
16#include <botan/internal/stl_util.h>
17#include <botan/internal/tls_handshake_hash.h>
18#include <botan/internal/tls_handshake_io.h>
19#include <botan/internal/tls_messages_internal.h>
20
21namespace Botan::TLS {
22
24 BOTAN_STATE_CHECK(m_data->legacy_version().is_datagram_protocol());
25
26 m_data->m_hello_cookie = hello_verify.cookie();
27}
28
30 if(const Supported_Point_Formats* ecc_formats = m_data->extensions().get<Supported_Point_Formats>()) {
31 return ecc_formats->prefers_compressed();
32 }
33 return false;
34}
35
37 return m_data->extensions().has<Renegotiation_Extension>();
38}
39
40std::vector<uint8_t> Client_Hello_12::renegotiation_info() const {
41 if(const Renegotiation_Extension* reneg = m_data->extensions().get<Renegotiation_Extension>()) {
42 return reneg->renegotiation_info();
43 }
44 return {};
45}
46
48 return m_data->extensions().has<Session_Ticket_Extension>();
49}
50
52 if(auto* ticket = m_data->extensions().get<Session_Ticket_Extension>()) {
53 return ticket->contents();
54 }
55 return {};
56}
57
58std::optional<Session_Handle> Client_Hello_12::session_handle() const {
59 // RFC 5077 3.4
60 // If a ticket is presented by the client, the server MUST NOT attempt
61 // to use the Session ID in the ClientHello for stateful session
62 // resumption.
63 if(auto ticket = session_ticket(); !ticket.empty()) {
64 return Session_Handle(ticket);
65 } else if(const auto& id = session_id(); !id.empty()) {
66 return Session_Handle(id);
67 } else {
68 return std::nullopt;
69 }
70}
71
73 return m_data->extensions().has<Extended_Master_Secret>();
74}
75
77 return m_data->extensions().has<Certificate_Status_Request>();
78}
79
81 return m_data->extensions().has<Encrypt_then_MAC>();
82}
83
84void Client_Hello_12::add_tls12_supported_groups_extensions(const Policy& policy) {
85 // RFC 7919 3.
86 // A client that offers a group MUST be able and willing to perform a DH
87 // key exchange using that group.
88 //
89 // We don't support hybrid key exchange in TLS 1.2
90
91 std::vector<Group_Params> compatible_kex_groups;
92 for(const auto& group : policy.key_exchange_groups()) {
93 if(!group.is_post_quantum()) {
94 compatible_kex_groups.push_back(group);
95 }
96 }
97
98 auto supported_groups = std::make_unique<Supported_Groups>(std::move(compatible_kex_groups));
99
100 if(!supported_groups->ec_groups().empty()) {
101 // NOLINTNEXTLINE(*-owning-memory)
102 m_data->extensions().add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
103 }
104
105 m_data->extensions().add(std::move(supported_groups));
106}
107
108/*
109* Create a new Client Hello message
110*/
112 Handshake_Hash& hash,
113 const Policy& policy,
114 Callbacks& cb,
116 const std::vector<uint8_t>& reneg_info,
117 const Client_Hello_12::Settings& client_settings,
118 const std::vector<std::string>& next_protocols) {
119 m_data->m_legacy_version = client_settings.protocol_version();
120 m_data->m_random = make_hello_random(rng, cb, policy);
121 m_data->m_suites = policy.ciphersuite_list(client_settings.protocol_version());
122
123 if(!policy.acceptable_protocol_version(m_data->legacy_version())) {
124 throw Internal_Error("Offering " + m_data->legacy_version().to_string() +
125 " but our own policy does not accept it");
126 }
127
128 /*
129 * Place all empty extensions in front to avoid a bug in some systems
130 * which reject hellos when the last extension in the list is empty.
131 */
132
133 // NOLINTBEGIN(*-owning-memory)
134
135 // EMS must always be used with TLS 1.2, regardless of the policy used.
136
137 m_data->extensions().add(new Extended_Master_Secret);
138
139 if(policy.negotiate_encrypt_then_mac()) {
140 m_data->extensions().add(new Encrypt_then_MAC);
141 }
142
143 m_data->extensions().add(new Session_Ticket_Extension());
144
145 m_data->extensions().add(new Renegotiation_Extension(reneg_info));
146
147 m_data->extensions().add(new Supported_Versions(m_data->legacy_version(), policy));
148
150 m_data->extensions().add(new Server_Name_Indicator(client_settings.hostname()));
151 }
152
153 if(policy.support_cert_status_message()) {
154 m_data->extensions().add(new Certificate_Status_Request({}, {}));
155 }
156
157 add_tls12_supported_groups_extensions(policy);
158
159 m_data->extensions().add(new Signature_Algorithms(policy.acceptable_signature_schemes()));
160 if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) {
161 // RFC 8446 4.2.3
162 // TLS 1.2 implementations SHOULD also process this extension.
163 // Implementations which have the same policy in both cases MAY omit
164 // the "signature_algorithms_cert" extension.
165 m_data->extensions().add(new Signature_Algorithms_Cert(std::move(cert_signing_prefs.value())));
166 }
167
168 if(reneg_info.empty() && !next_protocols.empty()) {
170 }
171
172 if(m_data->legacy_version().is_datagram_protocol()) {
173 m_data->extensions().add(new SRTP_Protection_Profiles(policy.srtp_profiles()));
174 }
175
176 // NOLINTEND(*-owning-memory)
177
179
180 hash.update(io.send(*this));
181}
182
183/*
184* Create a new Client Hello message (session resumption case)
185*/
187 Handshake_Hash& hash,
188 const Policy& policy,
189 Callbacks& cb,
191 const std::vector<uint8_t>& reneg_info,
192 const Session_with_Handle& session,
193 const std::vector<std::string>& next_protocols) {
194 m_data->m_legacy_version = session.session.version();
195 m_data->m_random = make_hello_random(rng, cb, policy);
196
197 // RFC 5077 3.4
198 // When presenting a ticket, the client MAY generate and include a
199 // Session ID in the TLS ClientHello. [...] If a ticket is presented by
200 // the client, the server MUST NOT attempt to use the Session ID in the
201 // ClientHello for stateful session resumption.
202 m_data->m_session_id = session.handle.id().value_or(Session_ID(make_hello_random(rng, cb, policy)));
203 m_data->m_suites = policy.ciphersuite_list(m_data->legacy_version());
204
205 if(!policy.acceptable_protocol_version(session.session.version())) {
206 throw Internal_Error("Offering " + m_data->legacy_version().to_string() +
207 " but our own policy does not accept it");
208 }
209
210 if(!value_exists(m_data->ciphersuites(), session.session.ciphersuite_code())) {
211 m_data->m_suites.push_back(session.session.ciphersuite_code());
212 }
213
214 /*
215 * As EMS must always be used with TLS 1.2, add it even if it wasn't used
216 * in the original session. If the server understands it and follows the
217 * RFC it should reject our resume attempt and upgrade us to a new session
218 * with the EMS protection.
219 */
220 // NOLINTBEGIN(*-owning-memory)
221 m_data->extensions().add(new Extended_Master_Secret);
222
223 if(session.session.supports_encrypt_then_mac()) {
224 m_data->extensions().add(new Encrypt_then_MAC);
225 }
226
227 if(session.handle.is_ticket()) {
228 m_data->extensions().add(new Session_Ticket_Extension(session.handle.ticket().value()));
229 }
230
231 m_data->extensions().add(new Renegotiation_Extension(reneg_info));
232
233 const std::string hostname = session.session.server_info().hostname();
234
236 m_data->extensions().add(new Server_Name_Indicator(hostname));
237 }
238
239 if(policy.support_cert_status_message()) {
240 m_data->extensions().add(new Certificate_Status_Request({}, {}));
241 }
242
243 add_tls12_supported_groups_extensions(policy);
244
245 m_data->extensions().add(new Signature_Algorithms(policy.acceptable_signature_schemes()));
246 if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) {
247 // RFC 8446 4.2.3
248 // TLS 1.2 implementations SHOULD also process this extension.
249 // Implementations which have the same policy in both cases MAY omit
250 // the "signature_algorithms_cert" extension.
251 m_data->extensions().add(new Signature_Algorithms_Cert(std::move(cert_signing_prefs.value())));
252 }
253
254 if(reneg_info.empty() && !next_protocols.empty()) {
256 }
257 // NOLINTEND(*-owning-memory)
258
260
261 hash.update(io.send(*this));
262}
263
264Client_Hello_12::Client_Hello_12(const std::vector<uint8_t>& buf) :
265 Client_Hello_12(std::make_unique<Client_Hello_Internal>(buf)) {}
266
267Client_Hello_12::Client_Hello_12(std::unique_ptr<Client_Hello_Internal> data) : Client_Hello_12_Shim(std::move(data)) {
268 const uint16_t TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
269
270 if(offered_suite(static_cast<uint16_t>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV))) {
271 if(const Renegotiation_Extension* reneg = m_data->extensions().get<Renegotiation_Extension>()) {
272 if(!reneg->renegotiation_info().empty()) {
273 throw TLS_Exception(Alert::HandshakeFailure, "Client sent renegotiation SCSV and non-empty extension");
274 }
275 } else {
276 // add fake extension
277 m_data->extensions().add(new Renegotiation_Extension()); // NOLINT(*-owning-memory)
278 }
279 }
280}
281
285
286Hello_Request::Hello_Request(const std::vector<uint8_t>& buf) {
287 if(!buf.empty()) {
288 throw Decoding_Error("Bad Hello_Request, has non-zero size");
289 }
290}
291
292std::vector<uint8_t> Hello_Request::serialize() const {
293 return std::vector<uint8_t>();
294}
295
296} // namespace Botan::TLS
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
virtual void tls_modify_extensions(Extensions &extn, Connection_Side which_side, Handshake_Type which_message)
const std::string & hostname() const
Protocol_Version protocol_version() const
void update_hello_cookie(const Hello_Verify_Request &hello_verify)
std::vector< uint8_t > renegotiation_info() const
Session_Ticket session_ticket() const
std::optional< Session_Handle > session_handle() const
Client_Hello_12(Handshake_IO &io, Handshake_Hash &hash, const Policy &policy, Callbacks &cb, RandomNumberGenerator &rng, const std::vector< uint8_t > &reneg_info, const Settings &client_settings, const std::vector< std::string > &next_protocols)
bool offered_suite(uint16_t ciphersuite) const
std::unique_ptr< Client_Hello_Internal > m_data
std::vector< std::string > next_protocols() const
const Session_ID & session_id() const
Handshake_Type type() const override
void update(const uint8_t in[], size_t length)
virtual std::vector< uint8_t > send(const Handshake_Message &msg)=0
virtual std::vector< uint8_t > serialize() const =0
const std::vector< uint8_t > & cookie() const
virtual std::vector< uint16_t > ciphersuite_list(Protocol_Version version) const
virtual std::vector< Group_Params > key_exchange_groups() const
virtual bool negotiate_encrypt_then_mac() const
virtual bool acceptable_protocol_version(Protocol_Version version) const
virtual std::vector< uint16_t > srtp_profiles() const
virtual bool support_cert_status_message() const
virtual std::optional< std::vector< Signature_Scheme > > acceptable_certificate_signature_schemes() const
virtual std::vector< Signature_Scheme > acceptable_signature_schemes() const
virtual bool use_ecc_point_compression() const
static bool hostname_acceptable_for_sni(std::string_view hostname)
Protocol_Version version() const
Definition tls_session.h:75
bool supports_encrypt_then_mac() const
uint16_t ciphersuite_code() const
Definition tls_session.h:80
const Server_Information & server_info() const
Helper class to embody a session handle in all protocol versions.
std::optional< Session_Ticket > ticket() const
std::optional< Session_ID > id() const
bool empty() const noexcept(noexcept(this->get().empty()))
std::vector< uint8_t > make_hello_random(RandomNumberGenerator &rng, Callbacks &cb, const Policy &policy)
Strong< std::vector< uint8_t >, struct Session_ID_ > Session_ID
holds a TLS 1.2 session ID for stateful resumption
Strong< std::vector< uint8_t >, struct Session_Ticket_ > Session_Ticket
holds a TLS 1.2 session ticket for stateless resumption
bool value_exists(const std::vector< T > &vec, const V &val)
Definition stl_util.h:43