• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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