blob: 29a732a08fddab0ff1aa452ea4f0176e15ac60ae [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 Rodgman7ff79652023-11-03 12:04:52 +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 Qian0e5a27b2023-04-21 09:58:07 +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"
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010022
Rich Evans00ab4702015-02-06 13:43:58 +000023#include <string.h>
24
Hanno Becker91796d72018-12-17 18:10:51 +000025/* Parameter validation macros based on platform_util.h */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010026#define ECDH_VALIDATE_RET(cond) \
27 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA)
28#define ECDH_VALIDATE(cond) \
29 MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker91796d72018-12-17 18:10:51 +000030
Janos Follath5a3e1bf2018-08-13 15:54:22 +010031#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
32typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
33#endif
34
Gilles Peskine30816292019-02-22 12:31:25 +010035static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010036 const mbedtls_ecdh_context *ctx)
Gilles Peskine30816292019-02-22 12:31:25 +010037{
38#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010039 return ctx->grp.id;
Gilles Peskine30816292019-02-22 12:31:25 +010040#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010041 return ctx->grp_id;
Gilles Peskine30816292019-02-22 12:31:25 +010042#endif
43}
44
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010045int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
Gilles Peskine20b3ef32019-02-11 18:41:27 +010046{
47 /* At this time, all groups support ECDH. */
48 (void) gid;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010049 return 1;
Gilles Peskine20b3ef32019-02-11 18:41:27 +010050}
51
Ron Eldora84c1cb2017-10-10 19:04:27 +030052#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010053/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020054 * Generate public key (restartable version)
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020055 *
56 * Note: this internal function relies on its caller preserving the value of
Manuel Pégourié-Gonnardca29fdf2018-10-22 09:56:53 +020057 * the output parameter 'd' across continuation calls. This would not be
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020058 * acceptable for a public function but is OK here as we control call sites.
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020059 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010060static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
61 mbedtls_mpi *d, mbedtls_ecp_point *Q,
62 int (*f_rng)(void *, unsigned char *, size_t),
63 void *p_rng,
64 mbedtls_ecp_restart_ctx *rs_ctx)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020065{
Janos Follath24eed8d2019-11-22 13:21:35 +000066 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020067
David Horstmannd2091972022-10-06 19:11:28 +010068 int restarting = 0;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020069#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010070 restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020071#endif
David Horstmannd2091972022-10-06 19:11:28 +010072 /* If multiplication is in progress, we already generated a privkey */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010073 if (!restarting) {
74 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
75 }
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020076
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010077 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
78 f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020079
80cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010081 return ret;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020082}
83
84/*
85 * Generate public key
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010086 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010087int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
88 int (*f_rng)(void *, unsigned char *, size_t),
89 void *p_rng)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010090{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010091 ECDH_VALIDATE_RET(grp != NULL);
92 ECDH_VALIDATE_RET(d != NULL);
93 ECDH_VALIDATE_RET(Q != NULL);
94 ECDH_VALIDATE_RET(f_rng != NULL);
95 return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010096}
Ron Eldor936d2842018-11-01 13:05:52 +020097#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010098
Ron Eldora84c1cb2017-10-10 19:04:27 +030099#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100100/*
101 * Compute shared secret (SEC1 3.3.1)
102 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100103static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
104 mbedtls_mpi *z,
105 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
106 int (*f_rng)(void *, unsigned char *, size_t),
107 void *p_rng,
108 mbedtls_ecp_restart_ctx *rs_ctx)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100109{
Janos Follath24eed8d2019-11-22 13:21:35 +0000110 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 mbedtls_ecp_point P;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100112
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100113 mbedtls_ecp_point_init(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100114
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100115 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
116 f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100117
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100118 if (mbedtls_ecp_is_zero(&P)) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakkerb548d772013-07-26 14:21:34 +0200120 goto cleanup;
121 }
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100122
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100123 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100124
125cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100126 mbedtls_ecp_point_free(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100127
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100128 return ret;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100129}
130
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100131/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200132 * Compute shared secret (SEC1 3.3.1)
133 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100134int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
135 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
136 int (*f_rng)(void *, unsigned char *, size_t),
137 void *p_rng)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200138{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100139 ECDH_VALIDATE_RET(grp != NULL);
140 ECDH_VALIDATE_RET(Q != NULL);
141 ECDH_VALIDATE_RET(d != NULL);
142 ECDH_VALIDATE_RET(z != NULL);
143 return ecdh_compute_shared_restartable(grp, z, Q, d,
144 f_rng, p_rng, NULL);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200145}
Ron Eldor936d2842018-11-01 13:05:52 +0200146#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200147
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100148static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100149{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100150 mbedtls_ecp_group_init(&ctx->grp);
151 mbedtls_mpi_init(&ctx->d);
152 mbedtls_ecp_point_init(&ctx->Q);
153 mbedtls_ecp_point_init(&ctx->Qp);
154 mbedtls_mpi_init(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200155
156#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100157 mbedtls_ecp_restart_init(&ctx->rs);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200158#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100159}
160
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100161/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100162 * Initialize context
Janos Follathf61e4862018-10-30 11:53:25 +0000163 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100164void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100165{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100166 ECDH_VALIDATE(ctx != NULL);
Hanno Becker91796d72018-12-17 18:10:51 +0000167
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100168#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100169 ecdh_init_internal(ctx);
170 mbedtls_ecp_point_init(&ctx->Vi);
171 mbedtls_ecp_point_init(&ctx->Vf);
172 mbedtls_mpi_init(&ctx->_d);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100173#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100174 memset(ctx, 0, sizeof(mbedtls_ecdh_context));
Christoph M. Wintersteigerd8c45d52019-02-20 17:16:53 +0000175
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100176 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
177#endif
178 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
179#if defined(MBEDTLS_ECP_RESTARTABLE)
180 ctx->restart_enabled = 0;
181#endif
182}
183
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100184static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
185 mbedtls_ecp_group_id grp_id)
Janos Follathf61e4862018-10-30 11:53:25 +0000186{
Janos Follath24eed8d2019-11-22 13:21:35 +0000187 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000188
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100189 ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
190 if (ret != 0) {
191 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Janos Follathf61e4862018-10-30 11:53:25 +0000192 }
193
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100194 return 0;
Janos Follathf61e4862018-10-30 11:53:25 +0000195}
196
197/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100198 * Setup context
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100199 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100201{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100202 ECDH_VALIDATE_RET(ctx != NULL);
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100203
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100204#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100205 return ecdh_setup_internal(ctx, grp_id);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100206#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100207 switch (grp_id) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100208#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000209 case MBEDTLS_ECP_DP_CURVE25519:
210 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
211 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
212 ctx->grp_id = grp_id;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100213 return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
Christoph M. Wintersteiger78c9c462018-12-06 17:16:32 +0000214#endif
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000215 default:
216 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
217 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
218 ctx->grp_id = grp_id;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 ecdh_init_internal(&ctx->ctx.mbed_ecdh);
220 return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100221 }
222#endif
223}
224
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100225static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100226{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100227 mbedtls_ecp_group_free(&ctx->grp);
228 mbedtls_mpi_free(&ctx->d);
229 mbedtls_ecp_point_free(&ctx->Q);
230 mbedtls_ecp_point_free(&ctx->Qp);
231 mbedtls_mpi_free(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200232
233#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100234 mbedtls_ecp_restart_free(&ctx->rs);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200235#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100236}
237
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200238#if defined(MBEDTLS_ECP_RESTARTABLE)
239/*
240 * Enable restartable operations for context
241 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100242void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200243{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100244 ECDH_VALIDATE(ctx != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100245
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200246 ctx->restart_enabled = 1;
247}
248#endif
249
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100250/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100251 * Free context
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100252 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100253void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100254{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100255 if (ctx == NULL) {
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100256 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100257 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100258
259#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100260 mbedtls_ecp_point_free(&ctx->Vi);
261 mbedtls_ecp_point_free(&ctx->Vf);
262 mbedtls_mpi_free(&ctx->_d);
263 ecdh_free_internal(ctx);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100264#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100265 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100266#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
267 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100268 mbedtls_everest_free(&ctx->ctx.everest_ecdh);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100269 break;
270#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100271 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 ecdh_free_internal(&ctx->ctx.mbed_ecdh);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100273 break;
274 default:
275 break;
276 }
277
278 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
279 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
280 ctx->grp_id = MBEDTLS_ECP_DP_NONE;
281#endif
282}
283
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100284static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
285 size_t *olen, int point_format,
286 unsigned char *buf, size_t blen,
287 int (*f_rng)(void *,
288 unsigned char *,
289 size_t),
290 void *p_rng,
291 int restart_enabled)
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100292{
Janos Follath24eed8d2019-11-22 13:21:35 +0000293 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100294 size_t grp_len, pt_len;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200295#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200296 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200297#endif
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100298
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100299 if (ctx->grp.pbits == 0) {
300 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
301 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100302
Ron Eldor19779c42018-11-05 16:58:13 +0200303#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100304 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200305 rs_ctx = &ctx->rs;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100306 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100307#else
308 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200309#endif
310
Ron Eldor8493f802018-11-01 11:32:15 +0200311
Ron Eldor2981d8f2018-11-05 18:07:10 +0200312#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
314 f_rng, p_rng, rs_ctx)) != 0) {
315 return ret;
316 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200317#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100318 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
319 f_rng, p_rng)) != 0) {
320 return ret;
321 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200322#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100323
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100324 if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
325 blen)) != 0) {
326 return ret;
327 }
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100328
329 buf += grp_len;
330 blen -= grp_len;
331
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100332 if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
333 &pt_len, buf, blen)) != 0) {
334 return ret;
335 }
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100336
337 *olen = grp_len + pt_len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100338 return 0;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100339}
340
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100341/*
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100342 * Setup and write the ServerKeyExchange parameters (RFC 4492)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100343 * struct {
344 * ECParameters curve_params;
345 * ECPoint public;
346 * } ServerECDHParams;
347 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100348int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
349 unsigned char *buf, size_t blen,
350 int (*f_rng)(void *, unsigned char *, size_t),
351 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100352{
353 int restart_enabled = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100354 ECDH_VALIDATE_RET(ctx != NULL);
355 ECDH_VALIDATE_RET(olen != NULL);
356 ECDH_VALIDATE_RET(buf != NULL);
357 ECDH_VALIDATE_RET(f_rng != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100358
359#if defined(MBEDTLS_ECP_RESTARTABLE)
360 restart_enabled = ctx->restart_enabled;
361#else
362 (void) restart_enabled;
363#endif
364
365#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100366 return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
367 f_rng, p_rng, restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100368#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100369 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100370#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
371 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100372 return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
373 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100374#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100375 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100376 return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
377 ctx->point_format, buf, blen,
378 f_rng, p_rng,
379 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100380 default:
381 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
382 }
383#endif
384}
385
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100386static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
387 const unsigned char **buf,
388 const unsigned char *end)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100389{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100390 return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
391 end - *buf);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100392}
393
394/*
bootstrap-prime7ef96ea2022-05-18 14:08:33 -0400395 * Read the ServerKeyExchange parameters (RFC 4492)
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100396 * struct {
397 * ECParameters curve_params;
398 * ECPoint public;
399 * } ServerECDHParams;
400 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100401int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
402 const unsigned char **buf,
403 const unsigned char *end)
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100404{
Janos Follath24eed8d2019-11-22 13:21:35 +0000405 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000406 mbedtls_ecp_group_id grp_id;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100407 ECDH_VALIDATE_RET(ctx != NULL);
408 ECDH_VALIDATE_RET(buf != NULL);
409 ECDH_VALIDATE_RET(*buf != NULL);
410 ECDH_VALIDATE_RET(end != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100411
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100412 if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, end - *buf))
413 != 0) {
414 return ret;
415 }
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100416
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100417 if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
418 return ret;
419 }
Janos Follathf61e4862018-10-30 11:53:25 +0000420
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100421#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100422 return ecdh_read_params_internal(ctx, buf, end);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100423#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100424 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100425#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
426 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100427 return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
428 buf, end);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100429#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100430 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100431 return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
432 buf, end);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100433 default:
434 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
435 }
436#endif
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100437}
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +0100438
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100439static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
440 const mbedtls_ecp_keypair *key,
441 mbedtls_ecdh_side side)
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100442{
Janos Follath24eed8d2019-11-22 13:21:35 +0000443 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100444
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100445 /* If it's not our key, just import the public part as Qp */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100446 if (side == MBEDTLS_ECDH_THEIRS) {
447 return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
448 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100449
450 /* Our key: import public (as Q) and private parts */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100451 if (side != MBEDTLS_ECDH_OURS) {
452 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
453 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100454
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100455 if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
456 (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
457 return ret;
458 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100459
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100460 return 0;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100461}
462
463/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100464 * Get parameters from a keypair
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100465 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100466int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
467 const mbedtls_ecp_keypair *key,
468 mbedtls_ecdh_side side)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100469{
Janos Follath24eed8d2019-11-22 13:21:35 +0000470 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100471 ECDH_VALIDATE_RET(ctx != NULL);
472 ECDH_VALIDATE_RET(key != NULL);
473 ECDH_VALIDATE_RET(side == MBEDTLS_ECDH_OURS ||
474 side == MBEDTLS_ECDH_THEIRS);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100475
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100476 if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100477 /* This is the first call to get_params(). Set up the context
478 * for use with the group. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100479 if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
480 return ret;
481 }
482 } else {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100483 /* This is not the first call to get_params(). Check that the
484 * current key's group is the same as the context's, which was set
485 * from the first key's group. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100486 if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
487 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
488 }
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100489 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100490
491#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100492 return ecdh_get_params_internal(ctx, key, side);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100493#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100494 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100495#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
496 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000497 {
Christoph M. Wintersteiger2e724a12019-01-07 14:19:41 +0000498 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100499 MBEDTLS_EVEREST_ECDH_OURS :
500 MBEDTLS_EVEREST_ECDH_THEIRS;
501 return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
502 key, s);
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000503 }
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100504#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100505 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100506 return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
507 key, side);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100508 default:
509 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
510 }
511#endif
512}
513
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100514static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
515 size_t *olen, int point_format,
516 unsigned char *buf, size_t blen,
517 int (*f_rng)(void *,
518 unsigned char *,
519 size_t),
520 void *p_rng,
521 int restart_enabled)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100522{
Janos Follath24eed8d2019-11-22 13:21:35 +0000523 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200524#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200525 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200526#endif
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100527
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100528 if (ctx->grp.pbits == 0) {
529 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
530 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100531
Ron Eldorb430d9f2018-11-05 17:18:29 +0200532#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100533 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200534 rs_ctx = &ctx->rs;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100535 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100536#else
537 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200538#endif
539
Ron Eldor2981d8f2018-11-05 18:07:10 +0200540#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100541 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
542 f_rng, p_rng, rs_ctx)) != 0) {
543 return ret;
544 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200545#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100546 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
547 f_rng, p_rng)) != 0) {
548 return ret;
549 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200550#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100551
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100552 return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
553 buf, blen);
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100554}
555
556/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100557 * Setup and export the client public value
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100558 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100559int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
560 unsigned char *buf, size_t blen,
561 int (*f_rng)(void *, unsigned char *, size_t),
562 void *p_rng)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100563{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100564 int restart_enabled = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100565 ECDH_VALIDATE_RET(ctx != NULL);
566 ECDH_VALIDATE_RET(olen != NULL);
567 ECDH_VALIDATE_RET(buf != NULL);
568 ECDH_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100569
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100570#if defined(MBEDTLS_ECP_RESTARTABLE)
571 restart_enabled = ctx->restart_enabled;
572#endif
573
574#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100575 return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
576 f_rng, p_rng, restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100577#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100578 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100579#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
580 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100581 return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
582 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100583#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100584 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100585 return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
586 ctx->point_format, buf, blen,
587 f_rng, p_rng,
588 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100589 default:
590 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
591 }
592#endif
593}
594
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100595static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
596 const unsigned char *buf, size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100597{
Janos Follath24eed8d2019-11-22 13:21:35 +0000598 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100599 const unsigned char *p = buf;
600
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100601 if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
602 blen)) != 0) {
603 return ret;
604 }
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100605
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100606 if ((size_t) (p - buf) != blen) {
607 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
608 }
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100609
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100610 return 0;
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100611}
612
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100613/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100614 * Parse and import the client's public value
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100615 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100616int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
617 const unsigned char *buf, size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100618{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100619 ECDH_VALIDATE_RET(ctx != NULL);
620 ECDH_VALIDATE_RET(buf != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100621
622#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100623 return ecdh_read_public_internal(ctx, buf, blen);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100624#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100625 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100626#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
627 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100628 return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
629 buf, blen);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100630#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100631 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100632 return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
633 buf, blen);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100634 default:
635 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
636 }
637#endif
638}
639
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100640static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
641 size_t *olen, unsigned char *buf,
642 size_t blen,
643 int (*f_rng)(void *,
644 unsigned char *,
645 size_t),
646 void *p_rng,
647 int restart_enabled)
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100648{
Janos Follath24eed8d2019-11-22 13:21:35 +0000649 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200650#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200651 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200652#endif
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100653
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100654 if (ctx == NULL || ctx->grp.pbits == 0) {
655 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
656 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100657
Ron Eldorb430d9f2018-11-05 17:18:29 +0200658#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100659 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200660 rs_ctx = &ctx->rs;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100661 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100662#else
663 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200664#endif
665
Ron Eldor2981d8f2018-11-05 18:07:10 +0200666#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100667 if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
668 &ctx->d, f_rng, p_rng,
669 rs_ctx)) != 0) {
670 return ret;
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200671 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200672#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100673 if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
674 &ctx->d, f_rng, p_rng)) != 0) {
675 return ret;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200676 }
677#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100678
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100679 if (mbedtls_mpi_size(&ctx->z) > blen) {
680 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
681 }
Paul Bakker41c83d32013-03-20 14:39:14 +0100682
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100683 *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
Janos Follathab0f71a2019-02-20 10:48:49 +0000684
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100685 if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
686 return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
687 }
Janos Follathab0f71a2019-02-20 10:48:49 +0000688
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100689 return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100690}
691
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100692/*
693 * Derive and export the shared secret
694 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100695int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
696 unsigned char *buf, size_t blen,
697 int (*f_rng)(void *, unsigned char *, size_t),
698 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100699{
700 int restart_enabled = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100701 ECDH_VALIDATE_RET(ctx != NULL);
702 ECDH_VALIDATE_RET(olen != NULL);
703 ECDH_VALIDATE_RET(buf != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100704
705#if defined(MBEDTLS_ECP_RESTARTABLE)
706 restart_enabled = ctx->restart_enabled;
707#endif
708
709#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100710 return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
711 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100712#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100713 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100714#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
715 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100716 return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
717 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100718#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100719 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100720 return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
721 blen, f_rng, p_rng,
722 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100723 default:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100724 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100725 }
726#endif
727}
728
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729#endif /* MBEDTLS_ECDH_C */