blob: 2e512223637a9bed2587f35d65894363fa9d02e2 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * Diffie-Hellman-Merkle key exchange
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
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 Bakker5121ce52009-01-03 21:22:43 +000018 */
19/*
Simon Butcherbdae02c2016-01-20 00:44:42 +000020 * The following sources were referenced in the design of this implementation
21 * of the Diffie-Hellman-Merkle algorithm:
Paul Bakker5121ce52009-01-03 21:22:43 +000022 *
Simon Butcherbdae02c2016-01-20 00:44:42 +000023 * [1] Handbook of Applied Cryptography - 1997, Chapter 12
24 * Menezes, van Oorschot and Vanstone
25 *
Paul Bakker5121ce52009-01-03 21:22:43 +000026 */
27
Gilles Peskinedb09ef62020-06-03 01:43:33 +020028#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000029
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if defined(MBEDTLS_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000031
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020032# include "mbedtls/dhm.h"
33# include "mbedtls/platform_util.h"
34# include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020036# include <string.h>
Rich Evans00ab4702015-02-06 13:43:58 +000037
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020038# if defined(MBEDTLS_PEM_PARSE_C)
39# include "mbedtls/pem.h"
40# endif
Paul Bakker40ce79f2013-09-15 17:43:54 +020041
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020042# if defined(MBEDTLS_ASN1_PARSE_C)
43# include "mbedtls/asn1.h"
44# endif
Paul Bakker40ce79f2013-09-15 17:43:54 +020045
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020046# if defined(MBEDTLS_PLATFORM_C)
47# include "mbedtls/platform.h"
48# else
49# include <stdlib.h>
50# include <stdio.h>
51# define mbedtls_printf printf
52# define mbedtls_calloc calloc
53# define mbedtls_free free
54# endif
Paul Bakker40ce79f2013-09-15 17:43:54 +020055
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020056# if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020057
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020058# define DHM_VALIDATE_RET(cond) \
59 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA)
60# define DHM_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE(cond)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050061
Paul Bakker5121ce52009-01-03 21:22:43 +000062/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020063 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000064 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020065static int
66dhm_read_bignum(mbedtls_mpi *X, unsigned char **p, const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +000067{
68 int ret, n;
69
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020070 if (end - *p < 2)
71 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +000072
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020073 n = ((*p)[0] << 8) | (*p)[1];
Paul Bakker5121ce52009-01-03 21:22:43 +000074 (*p) += 2;
75
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020076 if ((int)(end - *p) < n)
77 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +000078
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020079 if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0)
80 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
Paul Bakker5121ce52009-01-03 21:22:43 +000081
82 (*p) += n;
83
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020084 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000085}
86
87/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000088 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000089 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000090 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000091 *
Janos Follathaa325d72017-09-20 15:33:24 +010092 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +010093 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +010094 *
Paul Bakker345a6fe2011-02-28 21:20:02 +000095 * For more information on the attack, see:
96 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
97 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +000098 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020099static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
Paul Bakkerc47840e2011-02-20 16:37:30 +0000100{
Gilles Peskine8e38acc2021-03-31 22:56:43 +0200101 mbedtls_mpi U;
Janos Follathaa325d72017-09-20 15:33:24 +0100102 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000103
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200104 mbedtls_mpi_init(&U);
Paul Bakker3d8fb632014-04-17 12:42:41 +0200105
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200106 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
Paul Bakkerc47840e2011-02-20 16:37:30 +0000107
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200108 if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
109 mbedtls_mpi_cmp_mpi(param, &U) > 0) {
Janos Follathaa325d72017-09-20 15:33:24 +0100110 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000111 }
112
Paul Bakker3d8fb632014-04-17 12:42:41 +0200113cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200114 mbedtls_mpi_free(&U);
115 return ret;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000116}
117
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200118void mbedtls_dhm_init(mbedtls_dhm_context *ctx)
Paul Bakker8f870b02014-06-20 13:32:38 +0200119{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200120 DHM_VALIDATE(ctx != NULL);
121 memset(ctx, 0, sizeof(mbedtls_dhm_context));
Paul Bakker8f870b02014-06-20 13:32:38 +0200122}
123
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200124size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)
Gilles Peskine487bbf62021-05-27 22:17:07 +0200125{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200126 return mbedtls_mpi_bitlen(&ctx->P);
Gilles Peskine487bbf62021-05-27 22:17:07 +0200127}
128
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200129size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx)
Gilles Peskine487bbf62021-05-27 22:17:07 +0200130{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200131 return mbedtls_mpi_size(&ctx->P);
Gilles Peskine487bbf62021-05-27 22:17:07 +0200132}
133
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200134int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,
135 mbedtls_dhm_parameter param,
136 mbedtls_mpi *dest)
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200137{
138 const mbedtls_mpi *src = NULL;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200139 switch (param) {
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200140 case MBEDTLS_DHM_PARAM_P:
141 src = &ctx->P;
142 break;
143 case MBEDTLS_DHM_PARAM_G:
144 src = &ctx->G;
145 break;
146 case MBEDTLS_DHM_PARAM_X:
147 src = &ctx->X;
148 break;
149 case MBEDTLS_DHM_PARAM_GX:
150 src = &ctx->GX;
151 break;
152 case MBEDTLS_DHM_PARAM_GY:
153 src = &ctx->GY;
154 break;
155 case MBEDTLS_DHM_PARAM_K:
156 src = &ctx->K;
157 break;
158 default:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200159 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200160 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200161 return mbedtls_mpi_copy(dest, src);
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200162}
163
Paul Bakkerc47840e2011-02-20 16:37:30 +0000164/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000165 * Parse the ServerKeyExchange parameters
166 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200167int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
168 unsigned char **p,
169 const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +0000170{
Janos Follath24eed8d2019-11-22 13:21:35 +0000171 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200172 DHM_VALIDATE_RET(ctx != NULL);
173 DHM_VALIDATE_RET(p != NULL && *p != NULL);
174 DHM_VALIDATE_RET(end != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000175
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200176 if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 ||
177 (ret = dhm_read_bignum(&ctx->G, p, end)) != 0 ||
178 (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0)
179 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000180
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200181 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0)
182 return ret;
Paul Bakker345a6fe2011-02-28 21:20:02 +0000183
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200184 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000185}
186
Gilles Peskine17f1a262021-03-31 22:48:14 +0200187/*
Gilles Peskineda7ee012021-03-31 23:04:50 +0200188 * Pick a random R in the range [2, M-2] for blinding or key generation.
Gilles Peskine17f1a262021-03-31 22:48:14 +0200189 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200190static int dhm_random_below(mbedtls_mpi *R,
191 const mbedtls_mpi *M,
192 int (*f_rng)(void *, unsigned char *, size_t),
193 void *p_rng)
Gilles Peskine17f1a262021-03-31 22:48:14 +0200194{
Gilles Peskineda7ee012021-03-31 23:04:50 +0200195 int ret;
Gilles Peskine17f1a262021-03-31 22:48:14 +0200196
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200197 MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
198 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
Gilles Peskine17f1a262021-03-31 22:48:14 +0200199
200cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200201 return ret;
Gilles Peskine17f1a262021-03-31 22:48:14 +0200202}
203
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200204static int dhm_make_common(mbedtls_dhm_context *ctx,
205 int x_size,
206 int (*f_rng)(void *, unsigned char *, size_t),
207 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000208{
Gilles Peskine17f1a262021-03-31 22:48:14 +0200209 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000210
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200211 if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0)
212 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
213 if (x_size < 0)
214 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerb5b20f12012-09-16 15:07:49 +0000215
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200216 if ((unsigned)x_size < mbedtls_mpi_size(&ctx->P)) {
217 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
218 } else {
Gilles Peskine17f1a262021-03-31 22:48:14 +0200219 /* Generate X as large as possible ( <= P - 2 ) */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200220 ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
221 if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE)
222 return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
223 if (ret != 0)
224 return ret;
Gilles Peskine17f1a262021-03-31 22:48:14 +0200225 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000226
Paul Bakkerff7fe672010-07-18 09:45:05 +0000227 /*
228 * Calculate GX = G^X mod P
229 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200230 MBEDTLS_MPI_CHK(
231 mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X, &ctx->P, &ctx->RP));
Paul Bakker5121ce52009-01-03 21:22:43 +0000232
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200233 if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0)
234 return ret;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000235
Gilles Peskinecb660f22021-03-31 22:35:13 +0200236cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200237 return ret;
Gilles Peskinecb660f22021-03-31 22:35:13 +0200238}
239
240/*
241 * Setup and write the ServerKeyExchange parameters
242 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200243int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx,
244 int x_size,
245 unsigned char *output,
246 size_t *olen,
247 int (*f_rng)(void *, unsigned char *, size_t),
248 void *p_rng)
Gilles Peskinecb660f22021-03-31 22:35:13 +0200249{
250 int ret;
251 size_t n1, n2, n3;
252 unsigned char *p;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200253 DHM_VALIDATE_RET(ctx != NULL);
254 DHM_VALIDATE_RET(output != NULL);
255 DHM_VALIDATE_RET(olen != NULL);
256 DHM_VALIDATE_RET(f_rng != NULL);
Gilles Peskinecb660f22021-03-31 22:35:13 +0200257
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200258 ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
259 if (ret != 0)
Gilles Peskinecb660f22021-03-31 22:35:13 +0200260 goto cleanup;
261
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200262 /*
263 * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
264 * not required". We omit leading zeros for compactness.
265 */
266# define DHM_MPI_EXPORT(X, n) \
267 do { \
268 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X), p + 2, (n))); \
269 *p++ = (unsigned char)((n) >> 8); \
270 *p++ = (unsigned char)((n)); \
271 p += (n); \
272 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000273
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200274 n1 = mbedtls_mpi_size(&ctx->P);
275 n2 = mbedtls_mpi_size(&ctx->G);
276 n3 = mbedtls_mpi_size(&ctx->GX);
Paul Bakker5121ce52009-01-03 21:22:43 +0000277
278 p = output;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200279 DHM_MPI_EXPORT(&ctx->P, n1);
280 DHM_MPI_EXPORT(&ctx->G, n2);
281 DHM_MPI_EXPORT(&ctx->GX, n3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000282
Hanno Beckere71ad122017-09-28 10:32:25 +0100283 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000284
Paul Bakker5121ce52009-01-03 21:22:43 +0000285cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200286 if (ret != 0 && ret > -128)
287 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
288 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000289}
290
291/*
Hanno Becker8880e752017-10-04 13:15:08 +0100292 * Set prime modulus and generator
293 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200294int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
295 const mbedtls_mpi *P,
296 const mbedtls_mpi *G)
Hanno Becker8880e752017-10-04 13:15:08 +0100297{
Janos Follath24eed8d2019-11-22 13:21:35 +0000298 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200299 DHM_VALIDATE_RET(ctx != NULL);
300 DHM_VALIDATE_RET(P != NULL);
301 DHM_VALIDATE_RET(G != NULL);
Hanno Becker8880e752017-10-04 13:15:08 +0100302
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200303 if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
304 (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
305 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
Hanno Becker8880e752017-10-04 13:15:08 +0100306 }
307
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200308 return 0;
Hanno Becker8880e752017-10-04 13:15:08 +0100309}
310
311/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000312 * Import the peer's public value G^Y
313 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200314int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
315 const unsigned char *input,
316 size_t ilen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000317{
Janos Follath24eed8d2019-11-22 13:21:35 +0000318 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200319 DHM_VALIDATE_RET(ctx != NULL);
320 DHM_VALIDATE_RET(input != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000321
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200322 if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx))
323 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000324
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200325 if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0)
326 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
Paul Bakker5121ce52009-01-03 21:22:43 +0000327
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200328 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000329}
330
331/*
332 * Create own private value X and export G^X
333 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200334int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx,
335 int x_size,
336 unsigned char *output,
337 size_t olen,
338 int (*f_rng)(void *, unsigned char *, size_t),
339 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000340{
Gilles Peskinecb660f22021-03-31 22:35:13 +0200341 int ret;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200342 DHM_VALIDATE_RET(ctx != NULL);
343 DHM_VALIDATE_RET(output != NULL);
344 DHM_VALIDATE_RET(f_rng != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000345
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200346 if (olen < 1 || olen > mbedtls_dhm_get_len(ctx))
347 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000348
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200349 ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
350 if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED)
351 return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;
352 if (ret != 0)
Gilles Peskinecb660f22021-03-31 22:35:13 +0200353 goto cleanup;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000354
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200355 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000356
357cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200358 if (ret != 0 && ret > -128)
359 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);
360 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000361}
362
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200363/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200364 * Use the blinding method and optimisation suggested in section 10 of:
365 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200366 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200367 * Berlin Heidelberg, 1996. p. 104-113.
368 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200369static int dhm_update_blinding(mbedtls_dhm_context *ctx,
370 int (*f_rng)(void *, unsigned char *, size_t),
371 void *p_rng)
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200372{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200373 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200374 mbedtls_mpi R;
375
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200376 mbedtls_mpi_init(&R);
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200377
378 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200379 * Don't use any blinding the first time a particular X is used,
380 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200381 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200382 if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) {
383 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X));
384 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1));
385 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1));
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200386
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200387 return 0;
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200388 }
389
390 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200391 * Ok, we need blinding. Can we re-use existing values?
392 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200393 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200394 if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) {
395 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
396 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200397
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200398 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
399 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200400
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200401 return 0;
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200402 }
403
404 /*
405 * We need to generate blinding values from scratch
406 */
407
Gilles Peskine7b2b66e2021-03-31 22:50:57 +0200408 /* Vi = random( 2, P-2 ) */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200409 MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200410
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200411 /* Vf = Vi^-X mod P
412 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
413 * then elevate to the Xth power. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200414 MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng));
415 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R));
416 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
417 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P));
418 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R));
419 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200420
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200421 MBEDTLS_MPI_CHK(
422 mbedtls_mpi_exp_mod(&ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200423
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200424cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200425 mbedtls_mpi_free(&R);
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200426
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200427 return ret;
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200428}
429
430/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000431 * Derive and export the shared secret (G^Y)^X mod P
432 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200433int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,
434 unsigned char *output,
435 size_t output_size,
436 size_t *olen,
437 int (*f_rng)(void *, unsigned char *, size_t),
438 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000439{
Janos Follath24eed8d2019-11-22 13:21:35 +0000440 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200441 mbedtls_mpi GYb;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200442 DHM_VALIDATE_RET(ctx != NULL);
443 DHM_VALIDATE_RET(output != NULL);
444 DHM_VALIDATE_RET(olen != NULL);
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200445
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200446 if (f_rng == NULL)
447 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard1a877222021-06-15 11:29:26 +0200448
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200449 if (output_size < mbedtls_dhm_get_len(ctx))
450 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakker5121ce52009-01-03 21:22:43 +0000451
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200452 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0)
453 return ret;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000454
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200455 mbedtls_mpi_init(&GYb);
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200456
457 /* Blind peer's value */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200458 MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));
459 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));
460 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200461
462 /* Do modular exponentiation */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200463 MBEDTLS_MPI_CHK(
464 mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X, &ctx->P, &ctx->RP));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200465
466 /* Unblind secret value */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200467 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
468 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200469
Gilles Peskine03299dc2021-04-13 22:10:24 +0200470 /* Output the secret without any leading zero byte. This is mandatory
471 * for TLS per RFC 5246 §8.1.2. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200472 *olen = mbedtls_mpi_size(&ctx->K);
473 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000474
475cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200476 mbedtls_mpi_free(&GYb);
Paul Bakker5121ce52009-01-03 21:22:43 +0000477
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200478 if (ret != 0)
479 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
Paul Bakker5121ce52009-01-03 21:22:43 +0000480
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200481 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000482}
483
484/*
485 * Free the components of a DHM key
486 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200487void mbedtls_dhm_free(mbedtls_dhm_context *ctx)
Paul Bakker5121ce52009-01-03 21:22:43 +0000488{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200489 if (ctx == NULL)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500490 return;
491
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200492 mbedtls_mpi_free(&ctx->pX);
493 mbedtls_mpi_free(&ctx->Vf);
494 mbedtls_mpi_free(&ctx->Vi);
495 mbedtls_mpi_free(&ctx->RP);
496 mbedtls_mpi_free(&ctx->K);
497 mbedtls_mpi_free(&ctx->GY);
498 mbedtls_mpi_free(&ctx->GX);
499 mbedtls_mpi_free(&ctx->X);
500 mbedtls_mpi_free(&ctx->G);
501 mbedtls_mpi_free(&ctx->P);
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200502
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200503 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
Paul Bakker5121ce52009-01-03 21:22:43 +0000504}
505
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200506# if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200507/*
508 * Parse DHM parameters
509 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200510int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm,
511 const unsigned char *dhmin,
512 size_t dhminlen)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200513{
Janos Follath24eed8d2019-11-22 13:21:35 +0000514 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200515 size_t len;
516 unsigned char *p, *end;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200517# if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200518 mbedtls_pem_context pem;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200519# endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200520
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200521 DHM_VALIDATE_RET(dhm != NULL);
522 DHM_VALIDATE_RET(dhmin != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500523
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200524# if defined(MBEDTLS_PEM_PARSE_C)
525 mbedtls_pem_init(&pem);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200526
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200527 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200528 if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0')
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200529 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
530 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200531 ret = mbedtls_pem_read_buffer(&pem, "-----BEGIN DH PARAMETERS-----",
532 "-----END DH PARAMETERS-----", dhmin,
533 NULL, 0, &dhminlen);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200534
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200535 if (ret == 0) {
Paul Bakker40ce79f2013-09-15 17:43:54 +0200536 /*
537 * Was PEM encoded
538 */
539 dhminlen = pem.buflen;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200540 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200541 goto exit;
542
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200543 p = (ret == 0) ? pem.buf : (unsigned char *)dhmin;
544# else
545 p = (unsigned char *)dhmin;
546# endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200547 end = p + dhminlen;
548
549 /*
550 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400551 * prime INTEGER, -- P
552 * generator INTEGER, -- g
553 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200554 * }
555 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200556 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
557 MBEDTLS_ASN1_CONSTRUCTED |
558 MBEDTLS_ASN1_SEQUENCE)) != 0) {
559 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200560 goto exit;
561 }
562
563 end = p + len;
564
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200565 if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
566 (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
567 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200568 goto exit;
569 }
570
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200571 if (p != end) {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200572 /* This might be the optional privateValueLength.
573 * If so, we can cleanly discard it */
574 mbedtls_mpi rec;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200575 mbedtls_mpi_init(&rec);
576 ret = mbedtls_asn1_get_mpi(&p, end, &rec);
577 mbedtls_mpi_free(&rec);
578 if (ret != 0) {
579 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400580 goto exit;
581 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200582 if (p != end) {
583 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
584 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400585 goto exit;
586 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200587 }
588
589 ret = 0;
590
591exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200592# if defined(MBEDTLS_PEM_PARSE_C)
593 mbedtls_pem_free(&pem);
594# endif
595 if (ret != 0)
596 mbedtls_dhm_free(dhm);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200597
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200598 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200599}
600
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200601# if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200602/*
603 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200604 *
605 * The file is expected to contain either PEM or DER encoded data.
606 * A terminating null byte is always appended. It is included in the announced
607 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200608 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200609static int load_file(const char *path, unsigned char **buf, size_t *n)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200610{
611 FILE *f;
612 long size;
613
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200614 if ((f = fopen(path, "rb")) == NULL)
615 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200616
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200617 fseek(f, 0, SEEK_END);
618 if ((size = ftell(f)) == -1) {
619 fclose(f);
620 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200621 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200622 fseek(f, 0, SEEK_SET);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200623
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200624 *n = (size_t)size;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200625
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200626 if (*n + 1 == 0 || (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
627 fclose(f);
628 return MBEDTLS_ERR_DHM_ALLOC_FAILED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200629 }
630
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200631 if (fread(*buf, 1, *n, f) != *n) {
632 fclose(f);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100633
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200634 mbedtls_platform_zeroize(*buf, *n + 1);
635 mbedtls_free(*buf);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100636
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200637 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200638 }
639
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200640 fclose(f);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200641
642 (*buf)[*n] = '\0';
643
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200644 if (strstr((const char *)*buf, "-----BEGIN ") != NULL)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200645 ++*n;
646
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200647 return 0;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200648}
649
650/*
651 * Load and parse DHM parameters
652 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200653int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200654{
Janos Follath24eed8d2019-11-22 13:21:35 +0000655 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200656 size_t n;
657 unsigned char *buf;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200658 DHM_VALIDATE_RET(dhm != NULL);
659 DHM_VALIDATE_RET(path != NULL);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200660
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200661 if ((ret = load_file(path, &buf, &n)) != 0)
662 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200663
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200664 ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200665
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200666 mbedtls_platform_zeroize(buf, n);
667 mbedtls_free(buf);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200668
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200669 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200670}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200671# endif /* MBEDTLS_FS_IO */
672# endif /* MBEDTLS_ASN1_PARSE_C */
673# endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200674
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200675# if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000676
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200677# if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200678static const char mbedtls_test_dhm_params[] =
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200679 "-----BEGIN DH PARAMETERS-----\r\n"
680 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
681 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
682 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
683 "-----END DH PARAMETERS-----\r\n";
684# else /* MBEDTLS_PEM_PARSE_C */
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100685static const char mbedtls_test_dhm_params[] = {
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200686 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
687 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
688 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
689 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
690 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
691 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
692 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
693 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
694 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
695 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
696 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
697 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
698};
699# endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200700
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200701static const size_t mbedtls_test_dhm_params_len =
702 sizeof(mbedtls_test_dhm_params);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200703
Paul Bakker5121ce52009-01-03 21:22:43 +0000704/*
705 * Checkup routine
706 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200707int mbedtls_dhm_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +0000708{
Janos Follath24eed8d2019-11-22 13:21:35 +0000709 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200710 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200711
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200712 mbedtls_dhm_init(&dhm);
Paul Bakker8f870b02014-06-20 13:32:38 +0200713
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200714 if (verbose != 0)
715 mbedtls_printf(" DHM parameter load: ");
Paul Bakker40ce79f2013-09-15 17:43:54 +0200716
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200717 if ((ret = mbedtls_dhm_parse_dhm(
718 &dhm, (const unsigned char *)mbedtls_test_dhm_params,
719 mbedtls_test_dhm_params_len)) != 0) {
720 if (verbose != 0)
721 mbedtls_printf("failed\n");
Paul Bakker40ce79f2013-09-15 17:43:54 +0200722
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200723 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200724 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200725 }
726
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200727 if (verbose != 0)
728 mbedtls_printf("passed\n\n");
Paul Bakker40ce79f2013-09-15 17:43:54 +0200729
Paul Bakker8f870b02014-06-20 13:32:38 +0200730exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200731 mbedtls_dhm_free(&dhm);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200732
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200733 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000734}
735
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200736# endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000737
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200738#endif /* MBEDTLS_DHM_C */