blob: 1a41b91a90b625e0bbf784d9441c62a9ae7eac64 [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
Dave Rodgman7ff79652023-11-03 12:04:52 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker5121ce52009-01-03 21:22:43 +00006 */
7/*
Simon Butcherbdae02c2016-01-20 00:44:42 +00008 * The following sources were referenced in the design of this implementation
9 * of the Diffie-Hellman-Merkle algorithm:
Paul Bakker5121ce52009-01-03 21:22:43 +000010 *
Simon Butcherbdae02c2016-01-20 00:44:42 +000011 * [1] Handbook of Applied Cryptography - 1997, Chapter 12
12 * Menezes, van Oorschot and Vanstone
13 *
Paul Bakker5121ce52009-01-03 21:22:43 +000014 */
15
Gilles Peskinedb09ef62020-06-03 01:43:33 +020016#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000017
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020018#if defined(MBEDTLS_DHM_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000019
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000020#include "mbedtls/dhm.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050021#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000022#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000023
Rich Evans00ab4702015-02-06 13:43:58 +000024#include <string.h>
25
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020026#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000027#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020028#endif
29
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020032#endif
33
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020035
Reuven Levin1f35ca92017-12-07 10:09:32 +000036#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020037
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010038#define DHM_VALIDATE_RET(cond) \
39 MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA)
40#define DHM_VALIDATE(cond) \
41 MBEDTLS_INTERNAL_VALIDATE(cond)
Andrzej Kurekc470b6b2019-01-31 08:20:20 -050042
Paul Bakker5121ce52009-01-03 21:22:43 +000043/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020044 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000045 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010046static int dhm_read_bignum(mbedtls_mpi *X,
47 unsigned char **p,
48 const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +000049{
50 int ret, n;
51
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010052 if (end - *p < 2) {
53 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
54 }
Paul Bakker5121ce52009-01-03 21:22:43 +000055
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010056 n = ((*p)[0] << 8) | (*p)[1];
Paul Bakker5121ce52009-01-03 21:22:43 +000057 (*p) += 2;
58
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010059 if ((int) (end - *p) < n) {
60 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
61 }
Paul Bakker5121ce52009-01-03 21:22:43 +000062
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010063 if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {
64 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
65 }
Paul Bakker5121ce52009-01-03 21:22:43 +000066
67 (*p) += n;
68
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010069 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000070}
71
72/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000073 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000074 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000075 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000076 *
Janos Follathaa325d72017-09-20 15:33:24 +010077 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +010078 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +010079 *
Paul Bakker345a6fe2011-02-28 21:20:02 +000080 * For more information on the attack, see:
81 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
82 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +000083 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010084static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
Paul Bakkerc47840e2011-02-20 16:37:30 +000085{
Gilles Peskine58df4c92021-03-31 22:56:43 +020086 mbedtls_mpi U;
Janos Follathaa325d72017-09-20 15:33:24 +010087 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +000088
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010089 mbedtls_mpi_init(&U);
Paul Bakker3d8fb632014-04-17 12:42:41 +020090
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010091 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
Paul Bakkerc47840e2011-02-20 16:37:30 +000092
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010093 if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
94 mbedtls_mpi_cmp_mpi(param, &U) > 0) {
Janos Follathaa325d72017-09-20 15:33:24 +010095 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +000096 }
97
Paul Bakker3d8fb632014-04-17 12:42:41 +020098cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010099 mbedtls_mpi_free(&U);
100 return ret;
Paul Bakkerc47840e2011-02-20 16:37:30 +0000101}
102
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100103void mbedtls_dhm_init(mbedtls_dhm_context *ctx)
Paul Bakker8f870b02014-06-20 13:32:38 +0200104{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100105 DHM_VALIDATE(ctx != NULL);
106 memset(ctx, 0, sizeof(mbedtls_dhm_context));
Paul Bakker8f870b02014-06-20 13:32:38 +0200107}
108
Paul Bakkerc47840e2011-02-20 16:37:30 +0000109/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000110 * Parse the ServerKeyExchange parameters
111 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100112int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
113 unsigned char **p,
114 const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +0000115{
Janos Follath24eed8d2019-11-22 13:21:35 +0000116 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100117 DHM_VALIDATE_RET(ctx != NULL);
118 DHM_VALIDATE_RET(p != NULL && *p != NULL);
119 DHM_VALIDATE_RET(end != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000120
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100121 if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 ||
122 (ret = dhm_read_bignum(&ctx->G, p, end)) != 0 ||
123 (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {
124 return ret;
125 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000126
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100127 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
128 return ret;
129 }
Paul Bakker345a6fe2011-02-28 21:20:02 +0000130
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100131 ctx->len = mbedtls_mpi_size(&ctx->P);
Paul Bakker5121ce52009-01-03 21:22:43 +0000132
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100133 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000134}
135
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200136/*
Gilles Peskine16e36682021-03-31 23:04:50 +0200137 * Pick a random R in the range [2, M-2] for blinding or key generation.
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200138 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100139static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,
140 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200141{
Gilles Peskine16e36682021-03-31 23:04:50 +0200142 int ret;
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200143
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100144 MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
145 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200146
147cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100148 return ret;
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200149}
150
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100151static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,
152 int (*f_rng)(void *, unsigned char *, size_t),
153 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000154{
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200155 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000156
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100157 if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {
158 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000159 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100160 if (x_size < 0) {
161 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
162 }
163
164 if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {
165 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
166 } else {
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200167 /* Generate X as large as possible ( <= P - 2 ) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100168 ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
169 if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
170 return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
171 }
172 if (ret != 0) {
173 return ret;
174 }
Gilles Peskine87fdb1f2021-03-31 22:48:14 +0200175 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000176
Paul Bakkerff7fe672010-07-18 09:45:05 +0000177 /*
178 * Calculate GX = G^X mod P
179 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100180 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,
181 &ctx->P, &ctx->RP));
Paul Bakker5121ce52009-01-03 21:22:43 +0000182
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100183 if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {
184 return ret;
185 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000186
Gilles Peskine0853bb22021-03-31 22:35:13 +0200187cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100188 return ret;
Gilles Peskine0853bb22021-03-31 22:35:13 +0200189}
190
191/*
192 * Setup and write the ServerKeyExchange parameters
193 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100194int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
195 unsigned char *output, size_t *olen,
196 int (*f_rng)(void *, unsigned char *, size_t),
197 void *p_rng)
Gilles Peskine0853bb22021-03-31 22:35:13 +0200198{
199 int ret;
200 size_t n1, n2, n3;
201 unsigned char *p;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100202 DHM_VALIDATE_RET(ctx != NULL);
203 DHM_VALIDATE_RET(output != NULL);
204 DHM_VALIDATE_RET(olen != NULL);
205 DHM_VALIDATE_RET(f_rng != NULL);
Gilles Peskine0853bb22021-03-31 22:35:13 +0200206
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100207 ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
208 if (ret != 0) {
Gilles Peskine0853bb22021-03-31 22:35:13 +0200209 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100210 }
Gilles Peskine0853bb22021-03-31 22:35:13 +0200211
Paul Bakker5121ce52009-01-03 21:22:43 +0000212 /*
Gilles Peskine104eb822021-04-13 22:10:24 +0200213 * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
214 * not required". We omit leading zeros for compactness.
Paul Bakker5121ce52009-01-03 21:22:43 +0000215 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100216#define DHM_MPI_EXPORT(X, n) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100217 do { \
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100218 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X), \
219 p + 2, \
220 (n))); \
221 *p++ = MBEDTLS_BYTE_1(n); \
222 *p++ = MBEDTLS_BYTE_0(n); \
223 p += (n); \
224 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000225
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100226 n1 = mbedtls_mpi_size(&ctx->P);
227 n2 = mbedtls_mpi_size(&ctx->G);
228 n3 = mbedtls_mpi_size(&ctx->GX);
Paul Bakker5121ce52009-01-03 21:22:43 +0000229
230 p = output;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100231 DHM_MPI_EXPORT(&ctx->P, n1);
232 DHM_MPI_EXPORT(&ctx->G, n2);
233 DHM_MPI_EXPORT(&ctx->GX, n3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000234
Hanno Beckere71ad122017-09-28 10:32:25 +0100235 *olen = p - output;
Paul Bakker5121ce52009-01-03 21:22:43 +0000236
237 ctx->len = n1;
238
239cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100240 if (ret != 0 && ret > -128) {
241 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
242 }
243 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000244}
245
246/*
Hanno Becker8880e752017-10-04 13:15:08 +0100247 * Set prime modulus and generator
248 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100249int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
250 const mbedtls_mpi *P,
251 const mbedtls_mpi *G)
Hanno Becker8880e752017-10-04 13:15:08 +0100252{
Janos Follath24eed8d2019-11-22 13:21:35 +0000253 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100254 DHM_VALIDATE_RET(ctx != NULL);
255 DHM_VALIDATE_RET(P != NULL);
256 DHM_VALIDATE_RET(G != NULL);
Hanno Becker8880e752017-10-04 13:15:08 +0100257
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100258 if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
259 (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
260 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
Hanno Becker8880e752017-10-04 13:15:08 +0100261 }
262
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100263 ctx->len = mbedtls_mpi_size(&ctx->P);
264 return 0;
Hanno Becker8880e752017-10-04 13:15:08 +0100265}
266
267/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000268 * Import the peer's public value G^Y
269 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100270int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
271 const unsigned char *input, size_t ilen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000272{
Janos Follath24eed8d2019-11-22 13:21:35 +0000273 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100274 DHM_VALIDATE_RET(ctx != NULL);
275 DHM_VALIDATE_RET(input != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000276
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100277 if (ilen < 1 || ilen > ctx->len) {
278 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
279 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000280
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100281 if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {
282 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
283 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000284
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100285 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000286}
287
288/*
289 * Create own private value X and export G^X
290 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100291int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,
292 unsigned char *output, size_t olen,
293 int (*f_rng)(void *, unsigned char *, size_t),
294 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000295{
Gilles Peskine0853bb22021-03-31 22:35:13 +0200296 int ret;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100297 DHM_VALIDATE_RET(ctx != NULL);
298 DHM_VALIDATE_RET(output != NULL);
299 DHM_VALIDATE_RET(f_rng != NULL);
Paul Bakker5121ce52009-01-03 21:22:43 +0000300
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100301 if (olen < 1 || olen > ctx->len) {
302 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
303 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000304
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100305 ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
306 if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) {
307 return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;
308 }
309 if (ret != 0) {
Gilles Peskine0853bb22021-03-31 22:35:13 +0200310 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100311 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000312
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100313 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000314
315cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100316 if (ret != 0 && ret > -128) {
317 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);
318 }
319 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000320}
321
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200322
323/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200324 * Use the blinding method and optimisation suggested in section 10 of:
325 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200326 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200327 * Berlin Heidelberg, 1996. p. 104-113.
328 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100329static int dhm_update_blinding(mbedtls_dhm_context *ctx,
330 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200331{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200332 int ret;
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200333 mbedtls_mpi R;
334
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100335 mbedtls_mpi_init(&R);
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200336
337 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200338 * Don't use any blinding the first time a particular X is used,
339 * but remember it to use blinding next time.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200340 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100341 if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) {
342 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X));
343 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1));
344 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1));
Manuel Pégourié-Gonnarded8a02b2013-09-04 16:39:03 +0200345
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100346 return 0;
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200347 }
348
349 /*
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200350 * Ok, we need blinding. Can we re-use existing values?
351 * If yes, just update them by squaring them.
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200352 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100353 if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) {
354 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
355 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200356
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100357 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
358 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200359
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100360 return 0;
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200361 }
362
363 /*
364 * We need to generate blinding values from scratch
365 */
366
Gilles Peskineb4e815f2021-03-31 22:50:57 +0200367 /* Vi = random( 2, P-2 ) */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100368 MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200369
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200370 /* Vf = Vi^-X mod P
371 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
372 * then elevate to the Xth power. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100373 MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng));
374 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R));
375 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
376 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P));
377 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R));
378 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
Manuel Pégourié-Gonnard15d5de12013-09-17 11:34:11 +0200379
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100380 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 +0200381
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200382cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100383 mbedtls_mpi_free(&R);
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200384
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100385 return ret;
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200386}
387
388/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000389 * Derive and export the shared secret (G^Y)^X mod P
390 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100391int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,
392 unsigned char *output, size_t output_size, size_t *olen,
393 int (*f_rng)(void *, unsigned char *, size_t),
394 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000395{
Janos Follath24eed8d2019-11-22 13:21:35 +0000396 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200397 mbedtls_mpi GYb;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100398 DHM_VALIDATE_RET(ctx != NULL);
399 DHM_VALIDATE_RET(output != NULL);
400 DHM_VALIDATE_RET(olen != NULL);
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200401
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100402 if (output_size < ctx->len) {
403 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
404 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000405
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100406 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
407 return ret;
408 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000409
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100410 mbedtls_mpi_init(&GYb);
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200411
412 /* Blind peer's value */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100413 if (f_rng != NULL) {
414 MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));
415 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));
416 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));
417 } else {
418 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&GYb, &ctx->GY));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200419 }
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200420
421 /* Do modular exponentiation */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100422 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,
423 &ctx->P, &ctx->RP));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200424
425 /* Unblind secret value */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100426 if (f_rng != NULL) {
427 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
428 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200429 }
430
Gilles Peskine104eb822021-04-13 22:10:24 +0200431 /* Output the secret without any leading zero byte. This is mandatory
432 * for TLS per RFC 5246 §8.1.2. */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100433 *olen = mbedtls_mpi_size(&ctx->K);
434 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
436cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100437 mbedtls_mpi_free(&GYb);
Paul Bakker5121ce52009-01-03 21:22:43 +0000438
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100439 if (ret != 0) {
440 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
441 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100443 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000444}
445
446/*
447 * Free the components of a DHM key
448 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100449void mbedtls_dhm_free(mbedtls_dhm_context *ctx)
Paul Bakker5121ce52009-01-03 21:22:43 +0000450{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100451 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500452 return;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100453 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500454
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100455 mbedtls_mpi_free(&ctx->pX);
456 mbedtls_mpi_free(&ctx->Vf);
457 mbedtls_mpi_free(&ctx->Vi);
458 mbedtls_mpi_free(&ctx->RP);
459 mbedtls_mpi_free(&ctx->K);
460 mbedtls_mpi_free(&ctx->GY);
461 mbedtls_mpi_free(&ctx->GX);
462 mbedtls_mpi_free(&ctx->X);
463 mbedtls_mpi_free(&ctx->G);
464 mbedtls_mpi_free(&ctx->P);
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200465
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100466 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
Paul Bakker5121ce52009-01-03 21:22:43 +0000467}
468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200470/*
471 * Parse DHM parameters
472 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100473int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,
474 size_t dhminlen)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200475{
Janos Follath24eed8d2019-11-22 13:21:35 +0000476 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200477 size_t len;
478 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200479#if defined(MBEDTLS_PEM_PARSE_C)
480 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500481#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200482
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100483 DHM_VALIDATE_RET(dhm != NULL);
484 DHM_VALIDATE_RET(dhmin != NULL);
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500485
486#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100487 mbedtls_pem_init(&pem);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200488
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200489 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100490 if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200491 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100492 } else {
493 ret = mbedtls_pem_read_buffer(&pem,
494 "-----BEGIN DH PARAMETERS-----",
495 "-----END DH PARAMETERS-----",
496 dhmin, NULL, 0, &dhminlen);
497 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200498
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100499 if (ret == 0) {
Paul Bakker40ce79f2013-09-15 17:43:54 +0200500 /*
501 * Was PEM encoded
502 */
503 dhminlen = pem.buflen;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100504 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
Paul Bakker40ce79f2013-09-15 17:43:54 +0200505 goto exit;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100506 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200507
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100508 p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200509#else
510 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200511#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200512 end = p + dhminlen;
513
514 /*
515 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400516 * prime INTEGER, -- P
517 * generator INTEGER, -- g
518 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200519 * }
520 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100521 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
522 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
523 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200524 goto exit;
525 }
526
527 end = p + len;
528
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100529 if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
530 (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
531 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200532 goto exit;
533 }
534
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100535 if (p != end) {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200536 /* This might be the optional privateValueLength.
537 * If so, we can cleanly discard it */
538 mbedtls_mpi rec;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100539 mbedtls_mpi_init(&rec);
540 ret = mbedtls_asn1_get_mpi(&p, end, &rec);
541 mbedtls_mpi_free(&rec);
542 if (ret != 0) {
543 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400544 goto exit;
545 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100546 if (p != end) {
547 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
548 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400549 goto exit;
550 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200551 }
552
553 ret = 0;
554
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100555 dhm->len = mbedtls_mpi_size(&dhm->P);
Manuel Pégourié-Gonnard3fec2202014-03-29 16:42:38 +0100556
Paul Bakker40ce79f2013-09-15 17:43:54 +0200557exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200558#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100559 mbedtls_pem_free(&pem);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200560#endif
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100561 if (ret != 0) {
562 mbedtls_dhm_free(dhm);
563 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200564
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100565 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200566}
567
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200568#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200569/*
570 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200571 *
572 * The file is expected to contain either PEM or DER encoded data.
573 * A terminating null byte is always appended. It is included in the announced
574 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200575 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100576static int load_file(const char *path, unsigned char **buf, size_t *n)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200577{
578 FILE *f;
579 long size;
580
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100581 if ((f = fopen(path, "rb")) == NULL) {
582 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200583 }
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100584
585 fseek(f, 0, SEEK_END);
586 if ((size = ftell(f)) == -1) {
587 fclose(f);
588 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
589 }
590 fseek(f, 0, SEEK_SET);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200591
592 *n = (size_t) size;
593
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100594 if (*n + 1 == 0 ||
595 (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
596 fclose(f);
597 return MBEDTLS_ERR_DHM_ALLOC_FAILED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200598 }
599
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100600 if (fread(*buf, 1, *n, f) != *n) {
601 fclose(f);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100602
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100603 mbedtls_platform_zeroize(*buf, *n + 1);
604 mbedtls_free(*buf);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100605
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100606 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200607 }
608
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100609 fclose(f);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200610
611 (*buf)[*n] = '\0';
612
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100613 if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200614 ++*n;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100615 }
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200616
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100617 return 0;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200618}
619
620/*
621 * Load and parse DHM parameters
622 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100623int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200624{
Janos Follath24eed8d2019-11-22 13:21:35 +0000625 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200626 size_t n;
627 unsigned char *buf;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100628 DHM_VALIDATE_RET(dhm != NULL);
629 DHM_VALIDATE_RET(path != NULL);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200630
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100631 if ((ret = load_file(path, &buf, &n)) != 0) {
632 return ret;
633 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200634
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100635 ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200636
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100637 mbedtls_platform_zeroize(buf, n);
638 mbedtls_free(buf);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200639
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100640 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200641}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200642#endif /* MBEDTLS_FS_IO */
643#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000644#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200645
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200646#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000647
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100648#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200649static const char mbedtls_test_dhm_params[] =
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100650 "-----BEGIN DH PARAMETERS-----\r\n"
651 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
652 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
653 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
654 "-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100655#else /* MBEDTLS_PEM_PARSE_C */
656static const char mbedtls_test_dhm_params[] = {
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100657 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
658 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
659 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
660 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
661 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
662 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
663 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
664 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
665 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
666 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
667 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
668 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
669};
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100670#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200671
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100672static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200673
Paul Bakker5121ce52009-01-03 21:22:43 +0000674/*
675 * Checkup routine
676 */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100677int mbedtls_dhm_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +0000678{
Janos Follath24eed8d2019-11-22 13:21:35 +0000679 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200680 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200681
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100682 mbedtls_dhm_init(&dhm);
Paul Bakker8f870b02014-06-20 13:32:38 +0200683
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100684 if (verbose != 0) {
685 mbedtls_printf(" DHM parameter load: ");
686 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200687
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100688 if ((ret = mbedtls_dhm_parse_dhm(&dhm,
689 (const unsigned char *) mbedtls_test_dhm_params,
690 mbedtls_test_dhm_params_len)) != 0) {
691 if (verbose != 0) {
692 mbedtls_printf("failed\n");
693 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200694
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200695 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200696 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200697 }
698
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100699 if (verbose != 0) {
700 mbedtls_printf("passed\n\n");
701 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200702
Paul Bakker8f870b02014-06-20 13:32:38 +0200703exit:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100704 mbedtls_dhm_free(&dhm);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200705
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100706 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000707}
708
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000710
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200711#endif /* MBEDTLS_DHM_C */