blob: 7168f26c2bf49765abafaa5692cdfc42198427d3 [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
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200153/*
154 * Pick a random R in the range [2, M) for blinding or key generation.
155 */
156static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
157 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
158{
159 int ret, count;
160
161 count = 0;
162 do
163 {
164 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
165
166 while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
167 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
168
169 if( count++ > 10 )
170 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
171 }
172 while( dhm_check_range( R, M ) != 0 );
173
174cleanup:
175 return( ret );
176}
177
Gilles Peskine0853bb22021-03-31 22:35:13 +0200178static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
179 int (*f_rng)(void *, unsigned char *, size_t),
180 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200182 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
185 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200186 if( x_size < 0 )
187 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000188
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200189 if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000190 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200191 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000192 }
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200193 else
194 {
195 /* Generate X as large as possible ( <= P - 2 ) */
196 ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
197 if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
198 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
199 if( ret != 0 )
200 return( ret );
201 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000202
Paul Bakkerff7fe672010-07-18 09:45:05 +0000203 /*
204 * Calculate GX = G^X mod P
205 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200206 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000207 &ctx->P , &ctx->RP ) );
208
Paul Bakker345a6fe2011-02-28 21:20:02 +0000209 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000210 return( ret );
211
Gilles Peskine0853bb22021-03-31 22:35:13 +0200212cleanup:
213 return( ret );
214}
215
216/*
217 * Setup and write the ServerKeyExchange parameters
218 */
219int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
220 unsigned char *output, size_t *olen,
221 int (*f_rng)(void *, unsigned char *, size_t),
222 void *p_rng )
223{
224 int ret;
225 size_t n1, n2, n3;
226 unsigned char *p;
227 DHM_VALIDATE_RET( ctx != NULL );
228 DHM_VALIDATE_RET( output != NULL );
229 DHM_VALIDATE_RET( olen != NULL );
230 DHM_VALIDATE_RET( f_rng != NULL );
231
232 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
233 if( ret != 0 )
234 goto cleanup;
235
Paul Bakker5121ce52009-01-03 21:22:43 +0000236 /*
237 * export P, G, GX
238 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100239#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100240 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100241 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
242 p + 2, \
243 ( n ) ) ); \
244 *p++ = (unsigned char)( ( n ) >> 8 ); \
245 *p++ = (unsigned char)( ( n ) ); \
246 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100247 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249 n1 = mbedtls_mpi_size( &ctx->P );
250 n2 = mbedtls_mpi_size( &ctx->G );
251 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000252
253 p = output;
254 DHM_MPI_EXPORT( &ctx->P , n1 );
255 DHM_MPI_EXPORT( &ctx->G , n2 );
256 DHM_MPI_EXPORT( &ctx->GX, n3 );
257
Hanno Beckere71ad122017-09-28 10:32:25 +0100258 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000259
260 ctx->len = n1;
261
262cleanup:
Gilles Peskine0853bb22021-03-31 22:35:13 +0200263 if( ret != 0 && ret > -128 )
264 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret );
265 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266}
267
268/*
Hanno Becker8880e752017-10-04 13:15:08 +0100269 * Set prime modulus and generator
270 */
271int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
272 const mbedtls_mpi *P,
273 const mbedtls_mpi *G )
274{
Janos Follath24eed8d2019-11-22 13:21:35 +0000275 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500276 DHM_VALIDATE_RET( ctx != NULL );
277 DHM_VALIDATE_RET( P != NULL );
278 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100279
280 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
281 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
282 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100283 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) );
Hanno Becker8880e752017-10-04 13:15:08 +0100284 }
285
286 ctx->len = mbedtls_mpi_size( &ctx->P );
287 return( 0 );
288}
289
290/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000291 * Import the peer's public value G^Y
292 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000294 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000295{
Janos Follath24eed8d2019-11-22 13:21:35 +0000296 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500297 DHM_VALIDATE_RET( ctx != NULL );
298 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000299
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500300 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200301 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100304 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000305
306 return( 0 );
307}
308
309/*
310 * Create own private value X and export G^X
311 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000313 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000314 int (*f_rng)(void *, unsigned char *, size_t),
315 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000316{
Gilles Peskine0853bb22021-03-31 22:35:13 +0200317 int ret;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500318 DHM_VALIDATE_RET( ctx != NULL );
319 DHM_VALIDATE_RET( output != NULL );
320 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000321
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500322 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200323 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000324
Gilles Peskine0853bb22021-03-31 22:35:13 +0200325 ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
326 if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
327 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
328 if( ret != 0 )
329 goto cleanup;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000330
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000332
333cleanup:
Gilles Peskine0853bb22021-03-31 22:35:13 +0200334 if( ret != 0 && ret > -128 )
335 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret );
336 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000337}
338
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200339
340/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200341 * Use the blinding method and optimisation suggested in section 10 of:
342 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200343 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200344 * Berlin Heidelberg, 1996. p. 104-113.
345 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200347 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
348{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200349 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200350 mbedtls_mpi R;
351
352 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200353
354 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200355 * Don't use any blinding the first time a particular X is used,
356 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200357 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200358 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200359 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200360 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
361 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
362 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200363
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200364 return( 0 );
365 }
366
367 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200368 * Ok, we need blinding. Can we re-use existing values?
369 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200370 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200372 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
374 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200375
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200376 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
377 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200378
379 return( 0 );
380 }
381
382 /*
383 * We need to generate blinding values from scratch
384 */
385
Gilles Peskineb4e815f2021-03-31 22:50:57 +0200386 /* Vi = random( 2, P-2 ) */
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200387 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200388
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200389 /* Vf = Vi^-X mod P
390 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
391 * then elevate to the Xth power. */
392 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
393 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
394 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
395 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
396 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
397 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
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_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200400
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200401cleanup:
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200402 mbedtls_mpi_free( &R );
403
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200404 return( ret );
405}
406
407/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000408 * Derive and export the shared secret (G^Y)^X mod P
409 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100411 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200412 int (*f_rng)(void *, unsigned char *, size_t),
413 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000414{
Janos Follath24eed8d2019-11-22 13:21:35 +0000415 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416 mbedtls_mpi GYb;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500417 DHM_VALIDATE_RET( ctx != NULL );
418 DHM_VALIDATE_RET( output != NULL );
419 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200420
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500421 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200422 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000423
Paul Bakker345a6fe2011-02-28 21:20:02 +0000424 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000425 return( ret );
426
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200427 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200428
429 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200430 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200431 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
433 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
434 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200435 }
436 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200438
439 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200441 &ctx->P, &ctx->RP ) );
442
443 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200444 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200445 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
447 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200448 }
449
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200452 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000453
454cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000456
457 if( ret != 0 )
Chris Jones9f7a6932021-04-14 12:12:09 +0100458 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000459
460 return( 0 );
461}
462
463/*
464 * Free the components of a DHM key
465 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000467{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500468 if( ctx == NULL )
469 return;
470
471 mbedtls_mpi_free( &ctx->pX );
472 mbedtls_mpi_free( &ctx->Vf );
473 mbedtls_mpi_free( &ctx->Vi );
474 mbedtls_mpi_free( &ctx->RP );
475 mbedtls_mpi_free( &ctx->K );
476 mbedtls_mpi_free( &ctx->GY );
477 mbedtls_mpi_free( &ctx->GX );
478 mbedtls_mpi_free( &ctx->X );
479 mbedtls_mpi_free( &ctx->G );
480 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200481
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500482 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483}
484
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200486/*
487 * Parse DHM parameters
488 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200489int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200490 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200491{
Janos Follath24eed8d2019-11-22 13:21:35 +0000492 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200493 size_t len;
494 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495#if defined(MBEDTLS_PEM_PARSE_C)
496 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500497#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200498
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500499 DHM_VALIDATE_RET( dhm != NULL );
500 DHM_VALIDATE_RET( dhmin != NULL );
501
502#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200503 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200504
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200505 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200506 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200507 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
508 else
509 ret = mbedtls_pem_read_buffer( &pem,
510 "-----BEGIN DH PARAMETERS-----",
511 "-----END DH PARAMETERS-----",
512 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200513
514 if( ret == 0 )
515 {
516 /*
517 * Was PEM encoded
518 */
519 dhminlen = pem.buflen;
520 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200522 goto exit;
523
524 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
525#else
526 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200528 end = p + dhminlen;
529
530 /*
531 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400532 * prime INTEGER, -- P
533 * generator INTEGER, -- g
534 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200535 * }
536 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200537 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
538 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 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 end = p + len;
545
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
547 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200548 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100549 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200550 goto exit;
551 }
552
553 if( p != end )
554 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200555 /* This might be the optional privateValueLength.
556 * If so, we can cleanly discard it */
557 mbedtls_mpi rec;
558 mbedtls_mpi_init( &rec );
559 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
560 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400561 if ( ret != 0 )
562 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100563 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400564 goto exit;
565 }
566 if ( p != end )
567 {
Chris Jones9f7a6932021-04-14 12:12:09 +0100568 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT,
569 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400570 goto exit;
571 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200572 }
573
574 ret = 0;
575
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200576 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100577
Paul Bakker40ce79f2013-09-15 17:43:54 +0200578exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200579#if defined(MBEDTLS_PEM_PARSE_C)
580 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200581#endif
582 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200583 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200584
585 return( ret );
586}
587
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200589/*
590 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200591 *
592 * The file is expected to contain either PEM or DER encoded data.
593 * A terminating null byte is always appended. It is included in the announced
594 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200595 */
596static int load_file( const char *path, unsigned char **buf, size_t *n )
597{
598 FILE *f;
599 long size;
600
601 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200602 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200603
604 fseek( f, 0, SEEK_END );
605 if( ( size = ftell( f ) ) == -1 )
606 {
607 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200609 }
610 fseek( f, 0, SEEK_SET );
611
612 *n = (size_t) size;
613
614 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200615 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200616 {
617 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200618 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200619 }
620
621 if( fread( *buf, 1, *n, f ) != *n )
622 {
623 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100624
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500625 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100627
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200629 }
630
631 fclose( f );
632
633 (*buf)[*n] = '\0';
634
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200635 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
636 ++*n;
637
Paul Bakker40ce79f2013-09-15 17:43:54 +0200638 return( 0 );
639}
640
641/*
642 * Load and parse DHM parameters
643 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200645{
Janos Follath24eed8d2019-11-22 13:21:35 +0000646 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200647 size_t n;
648 unsigned char *buf;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500649 DHM_VALIDATE_RET( dhm != NULL );
650 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200651
Paul Bakker66d5d072014-06-17 16:39:18 +0200652 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200653 return( ret );
654
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200655 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200656
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500657 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200659
660 return( ret );
661}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662#endif /* MBEDTLS_FS_IO */
663#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000664#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200665
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000667
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100668#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200669static const char mbedtls_test_dhm_params[] =
670"-----BEGIN DH PARAMETERS-----\r\n"
671"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
672"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
673"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
674"-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100675#else /* MBEDTLS_PEM_PARSE_C */
676static const char mbedtls_test_dhm_params[] = {
677 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
678 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
679 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
680 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
681 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
682 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
683 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
684 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
685 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
686 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
687 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
688 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
689#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200690
691static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200692
Paul Bakker5121ce52009-01-03 21:22:43 +0000693/*
694 * Checkup routine
695 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200696int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000697{
Janos Follath24eed8d2019-11-22 13:21:35 +0000698 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200700
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200701 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200702
Paul Bakker40ce79f2013-09-15 17:43:54 +0200703 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200704 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200705
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200706 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
707 (const unsigned char *) mbedtls_test_dhm_params,
708 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200709 {
710 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200712
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200713 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200714 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200715 }
716
717 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200718 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200719
Paul Bakker8f870b02014-06-20 13:32:38 +0200720exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200722
Paul Bakker8f870b02014-06-20 13:32:38 +0200723 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000724}
725
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200726#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000727
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200728#endif /* MBEDTLS_DHM_C */