blob: 75af8b7910a1170dce9910a2fa4cf3d954aa21ba [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"
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
Paul Bakker5121ce52009-01-03 21:22:43 +000036/*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020037 * helper to validate the mbedtls_mpi size and import it
Paul Bakker5121ce52009-01-03 21:22:43 +000038 */
Gilles Peskine449bd832023-01-11 14:50:10 +010039static int dhm_read_bignum(mbedtls_mpi *X,
40 unsigned char **p,
41 const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +000042{
43 int ret, n;
44
Gilles Peskine449bd832023-01-11 14:50:10 +010045 if (end - *p < 2) {
46 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
47 }
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Dave Rodgmana3d0f612023-11-03 23:34:02 +000049 n = MBEDTLS_GET_UINT16_BE(*p, 0);
Paul Bakker5121ce52009-01-03 21:22:43 +000050 (*p) += 2;
51
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +000052 if ((size_t) (end - *p) < (size_t) n) {
Gilles Peskine449bd832023-01-11 14:50:10 +010053 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
54 }
Paul Bakker5121ce52009-01-03 21:22:43 +000055
Gilles Peskine449bd832023-01-11 14:50:10 +010056 if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {
57 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
58 }
Paul Bakker5121ce52009-01-03 21:22:43 +000059
60 (*p) += n;
61
Gilles Peskine449bd832023-01-11 14:50:10 +010062 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +000063}
64
65/*
Paul Bakkeraec37cb2012-04-26 18:59:59 +000066 * Verify sanity of parameter with regards to P
Paul Bakker345a6fe2011-02-28 21:20:02 +000067 *
Paul Bakkeraec37cb2012-04-26 18:59:59 +000068 * Parameter should be: 2 <= public_param <= P - 2
Paul Bakker345a6fe2011-02-28 21:20:02 +000069 *
Janos Follathaa325d72017-09-20 15:33:24 +010070 * This means that we need to return an error if
Janos Follath1ad1c6d2017-09-21 09:02:11 +010071 * public_param < 2 or public_param > P-2
Janos Follathaa325d72017-09-20 15:33:24 +010072 *
Paul Bakker345a6fe2011-02-28 21:20:02 +000073 * For more information on the attack, see:
74 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
75 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
Paul Bakkerc47840e2011-02-20 16:37:30 +000076 */
Gilles Peskine449bd832023-01-11 14:50:10 +010077static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
Paul Bakkerc47840e2011-02-20 16:37:30 +000078{
Gilles Peskine8e38acc2021-03-31 22:56:43 +020079 mbedtls_mpi U;
Janos Follathaa325d72017-09-20 15:33:24 +010080 int ret = 0;
Paul Bakkerc47840e2011-02-20 16:37:30 +000081
Gilles Peskine449bd832023-01-11 14:50:10 +010082 mbedtls_mpi_init(&U);
Paul Bakker3d8fb632014-04-17 12:42:41 +020083
Gilles Peskine449bd832023-01-11 14:50:10 +010084 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
Paul Bakkerc47840e2011-02-20 16:37:30 +000085
Gilles Peskine449bd832023-01-11 14:50:10 +010086 if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
87 mbedtls_mpi_cmp_mpi(param, &U) > 0) {
Janos Follathaa325d72017-09-20 15:33:24 +010088 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkerc47840e2011-02-20 16:37:30 +000089 }
90
Paul Bakker3d8fb632014-04-17 12:42:41 +020091cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +010092 mbedtls_mpi_free(&U);
93 return ret;
Paul Bakkerc47840e2011-02-20 16:37:30 +000094}
95
Gilles Peskine449bd832023-01-11 14:50:10 +010096void mbedtls_dhm_init(mbedtls_dhm_context *ctx)
Paul Bakker8f870b02014-06-20 13:32:38 +020097{
Gilles Peskine449bd832023-01-11 14:50:10 +010098 memset(ctx, 0, sizeof(mbedtls_dhm_context));
Paul Bakker8f870b02014-06-20 13:32:38 +020099}
100
Gilles Peskine449bd832023-01-11 14:50:10 +0100101size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)
Gilles Peskine487bbf62021-05-27 22:17:07 +0200102{
Gilles Peskine449bd832023-01-11 14:50:10 +0100103 return mbedtls_mpi_bitlen(&ctx->P);
Gilles Peskine487bbf62021-05-27 22:17:07 +0200104}
105
Gilles Peskine449bd832023-01-11 14:50:10 +0100106size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx)
Gilles Peskine487bbf62021-05-27 22:17:07 +0200107{
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 return mbedtls_mpi_size(&ctx->P);
Gilles Peskine487bbf62021-05-27 22:17:07 +0200109}
110
Gilles Peskine449bd832023-01-11 14:50:10 +0100111int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,
112 mbedtls_dhm_parameter param,
113 mbedtls_mpi *dest)
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200114{
115 const mbedtls_mpi *src = NULL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 switch (param) {
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200117 case MBEDTLS_DHM_PARAM_P:
118 src = &ctx->P;
119 break;
120 case MBEDTLS_DHM_PARAM_G:
121 src = &ctx->G;
122 break;
123 case MBEDTLS_DHM_PARAM_X:
124 src = &ctx->X;
125 break;
126 case MBEDTLS_DHM_PARAM_GX:
127 src = &ctx->GX;
128 break;
129 case MBEDTLS_DHM_PARAM_GY:
130 src = &ctx->GY;
131 break;
132 case MBEDTLS_DHM_PARAM_K:
133 src = &ctx->K;
134 break;
135 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100136 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200137 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100138 return mbedtls_mpi_copy(dest, src);
Gilles Peskine71acc6e2021-05-27 22:50:53 +0200139}
140
Paul Bakkerc47840e2011-02-20 16:37:30 +0000141/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000142 * Parse the ServerKeyExchange parameters
143 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100144int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
145 unsigned char **p,
146 const unsigned char *end)
Paul Bakker5121ce52009-01-03 21:22:43 +0000147{
Janos Follath24eed8d2019-11-22 13:21:35 +0000148 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5121ce52009-01-03 21:22:43 +0000149
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 ||
151 (ret = dhm_read_bignum(&ctx->G, p, end)) != 0 ||
152 (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {
153 return ret;
154 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000155
Gilles Peskine449bd832023-01-11 14:50:10 +0100156 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
157 return ret;
158 }
Paul Bakker345a6fe2011-02-28 21:20:02 +0000159
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000161}
162
Gilles Peskine17f1a262021-03-31 22:48:14 +0200163/*
Gilles Peskineda7ee012021-03-31 23:04:50 +0200164 * Pick a random R in the range [2, M-2] for blinding or key generation.
Gilles Peskine17f1a262021-03-31 22:48:14 +0200165 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100166static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,
167 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Gilles Peskine17f1a262021-03-31 22:48:14 +0200168{
Gilles Peskineda7ee012021-03-31 23:04:50 +0200169 int ret;
Gilles Peskine17f1a262021-03-31 22:48:14 +0200170
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
172 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
Gilles Peskine17f1a262021-03-31 22:48:14 +0200173
174cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100175 return ret;
Gilles Peskine17f1a262021-03-31 22:48:14 +0200176}
177
Gilles Peskine449bd832023-01-11 14:50:10 +0100178static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,
179 int (*f_rng)(void *, unsigned char *, size_t),
180 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000181{
Gilles Peskine17f1a262021-03-31 22:48:14 +0200182 int ret = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000183
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {
185 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
Paul Bakkeraec37cb2012-04-26 18:59:59 +0000186 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 if (x_size < 0) {
188 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
189 }
190
191 if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {
192 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
193 } else {
Gilles Peskine17f1a262021-03-31 22:48:14 +0200194 /* Generate X as large as possible ( <= P - 2 ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100195 ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
196 if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
197 return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
198 }
199 if (ret != 0) {
200 return ret;
201 }
Gilles Peskine17f1a262021-03-31 22:48:14 +0200202 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000203
Paul Bakkerff7fe672010-07-18 09:45:05 +0000204 /*
205 * Calculate GX = G^X mod P
206 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,
208 &ctx->P, &ctx->RP));
Paul Bakker5121ce52009-01-03 21:22:43 +0000209
Gilles Peskine449bd832023-01-11 14:50:10 +0100210 if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {
211 return ret;
212 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000213
Gilles Peskinecb660f22021-03-31 22:35:13 +0200214cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 return ret;
Gilles Peskinecb660f22021-03-31 22:35:13 +0200216}
217
218/*
219 * Setup and write the ServerKeyExchange parameters
220 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100221int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
222 unsigned char *output, size_t *olen,
223 int (*f_rng)(void *, unsigned char *, size_t),
224 void *p_rng)
Gilles Peskinecb660f22021-03-31 22:35:13 +0200225{
226 int ret;
227 size_t n1, n2, n3;
228 unsigned char *p;
Gilles Peskinecb660f22021-03-31 22:35:13 +0200229
Gilles Peskine449bd832023-01-11 14:50:10 +0100230 ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
231 if (ret != 0) {
Gilles Peskinecb660f22021-03-31 22:35:13 +0200232 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 }
Gilles Peskinecb660f22021-03-31 22:35:13 +0200234
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 /*
Gilles Peskine03299dc2021-04-13 22:10:24 +0200236 * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
237 * not required". We omit leading zeros for compactness.
Paul Bakker5121ce52009-01-03 21:22:43 +0000238 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100239#define DHM_MPI_EXPORT(X, n) \
Hanno Beckere71ad122017-09-28 10:32:25 +0100240 do { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X), \
242 p + 2, \
243 (n))); \
244 *p++ = MBEDTLS_BYTE_1(n); \
245 *p++ = MBEDTLS_BYTE_0(n); \
246 p += (n); \
247 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 n1 = mbedtls_mpi_size(&ctx->P);
250 n2 = mbedtls_mpi_size(&ctx->G);
251 n3 = mbedtls_mpi_size(&ctx->GX);
Paul Bakker5121ce52009-01-03 21:22:43 +0000252
253 p = output;
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 DHM_MPI_EXPORT(&ctx->P, n1);
255 DHM_MPI_EXPORT(&ctx->G, n2);
256 DHM_MPI_EXPORT(&ctx->GX, n3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000257
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000258 *olen = (size_t) (p - output);
Paul Bakker5121ce52009-01-03 21:22:43 +0000259
Paul Bakker5121ce52009-01-03 21:22:43 +0000260cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 if (ret != 0 && ret > -128) {
262 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
263 }
264 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000265}
266
267/*
Hanno Becker8880e752017-10-04 13:15:08 +0100268 * Set prime modulus and generator
269 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100270int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
271 const mbedtls_mpi *P,
272 const mbedtls_mpi *G)
Hanno Becker8880e752017-10-04 13:15:08 +0100273{
Janos Follath24eed8d2019-11-22 13:21:35 +0000274 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker8880e752017-10-04 13:15:08 +0100275
Gilles Peskine449bd832023-01-11 14:50:10 +0100276 if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
277 (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
278 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
Hanno Becker8880e752017-10-04 13:15:08 +0100279 }
280
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 return 0;
Hanno Becker8880e752017-10-04 13:15:08 +0100282}
283
284/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000285 * Import the peer's public value G^Y
286 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100287int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
288 const unsigned char *input, size_t ilen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000289{
Janos Follath24eed8d2019-11-22 13:21:35 +0000290 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker5121ce52009-01-03 21:22:43 +0000291
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) {
293 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
294 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {
297 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
298 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000299
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000301}
302
303/*
304 * Create own private value X and export G^X
305 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100306int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,
307 unsigned char *output, size_t olen,
308 int (*f_rng)(void *, unsigned char *, size_t),
309 void *p_rng)
Paul Bakker5121ce52009-01-03 21:22:43 +0000310{
Gilles Peskinecb660f22021-03-31 22:35:13 +0200311 int ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000312
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) {
314 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
315 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000316
Gilles Peskine449bd832023-01-11 14:50:10 +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 Peskinecb660f22021-03-31 22:35:13 +0200322 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100323 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000324
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000326
327cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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 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é-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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +0100395 mbedtls_mpi_free(&R);
Manuel Pégourié-Gonnardaf721672020-06-25 12:47:22 +0200396
Gilles Peskine449bd832023-01-11 14:50:10 +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 Peskine449bd832023-01-11 14:50:10 +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;
Manuel Pégourié-Gonnard2d627642013-09-04 14:22:07 +0200410
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 if (f_rng == NULL) {
412 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
413 }
Manuel Pégourié-Gonnard1a877222021-06-15 11:29:26 +0200414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 if (output_size < mbedtls_dhm_get_len(ctx)) {
416 return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
417 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000418
Gilles Peskine449bd832023-01-11 14:50:10 +0100419 if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
420 return ret;
421 }
Paul Bakkerc47840e2011-02-20 16:37:30 +0000422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 mbedtls_mpi_init(&GYb);
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200424
425 /* Blind peer's value */
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 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));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200429
430 /* Do modular exponentiation */
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,
432 &ctx->P, &ctx->RP));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200433
434 /* Unblind secret value */
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
436 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
Manuel Pégourié-Gonnard143b5022013-09-04 16:29:59 +0200437
Gilles Peskine03299dc2021-04-13 22:10:24 +0200438 /* Output the secret without any leading zero byte. This is mandatory
439 * for TLS per RFC 5246 §8.1.2. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 *olen = mbedtls_mpi_size(&ctx->K);
441 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
Paul Bakker5121ce52009-01-03 21:22:43 +0000442
443cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 mbedtls_mpi_free(&GYb);
Paul Bakker5121ce52009-01-03 21:22:43 +0000445
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 if (ret != 0) {
447 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
448 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000451}
452
453/*
454 * Free the components of a DHM key
455 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100456void mbedtls_dhm_free(mbedtls_dhm_context *ctx)
Paul Bakker5121ce52009-01-03 21:22:43 +0000457{
Gilles Peskine449bd832023-01-11 14:50:10 +0100458 if (ctx == NULL) {
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500459 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100460 }
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500461
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 mbedtls_mpi_free(&ctx->pX);
463 mbedtls_mpi_free(&ctx->Vf);
464 mbedtls_mpi_free(&ctx->Vi);
465 mbedtls_mpi_free(&ctx->RP);
466 mbedtls_mpi_free(&ctx->K);
467 mbedtls_mpi_free(&ctx->GY);
468 mbedtls_mpi_free(&ctx->GX);
469 mbedtls_mpi_free(&ctx->X);
470 mbedtls_mpi_free(&ctx->G);
471 mbedtls_mpi_free(&ctx->P);
Manuel Pégourié-Gonnardb72b4ed2013-09-13 13:55:26 +0200472
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
Paul Bakker5121ce52009-01-03 21:22:43 +0000474}
475
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200476#if defined(MBEDTLS_ASN1_PARSE_C)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200477/*
478 * Parse DHM parameters
479 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100480int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,
481 size_t dhminlen)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200482{
Janos Follath24eed8d2019-11-22 13:21:35 +0000483 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200484 size_t len;
485 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200486#if defined(MBEDTLS_PEM_PARSE_C)
487 mbedtls_pem_context pem;
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500488#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200489
Andrzej Kurekc470b6b2019-01-31 08:20:20 -0500490#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 mbedtls_pem_init(&pem);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200492
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200493 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200495 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 } else {
497 ret = mbedtls_pem_read_buffer(&pem,
498 "-----BEGIN DH PARAMETERS-----",
499 "-----END DH PARAMETERS-----",
500 dhmin, NULL, 0, &dhminlen);
501 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200502
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 if (ret == 0) {
Paul Bakker40ce79f2013-09-15 17:43:54 +0200504 /*
505 * Was PEM encoded
506 */
507 dhminlen = pem.buflen;
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
Paul Bakker40ce79f2013-09-15 17:43:54 +0200509 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100510 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200511
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200513#else
514 p = (unsigned char *) dhmin;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200515#endif /* MBEDTLS_PEM_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200516 end = p + dhminlen;
517
518 /*
519 * DHParams ::= SEQUENCE {
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400520 * prime INTEGER, -- P
521 * generator INTEGER, -- g
522 * privateValueLength INTEGER OPTIONAL
Paul Bakker40ce79f2013-09-15 17:43:54 +0200523 * }
524 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100525 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
526 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
527 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200528 goto exit;
529 }
530
531 end = p + len;
532
Gilles Peskine449bd832023-01-11 14:50:10 +0100533 if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
534 (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
535 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200536 goto exit;
537 }
538
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 if (p != end) {
Manuel Pégourié-Gonnardde9b3632015-04-17 20:06:31 +0200540 /* This might be the optional privateValueLength.
541 * If so, we can cleanly discard it */
542 mbedtls_mpi rec;
Gilles Peskine449bd832023-01-11 14:50:10 +0100543 mbedtls_mpi_init(&rec);
544 ret = mbedtls_asn1_get_mpi(&p, end, &rec);
545 mbedtls_mpi_free(&rec);
546 if (ret != 0) {
547 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400548 goto exit;
549 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 if (p != end) {
551 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
552 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Daniel Kahn Gillmor2ed81732015-04-03 13:09:24 -0400553 goto exit;
554 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200555 }
556
557 ret = 0;
558
559exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200560#if defined(MBEDTLS_PEM_PARSE_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100561 mbedtls_pem_free(&pem);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200562#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100563 if (ret != 0) {
564 mbedtls_dhm_free(dhm);
565 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200566
Gilles Peskine449bd832023-01-11 14:50:10 +0100567 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200568}
569
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200570#if defined(MBEDTLS_FS_IO)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200571/*
572 * Load all data from a file into a given buffer.
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200573 *
574 * The file is expected to contain either PEM or DER encoded data.
575 * A terminating null byte is always appended. It is included in the announced
576 * length only if the data looks like it is PEM encoded.
Paul Bakker40ce79f2013-09-15 17:43:54 +0200577 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100578static int load_file(const char *path, unsigned char **buf, size_t *n)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200579{
580 FILE *f;
581 long size;
582
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 if ((f = fopen(path, "rb")) == NULL) {
584 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
585 }
Gilles Peskineda0913b2022-06-30 17:03:40 +0200586 /* The data loaded here is public, so don't bother disabling buffering. */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 fseek(f, 0, SEEK_END);
589 if ((size = ftell(f)) == -1) {
590 fclose(f);
591 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200592 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 fseek(f, 0, SEEK_SET);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200594
595 *n = (size_t) size;
596
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 if (*n + 1 == 0 ||
598 (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
599 fclose(f);
600 return MBEDTLS_ERR_DHM_ALLOC_FAILED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200601 }
602
Gilles Peskine449bd832023-01-11 14:50:10 +0100603 if (fread(*buf, 1, *n, f) != *n) {
604 fclose(f);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100605
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100606 mbedtls_zeroize_and_free(*buf, *n + 1);
Andres Amaya Garciabdbca7b2017-06-23 16:23:21 +0100607
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200609 }
610
Gilles Peskine449bd832023-01-11 14:50:10 +0100611 fclose(f);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200612
613 (*buf)[*n] = '\0';
614
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200616 ++*n;
Gilles Peskine449bd832023-01-11 14:50:10 +0100617 }
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200618
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 return 0;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200620}
621
622/*
623 * Load and parse DHM parameters
624 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100625int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
Paul Bakker40ce79f2013-09-15 17:43:54 +0200626{
Janos Follath24eed8d2019-11-22 13:21:35 +0000627 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200628 size_t n;
629 unsigned char *buf;
630
Gilles Peskine449bd832023-01-11 14:50:10 +0100631 if ((ret = load_file(path, &buf, &n)) != 0) {
632 return ret;
633 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200634
Gilles Peskine449bd832023-01-11 14:50:10 +0100635 ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200636
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100637 mbedtls_zeroize_and_free(buf, n);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200638
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 return ret;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200640}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200641#endif /* MBEDTLS_FS_IO */
642#endif /* MBEDTLS_ASN1_PARSE_C */
Paul Bakker40ce79f2013-09-15 17:43:54 +0200643
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200644#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000645
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100646#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200647static const char mbedtls_test_dhm_params[] =
Gilles Peskine449bd832023-01-11 14:50:10 +0100648 "-----BEGIN DH PARAMETERS-----\r\n"
649 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
650 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
651 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
652 "-----END DH PARAMETERS-----\r\n";
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100653#else /* MBEDTLS_PEM_PARSE_C */
654static const char mbedtls_test_dhm_params[] = {
Gilles Peskine449bd832023-01-11 14:50:10 +0100655 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
656 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
657 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
658 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
659 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
660 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
661 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
662 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
663 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
664 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
665 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
666 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
667};
Hanno Becker8b0f9e62019-05-31 17:28:59 +0100668#endif /* MBEDTLS_PEM_PARSE_C */
Manuel Pégourié-Gonnard53585ee2015-06-25 08:52:25 +0200669
Gilles Peskine449bd832023-01-11 14:50:10 +0100670static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200671
Paul Bakker5121ce52009-01-03 21:22:43 +0000672/*
673 * Checkup routine
674 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100675int mbedtls_dhm_self_test(int verbose)
Paul Bakker5121ce52009-01-03 21:22:43 +0000676{
Janos Follath24eed8d2019-11-22 13:21:35 +0000677 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200678 mbedtls_dhm_context dhm;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200679
Gilles Peskine449bd832023-01-11 14:50:10 +0100680 mbedtls_dhm_init(&dhm);
Paul Bakker8f870b02014-06-20 13:32:38 +0200681
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 if (verbose != 0) {
683 mbedtls_printf(" DHM parameter load: ");
684 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200685
Gilles Peskine449bd832023-01-11 14:50:10 +0100686 if ((ret = mbedtls_dhm_parse_dhm(&dhm,
687 (const unsigned char *) mbedtls_test_dhm_params,
688 mbedtls_test_dhm_params_len)) != 0) {
689 if (verbose != 0) {
690 mbedtls_printf("failed\n");
691 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200692
Manuel Pégourié-Gonnardb196fc22014-07-09 16:53:29 +0200693 ret = 1;
Paul Bakker8f870b02014-06-20 13:32:38 +0200694 goto exit;
Paul Bakker40ce79f2013-09-15 17:43:54 +0200695 }
696
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 if (verbose != 0) {
698 mbedtls_printf("passed\n\n");
699 }
Paul Bakker40ce79f2013-09-15 17:43:54 +0200700
Paul Bakker8f870b02014-06-20 13:32:38 +0200701exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100702 mbedtls_dhm_free(&dhm);
Paul Bakker40ce79f2013-09-15 17:43:54 +0200703
Gilles Peskine449bd832023-01-11 14:50:10 +0100704 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000705}
706
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200707#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000708
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200709#endif /* MBEDTLS_DHM_C */