blob: 52b16170625ef4f1be6c815c685424d3173d2d3a [file] [log] [blame]
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +01001/*
2 * Elliptic curve Diffie-Hellman
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +01006 */
7
8/*
9 * References:
10 *
Xiaokang Qian47041472023-04-12 06:07:23 +000011 * SEC1 https://www.secg.org/sec1-v2.pdf
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +010012 * RFC 4492
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010013 */
14
Gilles Peskinedb09ef62020-06-03 01:43:33 +020015#include "common.h"
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010016
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020017#if defined(MBEDTLS_ECDH_C)
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010018
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000019#include "mbedtls/ecdh.h"
Hanno Becker91796d72018-12-17 18:10:51 +000020#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000021#include "mbedtls/error.h"
Jerry Yubdc71882021-09-14 19:30:36 +080022
Rich Evans00ab4702015-02-06 13:43:58 +000023#include <string.h>
24
Janos Follath5a3e1bf2018-08-13 15:54:22 +010025#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
26typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
27#endif
28
Gilles Peskine30816292019-02-22 12:31:25 +010029static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
Gilles Peskine449bd832023-01-11 14:50:10 +010030 const mbedtls_ecdh_context *ctx)
Gilles Peskine30816292019-02-22 12:31:25 +010031{
32#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +010033 return ctx->grp.id;
Gilles Peskine30816292019-02-22 12:31:25 +010034#else
Gilles Peskine449bd832023-01-11 14:50:10 +010035 return ctx->grp_id;
Gilles Peskine30816292019-02-22 12:31:25 +010036#endif
37}
38
Gilles Peskine449bd832023-01-11 14:50:10 +010039int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
Gilles Peskine20b3ef32019-02-11 18:41:27 +010040{
41 /* At this time, all groups support ECDH. */
42 (void) gid;
Gilles Peskine449bd832023-01-11 14:50:10 +010043 return 1;
Gilles Peskine20b3ef32019-02-11 18:41:27 +010044}
45
Ron Eldora84c1cb2017-10-10 19:04:27 +030046#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010047/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020048 * Generate public key (restartable version)
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020049 *
50 * Note: this internal function relies on its caller preserving the value of
Manuel Pégourié-Gonnardca29fdf2018-10-22 09:56:53 +020051 * the output parameter 'd' across continuation calls. This would not be
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020052 * acceptable for a public function but is OK here as we control call sites.
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020053 */
Gilles Peskine449bd832023-01-11 14:50:10 +010054static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
55 mbedtls_mpi *d, mbedtls_ecp_point *Q,
56 int (*f_rng)(void *, unsigned char *, size_t),
57 void *p_rng,
58 mbedtls_ecp_restart_ctx *rs_ctx)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020059{
Janos Follath24eed8d2019-11-22 13:21:35 +000060 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020061
David Horstmann91e20a02022-10-06 19:11:28 +010062 int restarting = 0;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020063#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +010064 restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020065#endif
David Horstmann91e20a02022-10-06 19:11:28 +010066 /* If multiplication is in progress, we already generated a privkey */
Gilles Peskine449bd832023-01-11 14:50:10 +010067 if (!restarting) {
68 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
69 }
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020070
Gilles Peskine449bd832023-01-11 14:50:10 +010071 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
72 f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020073
74cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +010075 return ret;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020076}
77
78/*
79 * Generate public key
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010080 */
Gilles Peskine449bd832023-01-11 14:50:10 +010081int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
82 int (*f_rng)(void *, unsigned char *, size_t),
83 void *p_rng)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010084{
Gilles Peskine449bd832023-01-11 14:50:10 +010085 return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010086}
Ron Eldor936d2842018-11-01 13:05:52 +020087#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010088
Ron Eldora84c1cb2017-10-10 19:04:27 +030089#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010090/*
91 * Compute shared secret (SEC1 3.3.1)
92 */
Gilles Peskine449bd832023-01-11 14:50:10 +010093static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
94 mbedtls_mpi *z,
95 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
96 int (*f_rng)(void *, unsigned char *, size_t),
97 void *p_rng,
98 mbedtls_ecp_restart_ctx *rs_ctx)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010099{
Janos Follath24eed8d2019-11-22 13:21:35 +0000100 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101 mbedtls_ecp_point P;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100102
Gilles Peskine449bd832023-01-11 14:50:10 +0100103 mbedtls_ecp_point_init(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100104
Gilles Peskine449bd832023-01-11 14:50:10 +0100105 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
106 f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100107
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 if (mbedtls_ecp_is_zero(&P)) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakkerb548d772013-07-26 14:21:34 +0200110 goto cleanup;
111 }
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100112
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100114
115cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 mbedtls_ecp_point_free(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100117
Gilles Peskine449bd832023-01-11 14:50:10 +0100118 return ret;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100119}
120
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100121/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200122 * Compute shared secret (SEC1 3.3.1)
123 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100124int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
125 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
126 int (*f_rng)(void *, unsigned char *, size_t),
127 void *p_rng)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200128{
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 return ecdh_compute_shared_restartable(grp, z, Q, d,
130 f_rng, p_rng, NULL);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200131}
Ron Eldor936d2842018-11-01 13:05:52 +0200132#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200133
Gilles Peskine449bd832023-01-11 14:50:10 +0100134static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100135{
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 mbedtls_ecp_group_init(&ctx->grp);
137 mbedtls_mpi_init(&ctx->d);
138 mbedtls_ecp_point_init(&ctx->Q);
139 mbedtls_ecp_point_init(&ctx->Qp);
140 mbedtls_mpi_init(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200141
142#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 mbedtls_ecp_restart_init(&ctx->rs);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200144#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100145}
146
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100147/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100148 * Initialize context
Janos Follathf61e4862018-10-30 11:53:25 +0000149 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100150void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100151{
152#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 ecdh_init_internal(ctx);
154 mbedtls_ecp_point_init(&ctx->Vi);
155 mbedtls_ecp_point_init(&ctx->Vf);
156 mbedtls_mpi_init(&ctx->_d);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100157#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100158 memset(ctx, 0, sizeof(mbedtls_ecdh_context));
Christoph M. Wintersteigerd8c45d52019-02-20 17:16:53 +0000159
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100160 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
161#endif
162 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
163#if defined(MBEDTLS_ECP_RESTARTABLE)
164 ctx->restart_enabled = 0;
165#endif
166}
167
Gilles Peskine449bd832023-01-11 14:50:10 +0100168static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
169 mbedtls_ecp_group_id grp_id)
Janos Follathf61e4862018-10-30 11:53:25 +0000170{
Janos Follath24eed8d2019-11-22 13:21:35 +0000171 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000172
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
174 if (ret != 0) {
175 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Janos Follathf61e4862018-10-30 11:53:25 +0000176 }
177
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 return 0;
Janos Follathf61e4862018-10-30 11:53:25 +0000179}
180
181/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100182 * Setup context
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100183 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100184int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100185{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100186#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 return ecdh_setup_internal(ctx, grp_id);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100188#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100189 switch (grp_id) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100190#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000191 case MBEDTLS_ECP_DP_CURVE25519:
192 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
193 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
194 ctx->grp_id = grp_id;
Gilles Peskine449bd832023-01-11 14:50:10 +0100195 return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
Christoph M. Wintersteiger78c9c462018-12-06 17:16:32 +0000196#endif
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000197 default:
198 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
199 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
200 ctx->grp_id = grp_id;
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 ecdh_init_internal(&ctx->ctx.mbed_ecdh);
202 return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100203 }
204#endif
205}
206
Gilles Peskine449bd832023-01-11 14:50:10 +0100207static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100208{
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 mbedtls_ecp_group_free(&ctx->grp);
210 mbedtls_mpi_free(&ctx->d);
211 mbedtls_ecp_point_free(&ctx->Q);
212 mbedtls_ecp_point_free(&ctx->Qp);
213 mbedtls_mpi_free(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200214
215#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 mbedtls_ecp_restart_free(&ctx->rs);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200217#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100218}
219
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200220#if defined(MBEDTLS_ECP_RESTARTABLE)
221/*
222 * Enable restartable operations for context
223 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100224void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200225{
226 ctx->restart_enabled = 1;
227}
228#endif
229
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100230/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100231 * Free context
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100232 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100233void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100234{
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 if (ctx == NULL) {
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100236 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100238
239#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 mbedtls_ecp_point_free(&ctx->Vi);
241 mbedtls_ecp_point_free(&ctx->Vf);
242 mbedtls_mpi_free(&ctx->_d);
243 ecdh_free_internal(ctx);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100244#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100246#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
247 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 mbedtls_everest_free(&ctx->ctx.everest_ecdh);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100249 break;
250#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100251 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100252 ecdh_free_internal(&ctx->ctx.mbed_ecdh);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100253 break;
254 default:
255 break;
256 }
257
258 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
259 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
260 ctx->grp_id = MBEDTLS_ECP_DP_NONE;
261#endif
262}
263
Gilles Peskine449bd832023-01-11 14:50:10 +0100264static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
265 size_t *olen, int point_format,
266 unsigned char *buf, size_t blen,
267 int (*f_rng)(void *,
268 unsigned char *,
269 size_t),
270 void *p_rng,
271 int restart_enabled)
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100272{
Janos Follath24eed8d2019-11-22 13:21:35 +0000273 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100274 size_t grp_len, pt_len;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200275#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200276 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200277#endif
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100278
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 if (ctx->grp.pbits == 0) {
280 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
281 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100282
Ron Eldor19779c42018-11-05 16:58:13 +0200283#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200285 rs_ctx = &ctx->rs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100287#else
288 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200289#endif
290
Ron Eldor8493f802018-11-01 11:32:15 +0200291
Ron Eldor2981d8f2018-11-05 18:07:10 +0200292#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
294 f_rng, p_rng, rs_ctx)) != 0) {
295 return ret;
296 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200297#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
299 f_rng, p_rng)) != 0) {
300 return ret;
301 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200302#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100303
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
305 blen)) != 0) {
306 return ret;
307 }
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100308
309 buf += grp_len;
310 blen -= grp_len;
311
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
313 &pt_len, buf, blen)) != 0) {
314 return ret;
315 }
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100316
317 *olen = grp_len + pt_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100318 return 0;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100319}
320
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100321/*
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100322 * Setup and write the ServerKeyExchange parameters (RFC 4492)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100323 * struct {
324 * ECParameters curve_params;
325 * ECPoint public;
326 * } ServerECDHParams;
327 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100328int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
329 unsigned char *buf, size_t blen,
330 int (*f_rng)(void *, unsigned char *, size_t),
331 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100332{
333 int restart_enabled = 0;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100334#if defined(MBEDTLS_ECP_RESTARTABLE)
335 restart_enabled = ctx->restart_enabled;
336#else
337 (void) restart_enabled;
338#endif
339
340#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
342 f_rng, p_rng, restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100343#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100344 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100345#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
346 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
348 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100349#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100350 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
352 ctx->point_format, buf, blen,
353 f_rng, p_rng,
354 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100355 default:
356 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
357 }
358#endif
359}
360
Gilles Peskine449bd832023-01-11 14:50:10 +0100361static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
362 const unsigned char **buf,
363 const unsigned char *end)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100364{
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000366 (size_t) (end - *buf));
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100367}
368
369/*
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400370 * Read the ServerKeyExchange parameters (RFC 4492)
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100371 * struct {
372 * ECParameters curve_params;
373 * ECPoint public;
374 * } ServerECDHParams;
375 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100376int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
377 const unsigned char **buf,
378 const unsigned char *end)
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100379{
Janos Follath24eed8d2019-11-22 13:21:35 +0000380 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000381 mbedtls_ecp_group_id grp_id;
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000382 if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 != 0) {
384 return ret;
385 }
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100386
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
388 return ret;
389 }
Janos Follathf61e4862018-10-30 11:53:25 +0000390
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100391#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 return ecdh_read_params_internal(ctx, buf, end);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100393#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100395#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
396 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
398 buf, end);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100399#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100400 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
402 buf, end);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100403 default:
404 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
405 }
406#endif
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100407}
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +0100408
Gilles Peskine449bd832023-01-11 14:50:10 +0100409static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
410 const mbedtls_ecp_keypair *key,
411 mbedtls_ecdh_side side)
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100412{
Janos Follath24eed8d2019-11-22 13:21:35 +0000413 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100414
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100415 /* If it's not our key, just import the public part as Qp */
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 if (side == MBEDTLS_ECDH_THEIRS) {
417 return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
418 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100419
420 /* Our key: import public (as Q) and private parts */
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 if (side != MBEDTLS_ECDH_OURS) {
422 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
423 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100424
Gilles Peskine449bd832023-01-11 14:50:10 +0100425 if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
426 (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
427 return ret;
428 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100429
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 return 0;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100431}
432
433/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100434 * Get parameters from a keypair
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100435 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100436int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
437 const mbedtls_ecp_keypair *key,
438 mbedtls_ecdh_side side)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100439{
Janos Follath24eed8d2019-11-22 13:21:35 +0000440 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100441 if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
442 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
443 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100444
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100446 /* This is the first call to get_params(). Set up the context
447 * for use with the group. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
449 return ret;
450 }
451 } else {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100452 /* This is not the first call to get_params(). Check that the
453 * current key's group is the same as the context's, which was set
454 * from the first key's group. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100455 if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
456 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
457 }
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100458 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100459
460#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100461 return ecdh_get_params_internal(ctx, key, side);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100462#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100464#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
465 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000466 {
Christoph M. Wintersteiger2e724a12019-01-07 14:19:41 +0000467 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 MBEDTLS_EVEREST_ECDH_OURS :
469 MBEDTLS_EVEREST_ECDH_THEIRS;
470 return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
471 key, s);
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000472 }
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100473#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100474 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100475 return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
476 key, side);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100477 default:
478 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
479 }
480#endif
481}
482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
484 size_t *olen, int point_format,
485 unsigned char *buf, size_t blen,
486 int (*f_rng)(void *,
487 unsigned char *,
488 size_t),
489 void *p_rng,
490 int restart_enabled)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100491{
Janos Follath24eed8d2019-11-22 13:21:35 +0000492 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200493#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200494 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200495#endif
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100496
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 if (ctx->grp.pbits == 0) {
498 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
499 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100500
Ron Eldorb430d9f2018-11-05 17:18:29 +0200501#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200503 rs_ctx = &ctx->rs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100504 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100505#else
506 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200507#endif
508
Ron Eldor2981d8f2018-11-05 18:07:10 +0200509#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100510 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
511 f_rng, p_rng, rs_ctx)) != 0) {
512 return ret;
513 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200514#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
516 f_rng, p_rng)) != 0) {
517 return ret;
518 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200519#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100520
Gilles Peskine449bd832023-01-11 14:50:10 +0100521 return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
522 buf, blen);
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100523}
524
525/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100526 * Setup and export the client public value
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100527 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100528int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
529 unsigned char *buf, size_t blen,
530 int (*f_rng)(void *, unsigned char *, size_t),
531 void *p_rng)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100532{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100533 int restart_enabled = 0;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100534#if defined(MBEDTLS_ECP_RESTARTABLE)
535 restart_enabled = ctx->restart_enabled;
536#endif
537
538#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
540 f_rng, p_rng, restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100541#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100543#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
544 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
546 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100547#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100548 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
550 ctx->point_format, buf, blen,
551 f_rng, p_rng,
552 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100553 default:
554 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
555 }
556#endif
557}
558
Gilles Peskine449bd832023-01-11 14:50:10 +0100559static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
560 const unsigned char *buf, size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100561{
Janos Follath24eed8d2019-11-22 13:21:35 +0000562 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100563 const unsigned char *p = buf;
564
Gilles Peskine449bd832023-01-11 14:50:10 +0100565 if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
566 blen)) != 0) {
567 return ret;
568 }
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100569
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 if ((size_t) (p - buf) != blen) {
571 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
572 }
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100573
Gilles Peskine449bd832023-01-11 14:50:10 +0100574 return 0;
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100575}
576
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100577/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100578 * Parse and import the client's public value
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100579 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100580int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
581 const unsigned char *buf, size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100582{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100583#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100584 return ecdh_read_public_internal(ctx, buf, blen);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100585#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100586 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100587#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
588 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
590 buf, blen);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100591#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100592 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
594 buf, blen);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100595 default:
596 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
597 }
598#endif
599}
600
Gilles Peskine449bd832023-01-11 14:50:10 +0100601static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
602 size_t *olen, unsigned char *buf,
603 size_t blen,
604 int (*f_rng)(void *,
605 unsigned char *,
606 size_t),
607 void *p_rng,
608 int restart_enabled)
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100609{
Janos Follath24eed8d2019-11-22 13:21:35 +0000610 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200611#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200612 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200613#endif
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100614
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 if (ctx == NULL || ctx->grp.pbits == 0) {
616 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
617 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100618
Ron Eldorb430d9f2018-11-05 17:18:29 +0200619#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100620 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200621 rs_ctx = &ctx->rs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100622 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100623#else
624 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200625#endif
626
Ron Eldor2981d8f2018-11-05 18:07:10 +0200627#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
629 &ctx->d, f_rng, p_rng,
630 rs_ctx)) != 0) {
631 return ret;
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200632 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200633#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100634 if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
635 &ctx->d, f_rng, p_rng)) != 0) {
636 return ret;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200637 }
638#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100639
Gilles Peskine449bd832023-01-11 14:50:10 +0100640 if (mbedtls_mpi_size(&ctx->z) > blen) {
641 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
642 }
Paul Bakker41c83d32013-03-20 14:39:14 +0100643
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
Janos Follathab0f71a2019-02-20 10:48:49 +0000645
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
647 return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
648 }
Janos Follathab0f71a2019-02-20 10:48:49 +0000649
Gilles Peskine449bd832023-01-11 14:50:10 +0100650 return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100651}
652
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100653/*
654 * Derive and export the shared secret
655 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100656int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
657 unsigned char *buf, size_t blen,
658 int (*f_rng)(void *, unsigned char *, size_t),
659 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100660{
661 int restart_enabled = 0;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100662#if defined(MBEDTLS_ECP_RESTARTABLE)
663 restart_enabled = ctx->restart_enabled;
664#endif
665
666#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100667 return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
668 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100669#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100670 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100671#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
672 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
674 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100675#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100676 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
678 blen, f_rng, p_rng,
679 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100680 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100681 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100682 }
683#endif
684}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685#endif /* MBEDTLS_ECDH_C */