xref: /optee_os/lib/libmbedtls/mbedtls/library/dhm.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Diffie-Hellman-Merkle key exchange
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander /*
20817466cbSJens Wiklander  *  The following sources were referenced in the design of this implementation
21817466cbSJens Wiklander  *  of the Diffie-Hellman-Merkle algorithm:
22817466cbSJens Wiklander  *
23817466cbSJens Wiklander  *  [1] Handbook of Applied Cryptography - 1997, Chapter 12
24817466cbSJens Wiklander  *      Menezes, van Oorschot and Vanstone
25817466cbSJens Wiklander  *
26817466cbSJens Wiklander  */
27817466cbSJens Wiklander 
287901324dSJerome Forissier #include "common.h"
29817466cbSJens Wiklander 
30817466cbSJens Wiklander #if defined(MBEDTLS_DHM_C)
31817466cbSJens Wiklander 
32817466cbSJens Wiklander #include "mbedtls/dhm.h"
333d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
3411fa71b9SJerome Forissier #include "mbedtls/error.h"
35817466cbSJens Wiklander 
36817466cbSJens Wiklander #include <string.h>
37817466cbSJens Wiklander 
38817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
39817466cbSJens Wiklander #include "mbedtls/pem.h"
40817466cbSJens Wiklander #endif
41817466cbSJens Wiklander 
42817466cbSJens Wiklander #if defined(MBEDTLS_ASN1_PARSE_C)
43817466cbSJens Wiklander #include "mbedtls/asn1.h"
44817466cbSJens Wiklander #endif
45817466cbSJens Wiklander 
46817466cbSJens Wiklander #include "mbedtls/platform.h"
47817466cbSJens Wiklander 
483d3b0591SJens Wiklander #if !defined(MBEDTLS_DHM_ALT)
493d3b0591SJens Wiklander 
50817466cbSJens Wiklander /*
51817466cbSJens Wiklander  * helper to validate the mbedtls_mpi size and import it
52817466cbSJens Wiklander  */
53817466cbSJens Wiklander static int dhm_read_bignum(mbedtls_mpi *X,
54817466cbSJens Wiklander                            unsigned char **p,
55817466cbSJens Wiklander                            const unsigned char *end)
56817466cbSJens Wiklander {
57817466cbSJens Wiklander     int ret, n;
58817466cbSJens Wiklander 
59*32b31808SJens Wiklander     if (end - *p < 2) {
60*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
61*32b31808SJens Wiklander     }
62817466cbSJens Wiklander 
63817466cbSJens Wiklander     n = ((*p)[0] << 8) | (*p)[1];
64817466cbSJens Wiklander     (*p) += 2;
65817466cbSJens Wiklander 
66*32b31808SJens Wiklander     if ((int) (end - *p) < n) {
67*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
68*32b31808SJens Wiklander     }
69817466cbSJens Wiklander 
70*32b31808SJens Wiklander     if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {
71*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
72*32b31808SJens Wiklander     }
73817466cbSJens Wiklander 
74817466cbSJens Wiklander     (*p) += n;
75817466cbSJens Wiklander 
76*32b31808SJens Wiklander     return 0;
77817466cbSJens Wiklander }
78817466cbSJens Wiklander 
79817466cbSJens Wiklander /*
80817466cbSJens Wiklander  * Verify sanity of parameter with regards to P
81817466cbSJens Wiklander  *
82817466cbSJens Wiklander  * Parameter should be: 2 <= public_param <= P - 2
83817466cbSJens Wiklander  *
843d3b0591SJens Wiklander  * This means that we need to return an error if
853d3b0591SJens Wiklander  *              public_param < 2 or public_param > P-2
863d3b0591SJens Wiklander  *
87817466cbSJens Wiklander  * For more information on the attack, see:
88817466cbSJens Wiklander  *  http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
89817466cbSJens Wiklander  *  http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
90817466cbSJens Wiklander  */
91817466cbSJens Wiklander static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
92817466cbSJens Wiklander {
937901324dSJerome Forissier     mbedtls_mpi U;
943d3b0591SJens Wiklander     int ret = 0;
95817466cbSJens Wiklander 
967901324dSJerome Forissier     mbedtls_mpi_init(&U);
97817466cbSJens Wiklander 
98817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
99817466cbSJens Wiklander 
1007901324dSJerome Forissier     if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
101*32b31808SJens Wiklander         mbedtls_mpi_cmp_mpi(param, &U) > 0) {
1023d3b0591SJens Wiklander         ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
103817466cbSJens Wiklander     }
104817466cbSJens Wiklander 
105817466cbSJens Wiklander cleanup:
1067901324dSJerome Forissier     mbedtls_mpi_free(&U);
107*32b31808SJens Wiklander     return ret;
108817466cbSJens Wiklander }
109817466cbSJens Wiklander 
110817466cbSJens Wiklander void mbedtls_dhm_init(mbedtls_dhm_context *ctx)
111817466cbSJens Wiklander {
112817466cbSJens Wiklander     memset(ctx, 0, sizeof(mbedtls_dhm_context));
113817466cbSJens Wiklander }
114817466cbSJens Wiklander 
115*32b31808SJens Wiklander size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)
116*32b31808SJens Wiklander {
117*32b31808SJens Wiklander     return mbedtls_mpi_bitlen(&ctx->P);
118*32b31808SJens Wiklander }
119*32b31808SJens Wiklander 
120*32b31808SJens Wiklander size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx)
121*32b31808SJens Wiklander {
122*32b31808SJens Wiklander     return mbedtls_mpi_size(&ctx->P);
123*32b31808SJens Wiklander }
124*32b31808SJens Wiklander 
125*32b31808SJens Wiklander int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,
126*32b31808SJens Wiklander                           mbedtls_dhm_parameter param,
127*32b31808SJens Wiklander                           mbedtls_mpi *dest)
128*32b31808SJens Wiklander {
129*32b31808SJens Wiklander     const mbedtls_mpi *src = NULL;
130*32b31808SJens Wiklander     switch (param) {
131*32b31808SJens Wiklander         case MBEDTLS_DHM_PARAM_P:
132*32b31808SJens Wiklander             src = &ctx->P;
133*32b31808SJens Wiklander             break;
134*32b31808SJens Wiklander         case MBEDTLS_DHM_PARAM_G:
135*32b31808SJens Wiklander             src = &ctx->G;
136*32b31808SJens Wiklander             break;
137*32b31808SJens Wiklander         case MBEDTLS_DHM_PARAM_X:
138*32b31808SJens Wiklander             src = &ctx->X;
139*32b31808SJens Wiklander             break;
140*32b31808SJens Wiklander         case MBEDTLS_DHM_PARAM_GX:
141*32b31808SJens Wiklander             src = &ctx->GX;
142*32b31808SJens Wiklander             break;
143*32b31808SJens Wiklander         case MBEDTLS_DHM_PARAM_GY:
144*32b31808SJens Wiklander             src = &ctx->GY;
145*32b31808SJens Wiklander             break;
146*32b31808SJens Wiklander         case MBEDTLS_DHM_PARAM_K:
147*32b31808SJens Wiklander             src = &ctx->K;
148*32b31808SJens Wiklander             break;
149*32b31808SJens Wiklander         default:
150*32b31808SJens Wiklander             return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
151*32b31808SJens Wiklander     }
152*32b31808SJens Wiklander     return mbedtls_mpi_copy(dest, src);
153*32b31808SJens Wiklander }
154*32b31808SJens Wiklander 
155817466cbSJens Wiklander /*
156817466cbSJens Wiklander  * Parse the ServerKeyExchange parameters
157817466cbSJens Wiklander  */
158817466cbSJens Wiklander int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
159817466cbSJens Wiklander                             unsigned char **p,
160817466cbSJens Wiklander                             const unsigned char *end)
161817466cbSJens Wiklander {
16211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
163817466cbSJens Wiklander 
164817466cbSJens Wiklander     if ((ret = dhm_read_bignum(&ctx->P,  p, end)) != 0 ||
165817466cbSJens Wiklander         (ret = dhm_read_bignum(&ctx->G,  p, end)) != 0 ||
166*32b31808SJens Wiklander         (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {
167*32b31808SJens Wiklander         return ret;
168*32b31808SJens Wiklander     }
169817466cbSJens Wiklander 
170*32b31808SJens Wiklander     if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
171*32b31808SJens Wiklander         return ret;
172*32b31808SJens Wiklander     }
173817466cbSJens Wiklander 
174*32b31808SJens Wiklander     return 0;
175817466cbSJens Wiklander }
176817466cbSJens Wiklander 
177817466cbSJens Wiklander /*
1787901324dSJerome Forissier  * Pick a random R in the range [2, M-2] for blinding or key generation.
179817466cbSJens Wiklander  */
1807901324dSJerome Forissier static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,
1817901324dSJerome Forissier                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
1827901324dSJerome Forissier {
1837901324dSJerome Forissier     int ret;
1847901324dSJerome Forissier 
1857901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
1867901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
1877901324dSJerome Forissier 
1887901324dSJerome Forissier cleanup:
189*32b31808SJens Wiklander     return ret;
1907901324dSJerome Forissier }
1917901324dSJerome Forissier 
1927901324dSJerome Forissier static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,
193817466cbSJens Wiklander                            int (*f_rng)(void *, unsigned char *, size_t),
194817466cbSJens Wiklander                            void *p_rng)
195817466cbSJens Wiklander {
1967901324dSJerome Forissier     int ret = 0;
197817466cbSJens Wiklander 
198*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {
199*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
200817466cbSJens Wiklander     }
201*32b31808SJens Wiklander     if (x_size < 0) {
202*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
203*32b31808SJens Wiklander     }
204*32b31808SJens Wiklander 
205*32b31808SJens Wiklander     if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {
206*32b31808SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
207*32b31808SJens Wiklander     } else {
2087901324dSJerome Forissier         /* Generate X as large as possible ( <= P - 2 ) */
2097901324dSJerome Forissier         ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
210*32b31808SJens Wiklander         if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
211*32b31808SJens Wiklander             return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
212*32b31808SJens Wiklander         }
213*32b31808SJens Wiklander         if (ret != 0) {
214*32b31808SJens Wiklander             return ret;
215*32b31808SJens Wiklander         }
2167901324dSJerome Forissier     }
217817466cbSJens Wiklander 
218817466cbSJens Wiklander     /*
219817466cbSJens Wiklander      * Calculate GX = G^X mod P
220817466cbSJens Wiklander      */
221817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,
222817466cbSJens Wiklander                                         &ctx->P, &ctx->RP));
223817466cbSJens Wiklander 
224*32b31808SJens Wiklander     if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {
225*32b31808SJens Wiklander         return ret;
226*32b31808SJens Wiklander     }
227817466cbSJens Wiklander 
2287901324dSJerome Forissier cleanup:
229*32b31808SJens Wiklander     return ret;
2307901324dSJerome Forissier }
2317901324dSJerome Forissier 
232817466cbSJens Wiklander /*
2337901324dSJerome Forissier  * Setup and write the ServerKeyExchange parameters
2347901324dSJerome Forissier  */
2357901324dSJerome Forissier int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
2367901324dSJerome Forissier                             unsigned char *output, size_t *olen,
2377901324dSJerome Forissier                             int (*f_rng)(void *, unsigned char *, size_t),
2387901324dSJerome Forissier                             void *p_rng)
2397901324dSJerome Forissier {
2407901324dSJerome Forissier     int ret;
2417901324dSJerome Forissier     size_t n1, n2, n3;
2427901324dSJerome Forissier     unsigned char *p;
2437901324dSJerome Forissier 
2447901324dSJerome Forissier     ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
245*32b31808SJens Wiklander     if (ret != 0) {
2467901324dSJerome Forissier         goto cleanup;
247*32b31808SJens Wiklander     }
2487901324dSJerome Forissier 
2497901324dSJerome Forissier     /*
2507901324dSJerome Forissier      * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
2517901324dSJerome Forissier      * not required". We omit leading zeros for compactness.
252817466cbSJens Wiklander      */
253817466cbSJens Wiklander #define DHM_MPI_EXPORT(X, n)                                          \
2543d3b0591SJens Wiklander     do {                                                                \
2553d3b0591SJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X),               \
2563d3b0591SJens Wiklander                                                  p + 2,               \
2573d3b0591SJens Wiklander                                                  (n)));           \
258039e02dfSJerome Forissier         *p++ = MBEDTLS_BYTE_1(n);                                     \
259039e02dfSJerome Forissier         *p++ = MBEDTLS_BYTE_0(n);                                     \
2603d3b0591SJens Wiklander         p += (n);                                                     \
2613d3b0591SJens Wiklander     } while (0)
262817466cbSJens Wiklander 
263817466cbSJens Wiklander     n1 = mbedtls_mpi_size(&ctx->P);
264817466cbSJens Wiklander     n2 = mbedtls_mpi_size(&ctx->G);
265817466cbSJens Wiklander     n3 = mbedtls_mpi_size(&ctx->GX);
266817466cbSJens Wiklander 
267817466cbSJens Wiklander     p = output;
268817466cbSJens Wiklander     DHM_MPI_EXPORT(&ctx->P, n1);
269817466cbSJens Wiklander     DHM_MPI_EXPORT(&ctx->G, n2);
270817466cbSJens Wiklander     DHM_MPI_EXPORT(&ctx->GX, n3);
271817466cbSJens Wiklander 
272817466cbSJens Wiklander     *olen = p - output;
273817466cbSJens Wiklander 
274817466cbSJens Wiklander cleanup:
275*32b31808SJens Wiklander     if (ret != 0 && ret > -128) {
2767901324dSJerome Forissier         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
277*32b31808SJens Wiklander     }
278*32b31808SJens Wiklander     return ret;
279817466cbSJens Wiklander }
280817466cbSJens Wiklander 
281817466cbSJens Wiklander /*
2823d3b0591SJens Wiklander  * Set prime modulus and generator
2833d3b0591SJens Wiklander  */
2843d3b0591SJens Wiklander int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
2853d3b0591SJens Wiklander                           const mbedtls_mpi *P,
2863d3b0591SJens Wiklander                           const mbedtls_mpi *G)
2873d3b0591SJens Wiklander {
28811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
2893d3b0591SJens Wiklander 
2903d3b0591SJens Wiklander     if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
291*32b31808SJens Wiklander         (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
292*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
2933d3b0591SJens Wiklander     }
2943d3b0591SJens Wiklander 
295*32b31808SJens Wiklander     return 0;
2963d3b0591SJens Wiklander }
2973d3b0591SJens Wiklander 
2983d3b0591SJens Wiklander /*
299817466cbSJens Wiklander  * Import the peer's public value G^Y
300817466cbSJens Wiklander  */
301817466cbSJens Wiklander int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
302817466cbSJens Wiklander                             const unsigned char *input, size_t ilen)
303817466cbSJens Wiklander {
30411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
305817466cbSJens Wiklander 
306*32b31808SJens Wiklander     if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) {
307*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
308*32b31808SJens Wiklander     }
309817466cbSJens Wiklander 
310*32b31808SJens Wiklander     if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {
311*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
312*32b31808SJens Wiklander     }
313817466cbSJens Wiklander 
314*32b31808SJens Wiklander     return 0;
315817466cbSJens Wiklander }
316817466cbSJens Wiklander 
317817466cbSJens Wiklander /*
318817466cbSJens Wiklander  * Create own private value X and export G^X
319817466cbSJens Wiklander  */
320817466cbSJens Wiklander int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,
321817466cbSJens Wiklander                             unsigned char *output, size_t olen,
322817466cbSJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t),
323817466cbSJens Wiklander                             void *p_rng)
324817466cbSJens Wiklander {
3257901324dSJerome Forissier     int ret;
326817466cbSJens Wiklander 
327*32b31808SJens Wiklander     if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) {
328*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
329*32b31808SJens Wiklander     }
330817466cbSJens Wiklander 
3317901324dSJerome Forissier     ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
332*32b31808SJens Wiklander     if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) {
333*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;
334*32b31808SJens Wiklander     }
335*32b31808SJens Wiklander     if (ret != 0) {
3367901324dSJerome Forissier         goto cleanup;
337*32b31808SJens Wiklander     }
338817466cbSJens Wiklander 
339817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
340817466cbSJens Wiklander 
341817466cbSJens Wiklander cleanup:
342*32b31808SJens Wiklander     if (ret != 0 && ret > -128) {
3437901324dSJerome Forissier         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);
344*32b31808SJens Wiklander     }
345*32b31808SJens Wiklander     return ret;
346817466cbSJens Wiklander }
347817466cbSJens Wiklander 
3487901324dSJerome Forissier 
349817466cbSJens Wiklander /*
350817466cbSJens Wiklander  * Use the blinding method and optimisation suggested in section 10 of:
351817466cbSJens Wiklander  *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
352817466cbSJens Wiklander  *  DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
353817466cbSJens Wiklander  *  Berlin Heidelberg, 1996. p. 104-113.
354817466cbSJens Wiklander  */
355817466cbSJens Wiklander static int dhm_update_blinding(mbedtls_dhm_context *ctx,
356817466cbSJens Wiklander                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
357817466cbSJens Wiklander {
3587901324dSJerome Forissier     int ret;
3597901324dSJerome Forissier     mbedtls_mpi R;
3607901324dSJerome Forissier 
3617901324dSJerome Forissier     mbedtls_mpi_init(&R);
362817466cbSJens Wiklander 
363817466cbSJens Wiklander     /*
364817466cbSJens Wiklander      * Don't use any blinding the first time a particular X is used,
365817466cbSJens Wiklander      * but remember it to use blinding next time.
366817466cbSJens Wiklander      */
367*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) {
368817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X));
369817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1));
370817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1));
371817466cbSJens Wiklander 
372*32b31808SJens Wiklander         return 0;
373817466cbSJens Wiklander     }
374817466cbSJens Wiklander 
375817466cbSJens Wiklander     /*
376817466cbSJens Wiklander      * Ok, we need blinding. Can we re-use existing values?
377817466cbSJens Wiklander      * If yes, just update them by squaring them.
378817466cbSJens Wiklander      */
379*32b31808SJens Wiklander     if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) {
380817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
381817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P));
382817466cbSJens Wiklander 
383817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
384817466cbSJens Wiklander         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
385817466cbSJens Wiklander 
386*32b31808SJens Wiklander         return 0;
387817466cbSJens Wiklander     }
388817466cbSJens Wiklander 
389817466cbSJens Wiklander     /*
390817466cbSJens Wiklander      * We need to generate blinding values from scratch
391817466cbSJens Wiklander      */
392817466cbSJens Wiklander 
3937901324dSJerome Forissier     /* Vi = random( 2, P-2 ) */
3947901324dSJerome Forissier     MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng));
395817466cbSJens Wiklander 
3967901324dSJerome Forissier     /* Vf = Vi^-X mod P
3977901324dSJerome Forissier      * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
3987901324dSJerome Forissier      * then elevate to the Xth power. */
3997901324dSJerome Forissier     MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng));
4007901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R));
4017901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
4027901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P));
4037901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R));
4047901324dSJerome Forissier     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
405817466cbSJens Wiklander 
406817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP));
407817466cbSJens Wiklander 
408817466cbSJens Wiklander cleanup:
4097901324dSJerome Forissier     mbedtls_mpi_free(&R);
4107901324dSJerome Forissier 
411*32b31808SJens Wiklander     return ret;
412817466cbSJens Wiklander }
413817466cbSJens Wiklander 
414817466cbSJens Wiklander /*
415817466cbSJens Wiklander  * Derive and export the shared secret (G^Y)^X mod P
416817466cbSJens Wiklander  */
417817466cbSJens Wiklander int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,
418817466cbSJens Wiklander                             unsigned char *output, size_t output_size, size_t *olen,
419817466cbSJens Wiklander                             int (*f_rng)(void *, unsigned char *, size_t),
420817466cbSJens Wiklander                             void *p_rng)
421817466cbSJens Wiklander {
42211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
423817466cbSJens Wiklander     mbedtls_mpi GYb;
424817466cbSJens Wiklander 
425*32b31808SJens Wiklander     if (f_rng == NULL) {
426*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
427*32b31808SJens Wiklander     }
428817466cbSJens Wiklander 
429*32b31808SJens Wiklander     if (output_size < mbedtls_dhm_get_len(ctx)) {
430*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
431*32b31808SJens Wiklander     }
432*32b31808SJens Wiklander 
433*32b31808SJens Wiklander     if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
434*32b31808SJens Wiklander         return ret;
435*32b31808SJens Wiklander     }
436817466cbSJens Wiklander 
437817466cbSJens Wiklander     mbedtls_mpi_init(&GYb);
438817466cbSJens Wiklander 
439817466cbSJens Wiklander     /* Blind peer's value */
440817466cbSJens Wiklander     MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));
441817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));
442817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));
443817466cbSJens Wiklander 
444817466cbSJens Wiklander     /* Do modular exponentiation */
445817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,
446817466cbSJens Wiklander                                         &ctx->P, &ctx->RP));
447817466cbSJens Wiklander 
448817466cbSJens Wiklander     /* Unblind secret value */
449817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
450817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
451817466cbSJens Wiklander 
4527901324dSJerome Forissier     /* Output the secret without any leading zero byte. This is mandatory
4537901324dSJerome Forissier      * for TLS per RFC 5246 §8.1.2. */
454817466cbSJens Wiklander     *olen = mbedtls_mpi_size(&ctx->K);
455817466cbSJens Wiklander     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
456817466cbSJens Wiklander 
457817466cbSJens Wiklander cleanup:
458817466cbSJens Wiklander     mbedtls_mpi_free(&GYb);
459817466cbSJens Wiklander 
460*32b31808SJens Wiklander     if (ret != 0) {
461*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
462*32b31808SJens Wiklander     }
463817466cbSJens Wiklander 
464*32b31808SJens Wiklander     return 0;
465817466cbSJens Wiklander }
466817466cbSJens Wiklander 
467817466cbSJens Wiklander /*
468817466cbSJens Wiklander  * Free the components of a DHM key
469817466cbSJens Wiklander  */
470817466cbSJens Wiklander void mbedtls_dhm_free(mbedtls_dhm_context *ctx)
471817466cbSJens Wiklander {
472*32b31808SJens Wiklander     if (ctx == NULL) {
4733d3b0591SJens Wiklander         return;
474*32b31808SJens Wiklander     }
4753d3b0591SJens Wiklander 
4763d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->pX);
4773d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->Vf);
4783d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->Vi);
4793d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->RP);
4803d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->K);
4813d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->GY);
4823d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->GX);
4833d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->X);
4843d3b0591SJens Wiklander     mbedtls_mpi_free(&ctx->G);
485817466cbSJens Wiklander     mbedtls_mpi_free(&ctx->P);
486817466cbSJens Wiklander 
4873d3b0591SJens Wiklander     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
488817466cbSJens Wiklander }
489817466cbSJens Wiklander 
490817466cbSJens Wiklander #if defined(MBEDTLS_ASN1_PARSE_C)
491817466cbSJens Wiklander /*
492817466cbSJens Wiklander  * Parse DHM parameters
493817466cbSJens Wiklander  */
494817466cbSJens Wiklander int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,
495817466cbSJens Wiklander                           size_t dhminlen)
496817466cbSJens Wiklander {
49711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
498817466cbSJens Wiklander     size_t len;
499817466cbSJens Wiklander     unsigned char *p, *end;
500817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
501817466cbSJens Wiklander     mbedtls_pem_context pem;
5023d3b0591SJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */
503817466cbSJens Wiklander 
5043d3b0591SJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
505817466cbSJens Wiklander     mbedtls_pem_init(&pem);
506817466cbSJens Wiklander 
507817466cbSJens Wiklander     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
508*32b31808SJens Wiklander     if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') {
509817466cbSJens Wiklander         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
510*32b31808SJens Wiklander     } else {
511817466cbSJens Wiklander         ret = mbedtls_pem_read_buffer(&pem,
512817466cbSJens Wiklander                                       "-----BEGIN DH PARAMETERS-----",
513817466cbSJens Wiklander                                       "-----END DH PARAMETERS-----",
514817466cbSJens Wiklander                                       dhmin, NULL, 0, &dhminlen);
515*32b31808SJens Wiklander     }
516817466cbSJens Wiklander 
517*32b31808SJens Wiklander     if (ret == 0) {
518817466cbSJens Wiklander         /*
519817466cbSJens Wiklander          * Was PEM encoded
520817466cbSJens Wiklander          */
521817466cbSJens Wiklander         dhminlen = pem.buflen;
522*32b31808SJens Wiklander     } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
523817466cbSJens Wiklander         goto exit;
524*32b31808SJens Wiklander     }
525817466cbSJens Wiklander 
526817466cbSJens Wiklander     p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;
527817466cbSJens Wiklander #else
528817466cbSJens Wiklander     p = (unsigned char *) dhmin;
529817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */
530817466cbSJens Wiklander     end = p + dhminlen;
531817466cbSJens Wiklander 
532817466cbSJens Wiklander     /*
533817466cbSJens Wiklander      *  DHParams ::= SEQUENCE {
534817466cbSJens Wiklander      *      prime              INTEGER,  -- P
535817466cbSJens Wiklander      *      generator          INTEGER,  -- g
536817466cbSJens Wiklander      *      privateValueLength INTEGER OPTIONAL
537817466cbSJens Wiklander      *  }
538817466cbSJens Wiklander      */
539817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
540*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
5417901324dSJerome Forissier         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
542817466cbSJens Wiklander         goto exit;
543817466cbSJens Wiklander     }
544817466cbSJens Wiklander 
545817466cbSJens Wiklander     end = p + len;
546817466cbSJens Wiklander 
547817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
548*32b31808SJens Wiklander         (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
5497901324dSJerome Forissier         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
550817466cbSJens Wiklander         goto exit;
551817466cbSJens Wiklander     }
552817466cbSJens Wiklander 
553*32b31808SJens Wiklander     if (p != end) {
554817466cbSJens Wiklander         /* This might be the optional privateValueLength.
555817466cbSJens Wiklander          * If so, we can cleanly discard it */
556817466cbSJens Wiklander         mbedtls_mpi rec;
557817466cbSJens Wiklander         mbedtls_mpi_init(&rec);
558817466cbSJens Wiklander         ret = mbedtls_asn1_get_mpi(&p, end, &rec);
559817466cbSJens Wiklander         mbedtls_mpi_free(&rec);
560*32b31808SJens Wiklander         if (ret != 0) {
5617901324dSJerome Forissier             ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
562817466cbSJens Wiklander             goto exit;
563817466cbSJens Wiklander         }
564*32b31808SJens Wiklander         if (p != end) {
5657901324dSJerome Forissier             ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
5667901324dSJerome Forissier                                     MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
567817466cbSJens Wiklander             goto exit;
568817466cbSJens Wiklander         }
569817466cbSJens Wiklander     }
570817466cbSJens Wiklander 
571817466cbSJens Wiklander     ret = 0;
572817466cbSJens Wiklander 
573817466cbSJens Wiklander exit:
574817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
575817466cbSJens Wiklander     mbedtls_pem_free(&pem);
576817466cbSJens Wiklander #endif
577*32b31808SJens Wiklander     if (ret != 0) {
578817466cbSJens Wiklander         mbedtls_dhm_free(dhm);
579*32b31808SJens Wiklander     }
580817466cbSJens Wiklander 
581*32b31808SJens Wiklander     return ret;
582817466cbSJens Wiklander }
583817466cbSJens Wiklander 
584817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
585817466cbSJens Wiklander /*
586817466cbSJens Wiklander  * Load all data from a file into a given buffer.
587817466cbSJens Wiklander  *
588817466cbSJens Wiklander  * The file is expected to contain either PEM or DER encoded data.
589817466cbSJens Wiklander  * A terminating null byte is always appended. It is included in the announced
590817466cbSJens Wiklander  * length only if the data looks like it is PEM encoded.
591817466cbSJens Wiklander  */
592817466cbSJens Wiklander static int load_file(const char *path, unsigned char **buf, size_t *n)
593817466cbSJens Wiklander {
594817466cbSJens Wiklander     FILE *f;
595817466cbSJens Wiklander     long size;
596817466cbSJens Wiklander 
597*32b31808SJens Wiklander     if ((f = fopen(path, "rb")) == NULL) {
598*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
599*32b31808SJens Wiklander     }
600*32b31808SJens Wiklander     /* The data loaded here is public, so don't bother disabling buffering. */
601817466cbSJens Wiklander 
602817466cbSJens Wiklander     fseek(f, 0, SEEK_END);
603*32b31808SJens Wiklander     if ((size = ftell(f)) == -1) {
604817466cbSJens Wiklander         fclose(f);
605*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
606817466cbSJens Wiklander     }
607817466cbSJens Wiklander     fseek(f, 0, SEEK_SET);
608817466cbSJens Wiklander 
609817466cbSJens Wiklander     *n = (size_t) size;
610817466cbSJens Wiklander 
611817466cbSJens Wiklander     if (*n + 1 == 0 ||
612*32b31808SJens Wiklander         (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
613817466cbSJens Wiklander         fclose(f);
614*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_ALLOC_FAILED;
615817466cbSJens Wiklander     }
616817466cbSJens Wiklander 
617*32b31808SJens Wiklander     if (fread(*buf, 1, *n, f) != *n) {
618817466cbSJens Wiklander         fclose(f);
6193d3b0591SJens Wiklander 
6203d3b0591SJens Wiklander         mbedtls_platform_zeroize(*buf, *n + 1);
621817466cbSJens Wiklander         mbedtls_free(*buf);
6223d3b0591SJens Wiklander 
623*32b31808SJens Wiklander         return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
624817466cbSJens Wiklander     }
625817466cbSJens Wiklander 
626817466cbSJens Wiklander     fclose(f);
627817466cbSJens Wiklander 
628817466cbSJens Wiklander     (*buf)[*n] = '\0';
629817466cbSJens Wiklander 
630*32b31808SJens Wiklander     if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
631817466cbSJens Wiklander         ++*n;
632*32b31808SJens Wiklander     }
633817466cbSJens Wiklander 
634*32b31808SJens Wiklander     return 0;
635817466cbSJens Wiklander }
636817466cbSJens Wiklander 
637817466cbSJens Wiklander /*
638817466cbSJens Wiklander  * Load and parse DHM parameters
639817466cbSJens Wiklander  */
640817466cbSJens Wiklander int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
641817466cbSJens Wiklander {
64211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
643817466cbSJens Wiklander     size_t n;
644817466cbSJens Wiklander     unsigned char *buf;
645817466cbSJens Wiklander 
646*32b31808SJens Wiklander     if ((ret = load_file(path, &buf, &n)) != 0) {
647*32b31808SJens Wiklander         return ret;
648*32b31808SJens Wiklander     }
649817466cbSJens Wiklander 
650817466cbSJens Wiklander     ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
651817466cbSJens Wiklander 
6523d3b0591SJens Wiklander     mbedtls_platform_zeroize(buf, n);
653817466cbSJens Wiklander     mbedtls_free(buf);
654817466cbSJens Wiklander 
655*32b31808SJens Wiklander     return ret;
656817466cbSJens Wiklander }
657817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
658817466cbSJens Wiklander #endif /* MBEDTLS_ASN1_PARSE_C */
6593d3b0591SJens Wiklander #endif /* MBEDTLS_DHM_ALT */
660817466cbSJens Wiklander 
661817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
662817466cbSJens Wiklander 
6635b25c76aSJerome Forissier #if defined(MBEDTLS_PEM_PARSE_C)
664817466cbSJens Wiklander static const char mbedtls_test_dhm_params[] =
665817466cbSJens Wiklander     "-----BEGIN DH PARAMETERS-----\r\n"
666817466cbSJens Wiklander     "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
667817466cbSJens Wiklander     "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
668817466cbSJens Wiklander     "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
669817466cbSJens Wiklander     "-----END DH PARAMETERS-----\r\n";
6705b25c76aSJerome Forissier #else /* MBEDTLS_PEM_PARSE_C */
6715b25c76aSJerome Forissier static const char mbedtls_test_dhm_params[] = {
6725b25c76aSJerome Forissier     0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
6735b25c76aSJerome Forissier     0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
6745b25c76aSJerome Forissier     0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
6755b25c76aSJerome Forissier     0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
6765b25c76aSJerome Forissier     0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
6775b25c76aSJerome Forissier     0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
6785b25c76aSJerome Forissier     0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
6795b25c76aSJerome Forissier     0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
6805b25c76aSJerome Forissier     0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
6815b25c76aSJerome Forissier     0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
6825b25c76aSJerome Forissier     0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
683*32b31808SJens Wiklander     0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
684*32b31808SJens Wiklander };
6855b25c76aSJerome Forissier #endif /* MBEDTLS_PEM_PARSE_C */
686817466cbSJens Wiklander 
687817466cbSJens Wiklander static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);
688817466cbSJens Wiklander 
689817466cbSJens Wiklander /*
690817466cbSJens Wiklander  * Checkup routine
691817466cbSJens Wiklander  */
692817466cbSJens Wiklander int mbedtls_dhm_self_test(int verbose)
693817466cbSJens Wiklander {
69411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
695817466cbSJens Wiklander     mbedtls_dhm_context dhm;
696817466cbSJens Wiklander 
697817466cbSJens Wiklander     mbedtls_dhm_init(&dhm);
698817466cbSJens Wiklander 
699*32b31808SJens Wiklander     if (verbose != 0) {
700817466cbSJens Wiklander         mbedtls_printf("  DHM parameter load: ");
701*32b31808SJens Wiklander     }
702817466cbSJens Wiklander 
703817466cbSJens Wiklander     if ((ret = mbedtls_dhm_parse_dhm(&dhm,
704817466cbSJens Wiklander                                      (const unsigned char *) mbedtls_test_dhm_params,
705*32b31808SJens Wiklander                                      mbedtls_test_dhm_params_len)) != 0) {
706*32b31808SJens Wiklander         if (verbose != 0) {
707817466cbSJens Wiklander             mbedtls_printf("failed\n");
708*32b31808SJens Wiklander         }
709817466cbSJens Wiklander 
710817466cbSJens Wiklander         ret = 1;
711817466cbSJens Wiklander         goto exit;
712817466cbSJens Wiklander     }
713817466cbSJens Wiklander 
714*32b31808SJens Wiklander     if (verbose != 0) {
715817466cbSJens Wiklander         mbedtls_printf("passed\n\n");
716*32b31808SJens Wiklander     }
717817466cbSJens Wiklander 
718817466cbSJens Wiklander exit:
719817466cbSJens Wiklander     mbedtls_dhm_free(&dhm);
720817466cbSJens Wiklander 
721*32b31808SJens Wiklander     return ret;
722817466cbSJens Wiklander }
723817466cbSJens Wiklander 
724817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
725817466cbSJens Wiklander 
726817466cbSJens Wiklander #endif /* MBEDTLS_DHM_C */
727