Branch data Line data Source code
1 : : /*
2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License").
5 : : * You may not use this file except in compliance with the License.
6 : : * A copy of the License is located at
7 : : *
8 : : * http://aws.amazon.com/apache2.0
9 : : *
10 : : * or in the "license" file accompanying this file. This file is distributed
11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 : : * express or implied. See the License for the specific language governing
13 : : * permissions and limitations under the License.
14 : : */
15 : :
16 : : #include "tls/s2n_client_hello.h"
17 : :
18 : : #include <stdint.h>
19 : : #include <stdlib.h>
20 : : #include <sys/param.h>
21 : : #include <time.h>
22 : :
23 : : #include "api/unstable/fingerprint.h"
24 : : #include "crypto/s2n_fips.h"
25 : : #include "crypto/s2n_hash.h"
26 : : #include "error/s2n_errno.h"
27 : : #include "stuffer/s2n_stuffer.h"
28 : : #include "tls/extensions/s2n_client_server_name.h"
29 : : #include "tls/extensions/s2n_client_supported_groups.h"
30 : : #include "tls/extensions/s2n_extension_list.h"
31 : : #include "tls/extensions/s2n_server_key_share.h"
32 : : #include "tls/s2n_alerts.h"
33 : : #include "tls/s2n_auth_selection.h"
34 : : #include "tls/s2n_cipher_preferences.h"
35 : : #include "tls/s2n_cipher_suites.h"
36 : : #include "tls/s2n_connection.h"
37 : : #include "tls/s2n_handshake_type.h"
38 : : #include "tls/s2n_security_policies.h"
39 : : #include "tls/s2n_signature_algorithms.h"
40 : : #include "tls/s2n_tls.h"
41 : : #include "utils/s2n_bitmap.h"
42 : : #include "utils/s2n_random.h"
43 : : #include "utils/s2n_safety.h"
44 : :
45 : : struct s2n_client_hello *s2n_connection_get_client_hello(struct s2n_connection *conn)
46 : 175 : {
47 [ + + ]: 175 : if (conn->client_hello.parsed != 1) {
48 : 3 : return NULL;
49 : 3 : }
50 : :
51 : 172 : return &conn->client_hello;
52 : 175 : }
53 : :
54 : : static uint32_t min_size(struct s2n_blob *blob, uint32_t max_length)
55 : 44 : {
56 [ + + ]: 44 : return blob->size < max_length ? blob->size : max_length;
57 : 44 : }
58 : :
59 : : static S2N_RESULT s2n_generate_client_session_id(struct s2n_connection *conn)
60 : 7348 : {
61 [ - + ][ # # ]: 7348 : RESULT_ENSURE_REF(conn);
62 [ - + ][ # # ]: 7348 : RESULT_ENSURE_REF(conn->config);
63 : :
64 : : /* Session id already generated - no-op */
65 [ + + ]: 7348 : if (conn->session_id_len) {
66 : 651 : return S2N_RESULT_OK;
67 : 651 : }
68 : :
69 : : /* Only generate the session id if using tickets */
70 : 6697 : bool generate = conn->config->use_tickets;
71 : :
72 : : /* TLS1.3 doesn't require session ids. The field is actually renamed to legacy_session_id.
73 : : * However, we still set a session id if dealing with troublesome middleboxes
74 : : * (middlebox compatibility mode) or if trying to use a TLS1.2 ticket.
75 : : */
76 [ + + ]: 6697 : if (conn->client_protocol_version >= S2N_TLS13) {
77 [ + + ][ + + ]: 4888 : generate = s2n_is_middlebox_compat_enabled(conn) || conn->resume_protocol_version;
78 : 4888 : }
79 : :
80 : : /* Session id not needed - no-op */
81 [ + + ]: 6697 : if (!generate) {
82 : 2009 : return S2N_RESULT_OK;
83 : 2009 : }
84 : :
85 : : /* QUIC should not allow session ids for any reason.
86 : : *
87 : : *= https://www.rfc-editor.org/rfc/rfc9001#section-8.4
88 : : *# A server SHOULD treat the receipt of a TLS ClientHello with a non-empty
89 : : *# legacy_session_id field as a connection error of type PROTOCOL_VIOLATION.
90 : : */
91 [ + - ][ + + ]: 4688 : RESULT_ENSURE(!conn->quic_enabled, S2N_ERR_UNSUPPORTED_WITH_QUIC);
92 : :
93 : 4687 : struct s2n_blob session_id = { 0 };
94 [ - + ]: 4687 : RESULT_GUARD_POSIX(s2n_blob_init(&session_id, conn->session_id, S2N_TLS_SESSION_ID_MAX_LEN));
95 [ - + ]: 4687 : RESULT_GUARD(s2n_get_public_random_data(&session_id));
96 : 4687 : conn->session_id_len = S2N_TLS_SESSION_ID_MAX_LEN;
97 : 4687 : return S2N_RESULT_OK;
98 : 4687 : }
99 : :
100 : : ssize_t s2n_client_hello_get_raw_message_length(struct s2n_client_hello *ch)
101 : 3 : {
102 [ + - ][ + + ]: 3 : POSIX_ENSURE_REF(ch);
103 : :
104 : 2 : return ch->raw_message.size;
105 : 3 : }
106 : :
107 : : ssize_t s2n_client_hello_get_raw_message(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length)
108 : 3 : {
109 [ + - ][ + + ]: 3 : POSIX_ENSURE_REF(ch);
110 [ # # ][ - + ]: 2 : POSIX_ENSURE_REF(out);
111 : :
112 : 2 : uint32_t len = min_size(&ch->raw_message, max_length);
113 [ # # ][ - + ]: 2 : POSIX_CHECKED_MEMCPY(out, ch->raw_message.data, len);
[ + - ]
114 : 2 : return len;
115 : 2 : }
116 : :
117 : : ssize_t s2n_client_hello_get_cipher_suites_length(struct s2n_client_hello *ch)
118 : 3 : {
119 [ + + ][ + - ]: 3 : POSIX_ENSURE_REF(ch);
120 : :
121 : 2 : return ch->cipher_suites.size;
122 : 3 : }
123 : :
124 : : int s2n_client_hello_cb_done(struct s2n_connection *conn)
125 : 28 : {
126 [ - + ][ # # ]: 28 : POSIX_ENSURE_REF(conn);
127 [ - + ][ # # ]: 28 : POSIX_ENSURE_REF(conn->config);
128 [ - + ][ # # ]: 28 : POSIX_ENSURE(conn->config->client_hello_cb_mode == S2N_CLIENT_HELLO_CB_NONBLOCKING, S2N_ERR_INVALID_STATE);
129 [ - + ][ # # ]: 28 : POSIX_ENSURE(conn->client_hello.callback_invoked == 1, S2N_ERR_ASYNC_NOT_PERFORMED);
130 [ # # ][ - + ]: 28 : POSIX_ENSURE(conn->client_hello.parsed == 1, S2N_ERR_INVALID_STATE);
131 : :
132 : 28 : conn->client_hello.callback_async_blocked = 0;
133 : 28 : conn->client_hello.callback_async_done = 1;
134 : :
135 : 28 : return S2N_SUCCESS;
136 : 28 : }
137 : :
138 : : ssize_t s2n_client_hello_get_cipher_suites(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length)
139 : 3 : {
140 [ + + ][ + - ]: 3 : POSIX_ENSURE_REF(ch);
141 [ # # ][ - + ]: 2 : POSIX_ENSURE_REF(out);
142 [ - + ][ # # ]: 2 : POSIX_ENSURE_REF(ch->cipher_suites.data);
143 : :
144 : 2 : uint32_t len = min_size(&ch->cipher_suites, max_length);
145 : :
146 [ - + ][ # # ]: 2 : POSIX_CHECKED_MEMCPY(out, ch->cipher_suites.data, len);
[ + - ]
147 : :
148 : 2 : return len;
149 : 2 : }
150 : :
151 : : ssize_t s2n_client_hello_get_extensions_length(struct s2n_client_hello *ch)
152 : 3 : {
153 [ + + ][ + - ]: 3 : POSIX_ENSURE_REF(ch);
154 : :
155 : 2 : return ch->extensions.raw.size;
156 : 3 : }
157 : :
158 : : ssize_t s2n_client_hello_get_extensions(struct s2n_client_hello *ch, uint8_t *out, uint32_t max_length)
159 : 3 : {
160 [ + + ][ + - ]: 3 : POSIX_ENSURE_REF(ch);
161 [ - + ][ # # ]: 2 : POSIX_ENSURE_REF(out);
162 [ # # ][ - + ]: 2 : POSIX_ENSURE_REF(ch->extensions.raw.data);
163 : :
164 : 2 : uint32_t len = min_size(&ch->extensions.raw, max_length);
165 : :
166 [ - + ][ # # ]: 2 : POSIX_CHECKED_MEMCPY(out, ch->extensions.raw.data, len);
[ + - ]
167 : :
168 : 2 : return len;
169 : 2 : }
170 : :
171 : : int s2n_client_hello_free_raw_message(struct s2n_client_hello *client_hello)
172 : 132730 : {
173 [ - + ][ # # ]: 132730 : POSIX_ENSURE_REF(client_hello);
174 : :
175 [ - + ]: 132730 : POSIX_GUARD(s2n_free(&client_hello->raw_message));
176 : :
177 : : /* These point to data in the raw_message stuffer,
178 : : so we don't need to free them */
179 : 132730 : client_hello->cipher_suites.data = NULL;
180 : 132730 : client_hello->extensions.raw.data = NULL;
181 : :
182 : 132730 : return 0;
183 : 132730 : }
184 : :
185 : : int s2n_client_hello_free(struct s2n_client_hello **ch)
186 : 194 : {
187 [ + + ][ + - ]: 194 : POSIX_ENSURE_REF(ch);
188 [ + + ]: 193 : if (*ch == NULL) {
189 : 88 : return S2N_SUCCESS;
190 : 88 : }
191 : :
192 [ + - ][ + + ]: 105 : POSIX_ENSURE((*ch)->alloced, S2N_ERR_INVALID_ARGUMENT);
193 [ - + ]: 93 : POSIX_GUARD(s2n_client_hello_free_raw_message(*ch));
194 [ - + ]: 93 : POSIX_GUARD(s2n_free_object((uint8_t **) ch, sizeof(struct s2n_client_hello)));
195 : 93 : *ch = NULL;
196 : 93 : return S2N_SUCCESS;
197 : 93 : }
198 : :
199 : : int s2n_collect_client_hello(struct s2n_client_hello *ch, struct s2n_stuffer *source)
200 : 7491 : {
201 [ - + ][ # # ]: 7491 : POSIX_ENSURE_REF(ch);
202 [ # # ][ - + ]: 7491 : POSIX_ENSURE_REF(source);
203 : :
204 : 7491 : uint32_t size = s2n_stuffer_data_available(source);
205 [ - + ][ # # ]: 7491 : S2N_ERROR_IF(size == 0, S2N_ERR_BAD_MESSAGE);
206 : :
207 [ - + ]: 7491 : POSIX_GUARD(s2n_realloc(&ch->raw_message, size));
208 [ - + ]: 7491 : POSIX_GUARD(s2n_stuffer_read(source, &ch->raw_message));
209 : :
210 : 7491 : return 0;
211 : 7491 : }
212 : :
213 : : static S2N_RESULT s2n_client_hello_verify_for_retry(struct s2n_connection *conn,
214 : : struct s2n_client_hello *old_ch, struct s2n_client_hello *new_ch,
215 : : uint8_t *previous_client_random)
216 : 7393 : {
217 [ - + ][ # # ]: 7393 : RESULT_ENSURE_REF(conn);
218 [ # # ][ - + ]: 7393 : RESULT_ENSURE_REF(old_ch);
219 [ - + ][ # # ]: 7393 : RESULT_ENSURE_REF(new_ch);
220 [ - + ][ # # ]: 7393 : RESULT_ENSURE_REF(previous_client_random);
221 : :
222 [ + + ]: 7393 : if (!s2n_is_hello_retry_handshake(conn)) {
223 : 6754 : return S2N_RESULT_OK;
224 : 6754 : }
225 : :
226 : : /*
227 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
228 : : *# The client will also send a
229 : : *# ClientHello when the server has responded to its ClientHello with a
230 : : *# HelloRetryRequest. In that case, the client MUST send the same
231 : : *# ClientHello without modification, except as follows:
232 : : *
233 : : * All of the exceptions that follow are extensions.
234 : : */
235 [ + + ][ + - ]: 639 : RESULT_ENSURE(old_ch->legacy_version == new_ch->legacy_version, S2N_ERR_BAD_MESSAGE);
236 [ # # ][ - + ]: 638 : RESULT_ENSURE(old_ch->compression_methods.size == new_ch->compression_methods.size, S2N_ERR_BAD_MESSAGE);
237 [ + + ][ + - ]: 638 : RESULT_ENSURE(s2n_constant_time_equals(old_ch->compression_methods.data, new_ch->compression_methods.data,
238 : 637 : new_ch->compression_methods.size),
239 : 637 : S2N_ERR_BAD_MESSAGE);
240 : :
241 : : /* Some clients are not compliant with TLS 1.3 RFC, and send mismatching values in their second
242 : : * ClientHello. For increased compatibility, these checks are skipped outside of tests. The
243 : : * checks are still included in tests to ensure the s2n-tls client remains compliant.
244 : : */
245 [ + + ]: 637 : if (s2n_in_test()) {
246 : : /* In the past, the s2n-tls client updated the client random in the second ClientHello
247 : : * which is not allowed by RFC8446: https://github.com/aws/s2n-tls/pull/3311. Although the
248 : : * issue was addressed, its existence means that old versions of the s2n-tls client will
249 : : * fail this validation.
250 : : */
251 [ + - ][ + + ]: 633 : RESULT_ENSURE(s2n_constant_time_equals(
252 : 632 : previous_client_random,
253 : 632 : conn->handshake_params.client_random,
254 : 632 : S2N_TLS_RANDOM_DATA_LEN),
255 : 632 : S2N_ERR_BAD_MESSAGE);
256 : :
257 : : /* Some clients have been found to send a mismatching legacy session ID. */
258 [ # # ][ - + ]: 632 : RESULT_ENSURE(old_ch->session_id.size == new_ch->session_id.size, S2N_ERR_BAD_MESSAGE);
259 [ + + ][ + - ]: 632 : RESULT_ENSURE(s2n_constant_time_equals(old_ch->session_id.data, new_ch->session_id.data,
260 : 631 : new_ch->session_id.size),
261 : 631 : S2N_ERR_BAD_MESSAGE);
262 : :
263 : : /* Some clients have been found to send a mismatching cipher suite list. */
264 [ # # ][ - + ]: 631 : RESULT_ENSURE(old_ch->cipher_suites.size == new_ch->cipher_suites.size, S2N_ERR_BAD_MESSAGE);
265 [ + + ][ + - ]: 631 : RESULT_ENSURE(s2n_constant_time_equals(old_ch->cipher_suites.data, new_ch->cipher_suites.data,
266 : 631 : new_ch->cipher_suites.size),
267 : 631 : S2N_ERR_BAD_MESSAGE);
268 : 631 : }
269 : :
270 : : /*
271 : : * Now enforce that the extensions also exactly match,
272 : : * except for the exceptions described in the RFC.
273 : : */
274 [ + + ]: 13891 : for (size_t i = 0; i < s2n_array_len(s2n_supported_extensions); i++) {
275 : 13260 : s2n_parsed_extension *old_extension = &old_ch->extensions.parsed_extensions[i];
276 : 13260 : uint32_t old_size = old_extension->extension.size;
277 : 13260 : s2n_parsed_extension *new_extension = &new_ch->extensions.parsed_extensions[i];
278 : 13260 : uint32_t new_size = new_extension->extension.size;
279 : :
280 : : /* The extension type is only set if the extension is present.
281 : : * Look for a non-zero-length extension.
282 : : */
283 : 13260 : uint16_t extension_type = 0;
284 [ + + ]: 13260 : if (old_size != 0) {
285 : 4099 : extension_type = old_extension->extension_type;
286 [ + + ]: 9161 : } else if (new_size != 0) {
287 : 38 : extension_type = new_extension->extension_type;
288 : 9123 : } else {
289 : 9123 : continue;
290 : 9123 : }
291 : :
292 : 4137 : switch (extension_type) {
293 : : /*
294 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
295 : : *# - If a "key_share" extension was supplied in the HelloRetryRequest,
296 : : *# replacing the list of shares with a list containing a single
297 : : *# KeyShareEntry from the indicated group.
298 : : */
299 [ + + ]: 631 : case TLS_EXTENSION_KEY_SHARE:
300 : : /* Handled when parsing the key share extension */
301 : 631 : break;
302 : : /*
303 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
304 : : *# - Removing the "early_data" extension (Section 4.2.10) if one was
305 : : *# present. Early data is not permitted after a HelloRetryRequest.
306 : : */
307 [ - + ]: 0 : case TLS_EXTENSION_EARLY_DATA:
308 [ # # ][ # # ]: 0 : RESULT_ENSURE(new_size == 0, S2N_ERR_BAD_MESSAGE);
309 : 0 : break;
310 : : /*
311 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
312 : : *# - Including a "cookie" extension if one was provided in the
313 : : *# HelloRetryRequest.
314 : : */
315 [ + + ]: 37 : case TLS_EXTENSION_COOKIE:
316 : : /* Handled when parsing the cookie extension */
317 : 37 : break;
318 : : /*
319 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.2
320 : : *# - Updating the "pre_shared_key" extension if present by recomputing
321 : : *# the "obfuscated_ticket_age" and binder values and (optionally)
322 : : *# removing any PSKs which are incompatible with the server's
323 : : *# indicated cipher suite.
324 : : */
325 [ + + ]: 462 : case TLS_EXTENSION_PRE_SHARED_KEY:
326 : : /* Handled when parsing the psk extension */
327 : 462 : break;
328 : :
329 : : /* Some clients have been found to send mismatching supported versions in their second
330 : : * ClientHello. The extension isn't compared byte-for-byte for increased compatibility
331 : : * with these clients.
332 : : */
333 [ + + ]: 631 : case TLS_EXTENSION_SUPPORTED_VERSIONS:
334 : : /* Additional HRR validation for the supported versions extension is performed when
335 : : * parsing the extension.
336 : : */
337 : 631 : break;
338 : :
339 : : /*
340 : : * No more exceptions.
341 : : * All other extensions must match.
342 : : */
343 [ + + ]: 2376 : default:
344 [ + - ][ + + ]: 2376 : RESULT_ENSURE(old_size == new_size, S2N_ERR_BAD_MESSAGE);
345 [ + - ][ + + ]: 4137 : RESULT_ENSURE(s2n_constant_time_equals(
346 : 4137 : new_extension->extension.data,
347 : 4137 : old_extension->extension.data,
348 : 4137 : old_size),
349 : 4137 : S2N_ERR_BAD_MESSAGE);
350 : 4137 : }
351 : 4137 : }
352 : :
353 : 631 : return S2N_RESULT_OK;
354 : 634 : }
355 : :
356 : : S2N_RESULT s2n_client_hello_parse_raw(struct s2n_client_hello *client_hello,
357 : : uint8_t client_random[S2N_TLS_RANDOM_DATA_LEN])
358 : 7484 : {
359 [ - + ][ # # ]: 7484 : RESULT_ENSURE_REF(client_hello);
360 : :
361 : 7484 : struct s2n_stuffer in_stuffer = { 0 };
362 [ - + ]: 7484 : RESULT_GUARD_POSIX(s2n_stuffer_init_written(&in_stuffer, &client_hello->raw_message));
363 : 7484 : struct s2n_stuffer *in = &in_stuffer;
364 : :
365 : : /**
366 : : * https://tools.ietf.org/rfc/rfc8446#4.1.2
367 : : * Structure of this message:
368 : : *
369 : : * uint16 ProtocolVersion;
370 : : * opaque Random[32];
371 : : *
372 : : * uint8 CipherSuite[2];
373 : : *
374 : : * struct {
375 : : * ProtocolVersion legacy_version = 0x0303;
376 : : * Random random;
377 : : * opaque legacy_session_id<0..32>;
378 : : * CipherSuite cipher_suites<2..2^16-2>;
379 : : * opaque legacy_compression_methods<1..2^8-1>;
380 : : * Extension extensions<8..2^16-1>;
381 : : * } ClientHello;
382 : : **/
383 : :
384 : : /* legacy_version */
385 : 7484 : uint8_t client_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
386 [ + + ]: 7484 : RESULT_GUARD_POSIX(s2n_stuffer_read_bytes(in, client_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
387 : :
388 : : /* Encode the version as a 1 byte representation of the two protocol version bytes, with the
389 : : * major version in the tens place and the minor version in the ones place. For example, the
390 : : * TLS 1.2 protocol version is 0x0303, which is encoded as S2N_TLS12 (33).
391 : : */
392 : 7483 : client_hello->legacy_version = (client_protocol_version[0] * 10) + client_protocol_version[1];
393 : :
394 : : /* random */
395 [ - + ]: 7483 : RESULT_GUARD_POSIX(s2n_stuffer_erase_and_read_bytes(in, client_random, S2N_TLS_RANDOM_DATA_LEN));
396 : :
397 : : /* legacy_session_id */
398 : 7483 : uint8_t session_id_len = 0;
399 [ - + ]: 7483 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(in, &session_id_len));
400 [ + + ][ + - ]: 7483 : RESULT_ENSURE(session_id_len <= S2N_TLS_SESSION_ID_MAX_LEN, S2N_ERR_BAD_MESSAGE);
401 : 7482 : uint8_t *session_id = s2n_stuffer_raw_read(in, session_id_len);
402 [ - + ][ # # ]: 7482 : RESULT_ENSURE(session_id != NULL, S2N_ERR_BAD_MESSAGE);
403 [ - + ]: 7482 : RESULT_GUARD_POSIX(s2n_blob_init(&client_hello->session_id, session_id, session_id_len));
404 : :
405 : : /* cipher suites */
406 : 7482 : uint16_t cipher_suites_length = 0;
407 [ - + ]: 7482 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(in, &cipher_suites_length));
408 [ + - ][ + + ]: 7482 : RESULT_ENSURE(cipher_suites_length > 0, S2N_ERR_BAD_MESSAGE);
409 [ - + ][ # # ]: 7480 : RESULT_ENSURE(cipher_suites_length % S2N_TLS_CIPHER_SUITE_LEN == 0, S2N_ERR_BAD_MESSAGE);
410 : 7480 : uint8_t *cipher_suites = s2n_stuffer_raw_read(in, cipher_suites_length);
411 [ - + ][ # # ]: 7480 : RESULT_ENSURE(cipher_suites != NULL, S2N_ERR_BAD_MESSAGE);
412 [ - + ]: 7480 : RESULT_GUARD_POSIX(s2n_blob_init(&client_hello->cipher_suites, cipher_suites, cipher_suites_length));
413 : :
414 : : /* legacy_compression_methods */
415 : 7480 : uint8_t compression_methods_len = 0;
416 [ - + ]: 7480 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(in, &compression_methods_len));
417 : 7480 : uint8_t *compression_methods = s2n_stuffer_raw_read(in, compression_methods_len);
418 [ - + ][ # # ]: 7480 : RESULT_ENSURE(compression_methods != NULL, S2N_ERR_BAD_MESSAGE);
419 [ - + ]: 7480 : RESULT_GUARD_POSIX(s2n_blob_init(&client_hello->compression_methods, compression_methods, compression_methods_len));
420 : :
421 : : /* extensions */
422 [ + + ]: 7480 : RESULT_GUARD_POSIX(s2n_extension_list_parse(in, &client_hello->extensions));
423 : :
424 : 7479 : return S2N_RESULT_OK;
425 : 7480 : }
426 : :
427 : : int s2n_parse_client_hello(struct s2n_connection *conn)
428 : 7407 : {
429 [ # # ][ - + ]: 7407 : POSIX_ENSURE_REF(conn);
430 : :
431 : : /* SSLv2 ClientHellos are not allowed during a HelloRetryRequest */
432 [ + + ]: 7407 : if (s2n_is_hello_retry_handshake(conn)) {
433 [ + + ][ + - ]: 640 : POSIX_ENSURE(!conn->client_hello.sslv2, S2N_ERR_BAD_MESSAGE);
434 : 640 : }
435 : :
436 : : /* If a retry, move the old version of the client hello
437 : : * somewhere safe so we can compare it to the new client hello later.
438 : : */
439 : 7406 : DEFER_CLEANUP(struct s2n_client_hello previous_hello_retry = conn->client_hello,
440 : 7406 : s2n_client_hello_free_raw_message);
441 [ + + ]: 7406 : if (s2n_is_hello_retry_handshake(conn)) {
442 [ # # ][ - + ]: 639 : POSIX_CHECKED_MEMSET(&conn->client_hello, 0, sizeof(struct s2n_client_hello));
[ + - ]
443 : 639 : }
444 : :
445 [ - + ]: 7406 : POSIX_GUARD(s2n_collect_client_hello(&conn->client_hello, &conn->handshake.io));
446 : :
447 [ + + ]: 7406 : if (conn->client_hello.sslv2) {
448 [ + + ]: 7 : POSIX_GUARD(s2n_sslv2_client_hello_parse(conn));
449 : 6 : return S2N_SUCCESS;
450 : 7 : }
451 : :
452 : : /* Save the current client_random for comparison in the case of a retry */
453 : 7399 : uint8_t previous_client_random[S2N_TLS_RANDOM_DATA_LEN] = { 0 };
454 [ - + ][ # # ]: 7399 : POSIX_CHECKED_MEMCPY(previous_client_random, conn->handshake_params.client_random,
[ + - ]
455 : 7399 : S2N_TLS_RANDOM_DATA_LEN);
456 : :
457 : : /* Parse raw, collected client hello */
458 [ + + ]: 7399 : POSIX_GUARD_RESULT(s2n_client_hello_parse_raw(&conn->client_hello,
459 : 7396 : conn->handshake_params.client_random));
460 : :
461 : : /* Protocol version in the ClientHello is fixed at 0x0303(TLS 1.2) for
462 : : * future versions of TLS. Therefore, we will negotiate down if a client sends
463 : : * an unexpected value above 0x0303.
464 : : */
465 : 7396 : conn->client_protocol_version = MIN(conn->client_hello.legacy_version, S2N_TLS12);
466 : :
467 : : /* Copy the session id to the connection. */
468 : 7396 : conn->session_id_len = conn->client_hello.session_id.size;
469 [ # # ][ - + ]: 7396 : POSIX_CHECKED_MEMCPY(conn->session_id, conn->client_hello.session_id.data, conn->session_id_len);
[ + + ]
470 : :
471 [ + + ]: 7396 : POSIX_GUARD_RESULT(s2n_client_hello_verify_for_retry(conn,
472 : 7388 : &previous_hello_retry, &conn->client_hello, previous_client_random));
473 : 7388 : return S2N_SUCCESS;
474 : 7396 : }
475 : :
476 : : static S2N_RESULT s2n_client_hello_parse_message_impl(struct s2n_client_hello **result,
477 : : const uint8_t *raw_message, uint32_t raw_message_size)
478 : 93 : {
479 [ - + ][ # # ]: 93 : RESULT_ENSURE_REF(result);
480 : :
481 : 93 : DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
482 [ - + ]: 93 : RESULT_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_client_hello)));
483 [ - + ]: 93 : RESULT_GUARD_POSIX(s2n_blob_zero(&mem));
484 : :
485 : 93 : DEFER_CLEANUP(struct s2n_client_hello *client_hello = NULL, s2n_client_hello_free);
486 : 93 : client_hello = (struct s2n_client_hello *) (void *) mem.data;
487 : 93 : client_hello->alloced = true;
488 : 93 : ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
489 : :
490 : 93 : DEFER_CLEANUP(struct s2n_stuffer in = { 0 }, s2n_stuffer_free);
491 [ - + ]: 93 : RESULT_GUARD_POSIX(s2n_stuffer_alloc(&in, raw_message_size));
492 [ - + ]: 93 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&in, raw_message, raw_message_size));
493 : :
494 : 93 : uint8_t message_type = 0;
495 : 93 : uint32_t message_len = 0;
496 [ - + ]: 93 : RESULT_GUARD(s2n_handshake_parse_header(&in, &message_type, &message_len));
497 [ + + ][ + - ]: 93 : RESULT_ENSURE(message_type == TLS_CLIENT_HELLO, S2N_ERR_BAD_MESSAGE);
498 [ + - ][ + + ]: 87 : RESULT_ENSURE(message_len == s2n_stuffer_data_available(&in), S2N_ERR_BAD_MESSAGE);
499 : :
500 [ - + ]: 85 : RESULT_GUARD_POSIX(s2n_collect_client_hello(client_hello, &in));
501 [ - + ][ # # ]: 85 : RESULT_ENSURE(s2n_stuffer_data_available(&in) == 0, S2N_ERR_BAD_MESSAGE);
502 : :
503 : 85 : uint8_t random[S2N_TLS_RANDOM_DATA_LEN] = { 0 };
504 [ + + ]: 85 : RESULT_GUARD(s2n_client_hello_parse_raw(client_hello, random));
505 : :
506 : 83 : *result = client_hello;
507 : 83 : ZERO_TO_DISABLE_DEFER_CLEANUP(client_hello);
508 : 83 : return S2N_RESULT_OK;
509 : 85 : }
510 : :
511 : : struct s2n_client_hello *s2n_client_hello_parse_message(const uint8_t *raw_message, uint32_t raw_message_size)
512 : 93 : {
513 : 93 : struct s2n_client_hello *result = NULL;
514 [ + + ]: 93 : PTR_GUARD_RESULT(s2n_client_hello_parse_message_impl(&result, raw_message, raw_message_size));
515 : 83 : return result;
516 : 93 : }
517 : :
518 : : int s2n_process_client_hello(struct s2n_connection *conn)
519 : 7378 : {
520 [ # # ][ - + ]: 7378 : POSIX_ENSURE_REF(conn);
521 [ - + ][ # # ]: 7378 : POSIX_ENSURE_REF(conn->secure);
522 [ # # ][ - + ]: 7378 : POSIX_ENSURE_REF(conn->secure->cipher_suite);
523 : :
524 : : /* Client hello is parsed and config is finalized.
525 : : * Negotiate protocol version, cipher suite, ALPN, select a cert, etc. */
526 : 7378 : struct s2n_client_hello *client_hello = &conn->client_hello;
527 : :
528 : 7378 : const struct s2n_security_policy *security_policy = NULL;
529 [ - + ]: 7378 : POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
530 : :
531 [ - + ][ + + ]: 7378 : if (!s2n_connection_supports_tls13(conn) || !s2n_security_policy_supports_tls13(security_policy)) {
532 : 2319 : conn->server_protocol_version = MIN(conn->server_protocol_version, S2N_TLS12);
533 : 2319 : conn->actual_protocol_version = MIN(conn->server_protocol_version, S2N_TLS12);
534 : 2319 : }
535 : :
536 : : /* Set default key exchange curve.
537 : : * This is going to be our fallback if the client has no preference.
538 : : *
539 : : * P-256 is our preferred fallback option because the TLS1.3 RFC requires
540 : : * all implementations to support it:
541 : : *
542 : : * https://tools.ietf.org/rfc/rfc8446#section-9.1
543 : : * A TLS-compliant application MUST support key exchange with secp256r1 (NIST P-256)
544 : : * and SHOULD support key exchange with X25519 [RFC7748]
545 : : *
546 : : *= https://www.rfc-editor.org/rfc/rfc4492#section-4
547 : : *# A client that proposes ECC cipher suites may choose not to include these extensions.
548 : : *# In this case, the server is free to choose any one of the elliptic curves or point formats listed in Section 5.
549 : : *
550 : : */
551 : 7378 : const struct s2n_ecc_preferences *ecc_pref = NULL;
552 [ - + ]: 7378 : POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_pref));
553 [ - + ][ # # ]: 7378 : POSIX_ENSURE_REF(ecc_pref);
554 [ - + ][ # # ]: 7378 : POSIX_ENSURE_GT(ecc_pref->count, 0);
555 [ + + ]: 7378 : if (s2n_ecc_preferences_includes_curve(ecc_pref, TLS_EC_CURVE_SECP_256_R1)) {
556 : 7356 : conn->kex_params.server_ecc_evp_params.negotiated_curve = &s2n_ecc_curve_secp256r1;
557 : 7356 : } else {
558 : : /* If P-256 isn't allowed by the current security policy, instead choose
559 : : * the first / most preferred curve.
560 : : */
561 : 22 : conn->kex_params.server_ecc_evp_params.negotiated_curve = ecc_pref->ecc_curves[0];
562 : 22 : }
563 : :
564 [ + + ]: 7378 : POSIX_GUARD(s2n_extension_list_process(S2N_EXTENSION_LIST_CLIENT_HELLO, conn, &conn->client_hello.extensions));
565 : :
566 : : /* After parsing extensions, select a curve and corresponding keyshare to use */
567 [ + + ]: 7370 : if (conn->actual_protocol_version >= S2N_TLS13) {
568 [ - + ]: 4918 : POSIX_GUARD(s2n_extensions_server_key_share_select(conn));
569 : 4918 : }
570 : :
571 : : /* for pre TLS 1.3 connections, protocol selection is not done in supported_versions extensions, so do it here */
572 [ + + ]: 7370 : if (conn->actual_protocol_version < S2N_TLS13) {
573 : 2452 : conn->actual_protocol_version = MIN(conn->server_protocol_version, conn->client_protocol_version);
574 : 2452 : }
575 : :
576 [ + + ]: 7370 : if (conn->client_protocol_version < security_policy->minimum_protocol_version) {
577 [ - + ]: 2 : POSIX_GUARD(s2n_queue_reader_unsupported_protocol_version_alert(conn));
578 [ + - ]: 2 : POSIX_BAIL(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
579 : 2 : }
580 : :
581 [ + + ]: 7368 : if (s2n_connection_is_quic_enabled(conn)) {
582 [ + + ][ + - ]: 12 : POSIX_ENSURE(conn->actual_protocol_version >= S2N_TLS13, S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED);
583 : 12 : }
584 : :
585 : : /* Find potential certificate matches before we choose the cipher. */
586 [ - + ]: 7367 : POSIX_GUARD(s2n_conn_find_name_matching_certs(conn));
587 : :
588 : : /* Save the previous cipher suite */
589 : 7367 : uint8_t previous_cipher_suite_iana[S2N_TLS_CIPHER_SUITE_LEN] = { 0 };
590 [ - + ][ # # ]: 7367 : POSIX_CHECKED_MEMCPY(previous_cipher_suite_iana, conn->secure->cipher_suite->iana_value, S2N_TLS_CIPHER_SUITE_LEN);
[ + - ]
591 : :
592 : : /* Now choose the ciphers we have certs for. */
593 [ + + ]: 7367 : if (conn->client_hello.sslv2) {
594 [ - + ]: 5 : POSIX_GUARD(s2n_set_cipher_as_sslv2_server(conn, client_hello->cipher_suites.data,
595 : 5 : client_hello->cipher_suites.size / S2N_SSLv2_CIPHER_SUITE_LEN));
596 : 7362 : } else {
597 [ + + ]: 7362 : POSIX_GUARD(s2n_set_cipher_as_tls_server(conn, client_hello->cipher_suites.data,
598 : 7362 : client_hello->cipher_suites.size / 2));
599 : 7362 : }
600 : :
601 : : /* Check if this is the second client hello in a hello retry handshake */
602 [ + + ][ + + ]: 7350 : if (s2n_is_hello_retry_handshake(conn) && conn->handshake.message_number > 0) {
603 : : /**
604 : : *= https://www.rfc-editor.org/rfc/rfc8446#4.1.4
605 : : *# Servers MUST ensure that they negotiate the
606 : : *# same cipher suite when receiving a conformant updated ClientHello (if
607 : : *# the server selects the cipher suite as the first step in the
608 : : *# negotiation, then this will happen automatically).
609 : : **/
610 [ + + ][ + - ]: 627 : POSIX_ENSURE(s2n_constant_time_equals(previous_cipher_suite_iana, conn->secure->cipher_suite->iana_value,
611 : 627 : S2N_TLS_CIPHER_SUITE_LEN),
612 : 627 : S2N_ERR_BAD_MESSAGE);
613 : 627 : }
614 : :
615 : : /* If we're using a PSK, we don't need to choose a signature algorithm or certificate,
616 : : * because no additional auth is required. */
617 [ + + ]: 7348 : if (conn->psk_params.chosen_psk != NULL) {
618 : 1066 : return S2N_SUCCESS;
619 : 1066 : }
620 : :
621 : : /* And set the signature and hash algorithm used for key exchange signatures */
622 [ + + ]: 6282 : POSIX_GUARD_RESULT(s2n_signature_algorithm_select(conn));
623 : :
624 : : /* And finally, set the certs specified by the final auth + sig_alg combo. */
625 [ + + ]: 6279 : POSIX_GUARD(s2n_select_certs_for_server_auth(conn, &conn->handshake_params.our_chain_and_key));
626 : :
627 : 6277 : return S2N_SUCCESS;
628 : 6279 : }
629 : :
630 : : static S2N_RESULT s2n_client_hello_process_cb_response(struct s2n_connection *conn, int rc)
631 : 122 : {
632 [ + + ]: 122 : if (rc < 0) {
633 : 4 : goto fail;
634 : 4 : }
635 [ - + ]: 118 : switch (conn->config->client_hello_cb_mode) {
636 [ + + ]: 90 : case S2N_CLIENT_HELLO_CB_BLOCKING: {
637 [ + + ]: 90 : if (rc) {
638 : 5 : conn->server_name_used = 1;
639 : 5 : }
640 : 90 : return S2N_RESULT_OK;
641 : 0 : }
642 [ + + ]: 28 : case S2N_CLIENT_HELLO_CB_NONBLOCKING: {
643 [ + + ]: 28 : if (conn->client_hello.callback_async_done) {
644 : 9 : return S2N_RESULT_OK;
645 : 9 : }
646 : 19 : conn->client_hello.callback_async_blocked = 1;
647 [ + - ]: 19 : RESULT_BAIL(S2N_ERR_ASYNC_BLOCKED);
648 : 19 : }
649 : 118 : }
650 : 4 : fail:
651 : : /* rc < 0 */
652 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_queue_reader_handshake_failure_alert(conn));
653 [ + - ]: 4 : RESULT_BAIL(S2N_ERR_CANCELLED);
654 : 4 : }
655 : :
656 : : int s2n_client_hello_recv(struct s2n_connection *conn)
657 : 7427 : {
658 [ + - ][ + + ]: 7427 : POSIX_ENSURE(!conn->client_hello.callback_async_blocked, S2N_ERR_ASYNC_BLOCKED);
659 : :
660 : : /* Only parse the ClientHello once */
661 [ + + ]: 7416 : if (!conn->client_hello.parsed) {
662 [ + + ]: 7392 : POSIX_GUARD(s2n_parse_client_hello(conn));
663 : : /* Mark the collected client hello as available when parsing is done and before the client hello callback */
664 : 7380 : conn->client_hello.parsed = true;
665 : 7380 : }
666 : :
667 : : /* Only invoke the ClientHello callback once.
668 : : * This means that we do NOT invoke the callback again on the second ClientHello
669 : : * in a TLS1.3 retry handshake. We explicitly check for a retry because the
670 : : * callback state may have been cleared while parsing the second ClientHello.
671 : : */
672 [ + + ][ + + ]: 7404 : if (!conn->client_hello.callback_invoked && !IS_HELLO_RETRY_HANDSHAKE(conn)) {
673 : : /* Mark the client hello callback as invoked to avoid calling it again. */
674 : 6753 : conn->client_hello.callback_invoked = true;
675 : :
676 : : /* Do NOT move this null check. A test exists to assert that a server connection can get
677 : : * as far as the client hello callback without using its config. To do this we need a
678 : : * specific error for a null config just before the client hello callback. The test's
679 : : * assertions are weakened if this check is moved. */
680 [ + - ][ + + ]: 6753 : POSIX_ENSURE(conn->config, S2N_ERR_CONFIG_NULL_BEFORE_CH_CALLBACK);
681 : :
682 : : /* Call client_hello_cb if exists, letting application to modify s2n_connection or swap s2n_config */
683 [ + + ]: 6750 : if (conn->config->client_hello_cb) {
684 : 124 : int rc = conn->config->client_hello_cb(conn, conn->config->client_hello_cb_ctx);
685 [ + + ]: 124 : POSIX_GUARD_RESULT(s2n_client_hello_process_cb_response(conn, rc));
686 : 124 : }
687 : 6750 : }
688 : :
689 [ + + ]: 7378 : POSIX_GUARD(s2n_process_client_hello(conn));
690 : :
691 : 7343 : return 0;
692 : 7378 : }
693 : :
694 : : S2N_RESULT s2n_cipher_suite_validate_available(struct s2n_connection *conn, struct s2n_cipher_suite *cipher)
695 : 157684 : {
696 [ # # ][ - + ]: 157684 : RESULT_ENSURE_REF(conn);
697 [ - + ][ # # ]: 157684 : RESULT_ENSURE_REF(cipher);
698 [ + + ][ + - ]: 157684 : RESULT_ENSURE_EQ(cipher->available, true);
699 [ + + ][ + - ]: 155741 : RESULT_ENSURE_LTE(cipher->minimum_required_tls_version, conn->client_protocol_version);
700 [ + + ]: 155304 : if (s2n_connection_is_quic_enabled(conn)) {
701 [ + + ][ + - ]: 251 : RESULT_ENSURE_GTE(cipher->minimum_required_tls_version, S2N_TLS13);
702 : 251 : }
703 : 155092 : return S2N_RESULT_OK;
704 : 155304 : }
705 : :
706 : : int s2n_client_hello_send(struct s2n_connection *conn)
707 : 7351 : {
708 [ # # ][ - + ]: 7351 : POSIX_ENSURE_REF(conn);
709 : :
710 : 7351 : const struct s2n_security_policy *security_policy = NULL;
711 [ - + ]: 7351 : POSIX_GUARD(s2n_connection_get_security_policy(conn, &security_policy));
712 : :
713 : 7351 : const struct s2n_cipher_preferences *cipher_preferences = security_policy->cipher_preferences;
714 [ # # ][ - + ]: 7351 : POSIX_ENSURE_REF(cipher_preferences);
715 : :
716 [ - + ][ + + ]: 7351 : if (!s2n_connection_supports_tls13(conn) || !s2n_security_policy_supports_tls13(security_policy)) {
717 : 1786 : conn->client_protocol_version = MIN(conn->client_protocol_version, S2N_TLS12);
718 : 1786 : conn->actual_protocol_version = MIN(conn->actual_protocol_version, S2N_TLS12);
719 : 1786 : }
720 : :
721 : 7351 : struct s2n_stuffer *out = &conn->handshake.io;
722 : 7351 : uint8_t client_protocol_version[S2N_TLS_PROTOCOL_VERSION_LEN] = { 0 };
723 : :
724 : 7351 : uint8_t reported_protocol_version = MIN(conn->client_protocol_version, S2N_TLS12);
725 : 7351 : conn->client_hello.legacy_version = reported_protocol_version;
726 : 7351 : client_protocol_version[0] = reported_protocol_version / 10;
727 : 7351 : client_protocol_version[1] = reported_protocol_version % 10;
728 [ - + ]: 7351 : POSIX_GUARD(s2n_stuffer_write_bytes(out, client_protocol_version, S2N_TLS_PROTOCOL_VERSION_LEN));
729 : :
730 : 7351 : struct s2n_blob client_random = { 0 };
731 [ - + ]: 7351 : POSIX_GUARD(s2n_blob_init(&client_random, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
732 [ + + ]: 7351 : if (!s2n_is_hello_retry_handshake(conn)) {
733 : : /* Only generate the random data for our first client hello.
734 : : * If we retry, we'll reuse the value. */
735 [ - + ]: 6709 : POSIX_GUARD_RESULT(s2n_get_public_random_data(&client_random));
736 : 6709 : }
737 [ - + ]: 7351 : POSIX_GUARD(s2n_stuffer_write(out, &client_random));
738 : :
739 [ + + ]: 7351 : POSIX_GUARD_RESULT(s2n_generate_client_session_id(conn));
740 [ - + ]: 7350 : POSIX_GUARD(s2n_stuffer_write_uint8(out, conn->session_id_len));
741 [ + + ]: 7350 : if (conn->session_id_len > 0) {
742 [ - + ]: 5338 : POSIX_GUARD(s2n_stuffer_write_bytes(out, conn->session_id, conn->session_id_len));
743 : 5338 : }
744 : :
745 : : /* Reserve space for size of the list of available ciphers */
746 : 7350 : struct s2n_stuffer_reservation available_cipher_suites_size;
747 [ - + ]: 7350 : POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &available_cipher_suites_size));
748 : :
749 : : /* Now, write the IANA values of every available cipher suite in our list */
750 : 7350 : struct s2n_cipher_suite *cipher = NULL;
751 : 7350 : bool tls12_is_possible = false;
752 [ + + ]: 165034 : for (size_t i = 0; i < security_policy->cipher_preferences->count; i++) {
753 : 157684 : cipher = cipher_preferences->suites[i];
754 [ + + ]: 157684 : if (s2n_result_is_error(s2n_cipher_suite_validate_available(conn, cipher))) {
755 : 2592 : continue;
756 : 2592 : }
757 [ + + ]: 155092 : if (cipher->minimum_required_tls_version < S2N_TLS13) {
758 : 138587 : tls12_is_possible = true;
759 : 138587 : }
760 [ - + ]: 155092 : POSIX_GUARD(s2n_stuffer_write_bytes(out, cipher->iana_value, S2N_TLS_CIPHER_SUITE_LEN));
761 : 155092 : }
762 : :
763 : : /**
764 : : * For initial handshakes:
765 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.4
766 : : *# o The client MUST include either an empty "renegotiation_info"
767 : : *# extension, or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling
768 : : *# cipher suite value in the ClientHello. Including both is NOT
769 : : *# RECOMMENDED.
770 : : * For maximum backwards compatibility, we choose to use the TLS_EMPTY_RENEGOTIATION_INFO_SCSV cipher suite
771 : : * rather than the "renegotiation_info" extension.
772 : : *
773 : : * For renegotiation handshakes:
774 : : *= https://www.rfc-editor.org/rfc/rfc5746#3.5
775 : : *# The SCSV MUST NOT be included.
776 : : */
777 [ + + ][ + + ]: 7350 : if (tls12_is_possible && !s2n_handshake_is_renegotiation(conn)) {
778 : 7025 : uint8_t renegotiation_info_scsv[S2N_TLS_CIPHER_SUITE_LEN] = { TLS_EMPTY_RENEGOTIATION_INFO_SCSV };
779 [ - + ]: 7025 : POSIX_GUARD(s2n_stuffer_write_bytes(out, renegotiation_info_scsv, S2N_TLS_CIPHER_SUITE_LEN));
780 : 7025 : }
781 : :
782 : : /* Write size of the list of available ciphers */
783 : 7350 : uint32_t ciphers_size = 0;
784 [ - + ]: 7350 : POSIX_GUARD(s2n_stuffer_get_vector_size(&available_cipher_suites_size, &ciphers_size));
785 [ + + ][ + - ]: 7350 : POSIX_ENSURE(ciphers_size > 0, S2N_ERR_INVALID_CIPHER_PREFERENCES);
786 [ - + ]: 7349 : POSIX_GUARD(s2n_stuffer_write_reservation(&available_cipher_suites_size, ciphers_size));
787 : :
788 : : /* Zero compression methods */
789 [ - + ]: 7349 : POSIX_GUARD(s2n_stuffer_write_uint8(out, 1));
790 [ - + ]: 7349 : POSIX_GUARD(s2n_stuffer_write_uint8(out, 0));
791 : :
792 : : /* Write the extensions */
793 [ - + ]: 7349 : POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_CLIENT_HELLO, conn, out));
794 : :
795 : : /* Once the message is complete, finish calculating the PSK binders.
796 : : *
797 : : * The PSK binders require all the sizes in the ClientHello to be written correctly,
798 : : * including the extension size and extension list size, and therefore have
799 : : * to be calculated AFTER we finish writing the entire extension list. */
800 [ - + ]: 7349 : POSIX_GUARD_RESULT(s2n_finish_psk_extension(conn));
801 : :
802 : : /* If early data was not requested as part of the ClientHello, it never will be. */
803 [ + + ]: 7349 : if (conn->early_data_state == S2N_UNKNOWN_EARLY_DATA_STATE) {
804 [ - + ]: 6168 : POSIX_GUARD_RESULT(s2n_connection_set_early_data_state(conn, S2N_EARLY_DATA_NOT_REQUESTED));
805 : 6168 : }
806 : :
807 : 7349 : return S2N_SUCCESS;
808 : 7349 : }
809 : :
810 : : /*
811 : : * s2n-tls does NOT support SSLv2. However, it does support SSLv2 ClientHellos.
812 : : * Clients may send SSLv2 ClientHellos advertising higher protocol versions for
813 : : * backwards compatibility reasons. See https://tools.ietf.org/rfc/rfc2246 Appendix E.
814 : : *
815 : : * In this case, conn->client_hello.legacy_version and conn->client_protocol_version
816 : : * will be higher than SSLv2.
817 : : *
818 : : * See http://www-archive.mozilla.org/projects/security/pki/nss/ssl/draft02.html Section 2.5
819 : : * for a description of the expected SSLv2 format.
820 : : * Alternatively, the TLS1.0 RFC includes a more modern description of the format:
821 : : * https://tools.ietf.org/rfc/rfc2246 Appendix E.1
822 : : */
823 : : int s2n_sslv2_client_hello_parse(struct s2n_connection *conn)
824 : 7 : {
825 : 7 : struct s2n_client_hello *client_hello = &conn->client_hello;
826 : 7 : conn->client_protocol_version = MIN(client_hello->legacy_version, S2N_TLS12);
827 : :
828 : 7 : struct s2n_stuffer in_stuffer = { 0 };
829 [ - + ]: 7 : POSIX_GUARD(s2n_stuffer_init(&in_stuffer, &client_hello->raw_message));
830 [ - + ]: 7 : POSIX_GUARD(s2n_stuffer_skip_write(&in_stuffer, client_hello->raw_message.size));
831 : 7 : struct s2n_stuffer *in = &in_stuffer;
832 : :
833 : : /* We start 5 bytes into the record */
834 : 7 : uint16_t cipher_suites_length = 0;
835 [ - + ]: 7 : POSIX_GUARD(s2n_stuffer_read_uint16(in, &cipher_suites_length));
836 [ + + ][ + - ]: 7 : POSIX_ENSURE(cipher_suites_length > 0, S2N_ERR_BAD_MESSAGE);
837 [ # # ][ - + ]: 6 : POSIX_ENSURE(cipher_suites_length % S2N_SSLv2_CIPHER_SUITE_LEN == 0, S2N_ERR_BAD_MESSAGE);
838 : :
839 : 6 : uint16_t session_id_length = 0;
840 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_read_uint16(in, &session_id_length));
841 : :
842 : 6 : uint16_t challenge_length = 0;
843 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_read_uint16(in, &challenge_length));
844 : :
845 [ - + ][ # # ]: 6 : S2N_ERROR_IF(challenge_length > S2N_TLS_RANDOM_DATA_LEN, S2N_ERR_BAD_MESSAGE);
846 : :
847 : 6 : client_hello->cipher_suites.size = cipher_suites_length;
848 : 6 : client_hello->cipher_suites.data = s2n_stuffer_raw_read(in, cipher_suites_length);
849 [ - + ][ # # ]: 6 : POSIX_ENSURE_REF(client_hello->cipher_suites.data);
850 : :
851 [ - + ][ # # ]: 6 : S2N_ERROR_IF(session_id_length > s2n_stuffer_data_available(in), S2N_ERR_BAD_MESSAGE);
852 [ - + ]: 6 : POSIX_GUARD(s2n_blob_init(&client_hello->session_id, s2n_stuffer_raw_read(in, session_id_length), session_id_length));
853 [ - + ][ # # ]: 6 : if (session_id_length > 0 && session_id_length <= S2N_TLS_SESSION_ID_MAX_LEN) {
854 [ # # ][ # # ]: 0 : POSIX_CHECKED_MEMCPY(conn->session_id, client_hello->session_id.data, session_id_length);
[ # # ]
855 : 0 : conn->session_id_len = (uint8_t) session_id_length;
856 : 0 : }
857 : :
858 : 6 : struct s2n_blob b = { 0 };
859 [ - + ]: 6 : POSIX_GUARD(s2n_blob_init(&b, conn->handshake_params.client_random, S2N_TLS_RANDOM_DATA_LEN));
860 : :
861 : 6 : b.data += S2N_TLS_RANDOM_DATA_LEN - challenge_length;
862 : 6 : b.size -= S2N_TLS_RANDOM_DATA_LEN - challenge_length;
863 : :
864 [ - + ]: 6 : POSIX_GUARD(s2n_stuffer_read(in, &b));
865 : :
866 : 6 : return 0;
867 : 6 : }
868 : :
869 : : int s2n_client_hello_get_parsed_extension(s2n_tls_extension_type extension_type,
870 : : s2n_parsed_extensions_list *parsed_extension_list, s2n_parsed_extension **parsed_extension)
871 : 745 : {
872 [ - + ][ # # ]: 745 : POSIX_ENSURE_REF(parsed_extension_list);
873 [ # # ][ - + ]: 745 : POSIX_ENSURE_REF(parsed_extension);
874 : :
875 : 745 : s2n_extension_type_id extension_type_id = 0;
876 [ - + ]: 745 : POSIX_GUARD(s2n_extension_supported_iana_value_to_id(extension_type, &extension_type_id));
877 : :
878 : 745 : s2n_parsed_extension *found_parsed_extension = &parsed_extension_list->parsed_extensions[extension_type_id];
879 [ + - ][ + + ]: 745 : POSIX_ENSURE(found_parsed_extension->extension.data, S2N_ERR_EXTENSION_NOT_RECEIVED);
880 [ + + ][ + - ]: 324 : POSIX_ENSURE(found_parsed_extension->extension_type == extension_type, S2N_ERR_INVALID_PARSED_EXTENSIONS);
881 : :
882 : 323 : *parsed_extension = found_parsed_extension;
883 : 323 : return S2N_SUCCESS;
884 : 324 : }
885 : :
886 : : ssize_t s2n_client_hello_get_extension_length(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type)
887 : 41 : {
888 [ + - ][ + + ]: 41 : POSIX_ENSURE_REF(ch);
889 : :
890 : 39 : s2n_parsed_extension *parsed_extension = NULL;
891 [ + + ]: 39 : if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) {
892 : 2 : return 0;
893 : 2 : }
894 : :
895 : 37 : return parsed_extension->extension.size;
896 : 39 : }
897 : :
898 : : ssize_t s2n_client_hello_get_extension_by_id(struct s2n_client_hello *ch, s2n_tls_extension_type extension_type, uint8_t *out, uint32_t max_length)
899 : 42 : {
900 [ + + ][ + - ]: 42 : POSIX_ENSURE_REF(ch);
901 [ - + ][ # # ]: 40 : POSIX_ENSURE_REF(out);
902 : :
903 : 40 : s2n_parsed_extension *parsed_extension = NULL;
904 [ + + ]: 40 : if (s2n_client_hello_get_parsed_extension(extension_type, &ch->extensions, &parsed_extension) != S2N_SUCCESS) {
905 : 3 : return 0;
906 : 3 : }
907 : :
908 : 37 : uint32_t len = min_size(&parsed_extension->extension, max_length);
909 [ # # ][ - + ]: 37 : POSIX_CHECKED_MEMCPY(out, parsed_extension->extension.data, len);
[ + - ]
910 : 37 : return len;
911 : 37 : }
912 : :
913 : : int s2n_client_hello_get_session_id_length(struct s2n_client_hello *ch, uint32_t *out_length)
914 : 2 : {
915 [ # # ][ - + ]: 2 : POSIX_ENSURE_REF(ch);
916 [ - + ][ # # ]: 2 : POSIX_ENSURE_REF(out_length);
917 : 2 : *out_length = ch->session_id.size;
918 : 2 : return S2N_SUCCESS;
919 : 2 : }
920 : :
921 : : int s2n_client_hello_get_session_id(struct s2n_client_hello *ch, uint8_t *out, uint32_t *out_length, uint32_t max_length)
922 : 1 : {
923 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(ch);
924 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(out);
925 [ # # ][ - + ]: 1 : POSIX_ENSURE_REF(out_length);
926 : :
927 : 1 : uint32_t len = min_size(&ch->session_id, max_length);
928 [ - + ][ # # ]: 1 : POSIX_CHECKED_MEMCPY(out, ch->session_id.data, len);
[ + - ]
929 : 1 : *out_length = len;
930 : :
931 : 1 : return S2N_SUCCESS;
932 : 1 : }
933 : :
934 : : int s2n_client_hello_get_compression_methods_length(struct s2n_client_hello *ch, uint32_t *out_length)
935 : 4 : {
936 [ + + ][ + - ]: 4 : POSIX_ENSURE_REF(ch);
937 [ + - ][ + + ]: 3 : POSIX_ENSURE_REF(out_length);
938 : 2 : *out_length = ch->compression_methods.size;
939 : 2 : return S2N_SUCCESS;
940 : 3 : }
941 : :
942 : : int s2n_client_hello_get_compression_methods(struct s2n_client_hello *ch, uint8_t *list, uint32_t list_length, uint32_t *out_length)
943 : 6 : {
944 [ + + ][ + - ]: 6 : POSIX_ENSURE_REF(ch);
945 [ + - ][ + + ]: 5 : POSIX_ENSURE_REF(list);
946 [ + - ][ + + ]: 4 : POSIX_ENSURE_REF(out_length);
947 : :
948 [ + + ][ + - ]: 3 : POSIX_ENSURE(list_length >= ch->compression_methods.size, S2N_ERR_INSUFFICIENT_MEM_SIZE);
949 [ - + ][ # # ]: 2 : POSIX_CHECKED_MEMCPY(list, ch->compression_methods.data, ch->compression_methods.size);
[ + - ]
950 : 2 : *out_length = ch->compression_methods.size;
951 : 2 : return S2N_SUCCESS;
952 : 2 : }
953 : :
954 : : int s2n_client_hello_get_legacy_protocol_version(struct s2n_client_hello *ch, uint8_t *out)
955 : 3 : {
956 [ + + ][ + - ]: 3 : POSIX_ENSURE_REF(ch);
957 [ + - ][ + + ]: 2 : POSIX_ENSURE_REF(out);
958 : 1 : *out = ch->legacy_version;
959 : 1 : return S2N_SUCCESS;
960 : 2 : }
961 : :
962 : : int s2n_client_hello_get_legacy_record_version(struct s2n_client_hello *ch, uint8_t *out)
963 : 3 : {
964 [ + + ][ + - ]: 3 : POSIX_ENSURE_REF(ch);
965 [ + - ][ + + ]: 2 : POSIX_ENSURE_REF(out);
966 [ - + ][ # # ]: 1 : POSIX_ENSURE(ch->record_version_recorded, S2N_ERR_INVALID_ARGUMENT);
967 : 1 : *out = ch->legacy_record_version;
968 : 1 : return S2N_SUCCESS;
969 : 1 : }
970 : :
971 : : S2N_RESULT s2n_client_hello_get_raw_extension(uint16_t extension_iana,
972 : : struct s2n_blob *raw_extensions, struct s2n_blob *extension)
973 : 6 : {
974 [ - + ][ # # ]: 6 : RESULT_ENSURE_REF(raw_extensions);
975 [ # # ][ - + ]: 6 : RESULT_ENSURE_REF(extension);
976 : :
977 : 6 : *extension = (struct s2n_blob){ 0 };
978 : :
979 : 6 : struct s2n_stuffer raw_extensions_stuffer = { 0 };
980 [ - + ]: 6 : RESULT_GUARD_POSIX(s2n_stuffer_init(&raw_extensions_stuffer, raw_extensions));
981 [ - + ]: 6 : RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&raw_extensions_stuffer, raw_extensions->size));
982 : :
983 [ + + ]: 12 : while (s2n_stuffer_data_available(&raw_extensions_stuffer) > 0) {
984 : 10 : uint16_t extension_type = 0;
985 [ - + ]: 10 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&raw_extensions_stuffer, &extension_type));
986 : :
987 : 10 : uint16_t extension_size = 0;
988 [ - + ]: 10 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&raw_extensions_stuffer, &extension_size));
989 : :
990 : 10 : uint8_t *extension_data = s2n_stuffer_raw_read(&raw_extensions_stuffer, extension_size);
991 [ - + ][ # # ]: 10 : RESULT_ENSURE_REF(extension_data);
992 : :
993 [ + + ]: 10 : if (extension_iana == extension_type) {
994 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_blob_init(extension, extension_data, extension_size));
995 : 4 : return S2N_RESULT_OK;
996 : 4 : }
997 : 10 : }
998 : 2 : return S2N_RESULT_OK;
999 : 6 : }
1000 : :
1001 : : int s2n_client_hello_has_extension(struct s2n_client_hello *ch, uint16_t extension_iana, bool *exists)
1002 : 237 : {
1003 [ + + ][ + - ]: 237 : POSIX_ENSURE_REF(ch);
1004 [ # # ][ - + ]: 236 : POSIX_ENSURE_REF(exists);
1005 : :
1006 : 236 : *exists = false;
1007 : :
1008 : 236 : s2n_extension_type_id extension_type_id = s2n_unsupported_extension;
1009 [ + + ]: 236 : if (s2n_extension_supported_iana_value_to_id(extension_iana, &extension_type_id) == S2N_SUCCESS) {
1010 : 233 : s2n_parsed_extension *parsed_extension = NULL;
1011 [ + + ]: 233 : if (s2n_client_hello_get_parsed_extension(extension_iana, &ch->extensions, &parsed_extension) == S2N_SUCCESS) {
1012 : 89 : *exists = true;
1013 : 89 : }
1014 : 233 : return S2N_SUCCESS;
1015 : 233 : }
1016 : :
1017 : 3 : struct s2n_blob extension = { 0 };
1018 [ - + ]: 3 : POSIX_GUARD_RESULT(s2n_client_hello_get_raw_extension(extension_iana, &ch->extensions.raw, &extension));
1019 [ + + ]: 3 : if (extension.data != NULL) {
1020 : 2 : *exists = true;
1021 : 2 : }
1022 : 3 : return S2N_SUCCESS;
1023 : 3 : }
1024 : :
1025 : : int s2n_client_hello_get_supported_groups(struct s2n_client_hello *ch, uint16_t *groups,
1026 : : uint16_t groups_count_max, uint16_t *groups_count_out)
1027 : 34 : {
1028 [ + + ][ + - ]: 34 : POSIX_ENSURE_REF(groups_count_out);
1029 : 33 : *groups_count_out = 0;
1030 [ + + ][ + - ]: 33 : POSIX_ENSURE_REF(ch);
1031 [ + + ][ + - ]: 32 : POSIX_ENSURE_REF(groups);
1032 : :
1033 : 31 : s2n_parsed_extension *supported_groups_extension = NULL;
1034 [ + + ]: 31 : POSIX_GUARD(s2n_client_hello_get_parsed_extension(S2N_EXTENSION_SUPPORTED_GROUPS, &ch->extensions, &supported_groups_extension));
1035 [ - + ][ # # ]: 29 : POSIX_ENSURE_REF(supported_groups_extension);
1036 : :
1037 : 29 : struct s2n_stuffer extension_stuffer = { 0 };
1038 [ - + ]: 29 : POSIX_GUARD(s2n_stuffer_init_written(&extension_stuffer, &supported_groups_extension->extension));
1039 : :
1040 : 29 : uint16_t supported_groups_count = 0;
1041 [ + + ]: 29 : POSIX_GUARD_RESULT(s2n_supported_groups_parse_count(&extension_stuffer, &supported_groups_count));
1042 [ + + ][ + - ]: 27 : POSIX_ENSURE(supported_groups_count <= groups_count_max, S2N_ERR_INSUFFICIENT_MEM_SIZE);
1043 : :
1044 [ + + ]: 199 : for (size_t i = 0; i < supported_groups_count; i++) {
1045 : : /* s2n_stuffer_read_uint16 is used to read each of the supported groups in network-order
1046 : : * endianness.
1047 : : */
1048 [ - + ]: 173 : POSIX_GUARD(s2n_stuffer_read_uint16(&extension_stuffer, &groups[i]));
1049 : 173 : }
1050 : :
1051 : 26 : *groups_count_out = supported_groups_count;
1052 : :
1053 : 26 : return S2N_SUCCESS;
1054 : 26 : }
1055 : :
1056 : : int s2n_client_hello_get_server_name_length(struct s2n_client_hello *ch, uint16_t *length)
1057 : 3 : {
1058 [ + + ][ + - ]: 3 : POSIX_ENSURE_REF(ch);
1059 [ + + ][ + - ]: 2 : POSIX_ENSURE_REF(length);
1060 : 1 : *length = 0;
1061 : :
1062 : 1 : s2n_parsed_extension *server_name_extension = NULL;
1063 [ - + ]: 1 : POSIX_GUARD(s2n_client_hello_get_parsed_extension(S2N_EXTENSION_SERVER_NAME, &ch->extensions, &server_name_extension));
1064 [ # # ][ - + ]: 1 : POSIX_ENSURE_REF(server_name_extension);
1065 : :
1066 : 1 : struct s2n_stuffer extension_stuffer = { 0 };
1067 [ - + ]: 1 : POSIX_GUARD(s2n_stuffer_init_written(&extension_stuffer, &server_name_extension->extension));
1068 : :
1069 : 1 : struct s2n_blob blob = { 0 };
1070 [ - + ]: 1 : POSIX_GUARD_RESULT(s2n_client_server_name_parse(&extension_stuffer, &blob));
1071 : 1 : *length = blob.size;
1072 : :
1073 : 1 : return S2N_SUCCESS;
1074 : 1 : }
1075 : :
1076 : : int s2n_client_hello_get_server_name(struct s2n_client_hello *ch, uint8_t *server_name, uint16_t length, uint16_t *out_length)
1077 : 5 : {
1078 [ + - ][ + + ]: 5 : POSIX_ENSURE_REF(out_length);
1079 [ + + ][ + - ]: 4 : POSIX_ENSURE_REF(ch);
1080 [ + - ][ + + ]: 3 : POSIX_ENSURE_REF(server_name);
1081 : 2 : *out_length = 0;
1082 : :
1083 : 2 : s2n_parsed_extension *server_name_extension = NULL;
1084 [ - + ]: 2 : POSIX_GUARD(s2n_client_hello_get_parsed_extension(S2N_EXTENSION_SERVER_NAME, &ch->extensions, &server_name_extension));
1085 [ # # ][ - + ]: 2 : POSIX_ENSURE_REF(server_name_extension);
1086 : :
1087 : 2 : struct s2n_stuffer extension_stuffer = { 0 };
1088 [ - + ]: 2 : POSIX_GUARD(s2n_stuffer_init_written(&extension_stuffer, &server_name_extension->extension));
1089 : :
1090 : 2 : struct s2n_blob blob = { 0 };
1091 [ - + ]: 2 : POSIX_GUARD_RESULT(s2n_client_server_name_parse(&extension_stuffer, &blob));
1092 [ + + ][ + - ]: 2 : POSIX_ENSURE_LTE(blob.size, length);
1093 [ - + ][ # # ]: 1 : POSIX_CHECKED_MEMCPY(server_name, blob.data, blob.size);
[ + - ]
1094 : :
1095 : 1 : *out_length = blob.size;
1096 : :
1097 : 1 : return S2N_SUCCESS;
1098 : 1 : }
|