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 "crypto/s2n_dhe.h"
17 : :
18 : : #include <openssl/bn.h>
19 : : #include <openssl/dh.h>
20 : : #include <openssl/evp.h>
21 : : #include <stdint.h>
22 : :
23 : : #include "crypto/s2n_openssl.h"
24 : : #include "error/s2n_errno.h"
25 : : #include "stuffer/s2n_stuffer.h"
26 : : #include "utils/s2n_blob.h"
27 : : #include "utils/s2n_mem.h"
28 : : #include "utils/s2n_safety.h"
29 : :
30 : : DEFINE_POINTER_CLEANUP_FUNC(BIGNUM *, BN_free);
31 : :
32 : : #define S2N_MIN_DH_PRIME_SIZE_BYTES (2048 / 8)
33 : :
34 : : /* Caller is not responsible for freeing values returned by these accessors
35 : : * Per https://www.openssl.org/docs/man1.1.0/crypto/DH_get0_pqg.html
36 : : */
37 : : static const BIGNUM *s2n_get_Ys_dh_param(struct s2n_dh_params *dh_params)
38 : 151 : {
39 : 151 : const BIGNUM *Ys = NULL;
40 : :
41 : : /* DH made opaque in Openssl 1.1.0 */
42 : 151 : #if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
43 : 151 : DH_get0_key(dh_params->dh, &Ys, NULL);
44 : : #else
45 : : Ys = dh_params->dh->pub_key;
46 : : #endif
47 : :
48 : 151 : return Ys;
49 : 151 : }
50 : :
51 : : static const BIGNUM *s2n_get_p_dh_param(struct s2n_dh_params *dh_params)
52 : 362 : {
53 : 362 : const BIGNUM *p = NULL;
54 : 362 : #if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
55 : 362 : DH_get0_pqg(dh_params->dh, &p, NULL, NULL);
56 : : #else
57 : : p = dh_params->dh->p;
58 : : #endif
59 : :
60 : 362 : return p;
61 : 362 : }
62 : :
63 : : /* Pad the shared secret with leading zeros to a constant length equal to
64 : : * expected_size. DH_compute_key may return fewer bytes when the result has
65 : : * leading zeros, and a variable-length output could theoretically leak
66 : : * information about the shared secret via timing.
67 : : *
68 : : * DH_compute_key_padded exists to handle this, but is only available in
69 : : * certain libcrypto implementations (OpenSSL 1.1.0+). We pad manually
70 : : * for portability across all supported libcryptos.
71 : : */
72 : : static void s2n_dh_pad_shared_secret(struct s2n_blob *shared_key, int computed_size, int expected_size)
73 : 48 : {
74 : 48 : int padding = expected_size - computed_size;
75 : 48 : memmove(shared_key->data + padding, shared_key->data, computed_size);
76 : 48 : memset(shared_key->data, 0, padding);
77 : 48 : shared_key->size = expected_size;
78 : 48 : }
79 : :
80 : : static const BIGNUM *s2n_get_g_dh_param(struct s2n_dh_params *dh_params)
81 : 285 : {
82 : 285 : const BIGNUM *g = NULL;
83 : 285 : #if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
84 : 285 : DH_get0_pqg(dh_params->dh, NULL, NULL, &g);
85 : : #else
86 : : g = dh_params->dh->g;
87 : : #endif
88 : :
89 : 285 : return g;
90 : 285 : }
91 : :
92 : : static int s2n_check_p_g_dh_params(struct s2n_dh_params *dh_params)
93 : 261 : {
94 [ - + ][ # # ]: 261 : POSIX_ENSURE_REF(dh_params);
95 [ + - ][ + + ]: 261 : POSIX_ENSURE_REF(dh_params->dh);
96 : :
97 : 260 : const BIGNUM *p = s2n_get_p_dh_param(dh_params);
98 : 260 : const BIGNUM *g = s2n_get_g_dh_param(dh_params);
99 : :
100 [ - + ][ # # ]: 260 : POSIX_ENSURE_REF(g);
101 [ # # ][ - + ]: 260 : POSIX_ENSURE_REF(p);
102 : :
103 [ - + ][ # # ]: 260 : S2N_ERROR_IF(DH_size(dh_params->dh) < S2N_MIN_DH_PRIME_SIZE_BYTES, S2N_ERR_DH_PARAMS_CREATE);
104 [ - + ][ # # ]: 260 : S2N_ERROR_IF(BN_is_zero(g), S2N_ERR_DH_PARAMS_CREATE);
105 [ - + ][ # # ]: 260 : S2N_ERROR_IF(BN_is_zero(p), S2N_ERR_DH_PARAMS_CREATE);
106 : :
107 : 260 : return S2N_SUCCESS;
108 : 260 : }
109 : :
110 : : static int s2n_check_pub_key_dh_params(struct s2n_dh_params *dh_params)
111 : 78 : {
112 : 78 : const BIGNUM *pub_key = s2n_get_Ys_dh_param(dh_params);
113 [ - + ][ # # ]: 78 : POSIX_ENSURE_REF(pub_key);
114 : :
115 : : /*
116 : : * https://www.rfc-editor.org/rfc/rfc2631#section-2.1.5
117 : : *
118 : : * The following algorithm MAY be used to validate a received public
119 : : * key y.
120 : : *
121 : : * 1. Verify that y lies within the interval [2,p-1].
122 : : * If it does not, the key is invalid.
123 : : *
124 : : * This check is optional per the RFC, but applied here as
125 : : * defense-in-depth to reject degenerate public key values.
126 : : */
127 [ - + ][ # # ]: 78 : S2N_ERROR_IF(BN_is_zero(pub_key), S2N_ERR_DH_PARAMS_CREATE);
128 [ + + ][ + - ]: 78 : S2N_ERROR_IF(BN_is_one(pub_key), S2N_ERR_DH_PARAMS_CREATE);
129 : :
130 : 77 : const BIGNUM *p = s2n_get_p_dh_param(dh_params);
131 [ - + ][ # # ]: 77 : POSIX_ENSURE_REF(p);
132 : :
133 : 77 : BIGNUM *p_minus_one = BN_dup(p);
134 [ - + ][ # # ]: 77 : POSIX_ENSURE_REF(p_minus_one);
135 [ - + ]: 77 : if (!BN_sub_word(p_minus_one, 1)) {
136 : 0 : BN_free(p_minus_one);
137 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_DH_PARAMS_CREATE);
138 : 0 : }
139 : 77 : int cmp = BN_cmp(pub_key, p_minus_one);
140 : 77 : BN_free(p_minus_one);
141 [ + + ][ + - ]: 77 : S2N_ERROR_IF(cmp > 0, S2N_ERR_DH_PARAMS_CREATE);
142 : :
143 : 76 : return S2N_SUCCESS;
144 : 77 : }
145 : :
146 : : static int s2n_set_p_g_Ys_dh_params(struct s2n_dh_params *dh_params, struct s2n_blob *p, struct s2n_blob *g,
147 : : struct s2n_blob *Ys)
148 : 28 : {
149 [ # # ][ - + ]: 28 : POSIX_ENSURE(p->size <= INT_MAX, S2N_ERR_INTEGER_OVERFLOW);
150 [ - + ][ # # ]: 28 : POSIX_ENSURE(g->size <= INT_MAX, S2N_ERR_INTEGER_OVERFLOW);
151 [ # # ][ - + ]: 28 : POSIX_ENSURE(Ys->size <= INT_MAX, S2N_ERR_INTEGER_OVERFLOW);
152 : 28 : BIGNUM *bn_p = BN_bin2bn((const unsigned char *) p->data, p->size, NULL);
153 : 28 : BIGNUM *bn_g = BN_bin2bn((const unsigned char *) g->data, g->size, NULL);
154 : 28 : BIGNUM *bn_Ys = BN_bin2bn((const unsigned char *) Ys->data, Ys->size, NULL);
155 : :
156 : 28 : #if S2N_OPENSSL_VERSION_AT_LEAST(1, 1, 0)
157 : : /* Per https://www.openssl.org/docs/man1.1.0/crypto/DH_get0_pqg.html:
158 : : * values that have been passed in should not be freed directly after this function has been called
159 : : */
160 [ - + ][ # # ]: 28 : POSIX_GUARD_OSSL(DH_set0_pqg(dh_params->dh, bn_p, NULL, bn_g), S2N_ERR_DH_PARAMS_CREATE);
161 : :
162 : : /* Same as DH_set0_pqg */
163 [ - + ][ # # ]: 28 : POSIX_GUARD_OSSL(DH_set0_key(dh_params->dh, bn_Ys, NULL), S2N_ERR_DH_PARAMS_CREATE);
164 : : #else
165 : : dh_params->dh->p = bn_p;
166 : : dh_params->dh->g = bn_g;
167 : : dh_params->dh->pub_key = bn_Ys;
168 : : #endif
169 : :
170 : 28 : return S2N_SUCCESS;
171 : 28 : }
172 : :
173 : : int s2n_check_all_dh_params(struct s2n_dh_params *dh_params)
174 : 78 : {
175 [ - + ]: 78 : POSIX_GUARD(s2n_check_p_g_dh_params(dh_params));
176 [ + + ]: 78 : POSIX_GUARD(s2n_check_pub_key_dh_params(dh_params));
177 : :
178 : 76 : return S2N_SUCCESS;
179 : 78 : }
180 : :
181 : : int s2n_pkcs3_to_dh_params(struct s2n_dh_params *dh_params, struct s2n_blob *pkcs3)
182 : 85 : {
183 [ # # ][ - + ]: 85 : POSIX_ENSURE_REF(dh_params);
184 [ - + ][ + - ]: 85 : POSIX_PRECONDITION(s2n_blob_validate(pkcs3));
185 : 85 : DEFER_CLEANUP(struct s2n_dh_params temp_dh_params = { 0 }, s2n_dh_params_free);
186 : :
187 : 85 : uint8_t *original_ptr = pkcs3->data;
188 : 85 : temp_dh_params.dh = d2i_DHparams(NULL, (const unsigned char **) (void *) &pkcs3->data, pkcs3->size);
189 : :
190 [ + + ]: 85 : POSIX_GUARD(s2n_check_p_g_dh_params(&temp_dh_params));
191 : :
192 [ + - ]: 84 : if (pkcs3->data) {
193 [ - + ][ # # ]: 84 : POSIX_ENSURE_GTE(pkcs3->data, original_ptr);
194 [ - + ][ # # ]: 84 : POSIX_ENSURE((uint32_t) (pkcs3->data - original_ptr) == pkcs3->size, S2N_ERR_INVALID_PKCS3);
195 : 84 : }
196 : :
197 : 84 : pkcs3->data = original_ptr;
198 : :
199 : : /* Require at least 2048 bits for the DH size */
200 [ - + ][ # # ]: 84 : POSIX_ENSURE(DH_size(temp_dh_params.dh) >= S2N_MIN_DH_PRIME_SIZE_BYTES, S2N_ERR_DH_TOO_SMALL);
201 : :
202 : : /* Check the generator and prime */
203 [ - + ]: 84 : POSIX_GUARD(s2n_dh_params_check(&temp_dh_params));
204 : :
205 : 84 : dh_params->dh = temp_dh_params.dh;
206 : :
207 : 84 : ZERO_TO_DISABLE_DEFER_CLEANUP(temp_dh_params);
208 : :
209 : 84 : return S2N_SUCCESS;
210 : 84 : }
211 : :
212 : : int s2n_dh_p_g_Ys_to_dh_params(struct s2n_dh_params *server_dh_params, struct s2n_blob *p, struct s2n_blob *g,
213 : : struct s2n_blob *Ys)
214 : 28 : {
215 [ # # ][ - + ]: 28 : POSIX_ENSURE_REF(server_dh_params);
216 [ - + ][ + - ]: 28 : POSIX_PRECONDITION(s2n_blob_validate(p));
217 [ - + ][ + - ]: 28 : POSIX_PRECONDITION(s2n_blob_validate(g));
218 [ - + ][ + - ]: 28 : POSIX_PRECONDITION(s2n_blob_validate(Ys));
219 : :
220 : 28 : server_dh_params->dh = DH_new();
221 [ - + ][ # # ]: 28 : POSIX_ENSURE(server_dh_params->dh != NULL, S2N_ERR_DH_PARAMS_CREATE);
222 : :
223 [ - + ]: 28 : POSIX_GUARD(s2n_set_p_g_Ys_dh_params(server_dh_params, p, g, Ys));
224 [ + + ]: 28 : POSIX_GUARD(s2n_check_all_dh_params(server_dh_params));
225 : :
226 : 26 : return S2N_SUCCESS;
227 : 28 : }
228 : :
229 : : int s2n_dh_params_to_p_g_Ys(struct s2n_dh_params *server_dh_params, struct s2n_stuffer *out, struct s2n_blob *output)
230 : 25 : {
231 [ - + ]: 25 : POSIX_GUARD(s2n_check_all_dh_params(server_dh_params));
232 [ - + ][ + - ]: 25 : POSIX_PRECONDITION(s2n_stuffer_validate(out));
233 [ - + ][ + - ]: 25 : POSIX_PRECONDITION(s2n_blob_validate(output));
234 : :
235 : 25 : const BIGNUM *bn_p = s2n_get_p_dh_param(server_dh_params);
236 : 25 : const BIGNUM *bn_g = s2n_get_g_dh_param(server_dh_params);
237 : 25 : const BIGNUM *bn_Ys = s2n_get_Ys_dh_param(server_dh_params);
238 : :
239 : : /* Reject sizes that don't fit in the uint16 wire encoding before truncating. */
240 : 25 : int p_num_bytes = BN_num_bytes(bn_p);
241 : 25 : int g_num_bytes = BN_num_bytes(bn_g);
242 : 25 : int Ys_num_bytes = BN_num_bytes(bn_Ys);
243 [ # # ][ + - ]: 25 : POSIX_ENSURE(p_num_bytes >= 0 && p_num_bytes <= UINT16_MAX, S2N_ERR_DH_SERIALIZING);
[ + - ]
244 [ # # ][ + - ]: 25 : POSIX_ENSURE(g_num_bytes >= 0 && g_num_bytes <= UINT16_MAX, S2N_ERR_DH_SERIALIZING);
[ + - ]
245 [ # # ][ + - ]: 25 : POSIX_ENSURE(Ys_num_bytes >= 0 && Ys_num_bytes <= UINT16_MAX, S2N_ERR_DH_SERIALIZING);
[ + - ]
246 : :
247 : 25 : uint16_t p_size = p_num_bytes;
248 : 25 : uint16_t g_size = g_num_bytes;
249 : 25 : uint16_t Ys_size = Ys_num_bytes;
250 : 25 : uint8_t *p = NULL;
251 : 25 : uint8_t *g = NULL;
252 : 25 : uint8_t *Ys = NULL;
253 : :
254 : 25 : output->data = s2n_stuffer_raw_write(out, 0);
255 [ - + ][ # # ]: 25 : POSIX_ENSURE_REF(output->data);
256 : :
257 [ - + ]: 25 : POSIX_GUARD(s2n_stuffer_write_uint16(out, p_size));
258 : 25 : p = s2n_stuffer_raw_write(out, p_size);
259 [ - + ][ # # ]: 25 : POSIX_ENSURE_REF(p);
260 [ # # ][ - + ]: 25 : POSIX_ENSURE(BN_bn2bin(bn_p, p) == p_size, S2N_ERR_DH_SERIALIZING);
261 : :
262 [ - + ]: 25 : POSIX_GUARD(s2n_stuffer_write_uint16(out, g_size));
263 : 25 : g = s2n_stuffer_raw_write(out, g_size);
264 [ - + ][ # # ]: 25 : POSIX_ENSURE_REF(g);
265 [ - + ][ # # ]: 25 : POSIX_ENSURE(BN_bn2bin(bn_g, g) == g_size, S2N_ERR_DH_SERIALIZING);
266 : :
267 [ - + ]: 25 : POSIX_GUARD(s2n_stuffer_write_uint16(out, Ys_size));
268 : 25 : Ys = s2n_stuffer_raw_write(out, Ys_size);
269 [ - + ][ # # ]: 25 : POSIX_ENSURE_REF(Ys);
270 [ # # ][ - + ]: 25 : POSIX_ENSURE(BN_bn2bin(bn_Ys, Ys) == Ys_size, S2N_ERR_DH_SERIALIZING);
271 : :
272 : 25 : output->size = p_size + 2 + g_size + 2 + Ys_size + 2;
273 : :
274 : 25 : return S2N_SUCCESS;
275 : 25 : }
276 : :
277 : : int s2n_dh_compute_shared_secret_as_client(struct s2n_dh_params *server_dh_params, struct s2n_stuffer *Yc_out,
278 : : struct s2n_blob *shared_key)
279 : 24 : {
280 : 24 : struct s2n_dh_params client_params = { 0 };
281 : 24 : uint8_t *client_pub_key = NULL;
282 : 24 : uint16_t client_pub_key_size = 0;
283 : 24 : int shared_key_size = 0;
284 : :
285 [ - + ]: 24 : POSIX_GUARD(s2n_dh_params_check(server_dh_params));
286 [ - + ]: 24 : POSIX_GUARD(s2n_dh_params_copy(server_dh_params, &client_params));
287 [ - + ]: 24 : POSIX_GUARD(s2n_dh_generate_ephemeral_key(&client_params));
288 [ - + ]: 24 : POSIX_GUARD(s2n_alloc(shared_key, DH_size(server_dh_params->dh)));
289 : :
290 : 24 : const BIGNUM *client_pub_key_bn = s2n_get_Ys_dh_param(&client_params);
291 [ - + ][ # # ]: 24 : POSIX_ENSURE_REF(client_pub_key_bn);
292 : : /* Reject sizes that don't fit in the uint16 wire encoding before truncating. */
293 : 24 : int client_pub_key_num_bytes = BN_num_bytes(client_pub_key_bn);
294 [ - + ][ - + ]: 24 : if (client_pub_key_num_bytes < 0 || client_pub_key_num_bytes > UINT16_MAX) {
295 [ # # ]: 0 : POSIX_GUARD(s2n_free(shared_key));
296 [ # # ]: 0 : POSIX_GUARD(s2n_dh_params_free(&client_params));
297 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_DH_WRITING_PUBLIC_KEY);
298 : 0 : }
299 : 24 : client_pub_key_size = client_pub_key_num_bytes;
300 [ - + ]: 24 : POSIX_GUARD(s2n_stuffer_write_uint16(Yc_out, client_pub_key_size));
301 : 24 : client_pub_key = s2n_stuffer_raw_write(Yc_out, client_pub_key_size);
302 [ - + ]: 24 : if (client_pub_key == NULL) {
303 [ # # ]: 0 : POSIX_GUARD(s2n_free(shared_key));
304 [ # # ]: 0 : POSIX_GUARD(s2n_dh_params_free(&client_params));
305 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_DH_WRITING_PUBLIC_KEY);
306 : 0 : }
307 : :
308 [ - + ]: 24 : if (BN_bn2bin(client_pub_key_bn, client_pub_key) != client_pub_key_size) {
309 [ # # ]: 0 : POSIX_GUARD(s2n_free(shared_key));
310 [ # # ]: 0 : POSIX_GUARD(s2n_dh_params_free(&client_params));
311 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_DH_COPYING_PUBLIC_KEY);
312 : 0 : }
313 : :
314 : : /* server_dh_params already validated */
315 : 24 : const BIGNUM *server_pub_key_bn = s2n_get_Ys_dh_param(server_dh_params);
316 : 24 : int server_dh_params_size = DH_size(server_dh_params->dh);
317 : 24 : shared_key_size = DH_compute_key(shared_key->data, server_pub_key_bn, client_params.dh);
318 [ - + ]: 24 : if (shared_key_size < 0) {
319 [ # # ]: 0 : POSIX_GUARD(s2n_free(shared_key));
320 [ # # ]: 0 : POSIX_GUARD(s2n_dh_params_free(&client_params));
321 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_DH_SHARED_SECRET);
322 : 0 : }
323 : :
324 : 24 : s2n_dh_pad_shared_secret(shared_key, shared_key_size, server_dh_params_size);
325 : :
326 [ - + ]: 24 : POSIX_GUARD(s2n_dh_params_free(&client_params));
327 : :
328 : 24 : return S2N_SUCCESS;
329 : 24 : }
330 : :
331 : : int s2n_dh_compute_shared_secret_as_server(struct s2n_dh_params *server_dh_params, struct s2n_stuffer *Yc_in,
332 : : struct s2n_blob *shared_key)
333 : 25 : {
334 : 25 : uint16_t Yc_length = 0;
335 : 25 : struct s2n_blob Yc = { 0 };
336 : 25 : int shared_key_size = 0;
337 : 25 : DEFER_CLEANUP(BIGNUM *pub_key = NULL, BN_free_pointer);
338 : :
339 [ - + ]: 25 : POSIX_GUARD(s2n_check_all_dh_params(server_dh_params));
340 : 25 : int server_dh_params_size = DH_size(server_dh_params->dh);
341 [ # # ][ - + ]: 25 : POSIX_ENSURE(server_dh_params_size <= INT32_MAX, S2N_ERR_INTEGER_OVERFLOW);
342 : :
343 : : /*
344 : : * As defined in https://www.rfc-editor.org/rfc/rfc5246#section-7.4.7.2,
345 : : * the client's DH public value (Yc) is sent as a variable-length opaque value.
346 : : * Validate that Yc_length does not exceed the DH group size to prevent
347 : : * unnecessary computation and memory allocation on oversized keys.
348 : : *
349 : : * According to https://www.rfc-editor.org/rfc/rfc2631#section-2.1.5,
350 : : * the valid range of Yc is [2, p-1]. When encoding a BIGNUM to bytes,
351 : : * leading zeros are often stripped, in which case Yc_length might be
352 : : * less than server_dh_params_size.
353 : : */
354 [ - + ]: 25 : POSIX_GUARD(s2n_stuffer_read_uint16(Yc_in, &Yc_length));
355 [ - + ][ # # ]: 25 : POSIX_ENSURE(Yc_length > 0, S2N_ERR_DH_SHARED_SECRET);
356 [ + - ][ + + ]: 25 : POSIX_ENSURE((int) Yc_length <= server_dh_params_size, S2N_ERR_DH_SHARED_SECRET);
357 : :
358 : 24 : Yc.size = Yc_length;
359 : 24 : Yc.data = s2n_stuffer_raw_read(Yc_in, Yc.size);
360 [ - + ][ # # ]: 24 : POSIX_ENSURE_REF(Yc.data);
361 : :
362 : 24 : pub_key = BN_bin2bn((const unsigned char *) Yc.data, Yc.size, NULL);
363 [ # # ][ - + ]: 24 : POSIX_ENSURE_REF(pub_key);
364 [ - + ]: 24 : POSIX_GUARD(s2n_alloc(shared_key, server_dh_params_size));
365 : :
366 : 24 : shared_key_size = DH_compute_key(shared_key->data, pub_key, server_dh_params->dh);
367 [ # # ][ - + ]: 24 : POSIX_ENSURE(shared_key_size > 0, S2N_ERR_DH_SHARED_SECRET);
368 : :
369 : 24 : s2n_dh_pad_shared_secret(shared_key, shared_key_size, server_dh_params_size);
370 : :
371 : 24 : return S2N_SUCCESS;
372 : 24 : }
373 : :
374 : : int s2n_dh_params_check(struct s2n_dh_params *dh_params)
375 : 108 : {
376 [ # # ][ - + ]: 108 : POSIX_ENSURE_REF(dh_params);
377 [ - + ][ # # ]: 108 : POSIX_ENSURE_REF(dh_params->dh);
378 : 108 : int codes = 0;
379 : :
380 [ # # ][ - + ]: 108 : POSIX_GUARD_OSSL(DH_check(dh_params->dh, &codes), S2N_ERR_DH_PARAMETER_CHECK);
381 [ - + ][ # # ]: 108 : POSIX_ENSURE(codes == 0, S2N_ERR_DH_PARAMETER_CHECK);
382 : :
383 : 108 : return S2N_SUCCESS;
384 : 108 : }
385 : :
386 : : int s2n_dh_params_copy(struct s2n_dh_params *from, struct s2n_dh_params *to)
387 : 48 : {
388 [ - + ]: 48 : POSIX_GUARD(s2n_check_p_g_dh_params(from));
389 [ # # ][ - + ]: 48 : POSIX_ENSURE_REF(to);
390 : :
391 : 48 : to->dh = DHparams_dup(from->dh);
392 [ # # ][ - + ]: 48 : POSIX_ENSURE(to->dh != NULL, S2N_ERR_DH_COPYING_PARAMETERS);
393 : :
394 : 48 : return S2N_SUCCESS;
395 : 48 : }
396 : :
397 : : int s2n_dh_generate_ephemeral_key(struct s2n_dh_params *dh_params)
398 : 50 : {
399 [ - + ]: 50 : POSIX_GUARD(s2n_check_p_g_dh_params(dh_params));
400 : :
401 [ - + ][ # # ]: 50 : POSIX_GUARD_OSSL(DH_generate_key(dh_params->dh), S2N_ERR_DH_GENERATING_PARAMETERS);
402 : :
403 : 50 : return S2N_SUCCESS;
404 : 50 : }
405 : :
406 : : int s2n_dh_params_free(struct s2n_dh_params *dh_params)
407 : 3553085 : {
408 [ - + ][ # # ]: 3553085 : POSIX_ENSURE_REF(dh_params);
409 : 3553085 : DH_free(dh_params->dh);
410 : 3553085 : dh_params->dh = NULL;
411 : :
412 : 3553085 : return S2N_SUCCESS;
413 : 3553085 : }
|