blob: ac601654430e8e34c038c82727dfa3a0e6e0e387 [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 Yu56fc07f2021-09-01 17:48:49 +080034#include "ssl_misc.h"
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010035
Rich Evans00ab4702015-02-06 13:43:58 +000036#include <string.h>
37
Hanno Becker91796d72018-12-17 18:10:51 +000038/* Parameter validation macros based on platform_util.h */
39#define ECDH_VALIDATE_RET( cond ) \
40 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
41#define ECDH_VALIDATE( cond ) \
42 MBEDTLS_INTERNAL_VALIDATE( cond )
43
Janos Follath5a3e1bf2018-08-13 15:54:22 +010044#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
45typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
46#endif
47
Gilles Peskine30816292019-02-22 12:31:25 +010048static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
49 const mbedtls_ecdh_context *ctx )
50{
51#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
52 return( ctx->grp.id );
53#else
54 return( ctx->grp_id );
55#endif
56}
57
Gilles Peskine20b3ef32019-02-11 18:41:27 +010058int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
59{
60 /* At this time, all groups support ECDH. */
61 (void) gid;
Christoph M. Wintersteigerc25df682019-04-16 12:54:56 +010062 return( 1 );
Gilles Peskine20b3ef32019-02-11 18:41:27 +010063}
64
Ron Eldora84c1cb2017-10-10 19:04:27 +030065#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010066/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020067 * Generate public key (restartable version)
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020068 *
69 * Note: this internal function relies on its caller preserving the value of
Manuel Pégourié-Gonnardca29fdf2018-10-22 09:56:53 +020070 * the output parameter 'd' across continuation calls. This would not be
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020071 * acceptable for a public function but is OK here as we control call sites.
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020072 */
73static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
74 mbedtls_mpi *d, mbedtls_ecp_point *Q,
75 int (*f_rng)(void *, unsigned char *, size_t),
76 void *p_rng,
77 mbedtls_ecp_restart_ctx *rs_ctx )
78{
Janos Follath24eed8d2019-11-22 13:21:35 +000079 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020080
81 /* If multiplication is in progress, we already generated a privkey */
82#if defined(MBEDTLS_ECP_RESTARTABLE)
83 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
84#endif
85 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
86
87 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
88 f_rng, p_rng, rs_ctx ) );
89
90cleanup:
91 return( ret );
92}
93
94/*
95 * Generate public key
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010096 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010098 int (*f_rng)(void *, unsigned char *, size_t),
99 void *p_rng )
100{
Hanno Becker91796d72018-12-17 18:10:51 +0000101 ECDH_VALIDATE_RET( grp != NULL );
102 ECDH_VALIDATE_RET( d != NULL );
103 ECDH_VALIDATE_RET( Q != NULL );
104 ECDH_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200105 return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100106}
Ron Eldor936d2842018-11-01 13:05:52 +0200107#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100108
Ron Eldora84c1cb2017-10-10 19:04:27 +0300109#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100110/*
111 * Compute shared secret (SEC1 3.3.1)
112 */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200113static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
114 mbedtls_mpi *z,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200115 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200116 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200117 void *p_rng,
118 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100119{
Janos Follath24eed8d2019-11-22 13:21:35 +0000120 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 mbedtls_ecp_point P;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100122
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 mbedtls_ecp_point_init( &P );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100124
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200125 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
126 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128 if( mbedtls_ecp_is_zero( &P ) )
Paul Bakkerb548d772013-07-26 14:21:34 +0200129 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakkerb548d772013-07-26 14:21:34 +0200131 goto cleanup;
132 }
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100133
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100135
136cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137 mbedtls_ecp_point_free( &P );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100138
139 return( ret );
140}
141
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100142/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200143 * Compute shared secret (SEC1 3.3.1)
144 */
145int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
146 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
147 int (*f_rng)(void *, unsigned char *, size_t),
148 void *p_rng )
149{
Hanno Becker91796d72018-12-17 18:10:51 +0000150 ECDH_VALIDATE_RET( grp != NULL );
151 ECDH_VALIDATE_RET( Q != NULL );
152 ECDH_VALIDATE_RET( d != NULL );
153 ECDH_VALIDATE_RET( z != NULL );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200154 return( ecdh_compute_shared_restartable( grp, z, Q, d,
155 f_rng, p_rng, NULL ) );
156}
Ron Eldor936d2842018-11-01 13:05:52 +0200157#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200158
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100159static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100160{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200161 mbedtls_ecp_group_init( &ctx->grp );
162 mbedtls_mpi_init( &ctx->d );
163 mbedtls_ecp_point_init( &ctx->Q );
164 mbedtls_ecp_point_init( &ctx->Qp );
165 mbedtls_mpi_init( &ctx->z );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200166
167#if defined(MBEDTLS_ECP_RESTARTABLE)
168 mbedtls_ecp_restart_init( &ctx->rs );
169#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100170}
171
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100172/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100173 * Initialize context
Janos Follathf61e4862018-10-30 11:53:25 +0000174 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100175void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
176{
Hanno Becker91796d72018-12-17 18:10:51 +0000177 ECDH_VALIDATE( ctx != NULL );
178
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100179#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
180 ecdh_init_internal( ctx );
181 mbedtls_ecp_point_init( &ctx->Vi );
182 mbedtls_ecp_point_init( &ctx->Vf );
183 mbedtls_mpi_init( &ctx->_d );
184#else
Christoph M. Wintersteigerd8c45d52019-02-20 17:16:53 +0000185 memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
186
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100187 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
188#endif
189 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
190#if defined(MBEDTLS_ECP_RESTARTABLE)
191 ctx->restart_enabled = 0;
192#endif
193}
194
195static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
196 mbedtls_ecp_group_id grp_id )
Janos Follathf61e4862018-10-30 11:53:25 +0000197{
Janos Follath24eed8d2019-11-22 13:21:35 +0000198 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000199
200 ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
201 if( ret != 0 )
202 {
Janos Follathf61e4862018-10-30 11:53:25 +0000203 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
204 }
205
206 return( 0 );
207}
208
209/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100210 * Setup context
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100211 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100212int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100213{
Hanno Becker91796d72018-12-17 18:10:51 +0000214 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)
217 return( ecdh_setup_internal( ctx, grp_id ) );
218#else
219 switch( grp_id )
220 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100221#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000222 case MBEDTLS_ECP_DP_CURVE25519:
223 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
224 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
225 ctx->grp_id = grp_id;
226 return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) );
Christoph M. Wintersteiger78c9c462018-12-06 17:16:32 +0000227#endif
Christoph M. Wintersteiger3ff60bc2019-02-15 12:59:59 +0000228 default:
229 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
230 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
231 ctx->grp_id = grp_id;
232 ecdh_init_internal( &ctx->ctx.mbed_ecdh );
233 return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100234 }
235#endif
236}
237
238static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
239{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 mbedtls_ecp_group_free( &ctx->grp );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200241 mbedtls_mpi_free( &ctx->d );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 mbedtls_ecp_point_free( &ctx->Q );
243 mbedtls_ecp_point_free( &ctx->Qp );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200244 mbedtls_mpi_free( &ctx->z );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200245
246#if defined(MBEDTLS_ECP_RESTARTABLE)
247 mbedtls_ecp_restart_free( &ctx->rs );
248#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100249}
250
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200251#if defined(MBEDTLS_ECP_RESTARTABLE)
252/*
253 * Enable restartable operations for context
254 */
255void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
256{
Hanno Beckera7634e82018-12-18 18:45:00 +0000257 ECDH_VALIDATE( ctx != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100258
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200259 ctx->restart_enabled = 1;
260}
261#endif
262
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100263/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100264 * Free context
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100265 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100266void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
267{
268 if( ctx == NULL )
269 return;
270
271#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
272 mbedtls_ecp_point_free( &ctx->Vi );
273 mbedtls_ecp_point_free( &ctx->Vf );
274 mbedtls_mpi_free( &ctx->_d );
275 ecdh_free_internal( ctx );
276#else
277 switch( ctx->var )
278 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100279#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
280 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000281 mbedtls_everest_free( &ctx->ctx.everest_ecdh );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100282 break;
283#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100284 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
285 ecdh_free_internal( &ctx->ctx.mbed_ecdh );
286 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;
294#endif
295}
296
297static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
298 size_t *olen, int point_format,
299 unsigned char *buf, size_t blen,
300 int (*f_rng)(void *,
301 unsigned char *,
302 size_t),
303 void *p_rng,
304 int restart_enabled )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100305{
Janos Follath24eed8d2019-11-22 13:21:35 +0000306 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100307 size_t grp_len, pt_len;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200308#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200309 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200310#endif
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100311
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100312 if( ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100314
Ron Eldor19779c42018-11-05 16:58:13 +0200315#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100316 if( restart_enabled )
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200317 rs_ctx = &ctx->rs;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100318#else
319 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200320#endif
321
Ron Eldor8493f802018-11-01 11:32:15 +0200322
Ron Eldor2981d8f2018-11-05 18:07:10 +0200323#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200324 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +0200325 f_rng, p_rng, rs_ctx ) ) != 0 )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100326 return( ret );
Ron Eldor2981d8f2018-11-05 18:07:10 +0200327#else
328 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
329 f_rng, p_rng ) ) != 0 )
330 return( ret );
331#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100332
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100333 if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
334 blen ) ) != 0 )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100335 return( ret );
336
337 buf += grp_len;
338 blen -= grp_len;
339
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100340 if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +0200341 &pt_len, buf, blen ) ) != 0 )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100342 return( ret );
343
344 *olen = grp_len + pt_len;
Paul Bakkerd8bb8262014-06-17 14:06:49 +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 */
355int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
356 unsigned char *buf, size_t blen,
357 int (*f_rng)(void *, unsigned char *, size_t),
358 void *p_rng )
359{
360 int restart_enabled = 0;
Hanno Becker91796d72018-12-17 18:10:51 +0000361 ECDH_VALIDATE_RET( ctx != NULL );
362 ECDH_VALIDATE_RET( olen != NULL );
363 ECDH_VALIDATE_RET( buf != NULL );
364 ECDH_VALIDATE_RET( f_rng != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100365
366#if defined(MBEDTLS_ECP_RESTARTABLE)
367 restart_enabled = ctx->restart_enabled;
368#else
369 (void) restart_enabled;
370#endif
371
372#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
373 return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
374 f_rng, p_rng, restart_enabled ) );
375#else
376 switch( ctx->var )
377 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100378#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
379 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000380 return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen,
381 buf, blen, f_rng, p_rng ) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100382#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100383 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
384 return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
385 ctx->point_format, buf, blen,
386 f_rng, p_rng,
387 restart_enabled ) );
388 default:
389 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
390 }
391#endif
392}
393
394static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
395 const unsigned char **buf,
396 const unsigned char *end )
397{
398 return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
399 end - *buf ) );
400}
401
402/*
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100403 * Read the ServerKeyExhange parameters (RFC 4492)
404 * struct {
405 * ECParameters curve_params;
406 * ECPoint public;
407 * } ServerECDHParams;
408 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100410 const unsigned char **buf,
411 const unsigned char *end )
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100412{
Janos Follath24eed8d2019-11-22 13:21:35 +0000413 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follathf61e4862018-10-30 11:53:25 +0000414 mbedtls_ecp_group_id grp_id;
Hanno Becker91796d72018-12-17 18:10:51 +0000415 ECDH_VALIDATE_RET( ctx != NULL );
416 ECDH_VALIDATE_RET( buf != NULL );
417 ECDH_VALIDATE_RET( *buf != NULL );
418 ECDH_VALIDATE_RET( end != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100419
Janos Follathf61e4862018-10-30 11:53:25 +0000420 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
421 != 0 )
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100422 return( ret );
423
Janos Follathf61e4862018-10-30 11:53:25 +0000424 if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
425 return( ret );
426
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100427#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
428 return( ecdh_read_params_internal( ctx, buf, end ) );
429#else
430 switch( ctx->var )
431 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100432#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
433 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000434 return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh,
435 buf, end) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100436#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100437 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
438 return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
439 buf, end ) );
440 default:
441 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
442 }
443#endif
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100444}
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +0100445
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100446static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
447 const mbedtls_ecp_keypair *key,
448 mbedtls_ecdh_side side )
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100449{
Janos Follath24eed8d2019-11-22 13:21:35 +0000450 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100451
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100452 /* If it's not our key, just import the public part as Qp */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 if( side == MBEDTLS_ECDH_THEIRS )
454 return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100455
456 /* Our key: import public (as Q) and private parts */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 if( side != MBEDTLS_ECDH_OURS )
458 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100459
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200460 if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
461 ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100462 return( ret );
463
464 return( 0 );
465}
466
467/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100468 * Get parameters from a keypair
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100469 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100470int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
471 const mbedtls_ecp_keypair *key,
472 mbedtls_ecdh_side side )
473{
Janos Follath24eed8d2019-11-22 13:21:35 +0000474 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker91796d72018-12-17 18:10:51 +0000475 ECDH_VALIDATE_RET( ctx != NULL );
476 ECDH_VALIDATE_RET( key != NULL );
477 ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
478 side == MBEDTLS_ECDH_THEIRS );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100479
Gilles Peskine30816292019-02-22 12:31:25 +0100480 if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100481 {
482 /* This is the first call to get_params(). Set up the context
483 * for use with the group. */
484 if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
485 return( ret );
486 }
487 else
488 {
489 /* This is not the first call to get_params(). Check that the
490 * current key's group is the same as the context's, which was set
491 * from the first key's group. */
Gilles Peskine30816292019-02-22 12:31:25 +0100492 if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id )
Gilles Peskine0b1b71d2018-11-07 22:10:59 +0100493 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
494 }
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100495
496#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
497 return( ecdh_get_params_internal( ctx, key, side ) );
498#else
499 switch( ctx->var )
500 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100501#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
502 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000503 {
Christoph M. Wintersteiger2e724a12019-01-07 14:19:41 +0000504 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000505 MBEDTLS_EVEREST_ECDH_OURS :
506 MBEDTLS_EVEREST_ECDH_THEIRS;
507 return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh,
508 key, s) );
509 }
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100510#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100511 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
512 return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
513 key, side ) );
514 default:
515 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
516 }
517#endif
518}
519
520static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
521 size_t *olen, int point_format,
522 unsigned char *buf, size_t blen,
523 int (*f_rng)(void *,
524 unsigned char *,
525 size_t),
526 void *p_rng,
527 int restart_enabled )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100528{
Janos Follath24eed8d2019-11-22 13:21:35 +0000529 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200530#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200531 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200532#endif
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100533
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100534 if( ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200535 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100536
Ron Eldorb430d9f2018-11-05 17:18:29 +0200537#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100538 if( restart_enabled )
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200539 rs_ctx = &ctx->rs;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100540#else
541 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200542#endif
543
Ron Eldor2981d8f2018-11-05 18:07:10 +0200544#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200545 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100546 f_rng, p_rng, rs_ctx ) ) != 0 )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100547 return( ret );
Ron Eldor2981d8f2018-11-05 18:07:10 +0200548#else
549 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
550 f_rng, p_rng ) ) != 0 )
551 return( ret );
552#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100553
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100554 return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
555 buf, blen );
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100556}
557
558/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100559 * Setup and export the client public value
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100560 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100561int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
562 unsigned char *buf, size_t blen,
563 int (*f_rng)(void *, unsigned char *, size_t),
564 void *p_rng )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100565{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100566 int restart_enabled = 0;
Hanno Becker91796d72018-12-17 18:10:51 +0000567 ECDH_VALIDATE_RET( ctx != NULL );
568 ECDH_VALIDATE_RET( olen != NULL );
569 ECDH_VALIDATE_RET( buf != NULL );
Hanno Beckerc81cfec2018-12-18 23:32:42 +0000570 ECDH_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100571
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100572#if defined(MBEDTLS_ECP_RESTARTABLE)
573 restart_enabled = ctx->restart_enabled;
574#endif
575
576#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
577 return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
578 f_rng, p_rng, restart_enabled ) );
579#else
580 switch( ctx->var )
581 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100582#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
583 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000584 return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen,
585 buf, blen, f_rng, p_rng ) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100586#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100587 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
588 return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
589 ctx->point_format, buf, blen,
590 f_rng, p_rng,
591 restart_enabled ) );
592 default:
593 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
594 }
595#endif
596}
597
598static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
599 const unsigned char *buf, size_t blen )
600{
Janos Follath24eed8d2019-11-22 13:21:35 +0000601 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100602 const unsigned char *p = buf;
603
604 if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
605 blen ) ) != 0 )
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100606 return( ret );
607
608 if( (size_t)( p - buf ) != blen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100610
611 return( 0 );
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100612}
613
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100614/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100615 * Parse and import the client's public value
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100616 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100617int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
618 const unsigned char *buf, size_t blen )
619{
Hanno Becker91796d72018-12-17 18:10:51 +0000620 ECDH_VALIDATE_RET( ctx != NULL );
621 ECDH_VALIDATE_RET( buf != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100622
623#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
624 return( ecdh_read_public_internal( ctx, buf, blen ) );
625#else
626 switch( ctx->var )
627 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100628#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
629 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000630 return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh,
631 buf, blen ) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100632#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100633 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
634 return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
635 buf, blen ) );
636 default:
637 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
638 }
639#endif
640}
641
642static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
643 size_t *olen, unsigned char *buf,
644 size_t blen,
645 int (*f_rng)(void *,
646 unsigned char *,
647 size_t),
648 void *p_rng,
649 int restart_enabled )
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100650{
Janos Follath24eed8d2019-11-22 13:21:35 +0000651 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200652#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200653 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200654#endif
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100655
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200656 if( ctx == NULL || ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100658
Ron Eldorb430d9f2018-11-05 17:18:29 +0200659#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100660 if( restart_enabled )
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200661 rs_ctx = &ctx->rs;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100662#else
663 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200664#endif
665
Ron Eldor2981d8f2018-11-05 18:07:10 +0200666#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100667 if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
668 &ctx->d, f_rng, p_rng,
669 rs_ctx ) ) != 0 )
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200670 {
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100671 return( ret );
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200672 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200673#else
674 if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
675 &ctx->d, f_rng, p_rng ) ) != 0 )
676 {
677 return( ret );
678 }
679#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100680
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 if( mbedtls_mpi_size( &ctx->z ) > blen )
682 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Paul Bakker41c83d32013-03-20 14:39:14 +0100683
Manuel Pégourié-Gonnard0a56c2c2014-01-17 21:24:04 +0100684 *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
Janos Follathab0f71a2019-02-20 10:48:49 +0000685
Janos Follath52ff8e92019-02-26 13:56:04 +0000686 if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
Janos Follathab0f71a2019-02-20 10:48:49 +0000687 return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen );
688
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100690}
691
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100692/*
693 * Derive and export the shared secret
694 */
695int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
696 unsigned char *buf, size_t blen,
697 int (*f_rng)(void *, unsigned char *, size_t),
698 void *p_rng )
699{
700 int restart_enabled = 0;
Hanno Becker91796d72018-12-17 18:10:51 +0000701 ECDH_VALIDATE_RET( ctx != NULL );
702 ECDH_VALIDATE_RET( olen != NULL );
703 ECDH_VALIDATE_RET( buf != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100704
705#if defined(MBEDTLS_ECP_RESTARTABLE)
706 restart_enabled = ctx->restart_enabled;
707#endif
708
709#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
710 return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
711 restart_enabled ) );
712#else
713 switch( ctx->var )
714 {
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100715#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
716 case MBEDTLS_ECDH_VARIANT_EVEREST:
Christoph M. Wintersteiger4936beb2018-12-12 17:26:41 +0000717 return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen,
718 buf, blen, f_rng, p_rng ) );
Christoph M. Wintersteigerc9f737b2018-10-25 13:03:05 +0100719#endif
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100720 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
721 return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
722 blen, f_rng, p_rng,
723 restart_enabled ) );
724 default:
725 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
726 }
727#endif
728}
729
Jerry Yu56fc07f2021-09-01 17:48:49 +0800730#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
731
732static int ecdh_tls13_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
733 size_t *olen, int point_format,
734 unsigned char *buf, size_t blen,
735 int ( *f_rng )( void *,
736 unsigned char *,
737 size_t),
738 void *p_rng, int restart_enabled )
739{
740 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
741#if defined(MBEDTLS_ECP_RESTARTABLE)
742 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
743#endif
744
745 if( ctx->grp.pbits == 0 )
746 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
747
748#if defined(MBEDTLS_ECP_RESTARTABLE)
749 if( restart_enabled )
750 rs_ctx = &ctx->rs;
751#else
752 (void) restart_enabled;
753#endif
754
755#if defined(MBEDTLS_ECP_RESTARTABLE)
756 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
757 f_rng, p_rng, rs_ctx ) ) != 0 )
758 return( ret );
759#else
760 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
761 f_rng, p_rng ) ) != 0 )
762 return( ret );
763#endif /* MBEDTLS_ECP_RESTARTABLE */
764
765 ret = mbedtls_ecp_point_write_binary( &ctx->grp, &ctx->Q, point_format,
766 olen, buf, blen );
767 if( ret != 0 )
768 return( ret );
769
770 return( 0 );
771}
772
773int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
774 unsigned char *buf, size_t blen,
775 int ( *f_rng )( void *, unsigned char *, size_t ),
776 void *p_rng )
777{
778 int restart_enabled = 0;
779 ECDH_VALIDATE_RET( ctx != NULL );
780 ECDH_VALIDATE_RET( olen != NULL );
781 ECDH_VALIDATE_RET( buf != NULL );
782 ECDH_VALIDATE_RET( f_rng != NULL );
783
784#if defined(MBEDTLS_ECP_RESTARTABLE)
785 restart_enabled = ctx->restart_enabled;
786#else
787 (void) restart_enabled;
788#endif
789
790#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
791 return( ecdh_tls13_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
792 f_rng, p_rng, restart_enabled ) );
793#else
794 switch( ctx->var )
795 {
796#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
797 case MBEDTLS_ECDH_VARIANT_EVEREST:
798 return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen,
799 buf, blen, f_rng, p_rng ) );
800#endif
801 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
802 return( ecdh_tls13_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
803 ctx->point_format, buf, blen,
804 f_rng, p_rng,
805 restart_enabled ) );
806 default:
807 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
808 }
809#endif
810}
811
812#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
813
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200814#endif /* MBEDTLS_ECDH_C */