blob: 28fe757eab0a8a80add344bde14632074098b767 [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
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010046/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020047 * Generate public key (restartable version)
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020048 *
49 * Note: this internal function relies on its caller preserving the value of
Manuel Pégourié-Gonnardca29fdf2018-10-22 09:56:53 +020050 * the output parameter 'd' across continuation calls. This would not be
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020051 * acceptable for a public function but is OK here as we control call sites.
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020052 */
Gilles Peskine449bd832023-01-11 14:50:10 +010053static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
54 mbedtls_mpi *d, mbedtls_ecp_point *Q,
55 int (*f_rng)(void *, unsigned char *, size_t),
56 void *p_rng,
57 mbedtls_ecp_restart_ctx *rs_ctx)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020058{
Janos Follath24eed8d2019-11-22 13:21:35 +000059 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020060
David Horstmann91e20a02022-10-06 19:11:28 +010061 int restarting = 0;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020062#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +010063 restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020064#endif
David Horstmann91e20a02022-10-06 19:11:28 +010065 /* If multiplication is in progress, we already generated a privkey */
Gilles Peskine449bd832023-01-11 14:50:10 +010066 if (!restarting) {
67 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
68 }
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020069
Gilles Peskine449bd832023-01-11 14:50:10 +010070 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
71 f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020072
73cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +010074 return ret;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020075}
76
77/*
78 * Generate public key
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010079 */
Gilles Peskine449bd832023-01-11 14:50:10 +010080int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
81 int (*f_rng)(void *, unsigned char *, size_t),
82 void *p_rng)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010083{
Gilles Peskine449bd832023-01-11 14:50:10 +010084 return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010085}
86
87/*
88 * Compute shared secret (SEC1 3.3.1)
89 */
Gilles Peskine449bd832023-01-11 14:50:10 +010090static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
91 mbedtls_mpi *z,
92 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
93 int (*f_rng)(void *, unsigned char *, size_t),
94 void *p_rng,
95 mbedtls_ecp_restart_ctx *rs_ctx)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010096{
Janos Follath24eed8d2019-11-22 13:21:35 +000097 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098 mbedtls_ecp_point P;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010099
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 mbedtls_ecp_point_init(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100101
Gilles Peskine449bd832023-01-11 14:50:10 +0100102 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
103 f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100104
Gilles Peskine449bd832023-01-11 14:50:10 +0100105 if (mbedtls_ecp_is_zero(&P)) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakkerb548d772013-07-26 14:21:34 +0200107 goto cleanup;
108 }
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100109
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100111
112cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 mbedtls_ecp_point_free(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100114
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 return ret;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100116}
117
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100118/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200119 * Compute shared secret (SEC1 3.3.1)
120 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100121int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
122 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
123 int (*f_rng)(void *, unsigned char *, size_t),
124 void *p_rng)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200125{
Gilles Peskine449bd832023-01-11 14:50:10 +0100126 return ecdh_compute_shared_restartable(grp, z, Q, d,
127 f_rng, p_rng, NULL);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200128}
129
Gilles Peskine449bd832023-01-11 14:50:10 +0100130static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100131{
Gilles Peskine449bd832023-01-11 14:50:10 +0100132 mbedtls_ecp_group_init(&ctx->grp);
133 mbedtls_mpi_init(&ctx->d);
134 mbedtls_ecp_point_init(&ctx->Q);
135 mbedtls_ecp_point_init(&ctx->Qp);
136 mbedtls_mpi_init(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200137
138#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 mbedtls_ecp_restart_init(&ctx->rs);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200140#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100141}
142
Minos Galanakisd7537382024-02-23 12:17:59 +0000143mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
144{
145#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
146 return ctx->MBEDTLS_PRIVATE(grp).id;
147#else
148 return ctx->MBEDTLS_PRIVATE(grp_id);
149#endif
150}
151
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100152/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100153 * Initialize context
Janos Follathf61e4862018-10-30 11:53:25 +0000154 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100155void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100156{
157#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100158 ecdh_init_internal(ctx);
159 mbedtls_ecp_point_init(&ctx->Vi);
160 mbedtls_ecp_point_init(&ctx->Vf);
161 mbedtls_mpi_init(&ctx->_d);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100162#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 memset(ctx, 0, sizeof(mbedtls_ecdh_context));
Christoph M. Wintersteigerd8c45d52019-02-20 17:16:53 +0000164
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100165 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
166#endif
167 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
168#if defined(MBEDTLS_ECP_RESTARTABLE)
169 ctx->restart_enabled = 0;
170#endif
171}
172
Gilles Peskine449bd832023-01-11 14:50:10 +0100173static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
174 mbedtls_ecp_group_id grp_id)
Janos Follathf61e4862018-10-30 11:53:25 +0000175{
Janos Follath24eed8d2019-11-22 13:21:35 +0000176 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000177
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
179 if (ret != 0) {
180 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Janos Follathf61e4862018-10-30 11:53:25 +0000181 }
182
Gilles Peskine449bd832023-01-11 14:50:10 +0100183 return 0;
Janos Follathf61e4862018-10-30 11:53:25 +0000184}
185
186/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100187 * Setup context
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100188 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100189int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100190{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100191#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100192 return ecdh_setup_internal(ctx, grp_id);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100193#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 switch (grp_id) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100195#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000196 case MBEDTLS_ECP_DP_CURVE25519:
197 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
198 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
199 ctx->grp_id = grp_id;
Gilles Peskine449bd832023-01-11 14:50:10 +0100200 return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
Christoph M. Wintersteiger78c9c462018-12-06 17:16:32 +0000201#endif
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000202 default:
203 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
204 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
205 ctx->grp_id = grp_id;
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 ecdh_init_internal(&ctx->ctx.mbed_ecdh);
207 return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100208 }
209#endif
210}
211
Gilles Peskine449bd832023-01-11 14:50:10 +0100212static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100213{
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 mbedtls_ecp_group_free(&ctx->grp);
215 mbedtls_mpi_free(&ctx->d);
216 mbedtls_ecp_point_free(&ctx->Q);
217 mbedtls_ecp_point_free(&ctx->Qp);
218 mbedtls_mpi_free(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200219
220#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 mbedtls_ecp_restart_free(&ctx->rs);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200222#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100223}
224
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200225#if defined(MBEDTLS_ECP_RESTARTABLE)
226/*
227 * Enable restartable operations for context
228 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100229void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200230{
231 ctx->restart_enabled = 1;
232}
233#endif
234
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100235/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100236 * Free context
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100237 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100238void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100239{
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 if (ctx == NULL) {
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100241 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100243
244#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100245 mbedtls_ecp_point_free(&ctx->Vi);
246 mbedtls_ecp_point_free(&ctx->Vf);
247 mbedtls_mpi_free(&ctx->_d);
248 ecdh_free_internal(ctx);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100249#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100251#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
252 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100253 mbedtls_everest_free(&ctx->ctx.everest_ecdh);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100254 break;
255#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100256 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 ecdh_free_internal(&ctx->ctx.mbed_ecdh);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100258 break;
259 default:
260 break;
261 }
262
263 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
264 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
265 ctx->grp_id = MBEDTLS_ECP_DP_NONE;
266#endif
267}
268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
270 size_t *olen, int point_format,
271 unsigned char *buf, size_t blen,
272 int (*f_rng)(void *,
273 unsigned char *,
274 size_t),
275 void *p_rng,
276 int restart_enabled)
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100277{
Janos Follath24eed8d2019-11-22 13:21:35 +0000278 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100279 size_t grp_len, pt_len;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200280#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200281 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200282#endif
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 if (ctx->grp.pbits == 0) {
285 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
286 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100287
Ron Eldor19779c42018-11-05 16:58:13 +0200288#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200290 rs_ctx = &ctx->rs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100292#else
293 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200294#endif
295
Ron Eldor8493f802018-11-01 11:32:15 +0200296
Ron Eldor2981d8f2018-11-05 18:07:10 +0200297#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
299 f_rng, p_rng, rs_ctx)) != 0) {
300 return ret;
301 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200302#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
304 f_rng, p_rng)) != 0) {
305 return ret;
306 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200307#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100308
Gilles Peskine449bd832023-01-11 14:50:10 +0100309 if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
310 blen)) != 0) {
311 return ret;
312 }
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100313
314 buf += grp_len;
315 blen -= grp_len;
316
Gilles Peskine449bd832023-01-11 14:50:10 +0100317 if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
318 &pt_len, buf, blen)) != 0) {
319 return ret;
320 }
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100321
322 *olen = grp_len + pt_len;
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 return 0;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100324}
325
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100326/*
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100327 * Setup and write the ServerKeyExchange parameters (RFC 4492)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100328 * struct {
329 * ECParameters curve_params;
330 * ECPoint public;
331 * } ServerECDHParams;
332 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100333int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
334 unsigned char *buf, size_t blen,
335 int (*f_rng)(void *, unsigned char *, size_t),
336 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100337{
338 int restart_enabled = 0;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100339#if defined(MBEDTLS_ECP_RESTARTABLE)
340 restart_enabled = ctx->restart_enabled;
341#else
342 (void) restart_enabled;
343#endif
344
345#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
347 f_rng, p_rng, restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100348#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100350#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
351 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
353 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100354#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100355 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
357 ctx->point_format, buf, blen,
358 f_rng, p_rng,
359 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100360 default:
361 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
362 }
363#endif
364}
365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
367 const unsigned char **buf,
368 const unsigned char *end)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100369{
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000371 (size_t) (end - *buf));
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100372}
373
374/*
bootstrap-prime6dbbf442022-05-17 19:30:44 -0400375 * Read the ServerKeyExchange parameters (RFC 4492)
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100376 * struct {
377 * ECParameters curve_params;
378 * ECPoint public;
379 * } ServerECDHParams;
380 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100381int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
382 const unsigned char **buf,
383 const unsigned char *end)
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100384{
Janos Follath24eed8d2019-11-22 13:21:35 +0000385 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000386 mbedtls_ecp_group_id grp_id;
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000387 if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
Gilles Peskine449bd832023-01-11 14:50:10 +0100388 != 0) {
389 return ret;
390 }
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100391
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
393 return ret;
394 }
Janos Follathf61e4862018-10-30 11:53:25 +0000395
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100396#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 return ecdh_read_params_internal(ctx, buf, end);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100398#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100400#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
401 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
403 buf, end);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100404#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100405 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
407 buf, end);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100408 default:
409 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
410 }
411#endif
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100412}
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +0100413
Gilles Peskine449bd832023-01-11 14:50:10 +0100414static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
415 const mbedtls_ecp_keypair *key,
416 mbedtls_ecdh_side side)
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100417{
Janos Follath24eed8d2019-11-22 13:21:35 +0000418 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100419
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100420 /* If it's not our key, just import the public part as Qp */
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 if (side == MBEDTLS_ECDH_THEIRS) {
422 return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
423 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100424
425 /* Our key: import public (as Q) and private parts */
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 if (side != MBEDTLS_ECDH_OURS) {
427 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
428 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100429
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
431 (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
432 return ret;
433 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100434
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 return 0;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100436}
437
438/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100439 * Get parameters from a keypair
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100440 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100441int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
442 const mbedtls_ecp_keypair *key,
443 mbedtls_ecdh_side side)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100444{
Janos Follath24eed8d2019-11-22 13:21:35 +0000445 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
447 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
448 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100449
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100451 /* This is the first call to get_params(). Set up the context
452 * for use with the group. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100453 if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
454 return ret;
455 }
456 } else {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100457 /* This is not the first call to get_params(). Check that the
458 * current key's group is the same as the context's, which was set
459 * from the first key's group. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
461 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
462 }
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100463 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100464
465#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 return ecdh_get_params_internal(ctx, key, side);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100467#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100469#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
470 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000471 {
Christoph M. Wintersteiger2e724a12019-01-07 14:19:41 +0000472 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 MBEDTLS_EVEREST_ECDH_OURS :
474 MBEDTLS_EVEREST_ECDH_THEIRS;
475 return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
476 key, s);
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000477 }
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100478#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100479 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
481 key, side);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100482 default:
483 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
484 }
485#endif
486}
487
Gilles Peskine449bd832023-01-11 14:50:10 +0100488static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
489 size_t *olen, int point_format,
490 unsigned char *buf, size_t blen,
491 int (*f_rng)(void *,
492 unsigned char *,
493 size_t),
494 void *p_rng,
495 int restart_enabled)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100496{
Janos Follath24eed8d2019-11-22 13:21:35 +0000497 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200498#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200499 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200500#endif
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 if (ctx->grp.pbits == 0) {
503 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
504 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100505
Ron Eldorb430d9f2018-11-05 17:18:29 +0200506#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200508 rs_ctx = &ctx->rs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100509 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100510#else
511 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200512#endif
513
Ron Eldor2981d8f2018-11-05 18:07:10 +0200514#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
516 f_rng, p_rng, rs_ctx)) != 0) {
517 return ret;
518 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200519#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
521 f_rng, p_rng)) != 0) {
522 return ret;
523 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200524#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100525
Gilles Peskine449bd832023-01-11 14:50:10 +0100526 return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
527 buf, blen);
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100528}
529
530/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100531 * Setup and export the client public value
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100532 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100533int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
534 unsigned char *buf, size_t blen,
535 int (*f_rng)(void *, unsigned char *, size_t),
536 void *p_rng)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100537{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100538 int restart_enabled = 0;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100539#if defined(MBEDTLS_ECP_RESTARTABLE)
540 restart_enabled = ctx->restart_enabled;
541#endif
542
543#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100544 return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
545 f_rng, p_rng, restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100546#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100548#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
549 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
551 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100552#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100553 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
555 ctx->point_format, buf, blen,
556 f_rng, p_rng,
557 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100558 default:
559 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
560 }
561#endif
562}
563
Gilles Peskine449bd832023-01-11 14:50:10 +0100564static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
565 const unsigned char *buf, size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100566{
Janos Follath24eed8d2019-11-22 13:21:35 +0000567 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100568 const unsigned char *p = buf;
569
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
571 blen)) != 0) {
572 return ret;
573 }
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100574
Gilles Peskine449bd832023-01-11 14:50:10 +0100575 if ((size_t) (p - buf) != blen) {
576 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
577 }
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100578
Gilles Peskine449bd832023-01-11 14:50:10 +0100579 return 0;
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100580}
581
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100582/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100583 * Parse and import the client's public value
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100584 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100585int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
586 const unsigned char *buf, size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100587{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100588#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 return ecdh_read_public_internal(ctx, buf, blen);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100590#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100591 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100592#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
593 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100594 return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
595 buf, blen);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100596#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100597 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100598 return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
599 buf, blen);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100600 default:
601 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
602 }
603#endif
604}
605
Gilles Peskine449bd832023-01-11 14:50:10 +0100606static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
607 size_t *olen, unsigned char *buf,
608 size_t blen,
609 int (*f_rng)(void *,
610 unsigned char *,
611 size_t),
612 void *p_rng,
613 int restart_enabled)
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100614{
Janos Follath24eed8d2019-11-22 13:21:35 +0000615 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200616#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200617 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200618#endif
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100619
Gilles Peskine449bd832023-01-11 14:50:10 +0100620 if (ctx == NULL || ctx->grp.pbits == 0) {
621 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
622 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100623
Ron Eldorb430d9f2018-11-05 17:18:29 +0200624#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100625 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200626 rs_ctx = &ctx->rs;
Gilles Peskine449bd832023-01-11 14:50:10 +0100627 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100628#else
629 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200630#endif
631
Ron Eldor2981d8f2018-11-05 18:07:10 +0200632#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
634 &ctx->d, f_rng, p_rng,
635 rs_ctx)) != 0) {
636 return ret;
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200637 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200638#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
640 &ctx->d, f_rng, p_rng)) != 0) {
641 return ret;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200642 }
643#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100644
Gilles Peskine449bd832023-01-11 14:50:10 +0100645 if (mbedtls_mpi_size(&ctx->z) > blen) {
646 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
647 }
Paul Bakker41c83d32013-03-20 14:39:14 +0100648
Gilles Peskine449bd832023-01-11 14:50:10 +0100649 *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
Janos Follathab0f71a2019-02-20 10:48:49 +0000650
Gilles Peskine449bd832023-01-11 14:50:10 +0100651 if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
652 return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
653 }
Janos Follathab0f71a2019-02-20 10:48:49 +0000654
Gilles Peskine449bd832023-01-11 14:50:10 +0100655 return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100656}
657
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100658/*
659 * Derive and export the shared secret
660 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100661int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
662 unsigned char *buf, size_t blen,
663 int (*f_rng)(void *, unsigned char *, size_t),
664 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100665{
666 int restart_enabled = 0;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100667#if defined(MBEDTLS_ECP_RESTARTABLE)
668 restart_enabled = ctx->restart_enabled;
669#endif
670
671#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine449bd832023-01-11 14:50:10 +0100672 return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
673 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100674#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100675 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100676#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
677 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine449bd832023-01-11 14:50:10 +0100678 return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
679 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100680#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100681 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
683 blen, f_rng, p_rng,
684 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100685 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100686 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100687 }
688#endif
689}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690#endif /* MBEDTLS_ECDH_C */