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