Branch data Line data Source code
1 : : /*
2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License").
5 : : * You may not use this file except in compliance with the License.
6 : : * A copy of the License is located at
7 : : *
8 : : * http://aws.amazon.com/apache2.0
9 : : *
10 : : * or in the "license" file accompanying this file. This file is distributed
11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 : : * express or implied. See the License for the specific language governing
13 : : * permissions and limitations under the License.
14 : : */
15 : :
16 : : #include "tls/s2n_kem.h"
17 : :
18 : : #include "crypto/s2n_evp_kem.h"
19 : : #include "crypto/s2n_pq.h"
20 : : #include "stuffer/s2n_stuffer.h"
21 : : #include "tls/extensions/s2n_key_share.h"
22 : : #include "tls/s2n_tls_parameters.h"
23 : : #include "utils/s2n_mem.h"
24 : : #include "utils/s2n_safety.h"
25 : :
26 : : const struct s2n_kem s2n_mlkem_768 = {
27 : : .name = "mlkem768",
28 : : .kem_nid = S2N_NID_MLKEM768,
29 : : .kem_extension_id = 0, /* This is not used in TLS 1.2's KEM extension */
30 : : .public_key_length = S2N_MLKEM_768_PUBLIC_KEY_BYTES,
31 : : .private_key_length = S2N_MLKEM_768_SECRET_KEY_BYTES,
32 : : .shared_secret_key_length = S2N_MLKEM_768_SHARED_SECRET_BYTES,
33 : : .ciphertext_length = S2N_MLKEM_768_CIPHERTEXT_BYTES,
34 : : .generate_keypair = &s2n_evp_kem_generate_keypair,
35 : : .encapsulate = &s2n_evp_kem_encapsulate,
36 : : .decapsulate = &s2n_evp_kem_decapsulate,
37 : : };
38 : :
39 : : const struct s2n_kem s2n_mlkem_1024 = {
40 : : .name = "mlkem1024",
41 : : .kem_nid = S2N_NID_MLKEM1024,
42 : : .kem_extension_id = 0, /* This is not used in TLS 1.2's KEM extension */
43 : : .public_key_length = S2N_MLKEM_1024_PUBLIC_KEY_BYTES,
44 : : .private_key_length = S2N_MLKEM_1024_SECRET_KEY_BYTES,
45 : : .shared_secret_key_length = S2N_MLKEM_1024_SHARED_SECRET_BYTES,
46 : : .ciphertext_length = S2N_MLKEM_1024_CIPHERTEXT_BYTES,
47 : : .generate_keypair = &s2n_evp_kem_generate_keypair,
48 : : .encapsulate = &s2n_evp_kem_encapsulate,
49 : : .decapsulate = &s2n_evp_kem_decapsulate,
50 : : };
51 : :
52 : : const struct s2n_iana_to_kem kem_mapping[1] = {
53 : : {
54 : : .iana_value = { TLS_NULL_WITH_NULL_NULL },
55 : : .kems = NULL,
56 : : .kem_count = 0,
57 : : },
58 : : };
59 : :
60 : : /*
61 : : * ML-KEM based pure PQ KEMs as specified by IETF and registered in IANA.
62 : : *
63 : : * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
64 : : * https://datatracker.ietf.org/doc/draft-connolly-tls-mlkem-key-agreement/05/
65 : : */
66 : : const struct s2n_kem_group s2n_pure_mlkem_1024 = {
67 : : .name = "MLKEM1024",
68 : : .iana_id = TLS_PQ_KEM_GROUP_ID_MLKEM_1024,
69 : : .curve = &s2n_ecc_curve_none,
70 : : .kem = &s2n_mlkem_1024,
71 : : .send_kem_first = 0,
72 : : };
73 : :
74 : : /*
75 : : * ML-KEM based hybrid KEMs as specified by IETF and registered in IANA.
76 : : *
77 : : * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
78 : : * https://datatracker.ietf.org/doc/draft-kwiatkowski-tls-ecdhe-mlkem/
79 : : */
80 : : const struct s2n_kem_group s2n_secp256r1_mlkem_768 = {
81 : : .name = "SecP256r1MLKEM768",
82 : : .iana_id = TLS_PQ_KEM_GROUP_ID_SECP256R1_MLKEM_768,
83 : : .curve = &s2n_ecc_curve_secp256r1,
84 : : .kem = &s2n_mlkem_768,
85 : : .send_kem_first = 0,
86 : : };
87 : :
88 : : const struct s2n_kem_group s2n_x25519_mlkem_768 = {
89 : : .name = "X25519MLKEM768",
90 : : .iana_id = TLS_PQ_KEM_GROUP_ID_X25519_MLKEM_768,
91 : : .curve = &s2n_ecc_curve_x25519,
92 : : .kem = &s2n_mlkem_768,
93 : : /* ML-KEM KeyShare should always be sent first for X25519MLKEM768.
94 : : * https://datatracker.ietf.org/doc/html/draft-kwiatkowski-tls-ecdhe-mlkem-02#name-negotiated-groups */
95 : : .send_kem_first = 1,
96 : : };
97 : :
98 : : const struct s2n_kem_group s2n_secp384r1_mlkem_1024 = {
99 : : .name = "SecP384r1MLKEM1024",
100 : : .iana_id = TLS_PQ_KEM_GROUP_ID_SECP384R1_MLKEM_1024,
101 : : .curve = &s2n_ecc_curve_secp384r1,
102 : : .kem = &s2n_mlkem_1024,
103 : : .send_kem_first = 0,
104 : : };
105 : :
106 : : const struct s2n_kem_group *ALL_SUPPORTED_KEM_GROUPS[] = {
107 : : &s2n_x25519_mlkem_768,
108 : : &s2n_secp256r1_mlkem_768,
109 : : &s2n_secp384r1_mlkem_1024,
110 : : &s2n_pure_mlkem_1024,
111 : : };
112 : :
113 : : /* Helper safety macro to call the NIST PQ KEM functions. The NIST
114 : : * functions may return any non-zero value to indicate failure. */
115 : 12 : #define GUARD_PQ_AS_RESULT(x) RESULT_ENSURE((x) == 0, S2N_ERR_PQ_CRYPTO)
116 : :
117 : : S2N_RESULT s2n_kem_generate_keypair(struct s2n_kem_params *kem_params)
118 : 4 : {
119 [ # # ][ - + ]: 4 : RESULT_ENSURE_REF(kem_params);
120 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem_params->kem);
121 : 4 : const struct s2n_kem *kem = kem_params->kem;
122 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem->generate_keypair);
123 : :
124 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem_params->public_key.data);
125 [ - + ][ # # ]: 4 : RESULT_ENSURE(kem_params->public_key.size == kem->public_key_length, S2N_ERR_SAFETY);
126 : :
127 : : /* Need to save the private key for decapsulation */
128 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_realloc(&kem_params->private_key, kem->private_key_length));
129 : :
130 [ - + ][ # # ]: 4 : GUARD_PQ_AS_RESULT(kem->generate_keypair(kem, kem_params->public_key.data, kem_params->private_key.data));
131 : 4 : return S2N_RESULT_OK;
132 : 4 : }
133 : :
134 : : S2N_RESULT s2n_kem_encapsulate(struct s2n_kem_params *kem_params, struct s2n_blob *ciphertext)
135 : 4 : {
136 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem_params);
137 [ # # ][ - + ]: 4 : RESULT_ENSURE_REF(kem_params->kem);
138 : 4 : const struct s2n_kem *kem = kem_params->kem;
139 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem->encapsulate);
140 : :
141 [ - + ][ # # ]: 4 : RESULT_ENSURE(kem_params->public_key.size == kem->public_key_length, S2N_ERR_SAFETY);
142 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem_params->public_key.data);
143 : :
144 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(ciphertext);
145 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(ciphertext->data);
146 [ - + ][ # # ]: 4 : RESULT_ENSURE(ciphertext->size == kem->ciphertext_length, S2N_ERR_SAFETY);
147 : :
148 : : /* Need to save the shared secret for key derivation */
149 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_alloc(&(kem_params->shared_secret), kem->shared_secret_key_length));
150 : :
151 [ - + ][ # # ]: 4 : GUARD_PQ_AS_RESULT(kem->encapsulate(kem, ciphertext->data, kem_params->shared_secret.data, kem_params->public_key.data));
152 : 4 : return S2N_RESULT_OK;
153 : 4 : }
154 : :
155 : : S2N_RESULT s2n_kem_decapsulate(struct s2n_kem_params *kem_params, const struct s2n_blob *ciphertext)
156 : 4 : {
157 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem_params);
158 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem_params->kem);
159 : 4 : const struct s2n_kem *kem = kem_params->kem;
160 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem->decapsulate);
161 : :
162 [ - + ][ # # ]: 4 : RESULT_ENSURE(kem_params->private_key.size == kem->private_key_length, S2N_ERR_SAFETY);
163 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(kem_params->private_key.data);
164 : :
165 [ # # ][ - + ]: 4 : RESULT_ENSURE_REF(ciphertext);
166 [ - + ][ # # ]: 4 : RESULT_ENSURE_REF(ciphertext->data);
167 [ - + ][ # # ]: 4 : RESULT_ENSURE(ciphertext->size == kem->ciphertext_length, S2N_ERR_SAFETY);
168 : :
169 : : /* Need to save the shared secret for key derivation */
170 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_alloc(&(kem_params->shared_secret), kem->shared_secret_key_length));
171 : :
172 [ - + ][ # # ]: 4 : GUARD_PQ_AS_RESULT(kem->decapsulate(kem, kem_params->shared_secret.data, ciphertext->data, kem_params->private_key.data));
173 : 4 : return S2N_RESULT_OK;
174 : 4 : }
175 : :
176 : : static int s2n_kem_check_kem_compatibility(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], const struct s2n_kem *candidate_kem,
177 : : uint8_t *kem_is_compatible)
178 : 0 : {
179 : 0 : const struct s2n_iana_to_kem *compatible_kems = NULL;
180 [ # # ]: 0 : POSIX_GUARD(s2n_cipher_suite_to_kem(iana_value, &compatible_kems));
181 : :
182 [ # # ]: 0 : for (uint8_t i = 0; i < compatible_kems->kem_count; i++) {
183 [ # # ]: 0 : if (candidate_kem->kem_extension_id == compatible_kems->kems[i]->kem_extension_id) {
184 : 0 : *kem_is_compatible = 1;
185 : 0 : return S2N_SUCCESS;
186 : 0 : }
187 : 0 : }
188 : :
189 : 0 : *kem_is_compatible = 0;
190 : 0 : return S2N_SUCCESS;
191 : 0 : }
192 : :
193 : : int s2n_choose_kem_with_peer_pref_list(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], struct s2n_blob *client_kem_ids,
194 : : const struct s2n_kem *server_kem_pref_list[], const uint8_t num_server_supported_kems, const struct s2n_kem **chosen_kem)
195 : 0 : {
196 : 0 : struct s2n_stuffer client_kem_ids_stuffer = { 0 };
197 [ # # ]: 0 : POSIX_GUARD(s2n_stuffer_init(&client_kem_ids_stuffer, client_kem_ids));
198 [ # # ]: 0 : POSIX_GUARD(s2n_stuffer_write(&client_kem_ids_stuffer, client_kem_ids));
199 : :
200 : : /* Each KEM ID is 2 bytes */
201 : 0 : uint8_t num_client_candidate_kems = client_kem_ids->size / 2;
202 : :
203 [ # # ]: 0 : for (uint8_t i = 0; i < num_server_supported_kems; i++) {
204 : 0 : const struct s2n_kem *candidate_server_kem = (server_kem_pref_list[i]);
205 : :
206 : 0 : uint8_t server_kem_is_compatible = 0;
207 [ # # ]: 0 : POSIX_GUARD(s2n_kem_check_kem_compatibility(iana_value, candidate_server_kem, &server_kem_is_compatible));
208 : :
209 [ # # ]: 0 : if (!server_kem_is_compatible) {
210 : 0 : continue;
211 : 0 : }
212 : :
213 [ # # ]: 0 : for (uint8_t j = 0; j < num_client_candidate_kems; j++) {
214 : 0 : kem_extension_size candidate_client_kem_id = 0;
215 [ # # ]: 0 : POSIX_GUARD(s2n_stuffer_read_uint16(&client_kem_ids_stuffer, &candidate_client_kem_id));
216 : :
217 [ # # ]: 0 : if (candidate_server_kem->kem_extension_id == candidate_client_kem_id) {
218 : 0 : *chosen_kem = candidate_server_kem;
219 : 0 : return S2N_SUCCESS;
220 : 0 : }
221 : 0 : }
222 [ # # ]: 0 : POSIX_GUARD(s2n_stuffer_reread(&client_kem_ids_stuffer));
223 : 0 : }
224 : :
225 : : /* Client and server did not propose any mutually supported KEMs compatible with the ciphersuite */
226 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
227 : 0 : }
228 : :
229 : : int s2n_choose_kem_without_peer_pref_list(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], const struct s2n_kem *server_kem_pref_list[],
230 : : const uint8_t num_server_supported_kems, const struct s2n_kem **chosen_kem)
231 : 0 : {
232 [ # # ]: 0 : for (uint8_t i = 0; i < num_server_supported_kems; i++) {
233 : 0 : uint8_t kem_is_compatible = 0;
234 [ # # ]: 0 : POSIX_GUARD(s2n_kem_check_kem_compatibility(iana_value, server_kem_pref_list[i], &kem_is_compatible));
235 [ # # ]: 0 : if (kem_is_compatible) {
236 : 0 : *chosen_kem = server_kem_pref_list[i];
237 : 0 : return S2N_SUCCESS;
238 : 0 : }
239 : 0 : }
240 : :
241 : : /* The server preference list did not contain any KEM extensions compatible with the ciphersuite */
242 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
243 : 0 : }
244 : :
245 : : int s2n_kem_free(struct s2n_kem_params *kem_params)
246 : 10664990 : {
247 [ + + ]: 10664990 : if (kem_params != NULL) {
248 [ - + ]: 10664989 : POSIX_GUARD(s2n_free_or_wipe(&kem_params->private_key));
249 [ - + ]: 10664989 : POSIX_GUARD(s2n_free_or_wipe(&kem_params->public_key));
250 [ - + ]: 10664989 : POSIX_GUARD(s2n_free_or_wipe(&kem_params->shared_secret));
251 : 10664989 : }
252 : 10664990 : return S2N_SUCCESS;
253 : 10664990 : }
254 : :
255 : : int s2n_kem_group_free(struct s2n_kem_group_params *kem_group_params)
256 : 7116299 : {
257 [ + + ]: 7116299 : if (kem_group_params != NULL) {
258 [ - + ]: 7116298 : POSIX_GUARD(s2n_kem_free(&kem_group_params->kem_params));
259 [ - + ]: 7116298 : POSIX_GUARD(s2n_ecc_evp_params_free(&kem_group_params->ecc_params));
260 : 7116298 : }
261 : 7116299 : return S2N_SUCCESS;
262 : 7116299 : }
263 : :
264 : : int s2n_cipher_suite_to_kem(const uint8_t iana_value[S2N_TLS_CIPHER_SUITE_LEN], const struct s2n_iana_to_kem **compatible_params)
265 : 0 : {
266 [ # # ]: 0 : for (size_t i = 0; i < s2n_array_len(kem_mapping); i++) {
267 : 0 : const struct s2n_iana_to_kem *candidate = &kem_mapping[i];
268 [ # # ]: 0 : if (s2n_constant_time_equals(iana_value, candidate->iana_value, S2N_TLS_CIPHER_SUITE_LEN)) {
269 : 0 : *compatible_params = candidate;
270 : 0 : return S2N_SUCCESS;
271 : 0 : }
272 : 0 : }
273 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
274 : 0 : }
275 : :
276 : : int s2n_get_kem_from_extension_id(kem_extension_size kem_id, const struct s2n_kem **kem)
277 : 1 : {
278 [ + + ]: 2 : for (size_t i = 0; i < s2n_array_len(kem_mapping); i++) {
279 : 1 : const struct s2n_iana_to_kem *iana_to_kem = &kem_mapping[i];
280 : :
281 [ - + ]: 1 : for (int j = 0; j < iana_to_kem->kem_count; j++) {
282 : 0 : const struct s2n_kem *candidate_kem = iana_to_kem->kems[j];
283 [ # # ]: 0 : if (candidate_kem->kem_extension_id == kem_id) {
284 : 0 : *kem = candidate_kem;
285 : 0 : return S2N_SUCCESS;
286 : 0 : }
287 : 0 : }
288 : 1 : }
289 : :
290 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_KEM_UNSUPPORTED_PARAMS);
291 : 1 : }
292 : :
293 : : int s2n_kem_send_public_key(struct s2n_stuffer *out, struct s2n_kem_params *kem_params)
294 : 8 : {
295 [ + - ][ + + ]: 8 : POSIX_ENSURE_REF(out);
296 [ + - ][ + + ]: 6 : POSIX_ENSURE_REF(kem_params);
297 [ + + ][ + - ]: 4 : POSIX_ENSURE_REF(kem_params->kem);
298 : :
299 : 2 : const struct s2n_kem *kem = kem_params->kem;
300 : :
301 [ + + ]: 2 : if (kem_params->len_prefixed) {
302 [ - + ]: 1 : POSIX_GUARD(s2n_stuffer_write_uint16(out, kem->public_key_length));
303 : 1 : }
304 : :
305 : : /* We don't need to store the public key after sending it.
306 : : * We write it directly to *out. */
307 : 2 : kem_params->public_key.data = s2n_stuffer_raw_write(out, kem->public_key_length);
308 [ # # ][ - + ]: 2 : POSIX_ENSURE_REF(kem_params->public_key.data);
309 : 2 : kem_params->public_key.size = kem->public_key_length;
310 : :
311 : : /* Saves the private key in kem_params */
312 [ - + ]: 2 : POSIX_GUARD_RESULT(s2n_kem_generate_keypair(kem_params));
313 : :
314 : : /* After using s2n_stuffer_raw_write() above to write the public
315 : : * key to the stuffer, we want to ensure that kem_params->public_key.data
316 : : * does not continue to point at *out, else we may unexpectedly
317 : : * overwrite part of the stuffer when s2n_kem_free() is called. */
318 : 2 : kem_params->public_key.data = NULL;
319 : 2 : kem_params->public_key.size = 0;
320 : :
321 : 2 : return S2N_SUCCESS;
322 : 2 : }
323 : :
324 : : int s2n_kem_recv_public_key(struct s2n_stuffer *in, struct s2n_kem_params *kem_params)
325 : 9 : {
326 [ + + ][ + - ]: 9 : POSIX_ENSURE_REF(in);
327 [ + + ][ + - ]: 7 : POSIX_ENSURE_REF(kem_params);
328 [ + + ][ + - ]: 5 : POSIX_ENSURE_REF(kem_params->kem);
329 : :
330 : 3 : const struct s2n_kem *kem = kem_params->kem;
331 : :
332 [ + + ]: 3 : if (kem_params->len_prefixed) {
333 : 2 : kem_public_key_size public_key_length = 0;
334 [ - + ]: 2 : POSIX_GUARD(s2n_stuffer_read_uint16(in, &public_key_length));
335 [ + + ][ + - ]: 2 : POSIX_ENSURE(public_key_length == kem->public_key_length, S2N_ERR_BAD_MESSAGE);
336 : 2 : }
337 : :
338 : : /* Alloc memory for the public key; the peer receiving it will need it
339 : : * later during the handshake to encapsulate the shared secret. */
340 [ - + ]: 2 : POSIX_GUARD(s2n_alloc(&(kem_params->public_key), kem->public_key_length));
341 [ - + ]: 2 : POSIX_GUARD(s2n_stuffer_read_bytes(in, kem_params->public_key.data, kem->public_key_length));
342 : :
343 : 2 : return S2N_SUCCESS;
344 : 2 : }
345 : :
346 : : int s2n_kem_send_ciphertext(struct s2n_stuffer *out, struct s2n_kem_params *kem_params)
347 : 10 : {
348 [ + - ][ + + ]: 10 : POSIX_ENSURE_REF(out);
349 [ + + ][ + - ]: 8 : POSIX_ENSURE_REF(kem_params);
350 [ + + ][ + - ]: 6 : POSIX_ENSURE_REF(kem_params->kem);
351 [ + + ][ + - ]: 4 : POSIX_ENSURE_REF(kem_params->public_key.data);
352 : :
353 : 2 : const struct s2n_kem *kem = kem_params->kem;
354 : :
355 [ + + ]: 2 : if (kem_params->len_prefixed) {
356 [ - + ]: 1 : POSIX_GUARD(s2n_stuffer_write_uint16(out, kem->ciphertext_length));
357 : 1 : }
358 : :
359 : : /* Ciphertext will get written to *out */
360 : 2 : struct s2n_blob ciphertext = { 0 };
361 [ - + ]: 2 : POSIX_GUARD(s2n_blob_init(&ciphertext, s2n_stuffer_raw_write(out, kem->ciphertext_length), kem->ciphertext_length));
362 [ # # ][ - + ]: 2 : POSIX_ENSURE_REF(ciphertext.data);
363 : :
364 : : /* Saves the shared secret in kem_params */
365 [ - + ]: 2 : POSIX_GUARD_RESULT(s2n_kem_encapsulate(kem_params, &ciphertext));
366 : :
367 : 2 : return S2N_SUCCESS;
368 : 2 : }
369 : :
370 : : int s2n_kem_recv_ciphertext(struct s2n_stuffer *in, struct s2n_kem_params *kem_params)
371 : 11 : {
372 [ + + ][ + - ]: 11 : POSIX_ENSURE_REF(in);
373 [ + + ][ + - ]: 9 : POSIX_ENSURE_REF(kem_params);
374 [ + + ][ + - ]: 7 : POSIX_ENSURE_REF(kem_params->kem);
375 [ + - ][ + + ]: 5 : POSIX_ENSURE_REF(kem_params->private_key.data);
376 : :
377 : 3 : const struct s2n_kem *kem = kem_params->kem;
378 : :
379 [ + + ]: 3 : if (kem_params->len_prefixed) {
380 : 2 : kem_ciphertext_key_size ciphertext_length = 0;
381 [ - + ]: 2 : POSIX_GUARD(s2n_stuffer_read_uint16(in, &ciphertext_length));
382 [ + + ][ + - ]: 2 : POSIX_ENSURE(ciphertext_length == kem->ciphertext_length, S2N_ERR_BAD_MESSAGE);
383 : 2 : }
384 : :
385 : 2 : const struct s2n_blob ciphertext = { .data = s2n_stuffer_raw_read(in, kem->ciphertext_length), .size = kem->ciphertext_length };
386 [ - + ][ # # ]: 2 : POSIX_ENSURE_REF(ciphertext.data);
387 : :
388 : : /* Saves the shared secret in kem_params */
389 [ - + ]: 2 : POSIX_GUARD_RESULT(s2n_kem_decapsulate(kem_params, &ciphertext));
390 : :
391 : 2 : return S2N_SUCCESS;
392 : 2 : }
393 : :
394 : : bool s2n_kem_is_available(const struct s2n_kem *kem)
395 : 11866 : {
396 [ - + ][ + - ]: 11866 : if (kem == NULL || kem->kem_nid == NID_undef) {
397 : 11866 : return false;
398 : 11866 : }
399 : :
400 : 0 : return s2n_libcrypto_supports_evp_kem();
401 : 11866 : }
402 : :
403 : : bool s2n_kem_group_is_available(const struct s2n_kem_group *kem_group)
404 : 11876 : {
405 : : /* Check for values that might be undefined when compiling for older libcrypto's */
406 [ + + ][ - + ]: 11876 : if (kem_group == NULL || kem_group->curve == NULL || kem_group->kem == NULL) {
[ - + ]
407 : 12 : return false;
408 : 12 : }
409 : :
410 : 11864 : bool available = s2n_kem_is_available(kem_group->kem);
411 : :
412 : : /* x25519 based tls13_kem_groups require EVP_APIS_SUPPORTED */
413 [ + + ]: 11864 : if (kem_group->curve == &s2n_ecc_curve_x25519) {
414 : 3936 : available &= s2n_is_evp_apis_supported();
415 : 3936 : }
416 : :
417 : 11864 : return available;
418 : 11876 : }
419 : :
420 : : int s2n_find_kem_group_from_iana_id(uint16_t iana_id, const struct s2n_kem_group **out, bool *found)
421 : 4 : {
422 [ - + ][ # # ]: 4 : POSIX_ENSURE_REF(out);
423 [ # # ][ - + ]: 4 : POSIX_ENSURE_REF(found);
424 : 4 : *found = false;
425 : :
426 [ + + ]: 20 : for (size_t i = 0; i < S2N_KEM_GROUPS_COUNT; i++) {
427 : 16 : const struct s2n_kem_group *kem_group = ALL_SUPPORTED_KEM_GROUPS[i];
428 [ - + ][ # # ]: 16 : POSIX_ENSURE_REF(kem_group);
429 [ - + ]: 16 : if (kem_group->iana_id == iana_id) {
430 : 0 : *out = kem_group;
431 : 0 : *found = true;
432 : 0 : return S2N_SUCCESS;
433 : 0 : }
434 : 16 : }
435 : 4 : return S2N_SUCCESS;
436 : 4 : }
|