blob: c6f955ee42685ae711c56870688b37ff27b87562 [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
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000032#include "mbedtls/dhm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050033#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000034#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000035
Rich Evans00ab4702015-02-06 13:43:58 +000036#include <string.h>
37
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020038#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000039#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020040#endif
41
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020042#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020044#endif
45
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000046#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020047
Reuven Levin1f35ca92017-12-07 10:09:32 +000048#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020049
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010050#define DHM_VALIDATE_RET(cond) \
51 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA)
52#define DHM_VALIDATE(cond) \
53 MBEDTLS_INTERNAL_VALIDATE(cond)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050054
Paul Bakker5121ce52009-01-03 21:22:43 +000055/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020056 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000057 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010058static int dhm_read_bignum(mbedtls_mpi *X,
59 unsigned char **p,
60 const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +000061{
62 int ret, n;
63
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010064 if (end - *p < 2) {
65 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
66 }
Paul Bakker5121ce52009-01-03 21:22:43 +000067
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010068 n = ((*p)[0] << 8) | (*p)[1];
Paul Bakker5121ce52009-01-03 21:22:43 +000069 (*p) += 2;
70
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010071 if ((int) (end - *p) < n) {
72 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
73 }
Paul Bakker5121ce52009-01-03 21:22:43 +000074
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010075 if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {
76 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
77 }
Paul Bakker5121ce52009-01-03 21:22:43 +000078
79 (*p) += n;
80
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010081 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000082}
83
84/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000085 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000086 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000087 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000088 *
Janos Follathaa325d72017-09-20 15:33:24 +010089 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +010090 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +010091 *
Paul Bakker345a6fe2011-02-28 21:20:02 +000092 * For more information on the attack, see:
93 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
94 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +000095 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010096static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
Paul Bakkerc47840e2011-02-20 16:37:30 +000097{
Gilles Peskine58df4c92021-03-31 22:56:43 +020098 mbedtls_mpi U;
Janos Follathaa325d72017-09-20 15:33:24 +010099 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000100
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100101 mbedtls_mpi_init(&U);
Paul Bakker3d8fb632014-04-17 12:42:41 +0200102
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100103 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
Paul Bakkerc47840e2011-02-20 16:37:30 +0000104
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100105 if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
106 mbedtls_mpi_cmp_mpi(param, &U) > 0) {
Janos Follathaa325d72017-09-20 15:33:24 +0100107 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000108 }
109
Paul Bakker3d8fb632014-04-17 12:42:41 +0200110cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100111 mbedtls_mpi_free(&U);
112 return ret;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000113}
114
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100115void mbedtls_dhm_init(mbedtls_dhm_context *ctx)
Paul Bakker8f870b02014-06-20 13:32:38 +0200116{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100117 DHM_VALIDATE(ctx != NULL);
118 memset(ctx, 0, sizeof(mbedtls_dhm_context));
Paul Bakker8f870b02014-06-20 13:32:38 +0200119}
120
Paul Bakkerc47840e2011-02-20 16:37:30 +0000121/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000122 * Parse the ServerKeyExchange parameters
123 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100124int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
125 unsigned char **p,
126 const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +0000127{
Janos Follath24eed8d2019-11-22 13:21:35 +0000128 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100129 DHM_VALIDATE_RET(ctx != NULL);
130 DHM_VALIDATE_RET(p != NULL && *p != NULL);
131 DHM_VALIDATE_RET(end != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100133 if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 ||
134 (ret = dhm_read_bignum(&ctx->G, p, end)) != 0 ||
135 (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {
136 return ret;
137 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000138
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100139 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
140 return ret;
141 }
Paul Bakker345a6fe2011-02-28 21:20:02 +0000142
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100143 ctx->len = mbedtls_mpi_size(&ctx->P);
Paul Bakker5121ce52009-01-03 21:22:43 +0000144
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100145 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000146}
147
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200148/*
Gilles Peskine16e36682021-03-31 23:04:50 +0200149 * Pick a random R in the range [2, M-2] for blinding or key generation.
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200150 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,
152 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200153{
Gilles Peskine16e36682021-03-31 23:04:50 +0200154 int ret;
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200155
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100156 MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
157 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200158
159cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100160 return ret;
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200161}
162
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100163static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,
164 int (*f_rng)(void *, unsigned char *, size_t),
165 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000166{
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200167 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000168
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100169 if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {
170 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000171 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100172 if (x_size < 0) {
173 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
174 }
175
176 if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {
177 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
178 } else {
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200179 /* Generate X as large as possible ( <= P - 2 ) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100180 ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
181 if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
182 return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
183 }
184 if (ret != 0) {
185 return ret;
186 }
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200187 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000188
Paul Bakkerff7fe672010-07-18 09:45:05 +0000189 /*
190 * Calculate GX = G^X mod P
191 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100192 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,
193 &ctx->P, &ctx->RP));
Paul Bakker5121ce52009-01-03 21:22:43 +0000194
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100195 if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {
196 return ret;
197 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000198
Gilles Peskine0853bb22021-03-31 22:35:13 +0200199cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200 return ret;
Gilles Peskine0853bb22021-03-31 22:35:13 +0200201}
202
203/*
204 * Setup and write the ServerKeyExchange parameters
205 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100206int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
207 unsigned char *output, size_t *olen,
208 int (*f_rng)(void *, unsigned char *, size_t),
209 void *p_rng)
Gilles Peskine0853bb22021-03-31 22:35:13 +0200210{
211 int ret;
212 size_t n1, n2, n3;
213 unsigned char *p;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100214 DHM_VALIDATE_RET(ctx != NULL);
215 DHM_VALIDATE_RET(output != NULL);
216 DHM_VALIDATE_RET(olen != NULL);
217 DHM_VALIDATE_RET(f_rng != NULL);
Gilles Peskine0853bb22021-03-31 22:35:13 +0200218
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100219 ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
220 if (ret != 0) {
Gilles Peskine0853bb22021-03-31 22:35:13 +0200221 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100222 }
Gilles Peskine0853bb22021-03-31 22:35:13 +0200223
Paul Bakker5121ce52009-01-03 21:22:43 +0000224 /*
Gilles Peskine104eb822021-04-13 22:10:24 +0200225 * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
226 * not required". We omit leading zeros for compactness.
Paul Bakker5121ce52009-01-03 21:22:43 +0000227 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100228#define DHM_MPI_EXPORT(X, n) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100229 do { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100230 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X), \
231 p + 2, \
232 (n))); \
233 *p++ = MBEDTLS_BYTE_1(n); \
234 *p++ = MBEDTLS_BYTE_0(n); \
235 p += (n); \
236 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000237
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100238 n1 = mbedtls_mpi_size(&ctx->P);
239 n2 = mbedtls_mpi_size(&ctx->G);
240 n3 = mbedtls_mpi_size(&ctx->GX);
Paul Bakker5121ce52009-01-03 21:22:43 +0000241
242 p = output;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100243 DHM_MPI_EXPORT(&ctx->P, n1);
244 DHM_MPI_EXPORT(&ctx->G, n2);
245 DHM_MPI_EXPORT(&ctx->GX, n3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000246
Hanno Beckere71ad122017-09-28 10:32:25 +0100247 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000248
249 ctx->len = n1;
250
251cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100252 if (ret != 0 && ret > -128) {
253 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
254 }
255 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000256}
257
258/*
Hanno Becker8880e752017-10-04 13:15:08 +0100259 * Set prime modulus and generator
260 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100261int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
262 const mbedtls_mpi *P,
263 const mbedtls_mpi *G)
Hanno Becker8880e752017-10-04 13:15:08 +0100264{
Janos Follath24eed8d2019-11-22 13:21:35 +0000265 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100266 DHM_VALIDATE_RET(ctx != NULL);
267 DHM_VALIDATE_RET(P != NULL);
268 DHM_VALIDATE_RET(G != NULL);
Hanno Becker8880e752017-10-04 13:15:08 +0100269
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100270 if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
271 (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
272 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
Hanno Becker8880e752017-10-04 13:15:08 +0100273 }
274
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100275 ctx->len = mbedtls_mpi_size(&ctx->P);
276 return 0;
Hanno Becker8880e752017-10-04 13:15:08 +0100277}
278
279/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000280 * Import the peer's public value G^Y
281 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100282int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
283 const unsigned char *input, size_t ilen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000284{
Janos Follath24eed8d2019-11-22 13:21:35 +0000285 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100286 DHM_VALIDATE_RET(ctx != NULL);
287 DHM_VALIDATE_RET(input != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000288
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100289 if (ilen < 1 || ilen > ctx->len) {
290 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
291 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000292
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100293 if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {
294 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
295 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000296
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000298}
299
300/*
301 * Create own private value X and export G^X
302 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100303int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,
304 unsigned char *output, size_t olen,
305 int (*f_rng)(void *, unsigned char *, size_t),
306 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000307{
Gilles Peskine0853bb22021-03-31 22:35:13 +0200308 int ret;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100309 DHM_VALIDATE_RET(ctx != NULL);
310 DHM_VALIDATE_RET(output != NULL);
311 DHM_VALIDATE_RET(f_rng != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000312
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 if (olen < 1 || olen > ctx->len) {
314 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
315 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000316
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100317 ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
318 if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) {
319 return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;
320 }
321 if (ret != 0) {
Gilles Peskine0853bb22021-03-31 22:35:13 +0200322 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100323 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000324
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100325 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000326
327cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100328 if (ret != 0 && ret > -128) {
329 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);
330 }
331 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000332}
333
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200334
335/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200336 * Use the blinding method and optimisation suggested in section 10 of:
337 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200338 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200339 * Berlin Heidelberg, 1996. p. 104-113.
340 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100341static int dhm_update_blinding(mbedtls_dhm_context *ctx,
342 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200343{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200344 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200345 mbedtls_mpi R;
346
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100347 mbedtls_mpi_init(&R);
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200348
349 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200350 * Don't use any blinding the first time a particular X is used,
351 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200352 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100353 if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) {
354 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X));
355 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1));
356 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1));
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200357
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100358 return 0;
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200359 }
360
361 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200362 * Ok, we need blinding. Can we re-use existing values?
363 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200364 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100365 if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) {
366 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
367 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200368
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100369 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
370 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200371
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100372 return 0;
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200373 }
374
375 /*
376 * We need to generate blinding values from scratch
377 */
378
Gilles Peskineb4e815f2021-03-31 22:50:57 +0200379 /* Vi = random( 2, P-2 ) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100380 MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200381
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200382 /* Vf = Vi^-X mod P
383 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
384 * then elevate to the Xth power. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100385 MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng));
386 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R));
387 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
388 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P));
389 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R));
390 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200391
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100392 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 +0200393
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200394cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100395 mbedtls_mpi_free(&R);
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200396
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100397 return ret;
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200398}
399
400/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000401 * Derive and export the shared secret (G^Y)^X mod P
402 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100403int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,
404 unsigned char *output, size_t output_size, size_t *olen,
405 int (*f_rng)(void *, unsigned char *, size_t),
406 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000407{
Janos Follath24eed8d2019-11-22 13:21:35 +0000408 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200409 mbedtls_mpi GYb;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100410 DHM_VALIDATE_RET(ctx != NULL);
411 DHM_VALIDATE_RET(output != NULL);
412 DHM_VALIDATE_RET(olen != NULL);
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200413
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100414 if (output_size < ctx->len) {
415 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
416 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000417
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100418 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
419 return ret;
420 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000421
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100422 mbedtls_mpi_init(&GYb);
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200423
424 /* Blind peer's value */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100425 if (f_rng != NULL) {
426 MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));
427 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));
428 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));
429 } else {
430 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&GYb, &ctx->GY));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200431 }
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200432
433 /* Do modular exponentiation */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100434 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,
435 &ctx->P, &ctx->RP));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200436
437 /* Unblind secret value */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100438 if (f_rng != NULL) {
439 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
440 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200441 }
442
Gilles Peskine104eb822021-04-13 22:10:24 +0200443 /* Output the secret without any leading zero byte. This is mandatory
444 * for TLS per RFC 5246 §8.1.2. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100445 *olen = mbedtls_mpi_size(&ctx->K);
446 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000447
448cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100449 mbedtls_mpi_free(&GYb);
Paul Bakker5121ce52009-01-03 21:22:43 +0000450
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100451 if (ret != 0) {
452 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
453 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000454
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100455 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000456}
457
458/*
459 * Free the components of a DHM key
460 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100461void mbedtls_dhm_free(mbedtls_dhm_context *ctx)
Paul Bakker5121ce52009-01-03 21:22:43 +0000462{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100463 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500464 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100465 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500466
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100467 mbedtls_mpi_free(&ctx->pX);
468 mbedtls_mpi_free(&ctx->Vf);
469 mbedtls_mpi_free(&ctx->Vi);
470 mbedtls_mpi_free(&ctx->RP);
471 mbedtls_mpi_free(&ctx->K);
472 mbedtls_mpi_free(&ctx->GY);
473 mbedtls_mpi_free(&ctx->GX);
474 mbedtls_mpi_free(&ctx->X);
475 mbedtls_mpi_free(&ctx->G);
476 mbedtls_mpi_free(&ctx->P);
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200477
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100478 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
Paul Bakker5121ce52009-01-03 21:22:43 +0000479}
480
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200481#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200482/*
483 * Parse DHM parameters
484 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100485int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,
486 size_t dhminlen)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200487{
Janos Follath24eed8d2019-11-22 13:21:35 +0000488 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200489 size_t len;
490 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200491#if defined(MBEDTLS_PEM_PARSE_C)
492 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500493#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200494
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100495 DHM_VALIDATE_RET(dhm != NULL);
496 DHM_VALIDATE_RET(dhmin != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500497
498#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100499 mbedtls_pem_init(&pem);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200500
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200501 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100502 if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200503 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100504 } else {
505 ret = mbedtls_pem_read_buffer(&pem,
506 "-----BEGIN DH PARAMETERS-----",
507 "-----END DH PARAMETERS-----",
508 dhmin, NULL, 0, &dhminlen);
509 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200510
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100511 if (ret == 0) {
Paul Bakker40ce79f2013-09-15 17:43:54 +0200512 /*
513 * Was PEM encoded
514 */
515 dhminlen = pem.buflen;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100516 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
Paul Bakker40ce79f2013-09-15 17:43:54 +0200517 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100518 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200519
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100520 p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200521#else
522 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200523#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200524 end = p + dhminlen;
525
526 /*
527 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400528 * prime INTEGER, -- P
529 * generator INTEGER, -- g
530 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200531 * }
532 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100533 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
534 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
535 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200536 goto exit;
537 }
538
539 end = p + len;
540
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100541 if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
542 (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
543 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200544 goto exit;
545 }
546
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100547 if (p != end) {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200548 /* This might be the optional privateValueLength.
549 * If so, we can cleanly discard it */
550 mbedtls_mpi rec;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100551 mbedtls_mpi_init(&rec);
552 ret = mbedtls_asn1_get_mpi(&p, end, &rec);
553 mbedtls_mpi_free(&rec);
554 if (ret != 0) {
555 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400556 goto exit;
557 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100558 if (p != end) {
559 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
560 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400561 goto exit;
562 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200563 }
564
565 ret = 0;
566
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100567 dhm->len = mbedtls_mpi_size(&dhm->P);
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100568
Paul Bakker40ce79f2013-09-15 17:43:54 +0200569exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100571 mbedtls_pem_free(&pem);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200572#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100573 if (ret != 0) {
574 mbedtls_dhm_free(dhm);
575 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200576
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100577 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200578}
579
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200580#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200581/*
582 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200583 *
584 * The file is expected to contain either PEM or DER encoded data.
585 * A terminating null byte is always appended. It is included in the announced
586 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200587 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100588static int load_file(const char *path, unsigned char **buf, size_t *n)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200589{
590 FILE *f;
591 long size;
592
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100593 if ((f = fopen(path, "rb")) == NULL) {
594 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200595 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100596
597 fseek(f, 0, SEEK_END);
598 if ((size = ftell(f)) == -1) {
599 fclose(f);
600 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
601 }
602 fseek(f, 0, SEEK_SET);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200603
604 *n = (size_t) size;
605
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100606 if (*n + 1 == 0 ||
607 (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
608 fclose(f);
609 return MBEDTLS_ERR_DHM_ALLOC_FAILED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200610 }
611
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100612 if (fread(*buf, 1, *n, f) != *n) {
613 fclose(f);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100614
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100615 mbedtls_platform_zeroize(*buf, *n + 1);
616 mbedtls_free(*buf);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100617
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100618 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200619 }
620
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100621 fclose(f);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200622
623 (*buf)[*n] = '\0';
624
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100625 if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200626 ++*n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100627 }
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200628
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100629 return 0;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200630}
631
632/*
633 * Load and parse DHM parameters
634 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100635int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200636{
Janos Follath24eed8d2019-11-22 13:21:35 +0000637 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200638 size_t n;
639 unsigned char *buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100640 DHM_VALIDATE_RET(dhm != NULL);
641 DHM_VALIDATE_RET(path != NULL);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200642
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100643 if ((ret = load_file(path, &buf, &n)) != 0) {
644 return ret;
645 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200646
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100647 ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200648
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100649 mbedtls_platform_zeroize(buf, n);
650 mbedtls_free(buf);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200651
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100652 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200653}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200654#endif /* MBEDTLS_FS_IO */
655#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000656#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200657
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200658#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000659
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100660#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200661static const char mbedtls_test_dhm_params[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100662 "-----BEGIN DH PARAMETERS-----\r\n"
663 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
664 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
665 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
666 "-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100667#else /* MBEDTLS_PEM_PARSE_C */
668static const char mbedtls_test_dhm_params[] = {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100669 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
670 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
671 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
672 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
673 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
674 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
675 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
676 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
677 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
678 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
679 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
680 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
681};
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100682#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200683
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100684static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200685
Paul Bakker5121ce52009-01-03 21:22:43 +0000686/*
687 * Checkup routine
688 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100689int mbedtls_dhm_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +0000690{
Janos Follath24eed8d2019-11-22 13:21:35 +0000691 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200693
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100694 mbedtls_dhm_init(&dhm);
Paul Bakker8f870b02014-06-20 13:32:38 +0200695
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100696 if (verbose != 0) {
697 mbedtls_printf(" DHM parameter load: ");
698 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200699
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100700 if ((ret = mbedtls_dhm_parse_dhm(&dhm,
701 (const unsigned char *) mbedtls_test_dhm_params,
702 mbedtls_test_dhm_params_len)) != 0) {
703 if (verbose != 0) {
704 mbedtls_printf("failed\n");
705 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200706
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200707 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200708 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200709 }
710
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100711 if (verbose != 0) {
712 mbedtls_printf("passed\n\n");
713 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200714
Paul Bakker8f870b02014-06-20 13:32:38 +0200715exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100716 mbedtls_dhm_free(&dhm);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200717
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100718 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000719}
720
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200721#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000722
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200723#endif /* MBEDTLS_DHM_C */