blob: 941a89da80b31e7d990a2ca78a20496c7dcbee97 [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 Rodgman16799db2023-11-02 19:47:20 +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"
Manuel Pégourié-Gonnardc2d210e2025-07-10 21:48:41 +020021#include "bignum_internal.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050022#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000023#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000024
Rich Evans00ab4702015-02-06 13:43:58 +000025#include <string.h>
26
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000028#include "mbedtls/pem.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020029#endif
30
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020031#if defined(MBEDTLS_ASN1_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000032#include "mbedtls/asn1.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020033#endif
34
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000035#include "mbedtls/platform.h"
Paul Bakker40ce79f2013-09-15 17:43:54 +020036
Reuven Levin1f35ca92017-12-07 10:09:32 +000037#if !defined(MBEDTLS_DHM_ALT)
Paul Bakker34617722014-06-13 17:20:13 +020038
Paul Bakker5121ce52009-01-03 21:22:43 +000039/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020040 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000041 */
Gilles Peskine449bd832023-01-11 14:50:10 +010042static int dhm_read_bignum(mbedtls_mpi *X,
43 unsigned char **p,
44 const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +000045{
46 int ret, n;
47
Gilles Peskine449bd832023-01-11 14:50:10 +010048 if (end - *p < 2) {
49 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
50 }
Paul Bakker5121ce52009-01-03 21:22:43 +000051
Dave Rodgmana3d0f612023-11-03 23:34:02 +000052 n = MBEDTLS_GET_UINT16_BE(*p, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +000053 (*p) += 2;
54
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +000055 if ((size_t) (end - *p) < (size_t) n) {
Gilles Peskine449bd832023-01-11 14:50:10 +010056 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
57 }
Paul Bakker5121ce52009-01-03 21:22:43 +000058
Gilles Peskine449bd832023-01-11 14:50:10 +010059 if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {
60 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
61 }
Paul Bakker5121ce52009-01-03 21:22:43 +000062
63 (*p) += n;
64
Gilles Peskine449bd832023-01-11 14:50:10 +010065 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000066}
67
68/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000069 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000070 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000071 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000072 *
Janos Follathaa325d72017-09-20 15:33:24 +010073 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +010074 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +010075 *
Paul Bakker345a6fe2011-02-28 21:20:02 +000076 * For more information on the attack, see:
77 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
78 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +000079 */
Gilles Peskine449bd832023-01-11 14:50:10 +010080static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
Paul Bakkerc47840e2011-02-20 16:37:30 +000081{
Gilles Peskine8e38acc2021-03-31 22:56:43 +020082 mbedtls_mpi U;
Janos Follathaa325d72017-09-20 15:33:24 +010083 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +000084
Gilles Peskine449bd832023-01-11 14:50:10 +010085 mbedtls_mpi_init(&U);
Paul Bakker3d8fb632014-04-17 12:42:41 +020086
Gilles Peskine449bd832023-01-11 14:50:10 +010087 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
Paul Bakkerc47840e2011-02-20 16:37:30 +000088
Gilles Peskine449bd832023-01-11 14:50:10 +010089 if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
90 mbedtls_mpi_cmp_mpi(param, &U) > 0) {
Janos Follathaa325d72017-09-20 15:33:24 +010091 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +000092 }
93
Paul Bakker3d8fb632014-04-17 12:42:41 +020094cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +010095 mbedtls_mpi_free(&U);
96 return ret;
Paul Bakkerc47840e2011-02-20 16:37:30 +000097}
98
Gilles Peskine449bd832023-01-11 14:50:10 +010099void mbedtls_dhm_init(mbedtls_dhm_context *ctx)
Paul Bakker8f870b02014-06-20 13:32:38 +0200100{
Gilles Peskine449bd832023-01-11 14:50:10 +0100101 memset(ctx, 0, sizeof(mbedtls_dhm_context));
Paul Bakker8f870b02014-06-20 13:32:38 +0200102}
103
Gilles Peskine449bd832023-01-11 14:50:10 +0100104size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)
Gilles Peskine487bbf62021-05-27 22:17:07 +0200105{
Gilles Peskine449bd832023-01-11 14:50:10 +0100106 return mbedtls_mpi_bitlen(&ctx->P);
Gilles Peskine487bbf62021-05-27 22:17:07 +0200107}
108
Gilles Peskine449bd832023-01-11 14:50:10 +0100109size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx)
Gilles Peskine487bbf62021-05-27 22:17:07 +0200110{
Gilles Peskine449bd832023-01-11 14:50:10 +0100111 return mbedtls_mpi_size(&ctx->P);
Gilles Peskine487bbf62021-05-27 22:17:07 +0200112}
113
Gilles Peskine449bd832023-01-11 14:50:10 +0100114int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,
115 mbedtls_dhm_parameter param,
116 mbedtls_mpi *dest)
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200117{
118 const mbedtls_mpi *src = NULL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 switch (param) {
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200120 case MBEDTLS_DHM_PARAM_P:
121 src = &ctx->P;
122 break;
123 case MBEDTLS_DHM_PARAM_G:
124 src = &ctx->G;
125 break;
126 case MBEDTLS_DHM_PARAM_X:
127 src = &ctx->X;
128 break;
129 case MBEDTLS_DHM_PARAM_GX:
130 src = &ctx->GX;
131 break;
132 case MBEDTLS_DHM_PARAM_GY:
133 src = &ctx->GY;
134 break;
135 case MBEDTLS_DHM_PARAM_K:
136 src = &ctx->K;
137 break;
138 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200140 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 return mbedtls_mpi_copy(dest, src);
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200142}
143
Paul Bakkerc47840e2011-02-20 16:37:30 +0000144/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000145 * Parse the ServerKeyExchange parameters
146 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100147int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
148 unsigned char **p,
149 const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +0000150{
Janos Follath24eed8d2019-11-22 13:21:35 +0000151 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5121ce52009-01-03 21:22:43 +0000152
Gilles Peskine449bd832023-01-11 14:50:10 +0100153 if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 ||
154 (ret = dhm_read_bignum(&ctx->G, p, end)) != 0 ||
155 (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {
156 return ret;
157 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000158
Gilles Peskine449bd832023-01-11 14:50:10 +0100159 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
160 return ret;
161 }
Paul Bakker345a6fe2011-02-28 21:20:02 +0000162
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000164}
165
Gilles Peskine17f1a262021-03-31 22:48:14 +0200166/*
Gilles Peskineda7ee012021-03-31 23:04:50 +0200167 * Pick a random R in the range [2, M-2] for blinding or key generation.
Gilles Peskine17f1a262021-03-31 22:48:14 +0200168 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100169static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,
170 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Gilles Peskine17f1a262021-03-31 22:48:14 +0200171{
Gilles Peskineda7ee012021-03-31 23:04:50 +0200172 int ret;
Gilles Peskine17f1a262021-03-31 22:48:14 +0200173
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
175 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
Gilles Peskine17f1a262021-03-31 22:48:14 +0200176
177cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 return ret;
Gilles Peskine17f1a262021-03-31 22:48:14 +0200179}
180
Gilles Peskine449bd832023-01-11 14:50:10 +0100181static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,
182 int (*f_rng)(void *, unsigned char *, size_t),
183 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000184{
Gilles Peskine17f1a262021-03-31 22:48:14 +0200185 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000186
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {
188 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000189 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 if (x_size < 0) {
191 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
192 }
193
194 if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {
195 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
196 } else {
Gilles Peskine17f1a262021-03-31 22:48:14 +0200197 /* Generate X as large as possible ( <= P - 2 ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100198 ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
199 if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
200 return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
201 }
202 if (ret != 0) {
203 return ret;
204 }
Gilles Peskine17f1a262021-03-31 22:48:14 +0200205 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000206
Paul Bakkerff7fe672010-07-18 09:45:05 +0000207 /*
208 * Calculate GX = G^X mod P
209 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,
211 &ctx->P, &ctx->RP));
Paul Bakker5121ce52009-01-03 21:22:43 +0000212
Gilles Peskine449bd832023-01-11 14:50:10 +0100213 if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {
214 return ret;
215 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000216
Gilles Peskinecb660f22021-03-31 22:35:13 +0200217cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 return ret;
Gilles Peskinecb660f22021-03-31 22:35:13 +0200219}
220
221/*
222 * Setup and write the ServerKeyExchange parameters
223 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100224int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
225 unsigned char *output, size_t *olen,
226 int (*f_rng)(void *, unsigned char *, size_t),
227 void *p_rng)
Gilles Peskinecb660f22021-03-31 22:35:13 +0200228{
229 int ret;
230 size_t n1, n2, n3;
231 unsigned char *p;
Gilles Peskinecb660f22021-03-31 22:35:13 +0200232
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
234 if (ret != 0) {
Gilles Peskinecb660f22021-03-31 22:35:13 +0200235 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 }
Gilles Peskinecb660f22021-03-31 22:35:13 +0200237
Paul Bakker5121ce52009-01-03 21:22:43 +0000238 /*
Gilles Peskine03299dc2021-04-13 22:10:24 +0200239 * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
240 * not required". We omit leading zeros for compactness.
Paul Bakker5121ce52009-01-03 21:22:43 +0000241 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100242#define DHM_MPI_EXPORT(X, n) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100243 do { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X), \
245 p + 2, \
246 (n))); \
247 *p++ = MBEDTLS_BYTE_1(n); \
248 *p++ = MBEDTLS_BYTE_0(n); \
249 p += (n); \
250 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000251
Gilles Peskine449bd832023-01-11 14:50:10 +0100252 n1 = mbedtls_mpi_size(&ctx->P);
253 n2 = mbedtls_mpi_size(&ctx->G);
254 n3 = mbedtls_mpi_size(&ctx->GX);
Paul Bakker5121ce52009-01-03 21:22:43 +0000255
256 p = output;
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 DHM_MPI_EXPORT(&ctx->P, n1);
258 DHM_MPI_EXPORT(&ctx->G, n2);
259 DHM_MPI_EXPORT(&ctx->GX, n3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000260
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000261 *olen = (size_t) (p - output);
Paul Bakker5121ce52009-01-03 21:22:43 +0000262
Paul Bakker5121ce52009-01-03 21:22:43 +0000263cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 if (ret != 0 && ret > -128) {
265 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
266 }
267 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000268}
269
270/*
Hanno Becker8880e752017-10-04 13:15:08 +0100271 * Set prime modulus and generator
272 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100273int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
274 const mbedtls_mpi *P,
275 const mbedtls_mpi *G)
Hanno Becker8880e752017-10-04 13:15:08 +0100276{
Janos Follath24eed8d2019-11-22 13:21:35 +0000277 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker8880e752017-10-04 13:15:08 +0100278
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
280 (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
281 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
Hanno Becker8880e752017-10-04 13:15:08 +0100282 }
283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 return 0;
Hanno Becker8880e752017-10-04 13:15:08 +0100285}
286
287/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000288 * Import the peer's public value G^Y
289 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100290int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
291 const unsigned char *input, size_t ilen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000292{
Janos Follath24eed8d2019-11-22 13:21:35 +0000293 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5121ce52009-01-03 21:22:43 +0000294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) {
296 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
297 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000298
Gilles Peskine449bd832023-01-11 14:50:10 +0100299 if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {
300 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
301 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000302
Gilles Peskine449bd832023-01-11 14:50:10 +0100303 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000304}
305
306/*
307 * Create own private value X and export G^X
308 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100309int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,
310 unsigned char *output, size_t olen,
311 int (*f_rng)(void *, unsigned char *, size_t),
312 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000313{
Gilles Peskinecb660f22021-03-31 22:35:13 +0200314 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000315
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) {
317 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
318 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000319
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
321 if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) {
322 return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;
323 }
324 if (ret != 0) {
Gilles Peskinecb660f22021-03-31 22:35:13 +0200325 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100326 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000327
Gilles Peskine449bd832023-01-11 14:50:10 +0100328 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000329
330cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100331 if (ret != 0 && ret > -128) {
332 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);
333 }
334 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000335}
336
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200337
338/*
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200339 * Use the blinding method and optimisation suggested in section 10 of:
340 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
Manuel Pégourié-Gonnard998930a2015-04-03 13:48:06 +0200341 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200342 * Berlin Heidelberg, 1996. p. 104-113.
343 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100344static int dhm_update_blinding(mbedtls_dhm_context *ctx,
345 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200346{
Manuel Pégourié-Gonnard9f58c4b2020-06-25 12:34:58 +0200347 int ret;
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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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 Peskine7b2b66e2021-03-31 22:50:57 +0200379 /* Vi = random( 2, P-2 ) */
Gilles Peskine449bd832023-01-11 14:50:10 +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é-Gonnard6ab0f512025-08-26 11:31:52 +0200382 /* Vf = Vi^-X = (Vi^-1)^X mod P */
Manuel Pégourié-Gonnardc2d210e2025-07-10 21:48:41 +0200383 MBEDTLS_MPI_CHK(mbedtls_mpi_gcd_modinv_odd(NULL, &ctx->Vf, &ctx->Vi, &ctx->P));
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 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 +0200385
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200386cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 return ret;
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200388}
389
390/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000391 * Derive and export the shared secret (G^Y)^X mod P
392 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100393int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,
394 unsigned char *output, size_t output_size, size_t *olen,
395 int (*f_rng)(void *, unsigned char *, size_t),
396 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000397{
Janos Follath24eed8d2019-11-22 13:21:35 +0000398 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200399 mbedtls_mpi GYb;
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200400
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 if (f_rng == NULL) {
402 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
403 }
Manuel Pégourié-Gonnard1a877222021-06-15 11:29:26 +0200404
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 if (output_size < mbedtls_dhm_get_len(ctx)) {
406 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
407 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000408
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
410 return ret;
411 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000412
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 mbedtls_mpi_init(&GYb);
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200414
415 /* Blind peer's value */
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));
417 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));
418 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200419
420 /* Do modular exponentiation */
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,
422 &ctx->P, &ctx->RP));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200423
424 /* Unblind secret value */
Gilles Peskine449bd832023-01-11 14:50:10 +0100425 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
426 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200427
Gilles Peskine03299dc2021-04-13 22:10:24 +0200428 /* Output the secret without any leading zero byte. This is mandatory
429 * for TLS per RFC 5246 §8.1.2. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 *olen = mbedtls_mpi_size(&ctx->K);
431 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000432
433cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 mbedtls_mpi_free(&GYb);
Paul Bakker5121ce52009-01-03 21:22:43 +0000435
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 if (ret != 0) {
437 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
438 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000439
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000441}
442
443/*
444 * Free the components of a DHM key
445 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100446void mbedtls_dhm_free(mbedtls_dhm_context *ctx)
Paul Bakker5121ce52009-01-03 21:22:43 +0000447{
Gilles Peskine449bd832023-01-11 14:50:10 +0100448 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500449 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500451
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 mbedtls_mpi_free(&ctx->pX);
453 mbedtls_mpi_free(&ctx->Vf);
454 mbedtls_mpi_free(&ctx->Vi);
455 mbedtls_mpi_free(&ctx->RP);
456 mbedtls_mpi_free(&ctx->K);
457 mbedtls_mpi_free(&ctx->GY);
458 mbedtls_mpi_free(&ctx->GX);
459 mbedtls_mpi_free(&ctx->X);
460 mbedtls_mpi_free(&ctx->G);
461 mbedtls_mpi_free(&ctx->P);
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200462
Gilles Peskine449bd832023-01-11 14:50:10 +0100463 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
Paul Bakker5121ce52009-01-03 21:22:43 +0000464}
465
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200466#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200467/*
468 * Parse DHM parameters
469 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100470int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,
471 size_t dhminlen)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200472{
Janos Follath24eed8d2019-11-22 13:21:35 +0000473 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200474 size_t len;
475 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476#if defined(MBEDTLS_PEM_PARSE_C)
477 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500478#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200479
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500480#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 mbedtls_pem_init(&pem);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200482
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200483 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200485 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +0100486 } else {
487 ret = mbedtls_pem_read_buffer(&pem,
488 "-----BEGIN DH PARAMETERS-----",
489 "-----END DH PARAMETERS-----",
490 dhmin, NULL, 0, &dhminlen);
491 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200492
Gilles Peskine449bd832023-01-11 14:50:10 +0100493 if (ret == 0) {
Paul Bakker40ce79f2013-09-15 17:43:54 +0200494 /*
495 * Was PEM encoded
496 */
497 dhminlen = pem.buflen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
Paul Bakker40ce79f2013-09-15 17:43:54 +0200499 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200503#else
504 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200505#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200506 end = p + dhminlen;
507
508 /*
509 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400510 * prime INTEGER, -- P
511 * generator INTEGER, -- g
512 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200513 * }
514 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100515 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
516 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
517 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200518 goto exit;
519 }
520
521 end = p + len;
522
Gilles Peskine449bd832023-01-11 14:50:10 +0100523 if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
524 (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
525 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200526 goto exit;
527 }
528
Gilles Peskine449bd832023-01-11 14:50:10 +0100529 if (p != end) {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200530 /* This might be the optional privateValueLength.
531 * If so, we can cleanly discard it */
532 mbedtls_mpi rec;
Gilles Peskine449bd832023-01-11 14:50:10 +0100533 mbedtls_mpi_init(&rec);
534 ret = mbedtls_asn1_get_mpi(&p, end, &rec);
535 mbedtls_mpi_free(&rec);
536 if (ret != 0) {
537 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400538 goto exit;
539 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100540 if (p != end) {
541 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
542 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400543 goto exit;
544 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200545 }
546
547 ret = 0;
548
549exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200550#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 mbedtls_pem_free(&pem);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200552#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 if (ret != 0) {
554 mbedtls_dhm_free(dhm);
555 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200556
Gilles Peskine449bd832023-01-11 14:50:10 +0100557 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200558}
559
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200561/*
562 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200563 *
564 * The file is expected to contain either PEM or DER encoded data.
565 * A terminating null byte is always appended. It is included in the announced
566 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200567 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100568static int load_file(const char *path, unsigned char **buf, size_t *n)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200569{
570 FILE *f;
571 long size;
572
Gilles Peskine449bd832023-01-11 14:50:10 +0100573 if ((f = fopen(path, "rb")) == NULL) {
574 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
575 }
Gilles Peskineda0913b2022-06-30 17:03:40 +0200576 /* The data loaded here is public, so don't bother disabling buffering. */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200577
Gilles Peskine449bd832023-01-11 14:50:10 +0100578 fseek(f, 0, SEEK_END);
579 if ((size = ftell(f)) == -1) {
580 fclose(f);
581 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200582 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 fseek(f, 0, SEEK_SET);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200584
585 *n = (size_t) size;
586
Gilles Peskine449bd832023-01-11 14:50:10 +0100587 if (*n + 1 == 0 ||
588 (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
589 fclose(f);
590 return MBEDTLS_ERR_DHM_ALLOC_FAILED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200591 }
592
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 if (fread(*buf, 1, *n, f) != *n) {
594 fclose(f);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100595
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100596 mbedtls_zeroize_and_free(*buf, *n + 1);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100597
Gilles Peskine449bd832023-01-11 14:50:10 +0100598 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200599 }
600
Gilles Peskine449bd832023-01-11 14:50:10 +0100601 fclose(f);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200602
603 (*buf)[*n] = '\0';
604
Gilles Peskine449bd832023-01-11 14:50:10 +0100605 if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200606 ++*n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100607 }
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200608
Gilles Peskine449bd832023-01-11 14:50:10 +0100609 return 0;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200610}
611
612/*
613 * Load and parse DHM parameters
614 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100615int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200616{
Janos Follath24eed8d2019-11-22 13:21:35 +0000617 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200618 size_t n;
619 unsigned char *buf;
620
Gilles Peskine449bd832023-01-11 14:50:10 +0100621 if ((ret = load_file(path, &buf, &n)) != 0) {
622 return ret;
623 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200624
Gilles Peskine449bd832023-01-11 14:50:10 +0100625 ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200626
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100627 mbedtls_zeroize_and_free(buf, n);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200628
Gilles Peskine449bd832023-01-11 14:50:10 +0100629 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200630}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200631#endif /* MBEDTLS_FS_IO */
632#endif /* MBEDTLS_ASN1_PARSE_C */
nirekh0149762fa2017-12-25 06:46:48 +0000633#endif /* MBEDTLS_DHM_ALT */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200634
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200635#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000636
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100637#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200638static const char mbedtls_test_dhm_params[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 "-----BEGIN DH PARAMETERS-----\r\n"
640 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
641 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
642 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
643 "-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100644#else /* MBEDTLS_PEM_PARSE_C */
645static const char mbedtls_test_dhm_params[] = {
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
647 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
648 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
649 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
650 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
651 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
652 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
653 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
654 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
655 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
656 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
657 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
658};
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100659#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200660
Gilles Peskine449bd832023-01-11 14:50:10 +0100661static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200662
Paul Bakker5121ce52009-01-03 21:22:43 +0000663/*
664 * Checkup routine
665 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100666int mbedtls_dhm_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +0000667{
Janos Follath24eed8d2019-11-22 13:21:35 +0000668 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200669 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200670
Gilles Peskine449bd832023-01-11 14:50:10 +0100671 mbedtls_dhm_init(&dhm);
Paul Bakker8f870b02014-06-20 13:32:38 +0200672
Gilles Peskine449bd832023-01-11 14:50:10 +0100673 if (verbose != 0) {
674 mbedtls_printf(" DHM parameter load: ");
675 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200676
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 if ((ret = mbedtls_dhm_parse_dhm(&dhm,
678 (const unsigned char *) mbedtls_test_dhm_params,
679 mbedtls_test_dhm_params_len)) != 0) {
680 if (verbose != 0) {
681 mbedtls_printf("failed\n");
682 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200683
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200684 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200685 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200686 }
687
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 if (verbose != 0) {
689 mbedtls_printf("passed\n\n");
690 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200691
Paul Bakker8f870b02014-06-20 13:32:38 +0200692exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100693 mbedtls_dhm_free(&dhm);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200694
Gilles Peskine449bd832023-01-11 14:50:10 +0100695 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000696}
697
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200698#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000699
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200700#endif /* MBEDTLS_DHM_C */