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
mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context * ctx)147 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 return ctx->MBEDTLS_PRIVATE(grp_id);
153 #endif
154 }
155
156 /*
157 * Initialize context
158 */
mbedtls_ecdh_init(mbedtls_ecdh_context * ctx)159 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 memset(ctx, 0, sizeof(mbedtls_ecdh_context));
168
169 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
170 #endif
171 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
172 #if defined(MBEDTLS_ECP_RESTARTABLE)
173 ctx->restart_enabled = 0;
174 #endif
175 }
176
ecdh_setup_internal(mbedtls_ecdh_context_mbed * ctx,mbedtls_ecp_group_id grp_id)177 static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
178 mbedtls_ecp_group_id grp_id)
179 {
180 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
181
182 ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
183 if (ret != 0) {
184 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
185 }
186
187 return 0;
188 }
189
190 /*
191 * Setup context
192 */
mbedtls_ecdh_setup(mbedtls_ecdh_context * ctx,mbedtls_ecp_group_id grp_id)193 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 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
ecdh_free_internal(mbedtls_ecdh_context_mbed * ctx)216 static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
217 {
218 mbedtls_ecp_group_free(&ctx->grp);
219 mbedtls_mpi_free(&ctx->d);
220 mbedtls_ecp_point_free(&ctx->Q);
221 mbedtls_ecp_point_free(&ctx->Qp);
222 mbedtls_mpi_free(&ctx->z);
223
224 #if defined(MBEDTLS_ECP_RESTARTABLE)
225 mbedtls_ecp_restart_free(&ctx->rs);
226 #endif
227 }
228
229 #if defined(MBEDTLS_ECP_RESTARTABLE)
230 /*
231 * Enable restartable operations for context
232 */
mbedtls_ecdh_enable_restart(mbedtls_ecdh_context * ctx)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 */
mbedtls_ecdh_free(mbedtls_ecdh_context * ctx)242 void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
243 {
244 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 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
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)273 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 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
283 size_t grp_len, pt_len;
284 #if defined(MBEDTLS_ECP_RESTARTABLE)
285 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
286 #endif
287
288 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 (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 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 if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
314 blen)) != 0) {
315 return ret;
316 }
317
318 buf += grp_len;
319 blen -= grp_len;
320
321 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 *olen = grp_len + pt_len;
327 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 */
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)337 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 int restart_enabled = 0;
343 #if defined(MBEDTLS_ECP_RESTARTABLE)
344 restart_enabled = ctx->restart_enabled;
345 #else
346 (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 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
ecdh_read_params_internal(mbedtls_ecdh_context_mbed * ctx,const unsigned char ** buf,const unsigned char * end)370 static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
371 const unsigned char **buf,
372 const unsigned char *end)
373 {
374 return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
375 (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 */
mbedtls_ecdh_read_params(mbedtls_ecdh_context * ctx,const unsigned char ** buf,const unsigned char * end)385 int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
386 const unsigned char **buf,
387 const unsigned char *end)
388 {
389 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
390 mbedtls_ecp_group_id grp_id;
391 if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
392 != 0) {
393 return ret;
394 }
395
396 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 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
ecdh_get_params_internal(mbedtls_ecdh_context_mbed * ctx,const mbedtls_ecp_keypair * key,mbedtls_ecdh_side side)418 static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
419 const mbedtls_ecp_keypair *key,
420 mbedtls_ecdh_side side)
421 {
422 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
423
424 /* If it's not our key, just import the public part as Qp */
425 if (side == MBEDTLS_ECDH_THEIRS) {
426 return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
427 }
428
429 /* Our key: import public (as Q) and private parts */
430 if (side != MBEDTLS_ECDH_OURS) {
431 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
432 }
433
434 if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
435 (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
436 return ret;
437 }
438
439 return 0;
440 }
441
442 /*
443 * Get parameters from a keypair
444 */
mbedtls_ecdh_get_params(mbedtls_ecdh_context * ctx,const mbedtls_ecp_keypair * key,mbedtls_ecdh_side side)445 int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
446 const mbedtls_ecp_keypair *key,
447 mbedtls_ecdh_side side)
448 {
449 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
450 if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
451 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
452 }
453
454 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 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 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 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
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)492 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 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 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 (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 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 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 */
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)537 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 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 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
ecdh_read_public_internal(mbedtls_ecdh_context_mbed * ctx,const unsigned char * buf,size_t blen)568 static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
569 const unsigned char *buf, size_t blen)
570 {
571 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
572 const unsigned char *p = buf;
573
574 if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
575 blen)) != 0) {
576 return ret;
577 }
578
579 if ((size_t) (p - buf) != blen) {
580 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 */
mbedtls_ecdh_read_public(mbedtls_ecdh_context * ctx,const unsigned char * buf,size_t blen)589 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 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
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)610 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 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 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 (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 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 if (mbedtls_mpi_size(&ctx->z) > blen) {
650 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651 }
652
653 *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
654
655 if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
656 return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
657 }
658
659 return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
660 }
661
662 /*
663 * Derive and export the shared secret
664 */
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)665 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 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 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 */
695