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