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

Generated by: LCOV version 1.14