blob: b276c6adadf4c4845950b540c831b2c8e0620f03 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * Elliptic curve Diffie-Hellman
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
Tom Van Eyckc1633172024-04-09 18:44:13 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7
8/*
9 * References:
10 *
Tom Van Eyckc1633172024-04-09 18:44:13 +020011 * SEC1 https://www.secg.org/sec1-v2.pdf
Jens Wiklander817466c2018-05-22 13:49:31 +020012 * RFC 4492
13 */
14
Jerome Forissier79013242021-07-28 10:24:04 +020015#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020016
17#if defined(MBEDTLS_ECDH_C)
18
19#include "mbedtls/ecdh.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010020#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020021#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020022
23#include <string.h>
24
Jens Wiklander3d3b0592019-03-20 15:30:29 +010025#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
26typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
27#endif
28
Jerome Forissier5b25c762020-04-07 11:18:49 +020029static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
Jens Wiklander32b31802023-10-06 16:59:46 +020030 const mbedtls_ecdh_context *ctx)
Jerome Forissier5b25c762020-04-07 11:18:49 +020031{
32#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +020033 return ctx->grp.id;
Jerome Forissier5b25c762020-04-07 11:18:49 +020034#else
Jens Wiklander32b31802023-10-06 16:59:46 +020035 return ctx->grp_id;
Jerome Forissier5b25c762020-04-07 11:18:49 +020036#endif
37}
38
Jens Wiklander32b31802023-10-06 16:59:46 +020039int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
Jerome Forissier11fa71b2020-04-20 17:17:56 +020040{
41 /* At this time, all groups support ECDH. */
42 (void) gid;
Jens Wiklander32b31802023-10-06 16:59:46 +020043 return 1;
Jerome Forissier11fa71b2020-04-20 17:17:56 +020044}
45
Jens Wiklander3d3b0592019-03-20 15:30:29 +010046#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +020047/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +010048 * Generate public key (restartable version)
49 *
50 * Note: this internal function relies on its caller preserving the value of
51 * the output parameter 'd' across continuation calls. This would not be
52 * acceptable for a public function but is OK here as we control call sites.
53 */
Jens Wiklander32b31802023-10-06 16:59:46 +020054static 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)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010059{
Jerome Forissier11fa71b2020-04-20 17:17:56 +020060 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +010061
Jens Wiklander32b31802023-10-06 16:59:46 +020062 int restarting = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +010063#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +020064 restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010065#endif
Jens Wiklander32b31802023-10-06 16:59:46 +020066 /* If multiplication is in progress, we already generated a privkey */
67 if (!restarting) {
68 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
69 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +010070
Jens Wiklander32b31802023-10-06 16:59:46 +020071 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
72 f_rng, p_rng, rs_ctx));
Jens Wiklander3d3b0592019-03-20 15:30:29 +010073
74cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +020075 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +010076}
77
78/*
79 * Generate public key
Jens Wiklander817466c2018-05-22 13:49:31 +020080 */
Jens Wiklander32b31802023-10-06 16:59:46 +020081int 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)
Jens Wiklander817466c2018-05-22 13:49:31 +020084{
Jens Wiklander32b31802023-10-06 16:59:46 +020085 return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
Jens Wiklander817466c2018-05-22 13:49:31 +020086}
Jens Wiklander3d3b0592019-03-20 15:30:29 +010087#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +020088
Jens Wiklander3d3b0592019-03-20 15:30:29 +010089#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +020090/*
91 * Compute shared secret (SEC1 3.3.1)
92 */
Jens Wiklander32b31802023-10-06 16:59:46 +020093static 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)
Jens Wiklander817466c2018-05-22 13:49:31 +020099{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200100 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200101 mbedtls_ecp_point P;
102
Jens Wiklander32b31802023-10-06 16:59:46 +0200103 mbedtls_ecp_point_init(&P);
Jens Wiklander817466c2018-05-22 13:49:31 +0200104
Jens Wiklander32b31802023-10-06 16:59:46 +0200105 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
106 f_rng, p_rng, rs_ctx));
Jens Wiklander817466c2018-05-22 13:49:31 +0200107
Jens Wiklander32b31802023-10-06 16:59:46 +0200108 if (mbedtls_ecp_is_zero(&P)) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200109 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
110 goto cleanup;
111 }
112
Jens Wiklander32b31802023-10-06 16:59:46 +0200113 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
Jens Wiklander817466c2018-05-22 13:49:31 +0200114
115cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200116 mbedtls_ecp_point_free(&P);
Jens Wiklander817466c2018-05-22 13:49:31 +0200117
Jens Wiklander32b31802023-10-06 16:59:46 +0200118 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200119}
120
121/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100122 * Compute shared secret (SEC1 3.3.1)
123 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200124int 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)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100128{
Jens Wiklander32b31802023-10-06 16:59:46 +0200129 return ecdh_compute_shared_restartable(grp, z, Q, d,
130 f_rng, p_rng, NULL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100131}
132#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
133
Jens Wiklander32b31802023-10-06 16:59:46 +0200134static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100135{
Jens Wiklander32b31802023-10-06 16:59:46 +0200136 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);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100141
142#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200143 mbedtls_ecp_restart_init(&ctx->rs);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100144#endif
145}
146
Tom Van Eyckc1633172024-04-09 18:44:13 +0200147mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
148{
149#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
150 return ctx->MBEDTLS_PRIVATE(grp).id;
151#else
152 return ctx->MBEDTLS_PRIVATE(grp_id);
153#endif
154}
155
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100156/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200157 * Initialize context
158 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200159void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200160{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100161#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200162 ecdh_init_internal(ctx);
163 mbedtls_ecp_point_init(&ctx->Vi);
164 mbedtls_ecp_point_init(&ctx->Vf);
165 mbedtls_mpi_init(&ctx->_d);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100166#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200167 memset(ctx, 0, sizeof(mbedtls_ecdh_context));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100168
169 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
170#endif
171 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
172#if defined(MBEDTLS_ECP_RESTARTABLE)
173 ctx->restart_enabled = 0;
174#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200175}
176
Jens Wiklander32b31802023-10-06 16:59:46 +0200177static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
178 mbedtls_ecp_group_id grp_id)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100179{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200180 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100181
Jens Wiklander32b31802023-10-06 16:59:46 +0200182 ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
183 if (ret != 0) {
184 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100185 }
186
Jens Wiklander32b31802023-10-06 16:59:46 +0200187 return 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100188}
189
190/*
191 * Setup context
192 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200193int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100194{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100195#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200196 return ecdh_setup_internal(ctx, grp_id);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100197#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200198 switch (grp_id) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200199#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
200 case MBEDTLS_ECP_DP_CURVE25519:
201 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
202 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
203 ctx->grp_id = grp_id;
Jens Wiklander32b31802023-10-06 16:59:46 +0200204 return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200205#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100206 default:
207 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
208 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
209 ctx->grp_id = grp_id;
Jens Wiklander32b31802023-10-06 16:59:46 +0200210 ecdh_init_internal(&ctx->ctx.mbed_ecdh);
211 return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100212 }
213#endif
214}
215
Jens Wiklander32b31802023-10-06 16:59:46 +0200216static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100217{
Jens Wiklander32b31802023-10-06 16:59:46 +0200218 mbedtls_ecp_group_free(&ctx->grp);
219 mbedtls_mpi_free(&ctx->d);
220 mbedtls_ecp_point_free(&ctx->Q);
221 mbedtls_ecp_point_free(&ctx->Qp);
222 mbedtls_mpi_free(&ctx->z);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100223
224#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200225 mbedtls_ecp_restart_free(&ctx->rs);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100226#endif
227}
228
229#if defined(MBEDTLS_ECP_RESTARTABLE)
230/*
231 * Enable restartable operations for context
232 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200233void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100234{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100235 ctx->restart_enabled = 1;
236}
237#endif
238
Jens Wiklander817466c2018-05-22 13:49:31 +0200239/*
240 * Free context
241 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200242void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200243{
Jens Wiklander32b31802023-10-06 16:59:46 +0200244 if (ctx == NULL) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200245 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200246 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200247
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100248#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200249 mbedtls_ecp_point_free(&ctx->Vi);
250 mbedtls_ecp_point_free(&ctx->Vf);
251 mbedtls_mpi_free(&ctx->_d);
252 ecdh_free_internal(ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100253#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200254 switch (ctx->var) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200255#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
256 case MBEDTLS_ECDH_VARIANT_EVEREST:
Jens Wiklander32b31802023-10-06 16:59:46 +0200257 mbedtls_everest_free(&ctx->ctx.everest_ecdh);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200258 break;
259#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100260 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Jens Wiklander32b31802023-10-06 16:59:46 +0200261 ecdh_free_internal(&ctx->ctx.mbed_ecdh);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100262 break;
263 default:
264 break;
265 }
266
267 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
268 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
269 ctx->grp_id = MBEDTLS_ECP_DP_NONE;
270#endif
271}
272
Jens Wiklander32b31802023-10-06 16:59:46 +0200273static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
274 size_t *olen, int point_format,
275 unsigned char *buf, size_t blen,
276 int (*f_rng)(void *,
277 unsigned char *,
278 size_t),
279 void *p_rng,
280 int restart_enabled)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100281{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200282 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100283 size_t grp_len, pt_len;
284#if defined(MBEDTLS_ECP_RESTARTABLE)
285 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
286#endif
287
Jens Wiklander32b31802023-10-06 16:59:46 +0200288 if (ctx->grp.pbits == 0) {
289 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
290 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100291
292#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200293 if (restart_enabled) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100294 rs_ctx = &ctx->rs;
Jens Wiklander32b31802023-10-06 16:59:46 +0200295 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100296#else
297 (void) restart_enabled;
298#endif
299
300
301#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200302 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
303 f_rng, p_rng, rs_ctx)) != 0) {
304 return ret;
305 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100306#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200307 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
308 f_rng, p_rng)) != 0) {
309 return ret;
310 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100311#endif /* MBEDTLS_ECP_RESTARTABLE */
312
Jens Wiklander32b31802023-10-06 16:59:46 +0200313 if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
314 blen)) != 0) {
315 return ret;
316 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100317
318 buf += grp_len;
319 blen -= grp_len;
320
Jens Wiklander32b31802023-10-06 16:59:46 +0200321 if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
322 &pt_len, buf, blen)) != 0) {
323 return ret;
324 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100325
326 *olen = grp_len + pt_len;
Jens Wiklander32b31802023-10-06 16:59:46 +0200327 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200328}
329
330/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200331 * Setup and write the ServerKeyExchange parameters (RFC 4492)
Jens Wiklander817466c2018-05-22 13:49:31 +0200332 * struct {
333 * ECParameters curve_params;
334 * ECPoint public;
335 * } ServerECDHParams;
336 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200337int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
338 unsigned char *buf, size_t blen,
339 int (*f_rng)(void *, unsigned char *, size_t),
340 void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200341{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100342 int restart_enabled = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100343#if defined(MBEDTLS_ECP_RESTARTABLE)
344 restart_enabled = ctx->restart_enabled;
345#else
346 (void) restart_enabled;
347#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200348
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100349#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200350 return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
351 f_rng, p_rng, restart_enabled);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100352#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200353 switch (ctx->var) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200354#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
355 case MBEDTLS_ECDH_VARIANT_EVEREST:
Jens Wiklander32b31802023-10-06 16:59:46 +0200356 return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
357 buf, blen, f_rng, p_rng);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200358#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100359 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Jens Wiklander32b31802023-10-06 16:59:46 +0200360 return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
361 ctx->point_format, buf, blen,
362 f_rng, p_rng,
363 restart_enabled);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100364 default:
365 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
366 }
367#endif
368}
Jens Wiklander817466c2018-05-22 13:49:31 +0200369
Jens Wiklander32b31802023-10-06 16:59:46 +0200370static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
371 const unsigned char **buf,
372 const unsigned char *end)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100373{
Jens Wiklander32b31802023-10-06 16:59:46 +0200374 return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
Tom Van Eyckc1633172024-04-09 18:44:13 +0200375 (size_t) (end - *buf));
Jens Wiklander817466c2018-05-22 13:49:31 +0200376}
377
378/*
Jerome Forissier039e02d2022-08-09 17:10:15 +0200379 * Read the ServerKeyExchange parameters (RFC 4492)
Jens Wiklander817466c2018-05-22 13:49:31 +0200380 * struct {
381 * ECParameters curve_params;
382 * ECPoint public;
383 * } ServerECDHParams;
384 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200385int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
386 const unsigned char **buf,
387 const unsigned char *end)
Jens Wiklander817466c2018-05-22 13:49:31 +0200388{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200389 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100390 mbedtls_ecp_group_id grp_id;
Tom Van Eyckc1633172024-04-09 18:44:13 +0200391 if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
Jens Wiklander32b31802023-10-06 16:59:46 +0200392 != 0) {
393 return ret;
394 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200395
Jens Wiklander32b31802023-10-06 16:59:46 +0200396 if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
397 return ret;
398 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200399
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100400#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200401 return ecdh_read_params_internal(ctx, buf, end);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100402#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200403 switch (ctx->var) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200404#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
405 case MBEDTLS_ECDH_VARIANT_EVEREST:
Jens Wiklander32b31802023-10-06 16:59:46 +0200406 return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
407 buf, end);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200408#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100409 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Jens Wiklander32b31802023-10-06 16:59:46 +0200410 return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
411 buf, end);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100412 default:
413 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
414 }
415#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200416}
417
Jens Wiklander32b31802023-10-06 16:59:46 +0200418static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
419 const mbedtls_ecp_keypair *key,
420 mbedtls_ecdh_side side)
Jens Wiklander817466c2018-05-22 13:49:31 +0200421{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200422 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200423
Jens Wiklander817466c2018-05-22 13:49:31 +0200424 /* If it's not our key, just import the public part as Qp */
Jens Wiklander32b31802023-10-06 16:59:46 +0200425 if (side == MBEDTLS_ECDH_THEIRS) {
426 return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
427 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200428
429 /* Our key: import public (as Q) and private parts */
Jens Wiklander32b31802023-10-06 16:59:46 +0200430 if (side != MBEDTLS_ECDH_OURS) {
431 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
432 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200433
Jens Wiklander32b31802023-10-06 16:59:46 +0200434 if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
435 (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
436 return ret;
437 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200438
Jens Wiklander32b31802023-10-06 16:59:46 +0200439 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200440}
441
442/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100443 * Get parameters from a keypair
Jens Wiklander817466c2018-05-22 13:49:31 +0200444 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200445int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
446 const mbedtls_ecp_keypair *key,
447 mbedtls_ecdh_side side)
Jens Wiklander817466c2018-05-22 13:49:31 +0200448{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200449 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200450 if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
451 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
452 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200453
Jens Wiklander32b31802023-10-06 16:59:46 +0200454 if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200455 /* This is the first call to get_params(). Set up the context
456 * for use with the group. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200457 if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
458 return ret;
459 }
460 } else {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200461 /* This is not the first call to get_params(). Check that the
462 * current key's group is the same as the context's, which was set
463 * from the first key's group. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200464 if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
465 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
466 }
Jerome Forissier5b25c762020-04-07 11:18:49 +0200467 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200468
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100469#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200470 return ecdh_get_params_internal(ctx, key, side);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100471#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200472 switch (ctx->var) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200473#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
474 case MBEDTLS_ECDH_VARIANT_EVEREST:
475 {
476 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
Jens Wiklander32b31802023-10-06 16:59:46 +0200477 MBEDTLS_EVEREST_ECDH_OURS :
478 MBEDTLS_EVEREST_ECDH_THEIRS;
479 return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
480 key, s);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200481 }
482#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100483 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Jens Wiklander32b31802023-10-06 16:59:46 +0200484 return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
485 key, side);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100486 default:
487 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
488 }
489#endif
490}
491
Jens Wiklander32b31802023-10-06 16:59:46 +0200492static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
493 size_t *olen, int point_format,
494 unsigned char *buf, size_t blen,
495 int (*f_rng)(void *,
496 unsigned char *,
497 size_t),
498 void *p_rng,
499 int restart_enabled)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100500{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200501 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100502#if defined(MBEDTLS_ECP_RESTARTABLE)
503 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
504#endif
505
Jens Wiklander32b31802023-10-06 16:59:46 +0200506 if (ctx->grp.pbits == 0) {
507 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
508 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100509
510#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200511 if (restart_enabled) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100512 rs_ctx = &ctx->rs;
Jens Wiklander32b31802023-10-06 16:59:46 +0200513 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100514#else
515 (void) restart_enabled;
516#endif
517
518#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200519 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
520 f_rng, p_rng, rs_ctx)) != 0) {
521 return ret;
522 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100523#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200524 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
525 f_rng, p_rng)) != 0) {
526 return ret;
527 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100528#endif /* MBEDTLS_ECP_RESTARTABLE */
529
Jens Wiklander32b31802023-10-06 16:59:46 +0200530 return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
531 buf, blen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200532}
533
534/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100535 * Setup and export the client public value
Jens Wiklander817466c2018-05-22 13:49:31 +0200536 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200537int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
538 unsigned char *buf, size_t blen,
539 int (*f_rng)(void *, unsigned char *, size_t),
540 void *p_rng)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100541{
542 int restart_enabled = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100543#if defined(MBEDTLS_ECP_RESTARTABLE)
544 restart_enabled = ctx->restart_enabled;
545#endif
546
547#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200548 return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
549 f_rng, p_rng, restart_enabled);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100550#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200551 switch (ctx->var) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200552#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
553 case MBEDTLS_ECDH_VARIANT_EVEREST:
Jens Wiklander32b31802023-10-06 16:59:46 +0200554 return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
555 buf, blen, f_rng, p_rng);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200556#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100557 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Jens Wiklander32b31802023-10-06 16:59:46 +0200558 return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
559 ctx->point_format, buf, blen,
560 f_rng, p_rng,
561 restart_enabled);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100562 default:
563 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
564 }
565#endif
566}
567
Jens Wiklander32b31802023-10-06 16:59:46 +0200568static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
569 const unsigned char *buf, size_t blen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200570{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200571 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200572 const unsigned char *p = buf;
573
Jens Wiklander32b31802023-10-06 16:59:46 +0200574 if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
575 blen)) != 0) {
576 return ret;
577 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200578
Jens Wiklander32b31802023-10-06 16:59:46 +0200579 if ((size_t) (p - buf) != blen) {
580 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
581 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200582
Jens Wiklander32b31802023-10-06 16:59:46 +0200583 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200584}
585
586/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100587 * Parse and import the client's public value
Jens Wiklander817466c2018-05-22 13:49:31 +0200588 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200589int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
590 const unsigned char *buf, size_t blen)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100591{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100592#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200593 return ecdh_read_public_internal(ctx, buf, blen);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100594#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200595 switch (ctx->var) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200596#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
597 case MBEDTLS_ECDH_VARIANT_EVEREST:
Jens Wiklander32b31802023-10-06 16:59:46 +0200598 return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
599 buf, blen);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200600#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100601 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Jens Wiklander32b31802023-10-06 16:59:46 +0200602 return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
603 buf, blen);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100604 default:
605 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
606 }
607#endif
608}
609
Jens Wiklander32b31802023-10-06 16:59:46 +0200610static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
611 size_t *olen, unsigned char *buf,
612 size_t blen,
613 int (*f_rng)(void *,
614 unsigned char *,
615 size_t),
616 void *p_rng,
617 int restart_enabled)
Jens Wiklander817466c2018-05-22 13:49:31 +0200618{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200619 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100620#if defined(MBEDTLS_ECP_RESTARTABLE)
621 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
622#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200623
Jens Wiklander32b31802023-10-06 16:59:46 +0200624 if (ctx == NULL || ctx->grp.pbits == 0) {
625 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
626 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200627
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100628#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200629 if (restart_enabled) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100630 rs_ctx = &ctx->rs;
Jens Wiklander32b31802023-10-06 16:59:46 +0200631 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100632#else
633 (void) restart_enabled;
634#endif
635
636#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200637 if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
638 &ctx->d, f_rng, p_rng,
639 rs_ctx)) != 0) {
640 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200641 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100642#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200643 if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
644 &ctx->d, f_rng, p_rng)) != 0) {
645 return ret;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100646 }
647#endif /* MBEDTLS_ECP_RESTARTABLE */
Jens Wiklander817466c2018-05-22 13:49:31 +0200648
Jens Wiklander32b31802023-10-06 16:59:46 +0200649 if (mbedtls_mpi_size(&ctx->z) > blen) {
650 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200652
Jens Wiklander32b31802023-10-06 16:59:46 +0200653 *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200654
Jens Wiklander32b31802023-10-06 16:59:46 +0200655 if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
656 return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
657 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200658
Jens Wiklander32b31802023-10-06 16:59:46 +0200659 return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
Jens Wiklander817466c2018-05-22 13:49:31 +0200660}
661
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100662/*
663 * Derive and export the shared secret
664 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200665int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
666 unsigned char *buf, size_t blen,
667 int (*f_rng)(void *, unsigned char *, size_t),
668 void *p_rng)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100669{
670 int restart_enabled = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100671#if defined(MBEDTLS_ECP_RESTARTABLE)
672 restart_enabled = ctx->restart_enabled;
673#endif
674
675#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200676 return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
677 restart_enabled);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100678#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200679 switch (ctx->var) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200680#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
681 case MBEDTLS_ECDH_VARIANT_EVEREST:
Jens Wiklander32b31802023-10-06 16:59:46 +0200682 return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
683 buf, blen, f_rng, p_rng);
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200684#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100685 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Jens Wiklander32b31802023-10-06 16:59:46 +0200686 return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
687 blen, f_rng, p_rng,
688 restart_enabled);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100689 default:
Jens Wiklander32b31802023-10-06 16:59:46 +0200690 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100691 }
692#endif
693}
Jens Wiklander817466c2018-05-22 13:49:31 +0200694#endif /* MBEDTLS_ECDH_C */