blob: 5396debc6af2fa5bbfb0819f7645105c0c81a082 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Diffie-Hellman-Merkle key exchange
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
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 * **********
45 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000046 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000047 */
48/*
Simon Butcherbdae02c2016-01-20 00:44:42 +000049 * The following sources were referenced in the design of this implementation
50 * of the Diffie-Hellman-Merkle algorithm:
Paul Bakker5121ce52009-01-03 21:22:43 +000051 *
Simon Butcherbdae02c2016-01-20 00:44:42 +000052 * [1] Handbook of Applied Cryptography - 1997, Chapter 12
53 * Menezes, van Oorschot and Vanstone
54 *
Paul Bakker5121ce52009-01-03 21:22:43 +000055 */
56
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000058#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020059#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020060#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020061#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000062
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063#if defined(MBEDTLS_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000064
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000065#include "mbedtls/dhm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050066#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000067
Rich Evans00ab4702015-02-06 13:43:58 +000068#include <string.h>
69
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000071#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020072#endif
73
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000075#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020076#endif
77
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000079#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020080#else
81#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000082#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020084#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085#define mbedtls_free free
Paul Bakker40ce79f2013-09-15 17:43:54 +020086#endif
87
Reuven Levin1f35ca92017-12-07 10:09:32 +000088#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020089
Hanno Becker5c14ed62018-12-12 19:44:47 +000090#define DHM_VALIDATE_RET( cond ) \
91 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
92#define DHM_VALIDATE( cond ) \
93 MBEDTLS_INTERNAL_VALIDATE( cond )
94
Paul Bakker5121ce52009-01-03 21:22:43 +000095/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000097 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020098static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +000099 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000100 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000101{
102 int ret, n;
103
104 if( end - *p < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000106
107 n = ( (*p)[0] << 8 ) | (*p)[1];
108 (*p) += 2;
109
110 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
114 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000115
116 (*p) += n;
117
118 return( 0 );
119}
120
121/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000122 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +0000123 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000124 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +0000125 *
Janos Follathaa325d72017-09-20 15:33:24 +0100126 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +0100127 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +0100128 *
Paul Bakker345a6fe2011-02-28 21:20:02 +0000129 * For more information on the attack, see:
130 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
131 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +0000132 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000134{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200135 mbedtls_mpi L, U;
Janos Follathaa325d72017-09-20 15:33:24 +0100136 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +0200139
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
141 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000142
Janos Follathaa325d72017-09-20 15:33:24 +0100143 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
144 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000145 {
Janos Follathaa325d72017-09-20 15:33:24 +0100146 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000147 }
148
Paul Bakker3d8fb632014-04-17 12:42:41 +0200149cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000151 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000152}
153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200155{
Hanno Becker5c14ed62018-12-12 19:44:47 +0000156 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200157 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200158}
159
Paul Bakkerc47840e2011-02-20 16:37:30 +0000160/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000161 * Parse the ServerKeyExchange parameters
162 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000164 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000165 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000166{
Paul Bakker13ed9ab2012-04-16 09:43:49 +0000167 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000168 DHM_VALIDATE_RET( ctx != NULL );
169 DHM_VALIDATE_RET( p != NULL && *p != NULL );
170 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000171
Paul Bakker5121ce52009-01-03 21:22:43 +0000172 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
173 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
174 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
175 return( ret );
176
Paul Bakker345a6fe2011-02-28 21:20:02 +0000177 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
178 return( ret );
179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000181
Paul Bakker5121ce52009-01-03 21:22:43 +0000182 return( 0 );
183}
184
185/*
186 * Setup and write the ServerKeyExchange parameters
187 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000189 unsigned char *output, size_t *olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000190 int (*f_rng)(void *, unsigned char *, size_t),
191 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000192{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000193 int ret, count = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000194 size_t n1, n2, n3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000195 unsigned char *p;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000196 DHM_VALIDATE_RET( ctx != NULL );
197 DHM_VALIDATE_RET( output != NULL );
198 DHM_VALIDATE_RET( olen != NULL );
199 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000200
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
202 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000203
Paul Bakker5121ce52009-01-03 21:22:43 +0000204 /*
Paul Bakkerff7fe672010-07-18 09:45:05 +0000205 * Generate X as large as possible ( < P )
Paul Bakker5121ce52009-01-03 21:22:43 +0000206 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000207 do
208 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200209 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
212 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000213
214 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000216 }
217 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000218
Paul Bakkerff7fe672010-07-18 09:45:05 +0000219 /*
220 * Calculate GX = G^X mod P
221 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200222 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000223 &ctx->P , &ctx->RP ) );
224
Paul Bakker345a6fe2011-02-28 21:20:02 +0000225 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000226 return( ret );
227
Paul Bakker5121ce52009-01-03 21:22:43 +0000228 /*
229 * export P, G, GX
230 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100231#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100232 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100233 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
234 p + 2, \
235 ( n ) ) ); \
236 *p++ = (unsigned char)( ( n ) >> 8 ); \
237 *p++ = (unsigned char)( ( n ) ); \
238 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100239 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241 n1 = mbedtls_mpi_size( &ctx->P );
242 n2 = mbedtls_mpi_size( &ctx->G );
243 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000244
245 p = output;
246 DHM_MPI_EXPORT( &ctx->P , n1 );
247 DHM_MPI_EXPORT( &ctx->G , n2 );
248 DHM_MPI_EXPORT( &ctx->GX, n3 );
249
Hanno Beckere71ad122017-09-28 10:32:25 +0100250 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000251
252 ctx->len = n1;
253
254cleanup:
255
256 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000258
259 return( 0 );
260}
261
262/*
Hanno Becker8880e752017-10-04 13:15:08 +0100263 * Set prime modulus and generator
264 */
265int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
266 const mbedtls_mpi *P,
267 const mbedtls_mpi *G )
268{
269 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000270 DHM_VALIDATE_RET( ctx != NULL );
271 DHM_VALIDATE_RET( P != NULL );
272 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100273
274 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
275 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
276 {
277 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
278 }
279
280 ctx->len = mbedtls_mpi_size( &ctx->P );
281 return( 0 );
282}
283
284/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000285 * Import the peer's public value G^Y
286 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000288 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000289{
290 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000291 DHM_VALIDATE_RET( ctx != NULL );
292 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000293
Hanno Becker5c14ed62018-12-12 19:44:47 +0000294 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000296
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
298 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000299
300 return( 0 );
301}
302
303/*
304 * Create own private value X and export G^X
305 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000307 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000308 int (*f_rng)(void *, unsigned char *, size_t),
309 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000310{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000311 int ret, count = 0;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000312 DHM_VALIDATE_RET( ctx != NULL );
313 DHM_VALIDATE_RET( output != NULL );
314 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000315
Hanno Becker5c14ed62018-12-12 19:44:47 +0000316 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000318
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
320 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000321
Paul Bakker5121ce52009-01-03 21:22:43 +0000322 /*
323 * generate X and calculate GX = G^X mod P
324 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000325 do
326 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200327 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
330 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000331
332 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000334 }
335 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000336
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200337 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000338 &ctx->P , &ctx->RP ) );
339
Paul Bakker345a6fe2011-02-28 21:20:02 +0000340 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
341 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000344
345cleanup:
346
347 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000349
350 return( 0 );
351}
352
353/*
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200354 * Pick a random R in the range [2, M) for blinding purposes
355 */
356static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
357 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
358{
359 int ret, count;
360
361 count = 0;
362 do
363 {
364 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
365
366 while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
367 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
368
369 if( count++ > 10 )
370 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
371 }
372 while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
373
374cleanup:
375 return( ret );
376}
377
378
379/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200380 * Use the blinding method and optimisation suggested in section 10 of:
381 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200382 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200383 * Berlin Heidelberg, 1996. p. 104-113.
384 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200386 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
387{
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200388 int ret;
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200389 mbedtls_mpi R;
390
391 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200392
393 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200394 * Don't use any blinding the first time a particular X is used,
395 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200396 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200398 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
400 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
401 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200402
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200403 return( 0 );
404 }
405
406 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200407 * Ok, we need blinding. Can we re-use existing values?
408 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200409 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200411 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
413 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200414
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200415 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
416 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200417
418 return( 0 );
419 }
420
421 /*
422 * We need to generate blinding values from scratch
423 */
424
425 /* Vi = random( 2, P-1 ) */
Manuel Pégourié-Gonnard41ee8392020-06-25 12:34:58 +0200426 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200427
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200428 /* Vf = Vi^-X mod P
429 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
430 * then elevate to the Xth power. */
431 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
432 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
433 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
434 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
435 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
436 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
437
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 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 +0200439
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200440cleanup:
Manuel Pégourié-Gonnardd96edbc2020-06-25 12:47:22 +0200441 mbedtls_mpi_free( &R );
442
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200443 return( ret );
444}
445
446/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000447 * Derive and export the shared secret (G^Y)^X mod P
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100450 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200451 int (*f_rng)(void *, unsigned char *, size_t),
452 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000453{
454 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 mbedtls_mpi GYb;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000456 DHM_VALIDATE_RET( ctx != NULL );
457 DHM_VALIDATE_RET( output != NULL );
458 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200459
Hanno Becker5c14ed62018-12-12 19:44:47 +0000460 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000462
Paul Bakker345a6fe2011-02-28 21:20:02 +0000463 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000464 return( ret );
465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200467
468 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200469 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200470 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
472 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
473 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200474 }
475 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200477
478 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200480 &ctx->P, &ctx->RP ) );
481
482 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200483 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200484 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
486 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200487 }
488
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000490
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000492
493cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000495
496 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200497 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000498
499 return( 0 );
500}
501
502/*
503 * Free the components of a DHM key
504 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000506{
Hanno Becker5c14ed62018-12-12 19:44:47 +0000507 if( ctx == NULL )
508 return;
509
irwir2239a862018-06-12 18:25:09 +0300510 mbedtls_mpi_free( &ctx->pX );
511 mbedtls_mpi_free( &ctx->Vf );
512 mbedtls_mpi_free( &ctx->Vi );
513 mbedtls_mpi_free( &ctx->RP );
514 mbedtls_mpi_free( &ctx->K );
515 mbedtls_mpi_free( &ctx->GY );
516 mbedtls_mpi_free( &ctx->GX );
517 mbedtls_mpi_free( &ctx->X );
518 mbedtls_mpi_free( &ctx->G );
519 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200520
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500521 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000522}
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200525/*
526 * Parse DHM parameters
527 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200529 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200530{
531 int ret;
532 size_t len;
533 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534#if defined(MBEDTLS_PEM_PARSE_C)
535 mbedtls_pem_context pem;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000536#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200537
Hanno Becker5c14ed62018-12-12 19:44:47 +0000538 DHM_VALIDATE_RET( dhm != NULL );
539 DHM_VALIDATE_RET( dhmin != NULL );
540
541#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200543
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200544 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200545 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200546 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
547 else
548 ret = mbedtls_pem_read_buffer( &pem,
549 "-----BEGIN DH PARAMETERS-----",
550 "-----END DH PARAMETERS-----",
551 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200552
553 if( ret == 0 )
554 {
555 /*
556 * Was PEM encoded
557 */
558 dhminlen = pem.buflen;
559 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200561 goto exit;
562
563 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
564#else
565 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200567 end = p + dhminlen;
568
569 /*
570 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400571 * prime INTEGER, -- P
572 * generator INTEGER, -- g
573 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200574 * }
575 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
577 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 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 end = p + len;
584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
586 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200587 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200589 goto exit;
590 }
591
592 if( p != end )
593 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200594 /* This might be the optional privateValueLength.
595 * If so, we can cleanly discard it */
596 mbedtls_mpi rec;
597 mbedtls_mpi_init( &rec );
598 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
599 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400600 if ( ret != 0 )
601 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200602 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400603 goto exit;
604 }
605 if ( p != end )
606 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200607 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
608 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400609 goto exit;
610 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200611 }
612
613 ret = 0;
614
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100616
Paul Bakker40ce79f2013-09-15 17:43:54 +0200617exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200618#if defined(MBEDTLS_PEM_PARSE_C)
619 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200620#endif
621 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200623
624 return( ret );
625}
626
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200628/*
629 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200630 *
631 * The file is expected to contain either PEM or DER encoded data.
632 * A terminating null byte is always appended. It is included in the announced
633 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200634 */
635static int load_file( const char *path, unsigned char **buf, size_t *n )
636{
637 FILE *f;
638 long size;
639
640 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200642
643 fseek( f, 0, SEEK_END );
644 if( ( size = ftell( f ) ) == -1 )
645 {
646 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200647 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200648 }
649 fseek( f, 0, SEEK_SET );
650
651 *n = (size_t) size;
652
653 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200654 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200655 {
656 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200657 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200658 }
659
660 if( fread( *buf, 1, *n, f ) != *n )
661 {
662 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100663
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500664 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100666
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200668 }
669
670 fclose( f );
671
672 (*buf)[*n] = '\0';
673
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200674 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
675 ++*n;
676
Paul Bakker40ce79f2013-09-15 17:43:54 +0200677 return( 0 );
678}
679
680/*
681 * Load and parse DHM parameters
682 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200684{
685 int ret;
686 size_t n;
687 unsigned char *buf;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000688 DHM_VALIDATE_RET( dhm != NULL );
689 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200690
Paul Bakker66d5d072014-06-17 16:39:18 +0200691 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200692 return( ret );
693
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200695
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500696 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200698
699 return( ret );
700}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701#endif /* MBEDTLS_FS_IO */
702#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000703#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200704
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000706
Hanno Becker7b34f0f2019-05-10 14:43:31 +0100707#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200708static const char mbedtls_test_dhm_params[] =
709"-----BEGIN DH PARAMETERS-----\r\n"
710"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
711"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
712"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
713"-----END DH PARAMETERS-----\r\n";
Hanno Becker7b34f0f2019-05-10 14:43:31 +0100714#else /* MBEDTLS_PEM_PARSE_C */
715static const char mbedtls_test_dhm_params[] = {
716 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
717 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
718 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
719 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
720 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
721 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
722 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
723 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
724 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
725 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
726 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
727 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
728#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200729
730static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200731
Paul Bakker5121ce52009-01-03 21:22:43 +0000732/*
733 * Checkup routine
734 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000736{
Paul Bakker40ce79f2013-09-15 17:43:54 +0200737 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200739
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200740 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200741
Paul Bakker40ce79f2013-09-15 17:43:54 +0200742 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200744
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200745 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
746 (const unsigned char *) mbedtls_test_dhm_params,
747 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200748 {
749 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200751
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200752 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200753 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200754 }
755
756 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200757 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200758
Paul Bakker8f870b02014-06-20 13:32:38 +0200759exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200760 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200761
Paul Bakker8f870b02014-06-20 13:32:38 +0200762 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000763}
764
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200765#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000766
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200767#endif /* MBEDTLS_DHM_C */