1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  Diffie-Hellman-Merkle key exchange
3a8e1175bSopenharmony_ci *
4a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
5a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6a8e1175bSopenharmony_ci */
7a8e1175bSopenharmony_ci/*
8a8e1175bSopenharmony_ci *  The following sources were referenced in the design of this implementation
9a8e1175bSopenharmony_ci *  of the Diffie-Hellman-Merkle algorithm:
10a8e1175bSopenharmony_ci *
11a8e1175bSopenharmony_ci *  [1] Handbook of Applied Cryptography - 1997, Chapter 12
12a8e1175bSopenharmony_ci *      Menezes, van Oorschot and Vanstone
13a8e1175bSopenharmony_ci *
14a8e1175bSopenharmony_ci */
15a8e1175bSopenharmony_ci
16a8e1175bSopenharmony_ci#include "common.h"
17a8e1175bSopenharmony_ci
18a8e1175bSopenharmony_ci#if defined(MBEDTLS_DHM_C)
19a8e1175bSopenharmony_ci
20a8e1175bSopenharmony_ci#include "mbedtls/dhm.h"
21a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h"
22a8e1175bSopenharmony_ci#include "mbedtls/error.h"
23a8e1175bSopenharmony_ci
24a8e1175bSopenharmony_ci#include <string.h>
25a8e1175bSopenharmony_ci
26a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
27a8e1175bSopenharmony_ci#include "mbedtls/pem.h"
28a8e1175bSopenharmony_ci#endif
29a8e1175bSopenharmony_ci
30a8e1175bSopenharmony_ci#if defined(MBEDTLS_ASN1_PARSE_C)
31a8e1175bSopenharmony_ci#include "mbedtls/asn1.h"
32a8e1175bSopenharmony_ci#endif
33a8e1175bSopenharmony_ci
34a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
35a8e1175bSopenharmony_ci
36a8e1175bSopenharmony_ci#if !defined(MBEDTLS_DHM_ALT)
37a8e1175bSopenharmony_ci
38a8e1175bSopenharmony_ci/*
39a8e1175bSopenharmony_ci * helper to validate the mbedtls_mpi size and import it
40a8e1175bSopenharmony_ci */
41a8e1175bSopenharmony_cistatic int dhm_read_bignum(mbedtls_mpi *X,
42a8e1175bSopenharmony_ci                           unsigned char **p,
43a8e1175bSopenharmony_ci                           const unsigned char *end)
44a8e1175bSopenharmony_ci{
45a8e1175bSopenharmony_ci    int ret, n;
46a8e1175bSopenharmony_ci
47a8e1175bSopenharmony_ci    if (end - *p < 2) {
48a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
49a8e1175bSopenharmony_ci    }
50a8e1175bSopenharmony_ci
51a8e1175bSopenharmony_ci    n = MBEDTLS_GET_UINT16_BE(*p, 0);
52a8e1175bSopenharmony_ci    (*p) += 2;
53a8e1175bSopenharmony_ci
54a8e1175bSopenharmony_ci    if ((size_t) (end - *p) < (size_t) n) {
55a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
56a8e1175bSopenharmony_ci    }
57a8e1175bSopenharmony_ci
58a8e1175bSopenharmony_ci    if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {
59a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
60a8e1175bSopenharmony_ci    }
61a8e1175bSopenharmony_ci
62a8e1175bSopenharmony_ci    (*p) += n;
63a8e1175bSopenharmony_ci
64a8e1175bSopenharmony_ci    return 0;
65a8e1175bSopenharmony_ci}
66a8e1175bSopenharmony_ci
67a8e1175bSopenharmony_ci/*
68a8e1175bSopenharmony_ci * Verify sanity of parameter with regards to P
69a8e1175bSopenharmony_ci *
70a8e1175bSopenharmony_ci * Parameter should be: 2 <= public_param <= P - 2
71a8e1175bSopenharmony_ci *
72a8e1175bSopenharmony_ci * This means that we need to return an error if
73a8e1175bSopenharmony_ci *              public_param < 2 or public_param > P-2
74a8e1175bSopenharmony_ci *
75a8e1175bSopenharmony_ci * For more information on the attack, see:
76a8e1175bSopenharmony_ci *  http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
77a8e1175bSopenharmony_ci *  http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
78a8e1175bSopenharmony_ci */
79a8e1175bSopenharmony_cistatic int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
80a8e1175bSopenharmony_ci{
81a8e1175bSopenharmony_ci    mbedtls_mpi U;
82a8e1175bSopenharmony_ci    int ret = 0;
83a8e1175bSopenharmony_ci
84a8e1175bSopenharmony_ci    mbedtls_mpi_init(&U);
85a8e1175bSopenharmony_ci
86a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
87a8e1175bSopenharmony_ci
88a8e1175bSopenharmony_ci    if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
89a8e1175bSopenharmony_ci        mbedtls_mpi_cmp_mpi(param, &U) > 0) {
90a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
91a8e1175bSopenharmony_ci    }
92a8e1175bSopenharmony_ci
93a8e1175bSopenharmony_cicleanup:
94a8e1175bSopenharmony_ci    mbedtls_mpi_free(&U);
95a8e1175bSopenharmony_ci    return ret;
96a8e1175bSopenharmony_ci}
97a8e1175bSopenharmony_ci
98a8e1175bSopenharmony_civoid mbedtls_dhm_init(mbedtls_dhm_context *ctx)
99a8e1175bSopenharmony_ci{
100a8e1175bSopenharmony_ci    memset(ctx, 0, sizeof(mbedtls_dhm_context));
101a8e1175bSopenharmony_ci}
102a8e1175bSopenharmony_ci
103a8e1175bSopenharmony_cisize_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)
104a8e1175bSopenharmony_ci{
105a8e1175bSopenharmony_ci    return mbedtls_mpi_bitlen(&ctx->P);
106a8e1175bSopenharmony_ci}
107a8e1175bSopenharmony_ci
108a8e1175bSopenharmony_cisize_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx)
109a8e1175bSopenharmony_ci{
110a8e1175bSopenharmony_ci    return mbedtls_mpi_size(&ctx->P);
111a8e1175bSopenharmony_ci}
112a8e1175bSopenharmony_ci
113a8e1175bSopenharmony_ciint mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,
114a8e1175bSopenharmony_ci                          mbedtls_dhm_parameter param,
115a8e1175bSopenharmony_ci                          mbedtls_mpi *dest)
116a8e1175bSopenharmony_ci{
117a8e1175bSopenharmony_ci    const mbedtls_mpi *src = NULL;
118a8e1175bSopenharmony_ci    switch (param) {
119a8e1175bSopenharmony_ci        case MBEDTLS_DHM_PARAM_P:
120a8e1175bSopenharmony_ci            src = &ctx->P;
121a8e1175bSopenharmony_ci            break;
122a8e1175bSopenharmony_ci        case MBEDTLS_DHM_PARAM_G:
123a8e1175bSopenharmony_ci            src = &ctx->G;
124a8e1175bSopenharmony_ci            break;
125a8e1175bSopenharmony_ci        case MBEDTLS_DHM_PARAM_X:
126a8e1175bSopenharmony_ci            src = &ctx->X;
127a8e1175bSopenharmony_ci            break;
128a8e1175bSopenharmony_ci        case MBEDTLS_DHM_PARAM_GX:
129a8e1175bSopenharmony_ci            src = &ctx->GX;
130a8e1175bSopenharmony_ci            break;
131a8e1175bSopenharmony_ci        case MBEDTLS_DHM_PARAM_GY:
132a8e1175bSopenharmony_ci            src = &ctx->GY;
133a8e1175bSopenharmony_ci            break;
134a8e1175bSopenharmony_ci        case MBEDTLS_DHM_PARAM_K:
135a8e1175bSopenharmony_ci            src = &ctx->K;
136a8e1175bSopenharmony_ci            break;
137a8e1175bSopenharmony_ci        default:
138a8e1175bSopenharmony_ci            return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
139a8e1175bSopenharmony_ci    }
140a8e1175bSopenharmony_ci    return mbedtls_mpi_copy(dest, src);
141a8e1175bSopenharmony_ci}
142a8e1175bSopenharmony_ci
143a8e1175bSopenharmony_ci/*
144a8e1175bSopenharmony_ci * Parse the ServerKeyExchange parameters
145a8e1175bSopenharmony_ci */
146a8e1175bSopenharmony_ciint mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
147a8e1175bSopenharmony_ci                            unsigned char **p,
148a8e1175bSopenharmony_ci                            const unsigned char *end)
149a8e1175bSopenharmony_ci{
150a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
151a8e1175bSopenharmony_ci
152a8e1175bSopenharmony_ci    if ((ret = dhm_read_bignum(&ctx->P,  p, end)) != 0 ||
153a8e1175bSopenharmony_ci        (ret = dhm_read_bignum(&ctx->G,  p, end)) != 0 ||
154a8e1175bSopenharmony_ci        (ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {
155a8e1175bSopenharmony_ci        return ret;
156a8e1175bSopenharmony_ci    }
157a8e1175bSopenharmony_ci
158a8e1175bSopenharmony_ci    if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
159a8e1175bSopenharmony_ci        return ret;
160a8e1175bSopenharmony_ci    }
161a8e1175bSopenharmony_ci
162a8e1175bSopenharmony_ci    return 0;
163a8e1175bSopenharmony_ci}
164a8e1175bSopenharmony_ci
165a8e1175bSopenharmony_ci/*
166a8e1175bSopenharmony_ci * Pick a random R in the range [2, M-2] for blinding or key generation.
167a8e1175bSopenharmony_ci */
168a8e1175bSopenharmony_cistatic int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,
169a8e1175bSopenharmony_ci                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
170a8e1175bSopenharmony_ci{
171a8e1175bSopenharmony_ci    int ret;
172a8e1175bSopenharmony_ci
173a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
174a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
175a8e1175bSopenharmony_ci
176a8e1175bSopenharmony_cicleanup:
177a8e1175bSopenharmony_ci    return ret;
178a8e1175bSopenharmony_ci}
179a8e1175bSopenharmony_ci
180a8e1175bSopenharmony_cistatic int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,
181a8e1175bSopenharmony_ci                           int (*f_rng)(void *, unsigned char *, size_t),
182a8e1175bSopenharmony_ci                           void *p_rng)
183a8e1175bSopenharmony_ci{
184a8e1175bSopenharmony_ci    int ret = 0;
185a8e1175bSopenharmony_ci
186a8e1175bSopenharmony_ci    if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {
187a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
188a8e1175bSopenharmony_ci    }
189a8e1175bSopenharmony_ci    if (x_size < 0) {
190a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
191a8e1175bSopenharmony_ci    }
192a8e1175bSopenharmony_ci
193a8e1175bSopenharmony_ci    if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {
194a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
195a8e1175bSopenharmony_ci    } else {
196a8e1175bSopenharmony_ci        /* Generate X as large as possible ( <= P - 2 ) */
197a8e1175bSopenharmony_ci        ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
198a8e1175bSopenharmony_ci        if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
199a8e1175bSopenharmony_ci            return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
200a8e1175bSopenharmony_ci        }
201a8e1175bSopenharmony_ci        if (ret != 0) {
202a8e1175bSopenharmony_ci            return ret;
203a8e1175bSopenharmony_ci        }
204a8e1175bSopenharmony_ci    }
205a8e1175bSopenharmony_ci
206a8e1175bSopenharmony_ci    /*
207a8e1175bSopenharmony_ci     * Calculate GX = G^X mod P
208a8e1175bSopenharmony_ci     */
209a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,
210a8e1175bSopenharmony_ci                                        &ctx->P, &ctx->RP));
211a8e1175bSopenharmony_ci
212a8e1175bSopenharmony_ci    if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {
213a8e1175bSopenharmony_ci        return ret;
214a8e1175bSopenharmony_ci    }
215a8e1175bSopenharmony_ci
216a8e1175bSopenharmony_cicleanup:
217a8e1175bSopenharmony_ci    return ret;
218a8e1175bSopenharmony_ci}
219a8e1175bSopenharmony_ci
220a8e1175bSopenharmony_ci/*
221a8e1175bSopenharmony_ci * Setup and write the ServerKeyExchange parameters
222a8e1175bSopenharmony_ci */
223a8e1175bSopenharmony_ciint mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
224a8e1175bSopenharmony_ci                            unsigned char *output, size_t *olen,
225a8e1175bSopenharmony_ci                            int (*f_rng)(void *, unsigned char *, size_t),
226a8e1175bSopenharmony_ci                            void *p_rng)
227a8e1175bSopenharmony_ci{
228a8e1175bSopenharmony_ci    int ret;
229a8e1175bSopenharmony_ci    size_t n1, n2, n3;
230a8e1175bSopenharmony_ci    unsigned char *p;
231a8e1175bSopenharmony_ci
232a8e1175bSopenharmony_ci    ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
233a8e1175bSopenharmony_ci    if (ret != 0) {
234a8e1175bSopenharmony_ci        goto cleanup;
235a8e1175bSopenharmony_ci    }
236a8e1175bSopenharmony_ci
237a8e1175bSopenharmony_ci    /*
238a8e1175bSopenharmony_ci     * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
239a8e1175bSopenharmony_ci     * not required". We omit leading zeros for compactness.
240a8e1175bSopenharmony_ci     */
241a8e1175bSopenharmony_ci#define DHM_MPI_EXPORT(X, n)                                          \
242a8e1175bSopenharmony_ci    do {                                                                \
243a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X),               \
244a8e1175bSopenharmony_ci                                                 p + 2,               \
245a8e1175bSopenharmony_ci                                                 (n)));           \
246a8e1175bSopenharmony_ci        *p++ = MBEDTLS_BYTE_1(n);                                     \
247a8e1175bSopenharmony_ci        *p++ = MBEDTLS_BYTE_0(n);                                     \
248a8e1175bSopenharmony_ci        p += (n);                                                     \
249a8e1175bSopenharmony_ci    } while (0)
250a8e1175bSopenharmony_ci
251a8e1175bSopenharmony_ci    n1 = mbedtls_mpi_size(&ctx->P);
252a8e1175bSopenharmony_ci    n2 = mbedtls_mpi_size(&ctx->G);
253a8e1175bSopenharmony_ci    n3 = mbedtls_mpi_size(&ctx->GX);
254a8e1175bSopenharmony_ci
255a8e1175bSopenharmony_ci    p = output;
256a8e1175bSopenharmony_ci    DHM_MPI_EXPORT(&ctx->P, n1);
257a8e1175bSopenharmony_ci    DHM_MPI_EXPORT(&ctx->G, n2);
258a8e1175bSopenharmony_ci    DHM_MPI_EXPORT(&ctx->GX, n3);
259a8e1175bSopenharmony_ci
260a8e1175bSopenharmony_ci    *olen = (size_t) (p - output);
261a8e1175bSopenharmony_ci
262a8e1175bSopenharmony_cicleanup:
263a8e1175bSopenharmony_ci    if (ret != 0 && ret > -128) {
264a8e1175bSopenharmony_ci        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
265a8e1175bSopenharmony_ci    }
266a8e1175bSopenharmony_ci    return ret;
267a8e1175bSopenharmony_ci}
268a8e1175bSopenharmony_ci
269a8e1175bSopenharmony_ci/*
270a8e1175bSopenharmony_ci * Set prime modulus and generator
271a8e1175bSopenharmony_ci */
272a8e1175bSopenharmony_ciint mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
273a8e1175bSopenharmony_ci                          const mbedtls_mpi *P,
274a8e1175bSopenharmony_ci                          const mbedtls_mpi *G)
275a8e1175bSopenharmony_ci{
276a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
277a8e1175bSopenharmony_ci
278a8e1175bSopenharmony_ci    if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
279a8e1175bSopenharmony_ci        (ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
280a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
281a8e1175bSopenharmony_ci    }
282a8e1175bSopenharmony_ci
283a8e1175bSopenharmony_ci    return 0;
284a8e1175bSopenharmony_ci}
285a8e1175bSopenharmony_ci
286a8e1175bSopenharmony_ci/*
287a8e1175bSopenharmony_ci * Import the peer's public value G^Y
288a8e1175bSopenharmony_ci */
289a8e1175bSopenharmony_ciint mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
290a8e1175bSopenharmony_ci                            const unsigned char *input, size_t ilen)
291a8e1175bSopenharmony_ci{
292a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
293a8e1175bSopenharmony_ci
294a8e1175bSopenharmony_ci    if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) {
295a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
296a8e1175bSopenharmony_ci    }
297a8e1175bSopenharmony_ci
298a8e1175bSopenharmony_ci    if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {
299a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
300a8e1175bSopenharmony_ci    }
301a8e1175bSopenharmony_ci
302a8e1175bSopenharmony_ci    return 0;
303a8e1175bSopenharmony_ci}
304a8e1175bSopenharmony_ci
305a8e1175bSopenharmony_ci/*
306a8e1175bSopenharmony_ci * Create own private value X and export G^X
307a8e1175bSopenharmony_ci */
308a8e1175bSopenharmony_ciint mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,
309a8e1175bSopenharmony_ci                            unsigned char *output, size_t olen,
310a8e1175bSopenharmony_ci                            int (*f_rng)(void *, unsigned char *, size_t),
311a8e1175bSopenharmony_ci                            void *p_rng)
312a8e1175bSopenharmony_ci{
313a8e1175bSopenharmony_ci    int ret;
314a8e1175bSopenharmony_ci
315a8e1175bSopenharmony_ci    if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) {
316a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
317a8e1175bSopenharmony_ci    }
318a8e1175bSopenharmony_ci
319a8e1175bSopenharmony_ci    ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
320a8e1175bSopenharmony_ci    if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) {
321a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;
322a8e1175bSopenharmony_ci    }
323a8e1175bSopenharmony_ci    if (ret != 0) {
324a8e1175bSopenharmony_ci        goto cleanup;
325a8e1175bSopenharmony_ci    }
326a8e1175bSopenharmony_ci
327a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
328a8e1175bSopenharmony_ci
329a8e1175bSopenharmony_cicleanup:
330a8e1175bSopenharmony_ci    if (ret != 0 && ret > -128) {
331a8e1175bSopenharmony_ci        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);
332a8e1175bSopenharmony_ci    }
333a8e1175bSopenharmony_ci    return ret;
334a8e1175bSopenharmony_ci}
335a8e1175bSopenharmony_ci
336a8e1175bSopenharmony_ci
337a8e1175bSopenharmony_ci/*
338a8e1175bSopenharmony_ci * Use the blinding method and optimisation suggested in section 10 of:
339a8e1175bSopenharmony_ci *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
340a8e1175bSopenharmony_ci *  DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
341a8e1175bSopenharmony_ci *  Berlin Heidelberg, 1996. p. 104-113.
342a8e1175bSopenharmony_ci */
343a8e1175bSopenharmony_cistatic int dhm_update_blinding(mbedtls_dhm_context *ctx,
344a8e1175bSopenharmony_ci                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
345a8e1175bSopenharmony_ci{
346a8e1175bSopenharmony_ci    int ret;
347a8e1175bSopenharmony_ci    mbedtls_mpi R;
348a8e1175bSopenharmony_ci
349a8e1175bSopenharmony_ci    mbedtls_mpi_init(&R);
350a8e1175bSopenharmony_ci
351a8e1175bSopenharmony_ci    /*
352a8e1175bSopenharmony_ci     * Don't use any blinding the first time a particular X is used,
353a8e1175bSopenharmony_ci     * but remember it to use blinding next time.
354a8e1175bSopenharmony_ci     */
355a8e1175bSopenharmony_ci    if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) {
356a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X));
357a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1));
358a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1));
359a8e1175bSopenharmony_ci
360a8e1175bSopenharmony_ci        return 0;
361a8e1175bSopenharmony_ci    }
362a8e1175bSopenharmony_ci
363a8e1175bSopenharmony_ci    /*
364a8e1175bSopenharmony_ci     * Ok, we need blinding. Can we re-use existing values?
365a8e1175bSopenharmony_ci     * If yes, just update them by squaring them.
366a8e1175bSopenharmony_ci     */
367a8e1175bSopenharmony_ci    if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) {
368a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
369a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P));
370a8e1175bSopenharmony_ci
371a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
372a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
373a8e1175bSopenharmony_ci
374a8e1175bSopenharmony_ci        return 0;
375a8e1175bSopenharmony_ci    }
376a8e1175bSopenharmony_ci
377a8e1175bSopenharmony_ci    /*
378a8e1175bSopenharmony_ci     * We need to generate blinding values from scratch
379a8e1175bSopenharmony_ci     */
380a8e1175bSopenharmony_ci
381a8e1175bSopenharmony_ci    /* Vi = random( 2, P-2 ) */
382a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng));
383a8e1175bSopenharmony_ci
384a8e1175bSopenharmony_ci    /* Vf = Vi^-X mod P
385a8e1175bSopenharmony_ci     * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
386a8e1175bSopenharmony_ci     * then elevate to the Xth power. */
387a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng));
388a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R));
389a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
390a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P));
391a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R));
392a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
393a8e1175bSopenharmony_ci
394a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP));
395a8e1175bSopenharmony_ci
396a8e1175bSopenharmony_cicleanup:
397a8e1175bSopenharmony_ci    mbedtls_mpi_free(&R);
398a8e1175bSopenharmony_ci
399a8e1175bSopenharmony_ci    return ret;
400a8e1175bSopenharmony_ci}
401a8e1175bSopenharmony_ci
402a8e1175bSopenharmony_ci/*
403a8e1175bSopenharmony_ci * Derive and export the shared secret (G^Y)^X mod P
404a8e1175bSopenharmony_ci */
405a8e1175bSopenharmony_ciint mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,
406a8e1175bSopenharmony_ci                            unsigned char *output, size_t output_size, size_t *olen,
407a8e1175bSopenharmony_ci                            int (*f_rng)(void *, unsigned char *, size_t),
408a8e1175bSopenharmony_ci                            void *p_rng)
409a8e1175bSopenharmony_ci{
410a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
411a8e1175bSopenharmony_ci    mbedtls_mpi GYb;
412a8e1175bSopenharmony_ci
413a8e1175bSopenharmony_ci    if (f_rng == NULL) {
414a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
415a8e1175bSopenharmony_ci    }
416a8e1175bSopenharmony_ci
417a8e1175bSopenharmony_ci    if (output_size < mbedtls_dhm_get_len(ctx)) {
418a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
419a8e1175bSopenharmony_ci    }
420a8e1175bSopenharmony_ci
421a8e1175bSopenharmony_ci    if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
422a8e1175bSopenharmony_ci        return ret;
423a8e1175bSopenharmony_ci    }
424a8e1175bSopenharmony_ci
425a8e1175bSopenharmony_ci    mbedtls_mpi_init(&GYb);
426a8e1175bSopenharmony_ci
427a8e1175bSopenharmony_ci    /* Blind peer's value */
428a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));
429a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));
430a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));
431a8e1175bSopenharmony_ci
432a8e1175bSopenharmony_ci    /* Do modular exponentiation */
433a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,
434a8e1175bSopenharmony_ci                                        &ctx->P, &ctx->RP));
435a8e1175bSopenharmony_ci
436a8e1175bSopenharmony_ci    /* Unblind secret value */
437a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
438a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
439a8e1175bSopenharmony_ci
440a8e1175bSopenharmony_ci    /* Output the secret without any leading zero byte. This is mandatory
441a8e1175bSopenharmony_ci     * for TLS per RFC 5246 §8.1.2. */
442a8e1175bSopenharmony_ci    *olen = mbedtls_mpi_size(&ctx->K);
443a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
444a8e1175bSopenharmony_ci
445a8e1175bSopenharmony_cicleanup:
446a8e1175bSopenharmony_ci    mbedtls_mpi_free(&GYb);
447a8e1175bSopenharmony_ci
448a8e1175bSopenharmony_ci    if (ret != 0) {
449a8e1175bSopenharmony_ci        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
450a8e1175bSopenharmony_ci    }
451a8e1175bSopenharmony_ci
452a8e1175bSopenharmony_ci    return 0;
453a8e1175bSopenharmony_ci}
454a8e1175bSopenharmony_ci
455a8e1175bSopenharmony_ci/*
456a8e1175bSopenharmony_ci * Free the components of a DHM key
457a8e1175bSopenharmony_ci */
458a8e1175bSopenharmony_civoid mbedtls_dhm_free(mbedtls_dhm_context *ctx)
459a8e1175bSopenharmony_ci{
460a8e1175bSopenharmony_ci    if (ctx == NULL) {
461a8e1175bSopenharmony_ci        return;
462a8e1175bSopenharmony_ci    }
463a8e1175bSopenharmony_ci
464a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->pX);
465a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->Vf);
466a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->Vi);
467a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->RP);
468a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->K);
469a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->GY);
470a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->GX);
471a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->X);
472a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->G);
473a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->P);
474a8e1175bSopenharmony_ci
475a8e1175bSopenharmony_ci    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
476a8e1175bSopenharmony_ci}
477a8e1175bSopenharmony_ci
478a8e1175bSopenharmony_ci#if defined(MBEDTLS_ASN1_PARSE_C)
479a8e1175bSopenharmony_ci/*
480a8e1175bSopenharmony_ci * Parse DHM parameters
481a8e1175bSopenharmony_ci */
482a8e1175bSopenharmony_ciint mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,
483a8e1175bSopenharmony_ci                          size_t dhminlen)
484a8e1175bSopenharmony_ci{
485a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
486a8e1175bSopenharmony_ci    size_t len;
487a8e1175bSopenharmony_ci    unsigned char *p, *end;
488a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
489a8e1175bSopenharmony_ci    mbedtls_pem_context pem;
490a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_PARSE_C */
491a8e1175bSopenharmony_ci
492a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
493a8e1175bSopenharmony_ci    mbedtls_pem_init(&pem);
494a8e1175bSopenharmony_ci
495a8e1175bSopenharmony_ci    /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
496a8e1175bSopenharmony_ci    if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') {
497a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
498a8e1175bSopenharmony_ci    } else {
499a8e1175bSopenharmony_ci        ret = mbedtls_pem_read_buffer(&pem,
500a8e1175bSopenharmony_ci                                      "-----BEGIN DH PARAMETERS-----",
501a8e1175bSopenharmony_ci                                      "-----END DH PARAMETERS-----",
502a8e1175bSopenharmony_ci                                      dhmin, NULL, 0, &dhminlen);
503a8e1175bSopenharmony_ci    }
504a8e1175bSopenharmony_ci
505a8e1175bSopenharmony_ci    if (ret == 0) {
506a8e1175bSopenharmony_ci        /*
507a8e1175bSopenharmony_ci         * Was PEM encoded
508a8e1175bSopenharmony_ci         */
509a8e1175bSopenharmony_ci        dhminlen = pem.buflen;
510a8e1175bSopenharmony_ci    } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
511a8e1175bSopenharmony_ci        goto exit;
512a8e1175bSopenharmony_ci    }
513a8e1175bSopenharmony_ci
514a8e1175bSopenharmony_ci    p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;
515a8e1175bSopenharmony_ci#else
516a8e1175bSopenharmony_ci    p = (unsigned char *) dhmin;
517a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_PARSE_C */
518a8e1175bSopenharmony_ci    end = p + dhminlen;
519a8e1175bSopenharmony_ci
520a8e1175bSopenharmony_ci    /*
521a8e1175bSopenharmony_ci     *  DHParams ::= SEQUENCE {
522a8e1175bSopenharmony_ci     *      prime              INTEGER,  -- P
523a8e1175bSopenharmony_ci     *      generator          INTEGER,  -- g
524a8e1175bSopenharmony_ci     *      privateValueLength INTEGER OPTIONAL
525a8e1175bSopenharmony_ci     *  }
526a8e1175bSopenharmony_ci     */
527a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
528a8e1175bSopenharmony_ci                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
529a8e1175bSopenharmony_ci        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
530a8e1175bSopenharmony_ci        goto exit;
531a8e1175bSopenharmony_ci    }
532a8e1175bSopenharmony_ci
533a8e1175bSopenharmony_ci    end = p + len;
534a8e1175bSopenharmony_ci
535a8e1175bSopenharmony_ci    if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
536a8e1175bSopenharmony_ci        (ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
537a8e1175bSopenharmony_ci        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
538a8e1175bSopenharmony_ci        goto exit;
539a8e1175bSopenharmony_ci    }
540a8e1175bSopenharmony_ci
541a8e1175bSopenharmony_ci    if (p != end) {
542a8e1175bSopenharmony_ci        /* This might be the optional privateValueLength.
543a8e1175bSopenharmony_ci         * If so, we can cleanly discard it */
544a8e1175bSopenharmony_ci        mbedtls_mpi rec;
545a8e1175bSopenharmony_ci        mbedtls_mpi_init(&rec);
546a8e1175bSopenharmony_ci        ret = mbedtls_asn1_get_mpi(&p, end, &rec);
547a8e1175bSopenharmony_ci        mbedtls_mpi_free(&rec);
548a8e1175bSopenharmony_ci        if (ret != 0) {
549a8e1175bSopenharmony_ci            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
550a8e1175bSopenharmony_ci            goto exit;
551a8e1175bSopenharmony_ci        }
552a8e1175bSopenharmony_ci        if (p != end) {
553a8e1175bSopenharmony_ci            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
554a8e1175bSopenharmony_ci                                    MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
555a8e1175bSopenharmony_ci            goto exit;
556a8e1175bSopenharmony_ci        }
557a8e1175bSopenharmony_ci    }
558a8e1175bSopenharmony_ci
559a8e1175bSopenharmony_ci    ret = 0;
560a8e1175bSopenharmony_ci
561a8e1175bSopenharmony_ciexit:
562a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
563a8e1175bSopenharmony_ci    mbedtls_pem_free(&pem);
564a8e1175bSopenharmony_ci#endif
565a8e1175bSopenharmony_ci    if (ret != 0) {
566a8e1175bSopenharmony_ci        mbedtls_dhm_free(dhm);
567a8e1175bSopenharmony_ci    }
568a8e1175bSopenharmony_ci
569a8e1175bSopenharmony_ci    return ret;
570a8e1175bSopenharmony_ci}
571a8e1175bSopenharmony_ci
572a8e1175bSopenharmony_ci#if defined(MBEDTLS_FS_IO)
573a8e1175bSopenharmony_ci/*
574a8e1175bSopenharmony_ci * Load all data from a file into a given buffer.
575a8e1175bSopenharmony_ci *
576a8e1175bSopenharmony_ci * The file is expected to contain either PEM or DER encoded data.
577a8e1175bSopenharmony_ci * A terminating null byte is always appended. It is included in the announced
578a8e1175bSopenharmony_ci * length only if the data looks like it is PEM encoded.
579a8e1175bSopenharmony_ci */
580a8e1175bSopenharmony_cistatic int load_file(const char *path, unsigned char **buf, size_t *n)
581a8e1175bSopenharmony_ci{
582a8e1175bSopenharmony_ci    FILE *f;
583a8e1175bSopenharmony_ci    long size;
584a8e1175bSopenharmony_ci
585a8e1175bSopenharmony_ci    if ((f = fopen(path, "rb")) == NULL) {
586a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
587a8e1175bSopenharmony_ci    }
588a8e1175bSopenharmony_ci    /* The data loaded here is public, so don't bother disabling buffering. */
589a8e1175bSopenharmony_ci
590a8e1175bSopenharmony_ci    fseek(f, 0, SEEK_END);
591a8e1175bSopenharmony_ci    if ((size = ftell(f)) == -1) {
592a8e1175bSopenharmony_ci        fclose(f);
593a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
594a8e1175bSopenharmony_ci    }
595a8e1175bSopenharmony_ci    fseek(f, 0, SEEK_SET);
596a8e1175bSopenharmony_ci
597a8e1175bSopenharmony_ci    *n = (size_t) size;
598a8e1175bSopenharmony_ci
599a8e1175bSopenharmony_ci    if (*n + 1 == 0 ||
600a8e1175bSopenharmony_ci        (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
601a8e1175bSopenharmony_ci        fclose(f);
602a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_ALLOC_FAILED;
603a8e1175bSopenharmony_ci    }
604a8e1175bSopenharmony_ci
605a8e1175bSopenharmony_ci    if (fread(*buf, 1, *n, f) != *n) {
606a8e1175bSopenharmony_ci        fclose(f);
607a8e1175bSopenharmony_ci
608a8e1175bSopenharmony_ci        mbedtls_zeroize_and_free(*buf, *n + 1);
609a8e1175bSopenharmony_ci
610a8e1175bSopenharmony_ci        return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
611a8e1175bSopenharmony_ci    }
612a8e1175bSopenharmony_ci
613a8e1175bSopenharmony_ci    fclose(f);
614a8e1175bSopenharmony_ci
615a8e1175bSopenharmony_ci    (*buf)[*n] = '\0';
616a8e1175bSopenharmony_ci
617a8e1175bSopenharmony_ci    if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
618a8e1175bSopenharmony_ci        ++*n;
619a8e1175bSopenharmony_ci    }
620a8e1175bSopenharmony_ci
621a8e1175bSopenharmony_ci    return 0;
622a8e1175bSopenharmony_ci}
623a8e1175bSopenharmony_ci
624a8e1175bSopenharmony_ci/*
625a8e1175bSopenharmony_ci * Load and parse DHM parameters
626a8e1175bSopenharmony_ci */
627a8e1175bSopenharmony_ciint mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
628a8e1175bSopenharmony_ci{
629a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
630a8e1175bSopenharmony_ci    size_t n;
631a8e1175bSopenharmony_ci    unsigned char *buf;
632a8e1175bSopenharmony_ci
633a8e1175bSopenharmony_ci    if ((ret = load_file(path, &buf, &n)) != 0) {
634a8e1175bSopenharmony_ci        return ret;
635a8e1175bSopenharmony_ci    }
636a8e1175bSopenharmony_ci
637a8e1175bSopenharmony_ci    ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
638a8e1175bSopenharmony_ci
639a8e1175bSopenharmony_ci    mbedtls_zeroize_and_free(buf, n);
640a8e1175bSopenharmony_ci
641a8e1175bSopenharmony_ci    return ret;
642a8e1175bSopenharmony_ci}
643a8e1175bSopenharmony_ci#endif /* MBEDTLS_FS_IO */
644a8e1175bSopenharmony_ci#endif /* MBEDTLS_ASN1_PARSE_C */
645a8e1175bSopenharmony_ci#endif /* MBEDTLS_DHM_ALT */
646a8e1175bSopenharmony_ci
647a8e1175bSopenharmony_ci#if defined(MBEDTLS_SELF_TEST)
648a8e1175bSopenharmony_ci
649a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_PARSE_C)
650a8e1175bSopenharmony_cistatic const char mbedtls_test_dhm_params[] =
651a8e1175bSopenharmony_ci    "-----BEGIN DH PARAMETERS-----\r\n"
652a8e1175bSopenharmony_ci    "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
653a8e1175bSopenharmony_ci    "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
654a8e1175bSopenharmony_ci    "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
655a8e1175bSopenharmony_ci    "-----END DH PARAMETERS-----\r\n";
656a8e1175bSopenharmony_ci#else /* MBEDTLS_PEM_PARSE_C */
657a8e1175bSopenharmony_cistatic const char mbedtls_test_dhm_params[] = {
658a8e1175bSopenharmony_ci    0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
659a8e1175bSopenharmony_ci    0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
660a8e1175bSopenharmony_ci    0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
661a8e1175bSopenharmony_ci    0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
662a8e1175bSopenharmony_ci    0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
663a8e1175bSopenharmony_ci    0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
664a8e1175bSopenharmony_ci    0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
665a8e1175bSopenharmony_ci    0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
666a8e1175bSopenharmony_ci    0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
667a8e1175bSopenharmony_ci    0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
668a8e1175bSopenharmony_ci    0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
669a8e1175bSopenharmony_ci    0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
670a8e1175bSopenharmony_ci};
671a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_PARSE_C */
672a8e1175bSopenharmony_ci
673a8e1175bSopenharmony_cistatic const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);
674a8e1175bSopenharmony_ci
675a8e1175bSopenharmony_ci/*
676a8e1175bSopenharmony_ci * Checkup routine
677a8e1175bSopenharmony_ci */
678a8e1175bSopenharmony_ciint mbedtls_dhm_self_test(int verbose)
679a8e1175bSopenharmony_ci{
680a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
681a8e1175bSopenharmony_ci    mbedtls_dhm_context dhm;
682a8e1175bSopenharmony_ci
683a8e1175bSopenharmony_ci    mbedtls_dhm_init(&dhm);
684a8e1175bSopenharmony_ci
685a8e1175bSopenharmony_ci    if (verbose != 0) {
686a8e1175bSopenharmony_ci        mbedtls_printf("  DHM parameter load: ");
687a8e1175bSopenharmony_ci    }
688a8e1175bSopenharmony_ci
689a8e1175bSopenharmony_ci    if ((ret = mbedtls_dhm_parse_dhm(&dhm,
690a8e1175bSopenharmony_ci                                     (const unsigned char *) mbedtls_test_dhm_params,
691a8e1175bSopenharmony_ci                                     mbedtls_test_dhm_params_len)) != 0) {
692a8e1175bSopenharmony_ci        if (verbose != 0) {
693a8e1175bSopenharmony_ci            mbedtls_printf("failed\n");
694a8e1175bSopenharmony_ci        }
695a8e1175bSopenharmony_ci
696a8e1175bSopenharmony_ci        ret = 1;
697a8e1175bSopenharmony_ci        goto exit;
698a8e1175bSopenharmony_ci    }
699a8e1175bSopenharmony_ci
700a8e1175bSopenharmony_ci    if (verbose != 0) {
701a8e1175bSopenharmony_ci        mbedtls_printf("passed\n\n");
702a8e1175bSopenharmony_ci    }
703a8e1175bSopenharmony_ci
704a8e1175bSopenharmony_ciexit:
705a8e1175bSopenharmony_ci    mbedtls_dhm_free(&dhm);
706a8e1175bSopenharmony_ci
707a8e1175bSopenharmony_ci    return ret;
708a8e1175bSopenharmony_ci}
709a8e1175bSopenharmony_ci
710a8e1175bSopenharmony_ci#endif /* MBEDTLS_SELF_TEST */
711a8e1175bSopenharmony_ci
712a8e1175bSopenharmony_ci#endif /* MBEDTLS_DHM_C */
713