xref: /optee_os/lib/libmbedtls/mbedtls/library/ecdh.c (revision b0563631928755fe864b97785160fb3088e9efdc)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Elliptic curve Diffie-Hellman
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
5*b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6817466cbSJens Wiklander  */
7817466cbSJens Wiklander 
8817466cbSJens Wiklander /*
9817466cbSJens Wiklander  * References:
10817466cbSJens Wiklander  *
11*b0563631STom Van Eyck  * SEC1 https://www.secg.org/sec1-v2.pdf
12817466cbSJens Wiklander  * RFC 4492
13817466cbSJens Wiklander  */
14817466cbSJens Wiklander 
157901324dSJerome Forissier #include "common.h"
16817466cbSJens Wiklander 
17817466cbSJens Wiklander #if defined(MBEDTLS_ECDH_C)
18817466cbSJens Wiklander 
19817466cbSJens Wiklander #include "mbedtls/ecdh.h"
203d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
2111fa71b9SJerome Forissier #include "mbedtls/error.h"
22817466cbSJens Wiklander 
23817466cbSJens Wiklander #include <string.h>
24817466cbSJens Wiklander 
253d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
263d3b0591SJens Wiklander typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
273d3b0591SJens Wiklander #endif
283d3b0591SJens Wiklander 
mbedtls_ecdh_grp_id(const mbedtls_ecdh_context * ctx)295b25c76aSJerome Forissier static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
305b25c76aSJerome Forissier     const mbedtls_ecdh_context *ctx)
315b25c76aSJerome Forissier {
325b25c76aSJerome Forissier #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
3332b31808SJens Wiklander     return ctx->grp.id;
345b25c76aSJerome Forissier #else
3532b31808SJens Wiklander     return ctx->grp_id;
365b25c76aSJerome Forissier #endif
375b25c76aSJerome Forissier }
385b25c76aSJerome Forissier 
mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)3911fa71b9SJerome Forissier int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
4011fa71b9SJerome Forissier {
4111fa71b9SJerome Forissier     /* At this time, all groups support ECDH. */
4211fa71b9SJerome Forissier     (void) gid;
4332b31808SJens Wiklander     return 1;
4411fa71b9SJerome Forissier }
4511fa71b9SJerome Forissier 
463d3b0591SJens Wiklander #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
47817466cbSJens Wiklander /*
483d3b0591SJens Wiklander  * Generate public key (restartable version)
493d3b0591SJens Wiklander  *
503d3b0591SJens Wiklander  * Note: this internal function relies on its caller preserving the value of
513d3b0591SJens Wiklander  * the output parameter 'd' across continuation calls. This would not be
523d3b0591SJens Wiklander  * acceptable for a public function but is OK here as we control call sites.
533d3b0591SJens Wiklander  */
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)543d3b0591SJens Wiklander static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
553d3b0591SJens Wiklander                                        mbedtls_mpi *d, mbedtls_ecp_point *Q,
563d3b0591SJens Wiklander                                        int (*f_rng)(void *, unsigned char *, size_t),
573d3b0591SJens Wiklander                                        void *p_rng,
583d3b0591SJens Wiklander                                        mbedtls_ecp_restart_ctx *rs_ctx)
593d3b0591SJens Wiklander {
6011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
613d3b0591SJens Wiklander 
6232b31808SJens Wiklander     int restarting = 0;
633d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
6432b31808SJens Wiklander     restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
653d3b0591SJens Wiklander #endif
6632b31808SJens Wiklander     /* If multiplication is in progress, we already generated a privkey */
6732b31808SJens Wiklander     if (!restarting) {
683d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
6932b31808SJens Wiklander     }
703d3b0591SJens Wiklander 
713d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
723d3b0591SJens Wiklander                                                 f_rng, p_rng, rs_ctx));
733d3b0591SJens Wiklander 
743d3b0591SJens Wiklander cleanup:
7532b31808SJens Wiklander     return ret;
763d3b0591SJens Wiklander }
773d3b0591SJens Wiklander 
783d3b0591SJens Wiklander /*
793d3b0591SJens Wiklander  * Generate public key
80817466cbSJens Wiklander  */
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)81817466cbSJens Wiklander int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
82817466cbSJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t),
83817466cbSJens Wiklander                             void *p_rng)
84817466cbSJens Wiklander {
8532b31808SJens Wiklander     return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
86817466cbSJens Wiklander }
873d3b0591SJens Wiklander #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
88817466cbSJens Wiklander 
893d3b0591SJens Wiklander #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
90817466cbSJens Wiklander /*
91817466cbSJens Wiklander  * Compute shared secret (SEC1 3.3.1)
92817466cbSJens Wiklander  */
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)933d3b0591SJens Wiklander static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
943d3b0591SJens Wiklander                                            mbedtls_mpi *z,
95817466cbSJens Wiklander                                            const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
96817466cbSJens Wiklander                                            int (*f_rng)(void *, unsigned char *, size_t),
973d3b0591SJens Wiklander                                            void *p_rng,
983d3b0591SJens Wiklander                                            mbedtls_ecp_restart_ctx *rs_ctx)
99817466cbSJens Wiklander {
10011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101817466cbSJens Wiklander     mbedtls_ecp_point P;
102817466cbSJens Wiklander 
103817466cbSJens Wiklander     mbedtls_ecp_point_init(&P);
104817466cbSJens Wiklander 
1053d3b0591SJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
1063d3b0591SJens Wiklander                                                 f_rng, p_rng, rs_ctx));
107817466cbSJens Wiklander 
10832b31808SJens Wiklander     if (mbedtls_ecp_is_zero(&P)) {
109817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
110817466cbSJens Wiklander         goto cleanup;
111817466cbSJens Wiklander     }
112817466cbSJens Wiklander 
113817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
114817466cbSJens Wiklander 
115817466cbSJens Wiklander cleanup:
116817466cbSJens Wiklander     mbedtls_ecp_point_free(&P);
117817466cbSJens Wiklander 
11832b31808SJens Wiklander     return ret;
119817466cbSJens Wiklander }
120817466cbSJens Wiklander 
121817466cbSJens Wiklander /*
1223d3b0591SJens Wiklander  * Compute shared secret (SEC1 3.3.1)
1233d3b0591SJens Wiklander  */
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)1243d3b0591SJens Wiklander int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
1253d3b0591SJens Wiklander                                 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
1263d3b0591SJens Wiklander                                 int (*f_rng)(void *, unsigned char *, size_t),
1273d3b0591SJens Wiklander                                 void *p_rng)
1283d3b0591SJens Wiklander {
12932b31808SJens Wiklander     return ecdh_compute_shared_restartable(grp, z, Q, d,
13032b31808SJens Wiklander                                            f_rng, p_rng, NULL);
1313d3b0591SJens Wiklander }
1323d3b0591SJens Wiklander #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
1333d3b0591SJens Wiklander 
ecdh_init_internal(mbedtls_ecdh_context_mbed * ctx)1343d3b0591SJens Wiklander static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
1353d3b0591SJens Wiklander {
1363d3b0591SJens Wiklander     mbedtls_ecp_group_init(&ctx->grp);
1373d3b0591SJens Wiklander     mbedtls_mpi_init(&ctx->d);
1383d3b0591SJens Wiklander     mbedtls_ecp_point_init(&ctx->Q);
1393d3b0591SJens Wiklander     mbedtls_ecp_point_init(&ctx->Qp);
1403d3b0591SJens Wiklander     mbedtls_mpi_init(&ctx->z);
1413d3b0591SJens Wiklander 
1423d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
1433d3b0591SJens Wiklander     mbedtls_ecp_restart_init(&ctx->rs);
1443d3b0591SJens Wiklander #endif
1453d3b0591SJens Wiklander }
1463d3b0591SJens Wiklander 
mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context * ctx)147*b0563631STom Van Eyck mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
148*b0563631STom Van Eyck {
149*b0563631STom Van Eyck #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
150*b0563631STom Van Eyck     return ctx->MBEDTLS_PRIVATE(grp).id;
151*b0563631STom Van Eyck #else
152*b0563631STom Van Eyck     return ctx->MBEDTLS_PRIVATE(grp_id);
153*b0563631STom Van Eyck #endif
154*b0563631STom Van Eyck }
155*b0563631STom Van Eyck 
1563d3b0591SJens Wiklander /*
157817466cbSJens Wiklander  * Initialize context
158817466cbSJens Wiklander  */
mbedtls_ecdh_init(mbedtls_ecdh_context * ctx)159817466cbSJens Wiklander void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
160817466cbSJens Wiklander {
1613d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
1623d3b0591SJens Wiklander     ecdh_init_internal(ctx);
1633d3b0591SJens Wiklander     mbedtls_ecp_point_init(&ctx->Vi);
1643d3b0591SJens Wiklander     mbedtls_ecp_point_init(&ctx->Vf);
1653d3b0591SJens Wiklander     mbedtls_mpi_init(&ctx->_d);
1663d3b0591SJens Wiklander #else
167817466cbSJens Wiklander     memset(ctx, 0, sizeof(mbedtls_ecdh_context));
1683d3b0591SJens Wiklander 
1693d3b0591SJens Wiklander     ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
1703d3b0591SJens Wiklander #endif
1713d3b0591SJens Wiklander     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
1723d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
1733d3b0591SJens Wiklander     ctx->restart_enabled = 0;
1743d3b0591SJens Wiklander #endif
175817466cbSJens Wiklander }
176817466cbSJens Wiklander 
ecdh_setup_internal(mbedtls_ecdh_context_mbed * ctx,mbedtls_ecp_group_id grp_id)1773d3b0591SJens Wiklander static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
1783d3b0591SJens Wiklander                                mbedtls_ecp_group_id grp_id)
1793d3b0591SJens Wiklander {
18011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1813d3b0591SJens Wiklander 
1823d3b0591SJens Wiklander     ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
18332b31808SJens Wiklander     if (ret != 0) {
18432b31808SJens Wiklander         return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
1853d3b0591SJens Wiklander     }
1863d3b0591SJens Wiklander 
18732b31808SJens Wiklander     return 0;
1883d3b0591SJens Wiklander }
1893d3b0591SJens Wiklander 
1903d3b0591SJens Wiklander /*
1913d3b0591SJens Wiklander  * Setup context
1923d3b0591SJens Wiklander  */
mbedtls_ecdh_setup(mbedtls_ecdh_context * ctx,mbedtls_ecp_group_id grp_id)1933d3b0591SJens Wiklander int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
1943d3b0591SJens Wiklander {
1953d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
19632b31808SJens Wiklander     return ecdh_setup_internal(ctx, grp_id);
1973d3b0591SJens Wiklander #else
19832b31808SJens Wiklander     switch (grp_id) {
19911fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
20011fa71b9SJerome Forissier         case MBEDTLS_ECP_DP_CURVE25519:
20111fa71b9SJerome Forissier             ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
20211fa71b9SJerome Forissier             ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
20311fa71b9SJerome Forissier             ctx->grp_id = grp_id;
20432b31808SJens Wiklander             return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
20511fa71b9SJerome Forissier #endif
2063d3b0591SJens Wiklander         default:
2073d3b0591SJens Wiklander             ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
2083d3b0591SJens Wiklander             ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
2093d3b0591SJens Wiklander             ctx->grp_id = grp_id;
2103d3b0591SJens Wiklander             ecdh_init_internal(&ctx->ctx.mbed_ecdh);
21132b31808SJens Wiklander             return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
2123d3b0591SJens Wiklander     }
2133d3b0591SJens Wiklander #endif
2143d3b0591SJens Wiklander }
2153d3b0591SJens Wiklander 
ecdh_free_internal(mbedtls_ecdh_context_mbed * ctx)2163d3b0591SJens Wiklander static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
2173d3b0591SJens Wiklander {
2183d3b0591SJens Wiklander     mbedtls_ecp_group_free(&ctx->grp);
2193d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->d);
2203d3b0591SJens Wiklander     mbedtls_ecp_point_free(&ctx->Q);
2213d3b0591SJens Wiklander     mbedtls_ecp_point_free(&ctx->Qp);
2223d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->z);
2233d3b0591SJens Wiklander 
2243d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
2253d3b0591SJens Wiklander     mbedtls_ecp_restart_free(&ctx->rs);
2263d3b0591SJens Wiklander #endif
2273d3b0591SJens Wiklander }
2283d3b0591SJens Wiklander 
2293d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
2303d3b0591SJens Wiklander /*
2313d3b0591SJens Wiklander  * Enable restartable operations for context
2323d3b0591SJens Wiklander  */
mbedtls_ecdh_enable_restart(mbedtls_ecdh_context * ctx)2333d3b0591SJens Wiklander void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
2343d3b0591SJens Wiklander {
2353d3b0591SJens Wiklander     ctx->restart_enabled = 1;
2363d3b0591SJens Wiklander }
2373d3b0591SJens Wiklander #endif
2383d3b0591SJens Wiklander 
239817466cbSJens Wiklander /*
240817466cbSJens Wiklander  * Free context
241817466cbSJens Wiklander  */
mbedtls_ecdh_free(mbedtls_ecdh_context * ctx)242817466cbSJens Wiklander void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
243817466cbSJens Wiklander {
24432b31808SJens Wiklander     if (ctx == NULL) {
245817466cbSJens Wiklander         return;
24632b31808SJens Wiklander     }
247817466cbSJens Wiklander 
2483d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
249817466cbSJens Wiklander     mbedtls_ecp_point_free(&ctx->Vi);
250817466cbSJens Wiklander     mbedtls_ecp_point_free(&ctx->Vf);
251817466cbSJens Wiklander     mbedtls_mpi_free(&ctx->_d);
2523d3b0591SJens Wiklander     ecdh_free_internal(ctx);
2533d3b0591SJens Wiklander #else
25432b31808SJens Wiklander     switch (ctx->var) {
25511fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
25611fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
25711fa71b9SJerome Forissier             mbedtls_everest_free(&ctx->ctx.everest_ecdh);
25811fa71b9SJerome Forissier             break;
25911fa71b9SJerome Forissier #endif
2603d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
2613d3b0591SJens Wiklander             ecdh_free_internal(&ctx->ctx.mbed_ecdh);
2623d3b0591SJens Wiklander             break;
2633d3b0591SJens Wiklander         default:
2643d3b0591SJens Wiklander             break;
2653d3b0591SJens Wiklander     }
2663d3b0591SJens Wiklander 
2673d3b0591SJens Wiklander     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
2683d3b0591SJens Wiklander     ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
2693d3b0591SJens Wiklander     ctx->grp_id = MBEDTLS_ECP_DP_NONE;
2703d3b0591SJens Wiklander #endif
2713d3b0591SJens Wiklander }
2723d3b0591SJens Wiklander 
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)2733d3b0591SJens Wiklander static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
2743d3b0591SJens Wiklander                                      size_t *olen, int point_format,
2753d3b0591SJens Wiklander                                      unsigned char *buf, size_t blen,
2763d3b0591SJens Wiklander                                      int (*f_rng)(void *,
2773d3b0591SJens Wiklander                                                   unsigned char *,
2783d3b0591SJens Wiklander                                                   size_t),
2793d3b0591SJens Wiklander                                      void *p_rng,
2803d3b0591SJens Wiklander                                      int restart_enabled)
2813d3b0591SJens Wiklander {
28211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2833d3b0591SJens Wiklander     size_t grp_len, pt_len;
2843d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
2853d3b0591SJens Wiklander     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
2863d3b0591SJens Wiklander #endif
2873d3b0591SJens Wiklander 
28832b31808SJens Wiklander     if (ctx->grp.pbits == 0) {
28932b31808SJens Wiklander         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
29032b31808SJens Wiklander     }
2913d3b0591SJens Wiklander 
2923d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
29332b31808SJens Wiklander     if (restart_enabled) {
2943d3b0591SJens Wiklander         rs_ctx = &ctx->rs;
29532b31808SJens Wiklander     }
2963d3b0591SJens Wiklander #else
2973d3b0591SJens Wiklander     (void) restart_enabled;
2983d3b0591SJens Wiklander #endif
2993d3b0591SJens Wiklander 
3003d3b0591SJens Wiklander 
3013d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
3023d3b0591SJens Wiklander     if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
30332b31808SJens Wiklander                                            f_rng, p_rng, rs_ctx)) != 0) {
30432b31808SJens Wiklander         return ret;
30532b31808SJens Wiklander     }
3063d3b0591SJens Wiklander #else
3073d3b0591SJens Wiklander     if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
30832b31808SJens Wiklander                                        f_rng, p_rng)) != 0) {
30932b31808SJens Wiklander         return ret;
31032b31808SJens Wiklander     }
3113d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
3123d3b0591SJens Wiklander 
3133d3b0591SJens Wiklander     if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
31432b31808SJens Wiklander                                            blen)) != 0) {
31532b31808SJens Wiklander         return ret;
31632b31808SJens Wiklander     }
3173d3b0591SJens Wiklander 
3183d3b0591SJens Wiklander     buf += grp_len;
3193d3b0591SJens Wiklander     blen -= grp_len;
3203d3b0591SJens Wiklander 
3213d3b0591SJens Wiklander     if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
32232b31808SJens Wiklander                                            &pt_len, buf, blen)) != 0) {
32332b31808SJens Wiklander         return ret;
32432b31808SJens Wiklander     }
3253d3b0591SJens Wiklander 
3263d3b0591SJens Wiklander     *olen = grp_len + pt_len;
32732b31808SJens Wiklander     return 0;
328817466cbSJens Wiklander }
329817466cbSJens Wiklander 
330817466cbSJens Wiklander /*
33111fa71b9SJerome Forissier  * Setup and write the ServerKeyExchange parameters (RFC 4492)
332817466cbSJens Wiklander  *      struct {
333817466cbSJens Wiklander  *          ECParameters    curve_params;
334817466cbSJens Wiklander  *          ECPoint         public;
335817466cbSJens Wiklander  *      } ServerECDHParams;
336817466cbSJens Wiklander  */
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)337817466cbSJens Wiklander int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
338817466cbSJens Wiklander                              unsigned char *buf, size_t blen,
339817466cbSJens Wiklander                              int (*f_rng)(void *, unsigned char *, size_t),
340817466cbSJens Wiklander                              void *p_rng)
341817466cbSJens Wiklander {
3423d3b0591SJens Wiklander     int restart_enabled = 0;
3433d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
3443d3b0591SJens Wiklander     restart_enabled = ctx->restart_enabled;
3453d3b0591SJens Wiklander #else
3463d3b0591SJens Wiklander     (void) restart_enabled;
3473d3b0591SJens Wiklander #endif
348817466cbSJens Wiklander 
3493d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
35032b31808SJens Wiklander     return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
35132b31808SJens Wiklander                                      f_rng, p_rng, restart_enabled);
3523d3b0591SJens Wiklander #else
35332b31808SJens Wiklander     switch (ctx->var) {
35411fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
35511fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
35632b31808SJens Wiklander             return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
35732b31808SJens Wiklander                                                buf, blen, f_rng, p_rng);
35811fa71b9SJerome Forissier #endif
3593d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
36032b31808SJens Wiklander             return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
3613d3b0591SJens Wiklander                                              ctx->point_format, buf, blen,
3623d3b0591SJens Wiklander                                              f_rng, p_rng,
36332b31808SJens Wiklander                                              restart_enabled);
3643d3b0591SJens Wiklander         default:
3653d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
3663d3b0591SJens Wiklander     }
3673d3b0591SJens Wiklander #endif
3683d3b0591SJens Wiklander }
369817466cbSJens Wiklander 
ecdh_read_params_internal(mbedtls_ecdh_context_mbed * ctx,const unsigned char ** buf,const unsigned char * end)3703d3b0591SJens Wiklander static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
3713d3b0591SJens Wiklander                                      const unsigned char **buf,
3723d3b0591SJens Wiklander                                      const unsigned char *end)
3733d3b0591SJens Wiklander {
37432b31808SJens Wiklander     return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
375*b0563631STom Van Eyck                                       (size_t) (end - *buf));
376817466cbSJens Wiklander }
377817466cbSJens Wiklander 
378817466cbSJens Wiklander /*
379039e02dfSJerome Forissier  * Read the ServerKeyExchange parameters (RFC 4492)
380817466cbSJens Wiklander  *      struct {
381817466cbSJens Wiklander  *          ECParameters    curve_params;
382817466cbSJens Wiklander  *          ECPoint         public;
383817466cbSJens Wiklander  *      } ServerECDHParams;
384817466cbSJens Wiklander  */
mbedtls_ecdh_read_params(mbedtls_ecdh_context * ctx,const unsigned char ** buf,const unsigned char * end)385817466cbSJens Wiklander int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
3863d3b0591SJens Wiklander                              const unsigned char **buf,
3873d3b0591SJens Wiklander                              const unsigned char *end)
388817466cbSJens Wiklander {
38911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3903d3b0591SJens Wiklander     mbedtls_ecp_group_id grp_id;
391*b0563631STom Van Eyck     if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
39232b31808SJens Wiklander         != 0) {
39332b31808SJens Wiklander         return ret;
39432b31808SJens Wiklander     }
395817466cbSJens Wiklander 
39632b31808SJens Wiklander     if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
39732b31808SJens Wiklander         return ret;
39832b31808SJens Wiklander     }
3993d3b0591SJens Wiklander 
4003d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
40132b31808SJens Wiklander     return ecdh_read_params_internal(ctx, buf, end);
4023d3b0591SJens Wiklander #else
40332b31808SJens Wiklander     switch (ctx->var) {
40411fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
40511fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
40632b31808SJens Wiklander             return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
40732b31808SJens Wiklander                                                buf, end);
40811fa71b9SJerome Forissier #endif
4093d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
41032b31808SJens Wiklander             return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
41132b31808SJens Wiklander                                              buf, end);
4123d3b0591SJens Wiklander         default:
4133d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
4143d3b0591SJens Wiklander     }
4153d3b0591SJens Wiklander #endif
416817466cbSJens Wiklander }
417817466cbSJens Wiklander 
ecdh_get_params_internal(mbedtls_ecdh_context_mbed * ctx,const mbedtls_ecp_keypair * key,mbedtls_ecdh_side side)4183d3b0591SJens Wiklander static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
4193d3b0591SJens Wiklander                                     const mbedtls_ecp_keypair *key,
420817466cbSJens Wiklander                                     mbedtls_ecdh_side side)
421817466cbSJens Wiklander {
42211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
423817466cbSJens Wiklander 
424817466cbSJens Wiklander     /* If it's not our key, just import the public part as Qp */
42532b31808SJens Wiklander     if (side == MBEDTLS_ECDH_THEIRS) {
42632b31808SJens Wiklander         return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
42732b31808SJens Wiklander     }
428817466cbSJens Wiklander 
429817466cbSJens Wiklander     /* Our key: import public (as Q) and private parts */
43032b31808SJens Wiklander     if (side != MBEDTLS_ECDH_OURS) {
43132b31808SJens Wiklander         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
43232b31808SJens Wiklander     }
433817466cbSJens Wiklander 
434817466cbSJens Wiklander     if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
43532b31808SJens Wiklander         (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
43632b31808SJens Wiklander         return ret;
43732b31808SJens Wiklander     }
438817466cbSJens Wiklander 
43932b31808SJens Wiklander     return 0;
440817466cbSJens Wiklander }
441817466cbSJens Wiklander 
442817466cbSJens Wiklander /*
4433d3b0591SJens Wiklander  * Get parameters from a keypair
4443d3b0591SJens Wiklander  */
mbedtls_ecdh_get_params(mbedtls_ecdh_context * ctx,const mbedtls_ecp_keypair * key,mbedtls_ecdh_side side)4453d3b0591SJens Wiklander int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
4463d3b0591SJens Wiklander                             const mbedtls_ecp_keypair *key,
4473d3b0591SJens Wiklander                             mbedtls_ecdh_side side)
4483d3b0591SJens Wiklander {
44911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
45032b31808SJens Wiklander     if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
45132b31808SJens Wiklander         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
45232b31808SJens Wiklander     }
4533d3b0591SJens Wiklander 
45432b31808SJens Wiklander     if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
4555b25c76aSJerome Forissier         /* This is the first call to get_params(). Set up the context
4565b25c76aSJerome Forissier          * for use with the group. */
45732b31808SJens Wiklander         if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
45832b31808SJens Wiklander             return ret;
4595b25c76aSJerome Forissier         }
46032b31808SJens Wiklander     } else {
4615b25c76aSJerome Forissier         /* This is not the first call to get_params(). Check that the
4625b25c76aSJerome Forissier          * current key's group is the same as the context's, which was set
4635b25c76aSJerome Forissier          * from the first key's group. */
46432b31808SJens Wiklander         if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
46532b31808SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
46632b31808SJens Wiklander         }
4675b25c76aSJerome Forissier     }
4683d3b0591SJens Wiklander 
4693d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
47032b31808SJens Wiklander     return ecdh_get_params_internal(ctx, key, side);
4713d3b0591SJens Wiklander #else
47232b31808SJens Wiklander     switch (ctx->var) {
47311fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
47411fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
47511fa71b9SJerome Forissier         {
47611fa71b9SJerome Forissier             mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
47711fa71b9SJerome Forissier                                           MBEDTLS_EVEREST_ECDH_OURS :
47811fa71b9SJerome Forissier                                           MBEDTLS_EVEREST_ECDH_THEIRS;
47932b31808SJens Wiklander             return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
48032b31808SJens Wiklander                                               key, s);
48111fa71b9SJerome Forissier         }
48211fa71b9SJerome Forissier #endif
4833d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
48432b31808SJens Wiklander             return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
48532b31808SJens Wiklander                                             key, side);
4863d3b0591SJens Wiklander         default:
4873d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
4883d3b0591SJens Wiklander     }
4893d3b0591SJens Wiklander #endif
4903d3b0591SJens Wiklander }
4913d3b0591SJens Wiklander 
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)4923d3b0591SJens Wiklander static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
4933d3b0591SJens Wiklander                                      size_t *olen, int point_format,
4943d3b0591SJens Wiklander                                      unsigned char *buf, size_t blen,
4953d3b0591SJens Wiklander                                      int (*f_rng)(void *,
4963d3b0591SJens Wiklander                                                   unsigned char *,
4973d3b0591SJens Wiklander                                                   size_t),
4983d3b0591SJens Wiklander                                      void *p_rng,
4993d3b0591SJens Wiklander                                      int restart_enabled)
5003d3b0591SJens Wiklander {
50111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
5023d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
5033d3b0591SJens Wiklander     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
5043d3b0591SJens Wiklander #endif
5053d3b0591SJens Wiklander 
50632b31808SJens Wiklander     if (ctx->grp.pbits == 0) {
50732b31808SJens Wiklander         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
50832b31808SJens Wiklander     }
5093d3b0591SJens Wiklander 
5103d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
51132b31808SJens Wiklander     if (restart_enabled) {
5123d3b0591SJens Wiklander         rs_ctx = &ctx->rs;
51332b31808SJens Wiklander     }
5143d3b0591SJens Wiklander #else
5153d3b0591SJens Wiklander     (void) restart_enabled;
5163d3b0591SJens Wiklander #endif
5173d3b0591SJens Wiklander 
5183d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
5193d3b0591SJens Wiklander     if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
52032b31808SJens Wiklander                                            f_rng, p_rng, rs_ctx)) != 0) {
52132b31808SJens Wiklander         return ret;
52232b31808SJens Wiklander     }
5233d3b0591SJens Wiklander #else
5243d3b0591SJens Wiklander     if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
52532b31808SJens Wiklander                                        f_rng, p_rng)) != 0) {
52632b31808SJens Wiklander         return ret;
52732b31808SJens Wiklander     }
5283d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
5293d3b0591SJens Wiklander 
5303d3b0591SJens Wiklander     return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
5313d3b0591SJens Wiklander                                        buf, blen);
5323d3b0591SJens Wiklander }
5333d3b0591SJens Wiklander 
5343d3b0591SJens Wiklander /*
535817466cbSJens Wiklander  * Setup and export the client public value
536817466cbSJens Wiklander  */
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)537817466cbSJens Wiklander int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
538817466cbSJens Wiklander                              unsigned char *buf, size_t blen,
539817466cbSJens Wiklander                              int (*f_rng)(void *, unsigned char *, size_t),
540817466cbSJens Wiklander                              void *p_rng)
541817466cbSJens Wiklander {
5423d3b0591SJens Wiklander     int restart_enabled = 0;
5433d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
5443d3b0591SJens Wiklander     restart_enabled = ctx->restart_enabled;
5453d3b0591SJens Wiklander #endif
5463d3b0591SJens Wiklander 
5473d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
54832b31808SJens Wiklander     return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
54932b31808SJens Wiklander                                      f_rng, p_rng, restart_enabled);
5503d3b0591SJens Wiklander #else
55132b31808SJens Wiklander     switch (ctx->var) {
55211fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
55311fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
55432b31808SJens Wiklander             return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
55532b31808SJens Wiklander                                                buf, blen, f_rng, p_rng);
55611fa71b9SJerome Forissier #endif
5573d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
55832b31808SJens Wiklander             return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
5593d3b0591SJens Wiklander                                              ctx->point_format, buf, blen,
5603d3b0591SJens Wiklander                                              f_rng, p_rng,
56132b31808SJens Wiklander                                              restart_enabled);
5623d3b0591SJens Wiklander         default:
5633d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
5643d3b0591SJens Wiklander     }
5653d3b0591SJens Wiklander #endif
5663d3b0591SJens Wiklander }
5673d3b0591SJens Wiklander 
ecdh_read_public_internal(mbedtls_ecdh_context_mbed * ctx,const unsigned char * buf,size_t blen)5683d3b0591SJens Wiklander static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
5693d3b0591SJens Wiklander                                      const unsigned char *buf, size_t blen)
5703d3b0591SJens Wiklander {
57111fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
5723d3b0591SJens Wiklander     const unsigned char *p = buf;
573817466cbSJens Wiklander 
5743d3b0591SJens Wiklander     if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
57532b31808SJens Wiklander                                           blen)) != 0) {
57632b31808SJens Wiklander         return ret;
57732b31808SJens Wiklander     }
578817466cbSJens Wiklander 
57932b31808SJens Wiklander     if ((size_t) (p - buf) != blen) {
58032b31808SJens Wiklander         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
58132b31808SJens Wiklander     }
5823d3b0591SJens Wiklander 
58332b31808SJens Wiklander     return 0;
584817466cbSJens Wiklander }
585817466cbSJens Wiklander 
586817466cbSJens Wiklander /*
587817466cbSJens Wiklander  * Parse and import the client's public value
588817466cbSJens Wiklander  */
mbedtls_ecdh_read_public(mbedtls_ecdh_context * ctx,const unsigned char * buf,size_t blen)589817466cbSJens Wiklander int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
590817466cbSJens Wiklander                              const unsigned char *buf, size_t blen)
591817466cbSJens Wiklander {
5923d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
59332b31808SJens Wiklander     return ecdh_read_public_internal(ctx, buf, blen);
5943d3b0591SJens Wiklander #else
59532b31808SJens Wiklander     switch (ctx->var) {
59611fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
59711fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
59832b31808SJens Wiklander             return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
59932b31808SJens Wiklander                                                buf, blen);
60011fa71b9SJerome Forissier #endif
6013d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
60232b31808SJens Wiklander             return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
60332b31808SJens Wiklander                                              buf, blen);
6043d3b0591SJens Wiklander         default:
6053d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
6063d3b0591SJens Wiklander     }
6073d3b0591SJens Wiklander #endif
6083d3b0591SJens Wiklander }
6093d3b0591SJens Wiklander 
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)6103d3b0591SJens Wiklander static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
6113d3b0591SJens Wiklander                                      size_t *olen, unsigned char *buf,
6123d3b0591SJens Wiklander                                      size_t blen,
6133d3b0591SJens Wiklander                                      int (*f_rng)(void *,
6143d3b0591SJens Wiklander                                                   unsigned char *,
6153d3b0591SJens Wiklander                                                   size_t),
6163d3b0591SJens Wiklander                                      void *p_rng,
6173d3b0591SJens Wiklander                                      int restart_enabled)
6183d3b0591SJens Wiklander {
61911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
6203d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
6213d3b0591SJens Wiklander     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
6223d3b0591SJens Wiklander #endif
623817466cbSJens Wiklander 
62432b31808SJens Wiklander     if (ctx == NULL || ctx->grp.pbits == 0) {
62532b31808SJens Wiklander         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
62632b31808SJens Wiklander     }
627817466cbSJens Wiklander 
6283d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
62932b31808SJens Wiklander     if (restart_enabled) {
6303d3b0591SJens Wiklander         rs_ctx = &ctx->rs;
63132b31808SJens Wiklander     }
6323d3b0591SJens Wiklander #else
6333d3b0591SJens Wiklander     (void) restart_enabled;
6343d3b0591SJens Wiklander #endif
6353d3b0591SJens Wiklander 
6363d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
6373d3b0591SJens Wiklander     if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
6383d3b0591SJens Wiklander                                                &ctx->d, f_rng, p_rng,
63932b31808SJens Wiklander                                                rs_ctx)) != 0) {
64032b31808SJens Wiklander         return ret;
6413d3b0591SJens Wiklander     }
6423d3b0591SJens Wiklander #else
6433d3b0591SJens Wiklander     if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
64432b31808SJens Wiklander                                            &ctx->d, f_rng, p_rng)) != 0) {
64532b31808SJens Wiklander         return ret;
6463d3b0591SJens Wiklander     }
6473d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
648817466cbSJens Wiklander 
64932b31808SJens Wiklander     if (mbedtls_mpi_size(&ctx->z) > blen) {
65032b31808SJens Wiklander         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
65132b31808SJens Wiklander     }
652817466cbSJens Wiklander 
6533d3b0591SJens Wiklander     *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
65411fa71b9SJerome Forissier 
65532b31808SJens Wiklander     if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
65611fa71b9SJerome Forissier         return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
65732b31808SJens Wiklander     }
65811fa71b9SJerome Forissier 
6593d3b0591SJens Wiklander     return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
660817466cbSJens Wiklander }
661817466cbSJens Wiklander 
662817466cbSJens Wiklander /*
663817466cbSJens Wiklander  * Derive and export the shared secret
664817466cbSJens Wiklander  */
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)665817466cbSJens Wiklander int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
666817466cbSJens Wiklander                              unsigned char *buf, size_t blen,
667817466cbSJens Wiklander                              int (*f_rng)(void *, unsigned char *, size_t),
668817466cbSJens Wiklander                              void *p_rng)
669817466cbSJens Wiklander {
6703d3b0591SJens Wiklander     int restart_enabled = 0;
6713d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
6723d3b0591SJens Wiklander     restart_enabled = ctx->restart_enabled;
6733d3b0591SJens Wiklander #endif
674817466cbSJens Wiklander 
6753d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
67632b31808SJens Wiklander     return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
67732b31808SJens Wiklander                                      restart_enabled);
6783d3b0591SJens Wiklander #else
67932b31808SJens Wiklander     switch (ctx->var) {
68011fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
68111fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
68232b31808SJens Wiklander             return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
68332b31808SJens Wiklander                                                buf, blen, f_rng, p_rng);
68411fa71b9SJerome Forissier #endif
6853d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
68632b31808SJens Wiklander             return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
6873d3b0591SJens Wiklander                                              blen, f_rng, p_rng,
68832b31808SJens Wiklander                                              restart_enabled);
6893d3b0591SJens Wiklander         default:
69032b31808SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
6913d3b0591SJens Wiklander     }
6923d3b0591SJens Wiklander #endif
693817466cbSJens Wiklander }
694817466cbSJens Wiklander #endif /* MBEDTLS_ECDH_C */
695