blob: f9c55892a01be450833d5201a1ed3cbe485f7d0b [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Diffie-Hellman-Merkle key exchange
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
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 Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
21/*
Simon Butcherbdae02c2016-01-20 00:44:42 +000022 * The following sources were referenced in the design of this implementation
23 * of the Diffie-Hellman-Merkle algorithm:
Paul Bakker5121ce52009-01-03 21:22:43 +000024 *
Simon Butcherbdae02c2016-01-20 00:44:42 +000025 * [1] Handbook of Applied Cryptography - 1997, Chapter 12
26 * Menezes, van Oorschot and Vanstone
27 *
Paul Bakker5121ce52009-01-03 21:22:43 +000028 */
29
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020033#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020034#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020036#if defined(MBEDTLS_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000038#include "mbedtls/dhm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050039#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000040#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000041
Rich Evans00ab4702015-02-06 13:43:58 +000042#include <string.h>
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020046#endif
47
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020050#endif
51
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020052#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000053#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020054#else
55#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000056#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020058#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020059#define mbedtls_free free
Paul Bakker40ce79f2013-09-15 17:43:54 +020060#endif
61
Reuven Levin1f35ca92017-12-07 10:09:32 +000062#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020063
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050064#define DHM_VALIDATE_RET( cond ) \
65 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
66#define DHM_VALIDATE( cond ) \
67 MBEDTLS_INTERNAL_VALIDATE( cond )
68
Paul Bakker5121ce52009-01-03 21:22:43 +000069/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000071 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +000073 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000074 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +000075{
76 int ret, n;
77
78 if( end - *p < 2 )
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
81 n = ( (*p)[0] << 8 ) | (*p)[1];
82 (*p) += 2;
83
84 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020085 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000086
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
88 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +000089
90 (*p) += n;
91
92 return( 0 );
93}
94
95/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000096 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000097 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000098 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000099 *
Janos Follathaa325d72017-09-20 15:33:24 +0100100 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +0100101 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +0100102 *
Paul Bakker345a6fe2011-02-28 21:20:02 +0000103 * For more information on the attack, see:
104 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
105 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +0000106 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000108{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 mbedtls_mpi L, U;
Janos Follathaa325d72017-09-20 15:33:24 +0100110 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000111
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200112 mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +0200113
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200114 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
115 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000116
Janos Follathaa325d72017-09-20 15:33:24 +0100117 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
118 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000119 {
Janos Follathaa325d72017-09-20 15:33:24 +0100120 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000121 }
122
Paul Bakker3d8fb632014-04-17 12:42:41 +0200123cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000125 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000126}
127
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200128void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200129{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500130 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200132}
133
Paul Bakkerc47840e2011-02-20 16:37:30 +0000134/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000135 * Parse the ServerKeyExchange parameters
136 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200137int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000138 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000139 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000140{
Janos Follath24eed8d2019-11-22 13:21:35 +0000141 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500142 DHM_VALIDATE_RET( ctx != NULL );
143 DHM_VALIDATE_RET( p != NULL && *p != NULL );
144 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000145
Paul Bakker5121ce52009-01-03 21:22:43 +0000146 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
147 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
148 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
149 return( ret );
150
Paul Bakker345a6fe2011-02-28 21:20:02 +0000151 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
152 return( ret );
153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000155
Paul Bakker5121ce52009-01-03 21:22:43 +0000156 return( 0 );
157}
158
159/*
160 * Setup and write the ServerKeyExchange parameters
161 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200162int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000163 unsigned char *output, size_t *olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000164 int (*f_rng)(void *, unsigned char *, size_t),
165 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000166{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000167 int ret, count = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000168 size_t n1, n2, n3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000169 unsigned char *p;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500170 DHM_VALIDATE_RET( ctx != NULL );
171 DHM_VALIDATE_RET( output != NULL );
172 DHM_VALIDATE_RET( olen != NULL );
173 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
176 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000177
Paul Bakker5121ce52009-01-03 21:22:43 +0000178 /*
Paul Bakkerff7fe672010-07-18 09:45:05 +0000179 * Generate X as large as possible ( < P )
Paul Bakker5121ce52009-01-03 21:22:43 +0000180 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000181 do
182 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200183 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
186 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000187
188 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000190 }
191 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000192
Paul Bakkerff7fe672010-07-18 09:45:05 +0000193 /*
194 * Calculate GX = G^X mod P
195 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200196 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000197 &ctx->P , &ctx->RP ) );
198
Paul Bakker345a6fe2011-02-28 21:20:02 +0000199 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000200 return( ret );
201
Paul Bakker5121ce52009-01-03 21:22:43 +0000202 /*
203 * export P, G, GX
204 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100205#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100206 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100207 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
208 p + 2, \
209 ( n ) ) ); \
210 *p++ = (unsigned char)( ( n ) >> 8 ); \
211 *p++ = (unsigned char)( ( n ) ); \
212 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100213 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200215 n1 = mbedtls_mpi_size( &ctx->P );
216 n2 = mbedtls_mpi_size( &ctx->G );
217 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000218
219 p = output;
220 DHM_MPI_EXPORT( &ctx->P , n1 );
221 DHM_MPI_EXPORT( &ctx->G , n2 );
222 DHM_MPI_EXPORT( &ctx->GX, n3 );
223
Hanno Beckere71ad122017-09-28 10:32:25 +0100224 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000225
226 ctx->len = n1;
227
228cleanup:
229
230 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200231 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000232
233 return( 0 );
234}
235
236/*
Hanno Becker8880e752017-10-04 13:15:08 +0100237 * Set prime modulus and generator
238 */
239int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
240 const mbedtls_mpi *P,
241 const mbedtls_mpi *G )
242{
Janos Follath24eed8d2019-11-22 13:21:35 +0000243 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500244 DHM_VALIDATE_RET( ctx != NULL );
245 DHM_VALIDATE_RET( P != NULL );
246 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100247
248 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
249 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
250 {
251 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
252 }
253
254 ctx->len = mbedtls_mpi_size( &ctx->P );
255 return( 0 );
256}
257
258/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000259 * Import the peer's public value G^Y
260 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200261int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000262 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000263{
Janos Follath24eed8d2019-11-22 13:21:35 +0000264 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500265 DHM_VALIDATE_RET( ctx != NULL );
266 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000267
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500268 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200269 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000270
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
272 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000273
274 return( 0 );
275}
276
277/*
278 * Create own private value X and export G^X
279 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000281 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000282 int (*f_rng)(void *, unsigned char *, size_t),
283 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000284{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000285 int ret, count = 0;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500286 DHM_VALIDATE_RET( ctx != NULL );
287 DHM_VALIDATE_RET( output != NULL );
288 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000289
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500290 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200291 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000292
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
294 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000295
Paul Bakker5121ce52009-01-03 21:22:43 +0000296 /*
297 * generate X and calculate GX = G^X mod P
298 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000299 do
300 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200301 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000302
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
304 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000305
306 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000308 }
309 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000310
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200311 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000312 &ctx->P , &ctx->RP ) );
313
Paul Bakker345a6fe2011-02-28 21:20:02 +0000314 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
315 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000318
319cleanup:
320
321 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000323
324 return( 0 );
325}
326
327/*
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200328 * Pick a random R in the range [2, M) for blinding purposes
329 */
330static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
331 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
332{
333 int ret, count;
334
335 count = 0;
336 do
337 {
338 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
339
340 while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
341 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
342
343 if( count++ > 10 )
344 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
345 }
346 while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
347
348cleanup:
349 return( ret );
350}
351
352
353/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200354 * Use the blinding method and optimisation suggested in section 10 of:
355 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200356 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200357 * Berlin Heidelberg, 1996. p. 104-113.
358 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200360 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
361{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200362 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200363 mbedtls_mpi R;
364
365 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200366
367 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200368 * Don't use any blinding the first time a particular X is used,
369 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200370 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200371 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200372 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200373 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
374 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
375 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200376
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200377 return( 0 );
378 }
379
380 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200381 * Ok, we need blinding. Can we re-use existing values?
382 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200383 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200385 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200386 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
387 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200388
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
390 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200391
392 return( 0 );
393 }
394
395 /*
396 * We need to generate blinding values from scratch
397 */
398
399 /* Vi = random( 2, P-1 ) */
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200400 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200401
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200402 /* Vf = Vi^-X mod P
403 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
404 * then elevate to the Xth power. */
405 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
406 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
407 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
408 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
409 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
410 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
411
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200412 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 +0200413
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200414cleanup:
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200415 mbedtls_mpi_free( &R );
416
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200417 return( ret );
418}
419
420/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000421 * Derive and export the shared secret (G^Y)^X mod P
422 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100424 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200425 int (*f_rng)(void *, unsigned char *, size_t),
426 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000427{
Janos Follath24eed8d2019-11-22 13:21:35 +0000428 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200429 mbedtls_mpi GYb;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500430 DHM_VALIDATE_RET( ctx != NULL );
431 DHM_VALIDATE_RET( output != NULL );
432 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200433
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500434 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000436
Paul Bakker345a6fe2011-02-28 21:20:02 +0000437 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000438 return( ret );
439
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200440 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200441
442 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200443 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200444 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
446 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
447 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200448 }
449 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200451
452 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200453 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200454 &ctx->P, &ctx->RP ) );
455
456 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200457 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200458 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
460 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200461 }
462
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200463 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
467cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000469
470 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
473 return( 0 );
474}
475
476/*
477 * Free the components of a DHM key
478 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000480{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500481 if( ctx == NULL )
482 return;
483
484 mbedtls_mpi_free( &ctx->pX );
485 mbedtls_mpi_free( &ctx->Vf );
486 mbedtls_mpi_free( &ctx->Vi );
487 mbedtls_mpi_free( &ctx->RP );
488 mbedtls_mpi_free( &ctx->K );
489 mbedtls_mpi_free( &ctx->GY );
490 mbedtls_mpi_free( &ctx->GX );
491 mbedtls_mpi_free( &ctx->X );
492 mbedtls_mpi_free( &ctx->G );
493 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200494
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500495 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000496}
497
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200499/*
500 * Parse DHM parameters
501 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200502int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200503 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200504{
Janos Follath24eed8d2019-11-22 13:21:35 +0000505 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200506 size_t len;
507 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508#if defined(MBEDTLS_PEM_PARSE_C)
509 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500510#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200511
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500512 DHM_VALIDATE_RET( dhm != NULL );
513 DHM_VALIDATE_RET( dhmin != NULL );
514
515#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200516 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200517
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200518 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200519 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200520 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
521 else
522 ret = mbedtls_pem_read_buffer( &pem,
523 "-----BEGIN DH PARAMETERS-----",
524 "-----END DH PARAMETERS-----",
525 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200526
527 if( ret == 0 )
528 {
529 /*
530 * Was PEM encoded
531 */
532 dhminlen = pem.buflen;
533 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200534 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200535 goto exit;
536
537 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
538#else
539 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200540#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200541 end = p + dhminlen;
542
543 /*
544 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400545 * prime INTEGER, -- P
546 * generator INTEGER, -- g
547 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200548 * }
549 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
551 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200552 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200553 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200554 goto exit;
555 }
556
557 end = p + len;
558
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200559 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
560 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200561 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200562 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200563 goto exit;
564 }
565
566 if( p != end )
567 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200568 /* This might be the optional privateValueLength.
569 * If so, we can cleanly discard it */
570 mbedtls_mpi rec;
571 mbedtls_mpi_init( &rec );
572 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
573 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400574 if ( ret != 0 )
575 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200576 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400577 goto exit;
578 }
579 if ( p != end )
580 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200581 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
582 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400583 goto exit;
584 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200585 }
586
587 ret = 0;
588
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100590
Paul Bakker40ce79f2013-09-15 17:43:54 +0200591exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592#if defined(MBEDTLS_PEM_PARSE_C)
593 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200594#endif
595 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200596 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200597
598 return( ret );
599}
600
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200602/*
603 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200604 *
605 * The file is expected to contain either PEM or DER encoded data.
606 * A terminating null byte is always appended. It is included in the announced
607 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200608 */
609static int load_file( const char *path, unsigned char **buf, size_t *n )
610{
611 FILE *f;
612 long size;
613
614 if( ( f = fopen( path, "rb" ) ) == NULL )
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_END );
618 if( ( size = ftell( f ) ) == -1 )
619 {
620 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200621 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200622 }
623 fseek( f, 0, SEEK_SET );
624
625 *n = (size_t) size;
626
627 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200628 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200629 {
630 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200631 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200632 }
633
634 if( fread( *buf, 1, *n, f ) != *n )
635 {
636 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100637
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500638 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100640
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200642 }
643
644 fclose( f );
645
646 (*buf)[*n] = '\0';
647
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200648 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
649 ++*n;
650
Paul Bakker40ce79f2013-09-15 17:43:54 +0200651 return( 0 );
652}
653
654/*
655 * Load and parse DHM parameters
656 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200657int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200658{
Janos Follath24eed8d2019-11-22 13:21:35 +0000659 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200660 size_t n;
661 unsigned char *buf;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500662 DHM_VALIDATE_RET( dhm != NULL );
663 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200664
Paul Bakker66d5d072014-06-17 16:39:18 +0200665 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200666 return( ret );
667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200669
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500670 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200672
673 return( ret );
674}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675#endif /* MBEDTLS_FS_IO */
676#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000677#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200678
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200679#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000680
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100681#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200682static const char mbedtls_test_dhm_params[] =
683"-----BEGIN DH PARAMETERS-----\r\n"
684"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
685"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
686"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
687"-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100688#else /* MBEDTLS_PEM_PARSE_C */
689static const char mbedtls_test_dhm_params[] = {
690 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
691 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
692 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
693 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
694 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
695 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
696 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
697 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
698 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
699 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
700 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
701 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
702#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200703
704static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200705
Paul Bakker5121ce52009-01-03 21:22:43 +0000706/*
707 * Checkup routine
708 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000710{
Janos Follath24eed8d2019-11-22 13:21:35 +0000711 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200715
Paul Bakker40ce79f2013-09-15 17:43:54 +0200716 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200718
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200719 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
720 (const unsigned char *) mbedtls_test_dhm_params,
721 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200722 {
723 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200725
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200726 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200727 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200728 }
729
730 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200731 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200732
Paul Bakker8f870b02014-06-20 13:32:38 +0200733exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200734 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200735
Paul Bakker8f870b02014-06-20 13:32:38 +0200736 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000737}
738
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200739#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000740
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200741#endif /* MBEDTLS_DHM_C */