blob: 9da33c901be392df298409b31606ad563ff619ba [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"
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Rich Evans00ab4702015-02-06 13:43:58 +000040#include <string.h>
41
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020044#endif
45
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020046#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000047#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020048#endif
49
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000051#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020052#else
53#include <stdlib.h>
Manuel Pégourié-Gonnard981732b2015-02-17 15:46:45 +000054#include <stdio.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055#define mbedtls_printf printf
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +020056#define mbedtls_calloc calloc
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020057#define mbedtls_free free
Paul Bakker40ce79f2013-09-15 17:43:54 +020058#endif
59
Hanno Becker0e6dc842017-09-27 11:48:02 +010060/*
61 * Diffie-Hellman groups from RFC 5114
62 *
63 * \warning The origin of the primes in RFC 5114 is not documented and
64 * their use therefore constitutes a security risk!
65 *
66 * \deprecated The primes from RFC 5114 are superseded by the primes
67 * from RFC 3526 and RFC 7919 and should no longer be used.
68 * They will be removed in the next major version.
69 */
70
71const char * mbedtls_dhm_rfc5114_modp_2048_p =
72 "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1"
73 "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15"
74 "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212"
75 "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207"
76 "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708"
77 "B3BF8A317091883681286130BC8985DB1602E714415D9330"
78 "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D"
79 "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8"
80 "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763"
81 "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71"
82 "CF9DE5384E71B81C0AC4DFFE0C10E64F";
83const char * mbedtls_dhm_rfc5114_modp_2048_g =
84 "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"
85 "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"
86 "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"
87 "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"
88 "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"
89 "F180EB34118E98D119529A45D6F834566E3025E316A330EF"
90 "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"
91 "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"
92 "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"
93 "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"
94 "81BC087F2A7065B384B890D3191F2BFA";
95
96/*
97 * Diffie-Hellman groups from RFC 3526
98 */
99
100const char * mbedtls_dhm_rfc3526_modp_2048_p =
101 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
102 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
103 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
104 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
105 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
106 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
107 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
108 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
109 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
110 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
111 "15728E5A8AACAA68FFFFFFFFFFFFFFFF";
112const char * mbedtls_dhm_rfc3526_modp_2048_g = "02";
113
114const char * mbedtls_dhm_rfc3526_modp_3072_p =
115 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
116 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
117 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
118 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
119 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
120 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
121 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
122 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
123 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
124 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
125 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
126 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
127 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
128 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
129 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
130 "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
131const char * mbedtls_dhm_rfc3526_modp_3072_g = "02";
132
133const char * mbedtls_dhm_rfc3526_modp_4096_p =
134 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
135 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
136 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
137 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
138 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
139 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
140 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
141 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
142 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
143 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
144 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
145 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
146 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
147 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
148 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
149 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
150 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
151 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
152 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
153 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
154 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
155 "FFFFFFFFFFFFFFFF";
156const char * mbedtls_dhm_rfc3526_modp_4096_g = "02";
Paul Bakker34617722014-06-13 17:20:13 +0200157/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200158static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakker34617722014-06-13 17:20:13 +0200159 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
160}
161
Paul Bakker5121ce52009-01-03 21:22:43 +0000162/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200163 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +0000164 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200165static int dhm_read_bignum( mbedtls_mpi *X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000166 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000167 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000168{
169 int ret, n;
170
171 if( end - *p < 2 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000173
174 n = ( (*p)[0] << 8 ) | (*p)[1];
175 (*p) += 2;
176
177 if( (int)( end - *p ) < n )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
181 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000182
183 (*p) += n;
184
185 return( 0 );
186}
187
188/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000189 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +0000190 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000191 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +0000192 *
193 * For more information on the attack, see:
194 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
195 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +0000196 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000198{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 mbedtls_mpi L, U;
200 int ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000201
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200202 mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
Paul Bakker3d8fb632014-04-17 12:42:41 +0200203
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200204 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
205 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000206
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 if( mbedtls_mpi_cmp_mpi( param, &L ) >= 0 &&
208 mbedtls_mpi_cmp_mpi( param, &U ) <= 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000209 {
Paul Bakker345a6fe2011-02-28 21:20:02 +0000210 ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000211 }
212
Paul Bakker3d8fb632014-04-17 12:42:41 +0200213cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200214 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
Paul Bakker345a6fe2011-02-28 21:20:02 +0000215 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000216}
217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
Paul Bakker8f870b02014-06-20 13:32:38 +0200219{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200220 memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
Paul Bakker8f870b02014-06-20 13:32:38 +0200221}
222
Paul Bakkerc47840e2011-02-20 16:37:30 +0000223/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 * Parse the ServerKeyExchange parameters
225 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200226int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 unsigned char **p,
Paul Bakkerff60ee62010-03-16 21:09:09 +0000228 const unsigned char *end )
Paul Bakker5121ce52009-01-03 21:22:43 +0000229{
Paul Bakker13ed9ab2012-04-16 09:43:49 +0000230 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000231
Paul Bakker5121ce52009-01-03 21:22:43 +0000232 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
233 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
234 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
235 return( ret );
236
Paul Bakker345a6fe2011-02-28 21:20:02 +0000237 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
238 return( ret );
239
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200240 ctx->len = mbedtls_mpi_size( &ctx->P );
Paul Bakker5121ce52009-01-03 21:22:43 +0000241
Paul Bakker5121ce52009-01-03 21:22:43 +0000242 return( 0 );
243}
244
245/*
246 * Setup and write the ServerKeyExchange parameters
247 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200248int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000249 unsigned char *output, size_t *olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000250 int (*f_rng)(void *, unsigned char *, size_t),
251 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000252{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000253 int ret, count = 0;
Paul Bakker23986e52011-04-24 08:57:21 +0000254 size_t n1, n2, n3;
Paul Bakker5121ce52009-01-03 21:22:43 +0000255 unsigned char *p;
256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
258 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000259
Paul Bakker5121ce52009-01-03 21:22:43 +0000260 /*
Paul Bakkerff7fe672010-07-18 09:45:05 +0000261 * Generate X as large as possible ( < P )
Paul Bakker5121ce52009-01-03 21:22:43 +0000262 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000263 do
264 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200265 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000266
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200267 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
268 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000269
270 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200271 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000272 }
273 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000274
Paul Bakkerff7fe672010-07-18 09:45:05 +0000275 /*
276 * Calculate GX = G^X mod P
277 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200278 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000279 &ctx->P , &ctx->RP ) );
280
Paul Bakker345a6fe2011-02-28 21:20:02 +0000281 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000282 return( ret );
283
Paul Bakker5121ce52009-01-03 21:22:43 +0000284 /*
285 * export P, G, GX
286 */
287#define DHM_MPI_EXPORT(X,n) \
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200288 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, p + 2, n ) ); \
Paul Bakker5121ce52009-01-03 21:22:43 +0000289 *p++ = (unsigned char)( n >> 8 ); \
290 *p++ = (unsigned char)( n ); p += n;
291
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 n1 = mbedtls_mpi_size( &ctx->P );
293 n2 = mbedtls_mpi_size( &ctx->G );
294 n3 = mbedtls_mpi_size( &ctx->GX );
Paul Bakker5121ce52009-01-03 21:22:43 +0000295
296 p = output;
297 DHM_MPI_EXPORT( &ctx->P , n1 );
298 DHM_MPI_EXPORT( &ctx->G , n2 );
299 DHM_MPI_EXPORT( &ctx->GX, n3 );
300
301 *olen = p - output;
302
303 ctx->len = n1;
304
305cleanup:
306
307 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200308 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000309
310 return( 0 );
311}
312
313/*
314 * Import the peer's public value G^Y
315 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200316int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
Paul Bakker23986e52011-04-24 08:57:21 +0000317 const unsigned char *input, size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000318{
319 int ret;
320
321 if( ctx == NULL || ilen < 1 || ilen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000323
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200324 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
325 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000326
327 return( 0 );
328}
329
330/*
331 * Create own private value X and export G^X
332 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200333int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
Paul Bakker23986e52011-04-24 08:57:21 +0000334 unsigned char *output, size_t olen,
Paul Bakkera3d195c2011-11-27 21:07:34 +0000335 int (*f_rng)(void *, unsigned char *, size_t),
336 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000337{
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000338 int ret, count = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000339
340 if( ctx == NULL || olen < 1 || olen > ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200341 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000342
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200343 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
344 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000345
Paul Bakker5121ce52009-01-03 21:22:43 +0000346 /*
347 * generate X and calculate GX = G^X mod P
348 */
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000349 do
350 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200351 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000352
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200353 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
354 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000355
356 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200357 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000358 }
359 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000360
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200361 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
Paul Bakker5121ce52009-01-03 21:22:43 +0000362 &ctx->P , &ctx->RP ) );
363
Paul Bakker345a6fe2011-02-28 21:20:02 +0000364 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
365 return( ret );
Paul Bakkerc47840e2011-02-20 16:37:30 +0000366
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200367 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000368
369cleanup:
370
371 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200372 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000373
374 return( 0 );
375}
376
377/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200378 * Use the blinding method and optimisation suggested in section 10 of:
379 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200380 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200381 * Berlin Heidelberg, 1996. p. 104-113.
382 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200383static int dhm_update_blinding( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200384 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
385{
386 int ret, count;
387
388 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200389 * Don't use any blinding the first time a particular X is used,
390 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200391 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200392 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200393 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200394 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
395 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
396 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200397
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200398 return( 0 );
399 }
400
401 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200402 * Ok, we need blinding. Can we re-use existing values?
403 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200404 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200405 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200406 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200407 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
408 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200409
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200410 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
411 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200412
413 return( 0 );
414 }
415
416 /*
417 * We need to generate blinding values from scratch
418 */
419
420 /* Vi = random( 2, P-1 ) */
421 count = 0;
422 do
423 {
Ron Eldor7269fee2017-01-12 14:50:50 +0200424 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 +0200425
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200426 while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
427 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200428
429 if( count++ > 10 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200430 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200431 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200432 while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200433
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200434 /* Vf = Vi^-X mod P */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200435 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
436 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 +0200437
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200438cleanup:
439 return( ret );
440}
441
442/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000443 * Derive and export the shared secret (G^Y)^X mod P
444 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200445int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100446 unsigned char *output, size_t output_size, size_t *olen,
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200447 int (*f_rng)(void *, unsigned char *, size_t),
448 void *p_rng )
Paul Bakker5121ce52009-01-03 21:22:43 +0000449{
450 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200451 mbedtls_mpi GYb;
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200452
Manuel Pégourié-Gonnard33352052015-06-02 16:17:08 +0100453 if( ctx == NULL || output_size < ctx->len )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
Paul Bakker5121ce52009-01-03 21:22:43 +0000455
Paul Bakker345a6fe2011-02-28 21:20:02 +0000456 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
Paul Bakkerc47840e2011-02-20 16:37:30 +0000457 return( ret );
458
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 mbedtls_mpi_init( &GYb );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200460
461 /* Blind peer's value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200462 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200463 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200464 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
465 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
466 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200467 }
468 else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200470
471 /* Do modular exponentiation */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200472 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200473 &ctx->P, &ctx->RP ) );
474
475 /* Unblind secret value */
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200476 if( f_rng != NULL )
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200477 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200478 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
479 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200480 }
481
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200482 *olen = mbedtls_mpi_size( &ctx->K );
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200484 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000485
486cleanup:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200487 mbedtls_mpi_free( &GYb );
Paul Bakker5121ce52009-01-03 21:22:43 +0000488
489 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200490 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000491
492 return( 0 );
493}
494
495/*
496 * Free the components of a DHM key
497 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200498void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
Paul Bakker5121ce52009-01-03 21:22:43 +0000499{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500 mbedtls_mpi_free( &ctx->pX); mbedtls_mpi_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->Vi );
501 mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY );
502 mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); mbedtls_mpi_free( &ctx->G );
503 mbedtls_mpi_free( &ctx->P );
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200504
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505 mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000506}
507
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200508#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200509/*
510 * Parse DHM parameters
511 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200512int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
Paul Bakkerb9e4e2c2014-05-01 14:18:25 +0200513 size_t dhminlen )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200514{
515 int ret;
516 size_t len;
517 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518#if defined(MBEDTLS_PEM_PARSE_C)
519 mbedtls_pem_context pem;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200520
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200521 mbedtls_pem_init( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200522
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200523 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Manuel Pégourié-Gonnard0ece0f92015-05-12 12:43:54 +0200524 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200525 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
526 else
527 ret = mbedtls_pem_read_buffer( &pem,
528 "-----BEGIN DH PARAMETERS-----",
529 "-----END DH PARAMETERS-----",
530 dhmin, NULL, 0, &dhminlen );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200531
532 if( ret == 0 )
533 {
534 /*
535 * Was PEM encoded
536 */
537 dhminlen = pem.buflen;
538 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200539 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200540 goto exit;
541
542 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
543#else
544 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200545#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200546 end = p + dhminlen;
547
548 /*
549 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400550 * prime INTEGER, -- P
551 * generator INTEGER, -- g
552 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200553 * }
554 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200555 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
556 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200557 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200559 goto exit;
560 }
561
562 end = p + len;
563
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200564 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
565 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200566 {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200567 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200568 goto exit;
569 }
570
571 if( p != end )
572 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200573 /* This might be the optional privateValueLength.
574 * If so, we can cleanly discard it */
575 mbedtls_mpi rec;
576 mbedtls_mpi_init( &rec );
577 ret = mbedtls_asn1_get_mpi( &p, end, &rec );
578 mbedtls_mpi_free( &rec );
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400579 if ( ret != 0 )
580 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200581 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400582 goto exit;
583 }
584 if ( p != end )
585 {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200586 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
587 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400588 goto exit;
589 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200590 }
591
592 ret = 0;
593
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200594 dhm->len = mbedtls_mpi_size( &dhm->P );
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100595
Paul Bakker40ce79f2013-09-15 17:43:54 +0200596exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200597#if defined(MBEDTLS_PEM_PARSE_C)
598 mbedtls_pem_free( &pem );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200599#endif
600 if( ret != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200601 mbedtls_dhm_free( dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200602
603 return( ret );
604}
605
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200606#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200607/*
608 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200609 *
610 * The file is expected to contain either PEM or DER encoded data.
611 * A terminating null byte is always appended. It is included in the announced
612 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200613 */
614static int load_file( const char *path, unsigned char **buf, size_t *n )
615{
616 FILE *f;
617 long size;
618
619 if( ( f = fopen( path, "rb" ) ) == NULL )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200620 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200621
622 fseek( f, 0, SEEK_END );
623 if( ( size = ftell( f ) ) == -1 )
624 {
625 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200627 }
628 fseek( f, 0, SEEK_SET );
629
630 *n = (size_t) size;
631
632 if( *n + 1 == 0 ||
Manuel Pégourié-Gonnard7551cb92015-05-26 16:04:06 +0200633 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200634 {
635 fclose( f );
Manuel Pégourié-Gonnard6a8ca332015-05-28 09:33:39 +0200636 return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200637 }
638
639 if( fread( *buf, 1, *n, f ) != *n )
640 {
641 fclose( f );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642 mbedtls_free( *buf );
643 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200644 }
645
646 fclose( f );
647
648 (*buf)[*n] = '\0';
649
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200650 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
651 ++*n;
652
Paul Bakker40ce79f2013-09-15 17:43:54 +0200653 return( 0 );
654}
655
656/*
657 * Load and parse DHM parameters
658 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200659int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200660{
661 int ret;
662 size_t n;
663 unsigned char *buf;
664
Paul Bakker66d5d072014-06-17 16:39:18 +0200665 if( ( ret = load_file( path, &buf, &n ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200666 return( ret );
667
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200668 ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200669
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200670 mbedtls_zeroize( buf, n );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200671 mbedtls_free( buf );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200672
673 return( ret );
674}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200675#endif /* MBEDTLS_FS_IO */
676#endif /* MBEDTLS_ASN1_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200677
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000679
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200680static const char mbedtls_test_dhm_params[] =
681"-----BEGIN DH PARAMETERS-----\r\n"
682"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
683"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
684"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
685"-----END DH PARAMETERS-----\r\n";
686
687static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200688
Paul Bakker5121ce52009-01-03 21:22:43 +0000689/*
690 * Checkup routine
691 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692int mbedtls_dhm_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000693{
Paul Bakker40ce79f2013-09-15 17:43:54 +0200694 int ret;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200695 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200696
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200697 mbedtls_dhm_init( &dhm );
Paul Bakker8f870b02014-06-20 13:32:38 +0200698
Paul Bakker40ce79f2013-09-15 17:43:54 +0200699 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700 mbedtls_printf( " DHM parameter load: " );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200701
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200702 if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
703 (const unsigned char *) mbedtls_test_dhm_params,
704 mbedtls_test_dhm_params_len ) ) != 0 )
Paul Bakker40ce79f2013-09-15 17:43:54 +0200705 {
706 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707 mbedtls_printf( "failed\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200708
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200709 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200710 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200711 }
712
713 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200714 mbedtls_printf( "passed\n\n" );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200715
Paul Bakker8f870b02014-06-20 13:32:38 +0200716exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200717 mbedtls_dhm_free( &dhm );
Paul Bakker40ce79f2013-09-15 17:43:54 +0200718
Paul Bakker8f870b02014-06-20 13:32:38 +0200719 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000720}
721
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200722#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000723
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200724#endif /* MBEDTLS_DHM_C */