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