blob: 2007e1670cf85e23f8293a3d409e78182ad6a6e0 [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
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/ecdh.h"
Hanno Becker91796d72018-12-17 18:10:51 +000032#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000033#include "mbedtls/error.h"
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010034
Rich Evans00ab4702015-02-06 13:43:58 +000035#include <string.h>
36
Hanno Becker91796d72018-12-17 18:10:51 +000037/* Parameter validation macros based on platform_util.h */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010038#define ECDH_VALIDATE_RET(cond) \
39 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA)
40#define ECDH_VALIDATE(cond) \
41 MBEDTLS_INTERNAL_VALIDATE(cond)
Hanno Becker91796d72018-12-17 18:10:51 +000042
Janos Follath5a3e1bf2018-08-13 15:54:22 +010043#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
44typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
45#endif
46
Gilles Peskine30816292019-02-22 12:31:25 +010047static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010048 const mbedtls_ecdh_context *ctx)
Gilles Peskine30816292019-02-22 12:31:25 +010049{
50#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010051 return ctx->grp.id;
Gilles Peskine30816292019-02-22 12:31:25 +010052#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010053 return ctx->grp_id;
Gilles Peskine30816292019-02-22 12:31:25 +010054#endif
55}
56
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010057int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
Gilles Peskine20b3ef32019-02-11 18:41:27 +010058{
59 /* At this time, all groups support ECDH. */
60 (void) gid;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010061 return 1;
Gilles Peskine20b3ef32019-02-11 18:41:27 +010062}
63
Ron Eldora84c1cb2017-10-10 19:04:27 +030064#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010065/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020066 * Generate public key (restartable version)
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020067 *
68 * Note: this internal function relies on its caller preserving the value of
Manuel Pégourié-Gonnardca29fdf2018-10-22 09:56:53 +020069 * the output parameter 'd' across continuation calls. This would not be
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020070 * acceptable for a public function but is OK here as we control call sites.
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020071 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010072static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
73 mbedtls_mpi *d, 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
David Horstmannd2091972022-10-06 19:11:28 +010080 int restarting = 0;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020081#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010082 restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020083#endif
David Horstmannd2091972022-10-06 19:11:28 +010084 /* If multiplication is in progress, we already generated a privkey */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010085 if (!restarting) {
86 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
87 }
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020088
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010089 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
90 f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020091
92cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010093 return ret;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020094}
95
96/*
97 * Generate public key
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010098 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010099int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
100 int (*f_rng)(void *, unsigned char *, size_t),
101 void *p_rng)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100102{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100103 ECDH_VALIDATE_RET(grp != NULL);
104 ECDH_VALIDATE_RET(d != NULL);
105 ECDH_VALIDATE_RET(Q != NULL);
106 ECDH_VALIDATE_RET(f_rng != NULL);
107 return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100108}
Ron Eldor936d2842018-11-01 13:05:52 +0200109#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100110
Ron Eldora84c1cb2017-10-10 19:04:27 +0300111#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100112/*
113 * Compute shared secret (SEC1 3.3.1)
114 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100115static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
116 mbedtls_mpi *z,
117 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
118 int (*f_rng)(void *, unsigned char *, size_t),
119 void *p_rng,
120 mbedtls_ecp_restart_ctx *rs_ctx)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100121{
Janos Follath24eed8d2019-11-22 13:21:35 +0000122 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 mbedtls_ecp_point P;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100124
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100125 mbedtls_ecp_point_init(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100126
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100127 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
128 f_rng, p_rng, rs_ctx));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100129
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100130 if (mbedtls_ecp_is_zero(&P)) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakkerb548d772013-07-26 14:21:34 +0200132 goto cleanup;
133 }
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100134
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100135 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100136
137cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100138 mbedtls_ecp_point_free(&P);
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100139
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100140 return ret;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100141}
142
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100143/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200144 * Compute shared secret (SEC1 3.3.1)
145 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100146int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
147 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
148 int (*f_rng)(void *, unsigned char *, size_t),
149 void *p_rng)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200150{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151 ECDH_VALIDATE_RET(grp != NULL);
152 ECDH_VALIDATE_RET(Q != NULL);
153 ECDH_VALIDATE_RET(d != NULL);
154 ECDH_VALIDATE_RET(z != NULL);
155 return ecdh_compute_shared_restartable(grp, z, Q, d,
156 f_rng, p_rng, NULL);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200157}
Ron Eldor936d2842018-11-01 13:05:52 +0200158#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200159
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100160static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100161{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100162 mbedtls_ecp_group_init(&ctx->grp);
163 mbedtls_mpi_init(&ctx->d);
164 mbedtls_ecp_point_init(&ctx->Q);
165 mbedtls_ecp_point_init(&ctx->Qp);
166 mbedtls_mpi_init(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200167
168#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100169 mbedtls_ecp_restart_init(&ctx->rs);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200170#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100171}
172
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100173/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100174 * Initialize context
Janos Follathf61e4862018-10-30 11:53:25 +0000175 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100176void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100177{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100178 ECDH_VALIDATE(ctx != NULL);
Hanno Becker91796d72018-12-17 18:10:51 +0000179
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100180#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100181 ecdh_init_internal(ctx);
182 mbedtls_ecp_point_init(&ctx->Vi);
183 mbedtls_ecp_point_init(&ctx->Vf);
184 mbedtls_mpi_init(&ctx->_d);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100185#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100186 memset(ctx, 0, sizeof(mbedtls_ecdh_context));
Christoph M. Wintersteigerd8c45d52019-02-20 17:16:53 +0000187
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100188 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
189#endif
190 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
191#if defined(MBEDTLS_ECP_RESTARTABLE)
192 ctx->restart_enabled = 0;
193#endif
194}
195
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100196static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
197 mbedtls_ecp_group_id grp_id)
Janos Follathf61e4862018-10-30 11:53:25 +0000198{
Janos Follath24eed8d2019-11-22 13:21:35 +0000199 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000200
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100201 ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
202 if (ret != 0) {
203 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
Janos Follathf61e4862018-10-30 11:53:25 +0000204 }
205
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100206 return 0;
Janos Follathf61e4862018-10-30 11:53:25 +0000207}
208
209/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100210 * Setup context
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100211 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100212int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100213{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100214 ECDH_VALIDATE_RET(ctx != NULL);
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100215
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100216#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100217 return ecdh_setup_internal(ctx, grp_id);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100218#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 switch (grp_id) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100220#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000221 case MBEDTLS_ECP_DP_CURVE25519:
222 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
223 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
224 ctx->grp_id = grp_id;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100225 return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
Christoph M. Wintersteiger78c9c462018-12-06 17:16:32 +0000226#endif
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000227 default:
228 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
229 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
230 ctx->grp_id = grp_id;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100231 ecdh_init_internal(&ctx->ctx.mbed_ecdh);
232 return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100233 }
234#endif
235}
236
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100237static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100238{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100239 mbedtls_ecp_group_free(&ctx->grp);
240 mbedtls_mpi_free(&ctx->d);
241 mbedtls_ecp_point_free(&ctx->Q);
242 mbedtls_ecp_point_free(&ctx->Qp);
243 mbedtls_mpi_free(&ctx->z);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200244
245#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100246 mbedtls_ecp_restart_free(&ctx->rs);
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200247#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100248}
249
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200250#if defined(MBEDTLS_ECP_RESTARTABLE)
251/*
252 * Enable restartable operations for context
253 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100254void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200255{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100256 ECDH_VALIDATE(ctx != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100257
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200258 ctx->restart_enabled = 1;
259}
260#endif
261
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100262/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100263 * Free context
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100264 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100265void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100266{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100267 if (ctx == NULL) {
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100268 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100269 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100270
271#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100272 mbedtls_ecp_point_free(&ctx->Vi);
273 mbedtls_ecp_point_free(&ctx->Vf);
274 mbedtls_mpi_free(&ctx->_d);
275 ecdh_free_internal(ctx);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100276#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100277 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100278#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
279 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100280 mbedtls_everest_free(&ctx->ctx.everest_ecdh);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100281 break;
282#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100283 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100284 ecdh_free_internal(&ctx->ctx.mbed_ecdh);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100285 break;
286 default:
287 break;
288 }
289
290 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
291 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
292 ctx->grp_id = MBEDTLS_ECP_DP_NONE;
293#endif
294}
295
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100296static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
297 size_t *olen, int point_format,
298 unsigned char *buf, size_t blen,
299 int (*f_rng)(void *,
300 unsigned char *,
301 size_t),
302 void *p_rng,
303 int restart_enabled)
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100304{
Janos Follath24eed8d2019-11-22 13:21:35 +0000305 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100306 size_t grp_len, pt_len;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200307#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200308 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200309#endif
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100310
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100311 if (ctx->grp.pbits == 0) {
312 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
313 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100314
Ron Eldor19779c42018-11-05 16:58:13 +0200315#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100316 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200317 rs_ctx = &ctx->rs;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100318 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100319#else
320 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200321#endif
322
Ron Eldor8493f802018-11-01 11:32:15 +0200323
Ron Eldor2981d8f2018-11-05 18:07:10 +0200324#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100325 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
326 f_rng, p_rng, rs_ctx)) != 0) {
327 return ret;
328 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200329#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100330 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
331 f_rng, p_rng)) != 0) {
332 return ret;
333 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200334#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100335
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100336 if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
337 blen)) != 0) {
338 return ret;
339 }
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100340
341 buf += grp_len;
342 blen -= grp_len;
343
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100344 if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
345 &pt_len, buf, blen)) != 0) {
346 return ret;
347 }
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100348
349 *olen = grp_len + pt_len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100350 return 0;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100351}
352
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100353/*
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100354 * Setup and write the ServerKeyExchange parameters (RFC 4492)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100355 * struct {
356 * ECParameters curve_params;
357 * ECPoint public;
358 * } ServerECDHParams;
359 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100360int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
361 unsigned char *buf, size_t blen,
362 int (*f_rng)(void *, unsigned char *, size_t),
363 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100364{
365 int restart_enabled = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100366 ECDH_VALIDATE_RET(ctx != NULL);
367 ECDH_VALIDATE_RET(olen != NULL);
368 ECDH_VALIDATE_RET(buf != NULL);
369 ECDH_VALIDATE_RET(f_rng != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100370
371#if defined(MBEDTLS_ECP_RESTARTABLE)
372 restart_enabled = ctx->restart_enabled;
373#else
374 (void) restart_enabled;
375#endif
376
377#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100378 return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
379 f_rng, p_rng, restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100380#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100381 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100382#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
383 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100384 return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
385 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100386#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100387 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100388 return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
389 ctx->point_format, buf, blen,
390 f_rng, p_rng,
391 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100392 default:
393 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
394 }
395#endif
396}
397
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100398static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
399 const unsigned char **buf,
400 const unsigned char *end)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100401{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100402 return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
403 end - *buf);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100404}
405
406/*
bootstrap-prime7ef96ea2022-05-18 14:08:33 -0400407 * Read the ServerKeyExchange parameters (RFC 4492)
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100408 * struct {
409 * ECParameters curve_params;
410 * ECPoint public;
411 * } ServerECDHParams;
412 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100413int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
414 const unsigned char **buf,
415 const unsigned char *end)
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100416{
Janos Follath24eed8d2019-11-22 13:21:35 +0000417 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000418 mbedtls_ecp_group_id grp_id;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100419 ECDH_VALIDATE_RET(ctx != NULL);
420 ECDH_VALIDATE_RET(buf != NULL);
421 ECDH_VALIDATE_RET(*buf != NULL);
422 ECDH_VALIDATE_RET(end != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100423
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100424 if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, end - *buf))
425 != 0) {
426 return ret;
427 }
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100428
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100429 if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
430 return ret;
431 }
Janos Follathf61e4862018-10-30 11:53:25 +0000432
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100433#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100434 return ecdh_read_params_internal(ctx, buf, end);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100435#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100436 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100437#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
438 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100439 return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
440 buf, end);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100441#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100442 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100443 return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
444 buf, end);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100445 default:
446 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
447 }
448#endif
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100449}
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +0100450
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100451static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
452 const mbedtls_ecp_keypair *key,
453 mbedtls_ecdh_side side)
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100454{
Janos Follath24eed8d2019-11-22 13:21:35 +0000455 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100456
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100457 /* If it's not our key, just import the public part as Qp */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100458 if (side == MBEDTLS_ECDH_THEIRS) {
459 return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
460 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100461
462 /* Our key: import public (as Q) and private parts */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100463 if (side != MBEDTLS_ECDH_OURS) {
464 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
465 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100466
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100467 if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
468 (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
469 return ret;
470 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100471
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100472 return 0;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100473}
474
475/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100476 * Get parameters from a keypair
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100477 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100478int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
479 const mbedtls_ecp_keypair *key,
480 mbedtls_ecdh_side side)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100481{
Janos Follath24eed8d2019-11-22 13:21:35 +0000482 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100483 ECDH_VALIDATE_RET(ctx != NULL);
484 ECDH_VALIDATE_RET(key != NULL);
485 ECDH_VALIDATE_RET(side == MBEDTLS_ECDH_OURS ||
486 side == MBEDTLS_ECDH_THEIRS);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100487
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100488 if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100489 /* This is the first call to get_params(). Set up the context
490 * for use with the group. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100491 if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
492 return ret;
493 }
494 } else {
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100495 /* This is not the first call to get_params(). Check that the
496 * current key's group is the same as the context's, which was set
497 * from the first key's group. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100498 if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
499 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
500 }
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100501 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100502
503#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100504 return ecdh_get_params_internal(ctx, key, side);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100505#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100506 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100507#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
508 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000509 {
Christoph M. Wintersteiger2e724a12019-01-07 14:19:41 +0000510 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100511 MBEDTLS_EVEREST_ECDH_OURS :
512 MBEDTLS_EVEREST_ECDH_THEIRS;
513 return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
514 key, s);
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000515 }
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100516#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100517 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100518 return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
519 key, side);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100520 default:
521 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
522 }
523#endif
524}
525
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100526static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
527 size_t *olen, int point_format,
528 unsigned char *buf, size_t blen,
529 int (*f_rng)(void *,
530 unsigned char *,
531 size_t),
532 void *p_rng,
533 int restart_enabled)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100534{
Janos Follath24eed8d2019-11-22 13:21:35 +0000535 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200536#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200537 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200538#endif
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100539
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100540 if (ctx->grp.pbits == 0) {
541 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
542 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100543
Ron Eldorb430d9f2018-11-05 17:18:29 +0200544#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100545 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200546 rs_ctx = &ctx->rs;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100547 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100548#else
549 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200550#endif
551
Ron Eldor2981d8f2018-11-05 18:07:10 +0200552#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100553 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
554 f_rng, p_rng, rs_ctx)) != 0) {
555 return ret;
556 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200557#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100558 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
559 f_rng, p_rng)) != 0) {
560 return ret;
561 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200562#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100563
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100564 return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
565 buf, blen);
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100566}
567
568/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100569 * Setup and export the client public value
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100570 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100571int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
572 unsigned char *buf, size_t blen,
573 int (*f_rng)(void *, unsigned char *, size_t),
574 void *p_rng)
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100575{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100576 int restart_enabled = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100577 ECDH_VALIDATE_RET(ctx != NULL);
578 ECDH_VALIDATE_RET(olen != NULL);
579 ECDH_VALIDATE_RET(buf != NULL);
580 ECDH_VALIDATE_RET(f_rng != NULL);
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100581
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100582#if defined(MBEDTLS_ECP_RESTARTABLE)
583 restart_enabled = ctx->restart_enabled;
584#endif
585
586#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100587 return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
588 f_rng, p_rng, restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100589#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100590 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100591#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
592 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100593 return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
594 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100595#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100596 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100597 return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
598 ctx->point_format, buf, blen,
599 f_rng, p_rng,
600 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100601 default:
602 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
603 }
604#endif
605}
606
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100607static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
608 const unsigned char *buf, size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100609{
Janos Follath24eed8d2019-11-22 13:21:35 +0000610 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100611 const unsigned char *p = buf;
612
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100613 if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
614 blen)) != 0) {
615 return ret;
616 }
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100617
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100618 if ((size_t) (p - buf) != blen) {
619 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
620 }
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100621
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100622 return 0;
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100623}
624
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100625/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100626 * Parse and import the client's public value
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100627 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100628int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
629 const unsigned char *buf, size_t blen)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100630{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100631 ECDH_VALIDATE_RET(ctx != NULL);
632 ECDH_VALIDATE_RET(buf != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100633
634#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100635 return ecdh_read_public_internal(ctx, buf, blen);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100636#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100637 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100638#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
639 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100640 return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
641 buf, blen);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100642#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100643 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100644 return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
645 buf, blen);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100646 default:
647 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
648 }
649#endif
650}
651
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100652static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
653 size_t *olen, unsigned char *buf,
654 size_t blen,
655 int (*f_rng)(void *,
656 unsigned char *,
657 size_t),
658 void *p_rng,
659 int restart_enabled)
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100660{
Janos Follath24eed8d2019-11-22 13:21:35 +0000661 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200662#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200663 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200664#endif
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100665
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100666 if (ctx == NULL || ctx->grp.pbits == 0) {
667 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
668 }
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100669
Ron Eldorb430d9f2018-11-05 17:18:29 +0200670#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100671 if (restart_enabled) {
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200672 rs_ctx = &ctx->rs;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100673 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100674#else
675 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200676#endif
677
Ron Eldor2981d8f2018-11-05 18:07:10 +0200678#if defined(MBEDTLS_ECP_RESTARTABLE)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100679 if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
680 &ctx->d, f_rng, p_rng,
681 rs_ctx)) != 0) {
682 return ret;
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200683 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200684#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100685 if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
686 &ctx->d, f_rng, p_rng)) != 0) {
687 return ret;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200688 }
689#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100690
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100691 if (mbedtls_mpi_size(&ctx->z) > blen) {
692 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
693 }
Paul Bakker41c83d32013-03-20 14:39:14 +0100694
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100695 *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
Janos Follathab0f71a2019-02-20 10:48:49 +0000696
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100697 if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
698 return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
699 }
Janos Follathab0f71a2019-02-20 10:48:49 +0000700
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100701 return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100702}
703
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100704/*
705 * Derive and export the shared secret
706 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100707int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
708 unsigned char *buf, size_t blen,
709 int (*f_rng)(void *, unsigned char *, size_t),
710 void *p_rng)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100711{
712 int restart_enabled = 0;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100713 ECDH_VALIDATE_RET(ctx != NULL);
714 ECDH_VALIDATE_RET(olen != NULL);
715 ECDH_VALIDATE_RET(buf != NULL);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100716
717#if defined(MBEDTLS_ECP_RESTARTABLE)
718 restart_enabled = ctx->restart_enabled;
719#endif
720
721#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100722 return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
723 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100724#else
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100725 switch (ctx->var) {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100726#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
727 case MBEDTLS_ECDH_VARIANT_EVEREST:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100728 return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
729 buf, blen, f_rng, p_rng);
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100730#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100731 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100732 return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
733 blen, f_rng, p_rng,
734 restart_enabled);
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100735 default:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100736 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100737 }
738#endif
739}
740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741#endif /* MBEDTLS_ECDH_C */