blob: d652cf0ac97825a98b0f1b4d953552294c778d76 [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
183/*
184 * Setup and write the ServerKeyExchange parameters
185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000187 unsigned char *output, size_t *olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000188 int (*f_rng)(void *, unsigned char *, size_t),
189 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000190{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000191 int ret, count = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000192 size_t n1, n2, n3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000193 unsigned char *p;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000194 DHM_VALIDATE_RET( ctx != NULL );
195 DHM_VALIDATE_RET( output != NULL );
196 DHM_VALIDATE_RET( olen != NULL );
197 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
200 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000201
Paul Bakker5121ce52009-01-03 21:22:43 +0000202 /*
Paul Bakkerff7fe672010-07-18 09:45:05 +0000203 * Generate X as large as possible ( < P )
Paul Bakker5121ce52009-01-03 21:22:43 +0000204 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000205 do
206 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200207 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
210 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000211
212 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000214 }
215 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000216
Paul Bakkerff7fe672010-07-18 09:45:05 +0000217 /*
218 * Calculate GX = G^X mod P
219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000221 &ctx->P , &ctx->RP ) );
222
Paul Bakker345a6fe2011-02-28 21:20:02 +0000223 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000224 return( ret );
225
Paul Bakker5121ce52009-01-03 21:22:43 +0000226 /*
227 * export P, G, GX
228 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100229#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100230 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100231 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
232 p + 2, \
233 ( n ) ) ); \
234 *p++ = (unsigned char)( ( n ) >> 8 ); \
235 *p++ = (unsigned char)( ( n ) ); \
236 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100237 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 n1 = mbedtls_mpi_size( &ctx->P );
240 n2 = mbedtls_mpi_size( &ctx->G );
241 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242
243 p = output;
244 DHM_MPI_EXPORT( &ctx->P , n1 );
245 DHM_MPI_EXPORT( &ctx->G , n2 );
246 DHM_MPI_EXPORT( &ctx->GX, n3 );
247
Hanno Beckere71ad122017-09-28 10:32:25 +0100248 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000249
250 ctx->len = n1;
251
252cleanup:
253
254 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000256
257 return( 0 );
258}
259
260/*
Hanno Becker8880e752017-10-04 13:15:08 +0100261 * Set prime modulus and generator
262 */
263int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
264 const mbedtls_mpi *P,
265 const mbedtls_mpi *G )
266{
267 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000268 DHM_VALIDATE_RET( ctx != NULL );
269 DHM_VALIDATE_RET( P != NULL );
270 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100271
272 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
273 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
274 {
275 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
276 }
277
278 ctx->len = mbedtls_mpi_size( &ctx->P );
279 return( 0 );
280}
281
282/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000283 * Import the peer's public value G^Y
284 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000286 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000287{
288 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000289 DHM_VALIDATE_RET( ctx != NULL );
290 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000291
Hanno Becker5c14ed62018-12-12 19:44:47 +0000292 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
296 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000297
298 return( 0 );
299}
300
301/*
302 * Create own private value X and export G^X
303 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000305 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000306 int (*f_rng)(void *, unsigned char *, size_t),
307 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000308{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000309 int ret, count = 0;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000310 DHM_VALIDATE_RET( ctx != NULL );
311 DHM_VALIDATE_RET( output != NULL );
312 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000313
Hanno Becker5c14ed62018-12-12 19:44:47 +0000314 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
318 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000319
Paul Bakker5121ce52009-01-03 21:22:43 +0000320 /*
321 * generate X and calculate GX = G^X mod P
322 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000323 do
324 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200325 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
328 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000329
330 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000332 }
333 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000336 &ctx->P , &ctx->RP ) );
337
Paul Bakker345a6fe2011-02-28 21:20:02 +0000338 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
339 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000342
343cleanup:
344
345 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000347
348 return( 0 );
349}
350
351/*
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200352 * Pick a random R in the range [2, M) for blinding purposes
353 */
354static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
355 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
356{
357 int ret, count;
358
359 count = 0;
360 do
361 {
362 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
363
364 while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
365 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
366
367 if( count++ > 10 )
368 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
369 }
370 while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
371
372cleanup:
373 return( ret );
374}
375
376
377/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200378 * Use the blinding method and optimisation suggested in section 10 of:
379 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200380 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200381 * Berlin Heidelberg, 1996. p. 104-113.
382 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200384 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
385{
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200386 int ret;
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200387 mbedtls_mpi R;
388
389 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200390
391 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200392 * Don't use any blinding the first time a particular X is used,
393 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200394 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200396 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
398 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
399 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200400
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200401 return( 0 );
402 }
403
404 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200405 * Ok, we need blinding. Can we re-use existing values?
406 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200407 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200409 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
411 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200412
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
414 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200415
416 return( 0 );
417 }
418
419 /*
420 * We need to generate blinding values from scratch
421 */
422
423 /* Vi = random( 2, P-1 ) */
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200424 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200425
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200426 /* Vf = Vi^-X mod P
427 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
428 * then elevate to the Xth power. */
429 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
430 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
431 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
432 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
433 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
434 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 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 +0200437
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200438cleanup:
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200439 mbedtls_mpi_free( &R );
440
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200441 return( ret );
442}
443
444/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000445 * Derive and export the shared secret (G^Y)^X mod P
446 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100448 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200449 int (*f_rng)(void *, unsigned char *, size_t),
450 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000451{
452 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 mbedtls_mpi GYb;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000454 DHM_VALIDATE_RET( ctx != NULL );
455 DHM_VALIDATE_RET( output != NULL );
456 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200457
Hanno Becker5c14ed62018-12-12 19:44:47 +0000458 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
Paul Bakker345a6fe2011-02-28 21:20:02 +0000461 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000462 return( ret );
463
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200465
466 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200467 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200468 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
470 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
471 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200472 }
473 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200475
476 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200478 &ctx->P, &ctx->RP ) );
479
480 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200481 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200482 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200483 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
484 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200485 }
486
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000490
491cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000493
494 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000496
497 return( 0 );
498}
499
500/*
501 * Free the components of a DHM key
502 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000504{
Hanno Becker5c14ed62018-12-12 19:44:47 +0000505 if( ctx == NULL )
506 return;
507
irwir2239a862018-06-12 18:25:09 +0300508 mbedtls_mpi_free( &ctx->pX );
509 mbedtls_mpi_free( &ctx->Vf );
510 mbedtls_mpi_free( &ctx->Vi );
511 mbedtls_mpi_free( &ctx->RP );
512 mbedtls_mpi_free( &ctx->K );
513 mbedtls_mpi_free( &ctx->GY );
514 mbedtls_mpi_free( &ctx->GX );
515 mbedtls_mpi_free( &ctx->X );
516 mbedtls_mpi_free( &ctx->G );
517 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200518
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500519 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000520}
521
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200523/*
524 * Parse DHM parameters
525 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200526int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200527 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200528{
529 int ret;
530 size_t len;
531 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200532#if defined(MBEDTLS_PEM_PARSE_C)
533 mbedtls_pem_context pem;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000534#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200535
Hanno Becker5c14ed62018-12-12 19:44:47 +0000536 DHM_VALIDATE_RET( dhm != NULL );
537 DHM_VALIDATE_RET( dhmin != NULL );
538
539#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200541
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200542 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200543 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200544 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
545 else
546 ret = mbedtls_pem_read_buffer( &pem,
547 "-----BEGIN DH PARAMETERS-----",
548 "-----END DH PARAMETERS-----",
549 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200550
551 if( ret == 0 )
552 {
553 /*
554 * Was PEM encoded
555 */
556 dhminlen = pem.buflen;
557 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200559 goto exit;
560
561 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
562#else
563 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200565 end = p + dhminlen;
566
567 /*
568 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400569 * prime INTEGER, -- P
570 * generator INTEGER, -- g
571 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200572 * }
573 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
575 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200576 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200578 goto exit;
579 }
580
581 end = p + len;
582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
584 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200585 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200587 goto exit;
588 }
589
590 if( p != end )
591 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200592 /* This might be the optional privateValueLength.
593 * If so, we can cleanly discard it */
594 mbedtls_mpi rec;
595 mbedtls_mpi_init( &rec );
596 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
597 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400598 if ( ret != 0 )
599 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200600 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400601 goto exit;
602 }
603 if ( p != end )
604 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200605 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
606 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400607 goto exit;
608 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200609 }
610
611 ret = 0;
612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100614
Paul Bakker40ce79f2013-09-15 17:43:54 +0200615exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200616#if defined(MBEDTLS_PEM_PARSE_C)
617 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200618#endif
619 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200621
622 return( ret );
623}
624
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200625#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200626/*
627 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200628 *
629 * The file is expected to contain either PEM or DER encoded data.
630 * A terminating null byte is always appended. It is included in the announced
631 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200632 */
633static int load_file( const char *path, unsigned char **buf, size_t *n )
634{
635 FILE *f;
636 long size;
637
638 if( ( f = fopen( path, "rb" ) ) == NULL )
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_END );
642 if( ( size = ftell( f ) ) == -1 )
643 {
644 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200646 }
647 fseek( f, 0, SEEK_SET );
648
649 *n = (size_t) size;
650
651 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200652 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200653 {
654 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200655 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200656 }
657
658 if( fread( *buf, 1, *n, f ) != *n )
659 {
660 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100661
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500662 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200663 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100664
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200666 }
667
668 fclose( f );
669
670 (*buf)[*n] = '\0';
671
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200672 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
673 ++*n;
674
Paul Bakker40ce79f2013-09-15 17:43:54 +0200675 return( 0 );
676}
677
678/*
679 * Load and parse DHM parameters
680 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200682{
683 int ret;
684 size_t n;
685 unsigned char *buf;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000686 DHM_VALIDATE_RET( dhm != NULL );
687 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200688
Paul Bakker66d5d072014-06-17 16:39:18 +0200689 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200690 return( ret );
691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200693
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500694 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200696
697 return( ret );
698}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699#endif /* MBEDTLS_FS_IO */
700#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000701#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200702
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000704
Hanno Becker7b34f0f2019-05-10 14:43:31 +0100705#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200706static const char mbedtls_test_dhm_params[] =
707"-----BEGIN DH PARAMETERS-----\r\n"
708"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
709"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
710"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
711"-----END DH PARAMETERS-----\r\n";
Hanno Becker7b34f0f2019-05-10 14:43:31 +0100712#else /* MBEDTLS_PEM_PARSE_C */
713static const char mbedtls_test_dhm_params[] = {
714 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
715 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
716 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
717 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
718 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
719 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
720 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
721 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
722 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
723 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
724 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
725 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
726#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200727
728static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200729
Paul Bakker5121ce52009-01-03 21:22:43 +0000730/*
731 * Checkup routine
732 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200733int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000734{
Paul Bakker40ce79f2013-09-15 17:43:54 +0200735 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200739
Paul Bakker40ce79f2013-09-15 17:43:54 +0200740 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200742
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200743 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
744 (const unsigned char *) mbedtls_test_dhm_params,
745 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200746 {
747 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200748 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200749
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200750 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200751 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200752 }
753
754 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200755 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200756
Paul Bakker8f870b02014-06-20 13:32:38 +0200757exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200758 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200759
Paul Bakker8f870b02014-06-20 13:32:38 +0200760 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000761}
762
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200763#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765#endif /* MBEDTLS_DHM_C */