blob: 4d2e33e689e82a2005f215ae926c4438e47f49ed [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é-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020047
Reuven Levin1f35ca92017-12-07 10:09:32 +000048#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020049
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050050#define DHM_VALIDATE_RET( cond ) \
51 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
52#define DHM_VALIDATE( cond ) \
53 MBEDTLS_INTERNAL_VALIDATE( cond )
54
Paul Bakker5121ce52009-01-03 21:22:43 +000055/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000057 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +000059 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000060 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +000061{
62 int ret, n;
63
64 if( end - *p < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020065 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000066
67 n = ( (*p)[0] << 8 ) | (*p)[1];
68 (*p) += 2;
69
70 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000072
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020073 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +010074 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +000075
76 (*p) += n;
77
78 return( 0 );
79}
80
81/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000082 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000083 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000084 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000085 *
Janos Follathaa325d72017-09-20 15:33:24 +010086 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +010087 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +010088 *
Paul Bakker345a6fe2011-02-28 21:20:02 +000089 * For more information on the attack, see:
90 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
91 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +000092 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020093static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +000094{
Gilles Peskine58df4c92021-03-31 22:56:43 +020095 mbedtls_mpi U;
Janos Follathaa325d72017-09-20 15:33:24 +010096 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +000097
Gilles Peskine58df4c92021-03-31 22:56:43 +020098 mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +020099
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200100 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000101
Gilles Peskine58df4c92021-03-31 22:56:43 +0200102 if( mbedtls_mpi_cmp_int( param, 2 ) < 0 ||
Janos Follathaa325d72017-09-20 15:33:24 +0100103 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000104 {
Janos Follathaa325d72017-09-20 15:33:24 +0100105 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000106 }
107
Paul Bakker3d8fb632014-04-17 12:42:41 +0200108cleanup:
Gilles Peskine58df4c92021-03-31 22:56:43 +0200109 mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000110 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000111}
112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200114{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500115 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200116 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200117}
118
Paul Bakkerc47840e2011-02-20 16:37:30 +0000119/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000120 * Parse the ServerKeyExchange parameters
121 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000123 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000124 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000125{
Janos Follath24eed8d2019-11-22 13:21:35 +0000126 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500127 DHM_VALIDATE_RET( ctx != NULL );
128 DHM_VALIDATE_RET( p != NULL && *p != NULL );
129 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000130
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
132 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
133 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
134 return( ret );
135
Paul Bakker345a6fe2011-02-28 21:20:02 +0000136 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
137 return( ret );
138
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200139 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000140
Paul Bakker5121ce52009-01-03 21:22:43 +0000141 return( 0 );
142}
143
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200144/*
Gilles Peskine16e36682021-03-31 23:04:50 +0200145 * Pick a random R in the range [2, M-2] for blinding or key generation.
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200146 */
147static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
148 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
149{
Gilles Peskine16e36682021-03-31 23:04:50 +0200150 int ret;
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200151
Gilles Peskine16e36682021-03-31 23:04:50 +0200152 MBEDTLS_MPI_CHK( mbedtls_mpi_random( R, 3, M, f_rng, p_rng ) );
153 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( R, R, 1 ) );
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200154
155cleanup:
156 return( ret );
157}
158
Gilles Peskine0853bb22021-03-31 22:35:13 +0200159static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
160 int (*f_rng)(void *, unsigned char *, size_t),
161 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000162{
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200163 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000164
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
166 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200167 if( x_size < 0 )
168 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000169
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200170 if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000171 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200172 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000173 }
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200174 else
175 {
176 /* Generate X as large as possible ( <= P - 2 ) */
177 ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
178 if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
179 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
180 if( ret != 0 )
181 return( ret );
182 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000183
Paul Bakkerff7fe672010-07-18 09:45:05 +0000184 /*
185 * Calculate GX = G^X mod P
186 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200187 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000188 &ctx->P , &ctx->RP ) );
189
Paul Bakker345a6fe2011-02-28 21:20:02 +0000190 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000191 return( ret );
192
Gilles Peskine0853bb22021-03-31 22:35:13 +0200193cleanup:
194 return( ret );
195}
196
197/*
198 * Setup and write the ServerKeyExchange parameters
199 */
200int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
201 unsigned char *output, size_t *olen,
202 int (*f_rng)(void *, unsigned char *, size_t),
203 void *p_rng )
204{
205 int ret;
206 size_t n1, n2, n3;
207 unsigned char *p;
208 DHM_VALIDATE_RET( ctx != NULL );
209 DHM_VALIDATE_RET( output != NULL );
210 DHM_VALIDATE_RET( olen != NULL );
211 DHM_VALIDATE_RET( f_rng != NULL );
212
213 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
214 if( ret != 0 )
215 goto cleanup;
216
Paul Bakker5121ce52009-01-03 21:22:43 +0000217 /*
Gilles Peskine104eb822021-04-13 22:10:24 +0200218 * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
219 * not required". We omit leading zeros for compactness.
Paul Bakker5121ce52009-01-03 21:22:43 +0000220 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100221#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100222 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100223 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
224 p + 2, \
225 ( n ) ) ); \
Joe Subbianiad1115a2021-07-16 14:27:50 +0100226 *p++ = MBEDTLS_BYTE_1( n ); \
227 *p++ = MBEDTLS_BYTE_0( n ); \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100228 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100229 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000230
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231 n1 = mbedtls_mpi_size( &ctx->P );
232 n2 = mbedtls_mpi_size( &ctx->G );
233 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000234
235 p = output;
236 DHM_MPI_EXPORT( &ctx->P , n1 );
237 DHM_MPI_EXPORT( &ctx->G , n2 );
238 DHM_MPI_EXPORT( &ctx->GX, n3 );
239
Hanno Beckere71ad122017-09-28 10:32:25 +0100240 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000241
242 ctx->len = n1;
243
244cleanup:
Gilles Peskine0853bb22021-03-31 22:35:13 +0200245 if( ret != 0 && ret > -128 )
246 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret );
247 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000248}
249
250/*
Hanno Becker8880e752017-10-04 13:15:08 +0100251 * Set prime modulus and generator
252 */
253int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
254 const mbedtls_mpi *P,
255 const mbedtls_mpi *G )
256{
Janos Follath24eed8d2019-11-22 13:21:35 +0000257 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500258 DHM_VALIDATE_RET( ctx != NULL );
259 DHM_VALIDATE_RET( P != NULL );
260 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100261
262 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
263 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
264 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100265 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) );
Hanno Becker8880e752017-10-04 13:15:08 +0100266 }
267
268 ctx->len = mbedtls_mpi_size( &ctx->P );
269 return( 0 );
270}
271
272/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000273 * Import the peer's public value G^Y
274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000276 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000277{
Janos Follath24eed8d2019-11-22 13:21:35 +0000278 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500279 DHM_VALIDATE_RET( ctx != NULL );
280 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000281
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500282 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000284
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100286 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000287
288 return( 0 );
289}
290
291/*
292 * Create own private value X and export G^X
293 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200294int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000295 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000296 int (*f_rng)(void *, unsigned char *, size_t),
297 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000298{
Gilles Peskine0853bb22021-03-31 22:35:13 +0200299 int ret;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500300 DHM_VALIDATE_RET( ctx != NULL );
301 DHM_VALIDATE_RET( output != NULL );
302 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000303
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500304 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000306
Gilles Peskine0853bb22021-03-31 22:35:13 +0200307 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
308 if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
309 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
310 if( ret != 0 )
311 goto cleanup;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000314
315cleanup:
Gilles Peskine0853bb22021-03-31 22:35:13 +0200316 if( ret != 0 && ret > -128 )
317 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret );
318 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319}
320
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200321
322/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200323 * Use the blinding method and optimisation suggested in section 10 of:
324 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200325 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200326 * Berlin Heidelberg, 1996. p. 104-113.
327 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200329 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
330{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200331 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200332 mbedtls_mpi R;
333
334 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200335
336 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200337 * Don't use any blinding the first time a particular X is used,
338 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200339 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200340 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200341 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
343 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
344 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200345
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200346 return( 0 );
347 }
348
349 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200350 * Ok, we need blinding. Can we re-use existing values?
351 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200354 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
356 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200357
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
359 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200360
361 return( 0 );
362 }
363
364 /*
365 * We need to generate blinding values from scratch
366 */
367
Gilles Peskineb4e815f2021-03-31 22:50:57 +0200368 /* Vi = random( 2, P-2 ) */
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200369 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200370
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200371 /* Vf = Vi^-X mod P
372 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
373 * then elevate to the Xth power. */
374 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
375 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
376 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
377 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
378 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
379 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200380
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 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 +0200382
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200383cleanup:
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200384 mbedtls_mpi_free( &R );
385
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200386 return( ret );
387}
388
389/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000390 * Derive and export the shared secret (G^Y)^X mod P
391 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100393 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200394 int (*f_rng)(void *, unsigned char *, size_t),
395 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000396{
Janos Follath24eed8d2019-11-22 13:21:35 +0000397 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 mbedtls_mpi GYb;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500399 DHM_VALIDATE_RET( ctx != NULL );
400 DHM_VALIDATE_RET( output != NULL );
401 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200402
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500403 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000405
Paul Bakker345a6fe2011-02-28 21:20:02 +0000406 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000407 return( ret );
408
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200410
411 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200412 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200413 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200414 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
415 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
416 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200417 }
418 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200420
421 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200423 &ctx->P, &ctx->RP ) );
424
425 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200426 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200427 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
429 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200430 }
431
Gilles Peskine104eb822021-04-13 22:10:24 +0200432 /* Output the secret without any leading zero byte. This is mandatory
433 * for TLS per RFC 5246 §8.1.2. */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 *olen = mbedtls_mpi_size( &ctx->K );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436
437cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
440 if( ret != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100441 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
443 return( 0 );
444}
445
446/*
447 * Free the components of a DHM key
448 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000450{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500451 if( ctx == NULL )
452 return;
453
454 mbedtls_mpi_free( &ctx->pX );
455 mbedtls_mpi_free( &ctx->Vf );
456 mbedtls_mpi_free( &ctx->Vi );
457 mbedtls_mpi_free( &ctx->RP );
458 mbedtls_mpi_free( &ctx->K );
459 mbedtls_mpi_free( &ctx->GY );
460 mbedtls_mpi_free( &ctx->GX );
461 mbedtls_mpi_free( &ctx->X );
462 mbedtls_mpi_free( &ctx->G );
463 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200464
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500465 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466}
467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200469/*
470 * Parse DHM parameters
471 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200473 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200474{
Janos Follath24eed8d2019-11-22 13:21:35 +0000475 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200476 size_t len;
477 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478#if defined(MBEDTLS_PEM_PARSE_C)
479 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500480#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200481
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500482 DHM_VALIDATE_RET( dhm != NULL );
483 DHM_VALIDATE_RET( dhmin != NULL );
484
485#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200487
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200488 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200489 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200490 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
491 else
492 ret = mbedtls_pem_read_buffer( &pem,
493 "-----BEGIN DH PARAMETERS-----",
494 "-----END DH PARAMETERS-----",
495 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200496
497 if( ret == 0 )
498 {
499 /*
500 * Was PEM encoded
501 */
502 dhminlen = pem.buflen;
503 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200505 goto exit;
506
507 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
508#else
509 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200511 end = p + dhminlen;
512
513 /*
514 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400515 * prime INTEGER, -- P
516 * generator INTEGER, -- g
517 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200518 * }
519 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
521 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200522 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100523 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200524 goto exit;
525 }
526
527 end = p + len;
528
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200529 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
530 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200531 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100532 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200533 goto exit;
534 }
535
536 if( p != end )
537 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200538 /* This might be the optional privateValueLength.
539 * If so, we can cleanly discard it */
540 mbedtls_mpi rec;
541 mbedtls_mpi_init( &rec );
542 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
543 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400544 if ( ret != 0 )
545 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100546 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400547 goto exit;
548 }
549 if ( p != end )
550 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100551 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT,
552 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400553 goto exit;
554 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200555 }
556
557 ret = 0;
558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200559 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100560
Paul Bakker40ce79f2013-09-15 17:43:54 +0200561exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562#if defined(MBEDTLS_PEM_PARSE_C)
563 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200564#endif
565 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200567
568 return( ret );
569}
570
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200571#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200572/*
573 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200574 *
575 * The file is expected to contain either PEM or DER encoded data.
576 * A terminating null byte is always appended. It is included in the announced
577 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200578 */
579static int load_file( const char *path, unsigned char **buf, size_t *n )
580{
581 FILE *f;
582 long size;
583
584 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200586
587 fseek( f, 0, SEEK_END );
588 if( ( size = ftell( f ) ) == -1 )
589 {
590 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200591 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200592 }
593 fseek( f, 0, SEEK_SET );
594
595 *n = (size_t) size;
596
597 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200598 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200599 {
600 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200601 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200602 }
603
604 if( fread( *buf, 1, *n, f ) != *n )
605 {
606 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100607
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500608 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100610
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200612 }
613
614 fclose( f );
615
616 (*buf)[*n] = '\0';
617
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200618 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
619 ++*n;
620
Paul Bakker40ce79f2013-09-15 17:43:54 +0200621 return( 0 );
622}
623
624/*
625 * Load and parse DHM parameters
626 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200628{
Janos Follath24eed8d2019-11-22 13:21:35 +0000629 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200630 size_t n;
631 unsigned char *buf;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500632 DHM_VALIDATE_RET( dhm != NULL );
633 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200634
Paul Bakker66d5d072014-06-17 16:39:18 +0200635 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200636 return( ret );
637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200639
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500640 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200642
643 return( ret );
644}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200645#endif /* MBEDTLS_FS_IO */
646#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000647#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200648
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000650
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100651#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200652static const char mbedtls_test_dhm_params[] =
653"-----BEGIN DH PARAMETERS-----\r\n"
654"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
655"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
656"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
657"-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100658#else /* MBEDTLS_PEM_PARSE_C */
659static const char mbedtls_test_dhm_params[] = {
660 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
661 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
662 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
663 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
664 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
665 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
666 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
667 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
668 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
669 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
670 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
671 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
672#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200673
674static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200675
Paul Bakker5121ce52009-01-03 21:22:43 +0000676/*
677 * Checkup routine
678 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000680{
Janos Follath24eed8d2019-11-22 13:21:35 +0000681 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200682 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200683
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200685
Paul Bakker40ce79f2013-09-15 17:43:54 +0200686 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200688
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200689 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
690 (const unsigned char *) mbedtls_test_dhm_params,
691 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200692 {
693 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200694 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200695
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200696 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200697 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200698 }
699
700 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200702
Paul Bakker8f870b02014-06-20 13:32:38 +0200703exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200705
Paul Bakker8f870b02014-06-20 13:32:38 +0200706 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000707}
708
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711#endif /* MBEDTLS_DHM_C */