blob: b1d7c2a3b3d9125e1314eceba76aeec20d2a527f [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"
Jerry Yud3f73342021-09-09 15:42:32 +080034#include "ssl_misc.h"
Jerry Yubdc71882021-09-14 19:30:36 +080035
36#include "ecdh_misc.h"
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Hanno Becker91796d72018-12-17 18:10:51 +000040/* Parameter validation macros based on platform_util.h */
41#define ECDH_VALIDATE_RET( cond ) \
42 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
43#define ECDH_VALIDATE( cond ) \
44 MBEDTLS_INTERNAL_VALIDATE( cond )
45
Janos Follath5a3e1bf2018-08-13 15:54:22 +010046#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
47typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
48#endif
49
Gilles Peskine30816292019-02-22 12:31:25 +010050static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
51 const mbedtls_ecdh_context *ctx )
52{
53#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
54 return( ctx->grp.id );
55#else
56 return( ctx->grp_id );
57#endif
58}
59
Gilles Peskine20b3ef32019-02-11 18:41:27 +010060int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
61{
62 /* At this time, all groups support ECDH. */
63 (void) gid;
Christoph M. Wintersteigerc25df682019-04-16 12:54:56 +010064 return( 1 );
Gilles Peskine20b3ef32019-02-11 18:41:27 +010065}
66
Ron Eldora84c1cb2017-10-10 19:04:27 +030067#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010068/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020069 * Generate public key (restartable version)
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020070 *
71 * Note: this internal function relies on its caller preserving the value of
Manuel Pégourié-Gonnardca29fdf2018-10-22 09:56:53 +020072 * the output parameter 'd' across continuation calls. This would not be
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020073 * acceptable for a public function but is OK here as we control call sites.
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020074 */
75static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
76 mbedtls_mpi *d, mbedtls_ecp_point *Q,
77 int (*f_rng)(void *, unsigned char *, size_t),
78 void *p_rng,
79 mbedtls_ecp_restart_ctx *rs_ctx )
80{
Janos Follath24eed8d2019-11-22 13:21:35 +000081 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020082
83 /* If multiplication is in progress, we already generated a privkey */
84#if defined(MBEDTLS_ECP_RESTARTABLE)
85 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
86#endif
87 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
88
89 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
90 f_rng, p_rng, rs_ctx ) );
91
92cleanup:
93 return( ret );
94}
95
96/*
97 * Generate public key
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010098 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100100 int (*f_rng)(void *, unsigned char *, size_t),
101 void *p_rng )
102{
Hanno Becker91796d72018-12-17 18:10:51 +0000103 ECDH_VALIDATE_RET( grp != NULL );
104 ECDH_VALIDATE_RET( d != NULL );
105 ECDH_VALIDATE_RET( Q != NULL );
106 ECDH_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200107 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 */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200115static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
116 mbedtls_mpi *z,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200117 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200118 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200119 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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 mbedtls_ecp_point_init( &P );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100126
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200127 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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 if( mbedtls_ecp_is_zero( &P ) )
Paul Bakkerb548d772013-07-26 14:21:34 +0200131 {
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
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100137
138cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 mbedtls_ecp_point_free( &P );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100140
141 return( ret );
142}
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 */
147int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
148 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
149 int (*f_rng)(void *, unsigned char *, size_t),
150 void *p_rng )
151{
Hanno Becker91796d72018-12-17 18:10:51 +0000152 ECDH_VALIDATE_RET( grp != NULL );
153 ECDH_VALIDATE_RET( Q != NULL );
154 ECDH_VALIDATE_RET( d != NULL );
155 ECDH_VALIDATE_RET( z != NULL );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200156 return( ecdh_compute_shared_restartable( grp, z, Q, d,
157 f_rng, p_rng, NULL ) );
158}
Ron Eldor936d2842018-11-01 13:05:52 +0200159#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200160
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100161static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100162{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200163 mbedtls_ecp_group_init( &ctx->grp );
164 mbedtls_mpi_init( &ctx->d );
165 mbedtls_ecp_point_init( &ctx->Q );
166 mbedtls_ecp_point_init( &ctx->Qp );
167 mbedtls_mpi_init( &ctx->z );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200168
169#if defined(MBEDTLS_ECP_RESTARTABLE)
170 mbedtls_ecp_restart_init( &ctx->rs );
171#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100172}
173
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100174/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100175 * Initialize context
Janos Follathf61e4862018-10-30 11:53:25 +0000176 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100177void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
178{
Hanno Becker91796d72018-12-17 18:10:51 +0000179 ECDH_VALIDATE( ctx != NULL );
180
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100181#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
182 ecdh_init_internal( ctx );
183 mbedtls_ecp_point_init( &ctx->Vi );
184 mbedtls_ecp_point_init( &ctx->Vf );
185 mbedtls_mpi_init( &ctx->_d );
186#else
Christoph M. Wintersteigerd8c45d52019-02-20 17:16:53 +0000187 memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
188
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100189 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
190#endif
191 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
192#if defined(MBEDTLS_ECP_RESTARTABLE)
193 ctx->restart_enabled = 0;
194#endif
195}
196
197static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
198 mbedtls_ecp_group_id grp_id )
Janos Follathf61e4862018-10-30 11:53:25 +0000199{
Janos Follath24eed8d2019-11-22 13:21:35 +0000200 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000201
202 ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
203 if( ret != 0 )
204 {
Janos Follathf61e4862018-10-30 11:53:25 +0000205 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
206 }
207
208 return( 0 );
209}
210
211/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100212 * Setup context
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100213 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100214int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100215{
Hanno Becker91796d72018-12-17 18:10:51 +0000216 ECDH_VALIDATE_RET( ctx != NULL );
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100217
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100218#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
219 return( ecdh_setup_internal( ctx, grp_id ) );
220#else
221 switch( grp_id )
222 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100223#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000224 case MBEDTLS_ECP_DP_CURVE25519:
225 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
226 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
227 ctx->grp_id = grp_id;
228 return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) );
Christoph M. Wintersteiger78c9c462018-12-06 17:16:32 +0000229#endif
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000230 default:
231 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
232 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
233 ctx->grp_id = grp_id;
234 ecdh_init_internal( &ctx->ctx.mbed_ecdh );
235 return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100236 }
237#endif
238}
239
240static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
241{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 mbedtls_ecp_group_free( &ctx->grp );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200243 mbedtls_mpi_free( &ctx->d );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200244 mbedtls_ecp_point_free( &ctx->Q );
245 mbedtls_ecp_point_free( &ctx->Qp );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200246 mbedtls_mpi_free( &ctx->z );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200247
248#if defined(MBEDTLS_ECP_RESTARTABLE)
249 mbedtls_ecp_restart_free( &ctx->rs );
250#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100251}
252
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200253#if defined(MBEDTLS_ECP_RESTARTABLE)
254/*
255 * Enable restartable operations for context
256 */
257void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
258{
Hanno Beckera7634e82018-12-18 18:45:00 +0000259 ECDH_VALIDATE( ctx != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100260
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200261 ctx->restart_enabled = 1;
262}
263#endif
264
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100265/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100266 * Free context
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100267 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100268void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
269{
270 if( ctx == NULL )
271 return;
272
273#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
274 mbedtls_ecp_point_free( &ctx->Vi );
275 mbedtls_ecp_point_free( &ctx->Vf );
276 mbedtls_mpi_free( &ctx->_d );
277 ecdh_free_internal( ctx );
278#else
279 switch( ctx->var )
280 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100281#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
282 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000283 mbedtls_everest_free( &ctx->ctx.everest_ecdh );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100284 break;
285#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100286 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
287 ecdh_free_internal( &ctx->ctx.mbed_ecdh );
288 break;
289 default:
290 break;
291 }
292
293 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
294 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
295 ctx->grp_id = MBEDTLS_ECP_DP_NONE;
296#endif
297}
298
299static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
300 size_t *olen, int point_format,
301 unsigned char *buf, size_t blen,
302 int (*f_rng)(void *,
303 unsigned char *,
304 size_t),
305 void *p_rng,
306 int restart_enabled )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100307{
Janos Follath24eed8d2019-11-22 13:21:35 +0000308 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100309 size_t grp_len, pt_len;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200310#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200311 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200312#endif
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100313
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100314 if( ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100316
Ron Eldor19779c42018-11-05 16:58:13 +0200317#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100318 if( restart_enabled )
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200319 rs_ctx = &ctx->rs;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100320#else
321 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200322#endif
323
Ron Eldor8493f802018-11-01 11:32:15 +0200324
Ron Eldor2981d8f2018-11-05 18:07:10 +0200325#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200326 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +0200327 f_rng, p_rng, rs_ctx ) ) != 0 )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100328 return( ret );
Ron Eldor2981d8f2018-11-05 18:07:10 +0200329#else
330 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
331 f_rng, p_rng ) ) != 0 )
332 return( ret );
333#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100334
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100335 if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
336 blen ) ) != 0 )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100337 return( ret );
338
339 buf += grp_len;
340 blen -= grp_len;
341
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100342 if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +0200343 &pt_len, buf, blen ) ) != 0 )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100344 return( ret );
345
346 *olen = grp_len + pt_len;
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200347 return( 0 );
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100348}
349
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100350/*
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100351 * Setup and write the ServerKeyExchange parameters (RFC 4492)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100352 * struct {
353 * ECParameters curve_params;
354 * ECPoint public;
355 * } ServerECDHParams;
356 */
357int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
358 unsigned char *buf, size_t blen,
359 int (*f_rng)(void *, unsigned char *, size_t),
360 void *p_rng )
361{
362 int restart_enabled = 0;
Hanno Becker91796d72018-12-17 18:10:51 +0000363 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
368#if defined(MBEDTLS_ECP_RESTARTABLE)
369 restart_enabled = ctx->restart_enabled;
370#else
371 (void) restart_enabled;
372#endif
373
374#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 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100380#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
381 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000382 return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen,
383 buf, blen, f_rng, p_rng ) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100384#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100385 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
386 return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
387 ctx->point_format, buf, blen,
388 f_rng, p_rng,
389 restart_enabled ) );
390 default:
391 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
392 }
393#endif
394}
395
396static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
397 const unsigned char **buf,
398 const unsigned char *end )
399{
400 return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
401 end - *buf ) );
402}
403
404/*
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100405 * Read the ServerKeyExhange parameters (RFC 4492)
406 * struct {
407 * ECParameters curve_params;
408 * ECPoint public;
409 * } ServerECDHParams;
410 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100412 const unsigned char **buf,
413 const unsigned char *end )
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100414{
Janos Follath24eed8d2019-11-22 13:21:35 +0000415 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000416 mbedtls_ecp_group_id grp_id;
Hanno Becker91796d72018-12-17 18:10:51 +0000417 ECDH_VALIDATE_RET( ctx != NULL );
418 ECDH_VALIDATE_RET( buf != NULL );
419 ECDH_VALIDATE_RET( *buf != NULL );
420 ECDH_VALIDATE_RET( end != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100421
Janos Follathf61e4862018-10-30 11:53:25 +0000422 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
423 != 0 )
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100424 return( ret );
425
Janos Follathf61e4862018-10-30 11:53:25 +0000426 if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
427 return( ret );
428
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100429#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
430 return( ecdh_read_params_internal( ctx, buf, end ) );
431#else
432 switch( ctx->var )
433 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100434#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
435 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000436 return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh,
437 buf, end) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100438#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100439 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
440 return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
441 buf, end ) );
442 default:
443 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
444 }
445#endif
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100446}
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +0100447
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100448static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
449 const mbedtls_ecp_keypair *key,
450 mbedtls_ecdh_side side )
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100451{
Janos Follath24eed8d2019-11-22 13:21:35 +0000452 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100453
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100454 /* If it's not our key, just import the public part as Qp */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 if( side == MBEDTLS_ECDH_THEIRS )
456 return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100457
458 /* Our key: import public (as Q) and private parts */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 if( side != MBEDTLS_ECDH_OURS )
460 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100461
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
463 ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100464 return( ret );
465
466 return( 0 );
467}
468
469/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100470 * Get parameters from a keypair
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100471 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100472int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
473 const mbedtls_ecp_keypair *key,
474 mbedtls_ecdh_side side )
475{
Janos Follath24eed8d2019-11-22 13:21:35 +0000476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker91796d72018-12-17 18:10:51 +0000477 ECDH_VALIDATE_RET( ctx != NULL );
478 ECDH_VALIDATE_RET( key != NULL );
479 ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
480 side == MBEDTLS_ECDH_THEIRS );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100481
Gilles Peskine30816292019-02-22 12:31:25 +0100482 if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100483 {
484 /* This is the first call to get_params(). Set up the context
485 * for use with the group. */
486 if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
487 return( ret );
488 }
489 else
490 {
491 /* This is not the first call to get_params(). Check that the
492 * current key's group is the same as the context's, which was set
493 * from the first key's group. */
Gilles Peskine30816292019-02-22 12:31:25 +0100494 if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id )
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100495 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
496 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100497
498#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
499 return( ecdh_get_params_internal( ctx, key, side ) );
500#else
501 switch( ctx->var )
502 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100503#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
504 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000505 {
Christoph M. Wintersteiger2e724a12019-01-07 14:19:41 +0000506 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000507 MBEDTLS_EVEREST_ECDH_OURS :
508 MBEDTLS_EVEREST_ECDH_THEIRS;
509 return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh,
510 key, s) );
511 }
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100512#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100513 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
514 return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
515 key, side ) );
516 default:
517 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
518 }
519#endif
520}
521
522static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
523 size_t *olen, int point_format,
524 unsigned char *buf, size_t blen,
525 int (*f_rng)(void *,
526 unsigned char *,
527 size_t),
528 void *p_rng,
529 int restart_enabled )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100530{
Janos Follath24eed8d2019-11-22 13:21:35 +0000531 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200532#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200533 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200534#endif
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100535
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100536 if( ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100538
Ron Eldorb430d9f2018-11-05 17:18:29 +0200539#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100540 if( restart_enabled )
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200541 rs_ctx = &ctx->rs;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100542#else
543 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200544#endif
545
Ron Eldor2981d8f2018-11-05 18:07:10 +0200546#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200547 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100548 f_rng, p_rng, rs_ctx ) ) != 0 )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100549 return( ret );
Ron Eldor2981d8f2018-11-05 18:07:10 +0200550#else
551 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
552 f_rng, p_rng ) ) != 0 )
553 return( ret );
554#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100555
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100556 return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
557 buf, blen );
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100558}
559
560/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100561 * Setup and export the client public value
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100562 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100563int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
564 unsigned char *buf, size_t blen,
565 int (*f_rng)(void *, unsigned char *, size_t),
566 void *p_rng )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100567{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100568 int restart_enabled = 0;
Hanno Becker91796d72018-12-17 18:10:51 +0000569 ECDH_VALIDATE_RET( ctx != NULL );
570 ECDH_VALIDATE_RET( olen != NULL );
571 ECDH_VALIDATE_RET( buf != NULL );
Hanno Beckerc81cfec2018-12-18 23:32:42 +0000572 ECDH_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100573
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100574#if defined(MBEDTLS_ECP_RESTARTABLE)
575 restart_enabled = ctx->restart_enabled;
576#endif
577
578#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
579 return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
580 f_rng, p_rng, restart_enabled ) );
581#else
582 switch( ctx->var )
583 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100584#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
585 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000586 return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen,
587 buf, blen, f_rng, p_rng ) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100588#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100589 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
590 return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
591 ctx->point_format, buf, blen,
592 f_rng, p_rng,
593 restart_enabled ) );
594 default:
595 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
596 }
597#endif
598}
599
600static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
601 const unsigned char *buf, size_t blen )
602{
Janos Follath24eed8d2019-11-22 13:21:35 +0000603 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100604 const unsigned char *p = buf;
605
606 if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
607 blen ) ) != 0 )
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100608 return( ret );
609
610 if( (size_t)( p - buf ) != blen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100612
613 return( 0 );
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100614}
615
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100616/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100617 * Parse and import the client's public value
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100618 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100619int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
620 const unsigned char *buf, size_t blen )
621{
Hanno Becker91796d72018-12-17 18:10:51 +0000622 ECDH_VALIDATE_RET( ctx != NULL );
623 ECDH_VALIDATE_RET( buf != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100624
625#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
626 return( ecdh_read_public_internal( ctx, buf, blen ) );
627#else
628 switch( ctx->var )
629 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100630#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
631 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000632 return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh,
633 buf, blen ) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100634#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100635 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
636 return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
637 buf, blen ) );
638 default:
639 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
640 }
641#endif
642}
643
644static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
645 size_t *olen, unsigned char *buf,
646 size_t blen,
647 int (*f_rng)(void *,
648 unsigned char *,
649 size_t),
650 void *p_rng,
651 int restart_enabled )
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100652{
Janos Follath24eed8d2019-11-22 13:21:35 +0000653 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200654#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200655 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200656#endif
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100657
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200658 if( ctx == NULL || ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100660
Ron Eldorb430d9f2018-11-05 17:18:29 +0200661#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100662 if( restart_enabled )
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200663 rs_ctx = &ctx->rs;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100664#else
665 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200666#endif
667
Ron Eldor2981d8f2018-11-05 18:07:10 +0200668#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100669 if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
670 &ctx->d, f_rng, p_rng,
671 rs_ctx ) ) != 0 )
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200672 {
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100673 return( ret );
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200674 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200675#else
676 if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
677 &ctx->d, f_rng, p_rng ) ) != 0 )
678 {
679 return( ret );
680 }
681#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100682
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 if( mbedtls_mpi_size( &ctx->z ) > blen )
684 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Paul Bakker41c83d32013-03-20 14:39:14 +0100685
Manuel Pégourié-Gonnard0a56c2c2014-01-17 21:24:04 +0100686 *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
Janos Follathab0f71a2019-02-20 10:48:49 +0000687
Janos Follath52ff8e92019-02-26 13:56:04 +0000688 if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
Janos Follathab0f71a2019-02-20 10:48:49 +0000689 return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen );
690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691 return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100692}
693
Jerry Yud3f73342021-09-09 15:42:32 +0800694#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
695
696static int ecdh_read_tls13_public_internal( mbedtls_ecdh_context_mbed *ctx,
697 const unsigned char *buf,
698 size_t blen )
699{
700 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
701 const unsigned char *p = buf;
702
703 if( ( ret = mbedtls_ecp_tls13_read_point( &ctx->grp, &ctx->Qp, &p,
704 blen ) ) != 0 )
705 return( ret );
706
707 if( (size_t)( p - buf ) != blen )
708 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
709
710 return( 0 );
711}
712
713/*
714 * Parse and import the client's TLS 1.3 public value
715 */
716int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx,
717 const unsigned char *buf, size_t blen )
718{
719 ECDH_VALIDATE_RET( ctx != NULL );
720 ECDH_VALIDATE_RET( buf != NULL );
721
722#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
723 return( ecdh_read_tls13_public_internal( ctx, buf, blen ) );
724#else
725 switch( ctx->var )
726 {
727#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
728 case MBEDTLS_ECDH_VARIANT_EVEREST:
729 return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh,
730 buf, blen ) );
731#endif
732 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
733 return( ecdh_read_tls13_public_internal( &ctx->ctx.mbed_ecdh,
734 buf, blen ) );
735 default:
736 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
737 }
738#endif
739}
740
741#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
742
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100743/*
744 * Derive and export the shared secret
745 */
746int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
747 unsigned char *buf, size_t blen,
748 int (*f_rng)(void *, unsigned char *, size_t),
749 void *p_rng )
750{
751 int restart_enabled = 0;
Hanno Becker91796d72018-12-17 18:10:51 +0000752 ECDH_VALIDATE_RET( ctx != NULL );
753 ECDH_VALIDATE_RET( olen != NULL );
754 ECDH_VALIDATE_RET( buf != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100755
756#if defined(MBEDTLS_ECP_RESTARTABLE)
757 restart_enabled = ctx->restart_enabled;
758#endif
759
760#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
761 return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
762 restart_enabled ) );
763#else
764 switch( ctx->var )
765 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100766#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
767 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000768 return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen,
769 buf, blen, f_rng, p_rng ) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100770#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100771 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
772 return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
773 blen, f_rng, p_rng,
774 restart_enabled ) );
775 default:
776 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
777 }
778#endif
779}
780
Jerry Yu56fc07f2021-09-01 17:48:49 +0800781#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
782
783static int ecdh_tls13_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
Jerry Yubdc71882021-09-14 19:30:36 +0800784 size_t *olen, int point_format, unsigned char *buf, size_t blen,
785 int ( *f_rng )( void *, unsigned char *, size_t), void *p_rng )
Jerry Yu56fc07f2021-09-01 17:48:49 +0800786{
787 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jerry Yu56fc07f2021-09-01 17:48:49 +0800788
789 if( ctx->grp.pbits == 0 )
790 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
791
Jerry Yu56fc07f2021-09-01 17:48:49 +0800792 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
793 f_rng, p_rng ) ) != 0 )
794 return( ret );
Jerry Yu56fc07f2021-09-01 17:48:49 +0800795
796 ret = mbedtls_ecp_point_write_binary( &ctx->grp, &ctx->Q, point_format,
797 olen, buf, blen );
798 if( ret != 0 )
799 return( ret );
800
801 return( 0 );
802}
803
804int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
Jerry Yubdc71882021-09-14 19:30:36 +0800805 unsigned char *buf, size_t blen,
806 int ( *f_rng )( void *, unsigned char *, size_t ),
807 void *p_rng )
Jerry Yu56fc07f2021-09-01 17:48:49 +0800808{
Jerry Yu56fc07f2021-09-01 17:48:49 +0800809 ECDH_VALIDATE_RET( ctx != NULL );
810 ECDH_VALIDATE_RET( olen != NULL );
811 ECDH_VALIDATE_RET( buf != NULL );
812 ECDH_VALIDATE_RET( f_rng != NULL );
813
Jerry Yubdc71882021-09-14 19:30:36 +0800814
Jerry Yu56fc07f2021-09-01 17:48:49 +0800815#if defined(MBEDTLS_ECP_RESTARTABLE)
Jerry Yubdc71882021-09-14 19:30:36 +0800816 if( ctx-> restart_enabled )
817 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Jerry Yu56fc07f2021-09-01 17:48:49 +0800818#endif
819
820#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
Jerry Yubdc71882021-09-14 19:30:36 +0800821 return( ecdh_tls13_make_params_internal( ctx, olen, ctx->point_format,
822 buf, blen, f_rng, p_rng ) );
Jerry Yu56fc07f2021-09-01 17:48:49 +0800823#else
824 switch( ctx->var )
825 {
826#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
827 case MBEDTLS_ECDH_VARIANT_EVEREST:
Jerry Yubdc71882021-09-14 19:30:36 +0800828 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
Jerry Yu56fc07f2021-09-01 17:48:49 +0800829#endif
830 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
831 return( ecdh_tls13_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
832 ctx->point_format, buf, blen,
Jerry Yubdc71882021-09-14 19:30:36 +0800833 f_rng, p_rng ) );
Jerry Yu56fc07f2021-09-01 17:48:49 +0800834 default:
835 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
836 }
837#endif
838}
839
Jerry Yudd1fb9e2021-09-15 11:10:15 +0800840/*
Jerry Yu388bd0d2021-09-15 18:41:02 +0800841 * Setup context without Everest
Jerry Yudd1fb9e2021-09-15 11:10:15 +0800842 */
843int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx,
844 mbedtls_ecp_group_id grp_id )
845{
846 ECDH_VALIDATE_RET( ctx != NULL );
847
848#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
849 return( ecdh_setup_internal( ctx, grp_id ) );
850#else
851 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
852 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
853 ctx->grp_id = grp_id;
854 ecdh_init_internal( &ctx->ctx.mbed_ecdh );
855 return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
856#endif
857}
858
Jerry Yu56fc07f2021-09-01 17:48:49 +0800859#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
860
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200861#endif /* MBEDTLS_ECDH_C */