blob: 88e148bb80ffc36eea3ccdb7d18d4c4d378aa4e4 [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 Peskine58df4c92021-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 Peskine58df4c92021-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 Peskine58df4c92021-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 Peskine58df4c92021-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
Paul Bakkerc47840e2011-02-20 16:37:30 +0000127/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000128 * Parse the ServerKeyExchange parameters
129 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000132 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000133{
Janos Follath24eed8d2019-11-22 13:21:35 +0000134 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500135 DHM_VALIDATE_RET( ctx != NULL );
136 DHM_VALIDATE_RET( p != NULL && *p != NULL );
137 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000138
Paul Bakker5121ce52009-01-03 21:22:43 +0000139 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
140 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
141 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
142 return( ret );
143
Paul Bakker345a6fe2011-02-28 21:20:02 +0000144 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
145 return( ret );
146
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200147 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000148
Paul Bakker5121ce52009-01-03 21:22:43 +0000149 return( 0 );
150}
151
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200152/*
Gilles Peskine16e36682021-03-31 23:04:50 +0200153 * Pick a random R in the range [2, M-2] for blinding or key generation.
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200154 */
155static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
156 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
157{
Gilles Peskine16e36682021-03-31 23:04:50 +0200158 int ret;
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200159
Gilles Peskine16e36682021-03-31 23:04:50 +0200160 MBEDTLS_MPI_CHK( mbedtls_mpi_random( R, 3, M, f_rng, p_rng ) );
161 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( R, R, 1 ) );
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200162
163cleanup:
164 return( ret );
165}
166
Gilles Peskine0853bb22021-03-31 22:35:13 +0200167static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
168 int (*f_rng)(void *, unsigned char *, size_t),
169 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000170{
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200171 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000172
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200173 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
174 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200175 if( x_size < 0 )
176 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000177
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200178 if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000179 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200180 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000181 }
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200182 else
183 {
184 /* Generate X as large as possible ( <= P - 2 ) */
185 ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
186 if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
187 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
188 if( ret != 0 )
189 return( ret );
190 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000191
Paul Bakkerff7fe672010-07-18 09:45:05 +0000192 /*
193 * Calculate GX = G^X mod P
194 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000196 &ctx->P , &ctx->RP ) );
197
Paul Bakker345a6fe2011-02-28 21:20:02 +0000198 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000199 return( ret );
200
Gilles Peskine0853bb22021-03-31 22:35:13 +0200201cleanup:
202 return( ret );
203}
204
205/*
206 * Setup and write the ServerKeyExchange parameters
207 */
208int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
209 unsigned char *output, size_t *olen,
210 int (*f_rng)(void *, unsigned char *, size_t),
211 void *p_rng )
212{
213 int ret;
214 size_t n1, n2, n3;
215 unsigned char *p;
216 DHM_VALIDATE_RET( ctx != NULL );
217 DHM_VALIDATE_RET( output != NULL );
218 DHM_VALIDATE_RET( olen != NULL );
219 DHM_VALIDATE_RET( f_rng != NULL );
220
221 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
222 if( ret != 0 )
223 goto cleanup;
224
Paul Bakker5121ce52009-01-03 21:22:43 +0000225 /*
Gilles Peskine104eb822021-04-13 22:10:24 +0200226 * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
227 * not required". We omit leading zeros for compactness.
Paul Bakker5121ce52009-01-03 21:22:43 +0000228 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100229#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100230 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100231 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
232 p + 2, \
233 ( n ) ) ); \
Joe Subbianiad1115a2021-07-16 14:27:50 +0100234 *p++ = MBEDTLS_BYTE_1( n ); \
235 *p++ = MBEDTLS_BYTE_0( n ); \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100236 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100237 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 n1 = mbedtls_mpi_size( &ctx->P );
240 n2 = mbedtls_mpi_size( &ctx->G );
241 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242
243 p = output;
244 DHM_MPI_EXPORT( &ctx->P , n1 );
245 DHM_MPI_EXPORT( &ctx->G , n2 );
246 DHM_MPI_EXPORT( &ctx->GX, n3 );
247
Hanno Beckere71ad122017-09-28 10:32:25 +0100248 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000249
250 ctx->len = n1;
251
252cleanup:
Gilles Peskine0853bb22021-03-31 22:35:13 +0200253 if( ret != 0 && ret > -128 )
254 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret );
255 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000256}
257
258/*
Hanno Becker8880e752017-10-04 13:15:08 +0100259 * Set prime modulus and generator
260 */
261int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
262 const mbedtls_mpi *P,
263 const mbedtls_mpi *G )
264{
Janos Follath24eed8d2019-11-22 13:21:35 +0000265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500266 DHM_VALIDATE_RET( ctx != NULL );
267 DHM_VALIDATE_RET( P != NULL );
268 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100269
270 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
271 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
272 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100273 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) );
Hanno Becker8880e752017-10-04 13:15:08 +0100274 }
275
276 ctx->len = mbedtls_mpi_size( &ctx->P );
277 return( 0 );
278}
279
280/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000281 * Import the peer's public value G^Y
282 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000284 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000285{
Janos Follath24eed8d2019-11-22 13:21:35 +0000286 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500287 DHM_VALIDATE_RET( ctx != NULL );
288 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000289
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500290 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200291 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100294 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295
296 return( 0 );
297}
298
299/*
300 * Create own private value X and export G^X
301 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000303 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000304 int (*f_rng)(void *, unsigned char *, size_t),
305 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000306{
Gilles Peskine0853bb22021-03-31 22:35:13 +0200307 int ret;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500308 DHM_VALIDATE_RET( ctx != NULL );
309 DHM_VALIDATE_RET( output != NULL );
310 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000311
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500312 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000314
Gilles Peskine0853bb22021-03-31 22:35:13 +0200315 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
316 if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
317 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
318 if( ret != 0 )
319 goto cleanup;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000320
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000322
323cleanup:
Gilles Peskine0853bb22021-03-31 22:35:13 +0200324 if( ret != 0 && ret > -128 )
325 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret );
326 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000327}
328
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200329
330/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200331 * Use the blinding method and optimisation suggested in section 10 of:
332 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200333 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200334 * Berlin Heidelberg, 1996. p. 104-113.
335 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200336static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200337 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
338{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200339 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200340 mbedtls_mpi R;
341
342 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200343
344 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200345 * Don't use any blinding the first time a particular X is used,
346 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200347 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200348 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200349 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200350 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
351 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
352 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200353
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200354 return( 0 );
355 }
356
357 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200358 * Ok, we need blinding. Can we re-use existing values?
359 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200360 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200362 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200363 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
364 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200365
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
367 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200368
369 return( 0 );
370 }
371
372 /*
373 * We need to generate blinding values from scratch
374 */
375
Gilles Peskineb4e815f2021-03-31 22:50:57 +0200376 /* Vi = random( 2, P-2 ) */
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200377 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200378
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200379 /* Vf = Vi^-X mod P
380 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
381 * then elevate to the Xth power. */
382 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
383 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
384 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
385 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
386 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
387 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 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 +0200390
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200391cleanup:
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200392 mbedtls_mpi_free( &R );
393
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200394 return( ret );
395}
396
397/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000398 * Derive and export the shared secret (G^Y)^X mod P
399 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100401 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200402 int (*f_rng)(void *, unsigned char *, size_t),
403 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000404{
Janos Follath24eed8d2019-11-22 13:21:35 +0000405 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 mbedtls_mpi GYb;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500407 DHM_VALIDATE_RET( ctx != NULL );
408 DHM_VALIDATE_RET( output != NULL );
409 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200410
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500411 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000413
Paul Bakker345a6fe2011-02-28 21:20:02 +0000414 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000415 return( ret );
416
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200418
419 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200420 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200421 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
423 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
424 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200425 }
426 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200428
429 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200431 &ctx->P, &ctx->RP ) );
432
433 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200434 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200435 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
437 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200438 }
439
Gilles Peskine104eb822021-04-13 22:10:24 +0200440 /* Output the secret without any leading zero byte. This is mandatory
441 * for TLS per RFC 5246 §8.1.2. */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 *olen = mbedtls_mpi_size( &ctx->K );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
445cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
448 if( ret != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100449 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000450
451 return( 0 );
452}
453
454/*
455 * Free the components of a DHM key
456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500459 if( ctx == NULL )
460 return;
461
462 mbedtls_mpi_free( &ctx->pX );
463 mbedtls_mpi_free( &ctx->Vf );
464 mbedtls_mpi_free( &ctx->Vi );
465 mbedtls_mpi_free( &ctx->RP );
466 mbedtls_mpi_free( &ctx->K );
467 mbedtls_mpi_free( &ctx->GY );
468 mbedtls_mpi_free( &ctx->GX );
469 mbedtls_mpi_free( &ctx->X );
470 mbedtls_mpi_free( &ctx->G );
471 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200472
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500473 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000474}
475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200477/*
478 * Parse DHM parameters
479 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200480int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200481 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200482{
Janos Follath24eed8d2019-11-22 13:21:35 +0000483 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200484 size_t len;
485 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486#if defined(MBEDTLS_PEM_PARSE_C)
487 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500488#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200489
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500490 DHM_VALIDATE_RET( dhm != NULL );
491 DHM_VALIDATE_RET( dhmin != NULL );
492
493#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200495
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200496 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200497 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200498 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
499 else
500 ret = mbedtls_pem_read_buffer( &pem,
501 "-----BEGIN DH PARAMETERS-----",
502 "-----END DH PARAMETERS-----",
503 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200504
505 if( ret == 0 )
506 {
507 /*
508 * Was PEM encoded
509 */
510 dhminlen = pem.buflen;
511 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200513 goto exit;
514
515 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
516#else
517 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200519 end = p + dhminlen;
520
521 /*
522 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400523 * prime INTEGER, -- P
524 * generator INTEGER, -- g
525 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200526 * }
527 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
529 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200530 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100531 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200532 goto exit;
533 }
534
535 end = p + len;
536
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
538 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200539 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100540 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200541 goto exit;
542 }
543
544 if( p != end )
545 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200546 /* This might be the optional privateValueLength.
547 * If so, we can cleanly discard it */
548 mbedtls_mpi rec;
549 mbedtls_mpi_init( &rec );
550 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
551 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400552 if ( ret != 0 )
553 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100554 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400555 goto exit;
556 }
557 if ( p != end )
558 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100559 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT,
560 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400561 goto exit;
562 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200563 }
564
565 ret = 0;
566
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100568
Paul Bakker40ce79f2013-09-15 17:43:54 +0200569exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570#if defined(MBEDTLS_PEM_PARSE_C)
571 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200572#endif
573 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200574 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200575
576 return( ret );
577}
578
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200580/*
581 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200582 *
583 * The file is expected to contain either PEM or DER encoded data.
584 * A terminating null byte is always appended. It is included in the announced
585 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200586 */
587static int load_file( const char *path, unsigned char **buf, size_t *n )
588{
589 FILE *f;
590 long size;
591
592 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200593 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200594
595 fseek( f, 0, SEEK_END );
596 if( ( size = ftell( f ) ) == -1 )
597 {
598 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200599 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200600 }
601 fseek( f, 0, SEEK_SET );
602
603 *n = (size_t) size;
604
605 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200606 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200607 {
608 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200609 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200610 }
611
612 if( fread( *buf, 1, *n, f ) != *n )
613 {
614 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100615
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500616 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100618
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200619 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200620 }
621
622 fclose( f );
623
624 (*buf)[*n] = '\0';
625
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200626 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
627 ++*n;
628
Paul Bakker40ce79f2013-09-15 17:43:54 +0200629 return( 0 );
630}
631
632/*
633 * Load and parse DHM parameters
634 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200636{
Janos Follath24eed8d2019-11-22 13:21:35 +0000637 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200638 size_t n;
639 unsigned char *buf;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500640 DHM_VALIDATE_RET( dhm != NULL );
641 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200642
Paul Bakker66d5d072014-06-17 16:39:18 +0200643 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200644 return( ret );
645
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200647
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500648 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200650
651 return( ret );
652}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653#endif /* MBEDTLS_FS_IO */
654#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000655#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200656
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000658
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100659#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200660static const char mbedtls_test_dhm_params[] =
661"-----BEGIN DH PARAMETERS-----\r\n"
662"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
663"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
664"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
665"-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100666#else /* MBEDTLS_PEM_PARSE_C */
667static const char mbedtls_test_dhm_params[] = {
668 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
669 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
670 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
671 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
672 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
673 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
674 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
675 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
676 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
677 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
678 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
679 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
680#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200681
682static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200683
Paul Bakker5121ce52009-01-03 21:22:43 +0000684/*
685 * Checkup routine
686 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000688{
Janos Follath24eed8d2019-11-22 13:21:35 +0000689 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200690 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200693
Paul Bakker40ce79f2013-09-15 17:43:54 +0200694 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200696
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200697 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
698 (const unsigned char *) mbedtls_test_dhm_params,
699 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200700 {
701 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200703
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200704 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200705 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200706 }
707
708 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200710
Paul Bakker8f870b02014-06-20 13:32:38 +0200711exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200713
Paul Bakker8f870b02014-06-20 13:32:38 +0200714 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000715}
716
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000718
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200719#endif /* MBEDTLS_DHM_C */