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