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