blob: 2543be194930c1aee60c5de9578c3f526abb8511 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Diffie-Hellman-Merkle key exchange
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
19/*
Simon Butcherbdae02c2016-01-20 00:44:42 +000020 * The following sources were referenced in the design of this implementation
21 * of the Diffie-Hellman-Merkle algorithm:
Paul Bakker5121ce52009-01-03 21:22:43 +000022 *
Simon Butcherbdae02c2016-01-20 00:44:42 +000023 * [1] Handbook of Applied Cryptography - 1997, Chapter 12
24 * Menezes, van Oorschot and Vanstone
25 *
Paul Bakker5121ce52009-01-03 21:22:43 +000026 */
27
Gilles Peskinedb09ef62020-06-03 01:43:33 +020028#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000029
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if defined(MBEDTLS_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000032#include "mbedtls/dhm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050033#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000034#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Rich Evans00ab4702015-02-06 13:43:58 +000036#include <string.h>
37
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020040#endif
41
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020044#endif
45
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020046#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020048#else
49#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000050#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020052#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053#define mbedtls_free free
Paul Bakker40ce79f2013-09-15 17:43:54 +020054#endif
55
Reuven Levin1f35ca92017-12-07 10:09:32 +000056#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020057
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050058#define DHM_VALIDATE_RET( cond ) \
59 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
60#define DHM_VALIDATE( cond ) \
61 MBEDTLS_INTERNAL_VALIDATE( cond )
62
Paul Bakker5121ce52009-01-03 21:22:43 +000063/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020064 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000065 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +000067 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000068 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +000069{
70 int ret, n;
71
72 if( end - *p < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000074
75 n = ( (*p)[0] << 8 ) | (*p)[1];
76 (*p) += 2;
77
78 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020079 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000080
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +010082 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +000083
84 (*p) += n;
85
86 return( 0 );
87}
88
89/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000090 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000091 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000092 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000093 *
Janos Follathaa325d72017-09-20 15:33:24 +010094 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +010095 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +010096 *
Paul Bakker345a6fe2011-02-28 21:20:02 +000097 * For more information on the attack, see:
98 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
99 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +0000100 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000102{
Gilles Peskine8e38acc2021-03-31 22:56:43 +0200103 mbedtls_mpi U;
Janos Follathaa325d72017-09-20 15:33:24 +0100104 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000105
Gilles Peskine8e38acc2021-03-31 22:56:43 +0200106 mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +0200107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000109
Gilles Peskine8e38acc2021-03-31 22:56:43 +0200110 if( mbedtls_mpi_cmp_int( param, 2 ) < 0 ||
Janos Follathaa325d72017-09-20 15:33:24 +0100111 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000112 {
Janos Follathaa325d72017-09-20 15:33:24 +0100113 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000114 }
115
Paul Bakker3d8fb632014-04-17 12:42:41 +0200116cleanup:
Gilles Peskine8e38acc2021-03-31 22:56:43 +0200117 mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000118 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000119}
120
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200121void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200122{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500123 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200125}
126
Gilles Peskine487bbf62021-05-27 22:17:07 +0200127size_t mbedtls_dhm_get_bitlen( const mbedtls_dhm_context *ctx )
128{
129 return( mbedtls_mpi_bitlen( &ctx->P ) );
130}
131
132size_t mbedtls_dhm_get_len( const mbedtls_dhm_context *ctx )
133{
134 return( mbedtls_mpi_size( &ctx->P ) );
135}
136
Paul Bakkerc47840e2011-02-20 16:37:30 +0000137/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 * Parse the ServerKeyExchange parameters
139 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000141 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000142 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000143{
Janos Follath24eed8d2019-11-22 13:21:35 +0000144 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500145 DHM_VALIDATE_RET( ctx != NULL );
146 DHM_VALIDATE_RET( p != NULL && *p != NULL );
147 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000148
Paul Bakker5121ce52009-01-03 21:22:43 +0000149 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
150 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
151 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
152 return( ret );
153
Paul Bakker345a6fe2011-02-28 21:20:02 +0000154 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
155 return( ret );
156
Paul Bakker5121ce52009-01-03 21:22:43 +0000157 return( 0 );
158}
159
Gilles Peskine17f1a262021-03-31 22:48:14 +0200160/*
Gilles Peskineda7ee012021-03-31 23:04:50 +0200161 * Pick a random R in the range [2, M-2] for blinding or key generation.
Gilles Peskine17f1a262021-03-31 22:48:14 +0200162 */
163static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
164 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
165{
Gilles Peskineda7ee012021-03-31 23:04:50 +0200166 int ret;
Gilles Peskine17f1a262021-03-31 22:48:14 +0200167
Gilles Peskineda7ee012021-03-31 23:04:50 +0200168 MBEDTLS_MPI_CHK( mbedtls_mpi_random( R, 3, M, f_rng, p_rng ) );
169 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( R, R, 1 ) );
Gilles Peskine17f1a262021-03-31 22:48:14 +0200170
171cleanup:
172 return( ret );
173}
174
Gilles Peskinecb660f22021-03-31 22:35:13 +0200175static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
176 int (*f_rng)(void *, unsigned char *, size_t),
177 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000178{
Gilles Peskine17f1a262021-03-31 22:48:14 +0200179 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
182 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Gilles Peskine17f1a262021-03-31 22:48:14 +0200183 if( x_size < 0 )
184 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000185
Gilles Peskine17f1a262021-03-31 22:48:14 +0200186 if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000187 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200188 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000189 }
Gilles Peskine17f1a262021-03-31 22:48:14 +0200190 else
191 {
192 /* Generate X as large as possible ( <= P - 2 ) */
193 ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
194 if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
195 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
196 if( ret != 0 )
197 return( ret );
198 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000199
Paul Bakkerff7fe672010-07-18 09:45:05 +0000200 /*
201 * Calculate GX = G^X mod P
202 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000204 &ctx->P , &ctx->RP ) );
205
Paul Bakker345a6fe2011-02-28 21:20:02 +0000206 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000207 return( ret );
208
Gilles Peskinecb660f22021-03-31 22:35:13 +0200209cleanup:
210 return( ret );
211}
212
213/*
214 * Setup and write the ServerKeyExchange parameters
215 */
216int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
217 unsigned char *output, size_t *olen,
218 int (*f_rng)(void *, unsigned char *, size_t),
219 void *p_rng )
220{
221 int ret;
222 size_t n1, n2, n3;
223 unsigned char *p;
224 DHM_VALIDATE_RET( ctx != NULL );
225 DHM_VALIDATE_RET( output != NULL );
226 DHM_VALIDATE_RET( olen != NULL );
227 DHM_VALIDATE_RET( f_rng != NULL );
228
229 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
230 if( ret != 0 )
231 goto cleanup;
232
Paul Bakker5121ce52009-01-03 21:22:43 +0000233 /*
Gilles Peskine03299dc2021-04-13 22:10:24 +0200234 * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
235 * not required". We omit leading zeros for compactness.
Paul Bakker5121ce52009-01-03 21:22:43 +0000236 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100237#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100238 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100239 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
240 p + 2, \
241 ( n ) ) ); \
242 *p++ = (unsigned char)( ( n ) >> 8 ); \
243 *p++ = (unsigned char)( ( n ) ); \
244 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100245 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000246
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200247 n1 = mbedtls_mpi_size( &ctx->P );
248 n2 = mbedtls_mpi_size( &ctx->G );
249 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000250
251 p = output;
252 DHM_MPI_EXPORT( &ctx->P , n1 );
253 DHM_MPI_EXPORT( &ctx->G , n2 );
254 DHM_MPI_EXPORT( &ctx->GX, n3 );
255
Hanno Beckere71ad122017-09-28 10:32:25 +0100256 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000257
Paul Bakker5121ce52009-01-03 21:22:43 +0000258cleanup:
Gilles Peskinecb660f22021-03-31 22:35:13 +0200259 if( ret != 0 && ret > -128 )
260 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret );
261 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000262}
263
264/*
Hanno Becker8880e752017-10-04 13:15:08 +0100265 * Set prime modulus and generator
266 */
267int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
268 const mbedtls_mpi *P,
269 const mbedtls_mpi *G )
270{
Janos Follath24eed8d2019-11-22 13:21:35 +0000271 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500272 DHM_VALIDATE_RET( ctx != NULL );
273 DHM_VALIDATE_RET( P != NULL );
274 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100275
276 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
277 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
278 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100279 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) );
Hanno Becker8880e752017-10-04 13:15:08 +0100280 }
281
Hanno Becker8880e752017-10-04 13:15:08 +0100282 return( 0 );
283}
284
285/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000286 * Import the peer's public value G^Y
287 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000289 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000290{
Janos Follath24eed8d2019-11-22 13:21:35 +0000291 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500292 DHM_VALIDATE_RET( ctx != NULL );
293 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000294
Gilles Peskine487bbf62021-05-27 22:17:07 +0200295 if( ilen < 1 || ilen > mbedtls_dhm_get_len( ctx ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200296 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000297
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200298 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100299 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000300
301 return( 0 );
302}
303
304/*
305 * Create own private value X and export G^X
306 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000308 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000309 int (*f_rng)(void *, unsigned char *, size_t),
310 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000311{
Gilles Peskinecb660f22021-03-31 22:35:13 +0200312 int ret;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500313 DHM_VALIDATE_RET( ctx != NULL );
314 DHM_VALIDATE_RET( output != NULL );
315 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000316
Gilles Peskine487bbf62021-05-27 22:17:07 +0200317 if( olen < 1 || olen > mbedtls_dhm_get_len( ctx ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Gilles Peskinecb660f22021-03-31 22:35:13 +0200320 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
321 if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
322 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
323 if( ret != 0 )
324 goto cleanup;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000327
328cleanup:
Gilles Peskinecb660f22021-03-31 22:35:13 +0200329 if( ret != 0 && ret > -128 )
330 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret );
331 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000332}
333
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200334
335/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200336 * Use the blinding method and optimisation suggested in section 10 of:
337 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200338 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200339 * Berlin Heidelberg, 1996. p. 104-113.
340 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200342 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
343{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200344 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200345 mbedtls_mpi R;
346
347 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200348
349 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200350 * Don't use any blinding the first time a particular X is used,
351 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200354 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
356 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
357 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200358
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200359 return( 0 );
360 }
361
362 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200363 * Ok, we need blinding. Can we re-use existing values?
364 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200365 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200367 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
369 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200370
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
372 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200373
374 return( 0 );
375 }
376
377 /*
378 * We need to generate blinding values from scratch
379 */
380
Gilles Peskine7b2b66e2021-03-31 22:50:57 +0200381 /* Vi = random( 2, P-2 ) */
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200382 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200383
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200384 /* Vf = Vi^-X mod P
385 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
386 * then elevate to the Xth power. */
387 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
388 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
389 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
390 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
391 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
392 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200393
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 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 +0200395
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200396cleanup:
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200397 mbedtls_mpi_free( &R );
398
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200399 return( ret );
400}
401
402/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000403 * Derive and export the shared secret (G^Y)^X mod P
404 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100406 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200407 int (*f_rng)(void *, unsigned char *, size_t),
408 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000409{
Janos Follath24eed8d2019-11-22 13:21:35 +0000410 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411 mbedtls_mpi GYb;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500412 DHM_VALIDATE_RET( ctx != NULL );
413 DHM_VALIDATE_RET( output != NULL );
414 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200415
Gilles Peskine487bbf62021-05-27 22:17:07 +0200416 if( output_size < mbedtls_dhm_get_len( ctx ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000418
Paul Bakker345a6fe2011-02-28 21:20:02 +0000419 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000420 return( ret );
421
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200423
424 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200425 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200426 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
428 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
429 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200430 }
431 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200433
434 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200436 &ctx->P, &ctx->RP ) );
437
438 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200439 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200440 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
442 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200443 }
444
Gilles Peskine03299dc2021-04-13 22:10:24 +0200445 /* Output the secret without any leading zero byte. This is mandatory
446 * for TLS per RFC 5246 §8.1.2. */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 *olen = mbedtls_mpi_size( &ctx->K );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
450cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000452
453 if( ret != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100454 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
456 return( 0 );
457}
458
459/*
460 * Free the components of a DHM key
461 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000463{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500464 if( ctx == NULL )
465 return;
466
467 mbedtls_mpi_free( &ctx->pX );
468 mbedtls_mpi_free( &ctx->Vf );
469 mbedtls_mpi_free( &ctx->Vi );
470 mbedtls_mpi_free( &ctx->RP );
471 mbedtls_mpi_free( &ctx->K );
472 mbedtls_mpi_free( &ctx->GY );
473 mbedtls_mpi_free( &ctx->GX );
474 mbedtls_mpi_free( &ctx->X );
475 mbedtls_mpi_free( &ctx->G );
476 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200477
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500478 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000479}
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200482/*
483 * Parse DHM parameters
484 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200486 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200487{
Janos Follath24eed8d2019-11-22 13:21:35 +0000488 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200489 size_t len;
490 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491#if defined(MBEDTLS_PEM_PARSE_C)
492 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500493#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200494
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500495 DHM_VALIDATE_RET( dhm != NULL );
496 DHM_VALIDATE_RET( dhmin != NULL );
497
498#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200500
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200501 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200502 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200503 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
504 else
505 ret = mbedtls_pem_read_buffer( &pem,
506 "-----BEGIN DH PARAMETERS-----",
507 "-----END DH PARAMETERS-----",
508 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200509
510 if( ret == 0 )
511 {
512 /*
513 * Was PEM encoded
514 */
515 dhminlen = pem.buflen;
516 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200517 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200518 goto exit;
519
520 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
521#else
522 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200524 end = p + dhminlen;
525
526 /*
527 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400528 * prime INTEGER, -- P
529 * generator INTEGER, -- g
530 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200531 * }
532 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
534 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200535 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100536 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200537 goto exit;
538 }
539
540 end = p + len;
541
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200542 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
543 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200544 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100545 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200546 goto exit;
547 }
548
549 if( p != end )
550 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200551 /* This might be the optional privateValueLength.
552 * If so, we can cleanly discard it */
553 mbedtls_mpi rec;
554 mbedtls_mpi_init( &rec );
555 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
556 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400557 if ( ret != 0 )
558 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100559 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400560 goto exit;
561 }
562 if ( p != end )
563 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100564 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT,
565 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400566 goto exit;
567 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200568 }
569
570 ret = 0;
571
572exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573#if defined(MBEDTLS_PEM_PARSE_C)
574 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200575#endif
576 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200577 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200578
579 return( ret );
580}
581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200583/*
584 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200585 *
586 * The file is expected to contain either PEM or DER encoded data.
587 * A terminating null byte is always appended. It is included in the announced
588 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200589 */
590static int load_file( const char *path, unsigned char **buf, size_t *n )
591{
592 FILE *f;
593 long size;
594
595 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200597
598 fseek( f, 0, SEEK_END );
599 if( ( size = ftell( f ) ) == -1 )
600 {
601 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200603 }
604 fseek( f, 0, SEEK_SET );
605
606 *n = (size_t) size;
607
608 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200609 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200610 {
611 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200612 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200613 }
614
615 if( fread( *buf, 1, *n, f ) != *n )
616 {
617 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100618
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500619 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100621
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200623 }
624
625 fclose( f );
626
627 (*buf)[*n] = '\0';
628
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200629 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
630 ++*n;
631
Paul Bakker40ce79f2013-09-15 17:43:54 +0200632 return( 0 );
633}
634
635/*
636 * Load and parse DHM parameters
637 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200639{
Janos Follath24eed8d2019-11-22 13:21:35 +0000640 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200641 size_t n;
642 unsigned char *buf;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500643 DHM_VALIDATE_RET( dhm != NULL );
644 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200645
Paul Bakker66d5d072014-06-17 16:39:18 +0200646 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200647 return( ret );
648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200650
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500651 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200652 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200653
654 return( ret );
655}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656#endif /* MBEDTLS_FS_IO */
657#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000658#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200659
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200660#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000661
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100662#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200663static const char mbedtls_test_dhm_params[] =
664"-----BEGIN DH PARAMETERS-----\r\n"
665"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
666"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
667"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
668"-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100669#else /* MBEDTLS_PEM_PARSE_C */
670static const char mbedtls_test_dhm_params[] = {
671 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
672 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
673 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
674 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
675 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
676 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
677 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
678 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
679 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
680 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
681 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
682 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
683#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200684
685static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200686
Paul Bakker5121ce52009-01-03 21:22:43 +0000687/*
688 * Checkup routine
689 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000691{
Janos Follath24eed8d2019-11-22 13:21:35 +0000692 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200693 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200694
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200696
Paul Bakker40ce79f2013-09-15 17:43:54 +0200697 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200699
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200700 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
701 (const unsigned char *) mbedtls_test_dhm_params,
702 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200703 {
704 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200706
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200707 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200708 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200709 }
710
711 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200713
Paul Bakker8f870b02014-06-20 13:32:38 +0200714exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200715 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200716
Paul Bakker8f870b02014-06-20 13:32:38 +0200717 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000718}
719
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722#endif /* MBEDTLS_DHM_C */