blob: 4624659bfecce1138449534425ab273fe5683993 [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{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 mbedtls_mpi L, U;
Janos Follathaa325d72017-09-20 15:33:24 +0100134 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 mbedtls_mpi_init( &L ); 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_lset( &L, 2 ) );
139 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000140
Janos Follathaa325d72017-09-20 15:33:24 +0100141 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
142 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000143 {
Janos Follathaa325d72017-09-20 15:33:24 +0100144 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000145 }
146
Paul Bakker3d8fb632014-04-17 12:42:41 +0200147cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000149 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000150}
151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200153{
Hanno Becker5c14ed62018-12-12 19:44:47 +0000154 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200156}
157
Paul Bakkerc47840e2011-02-20 16:37:30 +0000158/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000159 * Parse the ServerKeyExchange parameters
160 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000162 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000163 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000164{
Paul Bakker13ed9ab2012-04-16 09:43:49 +0000165 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000166 DHM_VALIDATE_RET( ctx != NULL );
167 DHM_VALIDATE_RET( p != NULL && *p != NULL );
168 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000169
Paul Bakker5121ce52009-01-03 21:22:43 +0000170 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
171 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
172 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
173 return( ret );
174
Paul Bakker345a6fe2011-02-28 21:20:02 +0000175 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
176 return( ret );
177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000179
Paul Bakker5121ce52009-01-03 21:22:43 +0000180 return( 0 );
181}
182
Gilles Peskinec53560e2021-03-31 22:48:14 +0200183/*
184 * Pick a random R in the range [2, M) for blinding or key generation.
185 */
186static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
187 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
188{
189 int ret, count;
190
191 count = 0;
192 do
193 {
194 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
195
196 while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
197 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
198
199 if( count++ > 10 )
200 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
201 }
202 while( dhm_check_range( R, M ) != 0 );
203
204cleanup:
205 return( ret );
206}
207
Gilles Peskinee75bb632021-03-31 22:35:13 +0200208static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
209 int (*f_rng)(void *, unsigned char *, size_t),
210 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000211{
Gilles Peskinec53560e2021-03-31 22:48:14 +0200212 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
215 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Gilles Peskinec53560e2021-03-31 22:48:14 +0200216 if( x_size < 0 )
217 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000218
Gilles Peskinec53560e2021-03-31 22:48:14 +0200219 if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000220 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200221 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000222 }
Gilles Peskinec53560e2021-03-31 22:48:14 +0200223 else
224 {
225 /* Generate X as large as possible ( <= P - 2 ) */
226 ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
227 if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
228 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
229 if( ret != 0 )
230 return( ret );
231 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000232
Paul Bakkerff7fe672010-07-18 09:45:05 +0000233 /*
234 * Calculate GX = G^X mod P
235 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000237 &ctx->P , &ctx->RP ) );
238
Paul Bakker345a6fe2011-02-28 21:20:02 +0000239 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000240 return( ret );
241
Gilles Peskinee75bb632021-03-31 22:35:13 +0200242cleanup:
243 return( ret );
244}
245
246/*
247 * Setup and write the ServerKeyExchange parameters
248 */
249int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
250 unsigned char *output, size_t *olen,
251 int (*f_rng)(void *, unsigned char *, size_t),
252 void *p_rng )
253{
254 int ret;
255 size_t n1, n2, n3;
256 unsigned char *p;
257 DHM_VALIDATE_RET( ctx != NULL );
258 DHM_VALIDATE_RET( output != NULL );
259 DHM_VALIDATE_RET( olen != NULL );
260 DHM_VALIDATE_RET( f_rng != NULL );
261
262 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
263 if( ret != 0 )
264 goto cleanup;
265
Paul Bakker5121ce52009-01-03 21:22:43 +0000266 /*
267 * export P, G, GX
268 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100269#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100270 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100271 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
272 p + 2, \
273 ( n ) ) ); \
274 *p++ = (unsigned char)( ( n ) >> 8 ); \
275 *p++ = (unsigned char)( ( n ) ); \
276 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100277 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000278
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279 n1 = mbedtls_mpi_size( &ctx->P );
280 n2 = mbedtls_mpi_size( &ctx->G );
281 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000282
283 p = output;
284 DHM_MPI_EXPORT( &ctx->P , n1 );
285 DHM_MPI_EXPORT( &ctx->G , n2 );
286 DHM_MPI_EXPORT( &ctx->GX, n3 );
287
Hanno Beckere71ad122017-09-28 10:32:25 +0100288 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000289
290 ctx->len = n1;
291
292cleanup:
Gilles Peskinee75bb632021-03-31 22:35:13 +0200293 if( ret != 0 && ret > -128 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Gilles Peskinee75bb632021-03-31 22:35:13 +0200295 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000296}
297
298/*
Hanno Becker8880e752017-10-04 13:15:08 +0100299 * Set prime modulus and generator
300 */
301int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
302 const mbedtls_mpi *P,
303 const mbedtls_mpi *G )
304{
305 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000306 DHM_VALIDATE_RET( ctx != NULL );
307 DHM_VALIDATE_RET( P != NULL );
308 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100309
310 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
311 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
312 {
313 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
314 }
315
316 ctx->len = mbedtls_mpi_size( &ctx->P );
317 return( 0 );
318}
319
320/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 * Import the peer's public value G^Y
322 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000324 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000325{
326 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000327 DHM_VALIDATE_RET( ctx != NULL );
328 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000329
Hanno Becker5c14ed62018-12-12 19:44:47 +0000330 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000332
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
334 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000335
336 return( 0 );
337}
338
339/*
340 * Create own private value X and export G^X
341 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000343 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000344 int (*f_rng)(void *, unsigned char *, size_t),
345 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000346{
Gilles Peskinee75bb632021-03-31 22:35:13 +0200347 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000348 DHM_VALIDATE_RET( ctx != NULL );
349 DHM_VALIDATE_RET( output != NULL );
350 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000351
Hanno Becker5c14ed62018-12-12 19:44:47 +0000352 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000354
Gilles Peskinee75bb632021-03-31 22:35:13 +0200355 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
356 if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
357 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
358 if( ret != 0 )
359 goto cleanup;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000362
363cleanup:
Gilles Peskinee75bb632021-03-31 22:35:13 +0200364 if( ret != 0 && ret > -128 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000366
Gilles Peskinee75bb632021-03-31 22:35:13 +0200367 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000368}
369
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200370
371/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200372 * Use the blinding method and optimisation suggested in section 10 of:
373 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200374 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200375 * Berlin Heidelberg, 1996. p. 104-113.
376 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200377static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200378 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
379{
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200380 int ret;
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200381 mbedtls_mpi R;
382
383 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200384
385 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200386 * Don't use any blinding the first time a particular X is used,
387 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200388 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200390 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
392 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
393 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200394
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200395 return( 0 );
396 }
397
398 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200399 * Ok, we need blinding. Can we re-use existing values?
400 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200401 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200403 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
405 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200406
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
408 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200409
410 return( 0 );
411 }
412
413 /*
414 * We need to generate blinding values from scratch
415 */
416
Gilles Peskineb2fbda32021-03-31 22:50:57 +0200417 /* Vi = random( 2, P-2 ) */
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200418 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200419
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200420 /* Vf = Vi^-X mod P
421 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
422 * then elevate to the Xth power. */
423 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
424 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
425 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
426 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
427 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
428 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
429
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 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 +0200431
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200432cleanup:
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200433 mbedtls_mpi_free( &R );
434
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200435 return( ret );
436}
437
438/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000439 * Derive and export the shared secret (G^Y)^X mod P
440 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100442 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200443 int (*f_rng)(void *, unsigned char *, size_t),
444 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000445{
446 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 mbedtls_mpi GYb;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000448 DHM_VALIDATE_RET( ctx != NULL );
449 DHM_VALIDATE_RET( output != NULL );
450 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200451
Hanno Becker5c14ed62018-12-12 19:44:47 +0000452 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
Paul Bakker345a6fe2011-02-28 21:20:02 +0000455 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000456 return( ret );
457
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200459
460 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200461 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200462 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
464 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
465 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200466 }
467 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200469
470 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200472 &ctx->P, &ctx->RP ) );
473
474 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200475 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200476 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
478 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200479 }
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000482
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000484
485cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000487
488 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000490
491 return( 0 );
492}
493
494/*
495 * Free the components of a DHM key
496 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000498{
Hanno Becker5c14ed62018-12-12 19:44:47 +0000499 if( ctx == NULL )
500 return;
501
irwir2239a862018-06-12 18:25:09 +0300502 mbedtls_mpi_free( &ctx->pX );
503 mbedtls_mpi_free( &ctx->Vf );
504 mbedtls_mpi_free( &ctx->Vi );
505 mbedtls_mpi_free( &ctx->RP );
506 mbedtls_mpi_free( &ctx->K );
507 mbedtls_mpi_free( &ctx->GY );
508 mbedtls_mpi_free( &ctx->GX );
509 mbedtls_mpi_free( &ctx->X );
510 mbedtls_mpi_free( &ctx->G );
511 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200512
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500513 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000514}
515
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200517/*
518 * Parse DHM parameters
519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200521 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200522{
523 int ret;
524 size_t len;
525 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526#if defined(MBEDTLS_PEM_PARSE_C)
527 mbedtls_pem_context pem;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000528#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200529
Hanno Becker5c14ed62018-12-12 19:44:47 +0000530 DHM_VALIDATE_RET( dhm != NULL );
531 DHM_VALIDATE_RET( dhmin != NULL );
532
533#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200535
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200536 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200537 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200538 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
539 else
540 ret = mbedtls_pem_read_buffer( &pem,
541 "-----BEGIN DH PARAMETERS-----",
542 "-----END DH PARAMETERS-----",
543 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200544
545 if( ret == 0 )
546 {
547 /*
548 * Was PEM encoded
549 */
550 dhminlen = pem.buflen;
551 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200553 goto exit;
554
555 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
556#else
557 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200559 end = p + dhminlen;
560
561 /*
562 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400563 * prime INTEGER, -- P
564 * generator INTEGER, -- g
565 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200566 * }
567 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
569 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200570 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200572 goto exit;
573 }
574
575 end = p + len;
576
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
578 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200579 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200581 goto exit;
582 }
583
584 if( p != end )
585 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200586 /* This might be the optional privateValueLength.
587 * If so, we can cleanly discard it */
588 mbedtls_mpi rec;
589 mbedtls_mpi_init( &rec );
590 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
591 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400592 if ( ret != 0 )
593 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200594 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400595 goto exit;
596 }
597 if ( p != end )
598 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200599 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
600 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400601 goto exit;
602 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200603 }
604
605 ret = 0;
606
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200607 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100608
Paul Bakker40ce79f2013-09-15 17:43:54 +0200609exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200610#if defined(MBEDTLS_PEM_PARSE_C)
611 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200612#endif
613 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200615
616 return( ret );
617}
618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200620/*
621 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200622 *
623 * The file is expected to contain either PEM or DER encoded data.
624 * A terminating null byte is always appended. It is included in the announced
625 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200626 */
627static int load_file( const char *path, unsigned char **buf, size_t *n )
628{
629 FILE *f;
630 long size;
631
632 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200634
635 fseek( f, 0, SEEK_END );
636 if( ( size = ftell( f ) ) == -1 )
637 {
638 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200640 }
641 fseek( f, 0, SEEK_SET );
642
643 *n = (size_t) size;
644
645 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200646 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200647 {
648 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200649 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200650 }
651
652 if( fread( *buf, 1, *n, f ) != *n )
653 {
654 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100655
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500656 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100658
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200660 }
661
662 fclose( f );
663
664 (*buf)[*n] = '\0';
665
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200666 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
667 ++*n;
668
Paul Bakker40ce79f2013-09-15 17:43:54 +0200669 return( 0 );
670}
671
672/*
673 * Load and parse DHM parameters
674 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200676{
677 int ret;
678 size_t n;
679 unsigned char *buf;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000680 DHM_VALIDATE_RET( dhm != NULL );
681 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200682
Paul Bakker66d5d072014-06-17 16:39:18 +0200683 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200684 return( ret );
685
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200687
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500688 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200690
691 return( ret );
692}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693#endif /* MBEDTLS_FS_IO */
694#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000695#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000698
Hanno Becker7b34f0f2019-05-10 14:43:31 +0100699#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200700static const char mbedtls_test_dhm_params[] =
701"-----BEGIN DH PARAMETERS-----\r\n"
702"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
703"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
704"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
705"-----END DH PARAMETERS-----\r\n";
Hanno Becker7b34f0f2019-05-10 14:43:31 +0100706#else /* MBEDTLS_PEM_PARSE_C */
707static const char mbedtls_test_dhm_params[] = {
708 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
709 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
710 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
711 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
712 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
713 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
714 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
715 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
716 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
717 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
718 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
719 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
720#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200721
722static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200723
Paul Bakker5121ce52009-01-03 21:22:43 +0000724/*
725 * Checkup routine
726 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000728{
Paul Bakker40ce79f2013-09-15 17:43:54 +0200729 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200731
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200732 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200733
Paul Bakker40ce79f2013-09-15 17:43:54 +0200734 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200736
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200737 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
738 (const unsigned char *) mbedtls_test_dhm_params,
739 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200740 {
741 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200742 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200743
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200744 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200745 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200746 }
747
748 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200749 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200750
Paul Bakker8f870b02014-06-20 13:32:38 +0200751exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200752 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200753
Paul Bakker8f870b02014-06-20 13:32:38 +0200754 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000755}
756
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000758
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200759#endif /* MBEDTLS_DHM_C */