blob: 7eb52b0833b8d9d325541ac4ff47c3e60c83cfc6 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Diffie-Hellman-Merkle key exchange
3 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
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.
Paul Bakkerb96f1542010-07-18 20:36:00 +000024 *
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 * **********
Paul Bakker5121ce52009-01-03 21:22:43 +000045 */
46/*
Simon Butcherbdae02c2016-01-20 00:44:42 +000047 * The following sources were referenced in the design of this implementation
48 * of the Diffie-Hellman-Merkle algorithm:
Paul Bakker5121ce52009-01-03 21:22:43 +000049 *
Simon Butcherbdae02c2016-01-20 00:44:42 +000050 * [1] Handbook of Applied Cryptography - 1997, Chapter 12
51 * Menezes, van Oorschot and Vanstone
52 *
Paul Bakker5121ce52009-01-03 21:22:43 +000053 */
54
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000056#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020057#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020059#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000060
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020061#if defined(MBEDTLS_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000062
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000063#include "mbedtls/dhm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050064#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000065
Rich Evans00ab4702015-02-06 13:43:58 +000066#include <string.h>
67
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000069#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020070#endif
71
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000073#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020074#endif
75
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000077#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020078#else
79#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000080#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020082#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083#define mbedtls_free free
Paul Bakker40ce79f2013-09-15 17:43:54 +020084#endif
85
Reuven Levin1f35ca92017-12-07 10:09:32 +000086#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020087
Hanno Becker5c14ed62018-12-12 19:44:47 +000088#define DHM_VALIDATE_RET( cond ) \
89 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
90#define DHM_VALIDATE( cond ) \
91 MBEDTLS_INTERNAL_VALIDATE( cond )
92
Paul Bakker5121ce52009-01-03 21:22:43 +000093/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +000097 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000098 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +000099{
100 int ret, n;
101
102 if( end - *p < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
105 n = ( (*p)[0] << 8 ) | (*p)[1];
106 (*p) += 2;
107
108 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
112 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000113
114 (*p) += n;
115
116 return( 0 );
117}
118
119/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000120 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +0000121 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000122 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +0000123 *
Janos Follathaa325d72017-09-20 15:33:24 +0100124 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +0100125 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +0100126 *
Paul Bakker345a6fe2011-02-28 21:20:02 +0000127 * For more information on the attack, see:
128 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
129 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +0000130 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000132{
Gilles Peskine260be632021-03-31 22:56:43 +0200133 mbedtls_mpi U;
Janos Follathaa325d72017-09-20 15:33:24 +0100134 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000135
Gilles Peskine260be632021-03-31 22:56:43 +0200136 mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +0200137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000139
Gilles Peskine260be632021-03-31 22:56:43 +0200140 if( mbedtls_mpi_cmp_int( param, 2 ) < 0 ||
Janos Follathaa325d72017-09-20 15:33:24 +0100141 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000142 {
Janos Follathaa325d72017-09-20 15:33:24 +0100143 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000144 }
145
Paul Bakker3d8fb632014-04-17 12:42:41 +0200146cleanup:
Gilles Peskine260be632021-03-31 22:56:43 +0200147 mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000148 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000149}
150
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200151void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200152{
Hanno Becker5c14ed62018-12-12 19:44:47 +0000153 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200155}
156
Paul Bakkerc47840e2011-02-20 16:37:30 +0000157/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000158 * Parse the ServerKeyExchange parameters
159 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200160int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000161 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000162 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000163{
Paul Bakker13ed9ab2012-04-16 09:43:49 +0000164 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000165 DHM_VALIDATE_RET( ctx != NULL );
166 DHM_VALIDATE_RET( p != NULL && *p != NULL );
167 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000168
Paul Bakker5121ce52009-01-03 21:22:43 +0000169 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
170 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
171 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
172 return( ret );
173
Paul Bakker345a6fe2011-02-28 21:20:02 +0000174 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
175 return( ret );
176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000178
Paul Bakker5121ce52009-01-03 21:22:43 +0000179 return( 0 );
180}
181
Gilles Peskinec53560e2021-03-31 22:48:14 +0200182/*
183 * Pick a random R in the range [2, M) for blinding or key generation.
184 */
185static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
186 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
187{
188 int ret, count;
189
190 count = 0;
191 do
192 {
193 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
194
195 while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
196 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
197
198 if( count++ > 10 )
199 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
200 }
201 while( dhm_check_range( R, M ) != 0 );
202
203cleanup:
204 return( ret );
205}
206
Gilles Peskinee75bb632021-03-31 22:35:13 +0200207static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
208 int (*f_rng)(void *, unsigned char *, size_t),
209 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000210{
Gilles Peskinec53560e2021-03-31 22:48:14 +0200211 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000212
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
214 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Gilles Peskinec53560e2021-03-31 22:48:14 +0200215 if( x_size < 0 )
216 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000217
Gilles Peskinec53560e2021-03-31 22:48:14 +0200218 if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000219 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200220 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000221 }
Gilles Peskinec53560e2021-03-31 22:48:14 +0200222 else
223 {
224 /* Generate X as large as possible ( <= P - 2 ) */
225 ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
226 if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
227 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
228 if( ret != 0 )
229 return( ret );
230 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000231
Paul Bakkerff7fe672010-07-18 09:45:05 +0000232 /*
233 * Calculate GX = G^X mod P
234 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200235 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000236 &ctx->P , &ctx->RP ) );
237
Paul Bakker345a6fe2011-02-28 21:20:02 +0000238 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000239 return( ret );
240
Gilles Peskinee75bb632021-03-31 22:35:13 +0200241cleanup:
242 return( ret );
243}
244
245/*
246 * Setup and write the ServerKeyExchange parameters
247 */
248int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
249 unsigned char *output, size_t *olen,
250 int (*f_rng)(void *, unsigned char *, size_t),
251 void *p_rng )
252{
253 int ret;
254 size_t n1, n2, n3;
255 unsigned char *p;
256 DHM_VALIDATE_RET( ctx != NULL );
257 DHM_VALIDATE_RET( output != NULL );
258 DHM_VALIDATE_RET( olen != NULL );
259 DHM_VALIDATE_RET( f_rng != NULL );
260
261 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
262 if( ret != 0 )
263 goto cleanup;
264
Paul Bakker5121ce52009-01-03 21:22:43 +0000265 /*
266 * export P, G, GX
267 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100268#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100269 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100270 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
271 p + 2, \
272 ( n ) ) ); \
273 *p++ = (unsigned char)( ( n ) >> 8 ); \
274 *p++ = (unsigned char)( ( n ) ); \
275 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100276 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 n1 = mbedtls_mpi_size( &ctx->P );
279 n2 = mbedtls_mpi_size( &ctx->G );
280 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000281
282 p = output;
283 DHM_MPI_EXPORT( &ctx->P , n1 );
284 DHM_MPI_EXPORT( &ctx->G , n2 );
285 DHM_MPI_EXPORT( &ctx->GX, n3 );
286
Hanno Beckere71ad122017-09-28 10:32:25 +0100287 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000288
289 ctx->len = n1;
290
291cleanup:
Gilles Peskinee75bb632021-03-31 22:35:13 +0200292 if( ret != 0 && ret > -128 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Gilles Peskinee75bb632021-03-31 22:35:13 +0200294 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295}
296
297/*
Hanno Becker8880e752017-10-04 13:15:08 +0100298 * Set prime modulus and generator
299 */
300int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
301 const mbedtls_mpi *P,
302 const mbedtls_mpi *G )
303{
304 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000305 DHM_VALIDATE_RET( ctx != NULL );
306 DHM_VALIDATE_RET( P != NULL );
307 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100308
309 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
310 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
311 {
312 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
313 }
314
315 ctx->len = mbedtls_mpi_size( &ctx->P );
316 return( 0 );
317}
318
319/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000320 * Import the peer's public value G^Y
321 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000323 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000324{
325 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000326 DHM_VALIDATE_RET( ctx != NULL );
327 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000328
Hanno Becker5c14ed62018-12-12 19:44:47 +0000329 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200330 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000331
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
333 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000334
335 return( 0 );
336}
337
338/*
339 * Create own private value X and export G^X
340 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000342 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000343 int (*f_rng)(void *, unsigned char *, size_t),
344 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000345{
Gilles Peskinee75bb632021-03-31 22:35:13 +0200346 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000347 DHM_VALIDATE_RET( ctx != NULL );
348 DHM_VALIDATE_RET( output != NULL );
349 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
Hanno Becker5c14ed62018-12-12 19:44:47 +0000351 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200352 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000353
Gilles Peskinee75bb632021-03-31 22:35:13 +0200354 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
355 if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
356 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
357 if( ret != 0 )
358 goto cleanup;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000359
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000361
362cleanup:
Gilles Peskinee75bb632021-03-31 22:35:13 +0200363 if( ret != 0 && ret > -128 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200364 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000365
Gilles Peskinee75bb632021-03-31 22:35:13 +0200366 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000367}
368
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200369
370/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200371 * Use the blinding method and optimisation suggested in section 10 of:
372 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200373 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200374 * Berlin Heidelberg, 1996. p. 104-113.
375 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200377 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
378{
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200379 int ret;
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200380 mbedtls_mpi R;
381
382 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200383
384 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200385 * Don't use any blinding the first time a particular X is used,
386 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200387 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200388 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200389 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200390 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
391 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
392 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200393
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200394 return( 0 );
395 }
396
397 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200398 * Ok, we need blinding. Can we re-use existing values?
399 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200400 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200401 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200402 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200403 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
404 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
407 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200408
409 return( 0 );
410 }
411
412 /*
413 * We need to generate blinding values from scratch
414 */
415
Gilles Peskineb2fbda32021-03-31 22:50:57 +0200416 /* Vi = random( 2, P-2 ) */
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200417 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200418
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200419 /* Vf = Vi^-X mod P
420 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
421 * then elevate to the Xth power. */
422 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
423 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
424 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
425 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
426 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
427 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
428
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200430
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200431cleanup:
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200432 mbedtls_mpi_free( &R );
433
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200434 return( ret );
435}
436
437/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000438 * Derive and export the shared secret (G^Y)^X mod P
439 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100441 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200442 int (*f_rng)(void *, unsigned char *, size_t),
443 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000444{
445 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 mbedtls_mpi GYb;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000447 DHM_VALIDATE_RET( ctx != NULL );
448 DHM_VALIDATE_RET( output != NULL );
449 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200450
Hanno Becker5c14ed62018-12-12 19:44:47 +0000451 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
Paul Bakker345a6fe2011-02-28 21:20:02 +0000454 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000455 return( ret );
456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200458
459 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200460 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200461 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
463 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
464 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200465 }
466 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200468
469 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200470 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200471 &ctx->P, &ctx->RP ) );
472
473 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200474 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200475 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
477 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200478 }
479
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200480 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
484cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000486
487 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200488 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000489
490 return( 0 );
491}
492
493/*
494 * Free the components of a DHM key
495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000497{
Hanno Becker5c14ed62018-12-12 19:44:47 +0000498 if( ctx == NULL )
499 return;
500
irwir2239a862018-06-12 18:25:09 +0300501 mbedtls_mpi_free( &ctx->pX );
502 mbedtls_mpi_free( &ctx->Vf );
503 mbedtls_mpi_free( &ctx->Vi );
504 mbedtls_mpi_free( &ctx->RP );
505 mbedtls_mpi_free( &ctx->K );
506 mbedtls_mpi_free( &ctx->GY );
507 mbedtls_mpi_free( &ctx->GX );
508 mbedtls_mpi_free( &ctx->X );
509 mbedtls_mpi_free( &ctx->G );
510 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200511
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500512 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000513}
514
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200516/*
517 * Parse DHM parameters
518 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200520 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200521{
522 int ret;
523 size_t len;
524 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200525#if defined(MBEDTLS_PEM_PARSE_C)
526 mbedtls_pem_context pem;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000527#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200528
Hanno Becker5c14ed62018-12-12 19:44:47 +0000529 DHM_VALIDATE_RET( dhm != NULL );
530 DHM_VALIDATE_RET( dhmin != NULL );
531
532#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200534
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200535 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200536 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200537 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
538 else
539 ret = mbedtls_pem_read_buffer( &pem,
540 "-----BEGIN DH PARAMETERS-----",
541 "-----END DH PARAMETERS-----",
542 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200543
544 if( ret == 0 )
545 {
546 /*
547 * Was PEM encoded
548 */
549 dhminlen = pem.buflen;
550 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200551 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200552 goto exit;
553
554 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
555#else
556 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200558 end = p + dhminlen;
559
560 /*
561 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400562 * prime INTEGER, -- P
563 * generator INTEGER, -- g
564 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200565 * }
566 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
568 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200569 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200571 goto exit;
572 }
573
574 end = p + len;
575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
577 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200578 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200580 goto exit;
581 }
582
583 if( p != end )
584 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200585 /* This might be the optional privateValueLength.
586 * If so, we can cleanly discard it */
587 mbedtls_mpi rec;
588 mbedtls_mpi_init( &rec );
589 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
590 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400591 if ( ret != 0 )
592 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200593 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400594 goto exit;
595 }
596 if ( p != end )
597 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200598 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
599 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400600 goto exit;
601 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200602 }
603
604 ret = 0;
605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100607
Paul Bakker40ce79f2013-09-15 17:43:54 +0200608exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609#if defined(MBEDTLS_PEM_PARSE_C)
610 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200611#endif
612 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200614
615 return( ret );
616}
617
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200619/*
620 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200621 *
622 * The file is expected to contain either PEM or DER encoded data.
623 * A terminating null byte is always appended. It is included in the announced
624 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200625 */
626static int load_file( const char *path, unsigned char **buf, size_t *n )
627{
628 FILE *f;
629 long size;
630
631 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200632 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200633
634 fseek( f, 0, SEEK_END );
635 if( ( size = ftell( f ) ) == -1 )
636 {
637 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200639 }
640 fseek( f, 0, SEEK_SET );
641
642 *n = (size_t) size;
643
644 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200645 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200646 {
647 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200648 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200649 }
650
651 if( fread( *buf, 1, *n, f ) != *n )
652 {
653 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100654
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500655 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200659 }
660
661 fclose( f );
662
663 (*buf)[*n] = '\0';
664
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200665 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
666 ++*n;
667
Paul Bakker40ce79f2013-09-15 17:43:54 +0200668 return( 0 );
669}
670
671/*
672 * Load and parse DHM parameters
673 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200674int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200675{
676 int ret;
677 size_t n;
678 unsigned char *buf;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000679 DHM_VALIDATE_RET( dhm != NULL );
680 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200681
Paul Bakker66d5d072014-06-17 16:39:18 +0200682 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200683 return( ret );
684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200686
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500687 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200689
690 return( ret );
691}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692#endif /* MBEDTLS_FS_IO */
693#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000694#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200695
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000697
Hanno Becker7b34f0f2019-05-10 14:43:31 +0100698#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200699static const char mbedtls_test_dhm_params[] =
700"-----BEGIN DH PARAMETERS-----\r\n"
701"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
702"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
703"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
704"-----END DH PARAMETERS-----\r\n";
Hanno Becker7b34f0f2019-05-10 14:43:31 +0100705#else /* MBEDTLS_PEM_PARSE_C */
706static const char mbedtls_test_dhm_params[] = {
707 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
708 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
709 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
710 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
711 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
712 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
713 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
714 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
715 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
716 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
717 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
718 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
719#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200720
721static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200722
Paul Bakker5121ce52009-01-03 21:22:43 +0000723/*
724 * Checkup routine
725 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000727{
Paul Bakker40ce79f2013-09-15 17:43:54 +0200728 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200730
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200732
Paul Bakker40ce79f2013-09-15 17:43:54 +0200733 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200735
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200736 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
737 (const unsigned char *) mbedtls_test_dhm_params,
738 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200739 {
740 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200742
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200743 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200744 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200745 }
746
747 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200749
Paul Bakker8f870b02014-06-20 13:32:38 +0200750exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200752
Paul Bakker8f870b02014-06-20 13:32:38 +0200753 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000754}
755
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200756#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000757
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200758#endif /* MBEDTLS_DHM_C */