blob: d7ceb770d587719573676d0f38bf56b321b04225 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Diffie-Hellman-Merkle key exchange
3 *
Bence Szépkútia2947ac2020-08-19 16:37:36 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkútif744bd72020-06-05 13:02:18 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +020012 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000024 *
Bence Szépkútif744bd72020-06-05 13:02:18 +020025 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
Paul Bakker5121ce52009-01-03 21:22:43 +000045 */
46/*
Simon Butcherbdae02c2016-01-20 00:44:42 +000047 * The following sources were referenced in the design of this implementation
48 * of the Diffie-Hellman-Merkle algorithm:
Paul Bakker5121ce52009-01-03 21:22:43 +000049 *
Simon Butcherbdae02c2016-01-20 00:44:42 +000050 * [1] Handbook of Applied Cryptography - 1997, Chapter 12
51 * Menezes, van Oorschot and Vanstone
52 *
Paul Bakker5121ce52009-01-03 21:22:43 +000053 */
54
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000056#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020057#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020059#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000060
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020061#if defined(MBEDTLS_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000062
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000063#include "mbedtls/dhm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050064#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000065
Rich Evans00ab4702015-02-06 13:43:58 +000066#include <string.h>
67
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000069#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020070#endif
71
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000073#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020074#endif
75
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020076#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000077#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020078#else
79#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000080#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020081#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020082#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020083#define mbedtls_free free
Paul Bakker40ce79f2013-09-15 17:43:54 +020084#endif
85
Reuven Levin1f35ca92017-12-07 10:09:32 +000086#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020087
Hanno Becker5c14ed62018-12-12 19:44:47 +000088#define DHM_VALIDATE_RET( cond ) \
89 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
90#define DHM_VALIDATE( cond ) \
91 MBEDTLS_INTERNAL_VALIDATE( cond )
92
Paul Bakker5121ce52009-01-03 21:22:43 +000093/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000095 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020096static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +000097 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000098 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +000099{
100 int ret, n;
101
102 if( end - *p < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200103 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000104
105 n = ( (*p)[0] << 8 ) | (*p)[1];
106 (*p) += 2;
107
108 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
112 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000113
114 (*p) += n;
115
116 return( 0 );
117}
118
119/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000120 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +0000121 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000122 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +0000123 *
Janos Follathaa325d72017-09-20 15:33:24 +0100124 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +0100125 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +0100126 *
Paul Bakker345a6fe2011-02-28 21:20:02 +0000127 * For more information on the attack, see:
128 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
129 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +0000130 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000132{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200133 mbedtls_mpi L, U;
Janos Follathaa325d72017-09-20 15:33:24 +0100134 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +0200137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
139 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000140
Janos Follathaa325d72017-09-20 15:33:24 +0100141 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
142 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000143 {
Janos Follathaa325d72017-09-20 15:33:24 +0100144 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000145 }
146
Paul Bakker3d8fb632014-04-17 12:42:41 +0200147cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000149 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000150}
151
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200153{
Hanno Becker5c14ed62018-12-12 19:44:47 +0000154 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200155 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200156}
157
Paul Bakkerc47840e2011-02-20 16:37:30 +0000158/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000159 * Parse the ServerKeyExchange parameters
160 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000162 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000163 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000164{
Paul Bakker13ed9ab2012-04-16 09:43:49 +0000165 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000166 DHM_VALIDATE_RET( ctx != NULL );
167 DHM_VALIDATE_RET( p != NULL && *p != NULL );
168 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000169
Paul Bakker5121ce52009-01-03 21:22:43 +0000170 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
171 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
172 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
173 return( ret );
174
Paul Bakker345a6fe2011-02-28 21:20:02 +0000175 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
176 return( ret );
177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000179
Paul Bakker5121ce52009-01-03 21:22:43 +0000180 return( 0 );
181}
182
183/*
184 * Setup and write the ServerKeyExchange parameters
185 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000187 unsigned char *output, size_t *olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000188 int (*f_rng)(void *, unsigned char *, size_t),
189 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000190{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000191 int ret, count = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000192 size_t n1, n2, n3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000193 unsigned char *p;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000194 DHM_VALIDATE_RET( ctx != NULL );
195 DHM_VALIDATE_RET( output != NULL );
196 DHM_VALIDATE_RET( olen != NULL );
197 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
200 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000201
Paul Bakker5121ce52009-01-03 21:22:43 +0000202 /*
Paul Bakkerff7fe672010-07-18 09:45:05 +0000203 * Generate X as large as possible ( < P )
Paul Bakker5121ce52009-01-03 21:22:43 +0000204 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000205 do
206 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200207 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000208
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200209 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
210 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000211
212 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000214 }
215 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000216
Paul Bakkerff7fe672010-07-18 09:45:05 +0000217 /*
218 * Calculate GX = G^X mod P
219 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000221 &ctx->P , &ctx->RP ) );
222
Paul Bakker345a6fe2011-02-28 21:20:02 +0000223 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000224 return( ret );
225
Paul Bakker5121ce52009-01-03 21:22:43 +0000226 /*
227 * export P, G, GX
228 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100229#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100230 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100231 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
232 p + 2, \
233 ( n ) ) ); \
234 *p++ = (unsigned char)( ( n ) >> 8 ); \
235 *p++ = (unsigned char)( ( n ) ); \
236 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100237 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000238
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200239 n1 = mbedtls_mpi_size( &ctx->P );
240 n2 = mbedtls_mpi_size( &ctx->G );
241 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000242
243 p = output;
244 DHM_MPI_EXPORT( &ctx->P , n1 );
245 DHM_MPI_EXPORT( &ctx->G , n2 );
246 DHM_MPI_EXPORT( &ctx->GX, n3 );
247
Hanno Beckere71ad122017-09-28 10:32:25 +0100248 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000249
250 ctx->len = n1;
251
252cleanup:
253
254 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000256
257 return( 0 );
258}
259
260/*
Hanno Becker8880e752017-10-04 13:15:08 +0100261 * Set prime modulus and generator
262 */
263int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
264 const mbedtls_mpi *P,
265 const mbedtls_mpi *G )
266{
267 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000268 DHM_VALIDATE_RET( ctx != NULL );
269 DHM_VALIDATE_RET( P != NULL );
270 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100271
272 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
273 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
274 {
275 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
276 }
277
278 ctx->len = mbedtls_mpi_size( &ctx->P );
279 return( 0 );
280}
281
282/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000283 * Import the peer's public value G^Y
284 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200285int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000286 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000287{
288 int ret;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000289 DHM_VALIDATE_RET( ctx != NULL );
290 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000291
Hanno Becker5c14ed62018-12-12 19:44:47 +0000292 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200293 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000294
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200295 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
296 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000297
298 return( 0 );
299}
300
301/*
302 * Create own private value X and export G^X
303 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200304int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000305 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000306 int (*f_rng)(void *, unsigned char *, size_t),
307 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000308{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000309 int ret, count = 0;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000310 DHM_VALIDATE_RET( ctx != NULL );
311 DHM_VALIDATE_RET( output != NULL );
312 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000313
Hanno Becker5c14ed62018-12-12 19:44:47 +0000314 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200315 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000316
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200317 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
318 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000319
Paul Bakker5121ce52009-01-03 21:22:43 +0000320 /*
321 * generate X and calculate GX = G^X mod P
322 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000323 do
324 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200325 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000326
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
328 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000329
330 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000332 }
333 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000334
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200335 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000336 &ctx->P , &ctx->RP ) );
337
Paul Bakker345a6fe2011-02-28 21:20:02 +0000338 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
339 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000340
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000342
343cleanup:
344
345 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200346 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000347
348 return( 0 );
349}
350
351/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200352 * Use the blinding method and optimisation suggested in section 10 of:
353 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200354 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200355 * Berlin Heidelberg, 1996. p. 104-113.
356 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200358 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
359{
360 int ret, count;
361
362 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200363 * Don't use any blinding the first time a particular X is used,
364 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200365 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200367 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
369 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
370 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200371
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200372 return( 0 );
373 }
374
375 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200376 * Ok, we need blinding. Can we re-use existing values?
377 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200378 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200380 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
382 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200383
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
385 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200386
387 return( 0 );
388 }
389
390 /*
391 * We need to generate blinding values from scratch
392 */
393
394 /* Vi = random( 2, P-1 ) */
395 count = 0;
396 do
397 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200398 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200399
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
401 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200402
403 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200405 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200407
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200408 /* Vf = Vi^-X mod P */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
410 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 +0200411
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200412cleanup:
413 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{
424 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200425 mbedtls_mpi GYb;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000426 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
Hanno Becker5c14ed62018-12-12 19:44:47 +0000430 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{
Hanno Becker5c14ed62018-12-12 19:44:47 +0000477 if( ctx == NULL )
478 return;
479
irwir2239a862018-06-12 18:25:09 +0300480 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{
501 int ret;
502 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;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000506#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200507
Hanno Becker5c14ed62018-12-12 19:44:47 +0000508 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{
655 int ret;
656 size_t n;
657 unsigned char *buf;
Hanno Becker5c14ed62018-12-12 19:44:47 +0000658 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 Becker7b34f0f2019-05-10 14:43:31 +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 Becker7b34f0f2019-05-10 14:43:31 +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{
Paul Bakker40ce79f2013-09-15 17:43:54 +0200707 int ret;
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 */