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 1074 : static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
30 : const mbedtls_ecdh_context *ctx)
31 : {
32 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
33 1074 : return ctx->grp.id;
34 : #else
35 : 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 : (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 168 : 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 168 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
61 :
62 168 : int restarting = 0;
63 : #if defined(MBEDTLS_ECP_RESTARTABLE)
64 168 : restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
65 : #endif
66 : /* If multiplication is in progress, we already generated a privkey */
67 168 : if (!restarting) {
68 168 : MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
69 : }
70 :
71 168 : MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
72 : f_rng, p_rng, rs_ctx));
73 :
74 168 : cleanup:
75 168 : return ret;
76 : }
77 :
78 : /*
79 : * Generate public key
80 : */
81 168 : 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 168 : 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 75 : 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 75 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101 : mbedtls_ecp_point P;
102 :
103 75 : mbedtls_ecp_point_init(&P);
104 :
105 75 : MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
106 : f_rng, p_rng, rs_ctx));
107 :
108 75 : if (mbedtls_ecp_is_zero(&P)) {
109 0 : ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
110 0 : goto cleanup;
111 : }
112 :
113 75 : MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
114 :
115 75 : cleanup:
116 75 : mbedtls_ecp_point_free(&P);
117 :
118 75 : return ret;
119 : }
120 :
121 : /*
122 : * Compute shared secret (SEC1 3.3.1)
123 : */
124 75 : 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 75 : 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 1244 : static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
135 : {
136 1244 : mbedtls_ecp_group_init(&ctx->grp);
137 1244 : mbedtls_mpi_init(&ctx->d);
138 1244 : mbedtls_ecp_point_init(&ctx->Q);
139 1244 : mbedtls_ecp_point_init(&ctx->Qp);
140 1244 : mbedtls_mpi_init(&ctx->z);
141 :
142 : #if defined(MBEDTLS_ECP_RESTARTABLE)
143 1244 : mbedtls_ecp_restart_init(&ctx->rs);
144 : #endif
145 1244 : }
146 :
147 470 : mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
148 : {
149 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
150 470 : return ctx->MBEDTLS_PRIVATE(grp).id;
151 : #else
152 : return ctx->MBEDTLS_PRIVATE(grp_id);
153 : #endif
154 : }
155 :
156 : /*
157 : * Initialize context
158 : */
159 1244 : void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
160 : {
161 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
162 1244 : ecdh_init_internal(ctx);
163 1244 : mbedtls_ecp_point_init(&ctx->Vi);
164 1244 : mbedtls_ecp_point_init(&ctx->Vf);
165 1244 : mbedtls_mpi_init(&ctx->_d);
166 : #else
167 : memset(ctx, 0, sizeof(mbedtls_ecdh_context));
168 :
169 : ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
170 : #endif
171 1244 : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
172 : #if defined(MBEDTLS_ECP_RESTARTABLE)
173 1244 : ctx->restart_enabled = 0;
174 : #endif
175 1244 : }
176 :
177 1244 : static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
178 : mbedtls_ecp_group_id grp_id)
179 : {
180 1244 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
181 :
182 1244 : ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
183 1244 : if (ret != 0) {
184 0 : return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
185 : }
186 :
187 1244 : return 0;
188 : }
189 :
190 : /*
191 : * Setup context
192 : */
193 1244 : int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
194 : {
195 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
196 1244 : return ecdh_setup_internal(ctx, grp_id);
197 : #else
198 : 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 : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
208 : ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
209 : ctx->grp_id = grp_id;
210 : ecdh_init_internal(&ctx->ctx.mbed_ecdh);
211 : return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
212 : }
213 : #endif
214 : }
215 :
216 1026 : static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
217 : {
218 1026 : mbedtls_ecp_group_free(&ctx->grp);
219 1026 : mbedtls_mpi_free(&ctx->d);
220 1026 : mbedtls_ecp_point_free(&ctx->Q);
221 1026 : mbedtls_ecp_point_free(&ctx->Qp);
222 1026 : mbedtls_mpi_free(&ctx->z);
223 :
224 : #if defined(MBEDTLS_ECP_RESTARTABLE)
225 1026 : mbedtls_ecp_restart_free(&ctx->rs);
226 : #endif
227 1026 : }
228 :
229 : #if defined(MBEDTLS_ECP_RESTARTABLE)
230 : /*
231 : * Enable restartable operations for context
232 : */
233 0 : void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
234 : {
235 0 : ctx->restart_enabled = 1;
236 0 : }
237 : #endif
238 :
239 : /*
240 : * Free context
241 : */
242 1026 : void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
243 : {
244 1026 : if (ctx == NULL) {
245 0 : return;
246 : }
247 :
248 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
249 1026 : mbedtls_ecp_point_free(&ctx->Vi);
250 1026 : mbedtls_ecp_point_free(&ctx->Vf);
251 1026 : mbedtls_mpi_free(&ctx->_d);
252 1026 : ecdh_free_internal(ctx);
253 : #else
254 : 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 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
261 : ecdh_free_internal(&ctx->ctx.mbed_ecdh);
262 : break;
263 : default:
264 : break;
265 : }
266 :
267 : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
268 : ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
269 : 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 : size_t grp_len, pt_len;
284 : #if defined(MBEDTLS_ECP_RESTARTABLE)
285 0 : mbedtls_ecp_restart_ctx *rs_ctx = NULL;
286 : #endif
287 :
288 0 : if (ctx->grp.pbits == 0) {
289 0 : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
290 : }
291 :
292 : #if defined(MBEDTLS_ECP_RESTARTABLE)
293 0 : if (restart_enabled) {
294 0 : rs_ctx = &ctx->rs;
295 : }
296 : #else
297 : (void) restart_enabled;
298 : #endif
299 :
300 :
301 : #if defined(MBEDTLS_ECP_RESTARTABLE)
302 0 : if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
303 : f_rng, p_rng, rs_ctx)) != 0) {
304 0 : return ret;
305 : }
306 : #else
307 : 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 0 : 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 0 : 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 0 : restart_enabled = ctx->restart_enabled;
345 : #else
346 : (void) restart_enabled;
347 : #endif
348 :
349 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
350 0 : return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
351 : f_rng, p_rng, restart_enabled);
352 : #else
353 : 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 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
360 : return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
361 : 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 : 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 0 : return ret;
394 : }
395 :
396 0 : if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
397 0 : return ret;
398 : }
399 :
400 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
401 0 : return ecdh_read_params_internal(ctx, buf, end);
402 : #else
403 : 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 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
410 : 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 1074 : static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
419 : const mbedtls_ecp_keypair *key,
420 : mbedtls_ecdh_side side)
421 : {
422 1074 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
423 :
424 : /* If it's not our key, just import the public part as Qp */
425 1074 : if (side == MBEDTLS_ECDH_THEIRS) {
426 0 : return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
427 : }
428 :
429 : /* Our key: import public (as Q) and private parts */
430 1074 : if (side != MBEDTLS_ECDH_OURS) {
431 0 : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
432 : }
433 :
434 2148 : if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
435 1074 : (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
436 0 : return ret;
437 : }
438 :
439 1074 : return 0;
440 : }
441 :
442 : /*
443 : * Get parameters from a keypair
444 : */
445 1074 : int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
446 : const mbedtls_ecp_keypair *key,
447 : mbedtls_ecdh_side side)
448 : {
449 1074 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
450 1074 : if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
451 0 : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
452 : }
453 :
454 1074 : 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 1074 : if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
458 0 : 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 0 : if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
465 0 : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
466 : }
467 : }
468 :
469 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
470 1074 : return ecdh_get_params_internal(ctx, key, side);
471 : #else
472 : 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 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
484 : 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 0 : mbedtls_ecp_restart_ctx *rs_ctx = NULL;
504 : #endif
505 :
506 0 : if (ctx->grp.pbits == 0) {
507 0 : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
508 : }
509 :
510 : #if defined(MBEDTLS_ECP_RESTARTABLE)
511 0 : if (restart_enabled) {
512 0 : rs_ctx = &ctx->rs;
513 : }
514 : #else
515 : (void) restart_enabled;
516 : #endif
517 :
518 : #if defined(MBEDTLS_ECP_RESTARTABLE)
519 0 : if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
520 : f_rng, p_rng, rs_ctx)) != 0) {
521 0 : return ret;
522 : }
523 : #else
524 : 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 0 : restart_enabled = ctx->restart_enabled;
545 : #endif
546 :
547 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
548 0 : return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
549 : f_rng, p_rng, restart_enabled);
550 : #else
551 : 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 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
558 : return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
559 : 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 0 : return ret;
577 : }
578 :
579 0 : if ((size_t) (p - buf) != blen) {
580 0 : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
581 : }
582 :
583 0 : 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 0 : return ecdh_read_public_internal(ctx, buf, blen);
594 : #else
595 : 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 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
602 : 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 0 : 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 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
620 : #if defined(MBEDTLS_ECP_RESTARTABLE)
621 0 : mbedtls_ecp_restart_ctx *rs_ctx = NULL;
622 : #endif
623 :
624 0 : if (ctx == NULL || ctx->grp.pbits == 0) {
625 0 : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
626 : }
627 :
628 : #if defined(MBEDTLS_ECP_RESTARTABLE)
629 0 : if (restart_enabled) {
630 0 : rs_ctx = &ctx->rs;
631 : }
632 : #else
633 : (void) restart_enabled;
634 : #endif
635 :
636 : #if defined(MBEDTLS_ECP_RESTARTABLE)
637 0 : if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
638 0 : &ctx->d, f_rng, p_rng,
639 : rs_ctx)) != 0) {
640 0 : return ret;
641 : }
642 : #else
643 : if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
644 : &ctx->d, f_rng, p_rng)) != 0) {
645 : return ret;
646 : }
647 : #endif /* MBEDTLS_ECP_RESTARTABLE */
648 :
649 0 : if (mbedtls_mpi_size(&ctx->z) > blen) {
650 0 : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651 : }
652 :
653 0 : *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
654 :
655 0 : 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 0 : return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
660 : }
661 :
662 : /*
663 : * Derive and export the shared secret
664 : */
665 0 : 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 0 : int restart_enabled = 0;
671 : #if defined(MBEDTLS_ECP_RESTARTABLE)
672 0 : restart_enabled = ctx->restart_enabled;
673 : #endif
674 :
675 : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
676 0 : return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
677 : restart_enabled);
678 : #else
679 : 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 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
686 : 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 */
|