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