/src/botan/src/lib/tls/msg_server_hello.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * TLS Server Hello and Server Hello Done |
3 | | * (C) 2004-2011,2015,2016,2019 Jack Lloyd |
4 | | * 2016 Matthias Gierlings |
5 | | * 2017 Harry Reimann, Rohde & Schwarz Cybersecurity |
6 | | * 2021 Elektrobit Automotive GmbH |
7 | | * 2022 René Meusel, Hannes Rantzsch - neXenio GmbH |
8 | | * |
9 | | * Botan is released under the Simplified BSD License (see license.txt) |
10 | | */ |
11 | | |
12 | | #include <botan/tls_messages.h> |
13 | | |
14 | | #include <botan/tls_extensions.h> |
15 | | #include <botan/tls_exceptn.h> |
16 | | #include <botan/tls_callbacks.h> |
17 | | #include <botan/internal/tls_reader.h> |
18 | | #include <botan/mem_ops.h> |
19 | | #include <botan/internal/tls_session_key.h> |
20 | | #include <botan/internal/tls_handshake_io.h> |
21 | | #include <botan/internal/tls_handshake_hash.h> |
22 | | |
23 | | #include <array> |
24 | | |
25 | | namespace Botan::TLS { |
26 | | |
27 | | namespace { |
28 | | |
29 | | const uint64_t DOWNGRADE_TLS11 = 0x444F574E47524400; |
30 | | const uint64_t DOWNGRADE_TLS12 = 0x444F574E47524401; |
31 | | |
32 | | std::vector<uint8_t> |
33 | | make_server_hello_random(RandomNumberGenerator& rng, |
34 | | Protocol_Version offered_version, |
35 | | Callbacks& cb, |
36 | | const Policy& policy) |
37 | 19.7k | { |
38 | 19.7k | BOTAN_UNUSED(offered_version); |
39 | 19.7k | auto random = make_hello_random(rng, cb, policy); |
40 | 19.7k | return random; |
41 | 19.7k | } |
42 | | |
43 | | } |
44 | | |
45 | | /* |
46 | | * Deserialize a Server Hello message |
47 | | */ |
48 | | Server_Hello::Internal::Internal(const std::vector<uint8_t>& buf) |
49 | 887 | { |
50 | 887 | if(buf.size() < 38) |
51 | 21 | { |
52 | 21 | throw Decoding_Error("Server_Hello: Packet corrupted"); |
53 | 21 | } |
54 | | |
55 | 866 | TLS_Data_Reader reader("ServerHello", buf); |
56 | | |
57 | 866 | const uint8_t major_version = reader.get_byte(); |
58 | 866 | const uint8_t minor_version = reader.get_byte(); |
59 | | |
60 | 866 | legacy_version = Protocol_Version(major_version, minor_version); |
61 | | |
62 | 866 | random = reader.get_fixed<uint8_t>(32); |
63 | | |
64 | 866 | session_id = reader.get_range<uint8_t>(1, 0, 32); |
65 | 866 | ciphersuite = reader.get_uint16_t(); |
66 | 866 | comp_method = reader.get_byte(); |
67 | | |
68 | 866 | extensions.deserialize(reader, Connection_Side::SERVER, |
69 | 866 | Handshake_Type::SERVER_HELLO); |
70 | 866 | } |
71 | | |
72 | | |
73 | | Server_Hello::Internal::Internal(Protocol_Version lv, |
74 | | std::vector<uint8_t> sid, |
75 | | std::vector<uint8_t> r, |
76 | | const uint16_t cs, |
77 | | const uint8_t cm) |
78 | | : legacy_version(lv) |
79 | | , session_id(std::move(sid)) |
80 | | , random(std::move(r)) |
81 | | , ciphersuite(cs) |
82 | 19.7k | , comp_method(cm) {} |
83 | | |
84 | | |
85 | | Protocol_Version Server_Hello::Internal::version() const |
86 | 0 | { |
87 | 0 | return legacy_version; |
88 | 0 | } |
89 | | |
90 | | |
91 | | /* |
92 | | * Serialize a Server Hello message |
93 | | */ |
94 | | std::vector<uint8_t> Server_Hello::serialize() const |
95 | 19.7k | { |
96 | 19.7k | std::vector<uint8_t> buf; |
97 | | |
98 | 19.7k | buf.push_back(m_data->legacy_version.major_version()); |
99 | 19.7k | buf.push_back(m_data->legacy_version.minor_version()); |
100 | 19.7k | buf += m_data->random; |
101 | | |
102 | 19.7k | append_tls_length_value(buf, m_data->session_id, 1); |
103 | | |
104 | 19.7k | buf.push_back(get_byte<0>(m_data->ciphersuite)); |
105 | 19.7k | buf.push_back(get_byte<1>(m_data->ciphersuite)); |
106 | | |
107 | 19.7k | buf.push_back(m_data->comp_method); |
108 | | |
109 | 19.7k | buf += m_data->extensions.serialize(Connection_Side::SERVER); |
110 | | |
111 | 19.7k | return buf; |
112 | 19.7k | } |
113 | | |
114 | | |
115 | | Handshake_Type Server_Hello::type() const |
116 | 39.5k | { |
117 | 39.5k | return SERVER_HELLO; |
118 | 39.5k | } |
119 | | |
120 | | Protocol_Version Server_Hello::legacy_version() const |
121 | 429 | { |
122 | 429 | return m_data->legacy_version; |
123 | 429 | } |
124 | | |
125 | | const std::vector<uint8_t>& Server_Hello::random() const |
126 | 26.2k | { |
127 | 26.2k | return m_data->random; |
128 | 26.2k | } |
129 | | |
130 | | uint8_t Server_Hello::compression_method() const |
131 | 857 | { |
132 | 857 | return m_data->comp_method; |
133 | 857 | } |
134 | | |
135 | | const std::vector<uint8_t>& Server_Hello::session_id() const |
136 | 451 | { |
137 | 451 | return m_data->session_id; |
138 | 451 | } |
139 | | |
140 | | uint16_t Server_Hello::ciphersuite() const |
141 | 20.2k | { |
142 | 20.2k | return m_data->ciphersuite; |
143 | 20.2k | } |
144 | | |
145 | | std::set<Handshake_Extension_Type> Server_Hello::extension_types() const |
146 | 0 | { |
147 | 0 | return m_data->extensions.extension_types(); |
148 | 0 | } |
149 | | |
150 | | const Extensions& Server_Hello::extensions() const |
151 | 0 | { |
152 | 0 | return m_data->extensions; |
153 | 0 | } |
154 | | |
155 | | // New session case |
156 | | Server_Hello_12::Server_Hello_12(Handshake_IO& io, |
157 | | Handshake_Hash& hash, |
158 | | const Policy& policy, |
159 | | Callbacks& cb, |
160 | | RandomNumberGenerator& rng, |
161 | | const std::vector<uint8_t>& reneg_info, |
162 | | const Client_Hello_12& client_hello, |
163 | | const Server_Hello_12::Settings& server_settings, |
164 | | const std::string& next_protocol) : |
165 | | Server_Hello(std::make_unique<Server_Hello::Internal>( |
166 | | server_settings.protocol_version(), |
167 | | server_settings.session_id(), |
168 | | make_server_hello_random(rng, server_settings.protocol_version(), cb, policy), |
169 | | server_settings.ciphersuite(), |
170 | | uint8_t(0))) |
171 | 19.7k | { |
172 | 19.7k | if(client_hello.supports_extended_master_secret()) |
173 | 887 | { |
174 | 887 | m_data->extensions.add(new Extended_Master_Secret); |
175 | 887 | } |
176 | | |
177 | | // Sending the extension back does not commit us to sending a stapled response |
178 | 19.7k | if(client_hello.supports_cert_status_message() && policy.support_cert_status_message()) |
179 | 2.02k | { |
180 | 2.02k | m_data->extensions.add(new Certificate_Status_Request); |
181 | 2.02k | } |
182 | | |
183 | 19.7k | if(!next_protocol.empty() && client_hello.supports_alpn()) |
184 | 3.39k | { |
185 | 3.39k | m_data->extensions.add(new Application_Layer_Protocol_Notification(next_protocol)); |
186 | 3.39k | } |
187 | | |
188 | 19.7k | const auto c = Ciphersuite::by_id(m_data->ciphersuite); |
189 | | |
190 | 19.7k | if(c && c->cbc_ciphersuite() && client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) |
191 | 2.44k | { |
192 | 2.44k | m_data->extensions.add(new Encrypt_then_MAC); |
193 | 2.44k | } |
194 | | |
195 | 19.7k | if(c && c->ecc_ciphersuite() && client_hello.extension_types().count(TLSEXT_EC_POINT_FORMATS)) |
196 | 3.51k | { |
197 | 3.51k | m_data->extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression())); |
198 | 3.51k | } |
199 | | |
200 | 19.7k | if(client_hello.secure_renegotiation()) |
201 | 11.0k | { |
202 | 11.0k | m_data->extensions.add(new Renegotiation_Extension(reneg_info)); |
203 | 11.0k | } |
204 | | |
205 | 19.7k | if(client_hello.supports_session_ticket() && server_settings.offer_session_ticket()) |
206 | 6.63k | { |
207 | 6.63k | m_data->extensions.add(new Session_Ticket()); |
208 | 6.63k | } |
209 | | |
210 | 19.7k | if(m_data->legacy_version.is_datagram_protocol()) |
211 | 0 | { |
212 | 0 | const std::vector<uint16_t> server_srtp = policy.srtp_profiles(); |
213 | 0 | const std::vector<uint16_t> client_srtp = client_hello.srtp_profiles(); |
214 | |
|
215 | 0 | if(!server_srtp.empty() && !client_srtp.empty()) |
216 | 0 | { |
217 | 0 | uint16_t shared = 0; |
218 | | // always using server preferences for now |
219 | 0 | for(auto s_srtp : server_srtp) |
220 | 0 | for(auto c_srtp : client_srtp) |
221 | 0 | { |
222 | 0 | if(shared == 0 && s_srtp == c_srtp) |
223 | 0 | { shared = s_srtp; } |
224 | 0 | } |
225 | |
|
226 | 0 | if(shared) |
227 | 0 | { |
228 | 0 | m_data->extensions.add(new SRTP_Protection_Profiles(shared)); |
229 | 0 | } |
230 | 0 | } |
231 | 0 | } |
232 | | |
233 | 19.7k | cb.tls_modify_extensions(m_data->extensions, SERVER); |
234 | | |
235 | 19.7k | hash.update(io.send(*this)); |
236 | 19.7k | } |
237 | | |
238 | | // Resuming |
239 | | Server_Hello_12::Server_Hello_12(Handshake_IO& io, |
240 | | Handshake_Hash& hash, |
241 | | const Policy& policy, |
242 | | Callbacks& cb, |
243 | | RandomNumberGenerator& rng, |
244 | | const std::vector<uint8_t>& reneg_info, |
245 | | const Client_Hello_12& client_hello, |
246 | | Session& resumed_session, |
247 | | bool offer_session_ticket, |
248 | | const std::string& next_protocol) : |
249 | | Server_Hello(std::make_unique<Server_Hello::Internal>( |
250 | | resumed_session.version(), |
251 | | client_hello.session_id(), |
252 | | make_hello_random(rng, cb, policy), |
253 | | resumed_session.ciphersuite_code(), |
254 | | uint8_t(0))) |
255 | 0 | { |
256 | 0 | if(client_hello.supports_extended_master_secret()) |
257 | 0 | { |
258 | 0 | m_data->extensions.add(new Extended_Master_Secret); |
259 | 0 | } |
260 | |
|
261 | 0 | if(!next_protocol.empty() && client_hello.supports_alpn()) |
262 | 0 | { |
263 | 0 | m_data->extensions.add(new Application_Layer_Protocol_Notification(next_protocol)); |
264 | 0 | } |
265 | |
|
266 | 0 | if(client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) |
267 | 0 | { |
268 | 0 | Ciphersuite c = resumed_session.ciphersuite(); |
269 | 0 | if(c.cbc_ciphersuite()) |
270 | 0 | { |
271 | 0 | m_data->extensions.add(new Encrypt_then_MAC); |
272 | 0 | } |
273 | 0 | } |
274 | |
|
275 | 0 | if(resumed_session.ciphersuite().ecc_ciphersuite() && client_hello.extension_types().count(TLSEXT_EC_POINT_FORMATS)) |
276 | 0 | { |
277 | 0 | m_data->extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression())); |
278 | 0 | } |
279 | |
|
280 | 0 | if(client_hello.secure_renegotiation()) |
281 | 0 | { |
282 | 0 | m_data->extensions.add(new Renegotiation_Extension(reneg_info)); |
283 | 0 | } |
284 | |
|
285 | 0 | if(client_hello.supports_session_ticket() && offer_session_ticket) |
286 | 0 | { |
287 | 0 | m_data->extensions.add(new Session_Ticket()); |
288 | 0 | } |
289 | |
|
290 | 0 | cb.tls_modify_extensions(m_data->extensions, SERVER); |
291 | |
|
292 | 0 | hash.update(io.send(*this)); |
293 | 0 | } |
294 | | |
295 | | |
296 | | Server_Hello_12::Server_Hello_12(const std::vector<uint8_t>& buf) |
297 | | : Server_Hello_12(std::make_unique<Server_Hello::Internal>(buf)) |
298 | 887 | {} |
299 | | |
300 | | Server_Hello_12::Server_Hello_12(std::unique_ptr<Server_Hello::Internal> data) |
301 | | : Server_Hello(std::move(data)) |
302 | 121 | { |
303 | 121 | } |
304 | | |
305 | | Protocol_Version Server_Hello_12::selected_version() const |
306 | 0 | { |
307 | 0 | return legacy_version(); |
308 | 0 | } |
309 | | |
310 | | bool Server_Hello_12::secure_renegotiation() const |
311 | 19.7k | { |
312 | 19.7k | return m_data->extensions.has<Renegotiation_Extension>(); |
313 | 19.7k | } |
314 | | |
315 | | std::vector<uint8_t> Server_Hello_12::renegotiation_info() const |
316 | 11.0k | { |
317 | 11.0k | if(Renegotiation_Extension* reneg = m_data->extensions.get<Renegotiation_Extension>()) |
318 | 11.0k | { return reneg->renegotiation_info(); } |
319 | 0 | return std::vector<uint8_t>(); |
320 | 11.0k | } |
321 | | |
322 | | bool Server_Hello_12::supports_extended_master_secret() const |
323 | 13.8k | { |
324 | 13.8k | return m_data->extensions.has<Extended_Master_Secret>(); |
325 | 13.8k | } |
326 | | |
327 | | bool Server_Hello_12::supports_encrypt_then_mac() const |
328 | 1.16k | { |
329 | 1.16k | return m_data->extensions.has<Encrypt_then_MAC>(); |
330 | 1.16k | } |
331 | | |
332 | | bool Server_Hello_12::supports_certificate_status_message() const |
333 | 0 | { |
334 | 0 | return m_data->extensions.has<Certificate_Status_Request>(); |
335 | 0 | } |
336 | | |
337 | | bool Server_Hello_12::supports_session_ticket() const |
338 | 435 | { |
339 | 435 | return m_data->extensions.has<Session_Ticket>(); |
340 | 435 | } |
341 | | |
342 | | uint16_t Server_Hello_12::srtp_profile() const |
343 | 308 | { |
344 | 308 | if(auto srtp = m_data->extensions.get<SRTP_Protection_Profiles>()) |
345 | 0 | { |
346 | 0 | auto prof = srtp->profiles(); |
347 | 0 | if(prof.size() != 1 || prof[0] == 0) |
348 | 0 | { throw Decoding_Error("Server sent malformed DTLS-SRTP extension"); } |
349 | 0 | return prof[0]; |
350 | 0 | } |
351 | | |
352 | 308 | return 0; |
353 | 308 | } |
354 | | |
355 | | std::string Server_Hello_12::next_protocol() const |
356 | 0 | { |
357 | 0 | if(auto alpn = m_data->extensions.get<Application_Layer_Protocol_Notification>()) |
358 | 0 | { |
359 | 0 | return alpn->single_protocol(); |
360 | 0 | } |
361 | 0 | return ""; |
362 | 0 | } |
363 | | |
364 | | bool Server_Hello_12::prefers_compressed_ec_points() const |
365 | 0 | { |
366 | 0 | if(auto ecc_formats = m_data->extensions.get<Supported_Point_Formats>()) |
367 | 0 | { |
368 | 0 | return ecc_formats->prefers_compressed(); |
369 | 0 | } |
370 | 0 | return false; |
371 | 0 | } |
372 | | |
373 | | std::optional<Protocol_Version> Server_Hello_12::random_signals_downgrade() const |
374 | 0 | { |
375 | 0 | const uint64_t last8 = load_be<uint64_t>(m_data->random.data(), 3); |
376 | 0 | if(last8 == DOWNGRADE_TLS11) |
377 | 0 | { return Protocol_Version::TLS_V11; } |
378 | 0 | if(last8 == DOWNGRADE_TLS12) |
379 | 0 | { return Protocol_Version::TLS_V12; } |
380 | | |
381 | 0 | return std::nullopt; |
382 | 0 | } |
383 | | |
384 | | |
385 | | /* |
386 | | * Create a new Server Hello Done message |
387 | | */ |
388 | | Server_Hello_Done::Server_Hello_Done(Handshake_IO& io, |
389 | | Handshake_Hash& hash) |
390 | 19.6k | { |
391 | 19.6k | hash.update(io.send(*this)); |
392 | 19.6k | } |
393 | | |
394 | | /* |
395 | | * Deserialize a Server Hello Done message |
396 | | */ |
397 | | Server_Hello_Done::Server_Hello_Done(const std::vector<uint8_t>& buf) |
398 | 0 | { |
399 | 0 | if(!buf.empty()) |
400 | 0 | { throw Decoding_Error("Server_Hello_Done: Must be empty, and is not"); } |
401 | 0 | } |
402 | | |
403 | | /* |
404 | | * Serialize a Server Hello Done message |
405 | | */ |
406 | | std::vector<uint8_t> Server_Hello_Done::serialize() const |
407 | 19.6k | { |
408 | 19.6k | return std::vector<uint8_t>(); |
409 | 19.6k | } |
410 | | |
411 | | } |