blob: 8255632a993fb5bf89b686c0f5d2b79ab1d1d6e5 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Diffie-Hellman-Merkle key exchange
3 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
21/*
Simon Butcherbdae02c2016-01-20 00:44:42 +000022 * The following sources were referenced in the design of this implementation
23 * of the Diffie-Hellman-Merkle algorithm:
Paul Bakker5121ce52009-01-03 21:22:43 +000024 *
Simon Butcherbdae02c2016-01-20 00:44:42 +000025 * [1] Handbook of Applied Cryptography - 1997, Chapter 12
26 * Menezes, van Oorschot and Vanstone
27 *
Paul Bakker5121ce52009-01-03 21:22:43 +000028 */
29
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020032#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020033#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020034#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020036#if defined(MBEDTLS_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000037
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000038#include "mbedtls/dhm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050039#include "mbedtls/platform_util.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000040
Rich Evans00ab4702015-02-06 13:43:58 +000041#include <string.h>
42
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020043#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000044#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020045#endif
46
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000048#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020049#endif
50
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020051#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000052#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020053#else
54#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000055#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020057#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020058#define mbedtls_free free
Paul Bakker40ce79f2013-09-15 17:43:54 +020059#endif
60
Reuven Levin1f35ca92017-12-07 10:09:32 +000061#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020062
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050063#define DHM_VALIDATE_RET( cond ) \
64 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
65#define DHM_VALIDATE( cond ) \
66 MBEDTLS_INTERNAL_VALIDATE( cond )
67
Paul Bakker5121ce52009-01-03 21:22:43 +000068/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020069 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000070 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020071static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +000072 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +000073 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +000074{
75 int ret, n;
76
77 if( end - *p < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000079
80 n = ( (*p)[0] << 8 ) | (*p)[1];
81 (*p) += 2;
82
83 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020084 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +000085
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020086 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
87 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +000088
89 (*p) += n;
90
91 return( 0 );
92}
93
94/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000095 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000096 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000097 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000098 *
Janos Follathaa325d72017-09-20 15:33:24 +010099 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +0100100 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +0100101 *
Paul Bakker345a6fe2011-02-28 21:20:02 +0000102 * For more information on the attack, see:
103 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
104 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +0000105 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200106static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000107{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200108 mbedtls_mpi L, U;
Janos Follathaa325d72017-09-20 15:33:24 +0100109 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000110
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200111 mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +0200112
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200113 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
114 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000115
Janos Follathaa325d72017-09-20 15:33:24 +0100116 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
117 mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000118 {
Janos Follathaa325d72017-09-20 15:33:24 +0100119 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000120 }
121
Paul Bakker3d8fb632014-04-17 12:42:41 +0200122cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200123 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000124 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000125}
126
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200128{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500129 DHM_VALIDATE( ctx != NULL );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200130 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200131}
132
Paul Bakkerc47840e2011-02-20 16:37:30 +0000133/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000134 * Parse the ServerKeyExchange parameters
135 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200136int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000137 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000138 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000139{
Paul Bakker13ed9ab2012-04-16 09:43:49 +0000140 int ret;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500141 DHM_VALIDATE_RET( ctx != NULL );
142 DHM_VALIDATE_RET( p != NULL && *p != NULL );
143 DHM_VALIDATE_RET( end != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000144
Paul Bakker5121ce52009-01-03 21:22:43 +0000145 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
146 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
147 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
148 return( ret );
149
Paul Bakker345a6fe2011-02-28 21:20:02 +0000150 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
151 return( ret );
152
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200153 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000154
Paul Bakker5121ce52009-01-03 21:22:43 +0000155 return( 0 );
156}
157
158/*
159 * Setup and write the ServerKeyExchange parameters
160 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000162 unsigned char *output, size_t *olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000163 int (*f_rng)(void *, unsigned char *, size_t),
164 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000165{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000166 int ret, count = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000167 size_t n1, n2, n3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000168 unsigned char *p;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500169 DHM_VALIDATE_RET( ctx != NULL );
170 DHM_VALIDATE_RET( output != NULL );
171 DHM_VALIDATE_RET( olen != NULL );
172 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
175 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000176
Paul Bakker5121ce52009-01-03 21:22:43 +0000177 /*
Paul Bakkerff7fe672010-07-18 09:45:05 +0000178 * Generate X as large as possible ( < P )
Paul Bakker5121ce52009-01-03 21:22:43 +0000179 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000180 do
181 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200182 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
185 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000186
187 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200188 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000189 }
190 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000191
Paul Bakkerff7fe672010-07-18 09:45:05 +0000192 /*
193 * Calculate GX = G^X mod P
194 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000196 &ctx->P , &ctx->RP ) );
197
Paul Bakker345a6fe2011-02-28 21:20:02 +0000198 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000199 return( ret );
200
Paul Bakker5121ce52009-01-03 21:22:43 +0000201 /*
202 * export P, G, GX
203 */
Hanno Beckerde6c1642017-10-02 15:03:15 +0100204#define DHM_MPI_EXPORT( X, n ) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100205 do { \
Hanno Beckerde6c1642017-10-02 15:03:15 +0100206 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
207 p + 2, \
208 ( n ) ) ); \
209 *p++ = (unsigned char)( ( n ) >> 8 ); \
210 *p++ = (unsigned char)( ( n ) ); \
211 p += ( n ); \
Hanno Beckere71ad122017-09-28 10:32:25 +0100212 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000213
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 n1 = mbedtls_mpi_size( &ctx->P );
215 n2 = mbedtls_mpi_size( &ctx->G );
216 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000217
218 p = output;
219 DHM_MPI_EXPORT( &ctx->P , n1 );
220 DHM_MPI_EXPORT( &ctx->G , n2 );
221 DHM_MPI_EXPORT( &ctx->GX, n3 );
222
Hanno Beckere71ad122017-09-28 10:32:25 +0100223 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000224
225 ctx->len = n1;
226
227cleanup:
228
229 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200230 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000231
232 return( 0 );
233}
234
235/*
Hanno Becker8880e752017-10-04 13:15:08 +0100236 * Set prime modulus and generator
237 */
238int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
239 const mbedtls_mpi *P,
240 const mbedtls_mpi *G )
241{
242 int ret;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500243 DHM_VALIDATE_RET( ctx != NULL );
244 DHM_VALIDATE_RET( P != NULL );
245 DHM_VALIDATE_RET( G != NULL );
Hanno Becker8880e752017-10-04 13:15:08 +0100246
247 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
248 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
249 {
250 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
251 }
252
253 ctx->len = mbedtls_mpi_size( &ctx->P );
254 return( 0 );
255}
256
257/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000258 * Import the peer's public value G^Y
259 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200260int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000261 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000262{
263 int ret;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500264 DHM_VALIDATE_RET( ctx != NULL );
265 DHM_VALIDATE_RET( input != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500267 if( ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200268 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000269
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200270 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
271 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000272
273 return( 0 );
274}
275
276/*
277 * Create own private value X and export G^X
278 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200279int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000280 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000281 int (*f_rng)(void *, unsigned char *, size_t),
282 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000283{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000284 int ret, count = 0;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500285 DHM_VALIDATE_RET( ctx != NULL );
286 DHM_VALIDATE_RET( output != NULL );
287 DHM_VALIDATE_RET( f_rng != NULL );
Paul Bakker5121ce52009-01-03 21:22:43 +0000288
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500289 if( olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200290 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
293 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000294
Paul Bakker5121ce52009-01-03 21:22:43 +0000295 /*
296 * generate X and calculate GX = G^X mod P
297 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000298 do
299 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200300 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000301
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
303 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000304
305 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200306 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000307 }
308 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000309
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200310 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000311 &ctx->P , &ctx->RP ) );
312
Paul Bakker345a6fe2011-02-28 21:20:02 +0000313 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
314 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000315
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000317
318cleanup:
319
320 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200321 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000322
323 return( 0 );
324}
325
326/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200327 * Use the blinding method and optimisation suggested in section 10 of:
328 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200329 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200330 * Berlin Heidelberg, 1996. p. 104-113.
331 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200332static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200333 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
334{
335 int ret, count;
336
337 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200338 * Don't use any blinding the first time a particular X is used,
339 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200340 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200342 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
344 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
345 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200346
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200347 return( 0 );
348 }
349
350 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200351 * Ok, we need blinding. Can we re-use existing values?
352 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200353 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200354 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200355 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200356 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
357 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200358
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200359 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
360 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200361
362 return( 0 );
363 }
364
365 /*
366 * We need to generate blinding values from scratch
367 */
368
369 /* Vi = random( 2, P-1 ) */
370 count = 0;
371 do
372 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200373 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 +0200374
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200375 while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
376 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200377
378 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200379 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200380 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200381 while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200382
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200383 /* Vf = Vi^-X mod P */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200384 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
385 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 +0200386
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200387cleanup:
388 return( ret );
389}
390
391/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000392 * Derive and export the shared secret (G^Y)^X mod P
393 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100395 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200396 int (*f_rng)(void *, unsigned char *, size_t),
397 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000398{
399 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200400 mbedtls_mpi GYb;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500401 DHM_VALIDATE_RET( ctx != NULL );
402 DHM_VALIDATE_RET( output != NULL );
403 DHM_VALIDATE_RET( olen != NULL );
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200404
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500405 if( output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200406 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000407
Paul Bakker345a6fe2011-02-28 21:20:02 +0000408 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000409 return( ret );
410
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200411 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200412
413 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200414 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200415 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200416 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
417 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
418 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200419 }
420 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200421 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200422
423 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200424 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200425 &ctx->P, &ctx->RP ) );
426
427 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200428 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200429 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
431 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200432 }
433
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200434 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200436 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000437
438cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000440
441 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200442 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000443
444 return( 0 );
445}
446
447/*
448 * Free the components of a DHM key
449 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200450void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000451{
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500452 if( ctx == NULL )
453 return;
454
455 mbedtls_mpi_free( &ctx->pX );
456 mbedtls_mpi_free( &ctx->Vf );
457 mbedtls_mpi_free( &ctx->Vi );
458 mbedtls_mpi_free( &ctx->RP );
459 mbedtls_mpi_free( &ctx->K );
460 mbedtls_mpi_free( &ctx->GY );
461 mbedtls_mpi_free( &ctx->GX );
462 mbedtls_mpi_free( &ctx->X );
463 mbedtls_mpi_free( &ctx->G );
464 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200465
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500466 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000467}
468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200470/*
471 * Parse DHM parameters
472 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200473int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200474 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200475{
476 int ret;
477 size_t len;
478 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479#if defined(MBEDTLS_PEM_PARSE_C)
480 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500481#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200482
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500483 DHM_VALIDATE_RET( dhm != NULL );
484 DHM_VALIDATE_RET( dhmin != NULL );
485
486#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200488
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200489 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200490 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200491 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
492 else
493 ret = mbedtls_pem_read_buffer( &pem,
494 "-----BEGIN DH PARAMETERS-----",
495 "-----END DH PARAMETERS-----",
496 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200497
498 if( ret == 0 )
499 {
500 /*
501 * Was PEM encoded
502 */
503 dhminlen = pem.buflen;
504 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200506 goto exit;
507
508 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
509#else
510 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200512 end = p + dhminlen;
513
514 /*
515 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400516 * prime INTEGER, -- P
517 * generator INTEGER, -- g
518 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200519 * }
520 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
522 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200523 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200524 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200525 goto exit;
526 }
527
528 end = p + len;
529
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200530 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
531 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200532 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200533 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200534 goto exit;
535 }
536
537 if( p != end )
538 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200539 /* This might be the optional privateValueLength.
540 * If so, we can cleanly discard it */
541 mbedtls_mpi rec;
542 mbedtls_mpi_init( &rec );
543 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
544 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400545 if ( ret != 0 )
546 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200547 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400548 goto exit;
549 }
550 if ( p != end )
551 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200552 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
553 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400554 goto exit;
555 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200556 }
557
558 ret = 0;
559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100561
Paul Bakker40ce79f2013-09-15 17:43:54 +0200562exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200563#if defined(MBEDTLS_PEM_PARSE_C)
564 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200565#endif
566 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200568
569 return( ret );
570}
571
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200572#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200573/*
574 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200575 *
576 * The file is expected to contain either PEM or DER encoded data.
577 * A terminating null byte is always appended. It is included in the announced
578 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200579 */
580static int load_file( const char *path, unsigned char **buf, size_t *n )
581{
582 FILE *f;
583 long size;
584
585 if( ( f = fopen( path, "rb" ) ) == NULL )
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_END );
589 if( ( size = ftell( f ) ) == -1 )
590 {
591 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200592 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200593 }
594 fseek( f, 0, SEEK_SET );
595
596 *n = (size_t) size;
597
598 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200599 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200600 {
601 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200602 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200603 }
604
605 if( fread( *buf, 1, *n, f ) != *n )
606 {
607 fclose( f );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100608
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500609 mbedtls_platform_zeroize( *buf, *n + 1 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200610 mbedtls_free( *buf );
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100611
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200612 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200613 }
614
615 fclose( f );
616
617 (*buf)[*n] = '\0';
618
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200619 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
620 ++*n;
621
Paul Bakker40ce79f2013-09-15 17:43:54 +0200622 return( 0 );
623}
624
625/*
626 * Load and parse DHM parameters
627 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200628int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200629{
630 int ret;
631 size_t n;
632 unsigned char *buf;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500633 DHM_VALIDATE_RET( dhm != NULL );
634 DHM_VALIDATE_RET( path != NULL );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200635
Paul Bakker66d5d072014-06-17 16:39:18 +0200636 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200637 return( ret );
638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200640
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500641 mbedtls_platform_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200643
644 return( ret );
645}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646#endif /* MBEDTLS_FS_IO */
647#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000648#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200649
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200650#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000651
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100652#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200653static const char mbedtls_test_dhm_params[] =
654"-----BEGIN DH PARAMETERS-----\r\n"
655"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
656"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
657"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
658"-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100659#else /* MBEDTLS_PEM_PARSE_C */
660static const char mbedtls_test_dhm_params[] = {
661 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
662 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
663 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
664 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
665 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
666 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
667 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
668 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
669 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
670 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
671 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
672 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
673#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200674
675static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200676
Paul Bakker5121ce52009-01-03 21:22:43 +0000677/*
678 * Checkup routine
679 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000681{
Paul Bakker40ce79f2013-09-15 17:43:54 +0200682 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200683 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200684
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200685 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200686
Paul Bakker40ce79f2013-09-15 17:43:54 +0200687 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200688 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200689
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200690 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
691 (const unsigned char *) mbedtls_test_dhm_params,
692 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200693 {
694 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200696
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200697 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200698 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200699 }
700
701 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200702 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200703
Paul Bakker8f870b02014-06-20 13:32:38 +0200704exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200705 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200706
Paul Bakker8f870b02014-06-20 13:32:38 +0200707 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000708}
709
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000711
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200712#endif /* MBEDTLS_DHM_C */