Branch data Line data Source code
1 : : /*
2 : : * Elliptic curve Diffie-Hellman
3 : : *
4 : : * Copyright The Mbed TLS Contributors
5 : : * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 : : */
7 : :
8 : : /*
9 : : * References:
10 : : *
11 : : * SEC1 https://www.secg.org/sec1-v2.pdf
12 : : * RFC 4492
13 : : */
14 : :
15 : : #include "common.h"
16 : :
17 : : #if defined(MBEDTLS_ECDH_C)
18 : :
19 : : #include "mbedtls/ecdh.h"
20 : : #include "mbedtls/platform_util.h"
21 : : #include "mbedtls/error.h"
22 : :
23 : : #include <string.h>
24 : :
25 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
26 : : typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
27 : : #endif
28 : :
29 : 8 : static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
30 : : const mbedtls_ecdh_context *ctx)
31 : : {
32 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
33 : : return ctx->grp.id;
34 : : #else
35 : 8 : return ctx->grp_id;
36 : : #endif
37 : : }
38 : :
39 : 0 : int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
40 : : {
41 : : /* At this time, all groups support ECDH. */
42 : 0 : (void) gid;
43 : 0 : return 1;
44 : : }
45 : :
46 : : #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
47 : : /*
48 : : * Generate public key (restartable version)
49 : : *
50 : : * Note: this internal function relies on its caller preserving the value of
51 : : * the output parameter 'd' across continuation calls. This would not be
52 : : * acceptable for a public function but is OK here as we control call sites.
53 : : */
54 : 0 : static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
55 : : mbedtls_mpi *d, mbedtls_ecp_point *Q,
56 : : int (*f_rng)(void *, unsigned char *, size_t),
57 : : void *p_rng,
58 : : mbedtls_ecp_restart_ctx *rs_ctx)
59 : : {
60 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
61 : :
62 : 0 : int restarting = 0;
63 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
64 : : restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
65 : : #endif
66 : : /* If multiplication is in progress, we already generated a privkey */
67 : 0 : if (!restarting) {
68 [ # # ]: 0 : MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
69 : : }
70 : :
71 : 0 : MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
72 : : f_rng, p_rng, rs_ctx));
73 : :
74 : 0 : cleanup:
75 : 0 : return ret;
76 : : }
77 : :
78 : : /*
79 : : * Generate public key
80 : : */
81 : 0 : int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
82 : : int (*f_rng)(void *, unsigned char *, size_t),
83 : : void *p_rng)
84 : : {
85 : 0 : return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
86 : : }
87 : : #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
88 : :
89 : : #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
90 : : /*
91 : : * Compute shared secret (SEC1 3.3.1)
92 : : */
93 : 4 : static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
94 : : mbedtls_mpi *z,
95 : : const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
96 : : int (*f_rng)(void *, unsigned char *, size_t),
97 : : void *p_rng,
98 : : mbedtls_ecp_restart_ctx *rs_ctx)
99 : : {
100 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101 : 4 : mbedtls_ecp_point P;
102 : :
103 : 4 : mbedtls_ecp_point_init(&P);
104 : :
105 [ - + ]: 4 : MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
106 : : f_rng, p_rng, rs_ctx));
107 : :
108 [ - + ]: 4 : if (mbedtls_ecp_is_zero(&P)) {
109 : 0 : ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
110 : 0 : goto cleanup;
111 : : }
112 : :
113 : 4 : MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
114 : :
115 : 4 : cleanup:
116 : 4 : mbedtls_ecp_point_free(&P);
117 : :
118 : 4 : return ret;
119 : : }
120 : :
121 : : /*
122 : : * Compute shared secret (SEC1 3.3.1)
123 : : */
124 : 4 : int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
125 : : const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
126 : : int (*f_rng)(void *, unsigned char *, size_t),
127 : : void *p_rng)
128 : : {
129 : 4 : return ecdh_compute_shared_restartable(grp, z, Q, d,
130 : : f_rng, p_rng, NULL);
131 : : }
132 : : #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
133 : :
134 : 4 : static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
135 : : {
136 : 4 : mbedtls_ecp_group_init(&ctx->grp);
137 : 4 : mbedtls_mpi_init(&ctx->d);
138 : 4 : mbedtls_ecp_point_init(&ctx->Q);
139 : 4 : mbedtls_ecp_point_init(&ctx->Qp);
140 : 4 : mbedtls_mpi_init(&ctx->z);
141 : :
142 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
143 : : mbedtls_ecp_restart_init(&ctx->rs);
144 : : #endif
145 : 4 : }
146 : :
147 : 0 : mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
148 : : {
149 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
150 : : return ctx->MBEDTLS_PRIVATE(grp).id;
151 : : #else
152 : 0 : return ctx->MBEDTLS_PRIVATE(grp_id);
153 : : #endif
154 : : }
155 : :
156 : : /*
157 : : * Initialize context
158 : : */
159 : 4 : void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
160 : : {
161 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
162 : : ecdh_init_internal(ctx);
163 : : mbedtls_ecp_point_init(&ctx->Vi);
164 : : mbedtls_ecp_point_init(&ctx->Vf);
165 : : mbedtls_mpi_init(&ctx->_d);
166 : : #else
167 : 4 : memset(ctx, 0, sizeof(mbedtls_ecdh_context));
168 : :
169 : 4 : ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
170 : : #endif
171 : 4 : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
172 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
173 : : ctx->restart_enabled = 0;
174 : : #endif
175 : 4 : }
176 : :
177 : 4 : static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
178 : : mbedtls_ecp_group_id grp_id)
179 : : {
180 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
181 : :
182 : 4 : ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
183 [ - + ]: 4 : if (ret != 0) {
184 : 0 : return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
185 : : }
186 : :
187 : : return 0;
188 : : }
189 : :
190 : : /*
191 : : * Setup context
192 : : */
193 : 4 : int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
194 : : {
195 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
196 : : return ecdh_setup_internal(ctx, grp_id);
197 : : #else
198 : 4 : switch (grp_id) {
199 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
200 : : case MBEDTLS_ECP_DP_CURVE25519:
201 : : ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
202 : : ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
203 : : ctx->grp_id = grp_id;
204 : : return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
205 : : #endif
206 : : default:
207 : 4 : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
208 : 4 : ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
209 : 4 : ctx->grp_id = grp_id;
210 : 4 : ecdh_init_internal(&ctx->ctx.mbed_ecdh);
211 : 4 : return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
212 : : }
213 : : #endif
214 : : }
215 : :
216 : 4 : static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
217 : : {
218 : 4 : mbedtls_ecp_group_free(&ctx->grp);
219 : 4 : mbedtls_mpi_free(&ctx->d);
220 : 4 : mbedtls_ecp_point_free(&ctx->Q);
221 : 4 : mbedtls_ecp_point_free(&ctx->Qp);
222 : 4 : mbedtls_mpi_free(&ctx->z);
223 : :
224 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
225 : : mbedtls_ecp_restart_free(&ctx->rs);
226 : : #endif
227 : 4 : }
228 : :
229 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
230 : : /*
231 : : * Enable restartable operations for context
232 : : */
233 : : void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
234 : : {
235 : : ctx->restart_enabled = 1;
236 : : }
237 : : #endif
238 : :
239 : : /*
240 : : * Free context
241 : : */
242 : 4 : void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
243 : : {
244 [ + - ]: 4 : if (ctx == NULL) {
245 : : return;
246 : : }
247 : :
248 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
249 : : mbedtls_ecp_point_free(&ctx->Vi);
250 : : mbedtls_ecp_point_free(&ctx->Vf);
251 : : mbedtls_mpi_free(&ctx->_d);
252 : : ecdh_free_internal(ctx);
253 : : #else
254 [ + - ]: 4 : switch (ctx->var) {
255 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
256 : : case MBEDTLS_ECDH_VARIANT_EVEREST:
257 : : mbedtls_everest_free(&ctx->ctx.everest_ecdh);
258 : : break;
259 : : #endif
260 : 4 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
261 : 4 : ecdh_free_internal(&ctx->ctx.mbed_ecdh);
262 : 4 : break;
263 : : default:
264 : : break;
265 : : }
266 : :
267 : 4 : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
268 : 4 : ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
269 : 4 : ctx->grp_id = MBEDTLS_ECP_DP_NONE;
270 : : #endif
271 : : }
272 : :
273 : 0 : static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
274 : : size_t *olen, int point_format,
275 : : unsigned char *buf, size_t blen,
276 : : int (*f_rng)(void *,
277 : : unsigned char *,
278 : : size_t),
279 : : void *p_rng,
280 : : int restart_enabled)
281 : : {
282 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
283 : 0 : size_t grp_len, pt_len;
284 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
285 : : mbedtls_ecp_restart_ctx *rs_ctx = NULL;
286 : : #endif
287 : :
288 [ # # ]: 0 : if (ctx->grp.pbits == 0) {
289 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
290 : : }
291 : :
292 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
293 : : if (restart_enabled) {
294 : : rs_ctx = &ctx->rs;
295 : : }
296 : : #else
297 : 0 : (void) restart_enabled;
298 : : #endif
299 : :
300 : :
301 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
302 : : if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
303 : : f_rng, p_rng, rs_ctx)) != 0) {
304 : : return ret;
305 : : }
306 : : #else
307 [ # # ]: 0 : if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
308 : : f_rng, p_rng)) != 0) {
309 : : return ret;
310 : : }
311 : : #endif /* MBEDTLS_ECP_RESTARTABLE */
312 : :
313 [ # # ]: 0 : if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
314 : : blen)) != 0) {
315 : : return ret;
316 : : }
317 : :
318 : 0 : buf += grp_len;
319 : 0 : blen -= grp_len;
320 : :
321 [ # # ]: 0 : if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
322 : : &pt_len, buf, blen)) != 0) {
323 : : return ret;
324 : : }
325 : :
326 : 0 : *olen = grp_len + pt_len;
327 : 0 : return 0;
328 : : }
329 : :
330 : : /*
331 : : * Setup and write the ServerKeyExchange parameters (RFC 4492)
332 : : * struct {
333 : : * ECParameters curve_params;
334 : : * ECPoint public;
335 : : * } ServerECDHParams;
336 : : */
337 : 0 : int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
338 : : unsigned char *buf, size_t blen,
339 : : int (*f_rng)(void *, unsigned char *, size_t),
340 : : void *p_rng)
341 : : {
342 : 0 : int restart_enabled = 0;
343 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
344 : : restart_enabled = ctx->restart_enabled;
345 : : #else
346 : 0 : (void) restart_enabled;
347 : : #endif
348 : :
349 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
350 : : return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
351 : : f_rng, p_rng, restart_enabled);
352 : : #else
353 [ # # ]: 0 : switch (ctx->var) {
354 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
355 : : case MBEDTLS_ECDH_VARIANT_EVEREST:
356 : : return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
357 : : buf, blen, f_rng, p_rng);
358 : : #endif
359 : 0 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
360 : 0 : return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
361 : 0 : ctx->point_format, buf, blen,
362 : : f_rng, p_rng,
363 : : restart_enabled);
364 : : default:
365 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
366 : : }
367 : : #endif
368 : : }
369 : :
370 : 0 : static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
371 : : const unsigned char **buf,
372 : : const unsigned char *end)
373 : : {
374 : 0 : return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
375 : 0 : (size_t) (end - *buf));
376 : : }
377 : :
378 : : /*
379 : : * Read the ServerKeyExchange parameters (RFC 4492)
380 : : * struct {
381 : : * ECParameters curve_params;
382 : : * ECPoint public;
383 : : * } ServerECDHParams;
384 : : */
385 : 0 : int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
386 : : const unsigned char **buf,
387 : : const unsigned char *end)
388 : : {
389 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
390 : 0 : mbedtls_ecp_group_id grp_id;
391 [ # # ]: 0 : if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
392 : : != 0) {
393 : : return ret;
394 : : }
395 : :
396 [ # # ]: 0 : if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
397 : : return ret;
398 : : }
399 : :
400 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
401 : : return ecdh_read_params_internal(ctx, buf, end);
402 : : #else
403 [ # # ]: 0 : switch (ctx->var) {
404 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
405 : : case MBEDTLS_ECDH_VARIANT_EVEREST:
406 : : return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
407 : : buf, end);
408 : : #endif
409 : 0 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
410 : 0 : return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
411 : : buf, end);
412 : : default:
413 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
414 : : }
415 : : #endif
416 : : }
417 : :
418 : 8 : static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
419 : : const mbedtls_ecp_keypair *key,
420 : : mbedtls_ecdh_side side)
421 : : {
422 : 8 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
423 : :
424 : : /* If it's not our key, just import the public part as Qp */
425 [ + + ]: 8 : if (side == MBEDTLS_ECDH_THEIRS) {
426 : 4 : return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
427 : : }
428 : :
429 : : /* Our key: import public (as Q) and private parts */
430 [ + - ]: 4 : if (side != MBEDTLS_ECDH_OURS) {
431 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
432 : : }
433 : :
434 [ + - ]: 4 : if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
435 [ - + ]: 4 : (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
436 : 0 : return ret;
437 : : }
438 : :
439 : : return 0;
440 : : }
441 : :
442 : : /*
443 : : * Get parameters from a keypair
444 : : */
445 : 8 : int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
446 : : const mbedtls_ecp_keypair *key,
447 : : mbedtls_ecdh_side side)
448 : : {
449 : 8 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
450 [ - + ]: 8 : if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
451 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
452 : : }
453 : :
454 [ + + ]: 8 : if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
455 : : /* This is the first call to get_params(). Set up the context
456 : : * for use with the group. */
457 [ + - ]: 4 : if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
458 : : return ret;
459 : : }
460 : : } else {
461 : : /* This is not the first call to get_params(). Check that the
462 : : * current key's group is the same as the context's, which was set
463 : : * from the first key's group. */
464 [ - + ]: 4 : if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
465 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
466 : : }
467 : : }
468 : :
469 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
470 : : return ecdh_get_params_internal(ctx, key, side);
471 : : #else
472 [ - + ]: 8 : switch (ctx->var) {
473 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
474 : : case MBEDTLS_ECDH_VARIANT_EVEREST:
475 : : {
476 : : mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
477 : : MBEDTLS_EVEREST_ECDH_OURS :
478 : : MBEDTLS_EVEREST_ECDH_THEIRS;
479 : : return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
480 : : key, s);
481 : : }
482 : : #endif
483 : 8 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
484 : 8 : return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
485 : : key, side);
486 : : default:
487 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
488 : : }
489 : : #endif
490 : : }
491 : :
492 : 0 : static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
493 : : size_t *olen, int point_format,
494 : : unsigned char *buf, size_t blen,
495 : : int (*f_rng)(void *,
496 : : unsigned char *,
497 : : size_t),
498 : : void *p_rng,
499 : : int restart_enabled)
500 : : {
501 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
502 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
503 : : mbedtls_ecp_restart_ctx *rs_ctx = NULL;
504 : : #endif
505 : :
506 [ # # ]: 0 : if (ctx->grp.pbits == 0) {
507 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
508 : : }
509 : :
510 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
511 : : if (restart_enabled) {
512 : : rs_ctx = &ctx->rs;
513 : : }
514 : : #else
515 : 0 : (void) restart_enabled;
516 : : #endif
517 : :
518 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
519 : : if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
520 : : f_rng, p_rng, rs_ctx)) != 0) {
521 : : return ret;
522 : : }
523 : : #else
524 [ # # ]: 0 : if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
525 : : f_rng, p_rng)) != 0) {
526 : : return ret;
527 : : }
528 : : #endif /* MBEDTLS_ECP_RESTARTABLE */
529 : :
530 : 0 : return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
531 : : buf, blen);
532 : : }
533 : :
534 : : /*
535 : : * Setup and export the client public value
536 : : */
537 : 0 : int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
538 : : unsigned char *buf, size_t blen,
539 : : int (*f_rng)(void *, unsigned char *, size_t),
540 : : void *p_rng)
541 : : {
542 : 0 : int restart_enabled = 0;
543 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
544 : : restart_enabled = ctx->restart_enabled;
545 : : #endif
546 : :
547 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
548 : : return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
549 : : f_rng, p_rng, restart_enabled);
550 : : #else
551 [ # # ]: 0 : switch (ctx->var) {
552 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
553 : : case MBEDTLS_ECDH_VARIANT_EVEREST:
554 : : return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
555 : : buf, blen, f_rng, p_rng);
556 : : #endif
557 : 0 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
558 : 0 : return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
559 : 0 : ctx->point_format, buf, blen,
560 : : f_rng, p_rng,
561 : : restart_enabled);
562 : : default:
563 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
564 : : }
565 : : #endif
566 : : }
567 : :
568 : 0 : static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
569 : : const unsigned char *buf, size_t blen)
570 : : {
571 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
572 : 0 : const unsigned char *p = buf;
573 : :
574 [ # # ]: 0 : if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
575 : : blen)) != 0) {
576 : : return ret;
577 : : }
578 : :
579 [ # # ]: 0 : if ((size_t) (p - buf) != blen) {
580 : 0 : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
581 : : }
582 : :
583 : : return 0;
584 : : }
585 : :
586 : : /*
587 : : * Parse and import the client's public value
588 : : */
589 : 0 : int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
590 : : const unsigned char *buf, size_t blen)
591 : : {
592 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
593 : : return ecdh_read_public_internal(ctx, buf, blen);
594 : : #else
595 [ # # ]: 0 : switch (ctx->var) {
596 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
597 : : case MBEDTLS_ECDH_VARIANT_EVEREST:
598 : : return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
599 : : buf, blen);
600 : : #endif
601 : 0 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
602 : 0 : return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
603 : : buf, blen);
604 : : default:
605 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
606 : : }
607 : : #endif
608 : : }
609 : :
610 : 4 : static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
611 : : size_t *olen, unsigned char *buf,
612 : : size_t blen,
613 : : int (*f_rng)(void *,
614 : : unsigned char *,
615 : : size_t),
616 : : void *p_rng,
617 : : int restart_enabled)
618 : : {
619 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
620 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
621 : : mbedtls_ecp_restart_ctx *rs_ctx = NULL;
622 : : #endif
623 : :
624 [ + - - + ]: 4 : if (ctx == NULL || ctx->grp.pbits == 0) {
625 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
626 : : }
627 : :
628 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
629 : : if (restart_enabled) {
630 : : rs_ctx = &ctx->rs;
631 : : }
632 : : #else
633 : 4 : (void) restart_enabled;
634 : : #endif
635 : :
636 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
637 : : if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
638 : : &ctx->d, f_rng, p_rng,
639 : : rs_ctx)) != 0) {
640 : : return ret;
641 : : }
642 : : #else
643 [ + - ]: 4 : if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
644 : 4 : &ctx->d, f_rng, p_rng)) != 0) {
645 : : return ret;
646 : : }
647 : : #endif /* MBEDTLS_ECP_RESTARTABLE */
648 : :
649 [ - + ]: 4 : if (mbedtls_mpi_size(&ctx->z) > blen) {
650 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651 : : }
652 : :
653 : 4 : *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
654 : :
655 [ - + ]: 4 : if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
656 : 0 : return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
657 : : }
658 : :
659 : 4 : return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
660 : : }
661 : :
662 : : /*
663 : : * Derive and export the shared secret
664 : : */
665 : 4 : int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
666 : : unsigned char *buf, size_t blen,
667 : : int (*f_rng)(void *, unsigned char *, size_t),
668 : : void *p_rng)
669 : : {
670 : 4 : int restart_enabled = 0;
671 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
672 : : restart_enabled = ctx->restart_enabled;
673 : : #endif
674 : :
675 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
676 : : return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
677 : : restart_enabled);
678 : : #else
679 [ + - ]: 4 : switch (ctx->var) {
680 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
681 : : case MBEDTLS_ECDH_VARIANT_EVEREST:
682 : : return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
683 : : buf, blen, f_rng, p_rng);
684 : : #endif
685 : 4 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
686 : 4 : return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
687 : : blen, f_rng, p_rng,
688 : : restart_enabled);
689 : : default:
690 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
691 : : }
692 : : #endif
693 : : }
694 : : #endif /* MBEDTLS_ECDH_C */
|