LCOV - code coverage report
Current view: top level - tls - s2n_connection.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 1207 1260 95.8 %
Date: 2026-10-06 07:26:09 Functions: 95 98 96.9 %
Branches: 832 1598 52.1 %

           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 : }

Generated by: LCOV version 1.14