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_connection.h"
17 : :
18 : : #include <stdbool.h>
19 : : #include <stdint.h>
20 : : #include <stdlib.h>
21 : : #include <string.h>
22 : : #include <strings.h>
23 : : #include <time.h>
24 : : #include <unistd.h>
25 : :
26 : : #include "api/s2n.h"
27 : : /* Required for s2n_connection_get_key_update_counts */
28 : : #include "api/unstable/ktls.h"
29 : : #include "crypto/s2n_certificate.h"
30 : : #include "crypto/s2n_cipher.h"
31 : : #include "crypto/s2n_crypto.h"
32 : : #include "crypto/s2n_fips.h"
33 : : #include "crypto/s2n_openssl_x509.h"
34 : : #include "error/s2n_errno.h"
35 : : #include "tls/extensions/s2n_client_server_name.h"
36 : : #include "tls/extensions/s2n_client_supported_versions.h"
37 : : #include "tls/s2n_alerts.h"
38 : : #include "tls/s2n_cipher_suites.h"
39 : : #include "tls/s2n_handshake.h"
40 : : #include "tls/s2n_internal.h"
41 : : #include "tls/s2n_kem.h"
42 : : #include "tls/s2n_prf.h"
43 : : #include "tls/s2n_record.h"
44 : : #include "tls/s2n_resume.h"
45 : : #include "tls/s2n_security_policies.h"
46 : : #include "tls/s2n_tls.h"
47 : : #include "tls/s2n_tls13_handshake.h"
48 : : #include "tls/s2n_tls_parameters.h"
49 : : #include "utils/s2n_atomic.h"
50 : : #include "utils/s2n_blob.h"
51 : : #include "utils/s2n_compiler.h"
52 : : #include "utils/s2n_io.h"
53 : : #include "utils/s2n_mem.h"
54 : : #include "utils/s2n_random.h"
55 : : #include "utils/s2n_safety.h"
56 : : #ifndef _WIN32
57 : : #include "utils/s2n_socket.h"
58 : : #endif
59 : : #include "utils/s2n_timer.h"
60 : :
61 : : #define S2N_SET_KEY_SHARE_LIST_EMPTY(keyshares) (keyshares |= 1)
62 : : #define S2N_SET_KEY_SHARE_REQUEST(keyshares, i) (keyshares |= (1 << (i + 1)))
63 : :
64 : : static S2N_RESULT s2n_connection_and_config_get_client_auth_type(const struct s2n_connection *conn,
65 : : const struct s2n_config *config, s2n_cert_auth_type *client_cert_auth_type);
66 : :
67 : : /* Allocates and initializes memory for a new connection.
68 : : *
69 : : * Since customers can reuse a connection, ensure that values on the connection are
70 : : * initialized in `s2n_connection_wipe` where possible. */
71 : : struct s2n_connection *s2n_connection_new(s2n_mode mode)
72 : 127103 : {
73 : 127103 : struct s2n_blob blob = { 0 };
74 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_alloc(&blob, sizeof(struct s2n_connection)));
75 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_blob_zero(&blob));
76 : :
77 : : /* Cast 'through' void to acknowledge that we are changing alignment,
78 : : * which is ok, as blob.data is always aligned.
79 : : */
80 : 127103 : struct s2n_connection *conn = (struct s2n_connection *) (void *) blob.data;
81 : :
82 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_connection_set_config(conn, s2n_fetch_default_config()));
83 : :
84 : : /* `mode` is initialized here since it's passed in as a parameter. */
85 : 127103 : conn->mode = mode;
86 : :
87 : : /* Allocate the fixed-size stuffers */
88 : 127103 : blob = (struct s2n_blob){ 0 };
89 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->alert_in_data, S2N_ALERT_LENGTH));
90 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_stuffer_init(&conn->alert_in, &blob));
91 : :
92 : 127103 : blob = (struct s2n_blob){ 0 };
93 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->ticket_ext_data, S2N_TLS12_TICKET_SIZE_IN_BYTES));
94 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_stuffer_init(&conn->client_ticket_to_decrypt, &blob));
95 : :
96 : : /* Allocate long term hash and HMAC memory */
97 [ - + ]: 127103 : PTR_GUARD_RESULT(s2n_prf_new(conn));
98 [ - + ]: 127103 : PTR_GUARD_RESULT(s2n_handshake_hashes_new(&conn->handshake.hashes));
99 : :
100 : : /* Initialize the growable stuffers. Zero length at first, but the resize
101 : : * in _wipe will fix that
102 : : */
103 : 127103 : blob = (struct s2n_blob){ 0 };
104 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_blob_init(&blob, conn->header_in_data, S2N_TLS_RECORD_HEADER_LENGTH));
105 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_stuffer_init(&conn->header_in, &blob));
106 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->out, 0));
107 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->buffer_in, 0));
108 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->handshake.io, 0));
109 [ - + ]: 127103 : PTR_GUARD_RESULT(s2n_timer_start(conn->config, &conn->write_timer));
110 : :
111 : : /* NOTE: s2n_connection_wipe MUST be called last in this function.
112 : : *
113 : : * s2n_connection_wipe is used for initializing values but also used by customers to
114 : : * reset/reuse the connection. Calling it last ensures that s2n_connection_wipe is
115 : : * implemented correctly and safe.
116 : : */
117 [ - + ]: 127103 : PTR_GUARD_POSIX(s2n_connection_wipe(conn));
118 : 127103 : return conn;
119 : 127103 : }
120 : :
121 : : static int s2n_connection_zero(struct s2n_connection *conn, int mode, struct s2n_config *config)
122 : 3422420 : {
123 [ - + ][ # # ]: 3422420 : POSIX_ENSURE_REF(conn);
124 [ # # ][ - + ]: 3422420 : POSIX_ENSURE_REF(config);
125 : :
126 : : /* Zero the whole connection structure */
127 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMSET(conn, 0, sizeof(struct s2n_connection));
[ + - ]
128 : :
129 : 3422420 : conn->mode = mode;
130 : 3422420 : conn->max_outgoing_fragment_length = S2N_DEFAULT_FRAGMENT_LENGTH;
131 : 3422420 : conn->handshake.end_of_messages = APPLICATION_DATA;
132 : 3422420 : s2n_connection_set_config(conn, config);
133 : :
134 : 3422420 : return 0;
135 : 3422420 : }
136 : :
137 : : S2N_RESULT s2n_connection_wipe_all_keyshares(struct s2n_connection *conn)
138 : 3559358 : {
139 [ # # ][ - + ]: 3559358 : RESULT_ENSURE_REF(conn);
140 : :
141 [ - + ]: 3559358 : RESULT_GUARD_POSIX(s2n_ecc_evp_params_free(&conn->kex_params.server_ecc_evp_params));
142 [ - + ]: 3559358 : RESULT_GUARD_POSIX(s2n_ecc_evp_params_free(&conn->kex_params.client_ecc_evp_params));
143 : :
144 [ - + ]: 3559358 : RESULT_GUARD_POSIX(s2n_kem_group_free(&conn->kex_params.server_kem_group_params));
145 [ - + ]: 3559358 : RESULT_GUARD_POSIX(s2n_kem_group_free(&conn->kex_params.client_kem_group_params));
146 : :
147 : 3559358 : return S2N_RESULT_OK;
148 : 3559358 : }
149 : :
150 : : static int s2n_connection_wipe_keys(struct s2n_connection *conn)
151 : 3549523 : {
152 [ - + ][ # # ]: 3549523 : POSIX_ENSURE_REF(conn);
153 : :
154 : : /* Free any server key received (we may not have completed a
155 : : * handshake, so this may not have been free'd yet) */
156 [ - + ]: 3549523 : POSIX_GUARD(s2n_pkey_free(&conn->handshake_params.server_public_key));
157 [ - + ]: 3549523 : POSIX_GUARD(s2n_pkey_zero_init(&conn->handshake_params.server_public_key));
158 [ - + ]: 3549523 : POSIX_GUARD(s2n_pkey_free(&conn->handshake_params.client_public_key));
159 [ - + ]: 3549523 : POSIX_GUARD(s2n_pkey_zero_init(&conn->handshake_params.client_public_key));
160 : 3549523 : s2n_x509_validator_wipe(&conn->x509_validator);
161 [ - + ]: 3549523 : POSIX_GUARD(s2n_dh_params_free(&conn->kex_params.server_dh_params));
162 [ - + ]: 3549523 : POSIX_GUARD_RESULT(s2n_connection_wipe_all_keyshares(conn));
163 [ - + ]: 3549523 : POSIX_GUARD(s2n_kem_free(&conn->kex_params.kem_params));
164 [ - + ]: 3549523 : POSIX_GUARD(s2n_free(&conn->handshake_params.client_cert_chain));
165 [ - + ]: 3549523 : POSIX_GUARD(s2n_free(&conn->ct_response));
166 : :
167 : 3549523 : return 0;
168 : 3549523 : }
169 : :
170 : : static int s2n_connection_free_managed_recv_io(struct s2n_connection *conn)
171 : 3578073 : {
172 [ - + ][ # # ]: 3578073 : POSIX_ENSURE_REF(conn);
173 : :
174 : 3578073 : #ifndef _WIN32
175 [ + + ]: 3578073 : if (conn->managed_recv_io) {
176 [ - + ]: 6812 : POSIX_GUARD(s2n_free_object((uint8_t **) &conn->recv_io_context, sizeof(struct s2n_socket_read_io_context)));
177 : 6812 : conn->managed_recv_io = false;
178 : 6812 : conn->recv = NULL;
179 : 6812 : }
180 : 3578073 : #endif
181 : 3578073 : return S2N_SUCCESS;
182 : 3578073 : }
183 : :
184 : : static int s2n_connection_free_managed_send_io(struct s2n_connection *conn)
185 : 3578138 : {
186 [ - + ][ # # ]: 3578138 : POSIX_ENSURE_REF(conn);
187 : :
188 : 3578138 : #ifndef _WIN32
189 [ + + ]: 3578138 : if (conn->managed_send_io) {
190 [ - + ]: 6817 : POSIX_GUARD(s2n_free_object((uint8_t **) &conn->send_io_context, sizeof(struct s2n_socket_write_io_context)));
191 : 6817 : conn->managed_send_io = false;
192 : 6817 : conn->send = NULL;
193 : 6817 : }
194 : 3578138 : #endif
195 : 3578138 : return S2N_SUCCESS;
196 : 3578138 : }
197 : :
198 : : static int s2n_connection_free_managed_io(struct s2n_connection *conn)
199 : 3549523 : {
200 [ - + ]: 3549523 : POSIX_GUARD(s2n_connection_free_managed_recv_io(conn));
201 [ - + ]: 3549523 : POSIX_GUARD(s2n_connection_free_managed_send_io(conn));
202 : 3549523 : return S2N_SUCCESS;
203 : 3549523 : }
204 : :
205 : : static int s2n_connection_wipe_io(struct s2n_connection *conn)
206 : 3422420 : {
207 : 3422420 : #ifndef _WIN32
208 [ - + ][ # # ]: 3422420 : if (s2n_connection_is_managed_corked(conn) && conn->recv) {
209 [ # # ]: 0 : POSIX_GUARD(s2n_socket_read_restore(conn));
210 : 0 : }
211 [ - + ][ # # ]: 3422420 : if (s2n_connection_is_managed_corked(conn) && conn->send) {
212 [ # # ]: 0 : POSIX_GUARD(s2n_socket_write_restore(conn));
213 : 0 : }
214 : 3422420 : #endif
215 : :
216 : : /* Remove all I/O-related members */
217 [ - + ]: 3422420 : POSIX_GUARD(s2n_connection_free_managed_io(conn));
218 : :
219 : 3422420 : return 0;
220 : 3422420 : }
221 : :
222 : : static uint8_t s2n_default_verify_host(const char *host_name, size_t len, void *data)
223 : 271 : {
224 : : /* if present, match server_name of the connection using rules
225 : : * outlined in RFC6125 6.4. */
226 : :
227 : 271 : struct s2n_connection *conn = data;
228 : :
229 [ + + ]: 271 : if (conn->server_name[0] == '\0') {
230 : 7 : return 0;
231 : 7 : }
232 : :
233 : : /* complete match */
234 [ + + ][ + + ]: 264 : if (strlen(conn->server_name) == len && strncasecmp(conn->server_name, host_name, len) == 0) {
235 : 259 : return 1;
236 : 259 : }
237 : :
238 : : /* match 1 level of wildcard */
239 [ + - ][ + + ]: 5 : if (len > 2 && host_name[0] == '*' && host_name[1] == '.') {
[ + - ]
240 : 2 : const char *suffix = strchr(conn->server_name, '.');
241 : :
242 [ - + ]: 2 : if (suffix == NULL) {
243 : 0 : return 0;
244 : 0 : }
245 : :
246 [ + + ][ + - ]: 2 : if (strlen(suffix) == len - 1 && strncasecmp(suffix, host_name + 1, len - 1) == 0) {
247 : 1 : return 1;
248 : 1 : }
249 : 2 : }
250 : :
251 : 4 : return 0;
252 : 5 : }
253 : :
254 : : S2N_CLEANUP_RESULT s2n_connection_ptr_free(struct s2n_connection **conn)
255 : 124825 : {
256 [ - + ][ # # ]: 124825 : RESULT_ENSURE_REF(conn);
257 [ - + ]: 124825 : RESULT_GUARD_POSIX(s2n_connection_free(*conn));
258 : 124825 : *conn = NULL;
259 : 124825 : return S2N_RESULT_OK;
260 : 124825 : }
261 : :
262 : : int s2n_connection_free(struct s2n_connection *conn)
263 : 127103 : {
264 [ - + ]: 127103 : POSIX_GUARD(s2n_connection_wipe_keys(conn));
265 [ - + ]: 127103 : POSIX_GUARD_RESULT(s2n_psk_parameters_wipe(&conn->psk_params));
266 : :
267 [ - + ]: 127103 : POSIX_GUARD_RESULT(s2n_prf_free(conn));
268 [ - + ]: 127103 : POSIX_GUARD_RESULT(s2n_handshake_hashes_free(&conn->handshake.hashes));
269 : :
270 [ - + ]: 127103 : POSIX_GUARD(s2n_connection_free_managed_io(conn));
271 : :
272 [ - + ]: 127103 : POSIX_GUARD(s2n_free(&conn->client_ticket));
273 [ - + ]: 127103 : POSIX_GUARD(s2n_free(&conn->status_response));
274 [ - + ]: 127103 : POSIX_GUARD(s2n_free(&conn->our_quic_transport_parameters));
275 [ - + ]: 127103 : POSIX_GUARD(s2n_free(&conn->peer_quic_transport_parameters));
276 [ - + ]: 127103 : POSIX_GUARD(s2n_free(&conn->server_early_data_context));
277 [ - + ]: 127103 : POSIX_GUARD(s2n_free(&conn->tls13_ticket_fields.session_secret));
278 [ - + ]: 127103 : POSIX_GUARD(s2n_stuffer_free(&conn->buffer_in));
279 [ - + ]: 127103 : POSIX_GUARD(s2n_stuffer_free(&conn->in));
280 [ - + ]: 127103 : POSIX_GUARD(s2n_stuffer_free(&conn->out));
281 [ - + ]: 127103 : POSIX_GUARD(s2n_stuffer_free(&conn->handshake.io));
282 [ - + ]: 127103 : POSIX_GUARD(s2n_stuffer_free(&conn->post_handshake.in));
283 : 127103 : s2n_x509_validator_wipe(&conn->x509_validator);
284 [ - + ]: 127103 : POSIX_GUARD_RESULT(s2n_async_offload_op_free(&conn->async_offload_op));
285 [ - + ]: 127103 : POSIX_GUARD(s2n_client_hello_free_raw_message(&conn->client_hello));
286 [ - + ]: 127103 : POSIX_GUARD(s2n_free(&conn->application_protocols_overridden));
287 [ - + ]: 127103 : POSIX_GUARD(s2n_free(&conn->cookie));
288 [ - + ]: 127103 : POSIX_GUARD(s2n_free(&conn->cert_authorities));
289 [ - + ]: 127103 : POSIX_GUARD_RESULT(s2n_crypto_parameters_free(&conn->initial));
290 [ - + ]: 127103 : POSIX_GUARD_RESULT(s2n_crypto_parameters_free(&conn->secure));
291 [ - + ]: 127103 : POSIX_GUARD(s2n_free_object((uint8_t **) &conn, sizeof(struct s2n_connection)));
292 : :
293 : 127103 : return 0;
294 : 127103 : }
295 : :
296 : : int s2n_connection_set_config(struct s2n_connection *conn, struct s2n_config *config)
297 : 3562655 : {
298 [ - + ][ # # ]: 3562655 : POSIX_ENSURE_REF(conn);
299 [ # # ][ - + ]: 3562655 : POSIX_ENSURE_REF(config);
300 : :
301 [ + + ]: 3562655 : if (conn->config == config) {
302 : 44 : return 0;
303 : 44 : }
304 : :
305 : : /* s2n_config invariant: any s2n_config is always in a state that respects the
306 : : * config->security_policy certificate preferences. Therefore we only need to
307 : : * validate certificates here if the connection is using a security policy override.
308 : : */
309 : 3562611 : const struct s2n_security_policy *security_policy_override = conn->security_policy_override;
310 [ + + ]: 3562611 : if (security_policy_override) {
311 [ + + ]: 205 : POSIX_GUARD_RESULT(s2n_config_validate_loaded_certificates(config, security_policy_override));
312 : 205 : }
313 : :
314 : : /* We only support one client certificate */
315 [ + + ][ - + ]: 3562610 : if (s2n_config_get_num_default_certs(config) > 1 && conn->mode == S2N_CLIENT) {
316 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_TOO_MANY_CERTIFICATES);
317 : 0 : }
318 : :
319 : : /* Build the new validator into a local so that the connection's existing
320 : : * validator is not destroyed until the new one is fully initialized.
321 : : * Without this staging, a failure mid-init (e.g. X509_STORE_CTX_new
322 : : * returning NULL under OOM) would leave conn->x509_validator wiped
323 : : * while conn->config still references the old config.
324 : : */
325 : 3562610 : struct s2n_x509_validator new_validator = { 0 };
326 : :
327 [ + + ]: 3562610 : if (config->disable_x509_validation) {
328 [ - + ]: 10635 : POSIX_GUARD(s2n_x509_validator_init_no_x509_validation(&new_validator));
329 : 3551975 : } else {
330 : 3551975 : int ret = s2n_x509_validator_init(&new_validator, &config->trust_store, config->check_ocsp);
331 [ - + ]: 3551975 : if (ret != S2N_SUCCESS) {
332 : : /* init may have partially populated new_validator before failing */
333 : 0 : s2n_x509_validator_wipe(&new_validator);
334 [ # # ]: 0 : POSIX_GUARD(ret);
335 : 0 : }
336 : :
337 [ + - ]: 3551975 : if (!conn->verify_host_fn_overridden) {
338 [ + + ]: 3551975 : if (config->verify_host_fn != NULL) {
339 : 146 : conn->verify_host_fn = config->verify_host_fn;
340 : 146 : conn->data_for_verify_host = config->data_for_verify_host;
341 : 3551829 : } else {
342 : 3551829 : conn->verify_host_fn = s2n_default_verify_host;
343 : 3551829 : conn->data_for_verify_host = conn;
344 : 3551829 : }
345 : 3551975 : }
346 : :
347 [ + + ]: 3551975 : if (config->max_verify_cert_chain_depth_set) {
348 : 1 : ret = s2n_x509_validator_set_max_chain_depth(&new_validator, config->max_verify_cert_chain_depth);
349 [ + - ]: 1 : if (ret != S2N_SUCCESS) {
350 : 1 : s2n_x509_validator_wipe(&new_validator);
351 [ + - ]: 1 : POSIX_GUARD(ret);
352 : 1 : }
353 : 1 : }
354 : 3551975 : }
355 : :
356 : : /* Keep the new validator staged in a local until all fallible steps below
357 : : * succeed. Swapping it into conn before conn->config is committed would, on
358 : : * any early return, leave the connection validating against the new config's
359 : : * trust store while still referencing the old config.
360 : : */
361 : 3562609 : DEFER_CLEANUP(struct s2n_x509_validator validator_to_commit = new_validator, s2n_x509_validator_wipe);
362 : :
363 : 3562609 : conn->tickets_to_send = config->initial_tickets_to_send;
364 : :
365 [ + + ][ + + ]: 3562609 : if (conn->psk_params.psk_list.len == 0 && !conn->psk_mode_overridden) {
366 [ - + ]: 3562597 : POSIX_GUARD(s2n_connection_set_psk_mode(conn, config->psk_mode));
367 : 3562597 : conn->psk_mode_overridden = false;
368 : 3562597 : }
369 : :
370 : : /* If at least one certificate does not have a private key configured,
371 : : * the config must provide an async pkey callback.
372 : : * The handshake could still fail if the callback doesn't offload the
373 : : * signature, but this at least catches configuration mistakes.
374 : : */
375 [ + + ]: 3562609 : if (config->no_signing_key) {
376 [ + + ][ + - ]: 26 : POSIX_ENSURE(config->async_pkey_cb, S2N_ERR_NO_PRIVATE_KEY);
377 : 26 : }
378 : :
379 [ + + ]: 3562606 : if (config->quic_enabled) {
380 : : /* If QUIC is ever enabled for a connection via the config,
381 : : * we should enforce that it can never be disabled by
382 : : * changing the config.
383 : : *
384 : : * Enabling QUIC indicates that the connection is being used by
385 : : * a QUIC implementation, which never changes. Disabling QUIC
386 : : * partially through a connection could also potentially be
387 : : * dangerous, as QUIC handles encryption.
388 : : */
389 [ - + ]: 36 : POSIX_GUARD(s2n_connection_enable_quic(conn));
390 : 36 : }
391 : :
392 [ + + ]: 3562606 : if (config->send_buffer_size_override) {
393 : 18 : conn->multirecord_send = true;
394 : 18 : }
395 : :
396 : : /* Historically, calling s2n_config_set_verification_ca_location enabled OCSP stapling
397 : : * regardless of the value set by an application calling s2n_config_set_status_request_type.
398 : : * We maintain this behavior for backwards compatibility.
399 : : *
400 : : * However, the s2n_config_set_verification_ca_location behavior predates client authentication
401 : : * support for OCSP stapling, so could only affect whether clients requested OCSP stapling. We
402 : : * therefore only have to maintain the legacy behavior for clients, not servers.
403 : : *
404 : : * Note: The Rust bindings do not maintain the legacy behavior.
405 : : */
406 : 3562606 : conn->request_ocsp_status = config->ocsp_status_requested_by_user;
407 [ + + ][ + + ]: 3562606 : if (config->ocsp_status_requested_by_s2n && conn->mode == S2N_CLIENT) {
408 : 397 : conn->request_ocsp_status = true;
409 : 397 : }
410 : :
411 : : /* All fallible work has succeeded. Commit the validator and config together
412 : : * as the final, infallible step. Disarm the cleanup so the now-installed
413 : : * validator is not freed on return.
414 : : */
415 : 3562606 : s2n_x509_validator_wipe(&conn->x509_validator);
416 : 3562606 : conn->x509_validator = validator_to_commit;
417 : 3562606 : ZERO_TO_DISABLE_DEFER_CLEANUP(validator_to_commit);
418 : :
419 : 3562606 : conn->config = config;
420 : 3562606 : return S2N_SUCCESS;
421 : 3562606 : }
422 : :
423 : : int s2n_connection_server_name_extension_used(struct s2n_connection *conn)
424 : 21 : {
425 [ # # ][ - + ]: 21 : POSIX_ENSURE_REF(conn);
426 [ # # ][ - + ]: 21 : POSIX_ENSURE(conn->mode == S2N_SERVER, S2N_ERR_INVALID_STATE);
427 [ - + ][ # # ]: 21 : POSIX_ENSURE(!(conn->handshake.client_hello_received), S2N_ERR_INVALID_STATE);
428 : :
429 : 21 : conn->server_name_used = 1;
430 : 21 : return S2N_SUCCESS;
431 : 21 : }
432 : :
433 : : int s2n_connection_set_ctx(struct s2n_connection *conn, void *ctx)
434 : 2413 : {
435 [ # # ][ - + ]: 2413 : POSIX_ENSURE_REF(conn);
436 : :
437 : 2413 : conn->context = ctx;
438 : 2413 : return S2N_SUCCESS;
439 : 2413 : }
440 : :
441 : : void *s2n_connection_get_ctx(struct s2n_connection *conn)
442 : 3218 : {
443 [ - + ][ # # ]: 3218 : PTR_ENSURE_REF(conn);
444 : 3218 : return conn->context;
445 : 3218 : }
446 : :
447 : : int s2n_connection_release_buffers(struct s2n_connection *conn)
448 : 2009 : {
449 [ # # ][ - + ]: 2009 : POSIX_ENSURE_REF(conn);
450 [ - + ][ + - ]: 2009 : POSIX_PRECONDITION(s2n_stuffer_validate(&conn->out));
451 [ - + ][ + - ]: 2009 : POSIX_PRECONDITION(s2n_stuffer_validate(&conn->in));
452 : :
453 [ - + ][ # # ]: 2009 : POSIX_ENSURE(s2n_stuffer_is_consumed(&conn->out), S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA);
454 [ - + ]: 2009 : POSIX_GUARD(s2n_stuffer_resize(&conn->out, 0));
455 : :
456 [ + - ][ + + ]: 2009 : POSIX_ENSURE(s2n_stuffer_is_consumed(&conn->in), S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA);
457 [ + + ]: 2007 : if (s2n_stuffer_is_consumed(&conn->buffer_in)) {
458 [ - + ]: 2006 : POSIX_GUARD(s2n_stuffer_resize(&conn->buffer_in, 0));
459 : 2006 : }
460 : :
461 [ + - ][ + + ]: 2007 : POSIX_ENSURE(s2n_stuffer_is_consumed(&conn->post_handshake.in), S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA);
462 [ - + ]: 2006 : POSIX_GUARD(s2n_stuffer_free(&conn->post_handshake.in));
463 : :
464 [ - + ][ + - ]: 2006 : POSIX_POSTCONDITION(s2n_stuffer_validate(&conn->out));
465 [ - + ][ + - ]: 2006 : POSIX_POSTCONDITION(s2n_stuffer_validate(&conn->in));
466 : 2006 : return S2N_SUCCESS;
467 : 2006 : }
468 : :
469 : : int s2n_connection_free_handshake(struct s2n_connection *conn)
470 : 288 : {
471 [ - + ][ # # ]: 288 : POSIX_ENSURE_REF(conn);
472 : :
473 : : /* We are done with the handshake */
474 [ - + ]: 288 : POSIX_GUARD_RESULT(s2n_handshake_hashes_free(&conn->handshake.hashes));
475 [ - + ]: 288 : POSIX_GUARD_RESULT(s2n_prf_free(conn));
476 : :
477 : : /* All IO should use conn->secure after the handshake.
478 : : * However, if this method is called before the handshake completes,
479 : : * the connection may still be using conn->initial.
480 : : */
481 [ + + ][ + - ]: 288 : if (conn->client != conn->initial && conn->server != conn->initial) {
482 [ - + ]: 283 : POSIX_GUARD_RESULT(s2n_crypto_parameters_free(&conn->initial));
483 : 283 : }
484 : :
485 : : /* Wipe the buffers we are going to free */
486 [ - + ]: 288 : POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
487 [ - + ]: 288 : POSIX_GUARD(s2n_blob_zero(&conn->client_hello.raw_message));
488 : :
489 : : /* Truncate buffers to save memory, we are done with the handshake */
490 [ - + ]: 288 : POSIX_GUARD(s2n_stuffer_resize(&conn->handshake.io, 0));
491 [ - + ]: 288 : POSIX_GUARD(s2n_free(&conn->client_hello.raw_message));
492 : :
493 : : /* We can free extension data we no longer need */
494 [ - + ]: 288 : POSIX_GUARD(s2n_free(&conn->client_ticket));
495 [ - + ]: 288 : POSIX_GUARD(s2n_free(&conn->status_response));
496 [ - + ]: 288 : POSIX_GUARD(s2n_free(&conn->our_quic_transport_parameters));
497 [ - + ]: 288 : POSIX_GUARD(s2n_free(&conn->application_protocols_overridden));
498 [ - + ]: 288 : POSIX_GUARD(s2n_free(&conn->cookie));
499 [ - + ]: 288 : POSIX_GUARD(s2n_free(&conn->cert_authorities));
500 : :
501 : 288 : return 0;
502 : 288 : }
503 : :
504 : : /* An idempotent operation which initializes values on the connection.
505 : : *
506 : : * Called in order to reuse a connection structure for a new connection. Should wipe
507 : : * any persistent memory, free any temporary memory, and set all fields back to their
508 : : * defaults.
509 : : */
510 : : int s2n_connection_wipe(struct s2n_connection *conn)
511 : 3422420 : {
512 [ # # ][ - + ]: 3422420 : POSIX_ENSURE_REF(conn);
513 : :
514 : : /* First make a copy of everything we'd like to save, which isn't very much. */
515 : 3422420 : int mode = conn->mode;
516 : 3422420 : struct s2n_config *config = conn->config;
517 : 3422420 : struct s2n_stuffer alert_in = { 0 };
518 : 3422420 : struct s2n_stuffer client_ticket_to_decrypt = { 0 };
519 : 3422420 : struct s2n_stuffer handshake_io = { 0 };
520 : 3422420 : struct s2n_stuffer header_in = { 0 };
521 : 3422420 : struct s2n_stuffer buffer_in = { 0 };
522 : 3422420 : struct s2n_stuffer out = { 0 };
523 : :
524 : : /* Some required structures might have been freed to conserve memory between handshakes.
525 : : * Restore them.
526 : : */
527 [ + + ]: 3422420 : if (!conn->handshake.hashes) {
528 [ - + ]: 262 : POSIX_GUARD_RESULT(s2n_handshake_hashes_new(&conn->handshake.hashes));
529 : 262 : }
530 [ - + ]: 3422420 : POSIX_GUARD_RESULT(s2n_handshake_hashes_wipe(conn->handshake.hashes));
531 : 3422420 : struct s2n_handshake_hashes *handshake_hashes = conn->handshake.hashes;
532 [ + + ]: 3422420 : if (!conn->prf_space) {
533 [ - + ]: 263 : POSIX_GUARD_RESULT(s2n_prf_new(conn));
534 : 263 : }
535 [ - + ]: 3422420 : POSIX_GUARD_RESULT(s2n_prf_wipe(conn));
536 : 3422420 : struct s2n_prf_working_space *prf_workspace = conn->prf_space;
537 [ + + ]: 3422420 : if (!conn->initial) {
538 [ - + ]: 127361 : POSIX_GUARD_RESULT(s2n_crypto_parameters_new(&conn->initial));
539 : 3295059 : } else {
540 [ - + ]: 3295059 : POSIX_GUARD_RESULT(s2n_crypto_parameters_wipe(conn->initial));
541 : 3295059 : }
542 : 3422420 : struct s2n_crypto_parameters *initial = conn->initial;
543 [ + + ]: 3422420 : if (!conn->secure) {
544 [ - + ]: 127624 : POSIX_GUARD_RESULT(s2n_crypto_parameters_new(&conn->secure));
545 : 3294796 : } else {
546 [ - + ]: 3294796 : POSIX_GUARD_RESULT(s2n_crypto_parameters_wipe(conn->secure));
547 : 3294796 : }
548 : 3422420 : struct s2n_crypto_parameters *secure = conn->secure;
549 : :
550 : : /* Wipe all of the sensitive stuff */
551 [ - + ]: 3422420 : POSIX_GUARD(s2n_connection_wipe_keys(conn));
552 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_wipe(&conn->alert_in));
553 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_wipe(&conn->client_ticket_to_decrypt));
554 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_wipe(&conn->handshake.io));
555 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_wipe(&conn->post_handshake.in));
556 [ - + ]: 3422420 : POSIX_GUARD(s2n_blob_zero(&conn->client_hello.raw_message));
557 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_wipe(&conn->header_in));
558 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_wipe(&conn->buffer_in));
559 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_wipe(&conn->out));
560 : :
561 : : /* Free stuffers we plan to just recreate */
562 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_free(&conn->post_handshake.in));
563 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_free(&conn->in));
564 : :
565 [ - + ]: 3422420 : POSIX_GUARD_RESULT(s2n_psk_parameters_wipe(&conn->psk_params));
566 [ - + ]: 3422420 : POSIX_GUARD_RESULT(s2n_async_offload_op_free(&conn->async_offload_op));
567 : :
568 : : /* Wipe the I/O-related info and restore the original socket if necessary */
569 [ - + ]: 3422420 : POSIX_GUARD(s2n_connection_wipe_io(conn));
570 : :
571 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->client_ticket));
572 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->status_response));
573 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->application_protocols_overridden));
574 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->our_quic_transport_parameters));
575 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->peer_quic_transport_parameters));
576 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->server_early_data_context));
577 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->tls13_ticket_fields.session_secret));
578 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->cookie));
579 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->cert_authorities));
580 : :
581 : : /* Allocate memory for handling handshakes */
582 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_resize(&conn->handshake.io, S2N_LARGE_RECORD_LENGTH));
583 : :
584 : : /* Truncate the message buffers to save memory, we will dynamically resize it as needed */
585 [ - + ]: 3422420 : POSIX_GUARD(s2n_free(&conn->client_hello.raw_message));
586 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_resize(&conn->buffer_in, 0));
587 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_resize(&conn->out, 0));
588 : :
589 : : /* Remove context associated with connection */
590 : 3422420 : conn->context = NULL;
591 : 3422420 : conn->verify_host_fn_overridden = 0;
592 : 3422420 : conn->verify_host_fn = NULL;
593 : 3422420 : conn->data_for_verify_host = NULL;
594 : :
595 : : /* Clone the stuffers */
596 : : /* ignore address warnings because dest is allocated on the stack */
597 : 3422420 : #ifdef S2N_DIAGNOSTICS_PUSH_SUPPORTED
598 : 3422420 : #pragma GCC diagnostic push
599 : 3422420 : #pragma GCC diagnostic ignored "-Waddress"
600 : 3422420 : #endif
601 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&alert_in, &conn->alert_in, sizeof(struct s2n_stuffer));
[ + - ]
602 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&client_ticket_to_decrypt, &conn->client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
[ + - ]
603 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&handshake_io, &conn->handshake.io, sizeof(struct s2n_stuffer));
[ + - ]
604 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&header_in, &conn->header_in, sizeof(struct s2n_stuffer));
[ + - ]
605 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&buffer_in, &conn->buffer_in, sizeof(struct s2n_stuffer));
[ + - ]
606 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&out, &conn->out, sizeof(struct s2n_stuffer));
[ + - ]
607 : 3422420 : #ifdef S2N_DIAGNOSTICS_POP_SUPPORTED
608 : 3422420 : #pragma GCC diagnostic pop
609 : 3422420 : #endif
610 : :
611 [ - + ]: 3422420 : POSIX_GUARD(s2n_connection_zero(conn, mode, config));
612 : :
613 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&conn->alert_in, &alert_in, sizeof(struct s2n_stuffer));
[ + - ]
614 [ # # ][ - + ]: 3422420 : POSIX_CHECKED_MEMCPY(&conn->client_ticket_to_decrypt, &client_ticket_to_decrypt, sizeof(struct s2n_stuffer));
[ + - ]
615 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&conn->handshake.io, &handshake_io, sizeof(struct s2n_stuffer));
[ + - ]
616 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&conn->header_in, &header_in, sizeof(struct s2n_stuffer));
[ + - ]
617 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&conn->buffer_in, &buffer_in, sizeof(struct s2n_stuffer));
[ + - ]
618 [ - + ][ # # ]: 3422420 : POSIX_CHECKED_MEMCPY(&conn->out, &out, sizeof(struct s2n_stuffer));
[ + - ]
619 : :
620 : : /* conn->in will eventually point to part of conn->buffer_in, but we initialize
621 : : * it as growable and allocated to support legacy tests.
622 : : */
623 [ - + ]: 3422420 : POSIX_GUARD(s2n_stuffer_growable_alloc(&conn->in, 0));
624 : :
625 : 3422420 : conn->handshake.hashes = handshake_hashes;
626 : 3422420 : conn->prf_space = prf_workspace;
627 : 3422420 : conn->initial = initial;
628 : 3422420 : conn->secure = secure;
629 : 3422420 : conn->client = conn->initial;
630 : 3422420 : conn->server = conn->initial;
631 : 3422420 : conn->handshake_params.client_cert_sig_scheme = &s2n_null_sig_scheme;
632 : 3422420 : conn->handshake_params.server_cert_sig_scheme = &s2n_null_sig_scheme;
633 : :
634 [ - + ]: 3422420 : POSIX_GUARD_RESULT(s2n_psk_parameters_init(&conn->psk_params));
635 : 3422420 : conn->server_keying_material_lifetime = ONE_WEEK_IN_SEC;
636 : :
637 : : /* Require all handshakes hashes. This set can be reduced as the handshake progresses. */
638 [ - + ]: 3422420 : POSIX_GUARD(s2n_handshake_require_all_hashes(&conn->handshake));
639 : :
640 [ + + ]: 3422420 : if (conn->mode == S2N_SERVER) {
641 : : /* Start with the highest protocol version so that the highest common protocol version can be selected */
642 : : /* during handshake. */
643 : 3367305 : conn->server_protocol_version = s2n_highest_protocol_version;
644 : 3367305 : conn->client_protocol_version = s2n_unknown_protocol_version;
645 : 3367305 : conn->actual_protocol_version = s2n_unknown_protocol_version;
646 : 3367305 : } else {
647 : : /* For clients, also set actual_protocol_version. Record generation uses that value for the initial */
648 : : /* ClientHello record version. Not all servers ignore the record version in ClientHello. */
649 : 55115 : conn->server_protocol_version = s2n_unknown_protocol_version;
650 : 55115 : conn->client_protocol_version = s2n_highest_protocol_version;
651 : 55115 : conn->actual_protocol_version = s2n_highest_protocol_version;
652 : 55115 : }
653 : :
654 : : /* Initialize remaining values */
655 : 3422420 : conn->blinding = S2N_BUILT_IN_BLINDING;
656 : 3422420 : conn->session_ticket_status = S2N_NO_TICKET;
657 : :
658 : 3422420 : return 0;
659 : 3422420 : }
660 : :
661 : : int s2n_connection_set_recv_ctx(struct s2n_connection *conn, void *ctx)
662 : 14274 : {
663 [ - + ][ # # ]: 14274 : POSIX_ENSURE_REF(conn);
664 [ - + ]: 14274 : POSIX_GUARD(s2n_connection_free_managed_recv_io(conn));
665 : 14274 : conn->recv_io_context = ctx;
666 : 14274 : return S2N_SUCCESS;
667 : 14274 : }
668 : :
669 : : int s2n_connection_set_send_ctx(struct s2n_connection *conn, void *ctx)
670 : 14308 : {
671 [ - + ][ # # ]: 14308 : POSIX_ENSURE_REF(conn);
672 [ - + ]: 14308 : POSIX_GUARD(s2n_connection_free_managed_send_io(conn));
673 : 14308 : conn->send_io_context = ctx;
674 : 14308 : return S2N_SUCCESS;
675 : 14308 : }
676 : :
677 : : int s2n_connection_set_recv_cb(struct s2n_connection *conn, s2n_recv_fn recv)
678 : 14276 : {
679 [ - + ][ # # ]: 14276 : POSIX_ENSURE_REF(conn);
680 [ - + ]: 14276 : POSIX_GUARD(s2n_connection_free_managed_recv_io(conn));
681 : 14276 : conn->recv = recv;
682 : 14276 : return S2N_SUCCESS;
683 : 14276 : }
684 : :
685 : : int s2n_connection_set_send_cb(struct s2n_connection *conn, s2n_send_fn send)
686 : 14307 : {
687 [ - + ][ # # ]: 14307 : POSIX_ENSURE_REF(conn);
688 [ - + ]: 14307 : POSIX_GUARD(s2n_connection_free_managed_send_io(conn));
689 : 14307 : conn->send = send;
690 : 14307 : return S2N_SUCCESS;
691 : 14307 : }
692 : :
693 : : int s2n_connection_get_client_cert_chain(struct s2n_connection *conn, uint8_t **cert_chain_out, uint32_t *cert_chain_len)
694 : 65 : {
695 [ - + ][ # # ]: 65 : POSIX_ENSURE_REF(conn);
696 [ # # ][ - + ]: 65 : POSIX_ENSURE_REF(cert_chain_out);
697 [ - + ][ # # ]: 65 : POSIX_ENSURE_REF(cert_chain_len);
698 [ + + ][ + - ]: 65 : POSIX_ENSURE_REF(conn->handshake_params.client_cert_chain.data);
699 : :
700 : 61 : *cert_chain_out = conn->handshake_params.client_cert_chain.data;
701 : 61 : *cert_chain_len = conn->handshake_params.client_cert_chain.size;
702 : :
703 : 61 : return S2N_SUCCESS;
704 : 65 : }
705 : :
706 : : int s2n_connection_get_cipher_preferences(struct s2n_connection *conn, const struct s2n_cipher_preferences **cipher_preferences)
707 : 1021 : {
708 [ + + ][ + - ]: 1021 : POSIX_ENSURE_REF(conn);
709 [ # # ][ - + ]: 1020 : POSIX_ENSURE_REF(conn->config);
710 [ - + ][ # # ]: 1020 : POSIX_ENSURE_REF(cipher_preferences);
711 : :
712 [ + + ]: 1020 : if (conn->security_policy_override != NULL) {
713 : 970 : *cipher_preferences = conn->security_policy_override->cipher_preferences;
714 [ + + ]: 970 : } else if (conn->config->security_policy != NULL) {
715 : 49 : *cipher_preferences = conn->config->security_policy->cipher_preferences;
716 : 49 : } else {
717 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_INVALID_CIPHER_PREFERENCES);
718 : 1 : }
719 : :
720 [ - + ][ # # ]: 1019 : POSIX_ENSURE_REF(*cipher_preferences);
721 : 1019 : return 0;
722 : 1019 : }
723 : :
724 : : int s2n_connection_get_certificate_match(struct s2n_connection *conn, s2n_cert_sni_match *match_status)
725 : 9 : {
726 [ + + ][ + - ]: 9 : POSIX_ENSURE(conn, S2N_ERR_INVALID_ARGUMENT);
727 [ # # ][ - + ]: 7 : POSIX_ENSURE(match_status, S2N_ERR_INVALID_ARGUMENT);
728 [ + + ][ + - ]: 7 : POSIX_ENSURE(conn->mode == S2N_SERVER, S2N_ERR_CLIENT_MODE);
729 : :
730 : : /* Server must have gotten past certificate selection */
731 [ + + ][ + - ]: 6 : POSIX_ENSURE(conn->handshake_params.our_chain_and_key, S2N_ERR_NO_CERT_FOUND);
732 : :
733 [ + + ]: 5 : if (!s2n_server_received_server_name(conn)) {
734 : 1 : *match_status = S2N_SNI_NONE;
735 [ + + ]: 4 : } else if (conn->handshake_params.exact_sni_match_exists) {
736 : 1 : *match_status = S2N_SNI_EXACT_MATCH;
737 [ + + ]: 3 : } else if (conn->handshake_params.wc_sni_match_exists) {
738 : 1 : *match_status = S2N_SNI_WILDCARD_MATCH;
739 : 2 : } else {
740 : 2 : *match_status = S2N_SNI_NO_MATCH;
741 : 2 : }
742 : :
743 : 5 : return S2N_SUCCESS;
744 : 6 : }
745 : :
746 : : int s2n_connection_get_security_policy(struct s2n_connection *conn, const struct s2n_security_policy **security_policy)
747 : 101437 : {
748 [ + + ][ + - ]: 101437 : POSIX_ENSURE_REF(conn);
749 [ # # ][ - + ]: 101436 : POSIX_ENSURE_REF(conn->config);
750 [ - + ][ # # ]: 101436 : POSIX_ENSURE_REF(security_policy);
751 : :
752 [ + + ]: 101436 : if (conn->security_policy_override != NULL) {
753 : 19202 : *security_policy = conn->security_policy_override;
754 [ + + ]: 82234 : } else if (conn->config->security_policy != NULL) {
755 : 82233 : *security_policy = conn->config->security_policy;
756 : 82233 : } else {
757 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_INVALID_SECURITY_POLICY);
758 : 1 : }
759 : :
760 [ - + ][ # # ]: 101435 : POSIX_ENSURE_REF(*security_policy);
761 : 101435 : return 0;
762 : 101435 : }
763 : :
764 : : int s2n_connection_get_kem_preferences(struct s2n_connection *conn, const struct s2n_kem_preferences **kem_preferences)
765 : 25058 : {
766 [ + - ][ + + ]: 25058 : POSIX_ENSURE_REF(conn);
767 [ - + ][ # # ]: 25057 : POSIX_ENSURE_REF(conn->config);
768 [ - + ][ # # ]: 25057 : POSIX_ENSURE_REF(kem_preferences);
769 : :
770 [ + + ]: 25057 : if (conn->security_policy_override != NULL) {
771 : 6314 : *kem_preferences = conn->security_policy_override->kem_preferences;
772 [ + + ]: 18743 : } else if (conn->config->security_policy != NULL) {
773 : 18742 : *kem_preferences = conn->config->security_policy->kem_preferences;
774 : 18742 : } else {
775 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_INVALID_KEM_PREFERENCES);
776 : 1 : }
777 : :
778 [ # # ][ - + ]: 25056 : POSIX_ENSURE_REF(*kem_preferences);
779 : 25056 : return 0;
780 : 25056 : }
781 : :
782 : : int s2n_connection_get_signature_preferences(struct s2n_connection *conn, const struct s2n_signature_preferences **signature_preferences)
783 : 17885 : {
784 [ + + ][ + - ]: 17885 : POSIX_ENSURE_REF(conn);
785 [ - + ][ # # ]: 17884 : POSIX_ENSURE_REF(conn->config);
786 [ # # ][ - + ]: 17884 : POSIX_ENSURE_REF(signature_preferences);
787 : :
788 [ + + ]: 17884 : if (conn->security_policy_override != NULL) {
789 : 2508 : *signature_preferences = conn->security_policy_override->signature_preferences;
790 [ + + ]: 15376 : } else if (conn->config->security_policy != NULL) {
791 : 15375 : *signature_preferences = conn->config->security_policy->signature_preferences;
792 : 15375 : } else {
793 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_INVALID_SIGNATURE_ALGORITHMS_PREFERENCES);
794 : 1 : }
795 : :
796 [ # # ][ - + ]: 17883 : POSIX_ENSURE_REF(*signature_preferences);
797 : 17883 : return 0;
798 : 17883 : }
799 : :
800 : : int s2n_connection_get_ecc_preferences(struct s2n_connection *conn, const struct s2n_ecc_preferences **ecc_preferences)
801 : 87152 : {
802 [ + - ][ + + ]: 87152 : POSIX_ENSURE_REF(conn);
803 [ - + ][ # # ]: 87151 : POSIX_ENSURE_REF(conn->config);
804 [ - + ][ # # ]: 87151 : POSIX_ENSURE_REF(ecc_preferences);
805 : :
806 [ + + ]: 87151 : if (conn->security_policy_override != NULL) {
807 : 19102 : *ecc_preferences = conn->security_policy_override->ecc_preferences;
808 [ + + ]: 68049 : } else if (conn->config->security_policy != NULL) {
809 : 68048 : *ecc_preferences = conn->config->security_policy->ecc_preferences;
810 : 68048 : } else {
811 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_INVALID_ECC_PREFERENCES);
812 : 1 : }
813 : :
814 [ - + ][ # # ]: 87150 : POSIX_ENSURE_REF(*ecc_preferences);
815 : 87150 : return 0;
816 : 87150 : }
817 : :
818 : : int s2n_connection_get_protocol_preferences(struct s2n_connection *conn, struct s2n_blob **protocol_preferences)
819 : 15885 : {
820 [ + + ][ + - ]: 15885 : POSIX_ENSURE_REF(conn);
821 [ - + ][ # # ]: 15884 : POSIX_ENSURE_REF(protocol_preferences);
822 : :
823 : 15884 : *protocol_preferences = NULL;
824 [ + + ]: 15884 : if (conn->application_protocols_overridden.size > 0) {
825 : 20 : *protocol_preferences = &conn->application_protocols_overridden;
826 : 15864 : } else {
827 [ # # ][ - + ]: 15864 : POSIX_ENSURE_REF(conn->config);
828 : 15864 : *protocol_preferences = &conn->config->application_protocols;
829 : 15864 : }
830 : :
831 [ - + ][ # # ]: 15884 : POSIX_ENSURE_REF(*protocol_preferences);
832 : 15884 : return 0;
833 : 15884 : }
834 : :
835 : : static S2N_RESULT s2n_connection_and_config_get_client_auth_type(const struct s2n_connection *conn,
836 : : const struct s2n_config *config, s2n_cert_auth_type *client_cert_auth_type)
837 : 62068 : {
838 [ # # ][ - + ]: 62068 : RESULT_ENSURE_REF(conn);
839 [ # # ][ - + ]: 62068 : RESULT_ENSURE_REF(config);
840 [ # # ][ - + ]: 62068 : RESULT_ENSURE_REF(client_cert_auth_type);
841 : :
842 [ + + ]: 62068 : if (conn->client_cert_auth_type_overridden) {
843 : 1263 : *client_cert_auth_type = conn->client_cert_auth_type;
844 [ + + ]: 60805 : } else if (config->client_cert_auth_type_overridden) {
845 : 1485 : *client_cert_auth_type = config->client_cert_auth_type;
846 [ + + ]: 59320 : } else if (conn->mode == S2N_CLIENT) {
847 : : /* Clients should default to "Optional" so that they handle any
848 : : * CertificateRequests sent by the server.
849 : : */
850 : 41014 : *client_cert_auth_type = S2N_CERT_AUTH_OPTIONAL;
851 : 41014 : } else {
852 : : /* Servers should default to "None" so that they send no CertificateRequests. */
853 : 18306 : *client_cert_auth_type = S2N_CERT_AUTH_NONE;
854 : 18306 : }
855 : :
856 : 62068 : return S2N_RESULT_OK;
857 : 62068 : }
858 : :
859 : : int s2n_connection_get_client_auth_type(struct s2n_connection *conn,
860 : : s2n_cert_auth_type *client_cert_auth_type)
861 : 62068 : {
862 [ # # ][ - + ]: 62068 : POSIX_ENSURE_REF(conn);
863 [ - + ]: 62068 : POSIX_GUARD_RESULT(s2n_connection_and_config_get_client_auth_type(
864 : 62068 : conn, conn->config, client_cert_auth_type));
865 : 62068 : return S2N_SUCCESS;
866 : 62068 : }
867 : :
868 : : int s2n_connection_set_client_auth_type(struct s2n_connection *conn, s2n_cert_auth_type client_cert_auth_type)
869 : 245 : {
870 [ # # ][ - + ]: 245 : POSIX_ENSURE_REF(conn);
871 : :
872 : 245 : conn->client_cert_auth_type_overridden = 1;
873 : 245 : conn->client_cert_auth_type = client_cert_auth_type;
874 : 245 : return 0;
875 : 245 : }
876 : :
877 : : #ifndef _WIN32
878 : : int s2n_connection_set_read_fd(struct s2n_connection *conn, int rfd)
879 : 6814 : {
880 : 6814 : struct s2n_blob ctx_mem = { 0 };
881 : 6814 : struct s2n_socket_read_io_context *peer_socket_ctx = NULL;
882 : :
883 [ + - ][ + + ]: 6814 : POSIX_ENSURE_REF(conn);
884 [ - + ]: 6812 : POSIX_GUARD(s2n_alloc(&ctx_mem, sizeof(struct s2n_socket_read_io_context)));
885 [ - + ]: 6812 : POSIX_GUARD(s2n_blob_zero(&ctx_mem));
886 : :
887 : 6812 : peer_socket_ctx = (struct s2n_socket_read_io_context *) (void *) ctx_mem.data;
888 : 6812 : peer_socket_ctx->fd = rfd;
889 : :
890 [ - + ]: 6812 : POSIX_GUARD(s2n_connection_set_recv_cb(conn, s2n_socket_read));
891 [ - + ]: 6812 : POSIX_GUARD(s2n_connection_set_recv_ctx(conn, peer_socket_ctx));
892 : 6812 : conn->managed_recv_io = true;
893 : :
894 : : /* This is only needed if the user is using corked io.
895 : : * Take the snapshot in case optimized io is enabled after setting the fd.
896 : : */
897 [ - + ]: 6812 : POSIX_GUARD(s2n_socket_read_snapshot(conn));
898 : :
899 : 6812 : return 0;
900 : 6812 : }
901 : :
902 : : int s2n_connection_get_read_fd(struct s2n_connection *conn, int *readfd)
903 : 18 : {
904 [ + + ][ + - ]: 18 : POSIX_ENSURE_REF(conn);
905 [ # # ][ - + ]: 17 : POSIX_ENSURE_REF(readfd);
906 [ + - ][ + - ]: 17 : POSIX_ENSURE((conn->managed_recv_io && conn->recv_io_context), S2N_ERR_INVALID_STATE);
[ + + ]
907 : :
908 : 16 : const struct s2n_socket_read_io_context *peer_socket_ctx = conn->recv_io_context;
909 : 16 : *readfd = peer_socket_ctx->fd;
910 : 16 : return S2N_SUCCESS;
911 : 17 : }
912 : :
913 : : int s2n_connection_set_write_fd(struct s2n_connection *conn, int wfd)
914 : 6818 : {
915 : 6818 : struct s2n_blob ctx_mem = { 0 };
916 : 6818 : struct s2n_socket_write_io_context *peer_socket_ctx = NULL;
917 : :
918 [ + - ][ + + ]: 6818 : POSIX_ENSURE_REF(conn);
919 [ - + ]: 6817 : POSIX_GUARD(s2n_alloc(&ctx_mem, sizeof(struct s2n_socket_write_io_context)));
920 : :
921 : 6817 : peer_socket_ctx = (struct s2n_socket_write_io_context *) (void *) ctx_mem.data;
922 : 6817 : peer_socket_ctx->fd = wfd;
923 : :
924 [ - + ]: 6817 : POSIX_GUARD(s2n_connection_set_send_cb(conn, s2n_socket_write));
925 [ - + ]: 6817 : POSIX_GUARD(s2n_connection_set_send_ctx(conn, peer_socket_ctx));
926 : 6817 : conn->managed_send_io = true;
927 : :
928 : : /* This is only needed if the user is using corked io.
929 : : * Take the snapshot in case optimized io is enabled after setting the fd.
930 : : */
931 [ - + ]: 6817 : POSIX_GUARD(s2n_socket_write_snapshot(conn));
932 : :
933 : 6817 : conn->write_fd_broken = 0;
934 : :
935 : 6817 : return 0;
936 : 6817 : }
937 : :
938 : : int s2n_connection_get_write_fd(struct s2n_connection *conn, int *writefd)
939 : 1500 : {
940 [ + - ][ + + ]: 1500 : POSIX_ENSURE_REF(conn);
941 [ # # ][ - + ]: 1499 : POSIX_ENSURE_REF(writefd);
942 [ + - ][ + - ]: 1499 : POSIX_ENSURE((conn->managed_send_io && conn->send_io_context), S2N_ERR_INVALID_STATE);
[ + + ]
943 : :
944 : 1498 : const struct s2n_socket_write_io_context *peer_socket_ctx = conn->send_io_context;
945 : 1498 : *writefd = peer_socket_ctx->fd;
946 : 1498 : return S2N_SUCCESS;
947 : 1499 : }
948 : : int s2n_connection_set_fd(struct s2n_connection *conn, int fd)
949 : 6792 : {
950 [ + + ]: 6792 : POSIX_GUARD(s2n_connection_set_read_fd(conn, fd));
951 [ - + ]: 6791 : POSIX_GUARD(s2n_connection_set_write_fd(conn, fd));
952 : 6791 : return 0;
953 : 6791 : }
954 : :
955 : : int s2n_connection_use_corked_io(struct s2n_connection *conn)
956 : 37 : {
957 [ - + ][ # # ]: 37 : POSIX_ENSURE_REF(conn);
958 : :
959 : : /* Caller shouldn't be trying to set s2n IO corked on non-s2n-managed IO */
960 [ + - ][ + + ]: 37 : POSIX_ENSURE(conn->managed_send_io, S2N_ERR_CORK_SET_ON_UNMANAGED);
961 : 36 : conn->corked_io = 1;
962 : :
963 : 36 : return 0;
964 : 37 : }
965 : : #endif
966 : :
967 : : uint64_t s2n_connection_get_wire_bytes_in(struct s2n_connection *conn)
968 : 0 : {
969 [ # # ]: 0 : if (conn == NULL) {
970 : 0 : return 0;
971 : 0 : }
972 [ # # ]: 0 : if (conn->ktls_recv_enabled) {
973 : 0 : return 0;
974 : 0 : }
975 : 0 : return conn->wire_bytes_in;
976 : 0 : }
977 : :
978 : : uint64_t s2n_connection_get_wire_bytes_out(struct s2n_connection *conn)
979 : 4 : {
980 [ - + ]: 4 : if (conn == NULL) {
981 : 0 : return 0;
982 : 0 : }
983 [ - + ]: 4 : if (conn->ktls_send_enabled) {
984 : 0 : return 0;
985 : 0 : }
986 : 4 : return conn->wire_bytes_out;
987 : 4 : }
988 : :
989 : : const char *s2n_connection_get_cipher(struct s2n_connection *conn)
990 : 20780 : {
991 [ + + ][ + - ]: 20780 : PTR_ENSURE_REF(conn);
992 [ # # ][ - + ]: 20779 : PTR_ENSURE_REF(conn->secure);
993 [ # # ][ - + ]: 20779 : PTR_ENSURE_REF(conn->secure->cipher_suite);
994 : :
995 : 20779 : return conn->secure->cipher_suite->name;
996 : 20779 : }
997 : :
998 : : int s2n_connection_get_cipher_iana_value(struct s2n_connection *conn, uint8_t *first, uint8_t *second)
999 : 72 : {
1000 [ # # ][ - + ]: 72 : POSIX_ENSURE_REF(conn);
1001 [ # # ][ - + ]: 72 : POSIX_ENSURE_REF(conn->secure);
1002 [ # # ][ - + ]: 72 : POSIX_ENSURE_REF(conn->secure->cipher_suite);
1003 [ # # ][ - + ]: 72 : POSIX_ENSURE_MUT(first);
1004 [ # # ][ - + ]: 72 : POSIX_ENSURE_MUT(second);
1005 : :
1006 : : /* ensure we've negotiated a cipher suite */
1007 [ + - ][ + + ]: 72 : POSIX_ENSURE(!s2n_constant_time_equals(conn->secure->cipher_suite->iana_value,
1008 : 71 : s2n_null_cipher_suite.iana_value, sizeof(s2n_null_cipher_suite.iana_value)),
1009 : 71 : S2N_ERR_INVALID_STATE);
1010 : :
1011 : 71 : const uint8_t *iana_value = conn->secure->cipher_suite->iana_value;
1012 : 71 : *first = iana_value[0];
1013 : 71 : *second = iana_value[1];
1014 : :
1015 : 71 : return S2N_SUCCESS;
1016 : 72 : }
1017 : :
1018 : : const char *s2n_connection_get_curve(struct s2n_connection *conn)
1019 : 20670 : {
1020 [ # # ][ - + ]: 20670 : PTR_ENSURE_REF(conn);
1021 [ # # ][ - + ]: 20670 : PTR_ENSURE_REF(conn->secure);
1022 [ - + ][ # # ]: 20670 : PTR_ENSURE_REF(conn->secure->cipher_suite);
1023 : :
1024 [ + + ]: 20670 : if (conn->kex_params.server_ecc_evp_params.negotiated_curve) {
1025 : : /* TLS1.3 currently only uses ECC groups. */
1026 : 19448 : bool tls13 = conn->actual_protocol_version >= S2N_TLS13;
1027 : : /* we check for a full handshake, because TLS 1.2 resumption does not perform
1028 : : * an additional diffie-hellman exchange */
1029 [ + + ]: 19448 : bool ecdhe_cipher_negotiated = s2n_kex_includes(conn->secure->cipher_suite->key_exchange_alg, &s2n_ecdhe)
1030 [ + + ]: 19448 : && IS_FULL_HANDSHAKE(conn);
1031 [ + + ][ + + ]: 19448 : if (tls13 || ecdhe_cipher_negotiated) {
1032 : 17286 : return conn->kex_params.server_ecc_evp_params.negotiated_curve->name;
1033 : 17286 : }
1034 : 19448 : }
1035 : :
1036 : 3384 : return "NONE";
1037 : 20670 : }
1038 : :
1039 : : const char *s2n_connection_get_kem_name(struct s2n_connection *conn)
1040 : 0 : {
1041 [ # # ][ # # ]: 0 : PTR_ENSURE_REF(conn);
1042 : :
1043 [ # # ]: 0 : if (!conn->kex_params.kem_params.kem) {
1044 : 0 : return "NONE";
1045 : 0 : }
1046 : :
1047 : 0 : return conn->kex_params.kem_params.kem->name;
1048 : 0 : }
1049 : :
1050 : : const char *s2n_connection_get_kem_group_name(struct s2n_connection *conn)
1051 : 0 : {
1052 [ # # ][ # # ]: 0 : PTR_ENSURE_REF(conn);
1053 : :
1054 [ # # ][ # # ]: 0 : if (conn->actual_protocol_version < S2N_TLS13 || !conn->kex_params.server_kem_group_params.kem_group) {
1055 : 0 : return "NONE";
1056 : 0 : }
1057 : :
1058 : 0 : return conn->kex_params.server_kem_group_params.kem_group->name;
1059 : 0 : }
1060 : :
1061 : : int s2n_connection_get_key_exchange_group(struct s2n_connection *conn, const char **group_name)
1062 : 20618 : {
1063 [ - + ][ # # ]: 20618 : POSIX_ENSURE_REF(conn);
1064 [ # # ][ - + ]: 20618 : POSIX_ENSURE_REF(group_name);
1065 : :
1066 : : /* s2n_connection_get_curve returns only the ECDH curve portion of a named group, even if
1067 : : the negotiated group was a hybrid PQ key exchange also containing a KEM. Therefore,
1068 : : we use the result of s2n_connection_get_kem_group_name if the connection supports PQ. */
1069 [ - + ]: 20618 : if (s2n_tls13_pq_hybrid_supported(conn)) {
1070 : 0 : *group_name = s2n_connection_get_kem_group_name(conn);
1071 : 20618 : } else {
1072 : 20618 : *group_name = s2n_connection_get_curve(conn);
1073 : 20618 : }
1074 : :
1075 [ + - ][ + + ]: 20618 : POSIX_ENSURE(*group_name != NULL && strcmp(*group_name, "NONE"), S2N_ERR_INVALID_STATE);
[ + - ]
1076 : :
1077 : 17236 : return S2N_SUCCESS;
1078 : 20618 : }
1079 : :
1080 : : static S2N_RESULT s2n_connection_get_client_supported_version(struct s2n_connection *conn,
1081 : : uint8_t *client_supported_version)
1082 : 43 : {
1083 [ - + ][ # # ]: 43 : RESULT_ENSURE_REF(conn);
1084 [ - + ][ # # ]: 43 : RESULT_ENSURE_EQ(conn->mode, S2N_SERVER);
1085 : :
1086 : 43 : struct s2n_client_hello *client_hello = s2n_connection_get_client_hello(conn);
1087 [ - + ][ # # ]: 43 : RESULT_ENSURE_REF(client_hello);
1088 : :
1089 : 43 : s2n_parsed_extension *supported_versions_extension = NULL;
1090 [ + + ]: 43 : RESULT_GUARD_POSIX(s2n_client_hello_get_parsed_extension(S2N_EXTENSION_SUPPORTED_VERSIONS, &client_hello->extensions,
1091 : 28 : &supported_versions_extension));
1092 [ # # ][ - + ]: 28 : RESULT_ENSURE_REF(supported_versions_extension);
1093 : :
1094 : 28 : struct s2n_stuffer supported_versions_stuffer = { 0 };
1095 [ - + ]: 28 : RESULT_GUARD_POSIX(s2n_stuffer_init_written(&supported_versions_stuffer, &supported_versions_extension->extension));
1096 : :
1097 : 28 : uint8_t client_protocol_version = s2n_unknown_protocol_version;
1098 : 28 : uint8_t actual_protocol_version = s2n_unknown_protocol_version;
1099 [ + + ]: 28 : RESULT_GUARD_POSIX(s2n_extensions_client_supported_versions_process(conn, &supported_versions_stuffer,
1100 : 24 : &client_protocol_version, &actual_protocol_version));
1101 : :
1102 [ + + ][ + - ]: 24 : RESULT_ENSURE_NE(client_protocol_version, s2n_unknown_protocol_version);
1103 : :
1104 : 20 : *client_supported_version = client_protocol_version;
1105 : :
1106 : 20 : return S2N_RESULT_OK;
1107 : 24 : }
1108 : :
1109 : : int s2n_connection_get_client_protocol_version(struct s2n_connection *conn)
1110 : 74 : {
1111 [ + + ][ + - ]: 74 : POSIX_ENSURE_REF(conn);
1112 : :
1113 : : /* For backwards compatibility, the client_protocol_version field isn't updated via the
1114 : : * supported versions extension on TLS 1.2 servers. See
1115 : : * https://github.com/aws/s2n-tls/issues/4240.
1116 : : *
1117 : : * The extension is processed here to ensure that TLS 1.2 servers report the same client
1118 : : * protocol version to applications as TLS 1.3 servers.
1119 : : */
1120 [ + + ][ + + ]: 73 : if (conn->mode == S2N_SERVER && conn->server_protocol_version <= S2N_TLS12) {
1121 : 43 : uint8_t client_supported_version = s2n_unknown_protocol_version;
1122 : 43 : s2n_result result = s2n_connection_get_client_supported_version(conn, &client_supported_version);
1123 : :
1124 : : /* If the extension wasn't received, or if a client protocol version couldn't be determined
1125 : : * after processing the extension, the extension is ignored.
1126 : : */
1127 [ + + ]: 43 : if (s2n_result_is_ok(result)) {
1128 : 20 : return client_supported_version;
1129 : 20 : }
1130 : 43 : }
1131 : :
1132 : 53 : return conn->client_protocol_version;
1133 : 73 : }
1134 : :
1135 : : int s2n_connection_get_server_protocol_version(struct s2n_connection *conn)
1136 : 55 : {
1137 [ + - ][ + + ]: 55 : POSIX_ENSURE_REF(conn);
1138 : :
1139 : 54 : return conn->server_protocol_version;
1140 : 55 : }
1141 : :
1142 : : int s2n_connection_get_actual_protocol_version(struct s2n_connection *conn)
1143 : 20699 : {
1144 [ + + ][ + - ]: 20699 : POSIX_ENSURE_REF(conn);
1145 : :
1146 : 20698 : return conn->actual_protocol_version;
1147 : 20699 : }
1148 : :
1149 : : int s2n_connection_get_client_hello_version(struct s2n_connection *conn)
1150 : 1262 : {
1151 [ + + ][ + - ]: 1262 : POSIX_ENSURE_REF(conn);
1152 : :
1153 [ + + ]: 1261 : if (conn->client_hello.sslv2) {
1154 : 2 : return S2N_SSLv2;
1155 : 1259 : } else {
1156 [ + + ]: 1259 : return S2N_MIN(conn->client_hello.legacy_version, S2N_TLS12);
1157 : 1259 : }
1158 : 1261 : }
1159 : :
1160 : : int s2n_connection_client_cert_used(struct s2n_connection *conn)
1161 : 180 : {
1162 [ - + ][ # # ]: 180 : POSIX_ENSURE_REF(conn);
1163 : :
1164 [ + + ][ + + ]: 180 : if (IS_CLIENT_AUTH_HANDSHAKE(conn) && is_handshake_complete(conn)) {
1165 [ + - ][ + + ]: 132 : if (IS_CLIENT_AUTH_NO_CERT(conn)) {
1166 : 32 : return 0;
1167 : 32 : }
1168 : 100 : return 1;
1169 : 132 : }
1170 : 48 : return 0;
1171 : 180 : }
1172 : :
1173 : : int s2n_connection_get_alert(struct s2n_connection *conn)
1174 : 3018 : {
1175 [ - + ][ # # ]: 3018 : POSIX_ENSURE_REF(conn);
1176 : :
1177 [ - + ][ # # ]: 3018 : S2N_ERROR_IF(s2n_stuffer_data_available(&conn->alert_in) != 2, S2N_ERR_NO_ALERT);
1178 : :
1179 : : /* Shallow copy the stuffer. We assume that multiple threads might call this
1180 : : * function concurrently, so we must not mutate anything outside of the function scope */
1181 : 3018 : struct s2n_stuffer alert_stuffer = conn->alert_in;
1182 : 3018 : uint8_t alert_code = 0;
1183 [ - + ]: 3018 : POSIX_GUARD(s2n_stuffer_read_uint8(&alert_stuffer, &alert_code));
1184 [ - + ]: 3018 : POSIX_GUARD(s2n_stuffer_read_uint8(&alert_stuffer, &alert_code));
1185 : :
1186 : 3018 : return alert_code;
1187 : 3018 : }
1188 : :
1189 : : int s2n_set_server_name(struct s2n_connection *conn, const char *server_name)
1190 : 231 : {
1191 [ # # ][ - + ]: 231 : POSIX_ENSURE_REF(conn);
1192 [ - + ][ # # ]: 231 : POSIX_ENSURE_REF(server_name);
1193 : :
1194 [ - + ][ # # ]: 231 : S2N_ERROR_IF(conn->mode != S2N_CLIENT, S2N_ERR_CLIENT_MODE);
1195 : :
1196 : 231 : int len = strlen(server_name);
1197 [ - + ][ # # ]: 231 : S2N_ERROR_IF(len > S2N_MAX_SERVER_NAME, S2N_ERR_SERVER_NAME_TOO_LONG);
1198 : :
1199 [ - + ][ # # ]: 231 : POSIX_CHECKED_MEMCPY(conn->server_name, server_name, len);
[ + + ]
1200 : :
1201 : 231 : return 0;
1202 : 231 : }
1203 : :
1204 : : const char *s2n_get_server_name(struct s2n_connection *conn)
1205 : 76 : {
1206 [ + - ][ + + ]: 76 : PTR_ENSURE_REF(conn);
1207 : :
1208 [ + + ]: 42 : if (conn->server_name[0]) {
1209 : 4 : return conn->server_name;
1210 : 4 : }
1211 : :
1212 [ - + ]: 38 : PTR_GUARD_POSIX(s2n_extension_process(&s2n_client_server_name_extension, conn, &conn->client_hello.extensions));
1213 : :
1214 [ + + ]: 38 : if (!conn->server_name[0]) {
1215 : 2 : return NULL;
1216 : 2 : }
1217 : :
1218 : 36 : return conn->server_name;
1219 : 38 : }
1220 : :
1221 : : const char *s2n_get_application_protocol(struct s2n_connection *conn)
1222 : 75 : {
1223 [ - + ][ # # ]: 75 : PTR_ENSURE_REF(conn);
1224 : :
1225 [ + + ]: 75 : if (strlen(conn->application_protocol) == 0) {
1226 : 16 : return NULL;
1227 : 16 : }
1228 : :
1229 : 59 : return conn->application_protocol;
1230 : 75 : }
1231 : :
1232 : : int s2n_connection_get_session_id_length(struct s2n_connection *conn)
1233 : 11 : {
1234 [ + + ][ + - ]: 11 : POSIX_ENSURE_REF(conn);
1235 : : /* Stateful session resumption in TLS1.3 using session id is not yet supported. */
1236 [ + + ]: 10 : if (conn->actual_protocol_version >= S2N_TLS13) {
1237 : 1 : return 0;
1238 : 1 : }
1239 : 9 : return conn->session_id_len;
1240 : 10 : }
1241 : :
1242 : : int s2n_connection_get_session_id(struct s2n_connection *conn, uint8_t *session_id, size_t max_length)
1243 : 3 : {
1244 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(conn);
1245 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(session_id);
1246 : :
1247 : 3 : const int session_id_len = s2n_connection_get_session_id_length(conn);
1248 [ - + ]: 3 : POSIX_GUARD(session_id_len);
1249 : :
1250 [ - + ][ # # ]: 3 : POSIX_ENSURE((size_t) session_id_len <= max_length, S2N_ERR_SESSION_ID_TOO_LONG);
1251 : :
1252 [ # # ][ - + ]: 3 : POSIX_CHECKED_MEMCPY(session_id, conn->session_id, session_id_len);
[ + - ]
1253 : :
1254 : 3 : return session_id_len;
1255 : 3 : }
1256 : :
1257 : : int s2n_connection_set_blinding(struct s2n_connection *conn, s2n_blinding blinding)
1258 : 8690 : {
1259 [ # # ][ - + ]: 8690 : POSIX_ENSURE_REF(conn);
1260 : 8690 : conn->blinding = blinding;
1261 : :
1262 : 8690 : return 0;
1263 : 8690 : }
1264 : :
1265 : 2380 : #define ONE_S INT64_C(1000000000)
1266 : :
1267 : : static S2N_RESULT s2n_connection_get_delay_impl(struct s2n_connection *conn, uint64_t *delay)
1268 : 34 : {
1269 [ - + ][ # # ]: 34 : RESULT_ENSURE_REF(conn);
1270 [ - + ][ # # ]: 34 : RESULT_ENSURE_REF(delay);
1271 : :
1272 [ + + ]: 34 : if (!conn->delay) {
1273 : 25 : *delay = 0;
1274 : 25 : return S2N_RESULT_OK;
1275 : 25 : }
1276 : :
1277 : 9 : uint64_t elapsed = 0;
1278 [ - + ]: 9 : RESULT_GUARD(s2n_timer_elapsed(conn->config, &conn->write_timer, &elapsed));
1279 : :
1280 [ - + ]: 9 : if (elapsed > conn->delay) {
1281 : 0 : *delay = 0;
1282 : 0 : return S2N_RESULT_OK;
1283 : 0 : }
1284 : :
1285 : 9 : *delay = conn->delay - elapsed;
1286 : :
1287 : 9 : return S2N_RESULT_OK;
1288 : 9 : }
1289 : :
1290 : : uint64_t s2n_connection_get_delay(struct s2n_connection *conn)
1291 : 34 : {
1292 : 34 : uint64_t delay = 0;
1293 [ + - ]: 34 : if (s2n_result_is_ok(s2n_connection_get_delay_impl(conn, &delay))) {
1294 : 34 : return delay;
1295 : 34 : } else {
1296 : 0 : return UINT64_MAX;
1297 : 0 : }
1298 : 34 : }
1299 : :
1300 : : /* s2n-tls has a random delay that will trigger for sensitive errors. This is a mitigation
1301 : : * for possible timing sidechannels.
1302 : : *
1303 : : * The historical sidechannel that inspired s2n-tls blinding was the Lucky 13 attack, which takes
1304 : : * advantage of potential timing differences when removing padding from a record encrypted in CBC mode.
1305 : : * The attack is only theoretical in TLS; the attack criteria is unlikely to ever occur
1306 : : * (See: Fardan, N. J. A., & Paterson, K. G. (2013, May 1). Lucky Thirteen: Breaking the TLS and
1307 : : * DTLS Record Protocols.) However, we still include blinding to provide a defense in depth mitigation.
1308 : : */
1309 : : S2N_RESULT s2n_connection_calculate_blinding(struct s2n_connection *conn, int64_t *min, int64_t *max)
1310 : 1185 : {
1311 [ - + ][ # # ]: 1185 : RESULT_ENSURE_REF(conn);
1312 [ # # ][ - + ]: 1185 : RESULT_ENSURE_REF(min);
1313 [ # # ][ - + ]: 1185 : RESULT_ENSURE_REF(max);
1314 [ # # ][ - + ]: 1185 : RESULT_ENSURE_REF(conn->config);
1315 : :
1316 : : /*
1317 : : * The default delay is a random value between 10-30s. The rationale behind the range is that the
1318 : : * floor is the fixed cost that an attacker must pay per attempt, in this case, 10s. The length of
1319 : : * the range then affects the number of attempts that an attacker must perform in order to recover a
1320 : : * byte of plaintext with a certain degree of confidence.
1321 : : *
1322 : : * A uniform distribution of the range [a, b] has a variance of ((b - a)^2)/12. Therefore, given a
1323 : : * hypothetical timing difference of 1us, the number of attempts necessary to distinguish the correct
1324 : : * byte from an incorrect byte in a Lucky13-style attack is (((30 - 10) * 10 ^6)^2)/12 ~= 3.3 trillion
1325 : : * (note that we first have to convert from seconds to microseconds to match the unit of the timing difference.)
1326 : : */
1327 : 1185 : *min = S2N_DEFAULT_BLINDING_MIN * ONE_S;
1328 : 1185 : *max = S2N_DEFAULT_BLINDING_MAX * ONE_S;
1329 : :
1330 : : /* Setting the min to 1/3 of the max is an arbitrary ratio of fixed to variable delay.
1331 : : * It is based on the ratio of our original default values.
1332 : : */
1333 [ + + ]: 1185 : if (conn->config->custom_blinding_set) {
1334 : 10 : *max = conn->config->max_blinding * ONE_S;
1335 : 10 : *min = *max / 3;
1336 : 10 : }
1337 : :
1338 : 1185 : return S2N_RESULT_OK;
1339 : 1185 : }
1340 : :
1341 : : static S2N_RESULT s2n_connection_kill(struct s2n_connection *conn)
1342 : 1179 : {
1343 [ - + ][ # # ]: 1179 : RESULT_ENSURE_REF(conn);
1344 [ - + ]: 1179 : RESULT_GUARD(s2n_connection_set_closed(conn));
1345 : :
1346 : 1179 : int64_t min = 0, max = 0;
1347 [ - + ]: 1179 : RESULT_GUARD(s2n_connection_calculate_blinding(conn, &min, &max));
1348 [ + + ]: 1179 : if (max == 0) {
1349 : 4 : return S2N_RESULT_OK;
1350 : 4 : }
1351 : :
1352 : : /* Keep track of the delay so that it can be enforced */
1353 : 1175 : uint64_t rand_delay = 0;
1354 [ - + ]: 1175 : RESULT_GUARD(s2n_public_random(max - min, &rand_delay));
1355 : :
1356 : 1175 : conn->delay = min + rand_delay;
1357 : :
1358 : : /* Restart the write timer */
1359 [ - + ]: 1175 : RESULT_GUARD(s2n_timer_start(conn->config, &conn->write_timer));
1360 : :
1361 [ - + ]: 1175 : if (conn->blinding == S2N_BUILT_IN_BLINDING) {
1362 : 0 : struct timespec sleep_time = { .tv_sec = conn->delay / ONE_S, .tv_nsec = conn->delay % ONE_S };
1363 : :
1364 : 0 : int r = 0;
1365 : 0 : do {
1366 : 0 : r = nanosleep(&sleep_time, &sleep_time);
1367 [ # # ]: 0 : } while (r != 0);
1368 : 0 : }
1369 : :
1370 : 1175 : return S2N_RESULT_OK;
1371 : 1175 : }
1372 : :
1373 : : S2N_CLEANUP_RESULT s2n_connection_apply_error_blinding(struct s2n_connection **conn)
1374 : 653613 : {
1375 [ + + ][ + - ]: 653613 : RESULT_ENSURE_REF(conn);
1376 [ + + ]: 653612 : if (*conn == NULL) {
1377 : 652308 : return S2N_RESULT_OK;
1378 : 652308 : }
1379 : :
1380 : 1304 : int error_code = s2n_errno;
1381 : 1304 : int error_type = s2n_error_get_type(error_code);
1382 : :
1383 : 1304 : switch (error_type) {
1384 [ + + ]: 1 : case S2N_ERR_T_OK:
1385 : : /* Ignore no error */
1386 : 1 : return S2N_RESULT_OK;
1387 [ + + ]: 83 : case S2N_ERR_T_BLOCKED:
1388 : : /* All blocking errors are retriable and should trigger no further action. */
1389 : 83 : return S2N_RESULT_OK;
1390 [ + + ]: 1220 : default:
1391 : 1220 : break;
1392 : 1304 : }
1393 : :
1394 : : /* Ensure that conn->in doesn't contain any leftover invalid or unauthenticated data. */
1395 [ - + ]: 1220 : RESULT_GUARD_POSIX(s2n_stuffer_wipe(&(*conn)->in));
1396 : :
1397 : 1220 : switch (error_code) {
1398 : : /* Don't invoke blinding on some of the common errors.
1399 : : *
1400 : : * Be careful adding new errors here. Disabling blinding for an
1401 : : * error that can be triggered by secret / encrypted values can
1402 : : * potentially lead to a side channel attack.
1403 : : *
1404 : : * We may want to someday add an explicit error type for these errors.
1405 : : */
1406 [ + + ]: 1 : case S2N_ERR_CLOSED:
1407 [ + + ]: 14 : case S2N_ERR_CANCELLED:
1408 [ + + ]: 31 : case S2N_ERR_CIPHER_NOT_SUPPORTED:
1409 [ + + ]: 34 : case S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED:
1410 [ + + ]: 36 : case S2N_ERR_CONFIG_NULL_BEFORE_CH_CALLBACK:
1411 [ + + ]: 41 : case S2N_ERR_MISSING_CLIENT_CERT:
1412 [ - + ]: 41 : RESULT_GUARD(s2n_connection_set_closed(*conn));
1413 : 41 : break;
1414 [ + + ]: 1179 : default:
1415 : : /* Apply blinding to all other errors */
1416 [ - + ]: 1179 : RESULT_GUARD(s2n_connection_kill(*conn));
1417 : 1179 : break;
1418 : 1220 : }
1419 : :
1420 : 1220 : return S2N_RESULT_OK;
1421 : 1220 : }
1422 : :
1423 : : S2N_RESULT s2n_connection_set_closed(struct s2n_connection *conn)
1424 : 4321 : {
1425 [ - + ][ # # ]: 4321 : RESULT_ENSURE_REF(conn);
1426 : 4321 : s2n_atomic_flag_set(&conn->read_closed);
1427 : 4321 : s2n_atomic_flag_set(&conn->write_closed);
1428 : 4321 : return S2N_RESULT_OK;
1429 : 4321 : }
1430 : :
1431 : : const uint8_t *s2n_connection_get_ocsp_response(struct s2n_connection *conn, uint32_t *length)
1432 : 17 : {
1433 [ # # ][ - + ]: 17 : PTR_ENSURE_REF(conn);
1434 [ - + ][ # # ]: 17 : PTR_ENSURE_REF(length);
1435 : :
1436 : 17 : *length = conn->status_response.size;
1437 : 17 : return conn->status_response.data;
1438 : 17 : }
1439 : :
1440 : : S2N_RESULT s2n_connection_set_max_fragment_length(struct s2n_connection *conn, uint16_t max_frag_length)
1441 : 5705 : {
1442 [ + + ][ + - ]: 5705 : RESULT_ENSURE_REF(conn);
1443 : :
1444 [ + + ]: 5704 : if (conn->negotiated_mfl_code) {
1445 : : /* Respect the upper limit agreed on with the peer */
1446 [ + + ][ + - ]: 775 : RESULT_ENSURE_LT(conn->negotiated_mfl_code, s2n_array_len(mfl_code_to_length));
1447 [ + + ]: 774 : conn->max_outgoing_fragment_length = S2N_MIN(mfl_code_to_length[conn->negotiated_mfl_code], max_frag_length);
1448 : 4929 : } else {
1449 : 4929 : conn->max_outgoing_fragment_length = max_frag_length;
1450 : 4929 : }
1451 : :
1452 : : /* If no buffer has been initialized yet, no need to resize.
1453 : : * The standard I/O logic will handle initializing the buffer.
1454 : : */
1455 [ + + ]: 5703 : if (s2n_stuffer_is_freed(&conn->out)) {
1456 : 5313 : return S2N_RESULT_OK;
1457 : 5313 : }
1458 : :
1459 : 390 : uint16_t max_wire_record_size = 0;
1460 [ - + ]: 390 : RESULT_GUARD(s2n_record_max_write_size(conn, conn->max_outgoing_fragment_length, &max_wire_record_size));
1461 [ + + ]: 390 : if ((conn->out.blob.size < max_wire_record_size)) {
1462 [ - + ]: 3 : RESULT_GUARD_POSIX(s2n_realloc(&conn->out.blob, max_wire_record_size));
1463 : 3 : }
1464 : :
1465 : 390 : return S2N_RESULT_OK;
1466 : 390 : }
1467 : :
1468 : : int s2n_connection_prefer_throughput(struct s2n_connection *conn)
1469 : 30 : {
1470 [ - + ]: 30 : POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, S2N_LARGE_FRAGMENT_LENGTH));
1471 : 30 : return S2N_SUCCESS;
1472 : 30 : }
1473 : :
1474 : : int s2n_connection_prefer_low_latency(struct s2n_connection *conn)
1475 : 4337 : {
1476 [ - + ]: 4337 : POSIX_GUARD_RESULT(s2n_connection_set_max_fragment_length(conn, S2N_SMALL_FRAGMENT_LENGTH));
1477 : 4337 : return S2N_SUCCESS;
1478 : 4337 : }
1479 : :
1480 : : int s2n_connection_set_dynamic_buffers(struct s2n_connection *conn, bool enabled)
1481 : 2 : {
1482 [ # # ][ - + ]: 2 : POSIX_ENSURE_REF(conn);
1483 : 2 : conn->dynamic_buffers = enabled;
1484 : 2 : return S2N_SUCCESS;
1485 : 2 : }
1486 : :
1487 : : int s2n_connection_set_dynamic_record_threshold(struct s2n_connection *conn, uint32_t resize_threshold, uint16_t timeout_threshold)
1488 : 6 : {
1489 [ - + ][ # # ]: 6 : POSIX_ENSURE_REF(conn);
1490 [ - + ][ # # ]: 6 : S2N_ERROR_IF(resize_threshold > S2N_TLS_MAX_RESIZE_THRESHOLD, S2N_ERR_INVALID_DYNAMIC_THRESHOLD);
1491 : :
1492 : 6 : conn->dynamic_record_resize_threshold = resize_threshold;
1493 : 6 : conn->dynamic_record_timeout_threshold = timeout_threshold;
1494 : 6 : return 0;
1495 : 6 : }
1496 : :
1497 : : int s2n_connection_set_verify_host_callback(struct s2n_connection *conn, s2n_verify_host_fn verify_host_fn, void *data)
1498 : 40 : {
1499 [ - + ][ # # ]: 40 : POSIX_ENSURE_REF(conn);
1500 : :
1501 : 40 : conn->verify_host_fn = verify_host_fn;
1502 : 40 : conn->data_for_verify_host = data;
1503 : 40 : conn->verify_host_fn_overridden = 1;
1504 : :
1505 : 40 : return 0;
1506 : 40 : }
1507 : :
1508 : : int s2n_connection_recv_stuffer(struct s2n_stuffer *stuffer, struct s2n_connection *conn, uint32_t len)
1509 : 1052899 : {
1510 [ + + ][ + - ]: 1052899 : POSIX_ENSURE_REF(conn->recv);
1511 : : /* Make sure we have enough space to write */
1512 [ - + ]: 1052894 : POSIX_GUARD(s2n_stuffer_reserve_space(stuffer, len));
1513 : :
1514 : 1052894 : int r = 0;
1515 [ + + ][ - + ]: 1052894 : S2N_IO_RETRY_EINTR(r,
1516 : 1052894 : conn->recv(conn->recv_io_context, stuffer->blob.data + stuffer->write_cursor, len));
1517 [ + + ][ + - ]: 1052894 : POSIX_ENSURE(r >= 0, S2N_ERR_RECV_STUFFER_FROM_CONN);
1518 : :
1519 : : /* Record just how many bytes we have written */
1520 [ - + ]: 588106 : POSIX_GUARD(s2n_stuffer_skip_write(stuffer, r));
1521 : 588106 : return r;
1522 : 588106 : }
1523 : :
1524 : : int s2n_connection_send_stuffer(struct s2n_stuffer *stuffer, struct s2n_connection *conn, uint32_t len)
1525 : 770493 : {
1526 [ - + ][ # # ]: 770493 : POSIX_ENSURE_REF(conn);
1527 [ + - ][ + + ]: 770493 : POSIX_ENSURE_REF(conn->send);
1528 [ + + ]: 770489 : if (conn->write_fd_broken) {
1529 [ + - ]: 3 : POSIX_BAIL(S2N_ERR_SEND_STUFFER_TO_CONN);
1530 : 3 : }
1531 : : /* Make sure we even have the data */
1532 [ - + ][ # # ]: 770486 : S2N_ERROR_IF(s2n_stuffer_data_available(stuffer) < len, S2N_ERR_STUFFER_OUT_OF_DATA);
1533 : :
1534 : 770486 : int w = 0;
1535 [ + + ][ - + ]: 770486 : S2N_IO_RETRY_EINTR(w,
1536 : 770486 : conn->send(conn->send_io_context, stuffer->blob.data + stuffer->read_cursor, len));
1537 [ + + ][ + + ]: 770486 : if (w < 0 && errno == EPIPE) {
1538 : 5 : conn->write_fd_broken = 1;
1539 : 5 : }
1540 [ + + ][ + - ]: 770486 : POSIX_ENSURE(w >= 0, S2N_ERR_SEND_STUFFER_TO_CONN);
1541 : :
1542 [ - + ]: 259114 : POSIX_GUARD(s2n_stuffer_skip_read(stuffer, w));
1543 : 259114 : return w;
1544 : 259114 : }
1545 : :
1546 : : int s2n_connection_is_managed_corked(const struct s2n_connection *s2n_connection)
1547 : 6844974 : {
1548 [ - + ][ # # ]: 6844974 : POSIX_ENSURE_REF(s2n_connection);
1549 : :
1550 [ + + ][ + + ]: 6844974 : return (s2n_connection->managed_send_io && s2n_connection->corked_io);
1551 : 6844974 : }
1552 : :
1553 : : const uint8_t *s2n_connection_get_sct_list(struct s2n_connection *conn, uint32_t *length)
1554 : 3 : {
1555 [ - + ][ # # ]: 3 : PTR_ENSURE_REF(conn);
1556 [ - + ]: 3 : if (!length) {
1557 : 0 : return NULL;
1558 : 0 : }
1559 : :
1560 : 3 : *length = conn->ct_response.size;
1561 : 3 : return conn->ct_response.data;
1562 : 3 : }
1563 : :
1564 : : int s2n_connection_is_client_auth_enabled(struct s2n_connection *s2n_connection)
1565 : 13290 : {
1566 : 13290 : s2n_cert_auth_type auth_type = 0;
1567 [ - + ]: 13290 : POSIX_GUARD(s2n_connection_get_client_auth_type(s2n_connection, &auth_type));
1568 : :
1569 : 13290 : return (auth_type != S2N_CERT_AUTH_NONE);
1570 : 13290 : }
1571 : :
1572 : : struct s2n_cert_chain_and_key *s2n_connection_get_selected_cert(struct s2n_connection *conn)
1573 : 893 : {
1574 [ # # ][ - + ]: 893 : PTR_ENSURE_REF(conn);
1575 : 893 : return conn->handshake_params.our_chain_and_key;
1576 : 893 : }
1577 : :
1578 : : uint8_t s2n_connection_get_protocol_version(const struct s2n_connection *conn)
1579 : 2201956 : {
1580 [ + + ]: 2201956 : if (conn == NULL) {
1581 : 2 : return S2N_UNKNOWN_PROTOCOL_VERSION;
1582 : 2 : }
1583 : :
1584 [ + + ]: 2201954 : if (conn->actual_protocol_version != S2N_UNKNOWN_PROTOCOL_VERSION) {
1585 : 2137251 : return conn->actual_protocol_version;
1586 : 2137251 : }
1587 : :
1588 [ + + ]: 64703 : if (conn->mode == S2N_CLIENT) {
1589 : 4 : return conn->client_protocol_version;
1590 : 4 : }
1591 : 64699 : return conn->server_protocol_version;
1592 : 64703 : }
1593 : :
1594 : : DEFINE_POINTER_CLEANUP_FUNC(struct s2n_cert_chain *, s2n_cert_chain_free);
1595 : :
1596 : : int s2n_connection_get_peer_cert_chain(const struct s2n_connection *conn, struct s2n_cert_chain_and_key *cert_chain_and_key)
1597 : 31 : {
1598 [ + + ][ + - ]: 31 : POSIX_ENSURE_REF(conn);
1599 [ + + ][ + - ]: 30 : POSIX_ENSURE_REF(cert_chain_and_key);
1600 [ - + ][ # # ]: 29 : POSIX_ENSURE_REF(cert_chain_and_key->cert_chain);
1601 : :
1602 : : /* Ensure that cert_chain_and_key is empty BEFORE we modify it in any way.
1603 : : * That includes before tying its cert_chain to DEFER_CLEANUP.
1604 : : */
1605 [ + - ][ + + ]: 29 : POSIX_ENSURE(cert_chain_and_key->cert_chain->head == NULL, S2N_ERR_INVALID_ARGUMENT);
1606 : :
1607 : 28 : DEFER_CLEANUP(struct s2n_cert_chain *cert_chain = cert_chain_and_key->cert_chain, s2n_cert_chain_free_pointer);
1608 : 28 : struct s2n_cert **insert = &cert_chain->head;
1609 : :
1610 : 28 : const struct s2n_x509_validator *validator = &conn->x509_validator;
1611 [ - + ][ # # ]: 28 : POSIX_ENSURE_REF(validator);
1612 [ + + ][ + - ]: 28 : POSIX_ENSURE(s2n_x509_validator_is_cert_chain_validated(validator), S2N_ERR_CERT_NOT_VALIDATED);
1613 : :
1614 : 27 : DEFER_CLEANUP(struct s2n_validated_cert_chain validated_cert_chain = { 0 }, s2n_x509_validator_validated_cert_chain_free);
1615 [ - + ]: 27 : POSIX_GUARD_RESULT(s2n_x509_validator_get_validated_cert_chain(validator, &validated_cert_chain));
1616 : 27 : STACK_OF(X509) *cert_chain_validated = validated_cert_chain.stack;
1617 [ - + ][ # # ]: 27 : POSIX_ENSURE_REF(cert_chain_validated);
1618 : :
1619 : 27 : int cert_count = sk_X509_num(cert_chain_validated);
1620 [ # # ][ - + ]: 27 : POSIX_ENSURE_GTE(cert_count, 0);
1621 : :
1622 [ + + ]: 78 : for (size_t cert_idx = 0; cert_idx < (size_t) cert_count; cert_idx++) {
1623 : 51 : X509 *cert = sk_X509_value(cert_chain_validated, cert_idx);
1624 [ - + ][ # # ]: 51 : POSIX_ENSURE_REF(cert);
1625 : 51 : DEFER_CLEANUP(uint8_t *cert_data = NULL, s2n_crypto_free);
1626 : 51 : int cert_size = i2d_X509(cert, &cert_data);
1627 [ - + ][ # # ]: 51 : POSIX_ENSURE_GT(cert_size, 0);
1628 : :
1629 : 51 : struct s2n_blob mem = { 0 };
1630 [ - + ]: 51 : POSIX_GUARD(s2n_alloc(&mem, sizeof(struct s2n_cert)));
1631 : :
1632 : 51 : struct s2n_cert *new_node = (struct s2n_cert *) (void *) mem.data;
1633 [ - + ][ # # ]: 51 : POSIX_ENSURE_REF(new_node);
1634 : :
1635 : 51 : new_node->next = NULL;
1636 : 51 : *insert = new_node;
1637 : 51 : insert = &new_node->next;
1638 : :
1639 [ - + ]: 51 : POSIX_GUARD(s2n_alloc(&new_node->raw, cert_size));
1640 [ # # ][ - + ]: 51 : POSIX_CHECKED_MEMCPY(new_node->raw.data, cert_data, cert_size);
[ + - ]
1641 : 51 : }
1642 : :
1643 : 27 : ZERO_TO_DISABLE_DEFER_CLEANUP(cert_chain);
1644 : :
1645 : 27 : return S2N_SUCCESS;
1646 : 27 : }
1647 : :
1648 : : static S2N_RESULT s2n_signature_scheme_to_tls_iana(const struct s2n_signature_scheme *sig_scheme,
1649 : : s2n_tls_hash_algorithm *converted_scheme)
1650 : 131082 : {
1651 [ - + ][ # # ]: 131082 : RESULT_ENSURE_REF(sig_scheme);
1652 [ - + ][ # # ]: 131082 : RESULT_ENSURE_REF(converted_scheme);
1653 : 131082 : *converted_scheme = S2N_TLS_HASH_NONE;
1654 : :
1655 [ + + ]: 131082 : switch (sig_scheme->hash_alg) {
1656 [ + + ]: 2 : case S2N_HASH_MD5:
1657 : 2 : *converted_scheme = S2N_TLS_HASH_MD5;
1658 : 2 : break;
1659 [ + + ]: 2 : case S2N_HASH_SHA1:
1660 : 2 : *converted_scheme = S2N_TLS_HASH_SHA1;
1661 : 2 : break;
1662 [ + + ]: 2 : case S2N_HASH_SHA224:
1663 : 2 : *converted_scheme = S2N_TLS_HASH_SHA224;
1664 : 2 : break;
1665 [ + + ]: 6 : case S2N_HASH_SHA256:
1666 : 6 : *converted_scheme = S2N_TLS_HASH_SHA256;
1667 : 6 : break;
1668 [ + + ]: 6 : case S2N_HASH_SHA384:
1669 : 6 : *converted_scheme = S2N_TLS_HASH_SHA384;
1670 : 6 : break;
1671 [ + + ]: 2 : case S2N_HASH_SHA512:
1672 : 2 : *converted_scheme = S2N_TLS_HASH_SHA512;
1673 : 2 : break;
1674 [ + + ]: 2 : case S2N_HASH_MD5_SHA1:
1675 : 2 : *converted_scheme = S2N_TLS_HASH_MD5_SHA1;
1676 : 2 : break;
1677 [ + + ]: 4 : case S2N_HASH_NONE:
1678 [ + + ]: 6 : case S2N_HASH_SHAKE256_64:
1679 [ + + ]: 8 : case S2N_HASH_ALGS_COUNT:
1680 : 8 : *converted_scheme = S2N_TLS_HASH_NONE;
1681 : 8 : break;
1682 : 131082 : }
1683 : :
1684 : 131082 : return S2N_RESULT_OK;
1685 : 131082 : }
1686 : :
1687 : : int s2n_connection_get_selected_digest_algorithm(struct s2n_connection *conn,
1688 : : s2n_tls_hash_algorithm *converted_scheme)
1689 : 65543 : {
1690 [ + + ][ + - ]: 65543 : POSIX_ENSURE_REF(conn);
1691 [ + + ][ + - ]: 65542 : POSIX_ENSURE_REF(converted_scheme);
1692 : :
1693 [ - + ]: 65541 : POSIX_GUARD_RESULT(s2n_signature_scheme_to_tls_iana(
1694 : 65541 : conn->handshake_params.server_cert_sig_scheme, converted_scheme));
1695 : :
1696 : 65541 : return S2N_SUCCESS;
1697 : 65541 : }
1698 : :
1699 : : int s2n_connection_get_selected_client_cert_digest_algorithm(struct s2n_connection *conn,
1700 : : s2n_tls_hash_algorithm *converted_scheme)
1701 : 65543 : {
1702 [ + + ][ + - ]: 65543 : POSIX_ENSURE_REF(conn);
1703 [ + + ][ + - ]: 65542 : POSIX_ENSURE_REF(converted_scheme);
1704 : :
1705 [ - + ]: 65541 : POSIX_GUARD_RESULT(s2n_signature_scheme_to_tls_iana(
1706 : 65541 : conn->handshake_params.client_cert_sig_scheme, converted_scheme));
1707 : 65541 : return S2N_SUCCESS;
1708 : 65541 : }
1709 : :
1710 : : static S2N_RESULT s2n_signature_scheme_to_signature_algorithm(const struct s2n_signature_scheme *sig_scheme,
1711 : : s2n_tls_signature_algorithm *converted_scheme)
1712 : 131097 : {
1713 [ # # ][ - + ]: 131097 : RESULT_ENSURE_REF(sig_scheme);
1714 [ - + ][ # # ]: 131097 : RESULT_ENSURE_REF(converted_scheme);
1715 : 131097 : *converted_scheme = S2N_TLS_SIGNATURE_ANONYMOUS;
1716 : :
1717 [ + + ]: 131097 : switch (sig_scheme->sig_alg) {
1718 [ + + ]: 10 : case S2N_SIGNATURE_RSA:
1719 : 10 : *converted_scheme = S2N_TLS_SIGNATURE_RSA;
1720 : 10 : break;
1721 [ + + ]: 12 : case S2N_SIGNATURE_ECDSA:
1722 : 12 : *converted_scheme = S2N_TLS_SIGNATURE_ECDSA;
1723 : 12 : break;
1724 [ + + ]: 5 : case S2N_SIGNATURE_RSA_PSS_RSAE:
1725 : 5 : *converted_scheme = S2N_TLS_SIGNATURE_RSA_PSS_RSAE;
1726 : 5 : break;
1727 [ + + ]: 2 : case S2N_SIGNATURE_RSA_PSS_PSS:
1728 : 2 : *converted_scheme = S2N_TLS_SIGNATURE_RSA_PSS_PSS;
1729 : 2 : break;
1730 [ + + ]: 2 : case S2N_SIGNATURE_MLDSA:
1731 : 2 : *converted_scheme = S2N_TLS_SIGNATURE_MLDSA;
1732 : 2 : break;
1733 [ + + ]: 6 : case S2N_SIGNATURE_ANONYMOUS:
1734 : 6 : *converted_scheme = S2N_TLS_SIGNATURE_ANONYMOUS;
1735 : 6 : break;
1736 : 131097 : }
1737 : :
1738 : 131097 : return S2N_RESULT_OK;
1739 : 131097 : }
1740 : :
1741 : : int s2n_connection_get_selected_signature_algorithm(struct s2n_connection *conn,
1742 : : s2n_tls_signature_algorithm *converted_scheme)
1743 : 65553 : {
1744 [ + + ][ + - ]: 65553 : POSIX_ENSURE_REF(conn);
1745 [ + - ][ + + ]: 65552 : POSIX_ENSURE_REF(converted_scheme);
1746 : :
1747 [ - + ]: 65551 : POSIX_GUARD_RESULT(s2n_signature_scheme_to_signature_algorithm(
1748 : 65551 : conn->handshake_params.server_cert_sig_scheme, converted_scheme));
1749 : :
1750 : 65551 : return S2N_SUCCESS;
1751 : 65551 : }
1752 : :
1753 : : int s2n_connection_get_selected_client_cert_signature_algorithm(struct s2n_connection *conn,
1754 : : s2n_tls_signature_algorithm *converted_scheme)
1755 : 65548 : {
1756 [ + - ][ + + ]: 65548 : POSIX_ENSURE_REF(conn);
1757 [ + - ][ + + ]: 65547 : POSIX_ENSURE_REF(converted_scheme);
1758 : :
1759 [ - + ]: 65546 : POSIX_GUARD_RESULT(s2n_signature_scheme_to_signature_algorithm(
1760 : 65546 : conn->handshake_params.client_cert_sig_scheme, converted_scheme));
1761 : :
1762 : 65546 : return S2N_SUCCESS;
1763 : 65546 : }
1764 : :
1765 : : int s2n_connection_get_signature_scheme(struct s2n_connection *conn, const char **scheme_name)
1766 : 710 : {
1767 [ + + ][ + - ]: 710 : POSIX_ENSURE_REF(conn);
1768 [ + - ][ + + ]: 709 : POSIX_ENSURE_REF(scheme_name);
1769 [ + + ][ + - ]: 708 : POSIX_ENSURE(IS_NEGOTIATED(conn), S2N_ERR_INVALID_STATE);
1770 : :
1771 : 707 : const struct s2n_signature_scheme *scheme = conn->handshake_params.server_cert_sig_scheme;
1772 : : /* The scheme should never be NULL. A "none" placeholder is used if no
1773 : : * scheme has been negotiated.
1774 : : */
1775 [ # # ][ - + ]: 707 : POSIX_ENSURE_REF(scheme);
1776 : :
1777 : 707 : *scheme_name = scheme->name;
1778 [ + + ]: 707 : if (scheme->signature_curve) {
1779 : : /* Some TLS1.2 and TLS1.3 signature schemes share an IANA value,
1780 : : * but are NOT the same. The TLS1.3 version implies a specific curve.
1781 : : */
1782 [ + + ]: 108 : if (conn->actual_protocol_version >= S2N_TLS13) {
1783 : 4 : *scheme_name = scheme->tls13_name;
1784 : 104 : } else {
1785 : 104 : *scheme_name = scheme->legacy_name;
1786 : 104 : }
1787 : 108 : }
1788 : :
1789 [ - + ][ # # ]: 707 : POSIX_ENSURE_REF(*scheme_name);
1790 : 707 : return S2N_SUCCESS;
1791 : 707 : }
1792 : :
1793 : : /*
1794 : : * Gets the config set on the connection.
1795 : : */
1796 : : int s2n_connection_get_config(struct s2n_connection *conn, struct s2n_config **config)
1797 : 2 : {
1798 [ - + ][ # # ]: 2 : POSIX_ENSURE_REF(conn);
1799 [ - + ][ # # ]: 2 : POSIX_ENSURE_REF(config);
1800 : :
1801 [ + + ]: 2 : if (s2n_fetch_default_config() == conn->config) {
1802 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_NULL);
1803 : 1 : }
1804 : :
1805 : 1 : *config = conn->config;
1806 : :
1807 : 1 : return S2N_SUCCESS;
1808 : 2 : }
1809 : :
1810 : : S2N_RESULT s2n_connection_dynamic_free_out_buffer(struct s2n_connection *conn)
1811 : 691010 : {
1812 [ # # ][ - + ]: 691010 : RESULT_ENSURE_REF(conn);
1813 : :
1814 : : /* free the out buffer if we're in dynamic mode and it's completely flushed */
1815 [ + + ][ + + ]: 691010 : if (conn->dynamic_buffers && s2n_stuffer_is_consumed(&conn->out)) {
1816 : : /* since outgoing buffers are already encrypted, the buffers don't need to be zeroed, which saves some overhead */
1817 [ - + ]: 5 : RESULT_GUARD_POSIX(s2n_stuffer_free_without_wipe(&conn->out));
1818 : :
1819 : : /* reset the stuffer to its initial state */
1820 [ - + ]: 5 : RESULT_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->out, 0));
1821 : 5 : }
1822 : :
1823 : 691010 : return S2N_RESULT_OK;
1824 : 691010 : }
1825 : :
1826 : : S2N_RESULT s2n_connection_dynamic_free_in_buffer(struct s2n_connection *conn)
1827 : 681699 : {
1828 [ - + ][ # # ]: 681699 : RESULT_ENSURE_REF(conn);
1829 : :
1830 : : /* free `buffer_in` if we're in dynamic mode and it's completely flushed */
1831 [ + + ][ + + ]: 681699 : if (conn->dynamic_buffers && s2n_stuffer_is_consumed(&conn->buffer_in)) {
1832 : : /* when copying the buffer into the application, we use `s2n_stuffer_erase_and_read`, which already zeroes the memory */
1833 [ - + ]: 5 : RESULT_GUARD_POSIX(s2n_stuffer_free_without_wipe(&conn->buffer_in));
1834 : :
1835 : : /* reset the stuffer to its initial state */
1836 [ - + ]: 5 : RESULT_GUARD_POSIX(s2n_stuffer_growable_alloc(&conn->buffer_in, 0));
1837 : 5 : }
1838 : :
1839 : 681699 : return S2N_RESULT_OK;
1840 : 681699 : }
1841 : :
1842 : : bool s2n_connection_check_io_status(struct s2n_connection *conn, s2n_io_status status)
1843 : 1791732 : {
1844 [ + + ]: 1791732 : if (!conn) {
1845 : 5 : return false;
1846 : 5 : }
1847 : :
1848 : 1791727 : bool read_closed = s2n_atomic_flag_test(&conn->read_closed);
1849 : 1791727 : bool write_closed = s2n_atomic_flag_test(&conn->write_closed);
1850 [ + + ][ + + ]: 1791727 : bool full_duplex = !read_closed && !write_closed;
1851 : :
1852 : : /*
1853 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-6.1
1854 : : *# Note that this is a change from versions of TLS prior to TLS 1.3 in
1855 : : *# which implementations were required to react to a "close_notify" by
1856 : : *# discarding pending writes and sending an immediate "close_notify"
1857 : : *# alert of their own.
1858 : : */
1859 [ + + ]: 1791727 : if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
1860 [ - + ]: 330991 : switch (status) {
1861 [ + + ]: 11824 : case S2N_IO_WRITABLE:
1862 [ + + ]: 265052 : case S2N_IO_READABLE:
1863 [ + + ]: 330967 : case S2N_IO_FULL_DUPLEX:
1864 : 330967 : return full_duplex;
1865 [ + + ]: 24 : case S2N_IO_CLOSED:
1866 : 24 : return !full_duplex;
1867 : 330991 : }
1868 : 330991 : }
1869 : :
1870 [ + + ]: 1460736 : switch (status) {
1871 [ + + ]: 494536 : case S2N_IO_WRITABLE:
1872 : 494536 : return !write_closed;
1873 [ + + ]: 758711 : case S2N_IO_READABLE:
1874 : 758711 : return !read_closed;
1875 [ + + ]: 204883 : case S2N_IO_FULL_DUPLEX:
1876 : 204883 : return full_duplex;
1877 [ + + ]: 3039 : case S2N_IO_CLOSED:
1878 [ + + ][ + + ]: 3039 : return read_closed && write_closed;
1879 : 1460736 : }
1880 : :
1881 : 1 : return false;
1882 : 1460736 : }
1883 : :
1884 : : S2N_RESULT s2n_connection_get_secure_cipher(struct s2n_connection *conn, const struct s2n_cipher **cipher)
1885 : 63450 : {
1886 [ - + ][ # # ]: 63450 : RESULT_ENSURE_REF(conn);
1887 [ # # ][ - + ]: 63450 : RESULT_ENSURE_REF(cipher);
1888 [ # # ][ - + ]: 63450 : RESULT_ENSURE_REF(conn->secure);
1889 [ - + ][ # # ]: 63450 : RESULT_ENSURE_REF(conn->secure->cipher_suite);
1890 [ - + ][ # # ]: 63450 : RESULT_ENSURE_REF(conn->secure->cipher_suite->record_alg);
1891 : 63450 : *cipher = conn->secure->cipher_suite->record_alg->cipher;
1892 : 63450 : return S2N_RESULT_OK;
1893 : 63450 : }
1894 : :
1895 : : S2N_RESULT s2n_connection_get_sequence_number(struct s2n_connection *conn,
1896 : : s2n_mode mode, struct s2n_blob *seq_num)
1897 : 85281 : {
1898 [ # # ][ - + ]: 85281 : RESULT_ENSURE_REF(conn);
1899 [ - + ][ # # ]: 85281 : RESULT_ENSURE_REF(seq_num);
1900 [ - + ][ # # ]: 85281 : RESULT_ENSURE_REF(conn->secure);
1901 : :
1902 : 85281 : switch (mode) {
1903 [ + + ]: 28690 : case S2N_CLIENT:
1904 [ - + ]: 28690 : RESULT_GUARD_POSIX(s2n_blob_init(seq_num, conn->secure->client_sequence_number,
1905 : 28690 : sizeof(conn->secure->client_sequence_number)));
1906 : 28690 : break;
1907 [ + + ]: 56591 : case S2N_SERVER:
1908 [ - + ]: 56591 : RESULT_GUARD_POSIX(s2n_blob_init(seq_num, conn->secure->server_sequence_number,
1909 : 56591 : sizeof(conn->secure->server_sequence_number)));
1910 : 56591 : break;
1911 [ - + ]: 56591 : default:
1912 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_SAFETY);
1913 : 85281 : }
1914 : :
1915 : 85281 : return S2N_RESULT_OK;
1916 : 85281 : }
1917 : :
1918 : : int s2n_connection_get_key_update_counts(struct s2n_connection *conn,
1919 : : uint8_t *send_key_updates, uint8_t *recv_key_updates)
1920 : 4 : {
1921 [ + + ][ + - ]: 4 : POSIX_ENSURE_REF(conn);
1922 [ + - ][ + + ]: 3 : POSIX_ENSURE_REF(send_key_updates);
1923 [ + - ][ + + ]: 2 : POSIX_ENSURE_REF(recv_key_updates);
1924 : 1 : *send_key_updates = conn->send_key_updated;
1925 : 1 : *recv_key_updates = conn->recv_key_updated;
1926 : 1 : return S2N_SUCCESS;
1927 : 2 : }
1928 : :
1929 : : int s2n_connection_set_recv_buffering(struct s2n_connection *conn, bool enabled)
1930 : 220 : {
1931 [ # # ][ - + ]: 220 : POSIX_ENSURE_REF(conn);
1932 : : /* QUIC support is not currently compatible with recv_buffering */
1933 [ - + ][ # # ]: 220 : POSIX_ENSURE(!s2n_connection_is_quic_enabled(conn), S2N_ERR_INVALID_STATE);
1934 : 220 : conn->recv_buffering = enabled;
1935 : 220 : return S2N_SUCCESS;
1936 : 220 : }
1937 : :
1938 : : s2n_mode s2n_connection_get_mode(struct s2n_connection *conn)
1939 : 3 : {
1940 [ + + ]: 3 : if (conn == NULL) {
1941 : 1 : return S2N_SERVER;
1942 : 1 : }
1943 : 2 : return conn->mode;
1944 : 3 : }
1945 : :
1946 : : int s2n_conn_get_signature_public_key_type(struct s2n_connection *conn,
1947 : : s2n_mode mode, char *output, uint32_t *output_size)
1948 : 16 : {
1949 [ + + ][ + - ]: 16 : POSIX_ENSURE_REF(conn);
1950 [ + - ][ + + ]: 15 : POSIX_ENSURE_REF(output);
1951 [ + - ][ + + ]: 14 : POSIX_ENSURE_REF(output_size);
1952 : :
1953 : 13 : const struct s2n_cert_info *cert_info = NULL;
1954 : 13 : struct s2n_cert_info peer_cert_info = { 0 };
1955 : :
1956 : 13 : bool requesting_own_cert = (mode == conn->mode);
1957 : :
1958 [ + + ]: 13 : if (requesting_own_cert) {
1959 : : /* Return info about our own certificate */
1960 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(conn->handshake_params.our_chain_and_key);
1961 [ - + ][ # # ]: 1 : POSIX_ENSURE_REF(conn->handshake_params.our_chain_and_key->cert_chain);
1962 [ # # ][ - + ]: 1 : POSIX_ENSURE_REF(conn->handshake_params.our_chain_and_key->cert_chain->head);
1963 : 1 : cert_info = &conn->handshake_params.our_chain_and_key->cert_chain->head->info;
1964 : 12 : } else {
1965 : : /* Return info about the peer's certificate (validated during handshake) */
1966 : 12 : const struct s2n_x509_validator *validator = &conn->x509_validator;
1967 [ + + ][ + - ]: 12 : POSIX_ENSURE(s2n_x509_validator_is_cert_chain_validated(validator), S2N_ERR_CERT_NOT_VALIDATED);
1968 : :
1969 : 11 : DEFER_CLEANUP(struct s2n_validated_cert_chain validated_cert_chain = { 0 },
1970 : 11 : s2n_x509_validator_validated_cert_chain_free);
1971 [ - + ]: 11 : POSIX_GUARD_RESULT(s2n_x509_validator_get_validated_cert_chain(validator, &validated_cert_chain));
1972 : 11 : STACK_OF(X509) *cert_chain_validated = validated_cert_chain.stack;
1973 [ # # ][ - + ]: 11 : POSIX_ENSURE_REF(cert_chain_validated);
1974 : :
1975 : 11 : int cert_count = sk_X509_num(cert_chain_validated);
1976 [ - + ][ # # ]: 11 : POSIX_ENSURE_GT(cert_count, 0);
1977 : :
1978 : : /* Get the leaf certificate (first in chain) */
1979 : 11 : X509 *leaf_cert = sk_X509_value(cert_chain_validated, 0);
1980 [ - + ][ # # ]: 11 : POSIX_ENSURE_REF(leaf_cert);
1981 : :
1982 [ - + ]: 11 : POSIX_GUARD_RESULT(s2n_openssl_x509_get_cert_info(leaf_cert, &peer_cert_info));
1983 : 11 : cert_info = &peer_cert_info;
1984 : 11 : }
1985 : :
1986 [ - + ][ # # ]: 12 : POSIX_ENSURE_REF(cert_info);
1987 : :
1988 : 12 : uint32_t required_size = 0;
1989 : 12 : s2n_result format_result = s2n_cert_info_format_public_key_string(cert_info, output, *output_size, &required_size);
1990 : :
1991 : : /* Always set the output_size to the required/written size */
1992 : 12 : *output_size = required_size;
1993 : :
1994 : : /* Now check the result - this will return failure if buffer was too small */
1995 [ + + ]: 12 : if (s2n_result_is_error(format_result)) {
1996 : : /* Propagate the error that was set by s2n_format_public_key_string */
1997 [ + - ]: 1 : POSIX_BAIL(s2n_errno);
1998 : 1 : }
1999 : :
2000 : 11 : return S2N_SUCCESS;
2001 : 12 : }
|