blob: 1d4efc61d8550d3255cf7f976b1bec4cd4608108 [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
Gilles Peskinedb09ef62020-06-03 01:43:33 +020030#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#if defined(MBEDTLS_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000033
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/dhm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050035#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000036#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Rich Evans00ab4702015-02-06 13:43:58 +000038#include <string.h>
39
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000041#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020042#endif
43
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000045#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020046#endif
47
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000049#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020050#else
51#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000052#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020053#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020054#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#define mbedtls_free free
Paul Bakker40ce79f2013-09-15 17:43:54 +020056#endif
57
Reuven Levin1f35ca92017-12-07 10:09:32 +000058#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020059
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050060#define DHM_VALIDATE_RET( cond ) \
61 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
62#define DHM_VALIDATE( cond ) \
63 MBEDTLS_INTERNAL_VALIDATE( cond )
64
Paul Bakker5121ce52009-01-03 21:22:43 +000065/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020066 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000067 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +000069 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000070 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +000071{
72 int ret, n;
73
74 if( end - *p < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000076
77 n = ( (*p)[0] << 8 ) | (*p)[1];
78 (*p) += 2;
79
80 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000082
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
84 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +000085
86 (*p) += n;
87
88 return( 0 );
89}
90
91/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000092 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000093 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000094 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000095 *
Janos Follathaa325d72017-09-20 15:33:24 +010096 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +010097 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +010098 *
Paul Bakker345a6fe2011-02-28 21:20:02 +000099 * For more information on the attack, see:
100 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
101 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +0000102 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000104{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200105 mbedtls_mpi L, U;
Janos Follathaa325d72017-09-20 15:33:24 +0100106 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000107
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +0200109
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200110 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
111 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000112
Janos Follathaa325d72017-09-20 15:33:24 +0100113 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
114 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000115 {
Janos Follathaa325d72017-09-20 15:33:24 +0100116 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000117 }
118
Paul Bakker3d8fb632014-04-17 12:42:41 +0200119cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200120 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000121 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000122}
123
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200124void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200125{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500126 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200128}
129
Paul Bakkerc47840e2011-02-20 16:37:30 +0000130/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000131 * Parse the ServerKeyExchange parameters
132 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000135 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000136{
Janos Follath24eed8d2019-11-22 13:21:35 +0000137 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500138 DHM_VALIDATE_RET( ctx != NULL );
139 DHM_VALIDATE_RET( p != NULL && *p != NULL );
140 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000141
Paul Bakker5121ce52009-01-03 21:22:43 +0000142 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
143 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
144 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
145 return( ret );
146
Paul Bakker345a6fe2011-02-28 21:20:02 +0000147 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
148 return( ret );
149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000151
Paul Bakker5121ce52009-01-03 21:22:43 +0000152 return( 0 );
153}
154
155/*
156 * Setup and write the ServerKeyExchange parameters
157 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000159 unsigned char *output, size_t *olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000160 int (*f_rng)(void *, unsigned char *, size_t),
161 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000162{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000163 int ret, count = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000164 size_t n1, n2, n3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000165 unsigned char *p;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500166 DHM_VALIDATE_RET( ctx != NULL );
167 DHM_VALIDATE_RET( output != NULL );
168 DHM_VALIDATE_RET( olen != NULL );
169 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000170
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
172 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000173
Paul Bakker5121ce52009-01-03 21:22:43 +0000174 /*
Paul Bakkerff7fe672010-07-18 09:45:05 +0000175 * Generate X as large as possible ( < P )
Paul Bakker5121ce52009-01-03 21:22:43 +0000176 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000177 do
178 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200179 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
182 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000183
184 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000186 }
187 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000188
Paul Bakkerff7fe672010-07-18 09:45:05 +0000189 /*
190 * Calculate GX = G^X mod P
191 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200192 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000193 &ctx->P , &ctx->RP ) );
194
Paul Bakker345a6fe2011-02-28 21:20:02 +0000195 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000196 return( ret );
197
Paul Bakker5121ce52009-01-03 21:22:43 +0000198 /*
199 * export P, G, GX
200 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100201#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100202 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100203 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
204 p + 2, \
205 ( n ) ) ); \
206 *p++ = (unsigned char)( ( n ) >> 8 ); \
207 *p++ = (unsigned char)( ( n ) ); \
208 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100209 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000210
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211 n1 = mbedtls_mpi_size( &ctx->P );
212 n2 = mbedtls_mpi_size( &ctx->G );
213 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
215 p = output;
216 DHM_MPI_EXPORT( &ctx->P , n1 );
217 DHM_MPI_EXPORT( &ctx->G , n2 );
218 DHM_MPI_EXPORT( &ctx->GX, n3 );
219
Hanno Beckere71ad122017-09-28 10:32:25 +0100220 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000221
222 ctx->len = n1;
223
224cleanup:
225
226 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000228
229 return( 0 );
230}
231
232/*
Hanno Becker8880e752017-10-04 13:15:08 +0100233 * Set prime modulus and generator
234 */
235int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
236 const mbedtls_mpi *P,
237 const mbedtls_mpi *G )
238{
Janos Follath24eed8d2019-11-22 13:21:35 +0000239 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500240 DHM_VALIDATE_RET( ctx != NULL );
241 DHM_VALIDATE_RET( P != NULL );
242 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100243
244 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
245 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
246 {
247 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
248 }
249
250 ctx->len = mbedtls_mpi_size( &ctx->P );
251 return( 0 );
252}
253
254/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000255 * Import the peer's public value G^Y
256 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000258 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000259{
Janos Follath24eed8d2019-11-22 13:21:35 +0000260 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500261 DHM_VALIDATE_RET( ctx != NULL );
262 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000263
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500264 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200265 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
268 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000269
270 return( 0 );
271}
272
273/*
274 * Create own private value X and export G^X
275 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200276int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000277 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000278 int (*f_rng)(void *, unsigned char *, size_t),
279 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000280{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000281 int ret, count = 0;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500282 DHM_VALIDATE_RET( ctx != NULL );
283 DHM_VALIDATE_RET( output != NULL );
284 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000285
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500286 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200287 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000288
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200289 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
290 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000291
Paul Bakker5121ce52009-01-03 21:22:43 +0000292 /*
293 * generate X and calculate GX = G^X mod P
294 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000295 do
296 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200297 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000298
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200299 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
300 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000301
302 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200303 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000304 }
305 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000306
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200307 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000308 &ctx->P , &ctx->RP ) );
309
Paul Bakker345a6fe2011-02-28 21:20:02 +0000310 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
311 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000312
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200313 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000314
315cleanup:
316
317 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
320 return( 0 );
321}
322
323/*
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200324 * Pick a random R in the range [2, M) for blinding purposes
325 */
326static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
327 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
328{
329 int ret, count;
330
331 count = 0;
332 do
333 {
334 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
335
336 while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
337 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
338
339 if( count++ > 10 )
340 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
341 }
342 while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
343
344cleanup:
345 return( ret );
346}
347
348
349/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200350 * Use the blinding method and optimisation suggested in section 10 of:
351 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200352 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200353 * Berlin Heidelberg, 1996. p. 104-113.
354 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200355static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200356 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
357{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200358 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200359 mbedtls_mpi R;
360
361 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200362
363 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200364 * Don't use any blinding the first time a particular X is used,
365 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200366 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200368 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
370 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
371 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200372
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200373 return( 0 );
374 }
375
376 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200377 * Ok, we need blinding. Can we re-use existing values?
378 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
383 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
386 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200387
388 return( 0 );
389 }
390
391 /*
392 * We need to generate blinding values from scratch
393 */
394
395 /* Vi = random( 2, P-1 ) */
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200396 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200397
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200398 /* Vf = Vi^-X mod P
399 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
400 * then elevate to the Xth power. */
401 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
402 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
403 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
404 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
405 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
406 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200407
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200408 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 +0200409
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200410cleanup:
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200411 mbedtls_mpi_free( &R );
412
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200413 return( ret );
414}
415
416/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000417 * Derive and export the shared secret (G^Y)^X mod P
418 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200419int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100420 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200421 int (*f_rng)(void *, unsigned char *, size_t),
422 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000423{
Janos Follath24eed8d2019-11-22 13:21:35 +0000424 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 mbedtls_mpi GYb;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500426 DHM_VALIDATE_RET( ctx != NULL );
427 DHM_VALIDATE_RET( output != NULL );
428 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200429
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500430 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000432
Paul Bakker345a6fe2011-02-28 21:20:02 +0000433 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000434 return( ret );
435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200437
438 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200439 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200440 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
442 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
443 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200444 }
445 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200447
448 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200450 &ctx->P, &ctx->RP ) );
451
452 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200453 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200454 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
456 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200457 }
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000460
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200461 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000462
463cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000465
466 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200467 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000468
469 return( 0 );
470}
471
472/*
473 * Free the components of a DHM key
474 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200475void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000476{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500477 if( ctx == NULL )
478 return;
479
480 mbedtls_mpi_free( &ctx->pX );
481 mbedtls_mpi_free( &ctx->Vf );
482 mbedtls_mpi_free( &ctx->Vi );
483 mbedtls_mpi_free( &ctx->RP );
484 mbedtls_mpi_free( &ctx->K );
485 mbedtls_mpi_free( &ctx->GY );
486 mbedtls_mpi_free( &ctx->GX );
487 mbedtls_mpi_free( &ctx->X );
488 mbedtls_mpi_free( &ctx->G );
489 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200490
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500491 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000492}
493
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200494#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200495/*
496 * Parse DHM parameters
497 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200499 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200500{
Janos Follath24eed8d2019-11-22 13:21:35 +0000501 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200502 size_t len;
503 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200504#if defined(MBEDTLS_PEM_PARSE_C)
505 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500506#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200507
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500508 DHM_VALIDATE_RET( dhm != NULL );
509 DHM_VALIDATE_RET( dhmin != NULL );
510
511#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200513
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200514 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200515 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200516 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
517 else
518 ret = mbedtls_pem_read_buffer( &pem,
519 "-----BEGIN DH PARAMETERS-----",
520 "-----END DH PARAMETERS-----",
521 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200522
523 if( ret == 0 )
524 {
525 /*
526 * Was PEM encoded
527 */
528 dhminlen = pem.buflen;
529 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200531 goto exit;
532
533 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
534#else
535 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200536#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200537 end = p + dhminlen;
538
539 /*
540 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400541 * prime INTEGER, -- P
542 * generator INTEGER, -- g
543 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200544 * }
545 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
547 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200548 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200549 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200550 goto exit;
551 }
552
553 end = p + len;
554
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
556 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200557 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200559 goto exit;
560 }
561
562 if( p != end )
563 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200564 /* This might be the optional privateValueLength.
565 * If so, we can cleanly discard it */
566 mbedtls_mpi rec;
567 mbedtls_mpi_init( &rec );
568 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
569 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400570 if ( ret != 0 )
571 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200572 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400573 goto exit;
574 }
575 if ( p != end )
576 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200577 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
578 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400579 goto exit;
580 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200581 }
582
583 ret = 0;
584
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100586
Paul Bakker40ce79f2013-09-15 17:43:54 +0200587exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200588#if defined(MBEDTLS_PEM_PARSE_C)
589 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200590#endif
591 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200593
594 return( ret );
595}
596
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200598/*
599 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200600 *
601 * The file is expected to contain either PEM or DER encoded data.
602 * A terminating null byte is always appended. It is included in the announced
603 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200604 */
605static int load_file( const char *path, unsigned char **buf, size_t *n )
606{
607 FILE *f;
608 long size;
609
610 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200611 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200612
613 fseek( f, 0, SEEK_END );
614 if( ( size = ftell( f ) ) == -1 )
615 {
616 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200617 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200618 }
619 fseek( f, 0, SEEK_SET );
620
621 *n = (size_t) size;
622
623 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200624 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200625 {
626 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200627 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200628 }
629
630 if( fread( *buf, 1, *n, f ) != *n )
631 {
632 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100633
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500634 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100636
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200637 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200638 }
639
640 fclose( f );
641
642 (*buf)[*n] = '\0';
643
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200644 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
645 ++*n;
646
Paul Bakker40ce79f2013-09-15 17:43:54 +0200647 return( 0 );
648}
649
650/*
651 * Load and parse DHM parameters
652 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200653int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200654{
Janos Follath24eed8d2019-11-22 13:21:35 +0000655 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200656 size_t n;
657 unsigned char *buf;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500658 DHM_VALIDATE_RET( dhm != NULL );
659 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200660
Paul Bakker66d5d072014-06-17 16:39:18 +0200661 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200662 return( ret );
663
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200665
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500666 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200667 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200668
669 return( ret );
670}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671#endif /* MBEDTLS_FS_IO */
672#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000673#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200674
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100677#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200678static const char mbedtls_test_dhm_params[] =
679"-----BEGIN DH PARAMETERS-----\r\n"
680"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
681"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
682"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
683"-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100684#else /* MBEDTLS_PEM_PARSE_C */
685static const char mbedtls_test_dhm_params[] = {
686 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
687 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
688 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
689 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
690 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
691 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
692 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
693 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
694 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
695 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
696 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
697 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
698#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200699
700static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200701
Paul Bakker5121ce52009-01-03 21:22:43 +0000702/*
703 * Checkup routine
704 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000706{
Janos Follath24eed8d2019-11-22 13:21:35 +0000707 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200708 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200709
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200711
Paul Bakker40ce79f2013-09-15 17:43:54 +0200712 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200713 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200714
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200715 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
716 (const unsigned char *) mbedtls_test_dhm_params,
717 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200718 {
719 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200720 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200721
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200722 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200723 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200724 }
725
726 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200727 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200728
Paul Bakker8f870b02014-06-20 13:32:38 +0200729exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200730 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200731
Paul Bakker8f870b02014-06-20 13:32:38 +0200732 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000733}
734
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200735#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000736
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200737#endif /* MBEDTLS_DHM_C */