blob: 7ea2200b6d9594a5649710ca50753ecb360d90fa [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
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010018 */
19
20/*
21 * References:
22 *
23 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +010024 * RFC 4492
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010025 */
26
Gilles Peskinedb09ef62020-06-03 01:43:33 +020027#include "common.h"
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010028
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if defined(MBEDTLS_ECDH_C)
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010030
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020031# include "mbedtls/ecdh.h"
32# include "mbedtls/platform_util.h"
33# include "mbedtls/error.h"
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010034
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020035# include <string.h>
Rich Evans00ab4702015-02-06 13:43:58 +000036
Hanno Becker91796d72018-12-17 18:10:51 +000037/* Parameter validation macros based on platform_util.h */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020038# define ECDH_VALIDATE_RET(cond) \
39 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA)
40# define ECDH_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker91796d72018-12-17 18:10:51 +000041
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020042# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Janos Follath5a3e1bf2018-08-13 15:54:22 +010043typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020044# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +010045
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020046static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(const mbedtls_ecdh_context *ctx)
Gilles Peskine30816292019-02-22 12:31:25 +010047{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020048# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
49 return ctx->grp.id;
50# else
51 return ctx->grp_id;
52# endif
Gilles Peskine30816292019-02-22 12:31:25 +010053}
54
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020055int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
Gilles Peskine20b3ef32019-02-11 18:41:27 +010056{
57 /* At this time, all groups support ECDH. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020058 (void)gid;
59 return 1;
Gilles Peskine20b3ef32019-02-11 18:41:27 +010060}
61
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020062# if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010063/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020064 * Generate public key (restartable version)
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020065 *
66 * Note: this internal function relies on its caller preserving the value of
Manuel Pégourié-Gonnardca29fdf2018-10-22 09:56:53 +020067 * the output parameter 'd' across continuation calls. This would not be
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020068 * acceptable for a public function but is OK here as we control call sites.
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020069 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020070static int
71ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
72 mbedtls_mpi *d,
73 mbedtls_ecp_point *Q,
74 int (*f_rng)(void *, unsigned char *, size_t),
75 void *p_rng,
76 mbedtls_ecp_restart_ctx *rs_ctx)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020077{
Janos Follath24eed8d2019-11-22 13:21:35 +000078 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020079
80 /* If multiplication is in progress, we already generated a privkey */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020081# if defined(MBEDTLS_ECP_RESTARTABLE)
82 if (rs_ctx == NULL || rs_ctx->rsm == NULL)
83# endif
84 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020085
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020086 MBEDTLS_MPI_CHK(
87 mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G, f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020088
89cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020090 return ret;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020091}
92
93/*
94 * Generate public key
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010095 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020096int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp,
97 mbedtls_mpi *d,
98 mbedtls_ecp_point *Q,
99 int (*f_rng)(void *, unsigned char *, size_t),
100 void *p_rng)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100101{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200102 ECDH_VALIDATE_RET(grp != NULL);
103 ECDH_VALIDATE_RET(d != NULL);
104 ECDH_VALIDATE_RET(Q != NULL);
105 ECDH_VALIDATE_RET(f_rng != NULL);
106 return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100107}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200108# endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100109
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200110# if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100111/*
112 * Compute shared secret (SEC1 3.3.1)
113 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200114static int
115ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
116 mbedtls_mpi *z,
117 const mbedtls_ecp_point *Q,
118 const mbedtls_mpi *d,
119 int (*f_rng)(void *, unsigned char *, size_t),
120 void *p_rng,
121 mbedtls_ecp_restart_ctx *rs_ctx)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100122{
Janos Follath24eed8d2019-11-22 13:21:35 +0000123 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 mbedtls_ecp_point P;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100125
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200126 mbedtls_ecp_point_init(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100127
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200128 MBEDTLS_MPI_CHK(
129 mbedtls_ecp_mul_restartable(grp, &P, d, Q, f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100130
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200131 if (mbedtls_ecp_is_zero(&P)) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakkerb548d772013-07-26 14:21:34 +0200133 goto cleanup;
134 }
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100135
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200136 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100137
138cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200139 mbedtls_ecp_point_free(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100140
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200141 return ret;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100142}
143
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100144/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200145 * Compute shared secret (SEC1 3.3.1)
146 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200147int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp,
148 mbedtls_mpi *z,
149 const mbedtls_ecp_point *Q,
150 const mbedtls_mpi *d,
151 int (*f_rng)(void *, unsigned char *, size_t),
152 void *p_rng)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200153{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200154 ECDH_VALIDATE_RET(grp != NULL);
155 ECDH_VALIDATE_RET(Q != NULL);
156 ECDH_VALIDATE_RET(d != NULL);
157 ECDH_VALIDATE_RET(z != NULL);
158 return (ecdh_compute_shared_restartable(grp, z, Q, d, f_rng, p_rng, NULL));
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200159}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200160# endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200161
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200162static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100163{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200164 mbedtls_ecp_group_init(&ctx->grp);
165 mbedtls_mpi_init(&ctx->d);
166 mbedtls_ecp_point_init(&ctx->Q);
167 mbedtls_ecp_point_init(&ctx->Qp);
168 mbedtls_mpi_init(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200169
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200170# if defined(MBEDTLS_ECP_RESTARTABLE)
171 mbedtls_ecp_restart_init(&ctx->rs);
172# endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100173}
174
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100175/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100176 * Initialize context
Janos Follathf61e4862018-10-30 11:53:25 +0000177 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200178void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100179{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200180 ECDH_VALIDATE(ctx != NULL);
Hanno Becker91796d72018-12-17 18:10:51 +0000181
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200182# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
183 ecdh_init_internal(ctx);
184 mbedtls_ecp_point_init(&ctx->Vi);
185 mbedtls_ecp_point_init(&ctx->Vf);
186 mbedtls_mpi_init(&ctx->_d);
187# else
188 memset(ctx, 0, sizeof(mbedtls_ecdh_context));
Christoph M. Wintersteigerd8c45d52019-02-20 17:16:53 +0000189
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100190 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200191# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100192 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200193# if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100194 ctx->restart_enabled = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200195# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100196}
197
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200198static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
199 mbedtls_ecp_group_id grp_id)
Janos Follathf61e4862018-10-30 11:53:25 +0000200{
Janos Follath24eed8d2019-11-22 13:21:35 +0000201 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000202
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200203 ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
204 if (ret != 0) {
205 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Janos Follathf61e4862018-10-30 11:53:25 +0000206 }
207
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200208 return 0;
Janos Follathf61e4862018-10-30 11:53:25 +0000209}
210
211/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100212 * Setup context
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100213 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200214int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100215{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200216 ECDH_VALIDATE_RET(ctx != NULL);
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100217
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200218# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
219 return ecdh_setup_internal(ctx, grp_id);
220# else
221 switch (grp_id) {
222# if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000223 case MBEDTLS_ECP_DP_CURVE25519:
224 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
225 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
226 ctx->grp_id = grp_id;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200227 return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
228# endif
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000229 default:
230 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
231 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
232 ctx->grp_id = grp_id;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200233 ecdh_init_internal(&ctx->ctx.mbed_ecdh);
234 return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100235 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200236# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100237}
238
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200239static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100240{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200241 mbedtls_ecp_group_free(&ctx->grp);
242 mbedtls_mpi_free(&ctx->d);
243 mbedtls_ecp_point_free(&ctx->Q);
244 mbedtls_ecp_point_free(&ctx->Qp);
245 mbedtls_mpi_free(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200246
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200247# if defined(MBEDTLS_ECP_RESTARTABLE)
248 mbedtls_ecp_restart_free(&ctx->rs);
249# endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100250}
251
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200252# if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200253/*
254 * Enable restartable operations for context
255 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200256void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200257{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200258 ECDH_VALIDATE(ctx != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100259
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200260 ctx->restart_enabled = 1;
261}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200262# endif
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200263
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100264/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100265 * Free context
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100266 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200267void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100268{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200269 if (ctx == NULL)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100270 return;
271
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200272# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
273 mbedtls_ecp_point_free(&ctx->Vi);
274 mbedtls_ecp_point_free(&ctx->Vf);
275 mbedtls_mpi_free(&ctx->_d);
276 ecdh_free_internal(ctx);
277# else
278 switch (ctx->var) {
279# if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100280 case MBEDTLS_ECDH_VARIANT_EVEREST:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200281 mbedtls_everest_free(&ctx->ctx.everest_ecdh);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100282 break;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200283# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100284 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200285 ecdh_free_internal(&ctx->ctx.mbed_ecdh);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100286 break;
287 default:
288 break;
289 }
290
291 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
292 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
293 ctx->grp_id = MBEDTLS_ECP_DP_NONE;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200294# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100295}
296
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200297static int
298ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
299 size_t *olen,
300 int point_format,
301 unsigned char *buf,
302 size_t blen,
303 int (*f_rng)(void *, unsigned char *, size_t),
304 void *p_rng,
305 int restart_enabled)
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100306{
Janos Follath24eed8d2019-11-22 13:21:35 +0000307 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100308 size_t grp_len, pt_len;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200309# if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200310 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200311# endif
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100312
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200313 if (ctx->grp.pbits == 0)
314 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100315
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200316# if defined(MBEDTLS_ECP_RESTARTABLE)
317 if (restart_enabled)
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200318 rs_ctx = &ctx->rs;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200319# else
320 (void)restart_enabled;
321# endif
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200322
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200323# if defined(MBEDTLS_ECP_RESTARTABLE)
324 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q, f_rng,
325 p_rng, rs_ctx)) != 0)
326 return ret;
327# else
328 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, f_rng,
329 p_rng)) != 0)
330 return ret;
331# endif /* MBEDTLS_ECP_RESTARTABLE */
Ron Eldor8493f802018-11-01 11:32:15 +0200332
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200333 if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf, blen)) !=
334 0)
335 return ret;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100336
337 buf += grp_len;
338 blen -= grp_len;
339
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200340 if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
341 &pt_len, buf, blen)) != 0)
342 return ret;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100343
344 *olen = grp_len + pt_len;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200345 return 0;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100346}
347
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100348/*
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100349 * Setup and write the ServerKeyExchange parameters (RFC 4492)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100350 * struct {
351 * ECParameters curve_params;
352 * ECPoint public;
353 * } ServerECDHParams;
354 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200355int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx,
356 size_t *olen,
357 unsigned char *buf,
358 size_t blen,
359 int (*f_rng)(void *, unsigned char *, size_t),
360 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100361{
362 int restart_enabled = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200363 ECDH_VALIDATE_RET(ctx != NULL);
364 ECDH_VALIDATE_RET(olen != NULL);
365 ECDH_VALIDATE_RET(buf != NULL);
366 ECDH_VALIDATE_RET(f_rng != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100367
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200368# if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100369 restart_enabled = ctx->restart_enabled;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200370# else
371 (void)restart_enabled;
372# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100373
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200374# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
375 return (ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
376 f_rng, p_rng, restart_enabled));
377# else
378 switch (ctx->var) {
379# if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100380 case MBEDTLS_ECDH_VARIANT_EVEREST:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200381 return (mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
382 buf, blen, f_rng, p_rng));
383# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100384 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200385 return (ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
386 ctx->point_format, buf, blen,
387 f_rng, p_rng, restart_enabled));
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100388 default:
389 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
390 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200391# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100392}
393
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200394static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
395 const unsigned char **buf,
396 const unsigned char *end)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100397{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200398 return (mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf, end - *buf));
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100399}
400
401/*
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100402 * Read the ServerKeyExhange parameters (RFC 4492)
403 * struct {
404 * ECParameters curve_params;
405 * ECPoint public;
406 * } ServerECDHParams;
407 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200408int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
409 const unsigned char **buf,
410 const unsigned char *end)
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100411{
Janos Follath24eed8d2019-11-22 13:21:35 +0000412 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000413 mbedtls_ecp_group_id grp_id;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200414 ECDH_VALIDATE_RET(ctx != NULL);
415 ECDH_VALIDATE_RET(buf != NULL);
416 ECDH_VALIDATE_RET(*buf != NULL);
417 ECDH_VALIDATE_RET(end != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100418
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200419 if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, end - *buf)) != 0)
420 return ret;
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100421
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200422 if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0)
423 return ret;
Janos Follathf61e4862018-10-30 11:53:25 +0000424
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200425# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
426 return ecdh_read_params_internal(ctx, buf, end);
427# else
428 switch (ctx->var) {
429# if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100430 case MBEDTLS_ECDH_VARIANT_EVEREST:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200431 return (
432 mbedtls_everest_read_params(&ctx->ctx.everest_ecdh, buf, end));
433# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100434 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200435 return (ecdh_read_params_internal(&ctx->ctx.mbed_ecdh, buf, end));
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100436 default:
437 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
438 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200439# endif
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100440}
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +0100441
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200442static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
443 const mbedtls_ecp_keypair *key,
444 mbedtls_ecdh_side side)
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100445{
Janos Follath24eed8d2019-11-22 13:21:35 +0000446 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100447
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100448 /* If it's not our key, just import the public part as Qp */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200449 if (side == MBEDTLS_ECDH_THEIRS)
450 return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100451
452 /* Our key: import public (as Q) and private parts */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200453 if (side != MBEDTLS_ECDH_OURS)
454 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100455
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200456 if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
457 (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0)
458 return ret;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100459
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200460 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 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200466int 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;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200471 ECDH_VALIDATE_RET(ctx != NULL);
472 ECDH_VALIDATE_RET(key != NULL);
473 ECDH_VALIDATE_RET(side == MBEDTLS_ECDH_OURS || side == MBEDTLS_ECDH_THEIRS);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100474
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200475 if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100476 /* This is the first call to get_params(). Set up the context
477 * for use with the group. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200478 if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0)
479 return ret;
480 } else {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100481 /* This is not the first call to get_params(). Check that the
482 * current key's group is the same as the context's, which was set
483 * from the first key's group. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200484 if (mbedtls_ecdh_grp_id(ctx) != key->grp.id)
485 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100486 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100487
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200488# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
489 return ecdh_get_params_internal(ctx, key, side);
490# else
491 switch (ctx->var) {
492# if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100493 case MBEDTLS_ECDH_VARIANT_EVEREST:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200494 {
495 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
496 MBEDTLS_EVEREST_ECDH_OURS :
497 MBEDTLS_EVEREST_ECDH_THEIRS;
498 return (
499 mbedtls_everest_get_params(&ctx->ctx.everest_ecdh, key, s));
500 }
501# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100502 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200503 return (ecdh_get_params_internal(&ctx->ctx.mbed_ecdh, key, side));
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100504 default:
505 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
506 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200507# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100508}
509
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200510static int
511ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
512 size_t *olen,
513 int point_format,
514 unsigned char *buf,
515 size_t blen,
516 int (*f_rng)(void *, unsigned char *, size_t),
517 void *p_rng,
518 int restart_enabled)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100519{
Janos Follath24eed8d2019-11-22 13:21:35 +0000520 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200521# if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200522 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200523# endif
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100524
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200525 if (ctx->grp.pbits == 0)
526 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100527
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200528# if defined(MBEDTLS_ECP_RESTARTABLE)
529 if (restart_enabled)
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200530 rs_ctx = &ctx->rs;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200531# else
532 (void)restart_enabled;
533# endif
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200534
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200535# if defined(MBEDTLS_ECP_RESTARTABLE)
536 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q, f_rng,
537 p_rng, rs_ctx)) != 0)
538 return ret;
539# else
540 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, f_rng,
541 p_rng)) != 0)
542 return ret;
543# endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100544
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200545 return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
546 buf, blen);
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100547}
548
549/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100550 * Setup and export the client public value
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100551 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200552int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx,
553 size_t *olen,
554 unsigned char *buf,
555 size_t blen,
556 int (*f_rng)(void *, unsigned char *, size_t),
557 void *p_rng)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100558{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100559 int restart_enabled = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200560 ECDH_VALIDATE_RET(ctx != NULL);
561 ECDH_VALIDATE_RET(olen != NULL);
562 ECDH_VALIDATE_RET(buf != NULL);
563 ECDH_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100564
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200565# if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100566 restart_enabled = ctx->restart_enabled;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200567# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100568
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200569# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
570 return (ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
571 f_rng, p_rng, restart_enabled));
572# else
573 switch (ctx->var) {
574# if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100575 case MBEDTLS_ECDH_VARIANT_EVEREST:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200576 return (mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
577 buf, blen, f_rng, p_rng));
578# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100579 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200580 return (ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
581 ctx->point_format, buf, blen,
582 f_rng, p_rng, restart_enabled));
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100583 default:
584 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
585 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200586# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100587}
588
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200589static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
590 const unsigned char *buf,
591 size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100592{
Janos Follath24eed8d2019-11-22 13:21:35 +0000593 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100594 const unsigned char *p = buf;
595
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200596 if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p, blen)) != 0)
597 return ret;
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100598
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200599 if ((size_t)(p - buf) != blen)
600 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100601
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200602 return 0;
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100603}
604
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100605/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100606 * Parse and import the client's public value
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100607 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200608int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
609 const unsigned char *buf,
610 size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100611{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200612 ECDH_VALIDATE_RET(ctx != NULL);
613 ECDH_VALIDATE_RET(buf != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100614
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200615# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
616 return ecdh_read_public_internal(ctx, buf, blen);
617# else
618 switch (ctx->var) {
619# if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100620 case MBEDTLS_ECDH_VARIANT_EVEREST:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200621 return (
622 mbedtls_everest_read_public(&ctx->ctx.everest_ecdh, buf, blen));
623# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100624 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200625 return (ecdh_read_public_internal(&ctx->ctx.mbed_ecdh, buf, blen));
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100626 default:
627 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
628 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200629# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100630}
631
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200632static int
633ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
634 size_t *olen,
635 unsigned char *buf,
636 size_t blen,
637 int (*f_rng)(void *, unsigned char *, size_t),
638 void *p_rng,
639 int restart_enabled)
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100640{
Janos Follath24eed8d2019-11-22 13:21:35 +0000641 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200642# if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200643 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200644# endif
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100645
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200646 if (ctx == NULL || ctx->grp.pbits == 0)
647 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100648
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200649# if defined(MBEDTLS_ECP_RESTARTABLE)
650 if (restart_enabled)
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200651 rs_ctx = &ctx->rs;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200652# else
653 (void)restart_enabled;
654# endif
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200655
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200656# if defined(MBEDTLS_ECP_RESTARTABLE)
657 if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
658 &ctx->d, f_rng, p_rng,
659 rs_ctx)) != 0) {
660 return ret;
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200661 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200662# else
663 if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
664 &ctx->d, f_rng, p_rng)) != 0) {
665 return ret;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200666 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200667# endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100668
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200669 if (mbedtls_mpi_size(&ctx->z) > blen)
670 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakker41c83d32013-03-20 14:39:14 +0100671
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200672 *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
Janos Follathab0f71a2019-02-20 10:48:49 +0000673
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200674 if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY)
675 return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
Janos Follathab0f71a2019-02-20 10:48:49 +0000676
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200677 return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100678}
679
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100680/*
681 * Derive and export the shared secret
682 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200683int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx,
684 size_t *olen,
685 unsigned char *buf,
686 size_t blen,
687 int (*f_rng)(void *, unsigned char *, size_t),
688 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100689{
690 int restart_enabled = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200691 ECDH_VALIDATE_RET(ctx != NULL);
692 ECDH_VALIDATE_RET(olen != NULL);
693 ECDH_VALIDATE_RET(buf != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100694
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200695# if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100696 restart_enabled = ctx->restart_enabled;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200697# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100698
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200699# if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
700 return (ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
701 restart_enabled));
702# else
703 switch (ctx->var) {
704# if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100705 case MBEDTLS_ECDH_VARIANT_EVEREST:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200706 return (mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
707 buf, blen, f_rng, p_rng));
708# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100709 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200710 return (ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
711 blen, f_rng, p_rng,
712 restart_enabled));
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100713 default:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200714 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100715 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200716# endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100717}
718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719#endif /* MBEDTLS_ECDH_C */