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