LCOV - code coverage report
Current view: top level - tls - s2n_config.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 788 869 90.7 %
Date: 2026-07-04 07:27:58 Functions: 85 89 95.5 %
Branches: 426 926 46.0 %

           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                 :            : #ifndef _S2N_PRELUDE_INCLUDED
      17                 :            :     /* make sure s2n_prelude.h is includes as part of the compiler flags, if not then fail the build */
      18                 :            :     #error "Expected s2n_prelude.h to be included as part of the compiler flags"
      19                 :            : #endif
      20                 :            : 
      21                 :            : #include <strings.h>
      22                 :            : #include <time.h>
      23                 :            : 
      24                 :            : #include "api/unstable/allow_ip_in_cn.h"
      25                 :            : #include "api/unstable/custom_x509_extensions.h"
      26                 :            : #include "api/unstable/npn.h"
      27                 :            : #include "crypto/s2n_certificate.h"
      28                 :            : #include "crypto/s2n_fips.h"
      29                 :            : #include "crypto/s2n_hkdf.h"
      30                 :            : #include "crypto/s2n_libcrypto.h"
      31                 :            : #include "crypto/s2n_pq.h"
      32                 :            : #include "error/s2n_errno.h"
      33                 :            : #include "tls/s2n_cipher_preferences.h"
      34                 :            : #include "tls/s2n_internal.h"
      35                 :            : #include "tls/s2n_ktls.h"
      36                 :            : #include "tls/s2n_security_policies.h"
      37                 :            : #include "tls/s2n_tls13.h"
      38                 :            : #include "utils/s2n_blob.h"
      39                 :            : #include "utils/s2n_map.h"
      40                 :            : #include "utils/s2n_safety.h"
      41                 :            : 
      42                 :            : #if defined(CLOCK_MONOTONIC_RAW)
      43                 :            :     #define S2N_CLOCK_HW CLOCK_MONOTONIC_RAW
      44                 :            : #else
      45                 :            :     #define S2N_CLOCK_HW CLOCK_MONOTONIC
      46                 :            : #endif
      47                 :            : 
      48                 :            : #define S2N_CLOCK_SYS CLOCK_REALTIME
      49                 :            : 
      50                 :            : int s2n_default_monotonic_clock(void *unused_data, uint64_t *nanoseconds)
      51                 :     455007 : {
      52                 :     455007 :     struct timespec current_time = { 0 };
      53                 :            : 
      54         [ -  + ]:     455007 :     POSIX_GUARD(clock_gettime(S2N_CLOCK_HW, &current_time));
      55                 :            : 
      56                 :     455007 :     *nanoseconds = (uint64_t) current_time.tv_sec * 1000000000ull;
      57                 :     455007 :     *nanoseconds += current_time.tv_nsec;
      58                 :            : 
      59                 :     455007 :     return 0;
      60                 :     455007 : }
      61                 :            : 
      62                 :            : static int wall_clock(void *data, uint64_t *nanoseconds)
      63                 :       4247 : {
      64                 :       4247 :     struct timespec current_time = { 0 };
      65                 :            : 
      66         [ -  + ]:       4247 :     POSIX_GUARD(clock_gettime(S2N_CLOCK_SYS, &current_time));
      67                 :            : 
      68                 :       4247 :     *nanoseconds = (uint64_t) current_time.tv_sec * 1000000000ull;
      69                 :       4247 :     *nanoseconds += current_time.tv_nsec;
      70                 :            : 
      71                 :       4247 :     return 0;
      72                 :       4247 : }
      73                 :            : 
      74                 :            : static struct s2n_config s2n_default_config = { 0 };
      75                 :            : static struct s2n_config s2n_default_fips_config = { 0 };
      76                 :            : static struct s2n_config s2n_default_tls13_config = { 0 };
      77                 :            : 
      78                 :            : static int s2n_config_setup_default(struct s2n_config *config)
      79                 :       3232 : {
      80         [ -  + ]:       3232 :     POSIX_GUARD(s2n_config_set_cipher_preferences(config, "default"));
      81                 :       3232 :     return S2N_SUCCESS;
      82                 :       3232 : }
      83                 :            : 
      84                 :            : static int s2n_config_setup_tls13(struct s2n_config *config)
      85                 :        570 : {
      86         [ -  + ]:        570 :     POSIX_GUARD(s2n_config_set_cipher_preferences(config, "default_tls13"));
      87                 :        570 :     return S2N_SUCCESS;
      88                 :        570 : }
      89                 :            : 
      90                 :            : static int s2n_config_setup_fips(struct s2n_config *config)
      91                 :          0 : {
      92         [ #  # ]:          0 :     POSIX_GUARD(s2n_config_set_cipher_preferences(config, "default_fips"));
      93                 :          0 :     return S2N_SUCCESS;
      94                 :          0 : }
      95                 :            : 
      96                 :            : static int s2n_config_init(struct s2n_config *config)
      97                 :       2887 : {
      98                 :       2887 :     config->wall_clock = wall_clock;
      99                 :       2887 :     config->monotonic_clock = s2n_default_monotonic_clock;
     100                 :       2887 :     config->ct_type = S2N_CT_SUPPORT_NONE;
     101                 :       2887 :     config->mfl_code = S2N_TLS_MAX_FRAG_LEN_EXT_NONE;
     102                 :       2887 :     config->alert_behavior = S2N_ALERT_FAIL_ON_WARNINGS;
     103                 :       2887 :     config->session_state_lifetime_in_nanos = S2N_STATE_LIFETIME_IN_NANOS;
     104                 :       2887 :     config->encrypt_decrypt_key_lifetime_in_nanos = S2N_TICKET_ENCRYPT_DECRYPT_KEY_LIFETIME_IN_NANOS;
     105                 :       2887 :     config->decrypt_key_lifetime_in_nanos = S2N_TICKET_DECRYPT_KEY_LIFETIME_IN_NANOS;
     106                 :       2887 :     config->async_pkey_validation_mode = S2N_ASYNC_PKEY_VALIDATION_FAST;
     107                 :       2887 :     config->check_ocsp = 1;
     108                 :            : 
     109                 :       2887 :     config->client_hello_cb_mode = S2N_CLIENT_HELLO_CB_BLOCKING;
     110                 :            : 
     111         [ -  + ]:       2887 :     POSIX_GUARD(s2n_config_setup_default(config));
     112         [ +  + ]:       2887 :     if (s2n_use_default_tls13_config()) {
     113         [ -  + ]:        225 :         POSIX_GUARD(s2n_config_setup_tls13(config));
     114         [ -  + ]:       2662 :     } else if (s2n_is_in_fips_mode()) {
     115         [ #  # ]:          0 :         POSIX_GUARD(s2n_config_setup_fips(config));
     116                 :          0 :     }
     117                 :            : 
     118         [ -  + ]:       2887 :     POSIX_GUARD_PTR(config->domain_name_to_cert_map = s2n_map_new_with_initial_capacity(1));
     119         [ -  + ]:       2887 :     POSIX_GUARD_RESULT(s2n_map_complete(config->domain_name_to_cert_map));
     120                 :            : 
     121                 :       2887 :     s2n_x509_trust_store_init_empty(&config->trust_store);
     122                 :            : 
     123                 :       2887 :     return 0;
     124                 :       2887 : }
     125                 :            : 
     126                 :            : static int s2n_config_cleanup(struct s2n_config *config)
     127                 :       3313 : {
     128                 :       3313 :     s2n_x509_trust_store_wipe(&config->trust_store);
     129                 :       3313 :     config->check_ocsp = 0;
     130                 :            : 
     131         [ -  + ]:       3313 :     if (config->custom_x509_extension_oids) {
     132                 :          0 :         sk_ASN1_OBJECT_pop_free(config->custom_x509_extension_oids, ASN1_OBJECT_free);
     133                 :          0 :         config->custom_x509_extension_oids = NULL;
     134                 :          0 :     }
     135                 :            : 
     136         [ -  + ]:       3313 :     POSIX_GUARD(s2n_config_free_session_ticket_keys(config));
     137         [ -  + ]:       3313 :     POSIX_GUARD(s2n_config_free_cert_chain_and_key(config));
     138         [ -  + ]:       3313 :     POSIX_GUARD(s2n_config_free_dhparams(config));
     139         [ +  + ]:       3313 :     POSIX_GUARD(s2n_free(&config->application_protocols));
     140         [ -  + ]:       3232 :     POSIX_GUARD(s2n_free(&config->cert_authorities));
     141         [ -  + ]:       3232 :     POSIX_GUARD_RESULT(s2n_map_free(config->domain_name_to_cert_map));
     142                 :            : 
     143 [ -  + ][ #  # ]:       3232 :     POSIX_CHECKED_MEMSET(config, 0, sizeof(struct s2n_config));
                 [ +  - ]
     144                 :            : 
     145                 :       3232 :     return 0;
     146                 :       3232 : }
     147                 :            : 
     148                 :            : static int s2n_config_update_domain_name_to_cert_map(struct s2n_config *config,
     149                 :            :         struct s2n_blob *name,
     150                 :            :         struct s2n_cert_chain_and_key *cert_key_pair)
     151                 :       1321 : {
     152 [ -  + ][ #  # ]:       1321 :     POSIX_ENSURE_REF(config);
     153 [ #  # ][ -  + ]:       1321 :     POSIX_ENSURE_REF(name);
     154                 :            : 
     155                 :       1321 :     struct s2n_map *domain_name_to_cert_map = config->domain_name_to_cert_map;
     156                 :            :     /* s2n_map does not allow zero-size key */
     157         [ -  + ]:       1321 :     if (name->size == 0) {
     158                 :          0 :         return 0;
     159                 :          0 :     }
     160                 :       1321 :     s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pair);
     161                 :       1321 :     struct s2n_blob s2n_map_value = { 0 };
     162                 :       1321 :     bool key_found = false;
     163         [ -  + ]:       1321 :     POSIX_GUARD_RESULT(s2n_map_lookup(domain_name_to_cert_map, name, &s2n_map_value, &key_found));
     164         [ +  + ]:       1321 :     if (!key_found) {
     165                 :       1219 :         struct certs_by_type value = { { 0 } };
     166                 :       1219 :         value.certs[cert_type] = cert_key_pair;
     167                 :       1219 :         s2n_map_value.data = (uint8_t *) &value;
     168                 :       1219 :         s2n_map_value.size = sizeof(struct certs_by_type);
     169                 :            : 
     170         [ -  + ]:       1219 :         POSIX_GUARD_RESULT(s2n_map_unlock(domain_name_to_cert_map));
     171                 :            : 
     172         [ +  + ]:       1219 :         int add_result = s2n_result_is_ok(s2n_map_add(domain_name_to_cert_map, name, &s2n_map_value)) ? S2N_SUCCESS : S2N_FAILURE;
     173                 :            : 
     174                 :            :         /* The map must always be re-completed (made immutable) after an unlock,
     175                 :            :          * even if the add failed. Otherwise s2n_map_lookup, called on every
     176                 :            :          * ClientHello for SNI matching, will fail its RESULT_ENSURE(map->immutable)
     177                 :            :          * check, silently disabling SNI-based certificate selection for the
     178                 :            :          * lifetime of this config.
     179                 :            :          */
     180         [ -  + ]:       1219 :         POSIX_GUARD_RESULT(s2n_map_complete(domain_name_to_cert_map));
     181         [ +  + ]:       1219 :         POSIX_GUARD(add_result);
     182                 :       1219 :     } else {
     183                 :        102 :         struct certs_by_type *value = (void *) s2n_map_value.data;
     184         [ -  + ]:        102 :         if (value->certs[cert_type] == NULL) {
     185                 :          0 :             value->certs[cert_type] = cert_key_pair;
     186         [ +  + ]:        102 :         } else if (config->cert_tiebreak_cb) {
     187                 :            :             /* There's an existing certificate for this (domain_name, auth_method).
     188                 :            :              * Run the application's tiebreaking callback to decide which cert should be used.
     189                 :            :              * An application may have some context specific logic to resolve ties that are based
     190                 :            :              * on factors like trust, expiry, etc.
     191                 :            :              */
     192                 :         99 :             struct s2n_cert_chain_and_key *winner = config->cert_tiebreak_cb(
     193                 :         99 :                     value->certs[cert_type],
     194                 :         99 :                     cert_key_pair,
     195                 :         99 :                     name->data,
     196                 :         99 :                     name->size);
     197         [ +  - ]:         99 :             if (winner) {
     198                 :         99 :                 value->certs[cert_type] = winner;
     199                 :         99 :             }
     200                 :         99 :         }
     201                 :        102 :     }
     202                 :            : 
     203                 :       1320 :     return 0;
     204                 :       1321 : }
     205                 :            : 
     206                 :            : int s2n_config_build_domain_name_to_cert_map(struct s2n_config *config, struct s2n_cert_chain_and_key *cert_key_pair)
     207                 :       1320 : {
     208                 :       1320 :     uint32_t cn_len = 0;
     209         [ -  + ]:       1320 :     POSIX_GUARD_RESULT(s2n_array_num_elements(cert_key_pair->cn_names, &cn_len));
     210                 :       1320 :     uint32_t san_len = 0;
     211         [ -  + ]:       1320 :     POSIX_GUARD_RESULT(s2n_array_num_elements(cert_key_pair->san_names, &san_len));
     212                 :            : 
     213         [ +  + ]:       1320 :     if (san_len == 0) {
     214         [ +  + ]:        154 :         for (uint32_t i = 0; i < cn_len; i++) {
     215                 :         77 :             struct s2n_blob *cn_name = NULL;
     216         [ -  + ]:         77 :             POSIX_GUARD_RESULT(s2n_array_get(cert_key_pair->cn_names, i, (void **) &cn_name));
     217         [ -  + ]:         77 :             POSIX_GUARD(s2n_config_update_domain_name_to_cert_map(config, cn_name, cert_key_pair));
     218                 :         77 :         }
     219                 :       1243 :     } else {
     220         [ +  + ]:       2486 :         for (uint32_t i = 0; i < san_len; i++) {
     221                 :       1244 :             struct s2n_blob *san_name = NULL;
     222         [ -  + ]:       1244 :             POSIX_GUARD_RESULT(s2n_array_get(cert_key_pair->san_names, i, (void **) &san_name));
     223         [ +  + ]:       1244 :             POSIX_GUARD(s2n_config_update_domain_name_to_cert_map(config, san_name, cert_key_pair));
     224                 :       1244 :         }
     225                 :       1243 :     }
     226                 :            : 
     227                 :       1319 :     return 0;
     228                 :       1320 : }
     229                 :            : 
     230                 :            : struct s2n_config *s2n_fetch_default_config(void)
     231                 :     126694 : {
     232         [ +  + ]:     126694 :     if (s2n_use_default_tls13_config()) {
     233                 :        645 :         return &s2n_default_tls13_config;
     234                 :        645 :     }
     235         [ -  + ]:     126049 :     if (s2n_is_in_fips_mode()) {
     236                 :          0 :         return &s2n_default_fips_config;
     237                 :          0 :     }
     238                 :     126049 :     return &s2n_default_config;
     239                 :     126049 : }
     240                 :            : 
     241                 :            : int s2n_config_set_unsafe_for_testing(struct s2n_config *config)
     242                 :        573 : {
     243 [ #  # ][ -  + ]:        573 :     POSIX_ENSURE(s2n_in_test(), S2N_ERR_NOT_IN_TEST);
     244                 :        573 :     config->check_ocsp = 0;
     245                 :        573 :     config->disable_x509_validation = 1;
     246                 :            : 
     247                 :        573 :     return S2N_SUCCESS;
     248                 :        573 : }
     249                 :            : 
     250                 :            : int s2n_config_defaults_init(void)
     251                 :        345 : {
     252                 :            :     /* Set up fips defaults */
     253         [ -  + ]:        345 :     if (s2n_is_in_fips_mode()) {
     254         [ #  # ]:          0 :         POSIX_GUARD(s2n_config_init(&s2n_default_fips_config));
     255         [ #  # ]:          0 :         POSIX_GUARD(s2n_config_setup_fips(&s2n_default_fips_config));
     256         [ #  # ]:          0 :         POSIX_GUARD(s2n_config_load_system_certs(&s2n_default_fips_config));
     257                 :        345 :     } else {
     258                 :            :         /* Set up default */
     259         [ -  + ]:        345 :         POSIX_GUARD(s2n_config_init(&s2n_default_config));
     260         [ -  + ]:        345 :         POSIX_GUARD(s2n_config_setup_default(&s2n_default_config));
     261         [ -  + ]:        345 :         POSIX_GUARD(s2n_config_load_system_certs(&s2n_default_config));
     262                 :        345 :     }
     263                 :            : 
     264                 :            :     /* TLS 1.3 default config is only used in tests so avoid initialization costs in applications */
     265         [ -  + ]:        345 :     POSIX_GUARD(s2n_config_init(&s2n_default_tls13_config));
     266         [ -  + ]:        345 :     POSIX_GUARD(s2n_config_setup_tls13(&s2n_default_tls13_config));
     267                 :            : 
     268                 :        345 :     return S2N_SUCCESS;
     269                 :        345 : }
     270                 :            : 
     271                 :            : void s2n_wipe_static_configs(void)
     272                 :        372 : {
     273                 :        372 :     s2n_config_cleanup(&s2n_default_fips_config);
     274                 :        372 :     s2n_config_cleanup(&s2n_default_config);
     275                 :        372 :     s2n_config_cleanup(&s2n_default_tls13_config);
     276                 :        372 : }
     277                 :            : 
     278                 :            : int s2n_config_load_system_certs(struct s2n_config *config)
     279                 :       2553 : {
     280 [ +  - ][ +  + ]:       2553 :     POSIX_ENSURE_REF(config);
     281                 :            : 
     282                 :       2552 :     struct s2n_x509_trust_store *store = &config->trust_store;
     283 [ +  + ][ +  - ]:       2552 :     POSIX_ENSURE(!store->loaded_system_certs, S2N_ERR_X509_TRUST_STORE);
     284                 :            : 
     285         [ +  + ]:       2472 :     if (!store->trust_store) {
     286                 :       2471 :         store->trust_store = X509_STORE_new();
     287 [ -  + ][ #  # ]:       2471 :         POSIX_ENSURE_REF(store->trust_store);
     288                 :       2471 :     }
     289                 :            : 
     290                 :       2472 :     int err_code = X509_STORE_set_default_paths(store->trust_store);
     291         [ -  + ]:       2472 :     if (!err_code) {
     292                 :          0 :         s2n_x509_trust_store_wipe(store);
     293         [ #  # ]:          0 :         POSIX_BAIL(S2N_ERR_X509_TRUST_STORE);
     294                 :          0 :     }
     295                 :       2472 :     store->loaded_system_certs = true;
     296                 :            : 
     297                 :       2472 :     return S2N_SUCCESS;
     298                 :       2472 : }
     299                 :            : 
     300                 :            : struct s2n_config *s2n_config_new_minimal(void)
     301                 :       2197 : {
     302                 :       2197 :     struct s2n_blob allocator = { 0 };
     303                 :       2197 :     struct s2n_config *new_config = NULL;
     304                 :            : 
     305         [ -  + ]:       2197 :     PTR_GUARD_POSIX(s2n_alloc(&allocator, sizeof(struct s2n_config)));
     306         [ -  + ]:       2197 :     PTR_GUARD_POSIX(s2n_blob_zero(&allocator));
     307                 :            : 
     308                 :       2197 :     new_config = (struct s2n_config *) (void *) allocator.data;
     309         [ -  + ]:       2197 :     if (s2n_config_init(new_config) != S2N_SUCCESS) {
     310                 :          0 :         s2n_free(&allocator);
     311                 :          0 :         return NULL;
     312                 :          0 :     }
     313                 :            : 
     314                 :       2197 :     return new_config;
     315                 :       2197 : }
     316                 :            : 
     317                 :            : struct s2n_config *s2n_config_new(void)
     318                 :       2105 : {
     319                 :       2105 :     struct s2n_config *new_config = s2n_config_new_minimal();
     320 [ -  + ][ #  # ]:       2105 :     PTR_ENSURE_REF(new_config);
     321                 :            : 
     322                 :            :     /* For backwards compatibility, s2n_config_new loads system certs by default. */
     323         [ -  + ]:       2105 :     PTR_GUARD_POSIX(s2n_config_load_system_certs(new_config));
     324                 :            : 
     325                 :       2105 :     return new_config;
     326                 :       2105 : }
     327                 :            : 
     328                 :            : int s2n_config_init_session_ticket_keys(struct s2n_config *config)
     329                 :        136 : {
     330         [ +  + ]:        136 :     if (config->ticket_keys == NULL) {
     331 [ #  # ][ -  + ]:        135 :         POSIX_ENSURE_REF(config->ticket_keys = s2n_array_new_with_capacity(sizeof(struct s2n_ticket_key), S2N_MAX_TICKET_KEYS));
     332                 :        135 :     }
     333                 :            : 
     334                 :        136 :     return 0;
     335                 :        136 : }
     336                 :            : 
     337                 :            : int s2n_config_free_session_ticket_keys(struct s2n_config *config)
     338                 :       3317 : {
     339         [ +  + ]:       3317 :     if (config->ticket_keys != NULL) {
     340         [ -  + ]:        135 :         POSIX_GUARD_RESULT(s2n_array_free_p(&config->ticket_keys));
     341                 :        135 :     }
     342                 :            : 
     343                 :       3317 :     return 0;
     344                 :       3317 : }
     345                 :            : 
     346                 :            : int s2n_config_free_cert_chain_and_key(struct s2n_config *config)
     347                 :       3321 : {
     348                 :            :     /* We track certificate ownership on the config itself because a config
     349                 :            :      * CANNOT use a combination of owned and unowned chains.
     350                 :            :      * If it does, and the unowned chains are freed before the config is,
     351                 :            :      * then iterating over the chains to determine which are owned and need to be freed
     352                 :            :      * will mean also reading the invalid, freed memory of any unowned certificates.
     353                 :            :      * As of now, some tests free chains before the config, so that pattern may also
     354                 :            :      * appear in application code.
     355                 :            :      */
     356 [ -  + ][ #  # ]:       3321 :     POSIX_ENSURE_REF(config);
     357         [ +  + ]:       3321 :     if (config->cert_ownership != S2N_LIB_OWNED) {
     358                 :       3307 :         return S2N_SUCCESS;
     359                 :       3307 :     }
     360                 :            : 
     361                 :            :     /* Free the cert_chain_and_key since the application has no reference
     362                 :            :      * to it. This is necessary until s2n_config_add_cert_chain_and_key is deprecated. */
     363         [ +  + ]:         70 :     for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
     364                 :         56 :         s2n_cert_chain_and_key_free(config->default_certs_by_type.certs[i]);
     365                 :         56 :         config->default_certs_by_type.certs[i] = NULL;
     366                 :         56 :     }
     367                 :            : 
     368                 :         14 :     config->cert_ownership = S2N_NOT_OWNED;
     369                 :         14 :     return S2N_SUCCESS;
     370                 :       3321 : }
     371                 :            : 
     372                 :            : int s2n_config_free_dhparams(struct s2n_config *config)
     373                 :       3313 : {
     374 [ #  # ][ -  + ]:       3313 :     POSIX_ENSURE_REF(config);
     375         [ +  + ]:       3313 :     if (config->dhparams) {
     376         [ -  + ]:         81 :         POSIX_GUARD(s2n_dh_params_free(config->dhparams));
     377                 :         81 :     }
     378                 :            : 
     379         [ -  + ]:       3313 :     POSIX_GUARD(s2n_free_object((uint8_t **) &config->dhparams, sizeof(struct s2n_dh_params)));
     380                 :       3313 :     return 0;
     381                 :       3313 : }
     382                 :            : 
     383                 :            : S2N_CLEANUP_RESULT s2n_config_ptr_free(struct s2n_config **config)
     384                 :       1629 : {
     385 [ #  # ][ -  + ]:       1629 :     RESULT_ENSURE_REF(config);
     386         [ -  + ]:       1629 :     RESULT_GUARD_POSIX(s2n_config_free(*config));
     387                 :       1629 :     *config = NULL;
     388                 :       1629 :     return S2N_RESULT_OK;
     389                 :       1629 : }
     390                 :            : 
     391                 :            : int s2n_config_free(struct s2n_config *config)
     392                 :       2197 : {
     393                 :       2197 :     s2n_config_cleanup(config);
     394                 :            : 
     395         [ -  + ]:       2197 :     POSIX_GUARD(s2n_free_object((uint8_t **) &config, sizeof(struct s2n_config)));
     396                 :       2197 :     return 0;
     397                 :       2197 : }
     398                 :            : 
     399                 :            : int s2n_config_get_client_auth_type(struct s2n_config *config, s2n_cert_auth_type *client_auth_type)
     400                 :          0 : {
     401 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(config);
     402 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(client_auth_type);
     403                 :          0 :     *client_auth_type = config->client_cert_auth_type;
     404                 :          0 :     return 0;
     405                 :          0 : }
     406                 :            : 
     407                 :            : int s2n_config_set_client_auth_type(struct s2n_config *config, s2n_cert_auth_type client_auth_type)
     408                 :        185 : {
     409 [ -  + ][ #  # ]:        185 :     POSIX_ENSURE_REF(config);
     410                 :        185 :     config->client_cert_auth_type_overridden = 1;
     411                 :        185 :     config->client_cert_auth_type = client_auth_type;
     412                 :        185 :     return 0;
     413                 :        185 : }
     414                 :            : 
     415                 :            : int s2n_config_set_ct_support_level(struct s2n_config *config, s2n_ct_support_level type)
     416                 :          6 : {
     417 [ -  + ][ #  # ]:          6 :     POSIX_ENSURE_REF(config);
     418                 :          6 :     config->ct_type = type;
     419                 :            : 
     420                 :          6 :     return 0;
     421                 :          6 : }
     422                 :            : 
     423                 :            : int s2n_config_set_alert_behavior(struct s2n_config *config, s2n_alert_behavior alert_behavior)
     424                 :          8 : {
     425 [ -  + ][ #  # ]:          8 :     POSIX_ENSURE_REF(config);
     426                 :            : 
     427                 :          8 :     switch (alert_behavior) {
     428         [ +  + ]:          1 :         case S2N_ALERT_FAIL_ON_WARNINGS:
     429         [ +  + ]:          8 :         case S2N_ALERT_IGNORE_WARNINGS:
     430                 :          8 :             config->alert_behavior = alert_behavior;
     431                 :          8 :             break;
     432         [ -  + ]:          0 :         default:
     433         [ #  # ]:          0 :             POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
     434                 :          8 :     }
     435                 :            : 
     436                 :          8 :     return 0;
     437                 :          8 : }
     438                 :            : 
     439                 :            : int s2n_config_set_verify_host_callback(struct s2n_config *config, s2n_verify_host_fn verify_host_fn, void *data)
     440                 :         29 : {
     441 [ -  + ][ #  # ]:         29 :     POSIX_ENSURE_REF(config);
     442                 :         29 :     config->verify_host_fn = verify_host_fn;
     443                 :         29 :     config->data_for_verify_host = data;
     444                 :         29 :     return 0;
     445                 :         29 : }
     446                 :            : 
     447                 :            : int s2n_config_set_check_stapled_ocsp_response(struct s2n_config *config, uint8_t check_ocsp)
     448                 :         20 : {
     449 [ -  + ][ #  # ]:         20 :     POSIX_ENSURE_REF(config);
     450 [ -  + ][ #  # ]:         20 :     S2N_ERROR_IF(check_ocsp && !s2n_x509_ocsp_stapling_supported(), S2N_ERR_OCSP_NOT_SUPPORTED);
                 [ #  # ]
     451                 :         20 :     config->check_ocsp = check_ocsp;
     452                 :         20 :     return 0;
     453                 :         20 : }
     454                 :            : 
     455                 :            : int s2n_config_disable_x509_time_verification(struct s2n_config *config)
     456                 :         11 : {
     457 [ +  - ][ +  + ]:         11 :     POSIX_ENSURE_REF(config);
     458                 :         10 :     config->disable_x509_time_validation = true;
     459                 :         10 :     return S2N_SUCCESS;
     460                 :         11 : }
     461                 :            : 
     462                 :            : int s2n_config_disable_x509_intent_verification(struct s2n_config *config)
     463                 :         49 : {
     464 [ +  + ][ +  - ]:         49 :     POSIX_ENSURE(config, S2N_ERR_INVALID_ARGUMENT);
     465                 :         48 :     config->disable_x509_intent_verification = true;
     466                 :         48 :     return S2N_SUCCESS;
     467                 :         49 : }
     468                 :            : 
     469                 :            : int s2n_config_allow_ip_in_cn(struct s2n_config *config)
     470                 :          3 : {
     471 [ +  - ][ +  + ]:          3 :     POSIX_ENSURE(config, S2N_ERR_INVALID_ARGUMENT);
     472                 :          2 :     config->allow_ip_in_cn = true;
     473                 :          2 :     return S2N_SUCCESS;
     474                 :          3 : }
     475                 :            : 
     476                 :            : int s2n_config_disable_x509_verification(struct s2n_config *config)
     477                 :        162 : {
     478 [ -  + ][ #  # ]:        162 :     POSIX_ENSURE_REF(config);
     479                 :        162 :     s2n_x509_trust_store_wipe(&config->trust_store);
     480                 :        162 :     config->disable_x509_validation = 1;
     481                 :        162 :     return 0;
     482                 :        162 : }
     483                 :            : 
     484                 :            : int s2n_config_set_max_cert_chain_depth(struct s2n_config *config, uint16_t max_depth)
     485                 :          0 : {
     486 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(config);
     487 [ #  # ][ #  # ]:          0 :     S2N_ERROR_IF(max_depth == 0, S2N_ERR_INVALID_ARGUMENT);
     488                 :            : 
     489                 :          0 :     config->max_verify_cert_chain_depth = max_depth;
     490                 :          0 :     config->max_verify_cert_chain_depth_set = 1;
     491                 :          0 :     return 0;
     492                 :          0 : }
     493                 :            : 
     494                 :            : int s2n_config_set_status_request_type(struct s2n_config *config, s2n_status_request_type type)
     495                 :         30 : {
     496 [ -  + ][ +  + ]:         30 :     S2N_ERROR_IF(type == S2N_STATUS_REQUEST_OCSP && !s2n_x509_ocsp_stapling_supported(), S2N_ERR_OCSP_NOT_SUPPORTED);
                 [ #  # ]
     497                 :            : 
     498 [ #  # ][ -  + ]:         30 :     POSIX_ENSURE_REF(config);
     499                 :         30 :     config->ocsp_status_requested_by_user = (type == S2N_STATUS_REQUEST_OCSP);
     500                 :            : 
     501                 :            :     /* Reset the ocsp_status_requested_by_s2n flag if OCSP status requests were disabled. */
     502         [ +  + ]:         30 :     if (type == S2N_STATUS_REQUEST_NONE) {
     503                 :          8 :         config->ocsp_status_requested_by_s2n = false;
     504                 :          8 :     }
     505                 :            : 
     506                 :         30 :     return 0;
     507                 :         30 : }
     508                 :            : 
     509                 :            : int s2n_config_wipe_trust_store(struct s2n_config *config)
     510                 :         28 : {
     511 [ #  # ][ -  + ]:         28 :     POSIX_ENSURE_REF(config);
     512                 :            : 
     513                 :         28 :     s2n_x509_trust_store_wipe(&config->trust_store);
     514                 :            : 
     515                 :         28 :     return S2N_SUCCESS;
     516                 :         28 : }
     517                 :            : 
     518                 :            : int s2n_config_add_pem_to_trust_store(struct s2n_config *config, const char *pem)
     519                 :         24 : {
     520 [ -  + ][ #  # ]:         24 :     POSIX_ENSURE_REF(config);
     521 [ #  # ][ -  + ]:         24 :     POSIX_ENSURE_REF(pem);
     522                 :            : 
     523         [ +  + ]:         24 :     POSIX_GUARD(s2n_x509_trust_store_add_pem(&config->trust_store, pem));
     524                 :            : 
     525                 :         23 :     return 0;
     526                 :         24 : }
     527                 :            : 
     528                 :            : int s2n_config_set_verification_ca_location(struct s2n_config *config, const char *ca_pem_filename, const char *ca_dir)
     529                 :        279 : {
     530 [ #  # ][ -  + ]:        279 :     POSIX_ENSURE_REF(config);
     531                 :        279 :     int err_code = s2n_x509_trust_store_from_ca_file(&config->trust_store, ca_pem_filename, ca_dir);
     532                 :            : 
     533         [ +  - ]:        279 :     if (!err_code) {
     534         [ +  - ]:        279 :         config->ocsp_status_requested_by_s2n = s2n_x509_ocsp_stapling_supported() ? S2N_STATUS_REQUEST_OCSP : S2N_STATUS_REQUEST_NONE;
     535                 :        279 :     }
     536                 :            : 
     537                 :        279 :     return err_code;
     538                 :        279 : }
     539                 :            : 
     540                 :            : static int s2n_config_add_cert_chain_and_key_impl(struct s2n_config *config, struct s2n_cert_chain_and_key *cert_key_pair)
     541                 :       1319 : {
     542 [ #  # ][ -  + ]:       1319 :     POSIX_ENSURE_REF(config->domain_name_to_cert_map);
     543 [ #  # ][ -  + ]:       1319 :     POSIX_ENSURE_REF(cert_key_pair);
     544                 :            : 
     545         [ +  + ]:       1319 :     POSIX_GUARD_RESULT(s2n_security_policy_validate_certificate_chain(config->security_policy, cert_key_pair));
     546                 :            : 
     547                 :       1318 :     s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pair);
     548                 :       1318 :     config->is_rsa_cert_configured |= (cert_type == S2N_PKEY_TYPE_RSA);
     549                 :            : 
     550                 :            :     /* Perform all fallible checks BEFORE inserting into the domain name map.
     551                 :            :      * If we insert into the map first and then fail, the caller's DEFER_CLEANUP
     552                 :            :      * will free cert_key_pair while the map still holds pointers to it,
     553                 :            :      * resulting in dangling pointers and a use-after-free during SNI lookup.
     554                 :            :      */
     555         [ +  - ]:       1318 :     if (!config->default_certs_are_explicit) {
     556 [ -  + ][ #  # ]:       1318 :         POSIX_ENSURE(cert_type >= 0, S2N_ERR_CERT_TYPE_UNSUPPORTED);
     557 [ -  + ][ #  # ]:       1318 :         POSIX_ENSURE(cert_type < S2N_CERT_TYPE_COUNT, S2N_ERR_CERT_TYPE_UNSUPPORTED);
     558         [ +  + ]:       1318 :         if (config->default_certs_by_type.certs[cert_type] != NULL) {
     559                 :            :             /* Because library-owned certificates are tracked and cleaned up via the
     560                 :            :              * default_certs_by_type mapping, library-owned chains MUST be set as the default
     561                 :            :              * to avoid a memory leak. If they're not the default, they're not freed.
     562                 :            :              */
     563 [ #  # ][ -  + ]:        109 :             POSIX_ENSURE(config->cert_ownership != S2N_LIB_OWNED,
     564                 :        109 :                     S2N_ERR_MULTIPLE_DEFAULT_CERTIFICATES_PER_AUTH_TYPE);
     565                 :        109 :         }
     566                 :       1318 :     }
     567                 :            : 
     568         [ -  + ]:       1318 :     POSIX_GUARD(s2n_config_build_domain_name_to_cert_map(config, cert_key_pair));
     569                 :            : 
     570         [ +  - ]:       1318 :     if (!config->default_certs_are_explicit) {
     571         [ +  + ]:       1318 :         if (config->default_certs_by_type.certs[cert_type] == NULL) {
     572                 :       1209 :             config->default_certs_by_type.certs[cert_type] = cert_key_pair;
     573                 :       1209 :         }
     574                 :       1318 :     }
     575                 :            : 
     576         [ +  + ]:       1318 :     if (s2n_pkey_check_key_exists(cert_key_pair->private_key) != S2N_SUCCESS) {
     577                 :          5 :         config->no_signing_key = true;
     578                 :          5 :     }
     579                 :            : 
     580                 :       1318 :     return S2N_SUCCESS;
     581                 :       1318 : }
     582                 :            : 
     583                 :            : S2N_RESULT s2n_config_validate_loaded_certificates(const struct s2n_config *config,
     584                 :            :         const struct s2n_security_policy *security_policy)
     585                 :       6577 : {
     586 [ #  # ][ -  + ]:       6577 :     RESULT_ENSURE_REF(config);
     587 [ -  + ][ #  # ]:       6577 :     RESULT_ENSURE_REF(security_policy);
     588                 :            : 
     589         [ +  + ]:       6577 :     if (security_policy->certificate_key_preferences == NULL
     590         [ +  + ]:       6577 :             && security_policy->certificate_signature_preferences == NULL) {
     591                 :       4295 :         return S2N_RESULT_OK;
     592                 :       4295 :     }
     593                 :            : 
     594                 :            :     /* Duplicates a check in s2n_security_policy_validate_certificate_chain.
     595                 :            :      * If a large number of certificates are configured, even iterating
     596                 :            :      * over the chains to call s2n_security_policy_validate_certificate_chain
     597                 :            :      * could be prohibitively expensive.
     598                 :            :      */
     599         [ +  + ]:       2282 :     if (!security_policy->certificate_preferences_apply_locally) {
     600                 :       2258 :         return S2N_RESULT_OK;
     601                 :       2258 :     }
     602                 :            : 
     603                 :            :     /* validate the default certs */
     604         [ +  + ]:        106 :     for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
     605                 :         86 :         struct s2n_cert_chain_and_key *cert = config->default_certs_by_type.certs[i];
     606         [ +  + ]:         86 :         if (cert == NULL) {
     607                 :         72 :             continue;
     608                 :         72 :         }
     609         [ +  + ]:         14 :         RESULT_GUARD(s2n_security_policy_validate_certificate_chain(security_policy, cert));
     610                 :         14 :     }
     611                 :            : 
     612                 :            :     /* validate the certs in the domain map */
     613         [ -  + ]:         20 :     if (config->domain_name_to_cert_map == NULL) {
     614                 :          0 :         return S2N_RESULT_OK;
     615                 :          0 :     }
     616                 :            : 
     617                 :         20 :     struct s2n_map_iterator iter = { 0 };
     618         [ +  + ]:         20 :     RESULT_GUARD(s2n_map_iterator_init(&iter, config->domain_name_to_cert_map));
     619                 :            : 
     620         [ +  + ]:         28 :     while (s2n_map_iterator_has_next(&iter)) {
     621                 :         10 :         struct s2n_blob value = { 0 };
     622         [ -  + ]:         10 :         RESULT_GUARD(s2n_map_iterator_next(&iter, &value));
     623                 :            : 
     624                 :         10 :         struct certs_by_type *domain_certs = (void *) value.data;
     625         [ +  + ]:         47 :         for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
     626                 :         38 :             struct s2n_cert_chain_and_key *cert = domain_certs->certs[i];
     627         [ +  + ]:         38 :             if (cert == NULL) {
     628                 :         28 :                 continue;
     629                 :         28 :             }
     630         [ +  + ]:         10 :             RESULT_GUARD(s2n_security_policy_validate_certificate_chain(security_policy, cert));
     631                 :         10 :         }
     632                 :         10 :     }
     633                 :         18 :     return S2N_RESULT_OK;
     634                 :         19 : }
     635                 :            : 
     636                 :            : /* Deprecated. Superseded by s2n_config_add_cert_chain_and_key_to_store */
     637                 :            : int s2n_config_add_cert_chain_and_key(struct s2n_config *config, const char *cert_chain_pem, const char *private_key_pem)
     638                 :         16 : {
     639 [ #  # ][ -  + ]:         16 :     POSIX_ENSURE_REF(config);
     640                 :            :     /* Only allow this deprecated API to be called once. Library-owned certs are
     641                 :            :      * tracked via default_certs_by_type, so adding a second cert that can't be
     642                 :            :      * stored there would leak or, worse, leave dangling pointers in the domain
     643                 :            :      * name map when DEFER_CLEANUP fires on failure.
     644                 :            :      */
     645 [ +  + ][ +  - ]:         16 :     POSIX_ENSURE(config->cert_ownership == S2N_NOT_OWNED, S2N_ERR_CERT_OWNERSHIP);
     646                 :            : 
     647                 :         13 :     DEFER_CLEANUP(struct s2n_cert_chain_and_key *chain_and_key = s2n_cert_chain_and_key_new(),
     648                 :         13 :             s2n_cert_chain_and_key_ptr_free);
     649 [ -  + ][ #  # ]:         13 :     POSIX_ENSURE_REF(chain_and_key);
     650         [ -  + ]:         13 :     POSIX_GUARD(s2n_cert_chain_and_key_load_pem(chain_and_key, cert_chain_pem, private_key_pem));
     651         [ -  + ]:         13 :     POSIX_GUARD(s2n_config_add_cert_chain_and_key_impl(config, chain_and_key));
     652                 :         13 :     config->cert_ownership = S2N_LIB_OWNED;
     653                 :            : 
     654                 :         13 :     ZERO_TO_DISABLE_DEFER_CLEANUP(chain_and_key);
     655                 :         13 :     return S2N_SUCCESS;
     656                 :         13 : }
     657                 :            : 
     658                 :            : /* Only used in the Rust bindings. Superseded by s2n_config_add_cert_chain_and_key_to_store */
     659                 :            : int s2n_config_add_cert_chain(struct s2n_config *config,
     660                 :            :         uint8_t *cert_chain_pem, uint32_t cert_chain_pem_size)
     661                 :          1 : {
     662 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(config);
     663                 :            :     /* Only allow this deprecated API to be called once. */
     664 [ #  # ][ -  + ]:          1 :     POSIX_ENSURE(config->cert_ownership == S2N_NOT_OWNED, S2N_ERR_CERT_OWNERSHIP);
     665                 :            : 
     666                 :          1 :     DEFER_CLEANUP(struct s2n_cert_chain_and_key *chain_and_key = s2n_cert_chain_and_key_new(),
     667                 :          1 :             s2n_cert_chain_and_key_ptr_free);
     668 [ #  # ][ -  + ]:          1 :     POSIX_ENSURE_REF(chain_and_key);
     669         [ -  + ]:          1 :     POSIX_GUARD(s2n_cert_chain_and_key_load_public_pem_bytes(chain_and_key,
     670                 :          1 :             cert_chain_pem, cert_chain_pem_size));
     671         [ -  + ]:          1 :     POSIX_GUARD(s2n_config_add_cert_chain_and_key_impl(config, chain_and_key));
     672                 :          1 :     config->cert_ownership = S2N_LIB_OWNED;
     673                 :            : 
     674                 :          1 :     ZERO_TO_DISABLE_DEFER_CLEANUP(chain_and_key);
     675                 :          1 :     return S2N_SUCCESS;
     676                 :          1 : }
     677                 :            : 
     678                 :            : int s2n_config_add_cert_chain_and_key_to_store(struct s2n_config *config, struct s2n_cert_chain_and_key *cert_key_pair)
     679                 :       1306 : {
     680 [ #  # ][ -  + ]:       1306 :     POSIX_ENSURE_REF(config);
     681 [ +  + ][ +  - ]:       1306 :     POSIX_ENSURE(config->cert_ownership != S2N_LIB_OWNED, S2N_ERR_CERT_OWNERSHIP);
     682                 :            : 
     683 [ -  + ][ #  # ]:       1305 :     POSIX_ENSURE_REF(cert_key_pair);
     684         [ +  + ]:       1305 :     POSIX_GUARD(s2n_config_add_cert_chain_and_key_impl(config, cert_key_pair));
     685                 :       1304 :     config->cert_ownership = S2N_APP_OWNED;
     686                 :            : 
     687                 :       1304 :     return S2N_SUCCESS;
     688                 :       1305 : }
     689                 :            : 
     690                 :            : int s2n_config_set_async_offload_callback(struct s2n_config *config, uint32_t allow_list, s2n_async_offload_cb fn, void *ctx)
     691                 :         14 : {
     692 [ +  - ][ +  + ]:         14 :     POSIX_ENSURE_REF(config);
     693 [ +  - ][ +  + ]:         13 :     POSIX_ENSURE_REF(fn);
     694 [ -  + ][ #  # ]:         12 :     POSIX_ENSURE(allow_list != 0, S2N_ERR_INVALID_ARGUMENT);
     695                 :            : 
     696                 :         12 :     config->async_offload_allow_list = allow_list;
     697                 :         12 :     config->async_offload_cb = fn;
     698                 :         12 :     config->async_offload_ctx = ctx;
     699                 :            : 
     700                 :         12 :     return S2N_SUCCESS;
     701                 :         12 : }
     702                 :            : 
     703                 :            : int s2n_config_set_async_pkey_callback(struct s2n_config *config, s2n_async_pkey_fn fn)
     704                 :         34 : {
     705 [ #  # ][ -  + ]:         34 :     POSIX_ENSURE_REF(config);
     706                 :            : 
     707                 :         34 :     config->async_pkey_cb = fn;
     708                 :            : 
     709                 :         34 :     return S2N_SUCCESS;
     710                 :         34 : }
     711                 :            : 
     712                 :            : static int s2n_config_clear_default_certificates(struct s2n_config *config)
     713                 :          5 : {
     714 [ #  # ][ -  + ]:          5 :     POSIX_ENSURE_REF(config);
     715                 :            : 
     716                 :            :     /* Clearing library-owned chains would lead to a memory leak.
     717                 :            :      * See s2n_config_free_cert_chain_and_key.
     718                 :            :      */
     719 [ -  + ][ #  # ]:          5 :     POSIX_ENSURE(config->cert_ownership != S2N_LIB_OWNED, S2N_ERR_CERT_OWNERSHIP);
     720                 :            : 
     721         [ +  + ]:         25 :     for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
     722                 :         20 :         config->default_certs_by_type.certs[i] = NULL;
     723                 :         20 :     }
     724                 :          5 :     config->cert_ownership = S2N_NOT_OWNED;
     725                 :          5 :     return 0;
     726                 :          5 : }
     727                 :            : 
     728                 :            : int s2n_config_set_cert_chain_and_key_defaults(struct s2n_config *config,
     729                 :            :         struct s2n_cert_chain_and_key **cert_key_pairs,
     730                 :            :         uint32_t num_cert_key_pairs)
     731                 :          9 : {
     732 [ #  # ][ -  + ]:          9 :     POSIX_ENSURE_REF(config);
     733 [ +  + ][ +  - ]:          9 :     POSIX_ENSURE_REF(cert_key_pairs);
     734 [ +  + ][ -  + ]:          8 :     S2N_ERROR_IF(num_cert_key_pairs < 1 || num_cert_key_pairs > S2N_CERT_TYPE_COUNT,
                 [ +  - ]
     735                 :          8 :             S2N_ERR_NUM_DEFAULT_CERTIFICATES);
     736                 :            : 
     737                 :            :     /* This method will set application-owned chains, so we must not already be using
     738                 :            :      * any library owned chains. See s2n_config_free_cert_chain_and_key.
     739                 :            :      */
     740 [ +  + ][ +  - ]:          7 :     POSIX_ENSURE(config->cert_ownership != S2N_LIB_OWNED, S2N_ERR_CERT_OWNERSHIP);
     741                 :            : 
     742                 :            :     /* Validate certs being set before clearing auto-chosen defaults or previously set defaults */
     743                 :          6 :     struct certs_by_type new_defaults = { { 0 } };
     744         [ +  + ]:         13 :     for (size_t i = 0; i < num_cert_key_pairs; i++) {
     745 [ -  + ][ #  # ]:          8 :         POSIX_ENSURE_REF(cert_key_pairs[i]);
     746                 :          8 :         s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pairs[i]);
     747 [ +  + ][ +  - ]:          8 :         S2N_ERROR_IF(new_defaults.certs[cert_type] != NULL, S2N_ERR_MULTIPLE_DEFAULT_CERTIFICATES_PER_AUTH_TYPE);
     748                 :          7 :         new_defaults.certs[cert_type] = cert_key_pairs[i];
     749                 :          7 :     }
     750                 :            : 
     751         [ -  + ]:          5 :     POSIX_GUARD(s2n_config_clear_default_certificates(config));
     752         [ +  + ]:         11 :     for (size_t i = 0; i < num_cert_key_pairs; i++) {
     753                 :          6 :         s2n_pkey_type cert_type = s2n_cert_chain_and_key_get_pkey_type(cert_key_pairs[i]);
     754                 :          6 :         config->is_rsa_cert_configured |= (cert_type == S2N_PKEY_TYPE_RSA);
     755                 :          6 :         config->default_certs_by_type.certs[cert_type] = cert_key_pairs[i];
     756                 :          6 :     }
     757                 :            : 
     758                 :          5 :     config->default_certs_are_explicit = 1;
     759                 :          5 :     config->cert_ownership = S2N_APP_OWNED;
     760                 :          5 :     return 0;
     761                 :          5 : }
     762                 :            : 
     763                 :            : int s2n_config_add_dhparams(struct s2n_config *config, const char *dhparams_pem)
     764                 :         81 : {
     765 [ -  + ][ #  # ]:         81 :     POSIX_ENSURE_REF(config);
     766                 :         81 :     DEFER_CLEANUP(struct s2n_stuffer dhparams_in_stuffer = { 0 }, s2n_stuffer_free);
     767                 :         81 :     DEFER_CLEANUP(struct s2n_stuffer dhparams_out_stuffer = { 0 }, s2n_stuffer_free);
     768                 :         81 :     struct s2n_blob dhparams_blob = { 0 };
     769                 :         81 :     struct s2n_blob mem = { 0 };
     770                 :            : 
     771                 :            :     /* Allocate the memory for the chain and key struct */
     772         [ -  + ]:         81 :     POSIX_GUARD(s2n_alloc(&mem, sizeof(struct s2n_dh_params)));
     773                 :         81 :     config->dhparams = (struct s2n_dh_params *) (void *) mem.data;
     774                 :            : 
     775         [ -  + ]:         81 :     if (s2n_stuffer_alloc_ro_from_string(&dhparams_in_stuffer, dhparams_pem) != S2N_SUCCESS) {
     776                 :          0 :         s2n_free(&mem);
     777                 :          0 :         S2N_ERROR_PRESERVE_ERRNO();
     778                 :          0 :     }
     779         [ -  + ]:         81 :     if (s2n_stuffer_growable_alloc(&dhparams_out_stuffer, strlen(dhparams_pem)) != S2N_SUCCESS) {
     780                 :          0 :         s2n_free(&mem);
     781                 :          0 :         S2N_ERROR_PRESERVE_ERRNO();
     782                 :          0 :     }
     783                 :            : 
     784                 :            :     /* Convert pem to asn1 and asn1 to the private key */
     785         [ -  + ]:         81 :     POSIX_GUARD(s2n_stuffer_dhparams_from_pem(&dhparams_in_stuffer, &dhparams_out_stuffer));
     786                 :            : 
     787                 :         81 :     dhparams_blob.size = s2n_stuffer_data_available(&dhparams_out_stuffer);
     788                 :         81 :     dhparams_blob.data = s2n_stuffer_raw_read(&dhparams_out_stuffer, dhparams_blob.size);
     789 [ #  # ][ -  + ]:         81 :     POSIX_ENSURE_REF(dhparams_blob.data);
     790                 :            : 
     791         [ -  + ]:         81 :     POSIX_GUARD(s2n_pkcs3_to_dh_params(config->dhparams, &dhparams_blob));
     792                 :            : 
     793                 :         81 :     return 0;
     794                 :         81 : }
     795                 :            : 
     796                 :            : int s2n_config_set_wall_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx)
     797                 :         65 : {
     798 [ #  # ][ -  + ]:         65 :     POSIX_ENSURE_REF(config);
     799 [ #  # ][ -  + ]:         65 :     POSIX_ENSURE_REF(clock_fn);
     800                 :            : 
     801                 :         65 :     config->wall_clock = clock_fn;
     802                 :         65 :     config->sys_clock_ctx = ctx;
     803                 :            : 
     804                 :         65 :     return 0;
     805                 :         65 : }
     806                 :            : 
     807                 :            : int s2n_config_set_monotonic_clock(struct s2n_config *config, s2n_clock_time_nanoseconds clock_fn, void *ctx)
     808                 :         11 : {
     809 [ #  # ][ -  + ]:         11 :     POSIX_ENSURE_REF(config);
     810 [ #  # ][ -  + ]:         11 :     POSIX_ENSURE_REF(clock_fn);
     811                 :            : 
     812                 :         11 :     config->monotonic_clock = clock_fn;
     813                 :         11 :     config->monotonic_clock_ctx = ctx;
     814                 :            : 
     815                 :         11 :     return 0;
     816                 :         11 : }
     817                 :            : 
     818                 :            : int s2n_config_set_cache_store_callback(struct s2n_config *config, s2n_cache_store_callback cache_store_callback, void *data)
     819                 :          2 : {
     820 [ #  # ][ -  + ]:          2 :     POSIX_ENSURE_REF(config);
     821 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(cache_store_callback);
     822                 :            : 
     823                 :          2 :     config->cache_store = cache_store_callback;
     824                 :          2 :     config->cache_store_data = data;
     825                 :            : 
     826                 :          2 :     return 0;
     827                 :          2 : }
     828                 :            : 
     829                 :            : int s2n_config_set_cache_retrieve_callback(struct s2n_config *config, s2n_cache_retrieve_callback cache_retrieve_callback, void *data)
     830                 :          2 : {
     831 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(config);
     832 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(cache_retrieve_callback);
     833                 :            : 
     834                 :          2 :     config->cache_retrieve = cache_retrieve_callback;
     835                 :          2 :     config->cache_retrieve_data = data;
     836                 :            : 
     837                 :          2 :     return 0;
     838                 :          2 : }
     839                 :            : 
     840                 :            : int s2n_config_set_cache_delete_callback(struct s2n_config *config, s2n_cache_delete_callback cache_delete_callback, void *data)
     841                 :          2 : {
     842 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(config);
     843 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(cache_delete_callback);
     844                 :            : 
     845                 :          2 :     config->cache_delete = cache_delete_callback;
     846                 :          2 :     config->cache_delete_data = data;
     847                 :            : 
     848                 :          2 :     return 0;
     849                 :          2 : }
     850                 :            : 
     851                 :            : int s2n_config_set_extension_data(struct s2n_config *config, s2n_tls_extension_type type, const uint8_t *data, uint32_t length)
     852                 :          8 : {
     853 [ #  # ][ -  + ]:          8 :     POSIX_ENSURE_REF(config);
     854                 :            : 
     855         [ -  + ]:          8 :     if (s2n_config_get_num_default_certs(config) == 0) {
     856         [ #  # ]:          0 :         POSIX_BAIL(S2N_ERR_UPDATING_EXTENSION);
     857                 :          0 :     }
     858                 :          8 :     struct s2n_cert_chain_and_key *config_chain_and_key = s2n_config_get_single_default_cert(config);
     859 [ #  # ][ -  + ]:          8 :     POSIX_ENSURE_REF(config_chain_and_key);
     860 [ +  + ][ +  - ]:          8 :     POSIX_ENSURE(config->cert_ownership == S2N_LIB_OWNED, S2N_ERR_CERT_OWNERSHIP);
     861                 :            : 
     862                 :          7 :     switch (type) {
     863         [ +  + ]:          2 :         case S2N_EXTENSION_CERTIFICATE_TRANSPARENCY:
     864         [ -  + ]:          2 :             POSIX_GUARD(s2n_cert_chain_and_key_set_sct_list(config_chain_and_key, data, length));
     865                 :          2 :             break;
     866         [ +  + ]:          5 :         case S2N_EXTENSION_OCSP_STAPLING:
     867         [ -  + ]:          5 :             POSIX_GUARD(s2n_cert_chain_and_key_set_ocsp_data(config_chain_and_key, data, length));
     868                 :          5 :             break;
     869         [ -  + ]:          5 :         default:
     870         [ #  # ]:          0 :             POSIX_BAIL(S2N_ERR_UNRECOGNIZED_EXTENSION);
     871                 :          7 :     }
     872                 :            : 
     873                 :          7 :     return 0;
     874                 :          7 : }
     875                 :            : 
     876                 :            : int s2n_config_add_custom_x509_extension(struct s2n_config *config, uint8_t *extension_oid, uint32_t extension_oid_len)
     877                 :          3 : {
     878 [ +  + ][ +  - ]:          3 :     POSIX_ENSURE(config, S2N_ERR_INVALID_ARGUMENT);
     879 [ +  + ][ +  - ]:          2 :     POSIX_ENSURE(extension_oid, S2N_ERR_INVALID_ARGUMENT);
     880                 :            : 
     881 [ +  - ][ +  - ]:          1 :     POSIX_ENSURE(s2n_libcrypto_supports_custom_oid(), S2N_ERR_API_UNSUPPORTED_BY_LIBCRYPTO);
     882                 :            : 
     883         [ #  # ]:          0 :     if (config->custom_x509_extension_oids == NULL) {
     884                 :          0 :         config->custom_x509_extension_oids = sk_ASN1_OBJECT_new_null();
     885                 :          0 :     }
     886 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(config->custom_x509_extension_oids);
     887                 :            : 
     888                 :          0 :     DEFER_CLEANUP(struct s2n_blob oid_buffer = { 0 }, s2n_free);
     889         [ #  # ]:          0 :     POSIX_GUARD(s2n_alloc(&oid_buffer, extension_oid_len + 1));
     890                 :            : 
     891         [ #  # ]:          0 :     POSIX_GUARD(s2n_blob_zero(&oid_buffer));
     892 [ #  # ][ #  # ]:          0 :     POSIX_CHECKED_MEMCPY(oid_buffer.data, extension_oid, extension_oid_len);
                 [ #  # ]
     893                 :          0 :     oid_buffer.data[extension_oid_len] = '\0';
     894                 :            : 
     895                 :          0 :     const char *oid_string = (const char *) oid_buffer.data;
     896 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(oid_string);
     897                 :            : 
     898                 :          0 :     ASN1_OBJECT *critical_oid = OBJ_txt2obj(oid_string, 1);
     899 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE_REF(critical_oid);
     900 [ #  # ][ #  # ]:          0 :     POSIX_ENSURE(sk_ASN1_OBJECT_push(config->custom_x509_extension_oids, critical_oid) > 0, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
     901                 :            : 
     902                 :          0 :     return S2N_SUCCESS;
     903                 :          0 : }
     904                 :            : 
     905                 :            : int s2n_config_set_cert_request_callback(struct s2n_config *config, s2n_cert_request_callback cert_request_cb, void *ctx)
     906                 :          3 : {
     907 [ +  - ][ +  + ]:          3 :     POSIX_ENSURE(config, S2N_ERR_INVALID_ARGUMENT);
     908                 :            : 
     909                 :          2 :     config->cert_request_cb = cert_request_cb;
     910                 :          2 :     config->cert_request_cb_ctx = ctx;
     911                 :            : 
     912                 :          2 :     return S2N_SUCCESS;
     913                 :          3 : }
     914                 :            : 
     915                 :            : int s2n_config_set_client_hello_cb(struct s2n_config *config, s2n_client_hello_fn client_hello_cb, void *ctx)
     916                 :        124 : {
     917 [ -  + ][ #  # ]:        124 :     POSIX_ENSURE_REF(config);
     918                 :            : 
     919                 :        124 :     config->client_hello_cb = client_hello_cb;
     920                 :        124 :     config->client_hello_cb_ctx = ctx;
     921                 :        124 :     return 0;
     922                 :        124 : }
     923                 :            : 
     924                 :            : int s2n_config_set_client_hello_cb_mode(struct s2n_config *config, s2n_client_hello_cb_mode cb_mode)
     925                 :         72 : {
     926 [ -  + ][ #  # ]:         72 :     POSIX_ENSURE_REF(config);
     927 [ #  # ][ +  + ]:         72 :     POSIX_ENSURE(cb_mode == S2N_CLIENT_HELLO_CB_BLOCKING || cb_mode == S2N_CLIENT_HELLO_CB_NONBLOCKING, S2N_ERR_INVALID_STATE);
                 [ +  - ]
     928                 :            : 
     929                 :         72 :     config->client_hello_cb_mode = cb_mode;
     930                 :         72 :     return S2N_SUCCESS;
     931                 :         72 : }
     932                 :            : 
     933                 :            : int s2n_config_send_max_fragment_length(struct s2n_config *config, s2n_max_frag_len mfl_code)
     934                 :        256 : {
     935 [ -  + ][ #  # ]:        256 :     POSIX_ENSURE_REF(config);
     936                 :            : 
     937 [ +  + ][ +  - ]:        256 :     S2N_ERROR_IF(mfl_code > S2N_TLS_MAX_FRAG_LEN_4096, S2N_ERR_INVALID_MAX_FRAG_LEN);
     938                 :            : 
     939                 :        255 :     config->mfl_code = mfl_code;
     940                 :            : 
     941                 :        255 :     return 0;
     942                 :        256 : }
     943                 :            : 
     944                 :            : int s2n_config_accept_max_fragment_length(struct s2n_config *config)
     945                 :         11 : {
     946 [ -  + ][ #  # ]:         11 :     POSIX_ENSURE_REF(config);
     947                 :            : 
     948                 :         11 :     config->accept_mfl = 1;
     949                 :            : 
     950                 :         11 :     return 0;
     951                 :         11 : }
     952                 :            : 
     953                 :            : int s2n_config_set_session_state_lifetime(struct s2n_config *config,
     954                 :            :         uint64_t lifetime_in_secs)
     955                 :         16 : {
     956 [ -  + ][ #  # ]:         16 :     POSIX_ENSURE_REF(config);
     957                 :            : 
     958                 :         16 :     config->session_state_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS);
     959                 :         16 :     return 0;
     960                 :         16 : }
     961                 :            : 
     962                 :            : int s2n_config_set_session_tickets_onoff(struct s2n_config *config, uint8_t enabled)
     963                 :        157 : {
     964 [ +  + ][ +  - ]:        157 :     POSIX_ENSURE_REF(config);
     965                 :            : 
     966         [ +  + ]:        155 :     if (config->use_tickets == enabled) {
     967                 :         17 :         return 0;
     968                 :         17 :     }
     969                 :            : 
     970                 :        138 :     config->use_tickets = enabled;
     971                 :            : 
     972         [ +  + ]:        138 :     if (config->initial_tickets_to_send == 0) {
     973                 :            :         /* Normally initial_tickets_to_send is set via s2n_config_set_initial_ticket_count.
     974                 :            :          * However, s2n_config_set_initial_ticket_count calls this method.
     975                 :            :          * So we set initial_tickets_to_send directly to avoid infinite recursion. */
     976                 :        130 :         config->initial_tickets_to_send = 1;
     977                 :        130 :     }
     978                 :            : 
     979                 :            :     /* session ticket || session id is enabled */
     980         [ +  + ]:        138 :     if (enabled) {
     981         [ -  + ]:        134 :         POSIX_GUARD(s2n_config_init_session_ticket_keys(config));
     982         [ +  - ]:        134 :     } else if (!config->use_session_cache) {
     983         [ -  + ]:          4 :         POSIX_GUARD(s2n_config_free_session_ticket_keys(config));
     984                 :          4 :     }
     985                 :            : 
     986                 :        138 :     return 0;
     987                 :        138 : }
     988                 :            : 
     989                 :            : int s2n_config_set_session_cache_onoff(struct s2n_config *config, uint8_t enabled)
     990                 :          3 : {
     991 [ -  + ][ #  # ]:          3 :     POSIX_ENSURE_REF(config);
     992 [ +  - ][ +  + ]:          3 :     if (enabled && config->cache_store && config->cache_retrieve && config->cache_delete) {
         [ +  - ][ +  - ]
     993         [ -  + ]:          2 :         POSIX_GUARD(s2n_config_init_session_ticket_keys(config));
     994                 :          2 :         config->use_session_cache = 1;
     995                 :          2 :     } else {
     996         [ -  + ]:          1 :         if (!config->use_tickets) {
     997         [ #  # ]:          0 :             POSIX_GUARD(s2n_config_free_session_ticket_keys(config));
     998                 :          0 :         }
     999                 :          1 :         config->use_session_cache = 0;
    1000                 :          1 :     }
    1001                 :          3 :     return 0;
    1002                 :          3 : }
    1003                 :            : 
    1004                 :            : int s2n_config_set_ticket_encrypt_decrypt_key_lifetime(struct s2n_config *config,
    1005                 :            :         uint64_t lifetime_in_secs)
    1006                 :          1 : {
    1007 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(config);
    1008                 :            : 
    1009                 :          1 :     config->encrypt_decrypt_key_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS);
    1010                 :          1 :     return 0;
    1011                 :          1 : }
    1012                 :            : 
    1013                 :            : int s2n_config_set_ticket_decrypt_key_lifetime(struct s2n_config *config,
    1014                 :            :         uint64_t lifetime_in_secs)
    1015                 :          1 : {
    1016 [ #  # ][ -  + ]:          1 :     POSIX_ENSURE_REF(config);
    1017                 :            : 
    1018                 :          1 :     config->decrypt_key_lifetime_in_nanos = (lifetime_in_secs * ONE_SEC_IN_NANOS);
    1019                 :          1 :     return 0;
    1020                 :          1 : }
    1021                 :            : 
    1022                 :            : int s2n_config_add_ticket_crypto_key(struct s2n_config *config,
    1023                 :            :         const uint8_t *name, uint32_t name_len,
    1024                 :            :         uint8_t *key, uint32_t key_len,
    1025                 :            :         uint64_t intro_time_in_seconds_from_epoch)
    1026                 :        140 : {
    1027 [ -  + ][ #  # ]:        140 :     POSIX_ENSURE_REF(config);
    1028 [ #  # ][ -  + ]:        140 :     POSIX_ENSURE_REF(name);
    1029 [ -  + ][ #  # ]:        140 :     POSIX_ENSURE_REF(key);
    1030                 :            : 
    1031                 :            :     /* both session ticket and session cache encryption/decryption can use the same key mechanism */
    1032 [ +  + ][ -  + ]:        140 :     if (!config->use_tickets && !config->use_session_cache) {
    1033                 :          0 :         return 0;
    1034                 :          0 :     }
    1035                 :            : 
    1036         [ -  + ]:        140 :     POSIX_GUARD(s2n_config_wipe_expired_ticket_crypto_keys(config, -1));
    1037                 :            : 
    1038 [ +  + ][ +  - ]:        140 :     POSIX_ENSURE(key_len != 0, S2N_ERR_INVALID_TICKET_KEY_LENGTH);
    1039                 :            : 
    1040                 :        139 :     uint32_t ticket_keys_len = 0;
    1041         [ -  + ]:        139 :     POSIX_GUARD_RESULT(s2n_array_num_elements(config->ticket_keys, &ticket_keys_len));
    1042 [ +  + ][ +  - ]:        139 :     POSIX_ENSURE(ticket_keys_len < S2N_MAX_TICKET_KEYS, S2N_ERR_TICKET_KEY_LIMIT);
    1043                 :            : 
    1044 [ +  - ][ +  + ]:        138 :     POSIX_ENSURE(name_len != 0, S2N_ERR_INVALID_TICKET_KEY_NAME_OR_NAME_LENGTH);
    1045 [ +  - ][ +  + ]:        137 :     POSIX_ENSURE(name_len <= S2N_TICKET_KEY_NAME_LEN, S2N_ERR_INVALID_TICKET_KEY_NAME_OR_NAME_LENGTH);
    1046                 :            : 
    1047                 :            :     /* Copy the name into a zero-padded array. */
    1048                 :            :     /* This ensures that all ticket names are equal in length, as the serialized name is fixed length */
    1049                 :        136 :     uint8_t name_data[S2N_TICKET_KEY_NAME_LEN] = { 0 };
    1050 [ -  + ][ #  # ]:        136 :     POSIX_CHECKED_MEMCPY(name_data, name, name_len);
                 [ +  - ]
    1051                 :            : 
    1052                 :        136 :     uint8_t output_pad[S2N_AES256_KEY_LEN + S2N_TICKET_AAD_IMPLICIT_LEN] = { 0 };
    1053                 :        136 :     struct s2n_blob out_key = { 0 };
    1054         [ -  + ]:        136 :     POSIX_GUARD(s2n_blob_init(&out_key, output_pad, s2n_array_len(output_pad)));
    1055                 :        136 :     struct s2n_blob in_key = { 0 };
    1056         [ -  + ]:        136 :     POSIX_GUARD(s2n_blob_init(&in_key, key, key_len));
    1057                 :        136 :     struct s2n_blob salt = { 0 };
    1058         [ -  + ]:        136 :     POSIX_GUARD(s2n_blob_init(&salt, NULL, 0));
    1059                 :        136 :     struct s2n_blob info = { 0 };
    1060         [ -  + ]:        136 :     POSIX_GUARD(s2n_blob_init(&info, NULL, 0));
    1061                 :            : 
    1062                 :        136 :     struct s2n_ticket_key *session_ticket_key = { 0 };
    1063                 :        136 :     DEFER_CLEANUP(struct s2n_blob allocator = { 0 }, s2n_free);
    1064         [ -  + ]:        136 :     POSIX_GUARD(s2n_alloc(&allocator, sizeof(struct s2n_ticket_key)));
    1065                 :        136 :     session_ticket_key = (struct s2n_ticket_key *) (void *) allocator.data;
    1066                 :            : 
    1067                 :        136 :     DEFER_CLEANUP(struct s2n_hmac_state hmac = { 0 }, s2n_hmac_free);
    1068                 :            : 
    1069         [ -  + ]:        136 :     POSIX_GUARD(s2n_hmac_new(&hmac));
    1070         [ -  + ]:        136 :     POSIX_GUARD(s2n_hkdf(&hmac, S2N_HMAC_SHA256, &salt, &in_key, &info, &out_key));
    1071                 :            : 
    1072 [ #  # ][ -  + ]:        136 :     POSIX_CHECKED_MEMCPY(session_ticket_key->key_name, name_data, s2n_array_len(name_data));
                 [ +  - ]
    1073 [ #  # ][ -  + ]:        136 :     POSIX_CHECKED_MEMCPY(session_ticket_key->aes_key, out_key.data, S2N_AES256_KEY_LEN);
                 [ +  - ]
    1074                 :        136 :     out_key.data = output_pad + S2N_AES256_KEY_LEN;
    1075 [ -  + ][ #  # ]:        136 :     POSIX_CHECKED_MEMCPY(session_ticket_key->implicit_aad, out_key.data, S2N_TICKET_AAD_IMPLICIT_LEN);
                 [ +  - ]
    1076                 :            : 
    1077         [ +  + ]:        136 :     if (intro_time_in_seconds_from_epoch == 0) {
    1078                 :         86 :         uint64_t now = 0;
    1079         [ -  + ]:         86 :         POSIX_GUARD_RESULT(s2n_config_wall_clock(config, &now));
    1080                 :         86 :         session_ticket_key->intro_timestamp = now;
    1081                 :         86 :     } else {
    1082                 :         50 :         session_ticket_key->intro_timestamp = (intro_time_in_seconds_from_epoch * ONE_SEC_IN_NANOS);
    1083                 :         50 :     }
    1084                 :            : 
    1085         [ +  + ]:        136 :     POSIX_GUARD(s2n_config_store_ticket_key(config, session_ticket_key));
    1086                 :            : 
    1087                 :        132 :     return 0;
    1088                 :        136 : }
    1089                 :            : 
    1090                 :            : int s2n_config_require_ticket_forward_secrecy(struct s2n_config *config, bool enabled)
    1091                 :          4 : {
    1092 [ #  # ][ -  + ]:          4 :     POSIX_ENSURE_REF(config);
    1093                 :            : 
    1094                 :          4 :     config->ticket_forward_secrecy = enabled;
    1095                 :            : 
    1096                 :          4 :     return S2N_SUCCESS;
    1097                 :          4 : }
    1098                 :            : 
    1099                 :            : int s2n_config_set_cert_tiebreak_callback(struct s2n_config *config, s2n_cert_tiebreak_callback cert_tiebreak_cb)
    1100                 :          1 : {
    1101 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(config);
    1102                 :          1 :     config->cert_tiebreak_cb = cert_tiebreak_cb;
    1103                 :          1 :     return 0;
    1104                 :          1 : }
    1105                 :            : 
    1106                 :            : struct s2n_cert_chain_and_key *s2n_config_get_single_default_cert(struct s2n_config *config)
    1107                 :        198 : {
    1108 [ -  + ][ #  # ]:        198 :     PTR_ENSURE_REF(config);
    1109                 :        198 :     struct s2n_cert_chain_and_key *cert = NULL;
    1110                 :            : 
    1111         [ +  + ]:        990 :     for (int i = S2N_CERT_TYPE_COUNT - 1; i >= 0; i--) {
    1112         [ +  + ]:        792 :         if (config->default_certs_by_type.certs[i] != NULL) {
    1113                 :        195 :             cert = config->default_certs_by_type.certs[i];
    1114                 :        195 :         }
    1115                 :        792 :     }
    1116                 :        198 :     return cert;
    1117                 :        198 : }
    1118                 :            : 
    1119                 :            : int s2n_config_get_num_default_certs(const struct s2n_config *config)
    1120                 :    3561580 : {
    1121 [ #  # ][ -  + ]:    3561580 :     POSIX_ENSURE_REF(config);
    1122                 :    3561580 :     int num_certs = 0;
    1123         [ +  + ]:   17807900 :     for (int i = 0; i < S2N_CERT_TYPE_COUNT; i++) {
    1124         [ +  + ]:   14246320 :         if (config->default_certs_by_type.certs[i] != NULL) {
    1125                 :      11651 :             num_certs++;
    1126                 :      11651 :         }
    1127                 :   14246320 :     }
    1128                 :            : 
    1129                 :    3561580 :     return num_certs;
    1130                 :    3561580 : }
    1131                 :            : 
    1132                 :            : int s2n_config_enable_cert_req_dss_legacy_compat(struct s2n_config *config)
    1133                 :          1 : {
    1134 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(config);
    1135                 :          1 :     config->cert_req_dss_legacy_compat_enabled = 1;
    1136                 :          1 :     return S2N_SUCCESS;
    1137                 :          1 : }
    1138                 :            : 
    1139                 :            : int s2n_config_set_psk_selection_callback(struct s2n_config *config, s2n_psk_selection_callback cb, void *context)
    1140                 :          9 : {
    1141 [ +  + ][ +  - ]:          9 :     POSIX_ENSURE_REF(config);
    1142                 :          8 :     config->psk_selection_cb = cb;
    1143                 :          8 :     config->psk_selection_ctx = context;
    1144                 :          8 :     return S2N_SUCCESS;
    1145                 :          9 : }
    1146                 :            : 
    1147                 :            : int s2n_config_set_key_log_cb(struct s2n_config *config, s2n_key_log_fn callback, void *ctx)
    1148                 :          4 : {
    1149 [ -  + ][ #  # ]:          4 :     POSIX_ENSURE_MUT(config);
    1150                 :            : 
    1151                 :          4 :     config->key_log_cb = callback;
    1152                 :          4 :     config->key_log_ctx = ctx;
    1153                 :            : 
    1154                 :          4 :     return S2N_SUCCESS;
    1155                 :          4 : }
    1156                 :            : 
    1157                 :            : int s2n_config_set_async_pkey_validation_mode(struct s2n_config *config, s2n_async_pkey_validation_mode mode)
    1158                 :          4 : {
    1159 [ -  + ][ #  # ]:          4 :     POSIX_ENSURE_REF(config);
    1160                 :            : 
    1161         [ -  + ]:          4 :     switch (mode) {
    1162         [ -  + ]:          0 :         case S2N_ASYNC_PKEY_VALIDATION_FAST:
    1163         [ +  - ]:          4 :         case S2N_ASYNC_PKEY_VALIDATION_STRICT:
    1164                 :          4 :             config->async_pkey_validation_mode = mode;
    1165                 :          4 :             return S2N_SUCCESS;
    1166                 :          4 :     }
    1167                 :            : 
    1168         [ #  # ]:          0 :     POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
    1169                 :          0 : }
    1170                 :            : 
    1171                 :            : int s2n_config_set_ctx(struct s2n_config *config, void *ctx)
    1172                 :          1 : {
    1173 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(config);
    1174                 :            : 
    1175                 :          1 :     config->context = ctx;
    1176                 :            : 
    1177                 :          1 :     return S2N_SUCCESS;
    1178                 :          1 : }
    1179                 :            : 
    1180                 :            : int s2n_config_get_ctx(struct s2n_config *config, void **ctx)
    1181                 :          2 : {
    1182 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(config);
    1183 [ -  + ][ #  # ]:          2 :     POSIX_ENSURE_REF(ctx);
    1184                 :            : 
    1185                 :          2 :     *ctx = config->context;
    1186                 :            : 
    1187                 :          2 :     return S2N_SUCCESS;
    1188                 :          2 : }
    1189                 :            : 
    1190                 :            : int s2n_config_set_send_buffer_size(struct s2n_config *config, uint32_t size)
    1191                 :         11 : {
    1192 [ +  - ][ +  + ]:         11 :     POSIX_ENSURE_REF(config);
    1193 [ +  + ][ +  - ]:         10 :     POSIX_ENSURE(size >= S2N_MIN_SEND_BUFFER_SIZE, S2N_ERR_INVALID_ARGUMENT);
    1194                 :          8 :     config->send_buffer_size_override = size;
    1195                 :          8 :     return S2N_SUCCESS;
    1196                 :         10 : }
    1197                 :            : 
    1198                 :            : int s2n_config_set_verify_after_sign(struct s2n_config *config, s2n_verify_after_sign mode)
    1199                 :         25 : {
    1200 [ +  + ][ +  - ]:         25 :     POSIX_ENSURE_REF(config);
    1201                 :         24 :     switch (mode) {
    1202         [ +  + ]:          1 :         case S2N_VERIFY_AFTER_SIGN_DISABLED:
    1203                 :          1 :             config->verify_after_sign = false;
    1204                 :          1 :             break;
    1205         [ +  + ]:         21 :         case S2N_VERIFY_AFTER_SIGN_ENABLED:
    1206                 :         21 :             config->verify_after_sign = true;
    1207                 :         21 :             break;
    1208         [ +  + ]:          2 :         default:
    1209         [ +  - ]:          2 :             POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
    1210                 :         24 :     }
    1211                 :         22 :     return S2N_SUCCESS;
    1212                 :         24 : }
    1213                 :            : 
    1214                 :            : /*
    1215                 :            :  *= https://www.rfc-editor.org/rfc/rfc5746#5
    1216                 :            :  *# TLS implementations SHOULD provide a mechanism to disable and enable
    1217                 :            :  *# renegotiation.
    1218                 :            :  */
    1219                 :            : int s2n_config_set_renegotiate_request_cb(struct s2n_config *config, s2n_renegotiate_request_cb cb, void *ctx)
    1220                 :         18 : {
    1221 [ +  - ][ +  + ]:         18 :     POSIX_ENSURE_REF(config);
    1222                 :            : 
    1223                 :            :     /* This feature cannot be used with serialization currently */
    1224 [ +  - ][ +  + ]:         17 :     POSIX_ENSURE(config->serialized_connection_version == S2N_SERIALIZED_CONN_NONE, S2N_ERR_INVALID_STATE);
    1225                 :            : 
    1226                 :         16 :     config->renegotiate_request_cb = cb;
    1227                 :         16 :     config->renegotiate_request_ctx = ctx;
    1228                 :         16 :     return S2N_SUCCESS;
    1229                 :         17 : }
    1230                 :            : 
    1231                 :            : int s2n_config_set_npn(struct s2n_config *config, bool enable)
    1232                 :          3 : {
    1233 [ +  - ][ +  + ]:          3 :     POSIX_ENSURE_REF(config);
    1234                 :            : 
    1235                 :          2 :     config->npn_supported = enable;
    1236                 :            : 
    1237                 :          2 :     return S2N_SUCCESS;
    1238                 :          3 : }
    1239                 :            : 
    1240                 :            : /*
    1241                 :            :  * Wrapper for wall_clock callback. This wrapper will ensure right return of s2n_errno everytime wall_clock
    1242                 :            :  * callback is called.
    1243                 :            :  */
    1244                 :            : S2N_RESULT s2n_config_wall_clock(struct s2n_config *config, uint64_t *output)
    1245                 :       4351 : {
    1246 [ -  + ][ #  # ]:       4351 :     RESULT_ENSURE_REF(config);
    1247 [ -  + ][ #  # ]:       4351 :     RESULT_ENSURE(config->wall_clock(config->sys_clock_ctx, output) >= S2N_SUCCESS, S2N_ERR_CANCELLED);
    1248                 :       4351 :     return S2N_RESULT_OK;
    1249                 :       4351 : }
    1250                 :            : 
    1251                 :            : /*
    1252                 :            :  * Get the indicated time from the monotonic clock.
    1253                 :            :  *
    1254                 :            :  * This callback ensures that the correct errno is set in the case of failure.
    1255                 :            :  */
    1256                 :            : S2N_RESULT s2n_config_monotonic_clock(struct s2n_config *config, uint64_t *output)
    1257                 :          0 : {
    1258 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_REF(config);
    1259 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE(config->monotonic_clock(config->monotonic_clock_ctx, output) >= S2N_SUCCESS, S2N_ERR_CANCELLED);
    1260                 :          0 :     return S2N_RESULT_OK;
    1261                 :          0 : }
    1262                 :            : 
    1263                 :            : int s2n_config_set_crl_lookup_cb(struct s2n_config *config, s2n_crl_lookup_callback cb, void *ctx)
    1264                 :         22 : {
    1265 [ +  + ][ +  - ]:         22 :     POSIX_ENSURE_REF(config);
    1266                 :         21 :     config->crl_lookup_cb = cb;
    1267                 :         21 :     config->crl_lookup_ctx = ctx;
    1268                 :         21 :     return S2N_SUCCESS;
    1269                 :         22 : }
    1270                 :            : 
    1271                 :            : int s2n_config_set_recv_multi_record(struct s2n_config *config, bool enabled)
    1272                 :          6 : {
    1273 [ -  + ][ #  # ]:          6 :     POSIX_ENSURE_REF(config);
    1274                 :            : 
    1275                 :          6 :     config->recv_multi_record = enabled;
    1276                 :            : 
    1277                 :          6 :     return S2N_SUCCESS;
    1278                 :          6 : }
    1279                 :            : 
    1280                 :            : int s2n_config_set_cert_validation_cb(struct s2n_config *config, s2n_cert_validation_callback cb, void *ctx)
    1281                 :         34 : {
    1282 [ +  + ][ +  - ]:         34 :     POSIX_ENSURE_REF(config);
    1283                 :            : 
    1284                 :         33 :     config->cert_validation_cb = cb;
    1285                 :         33 :     config->cert_validation_ctx = ctx;
    1286                 :            : 
    1287                 :         33 :     return S2N_SUCCESS;
    1288                 :         34 : }
    1289                 :            : 
    1290                 :            : int s2n_config_get_supported_groups(struct s2n_config *config, uint16_t *groups, uint16_t groups_count_max,
    1291                 :            :         uint16_t *groups_count_out)
    1292                 :        174 : {
    1293 [ +  + ][ +  - ]:        174 :     POSIX_ENSURE_REF(groups_count_out);
    1294                 :        173 :     *groups_count_out = 0;
    1295 [ +  + ][ +  - ]:        173 :     POSIX_ENSURE_REF(config);
    1296 [ +  + ][ +  - ]:        172 :     POSIX_ENSURE_REF(groups);
    1297                 :            : 
    1298                 :        171 :     const struct s2n_security_policy *security_policy = config->security_policy;
    1299 [ -  + ][ #  # ]:        171 :     POSIX_ENSURE_REF(security_policy);
    1300                 :        171 :     const struct s2n_kem_preferences *kem_preferences = security_policy->kem_preferences;
    1301 [ #  # ][ -  + ]:        171 :     POSIX_ENSURE_REF(kem_preferences);
    1302                 :        171 :     const struct s2n_ecc_preferences *ecc_preferences = security_policy->ecc_preferences;
    1303 [ -  + ][ #  # ]:        171 :     POSIX_ENSURE_REF(ecc_preferences);
    1304                 :            : 
    1305                 :        171 :     uint16_t groups_count = 0;
    1306         [ +  + ]:        303 :     for (uint8_t i = 0; i < kem_preferences->tls13_kem_group_count; i++) {
    1307                 :        132 :         const struct s2n_kem_group *kem_group = kem_preferences->tls13_kem_groups[i];
    1308 [ -  + ][ #  # ]:        132 :         POSIX_ENSURE_REF(kem_group);
    1309         [ +  - ]:        132 :         if (!s2n_kem_group_is_available(kem_group)) {
    1310                 :        132 :             continue;
    1311                 :        132 :         }
    1312                 :            : 
    1313 [ #  # ][ #  # ]:          0 :         POSIX_ENSURE(groups_count < groups_count_max, S2N_ERR_INSUFFICIENT_MEM_SIZE);
    1314                 :          0 :         groups[groups_count] = kem_group->iana_id;
    1315                 :          0 :         groups_count += 1;
    1316                 :          0 :     }
    1317                 :            : 
    1318         [ +  + ]:        609 :     for (uint8_t i = 0; i < ecc_preferences->count; i++) {
    1319                 :        443 :         const struct s2n_ecc_named_curve *ecc_curve = ecc_preferences->ecc_curves[i];
    1320 [ #  # ][ -  + ]:        443 :         POSIX_ENSURE_REF(ecc_curve);
    1321                 :            : 
    1322 [ +  + ][ +  - ]:        443 :         POSIX_ENSURE(groups_count < groups_count_max, S2N_ERR_INSUFFICIENT_MEM_SIZE);
    1323                 :        438 :         groups[groups_count] = ecc_curve->iana_id;
    1324                 :        438 :         groups_count += 1;
    1325                 :        438 :     }
    1326                 :            : 
    1327                 :        166 :     *groups_count_out = groups_count;
    1328                 :            : 
    1329                 :        166 :     return S2N_SUCCESS;
    1330                 :        171 : }
    1331                 :            : 
    1332                 :            : int s2n_config_set_serialization_version(struct s2n_config *config, s2n_serialization_version version)
    1333                 :         10 : {
    1334 [ #  # ][ -  + ]:         10 :     POSIX_ENSURE_REF(config);
    1335                 :            : 
    1336                 :            :     /* This feature cannot be used with renegotiation currently */
    1337 [ +  - ][ +  + ]:         10 :     POSIX_ENSURE(config->renegotiate_request_cb == NULL, S2N_ERR_INVALID_STATE);
    1338                 :            : 
    1339                 :            :     /* Currently there is only one format version supported */
    1340 [ -  + ][ #  # ]:          9 :     POSIX_ENSURE_EQ(version, S2N_SERIALIZED_CONN_V1);
    1341                 :          9 :     config->serialized_connection_version = version;
    1342                 :            : 
    1343                 :          9 :     return S2N_SUCCESS;
    1344                 :          9 : }
    1345                 :            : 
    1346                 :            : int s2n_config_set_max_blinding_delay(struct s2n_config *config, uint32_t seconds)
    1347                 :        573 : {
    1348 [ #  # ][ -  + ]:        573 :     POSIX_ENSURE_REF(config);
    1349                 :            : 
    1350                 :        573 :     config->custom_blinding_set = 1;
    1351                 :        573 :     config->max_blinding = seconds;
    1352                 :            : 
    1353                 :        573 :     return S2N_SUCCESS;
    1354                 :        573 : }
    1355                 :            : 
    1356                 :            : int s2n_config_set_subscriber(struct s2n_config *config, void *subscriber)
    1357                 :          3 : {
    1358 [ +  - ][ +  + ]:          3 :     POSIX_ENSURE_REF(config);
    1359                 :          1 :     config->subscriber = subscriber;
    1360                 :          1 :     return S2N_SUCCESS;
    1361                 :          3 : }
    1362                 :            : 
    1363                 :            : int s2n_config_set_handshake_event(struct s2n_config *config, s2n_event_on_handshake_cb callback)
    1364                 :          1 : {
    1365 [ #  # ][ -  + ]:          1 :     POSIX_ENSURE_REF(config);
    1366                 :          1 :     config->on_handshake_event = callback;
    1367                 :          1 :     return S2N_SUCCESS;
    1368                 :          1 : }

Generated by: LCOV version 1.14