blob: 9758af787242ca5f18c58781785a40073148f6e4 [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{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 mbedtls_mpi L, U;
Janos Follathaa325d72017-09-20 15:33:24 +0100104 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000105
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106 mbedtls_mpi_init( &L ); 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_lset( &L, 2 ) );
109 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000110
Janos Follathaa325d72017-09-20 15:33:24 +0100111 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
112 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000113 {
Janos Follathaa325d72017-09-20 15:33:24 +0100114 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000115 }
116
Paul Bakker3d8fb632014-04-17 12:42:41 +0200117cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200118 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000119 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000120}
121
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200122void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200123{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500124 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200125 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200126}
127
Paul Bakkerc47840e2011-02-20 16:37:30 +0000128/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000129 * Parse the ServerKeyExchange parameters
130 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000132 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000133 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000134{
Janos Follath24eed8d2019-11-22 13:21:35 +0000135 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500136 DHM_VALIDATE_RET( ctx != NULL );
137 DHM_VALIDATE_RET( p != NULL && *p != NULL );
138 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000139
Paul Bakker5121ce52009-01-03 21:22:43 +0000140 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
141 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
142 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
143 return( ret );
144
Paul Bakker345a6fe2011-02-28 21:20:02 +0000145 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
146 return( ret );
147
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000149
Paul Bakker5121ce52009-01-03 21:22:43 +0000150 return( 0 );
151}
152
153/*
154 * Setup and write the ServerKeyExchange parameters
155 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000157 unsigned char *output, size_t *olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000158 int (*f_rng)(void *, unsigned char *, size_t),
159 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000160{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000161 int ret, count = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000162 size_t n1, n2, n3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000163 unsigned char *p;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500164 DHM_VALIDATE_RET( ctx != NULL );
165 DHM_VALIDATE_RET( output != NULL );
166 DHM_VALIDATE_RET( olen != NULL );
167 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000168
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200169 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
170 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000171
Paul Bakker5121ce52009-01-03 21:22:43 +0000172 /*
Paul Bakkerff7fe672010-07-18 09:45:05 +0000173 * Generate X as large as possible ( < P )
Paul Bakker5121ce52009-01-03 21:22:43 +0000174 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000175 do
176 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200177 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000178
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200179 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
180 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000181
182 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200183 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000184 }
185 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000186
Paul Bakkerff7fe672010-07-18 09:45:05 +0000187 /*
188 * Calculate GX = G^X mod P
189 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200190 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000191 &ctx->P , &ctx->RP ) );
192
Paul Bakker345a6fe2011-02-28 21:20:02 +0000193 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000194 return( ret );
195
Paul Bakker5121ce52009-01-03 21:22:43 +0000196 /*
197 * export P, G, GX
198 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100199#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100200 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100201 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
202 p + 2, \
203 ( n ) ) ); \
204 *p++ = (unsigned char)( ( n ) >> 8 ); \
205 *p++ = (unsigned char)( ( n ) ); \
206 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100207 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 n1 = mbedtls_mpi_size( &ctx->P );
210 n2 = mbedtls_mpi_size( &ctx->G );
211 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000212
213 p = output;
214 DHM_MPI_EXPORT( &ctx->P , n1 );
215 DHM_MPI_EXPORT( &ctx->G , n2 );
216 DHM_MPI_EXPORT( &ctx->GX, n3 );
217
Hanno Beckere71ad122017-09-28 10:32:25 +0100218 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000219
220 ctx->len = n1;
221
222cleanup:
223
224 if( ret != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100225 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000226
227 return( 0 );
228}
229
230/*
Hanno Becker8880e752017-10-04 13:15:08 +0100231 * Set prime modulus and generator
232 */
233int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
234 const mbedtls_mpi *P,
235 const mbedtls_mpi *G )
236{
Janos Follath24eed8d2019-11-22 13:21:35 +0000237 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500238 DHM_VALIDATE_RET( ctx != NULL );
239 DHM_VALIDATE_RET( P != NULL );
240 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100241
242 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
243 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
244 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100245 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) );
Hanno Becker8880e752017-10-04 13:15:08 +0100246 }
247
248 ctx->len = mbedtls_mpi_size( &ctx->P );
249 return( 0 );
250}
251
252/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000253 * Import the peer's public value G^Y
254 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000256 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000257{
Janos Follath24eed8d2019-11-22 13:21:35 +0000258 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500259 DHM_VALIDATE_RET( ctx != NULL );
260 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000261
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500262 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200263 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000264
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100266 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000267
268 return( 0 );
269}
270
271/*
272 * Create own private value X and export G^X
273 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200274int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000275 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000276 int (*f_rng)(void *, unsigned char *, size_t),
277 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000278{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000279 int ret, count = 0;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500280 DHM_VALIDATE_RET( ctx != NULL );
281 DHM_VALIDATE_RET( output != NULL );
282 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000283
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500284 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000286
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
288 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000289
Paul Bakker5121ce52009-01-03 21:22:43 +0000290 /*
291 * generate X and calculate GX = G^X mod P
292 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000293 do
294 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200295 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000296
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200297 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
298 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000299
300 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000302 }
303 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000304
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200305 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000306 &ctx->P , &ctx->RP ) );
307
Paul Bakker345a6fe2011-02-28 21:20:02 +0000308 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
309 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200311 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000312
313cleanup:
314
315 if( ret != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100316 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000317
318 return( 0 );
319}
320
321/*
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200322 * Pick a random R in the range [2, M) for blinding purposes
323 */
324static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
325 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
326{
327 int ret, count;
328
329 count = 0;
330 do
331 {
332 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
333
334 while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
335 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
336
337 if( count++ > 10 )
338 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
339 }
340 while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
341
342cleanup:
343 return( ret );
344}
345
346
347/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200348 * Use the blinding method and optimisation suggested in section 10 of:
349 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200350 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200351 * Berlin Heidelberg, 1996. p. 104-113.
352 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200354 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
355{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200356 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200357 mbedtls_mpi R;
358
359 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200360
361 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200362 * Don't use any blinding the first time a particular X is used,
363 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200364 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200365 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200366 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
368 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
369 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200370
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200371 return( 0 );
372 }
373
374 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200375 * Ok, we need blinding. Can we re-use existing values?
376 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200377 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200378 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200379 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
381 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200382
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
384 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200385
386 return( 0 );
387 }
388
389 /*
390 * We need to generate blinding values from scratch
391 */
392
393 /* Vi = random( 2, P-1 ) */
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200394 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200395
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200396 /* Vf = Vi^-X mod P
397 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
398 * then elevate to the Xth power. */
399 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
400 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
401 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
402 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
403 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
404 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200405
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 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 +0200407
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200408cleanup:
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200409 mbedtls_mpi_free( &R );
410
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200411 return( ret );
412}
413
414/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000415 * Derive and export the shared secret (G^Y)^X mod P
416 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200417int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100418 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200419 int (*f_rng)(void *, unsigned char *, size_t),
420 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000421{
Janos Follath24eed8d2019-11-22 13:21:35 +0000422 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423 mbedtls_mpi GYb;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500424 DHM_VALIDATE_RET( ctx != NULL );
425 DHM_VALIDATE_RET( output != NULL );
426 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200427
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500428 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000430
Paul Bakker345a6fe2011-02-28 21:20:02 +0000431 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000432 return( ret );
433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200435
436 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200437 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200438 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
440 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
441 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200442 }
443 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200444 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200445
446 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200447 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200448 &ctx->P, &ctx->RP ) );
449
450 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200451 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200452 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
454 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200455 }
456
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
461cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200462 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000463
464 if( ret != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100465 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467 return( 0 );
468}
469
470/*
471 * Free the components of a DHM key
472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000474{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500475 if( ctx == NULL )
476 return;
477
478 mbedtls_mpi_free( &ctx->pX );
479 mbedtls_mpi_free( &ctx->Vf );
480 mbedtls_mpi_free( &ctx->Vi );
481 mbedtls_mpi_free( &ctx->RP );
482 mbedtls_mpi_free( &ctx->K );
483 mbedtls_mpi_free( &ctx->GY );
484 mbedtls_mpi_free( &ctx->GX );
485 mbedtls_mpi_free( &ctx->X );
486 mbedtls_mpi_free( &ctx->G );
487 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200488
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500489 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000490}
491
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200492#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200493/*
494 * Parse DHM parameters
495 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200497 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200498{
Janos Follath24eed8d2019-11-22 13:21:35 +0000499 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200500 size_t len;
501 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502#if defined(MBEDTLS_PEM_PARSE_C)
503 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500504#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200505
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500506 DHM_VALIDATE_RET( dhm != NULL );
507 DHM_VALIDATE_RET( dhmin != NULL );
508
509#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200510 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200511
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200512 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200513 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200514 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
515 else
516 ret = mbedtls_pem_read_buffer( &pem,
517 "-----BEGIN DH PARAMETERS-----",
518 "-----END DH PARAMETERS-----",
519 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200520
521 if( ret == 0 )
522 {
523 /*
524 * Was PEM encoded
525 */
526 dhminlen = pem.buflen;
527 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200528 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200529 goto exit;
530
531 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
532#else
533 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200535 end = p + dhminlen;
536
537 /*
538 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400539 * prime INTEGER, -- P
540 * generator INTEGER, -- g
541 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200542 * }
543 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200544 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
545 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200546 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100547 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200548 goto exit;
549 }
550
551 end = p + len;
552
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
554 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200555 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100556 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200557 goto exit;
558 }
559
560 if( p != end )
561 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200562 /* This might be the optional privateValueLength.
563 * If so, we can cleanly discard it */
564 mbedtls_mpi rec;
565 mbedtls_mpi_init( &rec );
566 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
567 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400568 if ( ret != 0 )
569 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100570 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400571 goto exit;
572 }
573 if ( p != end )
574 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100575 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT,
576 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400577 goto exit;
578 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200579 }
580
581 ret = 0;
582
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100584
Paul Bakker40ce79f2013-09-15 17:43:54 +0200585exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586#if defined(MBEDTLS_PEM_PARSE_C)
587 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200588#endif
589 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200590 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200591
592 return( ret );
593}
594
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200595#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200596/*
597 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200598 *
599 * The file is expected to contain either PEM or DER encoded data.
600 * A terminating null byte is always appended. It is included in the announced
601 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200602 */
603static int load_file( const char *path, unsigned char **buf, size_t *n )
604{
605 FILE *f;
606 long size;
607
608 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200609 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200610
611 fseek( f, 0, SEEK_END );
612 if( ( size = ftell( f ) ) == -1 )
613 {
614 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200615 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200616 }
617 fseek( f, 0, SEEK_SET );
618
619 *n = (size_t) size;
620
621 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200622 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200623 {
624 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200625 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200626 }
627
628 if( fread( *buf, 1, *n, f ) != *n )
629 {
630 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100631
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500632 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200633 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200636 }
637
638 fclose( f );
639
640 (*buf)[*n] = '\0';
641
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200642 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
643 ++*n;
644
Paul Bakker40ce79f2013-09-15 17:43:54 +0200645 return( 0 );
646}
647
648/*
649 * Load and parse DHM parameters
650 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200651int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200652{
Janos Follath24eed8d2019-11-22 13:21:35 +0000653 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200654 size_t n;
655 unsigned char *buf;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500656 DHM_VALIDATE_RET( dhm != NULL );
657 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200658
Paul Bakker66d5d072014-06-17 16:39:18 +0200659 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200660 return( ret );
661
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200663
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500664 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200665 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200666
667 return( ret );
668}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669#endif /* MBEDTLS_FS_IO */
670#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000671#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200672
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200673#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000674
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100675#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200676static const char mbedtls_test_dhm_params[] =
677"-----BEGIN DH PARAMETERS-----\r\n"
678"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
679"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
680"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
681"-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100682#else /* MBEDTLS_PEM_PARSE_C */
683static const char mbedtls_test_dhm_params[] = {
684 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
685 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
686 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
687 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
688 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
689 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
690 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
691 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
692 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
693 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
694 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
695 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
696#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200697
698static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200699
Paul Bakker5121ce52009-01-03 21:22:43 +0000700/*
701 * Checkup routine
702 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200703int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000704{
Janos Follath24eed8d2019-11-22 13:21:35 +0000705 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200707
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200709
Paul Bakker40ce79f2013-09-15 17:43:54 +0200710 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200712
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200713 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
714 (const unsigned char *) mbedtls_test_dhm_params,
715 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200716 {
717 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200719
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200720 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200721 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200722 }
723
724 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200725 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200726
Paul Bakker8f870b02014-06-20 13:32:38 +0200727exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200729
Paul Bakker8f870b02014-06-20 13:32:38 +0200730 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000731}
732
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200733#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735#endif /* MBEDTLS_DHM_C */