blob: d196852aa005e8f888d03b4af0fc26d2035cd4ce [file] [log] [blame]
Edison Aic6672fd2018-02-28 15:01:47 +08001// SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02002/*
3 * Elliptic curve Diffie-Hellman
4 *
5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
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.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
23 * References:
24 *
25 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
26 * RFC 4492
27 */
28
29#if !defined(MBEDTLS_CONFIG_FILE)
30#include "mbedtls/config.h"
31#else
32#include MBEDTLS_CONFIG_FILE
33#endif
34
35#if defined(MBEDTLS_ECDH_C)
36
37#include "mbedtls/ecdh.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010038#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020039#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020040
41#include <string.h>
42
Jens Wiklander3d3b0592019-03-20 15:30:29 +010043/* Parameter validation macros based on platform_util.h */
44#define ECDH_VALIDATE_RET( cond ) \
45 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
46#define ECDH_VALIDATE( cond ) \
47 MBEDTLS_INTERNAL_VALIDATE( cond )
48
49#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
50typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
51#endif
52
Jerome Forissier5b25c762020-04-07 11:18:49 +020053static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
54 const mbedtls_ecdh_context *ctx )
55{
56#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
57 return( ctx->grp.id );
58#else
59 return( ctx->grp_id );
60#endif
61}
62
Jerome Forissier11fa71b2020-04-20 17:17:56 +020063int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
64{
65 /* At this time, all groups support ECDH. */
66 (void) gid;
67 return( 1 );
68}
69
Jens Wiklander3d3b0592019-03-20 15:30:29 +010070#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +020071/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +010072 * Generate public key (restartable version)
73 *
74 * Note: this internal function relies on its caller preserving the value of
75 * the output parameter 'd' across continuation calls. This would not be
76 * acceptable for a public function but is OK here as we control call sites.
77 */
78static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
79 mbedtls_mpi *d, mbedtls_ecp_point *Q,
80 int (*f_rng)(void *, unsigned char *, size_t),
81 void *p_rng,
82 mbedtls_ecp_restart_ctx *rs_ctx )
83{
Jerome Forissier11fa71b2020-04-20 17:17:56 +020084 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +010085
86 /* If multiplication is in progress, we already generated a privkey */
87#if defined(MBEDTLS_ECP_RESTARTABLE)
88 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
89#endif
90 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
91
92 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
93 f_rng, p_rng, rs_ctx ) );
94
95cleanup:
96 return( ret );
97}
98
99/*
100 * Generate public key
Jens Wiklander817466c2018-05-22 13:49:31 +0200101 */
102int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
103 int (*f_rng)(void *, unsigned char *, size_t),
104 void *p_rng )
105{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100106 ECDH_VALIDATE_RET( grp != NULL );
107 ECDH_VALIDATE_RET( d != NULL );
108 ECDH_VALIDATE_RET( Q != NULL );
109 ECDH_VALIDATE_RET( f_rng != NULL );
110 return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200111}
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100112#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200113
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100114#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200115/*
116 * Compute shared secret (SEC1 3.3.1)
117 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100118static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
119 mbedtls_mpi *z,
Jens Wiklander817466c2018-05-22 13:49:31 +0200120 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
121 int (*f_rng)(void *, unsigned char *, size_t),
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100122 void *p_rng,
123 mbedtls_ecp_restart_ctx *rs_ctx )
Jens Wiklander817466c2018-05-22 13:49:31 +0200124{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200125 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200126 mbedtls_ecp_point P;
127
128 mbedtls_ecp_point_init( &P );
129
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100130 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
131 f_rng, p_rng, rs_ctx ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200132
133 if( mbedtls_ecp_is_zero( &P ) )
134 {
135 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
136 goto cleanup;
137 }
138
139 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
140
141cleanup:
142 mbedtls_ecp_point_free( &P );
143
144 return( ret );
145}
146
147/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100148 * Compute shared secret (SEC1 3.3.1)
149 */
150int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
151 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
152 int (*f_rng)(void *, unsigned char *, size_t),
153 void *p_rng )
154{
155 ECDH_VALIDATE_RET( grp != NULL );
156 ECDH_VALIDATE_RET( Q != NULL );
157 ECDH_VALIDATE_RET( d != NULL );
158 ECDH_VALIDATE_RET( z != NULL );
159 return( ecdh_compute_shared_restartable( grp, z, Q, d,
160 f_rng, p_rng, NULL ) );
161}
162#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
163
164static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
165{
166 mbedtls_ecp_group_init( &ctx->grp );
167 mbedtls_mpi_init( &ctx->d );
168 mbedtls_ecp_point_init( &ctx->Q );
169 mbedtls_ecp_point_init( &ctx->Qp );
170 mbedtls_mpi_init( &ctx->z );
171
172#if defined(MBEDTLS_ECP_RESTARTABLE)
173 mbedtls_ecp_restart_init( &ctx->rs );
174#endif
175}
176
177/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200178 * Initialize context
179 */
180void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
181{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100182 ECDH_VALIDATE( ctx != NULL );
183
184#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
185 ecdh_init_internal( ctx );
186 mbedtls_ecp_point_init( &ctx->Vi );
187 mbedtls_ecp_point_init( &ctx->Vf );
188 mbedtls_mpi_init( &ctx->_d );
189#else
Jens Wiklander817466c2018-05-22 13:49:31 +0200190 memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100191
192 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
193#endif
194 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
195#if defined(MBEDTLS_ECP_RESTARTABLE)
196 ctx->restart_enabled = 0;
197#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200198}
199
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100200static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
201 mbedtls_ecp_group_id grp_id )
202{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200203 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100204
205 ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
206 if( ret != 0 )
207 {
208 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
209 }
210
211 return( 0 );
212}
213
214/*
215 * Setup context
216 */
217int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
218{
219 ECDH_VALIDATE_RET( ctx != NULL );
220
221#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
222 return( ecdh_setup_internal( ctx, grp_id ) );
223#else
224 switch( grp_id )
225 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200226#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
227 case MBEDTLS_ECP_DP_CURVE25519:
228 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
229 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
230 ctx->grp_id = grp_id;
231 return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) );
232#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100233 default:
234 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
235 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
236 ctx->grp_id = grp_id;
237 ecdh_init_internal( &ctx->ctx.mbed_ecdh );
238 return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
239 }
240#endif
241}
242
243static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
244{
245 mbedtls_ecp_group_free( &ctx->grp );
246 mbedtls_mpi_free( &ctx->d );
247 mbedtls_ecp_point_free( &ctx->Q );
248 mbedtls_ecp_point_free( &ctx->Qp );
249 mbedtls_mpi_free( &ctx->z );
250
251#if defined(MBEDTLS_ECP_RESTARTABLE)
252 mbedtls_ecp_restart_free( &ctx->rs );
253#endif
254}
255
256#if defined(MBEDTLS_ECP_RESTARTABLE)
257/*
258 * Enable restartable operations for context
259 */
260void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
261{
262 ECDH_VALIDATE( ctx != NULL );
263
264 ctx->restart_enabled = 1;
265}
266#endif
267
Jens Wiklander817466c2018-05-22 13:49:31 +0200268/*
269 * Free context
270 */
271void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
272{
273 if( ctx == NULL )
274 return;
275
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100276#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
277 mbedtls_ecp_point_free( &ctx->Vi );
278 mbedtls_ecp_point_free( &ctx->Vf );
Jens Wiklander817466c2018-05-22 13:49:31 +0200279 mbedtls_mpi_free( &ctx->_d );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100280 ecdh_free_internal( ctx );
281#else
282 switch( ctx->var )
283 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200284#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
285 case MBEDTLS_ECDH_VARIANT_EVEREST:
286 mbedtls_everest_free( &ctx->ctx.everest_ecdh );
287 break;
288#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100289 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
290 ecdh_free_internal( &ctx->ctx.mbed_ecdh );
291 break;
292 default:
293 break;
294 }
295
296 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
297 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
298 ctx->grp_id = MBEDTLS_ECP_DP_NONE;
299#endif
300}
301
302static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
303 size_t *olen, int point_format,
304 unsigned char *buf, size_t blen,
305 int (*f_rng)(void *,
306 unsigned char *,
307 size_t),
308 void *p_rng,
309 int restart_enabled )
310{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200311 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100312 size_t grp_len, pt_len;
313#if defined(MBEDTLS_ECP_RESTARTABLE)
314 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
315#endif
316
317 if( ctx->grp.pbits == 0 )
318 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
319
320#if defined(MBEDTLS_ECP_RESTARTABLE)
321 if( restart_enabled )
322 rs_ctx = &ctx->rs;
323#else
324 (void) restart_enabled;
325#endif
326
327
328#if defined(MBEDTLS_ECP_RESTARTABLE)
329 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
330 f_rng, p_rng, rs_ctx ) ) != 0 )
331 return( ret );
332#else
333 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
334 f_rng, p_rng ) ) != 0 )
335 return( ret );
336#endif /* MBEDTLS_ECP_RESTARTABLE */
337
338 if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
339 blen ) ) != 0 )
340 return( ret );
341
342 buf += grp_len;
343 blen -= grp_len;
344
345 if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
346 &pt_len, buf, blen ) ) != 0 )
347 return( ret );
348
349 *olen = grp_len + pt_len;
350 return( 0 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200351}
352
353/*
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200354 * Setup and write the ServerKeyExchange parameters (RFC 4492)
Jens Wiklander817466c2018-05-22 13:49:31 +0200355 * struct {
356 * ECParameters curve_params;
357 * ECPoint public;
358 * } ServerECDHParams;
359 */
360int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100361 unsigned char *buf, size_t blen,
362 int (*f_rng)(void *, unsigned char *, size_t),
363 void *p_rng )
Jens Wiklander817466c2018-05-22 13:49:31 +0200364{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100365 int restart_enabled = 0;
366 ECDH_VALIDATE_RET( ctx != NULL );
367 ECDH_VALIDATE_RET( olen != NULL );
368 ECDH_VALIDATE_RET( buf != NULL );
369 ECDH_VALIDATE_RET( f_rng != NULL );
Jens Wiklander817466c2018-05-22 13:49:31 +0200370
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100371#if defined(MBEDTLS_ECP_RESTARTABLE)
372 restart_enabled = ctx->restart_enabled;
373#else
374 (void) restart_enabled;
375#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200376
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100377#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
378 return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
379 f_rng, p_rng, restart_enabled ) );
380#else
381 switch( ctx->var )
382 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200383#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
384 case MBEDTLS_ECDH_VARIANT_EVEREST:
385 return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen,
386 buf, blen, f_rng, p_rng ) );
387#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100388 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
389 return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
390 ctx->point_format, buf, blen,
391 f_rng, p_rng,
392 restart_enabled ) );
393 default:
394 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
395 }
396#endif
397}
Jens Wiklander817466c2018-05-22 13:49:31 +0200398
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100399static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
400 const unsigned char **buf,
401 const unsigned char *end )
402{
403 return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
404 end - *buf ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200405}
406
407/*
408 * Read the ServerKeyExhange parameters (RFC 4492)
409 * struct {
410 * ECParameters curve_params;
411 * ECPoint public;
412 * } ServerECDHParams;
413 */
414int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100415 const unsigned char **buf,
416 const unsigned char *end )
Jens Wiklander817466c2018-05-22 13:49:31 +0200417{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200418 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100419 mbedtls_ecp_group_id grp_id;
420 ECDH_VALIDATE_RET( ctx != NULL );
421 ECDH_VALIDATE_RET( buf != NULL );
422 ECDH_VALIDATE_RET( *buf != NULL );
423 ECDH_VALIDATE_RET( end != NULL );
Jens Wiklander817466c2018-05-22 13:49:31 +0200424
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100425 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
426 != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200427 return( ret );
428
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100429 if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200430 return( ret );
431
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100432#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
433 return( ecdh_read_params_internal( ctx, buf, end ) );
434#else
435 switch( ctx->var )
436 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200437#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
438 case MBEDTLS_ECDH_VARIANT_EVEREST:
439 return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh,
440 buf, end) );
441#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100442 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
443 return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
444 buf, end ) );
445 default:
446 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
447 }
448#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200449}
450
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100451static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
452 const mbedtls_ecp_keypair *key,
453 mbedtls_ecdh_side side )
Jens Wiklander817466c2018-05-22 13:49:31 +0200454{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200455 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200456
Jens Wiklander817466c2018-05-22 13:49:31 +0200457 /* If it's not our key, just import the public part as Qp */
458 if( side == MBEDTLS_ECDH_THEIRS )
459 return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
460
461 /* Our key: import public (as Q) and private parts */
462 if( side != MBEDTLS_ECDH_OURS )
463 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
464
465 if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
466 ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
467 return( ret );
468
469 return( 0 );
470}
471
472/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100473 * Get parameters from a keypair
Jens Wiklander817466c2018-05-22 13:49:31 +0200474 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100475int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
476 const mbedtls_ecp_keypair *key,
477 mbedtls_ecdh_side side )
Jens Wiklander817466c2018-05-22 13:49:31 +0200478{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200479 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100480 ECDH_VALIDATE_RET( ctx != NULL );
481 ECDH_VALIDATE_RET( key != NULL );
482 ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
483 side == MBEDTLS_ECDH_THEIRS );
Jens Wiklander817466c2018-05-22 13:49:31 +0200484
Jerome Forissier5b25c762020-04-07 11:18:49 +0200485 if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
486 {
487 /* This is the first call to get_params(). Set up the context
488 * for use with the group. */
489 if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
490 return( ret );
491 }
492 else
493 {
494 /* This is not the first call to get_params(). Check that the
495 * current key's group is the same as the context's, which was set
496 * from the first key's group. */
497 if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id )
498 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
499 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200500
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100501#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
502 return( ecdh_get_params_internal( ctx, key, side ) );
503#else
504 switch( ctx->var )
505 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200506#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
507 case MBEDTLS_ECDH_VARIANT_EVEREST:
508 {
509 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
510 MBEDTLS_EVEREST_ECDH_OURS :
511 MBEDTLS_EVEREST_ECDH_THEIRS;
512 return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh,
513 key, s) );
514 }
515#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100516 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
517 return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
518 key, side ) );
519 default:
520 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
521 }
522#endif
523}
524
525static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
526 size_t *olen, int point_format,
527 unsigned char *buf, size_t blen,
528 int (*f_rng)(void *,
529 unsigned char *,
530 size_t),
531 void *p_rng,
532 int restart_enabled )
533{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200534 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100535#if defined(MBEDTLS_ECP_RESTARTABLE)
536 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
537#endif
538
539 if( ctx->grp.pbits == 0 )
540 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
541
542#if defined(MBEDTLS_ECP_RESTARTABLE)
543 if( restart_enabled )
544 rs_ctx = &ctx->rs;
545#else
546 (void) restart_enabled;
547#endif
548
549#if defined(MBEDTLS_ECP_RESTARTABLE)
550 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
551 f_rng, p_rng, rs_ctx ) ) != 0 )
552 return( ret );
553#else
554 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
555 f_rng, p_rng ) ) != 0 )
556 return( ret );
557#endif /* MBEDTLS_ECP_RESTARTABLE */
558
559 return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
560 buf, blen );
Jens Wiklander817466c2018-05-22 13:49:31 +0200561}
562
563/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100564 * Setup and export the client public value
Jens Wiklander817466c2018-05-22 13:49:31 +0200565 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100566int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
567 unsigned char *buf, size_t blen,
568 int (*f_rng)(void *, unsigned char *, size_t),
569 void *p_rng )
570{
571 int restart_enabled = 0;
572 ECDH_VALIDATE_RET( ctx != NULL );
573 ECDH_VALIDATE_RET( olen != NULL );
574 ECDH_VALIDATE_RET( buf != NULL );
575 ECDH_VALIDATE_RET( f_rng != NULL );
576
577#if defined(MBEDTLS_ECP_RESTARTABLE)
578 restart_enabled = ctx->restart_enabled;
579#endif
580
581#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
582 return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
583 f_rng, p_rng, restart_enabled ) );
584#else
585 switch( ctx->var )
586 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200587#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
588 case MBEDTLS_ECDH_VARIANT_EVEREST:
589 return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen,
590 buf, blen, f_rng, p_rng ) );
591#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100592 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
593 return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
594 ctx->point_format, buf, blen,
595 f_rng, p_rng,
596 restart_enabled ) );
597 default:
598 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
599 }
600#endif
601}
602
603static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
604 const unsigned char *buf, size_t blen )
Jens Wiklander817466c2018-05-22 13:49:31 +0200605{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200606 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200607 const unsigned char *p = buf;
608
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100609 if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
610 blen ) ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200611 return( ret );
612
613 if( (size_t)( p - buf ) != blen )
614 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
615
616 return( 0 );
617}
618
619/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100620 * Parse and import the client's public value
Jens Wiklander817466c2018-05-22 13:49:31 +0200621 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100622int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
623 const unsigned char *buf, size_t blen )
624{
625 ECDH_VALIDATE_RET( ctx != NULL );
626 ECDH_VALIDATE_RET( buf != NULL );
627
628#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
629 return( ecdh_read_public_internal( ctx, buf, blen ) );
630#else
631 switch( ctx->var )
632 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200633#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
634 case MBEDTLS_ECDH_VARIANT_EVEREST:
635 return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh,
636 buf, blen ) );
637#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100638 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
639 return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
640 buf, blen ) );
641 default:
642 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
643 }
644#endif
645}
646
647static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
648 size_t *olen, unsigned char *buf,
649 size_t blen,
650 int (*f_rng)(void *,
651 unsigned char *,
652 size_t),
653 void *p_rng,
654 int restart_enabled )
Jens Wiklander817466c2018-05-22 13:49:31 +0200655{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200656 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100657#if defined(MBEDTLS_ECP_RESTARTABLE)
658 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
659#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200660
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100661 if( ctx == NULL || ctx->grp.pbits == 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200662 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
663
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100664#if defined(MBEDTLS_ECP_RESTARTABLE)
665 if( restart_enabled )
666 rs_ctx = &ctx->rs;
667#else
668 (void) restart_enabled;
669#endif
670
671#if defined(MBEDTLS_ECP_RESTARTABLE)
672 if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
673 &ctx->d, f_rng, p_rng,
674 rs_ctx ) ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200675 {
676 return( ret );
677 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100678#else
679 if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
680 &ctx->d, f_rng, p_rng ) ) != 0 )
681 {
682 return( ret );
683 }
684#endif /* MBEDTLS_ECP_RESTARTABLE */
Jens Wiklander817466c2018-05-22 13:49:31 +0200685
686 if( mbedtls_mpi_size( &ctx->z ) > blen )
687 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
688
689 *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200690
691 if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
692 return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen );
693
Jens Wiklander817466c2018-05-22 13:49:31 +0200694 return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
695}
696
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100697/*
698 * Derive and export the shared secret
699 */
700int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
701 unsigned char *buf, size_t blen,
702 int (*f_rng)(void *, unsigned char *, size_t),
703 void *p_rng )
704{
705 int restart_enabled = 0;
706 ECDH_VALIDATE_RET( ctx != NULL );
707 ECDH_VALIDATE_RET( olen != NULL );
708 ECDH_VALIDATE_RET( buf != NULL );
709
710#if defined(MBEDTLS_ECP_RESTARTABLE)
711 restart_enabled = ctx->restart_enabled;
712#endif
713
714#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
715 return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
716 restart_enabled ) );
717#else
718 switch( ctx->var )
719 {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200720#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
721 case MBEDTLS_ECDH_VARIANT_EVEREST:
722 return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen,
723 buf, blen, f_rng, p_rng ) );
724#endif
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100725 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
726 return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
727 blen, f_rng, p_rng,
728 restart_enabled ) );
729 default:
730 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
731 }
732#endif
733}
734
Jens Wiklander817466c2018-05-22 13:49:31 +0200735#endif /* MBEDTLS_ECDH_C */