blob: e15cc8e949e8c8a1b31ffe9e3c75fadd8103865f [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Diffie-Hellman-Merkle key exchange
3 *
Bence Szépkúti44bfbe32020-08-19 16:54:51 +02004 * Copyright The Mbed TLS Contributors
Bence Szépkúti4e9f7122020-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úti4e9f7122020-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"
Paul Bakker5121ce52009-01-03 21:22:43 +000064
Rich Evans00ab4702015-02-06 13:43:58 +000065#include <string.h>
66
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020067#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000068#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020069#endif
70
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000072#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020073#endif
74
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020075#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000076#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020077#else
78#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000079#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020081#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020082#define mbedtls_free free
Paul Bakker40ce79f2013-09-15 17:43:54 +020083#endif
84
Reuven Levin1f35ca92017-12-07 10:09:32 +000085#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020086/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020087static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +020088 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
89}
90
Paul Bakker5121ce52009-01-03 21:22:43 +000091/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000093 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020094static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +000095 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000096 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +000097{
98 int ret, n;
99
100 if( end - *p < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200101 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000102
103 n = ( (*p)[0] << 8 ) | (*p)[1];
104 (*p) += 2;
105
106 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200107 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000108
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200109 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
110 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000111
112 (*p) += n;
113
114 return( 0 );
115}
116
117/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000118 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +0000119 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000120 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +0000121 *
Janos Follathaa325d72017-09-20 15:33:24 +0100122 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +0100123 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +0100124 *
Paul Bakker345a6fe2011-02-28 21:20:02 +0000125 * For more information on the attack, see:
126 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
127 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +0000128 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200129static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000130{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200131 mbedtls_mpi L, U;
Janos Follathaa325d72017-09-20 15:33:24 +0100132 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000133
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200134 mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +0200135
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
137 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000138
Janos Follathaa325d72017-09-20 15:33:24 +0100139 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
140 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000141 {
Janos Follathaa325d72017-09-20 15:33:24 +0100142 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000143 }
144
Paul Bakker3d8fb632014-04-17 12:42:41 +0200145cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000147 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000148}
149
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200150void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200151{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200152 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200153}
154
Paul Bakkerc47840e2011-02-20 16:37:30 +0000155/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000156 * Parse the ServerKeyExchange parameters
157 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000159 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000160 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000161{
Paul Bakker13ed9ab2012-04-16 09:43:49 +0000162 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000163
Paul Bakker5121ce52009-01-03 21:22:43 +0000164 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
165 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
166 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
167 return( ret );
168
Paul Bakker345a6fe2011-02-28 21:20:02 +0000169 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
170 return( ret );
171
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000173
Paul Bakker5121ce52009-01-03 21:22:43 +0000174 return( 0 );
175}
176
177/*
178 * Setup and write the ServerKeyExchange parameters
179 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000181 unsigned char *output, size_t *olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000182 int (*f_rng)(void *, unsigned char *, size_t),
183 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000184{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000185 int ret, count = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000186 size_t n1, n2, n3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000187 unsigned char *p;
188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
190 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000191
Paul Bakker5121ce52009-01-03 21:22:43 +0000192 /*
Paul Bakkerff7fe672010-07-18 09:45:05 +0000193 * Generate X as large as possible ( < P )
Paul Bakker5121ce52009-01-03 21:22:43 +0000194 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000195 do
196 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200197 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000198
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
200 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000201
202 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200203 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000204 }
205 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000206
Paul Bakkerff7fe672010-07-18 09:45:05 +0000207 /*
208 * Calculate GX = G^X mod P
209 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200210 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000211 &ctx->P , &ctx->RP ) );
212
Paul Bakker345a6fe2011-02-28 21:20:02 +0000213 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000214 return( ret );
215
Paul Bakker5121ce52009-01-03 21:22:43 +0000216 /*
217 * export P, G, GX
218 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100219#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100220 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100221 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
222 p + 2, \
223 ( n ) ) ); \
224 *p++ = (unsigned char)( ( n ) >> 8 ); \
225 *p++ = (unsigned char)( ( n ) ); \
226 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100227 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000228
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229 n1 = mbedtls_mpi_size( &ctx->P );
230 n2 = mbedtls_mpi_size( &ctx->G );
231 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000232
233 p = output;
234 DHM_MPI_EXPORT( &ctx->P , n1 );
235 DHM_MPI_EXPORT( &ctx->G , n2 );
236 DHM_MPI_EXPORT( &ctx->GX, n3 );
237
Hanno Beckere71ad122017-09-28 10:32:25 +0100238 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000239
240 ctx->len = n1;
241
242cleanup:
243
244 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000246
247 return( 0 );
248}
249
250/*
Hanno Becker8880e752017-10-04 13:15:08 +0100251 * Set prime modulus and generator
252 */
253int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
254 const mbedtls_mpi *P,
255 const mbedtls_mpi *G )
256{
257 int ret;
258
259 if( ctx == NULL || P == NULL || G == NULL )
260 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
261
262 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
263 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
264 {
265 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
266 }
267
268 ctx->len = mbedtls_mpi_size( &ctx->P );
269 return( 0 );
270}
271
272/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000273 * Import the peer's public value G^Y
274 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200275int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000276 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000277{
278 int ret;
279
280 if( ctx == NULL || ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200281 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000282
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
284 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000285
286 return( 0 );
287}
288
289/*
290 * Create own private value X and export G^X
291 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000293 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000294 int (*f_rng)(void *, unsigned char *, size_t),
295 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000296{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000297 int ret, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000298
299 if( ctx == NULL || olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200300 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
303 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000304
Paul Bakker5121ce52009-01-03 21:22:43 +0000305 /*
306 * generate X and calculate GX = G^X mod P
307 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000308 do
309 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200310 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000311
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200312 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
313 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000314
315 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000317 }
318 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200320 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000321 &ctx->P , &ctx->RP ) );
322
Paul Bakker345a6fe2011-02-28 21:20:02 +0000323 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
324 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000325
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200326 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000327
328cleanup:
329
330 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000332
333 return( 0 );
334}
335
336/*
Manuel Pégourié-Gonnardf0f43c52020-06-25 12:34:58 +0200337 * Pick a random R in the range [2, M) for blinding purposes
338 */
339static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
340 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
341{
342 int ret, count;
343
344 count = 0;
345 do
346 {
347 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
348
349 while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
350 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
351
352 if( count++ > 10 )
353 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
354 }
355 while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
356
357cleanup:
358 return( ret );
359}
360
361
362/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200363 * Use the blinding method and optimisation suggested in section 10 of:
364 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200365 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200366 * Berlin Heidelberg, 1996. p. 104-113.
367 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200368static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200369 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
370{
Manuel Pégourié-Gonnardf0f43c52020-06-25 12:34:58 +0200371 int ret;
Manuel Pégourié-Gonnarda35e98a2020-06-25 12:47:22 +0200372 mbedtls_mpi R;
373
374 mbedtls_mpi_init( &R );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200375
376 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200377 * Don't use any blinding the first time a particular X is used,
378 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200379 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200380 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200381 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200382 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
383 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
384 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200385
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200386 return( 0 );
387 }
388
389 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200390 * Ok, we need blinding. Can we re-use existing values?
391 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200392 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200393 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200394 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200395 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
396 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200397
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200398 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
399 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200400
401 return( 0 );
402 }
403
404 /*
405 * We need to generate blinding values from scratch
406 */
407
408 /* Vi = random( 2, P-1 ) */
Manuel Pégourié-Gonnardf0f43c52020-06-25 12:34:58 +0200409 MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200410
Manuel Pégourié-Gonnarda35e98a2020-06-25 12:47:22 +0200411 /* Vf = Vi^-X mod P
412 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
413 * then elevate to the Xth power. */
414 MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
415 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
416 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
417 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
418 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
419 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
420
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 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 +0200422
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200423cleanup:
Manuel Pégourié-Gonnarda35e98a2020-06-25 12:47:22 +0200424 mbedtls_mpi_free( &R );
425
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200426 return( ret );
427}
428
429/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000430 * Derive and export the shared secret (G^Y)^X mod P
431 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100433 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200434 int (*f_rng)(void *, unsigned char *, size_t),
435 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000436{
437 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200438 mbedtls_mpi GYb;
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200439
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100440 if( ctx == NULL || output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Paul Bakker345a6fe2011-02-28 21:20:02 +0000443 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000444 return( ret );
445
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200447
448 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200449 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200450 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
452 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
453 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200454 }
455 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200457
458 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200460 &ctx->P, &ctx->RP ) );
461
462 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200463 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200464 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
466 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200467 }
468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000470
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200471 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000472
473cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200474 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000475
476 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200477 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000478
479 return( 0 );
480}
481
482/*
483 * Free the components of a DHM key
484 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000486{
Hanno Beckere71ad122017-09-28 10:32:25 +0100487 mbedtls_mpi_free( &ctx->pX ); mbedtls_mpi_free( &ctx->Vf );
488 mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->RP );
489 mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY );
490 mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X );
491 mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200492
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200493 mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000494}
495
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200497/*
498 * Parse DHM parameters
499 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200501 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200502{
503 int ret;
504 size_t len;
505 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200506#if defined(MBEDTLS_PEM_PARSE_C)
507 mbedtls_pem_context pem;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200508
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200509 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200510
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200511 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200512 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200513 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
514 else
515 ret = mbedtls_pem_read_buffer( &pem,
516 "-----BEGIN DH PARAMETERS-----",
517 "-----END DH PARAMETERS-----",
518 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200519
520 if( ret == 0 )
521 {
522 /*
523 * Was PEM encoded
524 */
525 dhminlen = pem.buflen;
526 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200528 goto exit;
529
530 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
531#else
532 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200534 end = p + dhminlen;
535
536 /*
537 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400538 * prime INTEGER, -- P
539 * generator INTEGER, -- g
540 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200541 * }
542 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200543 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
544 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200545 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200546 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200547 goto exit;
548 }
549
550 end = p + len;
551
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200552 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
553 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200554 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200556 goto exit;
557 }
558
559 if( p != end )
560 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200561 /* This might be the optional privateValueLength.
562 * If so, we can cleanly discard it */
563 mbedtls_mpi rec;
564 mbedtls_mpi_init( &rec );
565 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
566 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400567 if ( ret != 0 )
568 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200569 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400570 goto exit;
571 }
572 if ( p != end )
573 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200574 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
575 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400576 goto exit;
577 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200578 }
579
580 ret = 0;
581
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200582 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100583
Paul Bakker40ce79f2013-09-15 17:43:54 +0200584exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200585#if defined(MBEDTLS_PEM_PARSE_C)
586 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200587#endif
588 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200589 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200590
591 return( ret );
592}
593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200595/*
596 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200597 *
598 * The file is expected to contain either PEM or DER encoded data.
599 * A terminating null byte is always appended. It is included in the announced
600 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200601 */
602static int load_file( const char *path, unsigned char **buf, size_t *n )
603{
604 FILE *f;
605 long size;
606
607 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200608 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200609
610 fseek( f, 0, SEEK_END );
611 if( ( size = ftell( f ) ) == -1 )
612 {
613 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200614 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200615 }
616 fseek( f, 0, SEEK_SET );
617
618 *n = (size_t) size;
619
620 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200621 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200622 {
623 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200624 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200625 }
626
627 if( fread( *buf, 1, *n, f ) != *n )
628 {
629 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100630
631 mbedtls_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200632 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100633
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200635 }
636
637 fclose( f );
638
639 (*buf)[*n] = '\0';
640
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200641 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
642 ++*n;
643
Paul Bakker40ce79f2013-09-15 17:43:54 +0200644 return( 0 );
645}
646
647/*
648 * Load and parse DHM parameters
649 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200651{
652 int ret;
653 size_t n;
654 unsigned char *buf;
655
Paul Bakker66d5d072014-06-17 16:39:18 +0200656 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200657 return( ret );
658
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200660
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200661 mbedtls_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200662 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200663
664 return( ret );
665}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200666#endif /* MBEDTLS_FS_IO */
667#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000668#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200669
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200670#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000671
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200672static const char mbedtls_test_dhm_params[] =
673"-----BEGIN DH PARAMETERS-----\r\n"
674"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
675"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
676"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
677"-----END DH PARAMETERS-----\r\n";
678
679static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200680
Paul Bakker5121ce52009-01-03 21:22:43 +0000681/*
682 * Checkup routine
683 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200684int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000685{
Paul Bakker40ce79f2013-09-15 17:43:54 +0200686 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200687 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200688
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200689 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200690
Paul Bakker40ce79f2013-09-15 17:43:54 +0200691 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200693
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200694 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
695 (const unsigned char *) mbedtls_test_dhm_params,
696 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200697 {
698 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200699 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200700
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200701 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200702 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200703 }
704
705 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200706 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200707
Paul Bakker8f870b02014-06-20 13:32:38 +0200708exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200710
Paul Bakker8f870b02014-06-20 13:32:38 +0200711 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000712}
713
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200716#endif /* MBEDTLS_DHM_C */