blob: 5ef205f36ddbe00a11528b5cd44feeb9b253305c [file] [log] [blame]
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +01001/*
2 * Elliptic curve Diffie-Hellman
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
45 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000046 * This file is part of mbed TLS (https://tls.mbed.org)
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010047 */
48
49/*
50 * References:
51 *
52 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +010053 * RFC 4492
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010054 */
55
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000057#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020058#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020060#endif
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010061
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020062#if defined(MBEDTLS_ECDH_C)
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010063
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000064#include "mbedtls/ecdh.h"
Hanno Becker91796d72018-12-17 18:10:51 +000065#include "mbedtls/platform_util.h"
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010066
Rich Evans00ab4702015-02-06 13:43:58 +000067#include <string.h>
68
Hanno Becker91796d72018-12-17 18:10:51 +000069/* Parameter validation macros based on platform_util.h */
70#define ECDH_VALIDATE_RET( cond ) \
71 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
72#define ECDH_VALIDATE( cond ) \
73 MBEDTLS_INTERNAL_VALIDATE( cond )
74
Janos Follath5a3e1bf2018-08-13 15:54:22 +010075#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
76typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
77#endif
78
Gilles Peskine05fcf4f2019-02-22 12:31:25 +010079static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
80 const mbedtls_ecdh_context *ctx )
81{
82#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
83 return( ctx->grp.id );
84#else
85 return( ctx->grp_id );
86#endif
87}
88
Ron Eldora84c1cb2017-10-10 19:04:27 +030089#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010090/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020091 * Generate public key (restartable version)
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020092 *
93 * Note: this internal function relies on its caller preserving the value of
Manuel Pégourié-Gonnardca29fdf2018-10-22 09:56:53 +020094 * the output parameter 'd' across continuation calls. This would not be
Manuel Pégourié-Gonnardc0edc962018-10-16 10:38:19 +020095 * acceptable for a public function but is OK here as we control call sites.
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +020096 */
97static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
98 mbedtls_mpi *d, mbedtls_ecp_point *Q,
99 int (*f_rng)(void *, unsigned char *, size_t),
100 void *p_rng,
101 mbedtls_ecp_restart_ctx *rs_ctx )
102{
103 int ret;
104
105 /* If multiplication is in progress, we already generated a privkey */
106#if defined(MBEDTLS_ECP_RESTARTABLE)
107 if( rs_ctx == NULL || rs_ctx->rsm == NULL )
108#endif
109 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
110
111 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
112 f_rng, p_rng, rs_ctx ) );
113
114cleanup:
115 return( ret );
116}
117
118/*
119 * Generate public key
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100120 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100122 int (*f_rng)(void *, unsigned char *, size_t),
123 void *p_rng )
124{
Hanno Becker91796d72018-12-17 18:10:51 +0000125 ECDH_VALIDATE_RET( grp != NULL );
126 ECDH_VALIDATE_RET( d != NULL );
127 ECDH_VALIDATE_RET( Q != NULL );
128 ECDH_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200129 return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100130}
Ron Eldor936d2842018-11-01 13:05:52 +0200131#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100132
Ron Eldora84c1cb2017-10-10 19:04:27 +0300133#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100134/*
135 * Compute shared secret (SEC1 3.3.1)
136 */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200137static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
138 mbedtls_mpi *z,
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200140 int (*f_rng)(void *, unsigned char *, size_t),
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200141 void *p_rng,
142 mbedtls_ecp_restart_ctx *rs_ctx )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100143{
144 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200145 mbedtls_ecp_point P;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100146
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 mbedtls_ecp_point_init( &P );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100148
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200149 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
150 f_rng, p_rng, rs_ctx ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 if( mbedtls_ecp_is_zero( &P ) )
Paul Bakkerb548d772013-07-26 14:21:34 +0200153 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakkerb548d772013-07-26 14:21:34 +0200155 goto cleanup;
156 }
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100157
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100159
160cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 mbedtls_ecp_point_free( &P );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100162
163 return( ret );
164}
165
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100166/*
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200167 * Compute shared secret (SEC1 3.3.1)
168 */
169int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
170 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
171 int (*f_rng)(void *, unsigned char *, size_t),
172 void *p_rng )
173{
Hanno Becker91796d72018-12-17 18:10:51 +0000174 ECDH_VALIDATE_RET( grp != NULL );
175 ECDH_VALIDATE_RET( Q != NULL );
176 ECDH_VALIDATE_RET( d != NULL );
177 ECDH_VALIDATE_RET( z != NULL );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200178 return( ecdh_compute_shared_restartable( grp, z, Q, d,
179 f_rng, p_rng, NULL ) );
180}
Ron Eldor936d2842018-11-01 13:05:52 +0200181#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200182
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100183static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100184{
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200185 mbedtls_ecp_group_init( &ctx->grp );
186 mbedtls_mpi_init( &ctx->d );
187 mbedtls_ecp_point_init( &ctx->Q );
188 mbedtls_ecp_point_init( &ctx->Qp );
189 mbedtls_mpi_init( &ctx->z );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200190
191#if defined(MBEDTLS_ECP_RESTARTABLE)
192 mbedtls_ecp_restart_init( &ctx->rs );
193#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100194}
195
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100196/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100197 * Initialize context
Janos Follathf61e4862018-10-30 11:53:25 +0000198 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100199void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
200{
Hanno Becker91796d72018-12-17 18:10:51 +0000201 ECDH_VALIDATE( ctx != NULL );
202
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100203#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
204 ecdh_init_internal( ctx );
205 mbedtls_ecp_point_init( &ctx->Vi );
206 mbedtls_ecp_point_init( &ctx->Vf );
207 mbedtls_mpi_init( &ctx->_d );
208#else
209 memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
210
211 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
212#endif
213 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
214#if defined(MBEDTLS_ECP_RESTARTABLE)
215 ctx->restart_enabled = 0;
216#endif
217}
218
219static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
220 mbedtls_ecp_group_id grp_id )
Janos Follathf61e4862018-10-30 11:53:25 +0000221{
222 int ret;
223
224 ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
225 if( ret != 0 )
226 {
Janos Follathf61e4862018-10-30 11:53:25 +0000227 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
228 }
229
230 return( 0 );
231}
232
233/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100234 * Setup context
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100235 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100236int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100237{
Hanno Becker91796d72018-12-17 18:10:51 +0000238 ECDH_VALIDATE_RET( ctx != NULL );
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100239
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100240#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
241 return( ecdh_setup_internal( ctx, grp_id ) );
242#else
243 switch( grp_id )
244 {
245 default:
246 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
247 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
248 ctx->grp_id = grp_id;
249 ecdh_init_internal( &ctx->ctx.mbed_ecdh );
250 return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
251 }
252#endif
253}
254
255static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
256{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 mbedtls_ecp_group_free( &ctx->grp );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200258 mbedtls_mpi_free( &ctx->d );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200259 mbedtls_ecp_point_free( &ctx->Q );
260 mbedtls_ecp_point_free( &ctx->Qp );
Manuel Pégourié-Gonnard5bd38b12017-08-23 16:55:59 +0200261 mbedtls_mpi_free( &ctx->z );
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200262
263#if defined(MBEDTLS_ECP_RESTARTABLE)
264 mbedtls_ecp_restart_free( &ctx->rs );
265#endif
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100266}
267
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200268#if defined(MBEDTLS_ECP_RESTARTABLE)
269/*
270 * Enable restartable operations for context
271 */
272void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
273{
Hanno Beckera7634e82018-12-18 18:45:00 +0000274 ECDH_VALIDATE( ctx != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100275
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200276 ctx->restart_enabled = 1;
277}
278#endif
279
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100280/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100281 * Free context
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100282 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100283void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
284{
285 if( ctx == NULL )
286 return;
287
288#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
289 mbedtls_ecp_point_free( &ctx->Vi );
290 mbedtls_ecp_point_free( &ctx->Vf );
291 mbedtls_mpi_free( &ctx->_d );
292 ecdh_free_internal( ctx );
293#else
294 switch( ctx->var )
295 {
296 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
297 ecdh_free_internal( &ctx->ctx.mbed_ecdh );
298 break;
299 default:
300 break;
301 }
302
303 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
304 ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
305 ctx->grp_id = MBEDTLS_ECP_DP_NONE;
306#endif
307}
308
309static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
310 size_t *olen, int point_format,
311 unsigned char *buf, size_t blen,
312 int (*f_rng)(void *,
313 unsigned char *,
314 size_t),
315 void *p_rng,
316 int restart_enabled )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100317{
318 int ret;
319 size_t grp_len, pt_len;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200320#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200321 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200322#endif
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100323
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100324 if( ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200325 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100326
Ron Eldor19779c42018-11-05 16:58:13 +0200327#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100328 if( restart_enabled )
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200329 rs_ctx = &ctx->rs;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100330#else
331 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200332#endif
333
Ron Eldor8493f802018-11-01 11:32:15 +0200334
Ron Eldor2981d8f2018-11-05 18:07:10 +0200335#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200336 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +0200337 f_rng, p_rng, rs_ctx ) ) != 0 )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100338 return( ret );
Ron Eldor2981d8f2018-11-05 18:07:10 +0200339#else
340 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
341 f_rng, p_rng ) ) != 0 )
342 return( ret );
343#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100344
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100345 if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
346 blen ) ) != 0 )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100347 return( ret );
348
349 buf += grp_len;
350 blen -= grp_len;
351
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100352 if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
Manuel Pégourié-Gonnardee68cff2018-10-15 15:27:49 +0200353 &pt_len, buf, blen ) ) != 0 )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100354 return( ret );
355
356 *olen = grp_len + pt_len;
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200357 return( 0 );
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100358}
359
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100360/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100361 * Setup and write the ServerKeyExhange parameters (RFC 4492)
362 * struct {
363 * ECParameters curve_params;
364 * ECPoint public;
365 * } ServerECDHParams;
366 */
367int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
368 unsigned char *buf, size_t blen,
369 int (*f_rng)(void *, unsigned char *, size_t),
370 void *p_rng )
371{
372 int restart_enabled = 0;
Hanno Becker91796d72018-12-17 18:10:51 +0000373 ECDH_VALIDATE_RET( ctx != NULL );
374 ECDH_VALIDATE_RET( olen != NULL );
375 ECDH_VALIDATE_RET( buf != NULL );
376 ECDH_VALIDATE_RET( f_rng != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100377
378#if defined(MBEDTLS_ECP_RESTARTABLE)
379 restart_enabled = ctx->restart_enabled;
380#else
381 (void) restart_enabled;
382#endif
383
384#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
385 return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
386 f_rng, p_rng, restart_enabled ) );
387#else
388 switch( ctx->var )
389 {
390 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
391 return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
392 ctx->point_format, buf, blen,
393 f_rng, p_rng,
394 restart_enabled ) );
395 default:
396 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
397 }
398#endif
399}
400
401static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
402 const unsigned char **buf,
403 const unsigned char *end )
404{
405 return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
406 end - *buf ) );
407}
408
409/*
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100410 * Read the ServerKeyExhange parameters (RFC 4492)
411 * struct {
412 * ECParameters curve_params;
413 * ECPoint public;
414 * } ServerECDHParams;
415 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100417 const unsigned char **buf,
418 const unsigned char *end )
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100419{
420 int ret;
Janos Follathf61e4862018-10-30 11:53:25 +0000421 mbedtls_ecp_group_id grp_id;
Hanno Becker91796d72018-12-17 18:10:51 +0000422 ECDH_VALIDATE_RET( ctx != NULL );
423 ECDH_VALIDATE_RET( buf != NULL );
424 ECDH_VALIDATE_RET( *buf != NULL );
425 ECDH_VALIDATE_RET( end != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100426
Janos Follathf61e4862018-10-30 11:53:25 +0000427 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
428 != 0 )
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100429 return( ret );
430
Janos Follathf61e4862018-10-30 11:53:25 +0000431 if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
432 return( ret );
433
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100434#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
435 return( ecdh_read_params_internal( ctx, buf, end ) );
436#else
437 switch( ctx->var )
438 {
439 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{
452 int ret;
453
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{
476 int ret;
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 Peskine05fcf4f2019-02-22 12:31:25 +0100482 if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
Gilles Peskineb47045a2018-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 Peskine05fcf4f2019-02-22 12:31:25 +0100494 if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id )
Gilles Peskineb47045a2018-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 {
503 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
504 return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
505 key, side ) );
506 default:
507 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
508 }
509#endif
510}
511
512static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
513 size_t *olen, int point_format,
514 unsigned char *buf, size_t blen,
515 int (*f_rng)(void *,
516 unsigned char *,
517 size_t),
518 void *p_rng,
519 int restart_enabled )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100520{
521 int ret;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200522#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200523 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200524#endif
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100525
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100526 if( ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100528
Ron Eldorb430d9f2018-11-05 17:18:29 +0200529#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100530 if( restart_enabled )
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200531 rs_ctx = &ctx->rs;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100532#else
533 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200534#endif
535
Ron Eldor2981d8f2018-11-05 18:07:10 +0200536#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200537 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100538 f_rng, p_rng, rs_ctx ) ) != 0 )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100539 return( ret );
Ron Eldor2981d8f2018-11-05 18:07:10 +0200540#else
541 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
542 f_rng, p_rng ) ) != 0 )
543 return( ret );
544#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100545
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100546 return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
547 buf, blen );
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100548}
549
550/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100551 * Setup and export the client public value
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100552 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100553int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
554 unsigned char *buf, size_t blen,
555 int (*f_rng)(void *, unsigned char *, size_t),
556 void *p_rng )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100557{
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100558 int restart_enabled = 0;
Hanno Becker91796d72018-12-17 18:10:51 +0000559 ECDH_VALIDATE_RET( ctx != NULL );
560 ECDH_VALIDATE_RET( olen != NULL );
561 ECDH_VALIDATE_RET( buf != NULL );
Hanno Beckerc81cfec2018-12-18 23:32:42 +0000562 ECDH_VALIDATE_RET( f_rng != NULL );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100563
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100564#if defined(MBEDTLS_ECP_RESTARTABLE)
565 restart_enabled = ctx->restart_enabled;
566#endif
567
568#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
569 return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
570 f_rng, p_rng, restart_enabled ) );
571#else
572 switch( ctx->var )
573 {
574 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
575 return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
576 ctx->point_format, buf, blen,
577 f_rng, p_rng,
578 restart_enabled ) );
579 default:
580 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
581 }
582#endif
583}
584
585static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
586 const unsigned char *buf, size_t blen )
587{
588 int ret;
589 const unsigned char *p = buf;
590
591 if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
592 blen ) ) != 0 )
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100593 return( ret );
594
595 if( (size_t)( p - buf ) != blen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100597
598 return( 0 );
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100599}
600
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100601/*
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100602 * Parse and import the client's public value
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100603 */
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100604int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
605 const unsigned char *buf, size_t blen )
606{
Hanno Becker91796d72018-12-17 18:10:51 +0000607 ECDH_VALIDATE_RET( ctx != NULL );
608 ECDH_VALIDATE_RET( buf != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100609
610#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
611 return( ecdh_read_public_internal( ctx, buf, blen ) );
612#else
613 switch( ctx->var )
614 {
615 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
616 return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
617 buf, blen ) );
618 default:
619 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
620 }
621#endif
622}
623
624static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
625 size_t *olen, unsigned char *buf,
626 size_t blen,
627 int (*f_rng)(void *,
628 unsigned char *,
629 size_t),
630 void *p_rng,
631 int restart_enabled )
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100632{
633 int ret;
Ron Eldor2981d8f2018-11-05 18:07:10 +0200634#if defined(MBEDTLS_ECP_RESTARTABLE)
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200635 mbedtls_ecp_restart_ctx *rs_ctx = NULL;
Ron Eldor936d2842018-11-01 13:05:52 +0200636#endif
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100637
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200638 if( ctx == NULL || ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100640
Ron Eldorb430d9f2018-11-05 17:18:29 +0200641#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100642 if( restart_enabled )
Manuel Pégourié-Gonnard23e41622017-05-18 12:35:37 +0200643 rs_ctx = &ctx->rs;
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100644#else
645 (void) restart_enabled;
Manuel Pégourié-Gonnard66ba48a2017-04-27 11:38:26 +0200646#endif
647
Ron Eldor2981d8f2018-11-05 18:07:10 +0200648#if defined(MBEDTLS_ECP_RESTARTABLE)
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100649 if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
650 &ctx->d, f_rng, p_rng,
651 rs_ctx ) ) != 0 )
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200652 {
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100653 return( ret );
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200654 }
Ron Eldor2981d8f2018-11-05 18:07:10 +0200655#else
656 if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
657 &ctx->d, f_rng, p_rng ) ) != 0 )
658 {
659 return( ret );
660 }
661#endif /* MBEDTLS_ECP_RESTARTABLE */
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100662
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663 if( mbedtls_mpi_size( &ctx->z ) > blen )
664 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Paul Bakker41c83d32013-03-20 14:39:14 +0100665
Manuel Pégourié-Gonnard0a56c2c2014-01-17 21:24:04 +0100666 *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667 return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100668}
669
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100670/*
671 * Derive and export the shared secret
672 */
673int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
674 unsigned char *buf, size_t blen,
675 int (*f_rng)(void *, unsigned char *, size_t),
676 void *p_rng )
677{
678 int restart_enabled = 0;
Hanno Becker91796d72018-12-17 18:10:51 +0000679 ECDH_VALIDATE_RET( ctx != NULL );
680 ECDH_VALIDATE_RET( olen != NULL );
681 ECDH_VALIDATE_RET( buf != NULL );
Janos Follath5a3e1bf2018-08-13 15:54:22 +0100682
683#if defined(MBEDTLS_ECP_RESTARTABLE)
684 restart_enabled = ctx->restart_enabled;
685#endif
686
687#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
688 return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
689 restart_enabled ) );
690#else
691 switch( ctx->var )
692 {
693 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
694 return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
695 blen, f_rng, p_rng,
696 restart_enabled ) );
697 default:
698 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
699 }
700#endif
701}
702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703#endif /* MBEDTLS_ECDH_C */