blob: 4c97f8ef359cf767ca2803bbcd6e56c8190129bb [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úti4e9f7122020-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úti4e9f7122020-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"
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +010065
Rich Evans00ab4702015-02-06 13:43:58 +000066#include <string.h>
67
Ron Eldora84c1cb2017-10-10 19:04:27 +030068#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010069/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070 * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010071 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010073 int (*f_rng)(void *, unsigned char *, size_t),
74 void *p_rng )
75{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076 return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010077}
Ron Eldora84c1cb2017-10-10 19:04:27 +030078#endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010079
Ron Eldora84c1cb2017-10-10 19:04:27 +030080#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010081/*
82 * Compute shared secret (SEC1 3.3.1)
83 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
85 const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +020086 int (*f_rng)(void *, unsigned char *, size_t),
87 void *p_rng )
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010088{
89 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020090 mbedtls_ecp_point P;
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010091
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 mbedtls_ecp_point_init( &P );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010093
94 /*
95 * Make sure Q is a valid pubkey before using it
96 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020097 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +010098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100100
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101 if( mbedtls_ecp_is_zero( &P ) )
Paul Bakkerb548d772013-07-26 14:21:34 +0200102 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Paul Bakkerb548d772013-07-26 14:21:34 +0200104 goto cleanup;
105 }
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100106
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100108
109cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 mbedtls_ecp_point_free( &P );
Manuel Pégourié-Gonnard6545ca72013-01-26 16:05:22 +0100111
112 return( ret );
113}
Ron Eldora84c1cb2017-10-10 19:04:27 +0300114#endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
115
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100116/*
117 * Initialize context
118 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200119void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100120{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121 memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100122}
123
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100124/*
125 * Free context
126 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100128{
129 if( ctx == NULL )
130 return;
131
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200132 mbedtls_ecp_group_free( &ctx->grp );
133 mbedtls_ecp_point_free( &ctx->Q );
134 mbedtls_ecp_point_free( &ctx->Qp );
135 mbedtls_ecp_point_free( &ctx->Vi );
136 mbedtls_ecp_point_free( &ctx->Vf );
137 mbedtls_mpi_free( &ctx->d );
138 mbedtls_mpi_free( &ctx->z );
139 mbedtls_mpi_free( &ctx->_d );
Manuel Pégourié-Gonnard63533e42013-02-10 14:21:04 +0100140}
141
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100142/*
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100143 * Setup and write the ServerKeyExhange parameters (RFC 4492)
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100144 * struct {
145 * ECParameters curve_params;
146 * ECPoint public;
147 * } ServerECDHParams;
148 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200149int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100150 unsigned char *buf, size_t blen,
151 int (*f_rng)(void *, unsigned char *, size_t),
152 void *p_rng )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100153{
154 int ret;
155 size_t grp_len, pt_len;
156
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100157 if( ctx == NULL || ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100159
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100161 != 0 )
162 return( ret );
163
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200164 if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100165 != 0 )
166 return( ret );
167
168 buf += grp_len;
169 blen -= grp_len;
170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100172 &pt_len, buf, blen ) ) != 0 )
173 return( ret );
174
175 *olen = grp_len + pt_len;
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200176 return( 0 );
Manuel Pégourié-Gonnard13724762013-02-10 15:01:54 +0100177}
178
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100179/*
180 * Read the ServerKeyExhange parameters (RFC 4492)
181 * struct {
182 * ECParameters curve_params;
183 * ECPoint public;
184 * } ServerECDHParams;
185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100187 const unsigned char **buf, const unsigned char *end )
188{
189 int ret;
190
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 )
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100192 return( ret );
193
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200194 if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) )
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100195 != 0 )
196 return( ret );
197
Paul Bakkerd8bb8262014-06-17 14:06:49 +0200198 return( 0 );
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100199}
Manuel Pégourié-Gonnard0bad5c22013-01-26 15:30:46 +0100200
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100201/*
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100202 * Get parameters from a keypair
203 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
205 mbedtls_ecdh_side side )
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100206{
207 int ret;
208
Gilles Peskinef58078c2018-11-07 22:10:59 +0100209 if( ctx->grp.id == MBEDTLS_ECP_DP_NONE )
210 {
211 /* This is the first call to get_params(). Copy the group information
212 * into the context. */
213 if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
214 return( ret );
215 }
216 else
217 {
218 /* This is not the first call to get_params(). Check that the group
219 * is the same as the first time. */
220 if( ctx->grp.id != key->grp.id )
221 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
222 }
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100223
224 /* If it's not our key, just import the public part as Qp */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200225 if( side == MBEDTLS_ECDH_THEIRS )
226 return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100227
228 /* Our key: import public (as Q) and private parts */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 if( side != MBEDTLS_ECDH_OURS )
230 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100231
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200232 if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
233 ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
Manuel Pégourié-Gonnardcdff3cf2013-12-12 09:55:52 +0100234 return( ret );
235
236 return( 0 );
237}
238
239/*
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100240 * Setup and export the client public value
241 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100243 unsigned char *buf, size_t blen,
244 int (*f_rng)(void *, unsigned char *, size_t),
245 void *p_rng )
246{
247 int ret;
248
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100249 if( ctx == NULL || ctx->grp.pbits == 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200250 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100251
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200252 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100253 != 0 )
254 return( ret );
255
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200256 return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100257 olen, buf, blen );
258}
259
260/*
261 * Parse and import the client's public value
262 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100264 const unsigned char *buf, size_t blen )
265{
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100266 int ret;
267 const unsigned char *p = buf;
268
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100269 if( ctx == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100271
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 )
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100273 return( ret );
274
275 if( (size_t)( p - buf ) != blen )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnard969ccc62014-03-26 19:53:25 +0100277
278 return( 0 );
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100279}
280
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100281/*
282 * Derive and export the shared secret
283 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200284int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200285 unsigned char *buf, size_t blen,
286 int (*f_rng)(void *, unsigned char *, size_t),
287 void *p_rng )
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100288{
289 int ret;
290
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100291 if( ctx == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Manuel Pégourié-Gonnardf35b7392013-02-11 22:12:39 +0100293
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200295 f_rng, p_rng ) ) != 0 )
296 {
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100297 return( ret );
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200298 }
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100299
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200300 if( mbedtls_mpi_size( &ctx->z ) > blen )
301 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
Paul Bakker41c83d32013-03-20 14:39:14 +0100302
Manuel Pégourié-Gonnard0a56c2c2014-01-17 21:24:04 +0100303 *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304 return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100305}
306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307#endif /* MBEDTLS_ECDH_C */