blob: cb9299faba6b885d23fff3df351dc780a992c1ab [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
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200137int mbedtls_dhm_get_value( mbedtls_mpi *dest,
138 const mbedtls_dhm_context *ctx,
139 mbedtls_dhm_parameter param )
140{
141 const mbedtls_mpi *src = NULL;
142 switch( param )
143 {
144 case MBEDTLS_DHM_PARAM_P:
145 src = &ctx->P;
146 break;
147 case MBEDTLS_DHM_PARAM_G:
148 src = &ctx->G;
149 break;
150 case MBEDTLS_DHM_PARAM_X:
151 src = &ctx->X;
152 break;
153 case MBEDTLS_DHM_PARAM_GX:
154 src = &ctx->GX;
155 break;
156 case MBEDTLS_DHM_PARAM_GY:
157 src = &ctx->GY;
158 break;
159 case MBEDTLS_DHM_PARAM_K:
160 src = &ctx->K;
161 break;
162 default:
163 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
164 }
165 return( mbedtls_mpi_copy( dest, src ) );
166}
167
Paul Bakkerc47840e2011-02-20 16:37:30 +0000168/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000169 * Parse the ServerKeyExchange parameters
170 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000172 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000173 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000174{
Janos Follath24eed8d2019-11-22 13:21:35 +0000175 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500176 DHM_VALIDATE_RET( ctx != NULL );
177 DHM_VALIDATE_RET( p != NULL && *p != NULL );
178 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000179
Paul Bakker5121ce52009-01-03 21:22:43 +0000180 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
181 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
182 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
183 return( ret );
184
Paul Bakker345a6fe2011-02-28 21:20:02 +0000185 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
186 return( ret );
187
Paul Bakker5121ce52009-01-03 21:22:43 +0000188 return( 0 );
189}
190
Gilles Peskine17f1a262021-03-31 22:48:14 +0200191/*
Gilles Peskineda7ee012021-03-31 23:04:50 +0200192 * Pick a random R in the range [2, M-2] for blinding or key generation.
Gilles Peskine17f1a262021-03-31 22:48:14 +0200193 */
194static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
195 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
196{
Gilles Peskineda7ee012021-03-31 23:04:50 +0200197 int ret;
Gilles Peskine17f1a262021-03-31 22:48:14 +0200198
Gilles Peskineda7ee012021-03-31 23:04:50 +0200199 MBEDTLS_MPI_CHK( mbedtls_mpi_random( R, 3, M, f_rng, p_rng ) );
200 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( R, R, 1 ) );
Gilles Peskine17f1a262021-03-31 22:48:14 +0200201
202cleanup:
203 return( ret );
204}
205
Gilles Peskinecb660f22021-03-31 22:35:13 +0200206static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
207 int (*f_rng)(void *, unsigned char *, size_t),
208 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000209{
Gilles Peskine17f1a262021-03-31 22:48:14 +0200210 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000211
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200212 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
213 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Gilles Peskine17f1a262021-03-31 22:48:14 +0200214 if( x_size < 0 )
215 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000216
Gilles Peskine17f1a262021-03-31 22:48:14 +0200217 if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000218 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200219 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000220 }
Gilles Peskine17f1a262021-03-31 22:48:14 +0200221 else
222 {
223 /* Generate X as large as possible ( <= P - 2 ) */
224 ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
225 if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
226 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
227 if( ret != 0 )
228 return( ret );
229 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000230
Paul Bakkerff7fe672010-07-18 09:45:05 +0000231 /*
232 * Calculate GX = G^X mod P
233 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200234 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 &ctx->P , &ctx->RP ) );
236
Paul Bakker345a6fe2011-02-28 21:20:02 +0000237 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000238 return( ret );
239
Gilles Peskinecb660f22021-03-31 22:35:13 +0200240cleanup:
241 return( ret );
242}
243
244/*
245 * Setup and write the ServerKeyExchange parameters
246 */
247int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
248 unsigned char *output, size_t *olen,
249 int (*f_rng)(void *, unsigned char *, size_t),
250 void *p_rng )
251{
252 int ret;
253 size_t n1, n2, n3;
254 unsigned char *p;
255 DHM_VALIDATE_RET( ctx != NULL );
256 DHM_VALIDATE_RET( output != NULL );
257 DHM_VALIDATE_RET( olen != NULL );
258 DHM_VALIDATE_RET( f_rng != NULL );
259
260 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
261 if( ret != 0 )
262 goto cleanup;
263
Paul Bakker5121ce52009-01-03 21:22:43 +0000264 /*
Gilles Peskine03299dc2021-04-13 22:10:24 +0200265 * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
266 * not required". We omit leading zeros for compactness.
Paul Bakker5121ce52009-01-03 21:22:43 +0000267 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100268#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100269 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100270 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
271 p + 2, \
272 ( n ) ) ); \
273 *p++ = (unsigned char)( ( n ) >> 8 ); \
274 *p++ = (unsigned char)( ( n ) ); \
275 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100276 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000277
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 n1 = mbedtls_mpi_size( &ctx->P );
279 n2 = mbedtls_mpi_size( &ctx->G );
280 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000281
282 p = output;
283 DHM_MPI_EXPORT( &ctx->P , n1 );
284 DHM_MPI_EXPORT( &ctx->G , n2 );
285 DHM_MPI_EXPORT( &ctx->GX, n3 );
286
Hanno Beckere71ad122017-09-28 10:32:25 +0100287 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000288
Paul Bakker5121ce52009-01-03 21:22:43 +0000289cleanup:
Gilles Peskinecb660f22021-03-31 22:35:13 +0200290 if( ret != 0 && ret > -128 )
291 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret );
292 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000293}
294
295/*
Hanno Becker8880e752017-10-04 13:15:08 +0100296 * Set prime modulus and generator
297 */
298int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
299 const mbedtls_mpi *P,
300 const mbedtls_mpi *G )
301{
Janos Follath24eed8d2019-11-22 13:21:35 +0000302 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500303 DHM_VALIDATE_RET( ctx != NULL );
304 DHM_VALIDATE_RET( P != NULL );
305 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100306
307 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
308 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
309 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100310 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) );
Hanno Becker8880e752017-10-04 13:15:08 +0100311 }
312
Hanno Becker8880e752017-10-04 13:15:08 +0100313 return( 0 );
314}
315
316/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000317 * Import the peer's public value G^Y
318 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200319int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000320 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000321{
Janos Follath24eed8d2019-11-22 13:21:35 +0000322 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500323 DHM_VALIDATE_RET( ctx != NULL );
324 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000325
Gilles Peskine487bbf62021-05-27 22:17:07 +0200326 if( ilen < 1 || ilen > mbedtls_dhm_get_len( ctx ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000328
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200329 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100330 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000331
332 return( 0 );
333}
334
335/*
336 * Create own private value X and export G^X
337 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200338int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000339 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000340 int (*f_rng)(void *, unsigned char *, size_t),
341 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000342{
Gilles Peskinecb660f22021-03-31 22:35:13 +0200343 int ret;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500344 DHM_VALIDATE_RET( ctx != NULL );
345 DHM_VALIDATE_RET( output != NULL );
346 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000347
Gilles Peskine487bbf62021-05-27 22:17:07 +0200348 if( olen < 1 || olen > mbedtls_dhm_get_len( ctx ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200349 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000350
Gilles Peskinecb660f22021-03-31 22:35:13 +0200351 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
352 if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
353 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
354 if( ret != 0 )
355 goto cleanup;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000356
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000358
359cleanup:
Gilles Peskinecb660f22021-03-31 22:35:13 +0200360 if( ret != 0 && ret > -128 )
361 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret );
362 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000363}
364
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200365
366/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200367 * Use the blinding method and optimisation suggested in section 10 of:
368 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200369 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200370 * Berlin Heidelberg, 1996. p. 104-113.
371 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200373 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
374{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200375 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200376 mbedtls_mpi R;
377
378 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200379
380 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200381 * Don't use any blinding the first time a particular X is used,
382 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200385 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
387 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
388 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200389
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200390 return( 0 );
391 }
392
393 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200394 * Ok, we need blinding. Can we re-use existing values?
395 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200396 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200398 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
400 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200401
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200402 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
403 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200404
405 return( 0 );
406 }
407
408 /*
409 * We need to generate blinding values from scratch
410 */
411
Gilles Peskine7b2b66e2021-03-31 22:50:57 +0200412 /* Vi = random( 2, P-2 ) */
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200413 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200414
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200415 /* Vf = Vi^-X mod P
416 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
417 * then elevate to the Xth power. */
418 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
419 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
420 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
421 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
422 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
423 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200424
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 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 +0200426
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200427cleanup:
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200428 mbedtls_mpi_free( &R );
429
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200430 return( ret );
431}
432
433/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000434 * Derive and export the shared secret (G^Y)^X mod P
435 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100437 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200438 int (*f_rng)(void *, unsigned char *, size_t),
439 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000440{
Janos Follath24eed8d2019-11-22 13:21:35 +0000441 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 mbedtls_mpi GYb;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500443 DHM_VALIDATE_RET( ctx != NULL );
444 DHM_VALIDATE_RET( output != NULL );
445 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200446
Gilles Peskine487bbf62021-05-27 22:17:07 +0200447 if( output_size < mbedtls_dhm_get_len( ctx ) )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200448 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
Paul Bakker345a6fe2011-02-28 21:20:02 +0000450 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000451 return( ret );
452
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200454
455 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200456 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200457 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
459 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
460 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200461 }
462 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200464
465 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200467 &ctx->P, &ctx->RP ) );
468
469 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200470 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200471 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
473 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200474 }
475
Gilles Peskine03299dc2021-04-13 22:10:24 +0200476 /* Output the secret without any leading zero byte. This is mandatory
477 * for TLS per RFC 5246 §8.1.2. */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 *olen = mbedtls_mpi_size( &ctx->K );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
481cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
484 if( ret != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100485 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000486
487 return( 0 );
488}
489
490/*
491 * Free the components of a DHM key
492 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000494{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500495 if( ctx == NULL )
496 return;
497
498 mbedtls_mpi_free( &ctx->pX );
499 mbedtls_mpi_free( &ctx->Vf );
500 mbedtls_mpi_free( &ctx->Vi );
501 mbedtls_mpi_free( &ctx->RP );
502 mbedtls_mpi_free( &ctx->K );
503 mbedtls_mpi_free( &ctx->GY );
504 mbedtls_mpi_free( &ctx->GX );
505 mbedtls_mpi_free( &ctx->X );
506 mbedtls_mpi_free( &ctx->G );
507 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200508
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500509 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000510}
511
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200513/*
514 * Parse DHM parameters
515 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200517 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200518{
Janos Follath24eed8d2019-11-22 13:21:35 +0000519 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200520 size_t len;
521 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200522#if defined(MBEDTLS_PEM_PARSE_C)
523 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500524#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200525
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500526 DHM_VALIDATE_RET( dhm != NULL );
527 DHM_VALIDATE_RET( dhmin != NULL );
528
529#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200531
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200532 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200533 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200534 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
535 else
536 ret = mbedtls_pem_read_buffer( &pem,
537 "-----BEGIN DH PARAMETERS-----",
538 "-----END DH PARAMETERS-----",
539 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200540
541 if( ret == 0 )
542 {
543 /*
544 * Was PEM encoded
545 */
546 dhminlen = pem.buflen;
547 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200548 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200549 goto exit;
550
551 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
552#else
553 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200555 end = p + dhminlen;
556
557 /*
558 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400559 * prime INTEGER, -- P
560 * generator INTEGER, -- g
561 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200562 * }
563 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
565 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200566 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100567 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200568 goto exit;
569 }
570
571 end = p + len;
572
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200573 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
574 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200575 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100576 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200577 goto exit;
578 }
579
580 if( p != end )
581 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200582 /* This might be the optional privateValueLength.
583 * If so, we can cleanly discard it */
584 mbedtls_mpi rec;
585 mbedtls_mpi_init( &rec );
586 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
587 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400588 if ( ret != 0 )
589 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100590 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400591 goto exit;
592 }
593 if ( p != end )
594 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100595 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT,
596 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400597 goto exit;
598 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200599 }
600
601 ret = 0;
602
603exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604#if defined(MBEDTLS_PEM_PARSE_C)
605 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200606#endif
607 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200609
610 return( ret );
611}
612
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200613#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200614/*
615 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200616 *
617 * The file is expected to contain either PEM or DER encoded data.
618 * A terminating null byte is always appended. It is included in the announced
619 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200620 */
621static int load_file( const char *path, unsigned char **buf, size_t *n )
622{
623 FILE *f;
624 long size;
625
626 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200627 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200628
629 fseek( f, 0, SEEK_END );
630 if( ( size = ftell( f ) ) == -1 )
631 {
632 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200634 }
635 fseek( f, 0, SEEK_SET );
636
637 *n = (size_t) size;
638
639 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200640 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200641 {
642 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200643 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200644 }
645
646 if( fread( *buf, 1, *n, f ) != *n )
647 {
648 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100649
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500650 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100652
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200654 }
655
656 fclose( f );
657
658 (*buf)[*n] = '\0';
659
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200660 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
661 ++*n;
662
Paul Bakker40ce79f2013-09-15 17:43:54 +0200663 return( 0 );
664}
665
666/*
667 * Load and parse DHM parameters
668 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200670{
Janos Follath24eed8d2019-11-22 13:21:35 +0000671 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200672 size_t n;
673 unsigned char *buf;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500674 DHM_VALIDATE_RET( dhm != NULL );
675 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200676
Paul Bakker66d5d072014-06-17 16:39:18 +0200677 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200678 return( ret );
679
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200681
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500682 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200684
685 return( ret );
686}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687#endif /* MBEDTLS_FS_IO */
688#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000689#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200690
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200691#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000692
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100693#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200694static const char mbedtls_test_dhm_params[] =
695"-----BEGIN DH PARAMETERS-----\r\n"
696"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
697"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
698"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
699"-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100700#else /* MBEDTLS_PEM_PARSE_C */
701static const char mbedtls_test_dhm_params[] = {
702 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
703 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
704 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
705 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
706 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
707 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
708 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
709 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
710 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
711 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
712 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
713 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
714#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200715
716static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200717
Paul Bakker5121ce52009-01-03 21:22:43 +0000718/*
719 * Checkup routine
720 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000722{
Janos Follath24eed8d2019-11-22 13:21:35 +0000723 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200725
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200727
Paul Bakker40ce79f2013-09-15 17:43:54 +0200728 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200729 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200730
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200731 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
732 (const unsigned char *) mbedtls_test_dhm_params,
733 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200734 {
735 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200736 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200737
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200738 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200739 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200740 }
741
742 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200743 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200744
Paul Bakker8f870b02014-06-20 13:32:38 +0200745exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200746 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200747
Paul Bakker8f870b02014-06-20 13:32:38 +0200748 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000749}
750
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200751#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000752
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200753#endif /* MBEDTLS_DHM_C */