blob: 79ef11657d13fb9a990fa7ae84a41f185949afea [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é-Gonnard143b5022013-09-04 16:29:59 +0200337 * Use the blinding method and optimisation suggested in section 10 of:
338 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200339 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200340 * Berlin Heidelberg, 1996. p. 104-113.
341 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200342static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200343 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
344{
345 int ret, count;
346
347 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200348 * Don't use any blinding the first time a particular X is used,
349 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200350 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200351 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200352 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
354 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
355 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200356
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200357 return( 0 );
358 }
359
360 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200361 * Ok, we need blinding. Can we re-use existing values?
362 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200363 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200364 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200365 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200366 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
367 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200368
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200369 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
370 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200371
372 return( 0 );
373 }
374
375 /*
376 * We need to generate blinding values from scratch
377 */
378
379 /* Vi = random( 2, P-1 ) */
380 count = 0;
381 do
382 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200383 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 +0200384
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200385 while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
386 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200387
388 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200389 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200390 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200391 while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200392
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200393 /* Vf = Vi^-X mod P */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
395 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 +0200396
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200397cleanup:
398 return( ret );
399}
400
401/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000402 * Derive and export the shared secret (G^Y)^X mod P
403 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200404int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100405 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200406 int (*f_rng)(void *, unsigned char *, size_t),
407 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000408{
409 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410 mbedtls_mpi GYb;
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200411
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100412 if( ctx == NULL || output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200413 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000414
Paul Bakker345a6fe2011-02-28 21:20:02 +0000415 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000416 return( ret );
417
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200418 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200419
420 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200421 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200422 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200423 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
424 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
425 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200426 }
427 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200428 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200429
430 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200431 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200432 &ctx->P, &ctx->RP ) );
433
434 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200435 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200436 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200437 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
438 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200439 }
440
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200443 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000444
445cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200446 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
448 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200449 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000450
451 return( 0 );
452}
453
454/*
455 * Free the components of a DHM key
456 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200457void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458{
Hanno Beckere71ad122017-09-28 10:32:25 +0100459 mbedtls_mpi_free( &ctx->pX ); mbedtls_mpi_free( &ctx->Vf );
460 mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->RP );
461 mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY );
462 mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X );
463 mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200464
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200465 mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000466}
467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200469/*
470 * Parse DHM parameters
471 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200473 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200474{
475 int ret;
476 size_t len;
477 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478#if defined(MBEDTLS_PEM_PARSE_C)
479 mbedtls_pem_context pem;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200482
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200483 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200484 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200485 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
486 else
487 ret = mbedtls_pem_read_buffer( &pem,
488 "-----BEGIN DH PARAMETERS-----",
489 "-----END DH PARAMETERS-----",
490 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200491
492 if( ret == 0 )
493 {
494 /*
495 * Was PEM encoded
496 */
497 dhminlen = pem.buflen;
498 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200500 goto exit;
501
502 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
503#else
504 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200506 end = p + dhminlen;
507
508 /*
509 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400510 * prime INTEGER, -- P
511 * generator INTEGER, -- g
512 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200513 * }
514 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
516 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200517 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200519 goto exit;
520 }
521
522 end = p + len;
523
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
525 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200526 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200527 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200528 goto exit;
529 }
530
531 if( p != end )
532 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200533 /* This might be the optional privateValueLength.
534 * If so, we can cleanly discard it */
535 mbedtls_mpi rec;
536 mbedtls_mpi_init( &rec );
537 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
538 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400539 if ( ret != 0 )
540 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200541 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400542 goto exit;
543 }
544 if ( p != end )
545 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200546 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
547 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400548 goto exit;
549 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200550 }
551
552 ret = 0;
553
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200554 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100555
Paul Bakker40ce79f2013-09-15 17:43:54 +0200556exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200557#if defined(MBEDTLS_PEM_PARSE_C)
558 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200559#endif
560 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200561 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200562
563 return( ret );
564}
565
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200566#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200567/*
568 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200569 *
570 * The file is expected to contain either PEM or DER encoded data.
571 * A terminating null byte is always appended. It is included in the announced
572 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200573 */
574static int load_file( const char *path, unsigned char **buf, size_t *n )
575{
576 FILE *f;
577 long size;
578
579 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200581
582 fseek( f, 0, SEEK_END );
583 if( ( size = ftell( f ) ) == -1 )
584 {
585 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200586 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200587 }
588 fseek( f, 0, SEEK_SET );
589
590 *n = (size_t) size;
591
592 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200593 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200594 {
595 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200596 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200597 }
598
599 if( fread( *buf, 1, *n, f ) != *n )
600 {
601 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100602
603 mbedtls_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200604 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200607 }
608
609 fclose( f );
610
611 (*buf)[*n] = '\0';
612
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200613 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
614 ++*n;
615
Paul Bakker40ce79f2013-09-15 17:43:54 +0200616 return( 0 );
617}
618
619/*
620 * Load and parse DHM parameters
621 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200622int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200623{
624 int ret;
625 size_t n;
626 unsigned char *buf;
627
Paul Bakker66d5d072014-06-17 16:39:18 +0200628 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200629 return( ret );
630
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200632
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200633 mbedtls_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200634 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200635
636 return( ret );
637}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638#endif /* MBEDTLS_FS_IO */
639#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000640#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200641
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200644static const char mbedtls_test_dhm_params[] =
645"-----BEGIN DH PARAMETERS-----\r\n"
646"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
647"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
648"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
649"-----END DH PARAMETERS-----\r\n";
650
651static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200652
Paul Bakker5121ce52009-01-03 21:22:43 +0000653/*
654 * Checkup routine
655 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200656int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000657{
Paul Bakker40ce79f2013-09-15 17:43:54 +0200658 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200660
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200661 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200662
Paul Bakker40ce79f2013-09-15 17:43:54 +0200663 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200664 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200665
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200666 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
667 (const unsigned char *) mbedtls_test_dhm_params,
668 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200669 {
670 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200672
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200673 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200674 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200675 }
676
677 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200679
Paul Bakker8f870b02014-06-20 13:32:38 +0200680exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200681 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200682
Paul Bakker8f870b02014-06-20 13:32:38 +0200683 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000684}
685
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200686#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000687
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688#endif /* MBEDTLS_DHM_C */