1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  Elliptic curve Diffie-Hellman
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/*
9a8e1175bSopenharmony_ci * References:
10a8e1175bSopenharmony_ci *
11a8e1175bSopenharmony_ci * SEC1 https://www.secg.org/sec1-v2.pdf
12a8e1175bSopenharmony_ci * RFC 4492
13a8e1175bSopenharmony_ci */
14a8e1175bSopenharmony_ci
15a8e1175bSopenharmony_ci#include "common.h"
16a8e1175bSopenharmony_ci
17a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_C)
18a8e1175bSopenharmony_ci
19a8e1175bSopenharmony_ci#include "mbedtls/ecdh.h"
20a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h"
21a8e1175bSopenharmony_ci#include "mbedtls/error.h"
22a8e1175bSopenharmony_ci
23a8e1175bSopenharmony_ci#include <string.h>
24a8e1175bSopenharmony_ci
25a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
26a8e1175bSopenharmony_citypedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
27a8e1175bSopenharmony_ci#endif
28a8e1175bSopenharmony_ci
29a8e1175bSopenharmony_cistatic mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
30a8e1175bSopenharmony_ci    const mbedtls_ecdh_context *ctx)
31a8e1175bSopenharmony_ci{
32a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
33a8e1175bSopenharmony_ci    return ctx->grp.id;
34a8e1175bSopenharmony_ci#else
35a8e1175bSopenharmony_ci    return ctx->grp_id;
36a8e1175bSopenharmony_ci#endif
37a8e1175bSopenharmony_ci}
38a8e1175bSopenharmony_ci
39a8e1175bSopenharmony_ciint mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
40a8e1175bSopenharmony_ci{
41a8e1175bSopenharmony_ci    /* At this time, all groups support ECDH. */
42a8e1175bSopenharmony_ci    (void) gid;
43a8e1175bSopenharmony_ci    return 1;
44a8e1175bSopenharmony_ci}
45a8e1175bSopenharmony_ci
46a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
47a8e1175bSopenharmony_ci/*
48a8e1175bSopenharmony_ci * Generate public key (restartable version)
49a8e1175bSopenharmony_ci *
50a8e1175bSopenharmony_ci * Note: this internal function relies on its caller preserving the value of
51a8e1175bSopenharmony_ci * the output parameter 'd' across continuation calls. This would not be
52a8e1175bSopenharmony_ci * acceptable for a public function but is OK here as we control call sites.
53a8e1175bSopenharmony_ci */
54a8e1175bSopenharmony_cistatic int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
55a8e1175bSopenharmony_ci                                       mbedtls_mpi *d, mbedtls_ecp_point *Q,
56a8e1175bSopenharmony_ci                                       int (*f_rng)(void *, unsigned char *, size_t),
57a8e1175bSopenharmony_ci                                       void *p_rng,
58a8e1175bSopenharmony_ci                                       mbedtls_ecp_restart_ctx *rs_ctx)
59a8e1175bSopenharmony_ci{
60a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
61a8e1175bSopenharmony_ci
62a8e1175bSopenharmony_ci    int restarting = 0;
63a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
64a8e1175bSopenharmony_ci    restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
65a8e1175bSopenharmony_ci#endif
66a8e1175bSopenharmony_ci    /* If multiplication is in progress, we already generated a privkey */
67a8e1175bSopenharmony_ci    if (!restarting) {
68a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
69a8e1175bSopenharmony_ci    }
70a8e1175bSopenharmony_ci
71a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
72a8e1175bSopenharmony_ci                                                f_rng, p_rng, rs_ctx));
73a8e1175bSopenharmony_ci
74a8e1175bSopenharmony_cicleanup:
75a8e1175bSopenharmony_ci    return ret;
76a8e1175bSopenharmony_ci}
77a8e1175bSopenharmony_ci
78a8e1175bSopenharmony_ci/*
79a8e1175bSopenharmony_ci * Generate public key
80a8e1175bSopenharmony_ci */
81a8e1175bSopenharmony_ciint mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
82a8e1175bSopenharmony_ci                            int (*f_rng)(void *, unsigned char *, size_t),
83a8e1175bSopenharmony_ci                            void *p_rng)
84a8e1175bSopenharmony_ci{
85a8e1175bSopenharmony_ci    return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
86a8e1175bSopenharmony_ci}
87a8e1175bSopenharmony_ci#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
88a8e1175bSopenharmony_ci
89a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
90a8e1175bSopenharmony_ci/*
91a8e1175bSopenharmony_ci * Compute shared secret (SEC1 3.3.1)
92a8e1175bSopenharmony_ci */
93a8e1175bSopenharmony_cistatic int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
94a8e1175bSopenharmony_ci                                           mbedtls_mpi *z,
95a8e1175bSopenharmony_ci                                           const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
96a8e1175bSopenharmony_ci                                           int (*f_rng)(void *, unsigned char *, size_t),
97a8e1175bSopenharmony_ci                                           void *p_rng,
98a8e1175bSopenharmony_ci                                           mbedtls_ecp_restart_ctx *rs_ctx)
99a8e1175bSopenharmony_ci{
100a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101a8e1175bSopenharmony_ci    mbedtls_ecp_point P;
102a8e1175bSopenharmony_ci
103a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&P);
104a8e1175bSopenharmony_ci
105a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
106a8e1175bSopenharmony_ci                                                f_rng, p_rng, rs_ctx));
107a8e1175bSopenharmony_ci
108a8e1175bSopenharmony_ci    if (mbedtls_ecp_is_zero(&P)) {
109a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
110a8e1175bSopenharmony_ci        goto cleanup;
111a8e1175bSopenharmony_ci    }
112a8e1175bSopenharmony_ci
113a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
114a8e1175bSopenharmony_ci
115a8e1175bSopenharmony_cicleanup:
116a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&P);
117a8e1175bSopenharmony_ci
118a8e1175bSopenharmony_ci    return ret;
119a8e1175bSopenharmony_ci}
120a8e1175bSopenharmony_ci
121a8e1175bSopenharmony_ci/*
122a8e1175bSopenharmony_ci * Compute shared secret (SEC1 3.3.1)
123a8e1175bSopenharmony_ci */
124a8e1175bSopenharmony_ciint mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
125a8e1175bSopenharmony_ci                                const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
126a8e1175bSopenharmony_ci                                int (*f_rng)(void *, unsigned char *, size_t),
127a8e1175bSopenharmony_ci                                void *p_rng)
128a8e1175bSopenharmony_ci{
129a8e1175bSopenharmony_ci    return ecdh_compute_shared_restartable(grp, z, Q, d,
130a8e1175bSopenharmony_ci                                           f_rng, p_rng, NULL);
131a8e1175bSopenharmony_ci}
132a8e1175bSopenharmony_ci#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
133a8e1175bSopenharmony_ci
134a8e1175bSopenharmony_cistatic void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
135a8e1175bSopenharmony_ci{
136a8e1175bSopenharmony_ci    mbedtls_ecp_group_init(&ctx->grp);
137a8e1175bSopenharmony_ci    mbedtls_mpi_init(&ctx->d);
138a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&ctx->Q);
139a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&ctx->Qp);
140a8e1175bSopenharmony_ci    mbedtls_mpi_init(&ctx->z);
141a8e1175bSopenharmony_ci
142a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
143a8e1175bSopenharmony_ci    mbedtls_ecp_restart_init(&ctx->rs);
144a8e1175bSopenharmony_ci#endif
145a8e1175bSopenharmony_ci}
146a8e1175bSopenharmony_ci
147a8e1175bSopenharmony_cimbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
148a8e1175bSopenharmony_ci{
149a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
150a8e1175bSopenharmony_ci    return ctx->MBEDTLS_PRIVATE(grp).id;
151a8e1175bSopenharmony_ci#else
152a8e1175bSopenharmony_ci    return ctx->MBEDTLS_PRIVATE(grp_id);
153a8e1175bSopenharmony_ci#endif
154a8e1175bSopenharmony_ci}
155a8e1175bSopenharmony_ci
156a8e1175bSopenharmony_ci/*
157a8e1175bSopenharmony_ci * Initialize context
158a8e1175bSopenharmony_ci */
159a8e1175bSopenharmony_civoid mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
160a8e1175bSopenharmony_ci{
161a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
162a8e1175bSopenharmony_ci    ecdh_init_internal(ctx);
163a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&ctx->Vi);
164a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&ctx->Vf);
165a8e1175bSopenharmony_ci    mbedtls_mpi_init(&ctx->_d);
166a8e1175bSopenharmony_ci#else
167a8e1175bSopenharmony_ci    memset(ctx, 0, sizeof(mbedtls_ecdh_context));
168a8e1175bSopenharmony_ci
169a8e1175bSopenharmony_ci    ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
170a8e1175bSopenharmony_ci#endif
171a8e1175bSopenharmony_ci    ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
172a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
173a8e1175bSopenharmony_ci    ctx->restart_enabled = 0;
174a8e1175bSopenharmony_ci#endif
175a8e1175bSopenharmony_ci}
176a8e1175bSopenharmony_ci
177a8e1175bSopenharmony_cistatic int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
178a8e1175bSopenharmony_ci                               mbedtls_ecp_group_id grp_id)
179a8e1175bSopenharmony_ci{
180a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
181a8e1175bSopenharmony_ci
182a8e1175bSopenharmony_ci    ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
183a8e1175bSopenharmony_ci    if (ret != 0) {
184a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
185a8e1175bSopenharmony_ci    }
186a8e1175bSopenharmony_ci
187a8e1175bSopenharmony_ci    return 0;
188a8e1175bSopenharmony_ci}
189a8e1175bSopenharmony_ci
190a8e1175bSopenharmony_ci/*
191a8e1175bSopenharmony_ci * Setup context
192a8e1175bSopenharmony_ci */
193a8e1175bSopenharmony_ciint mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
194a8e1175bSopenharmony_ci{
195a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
196a8e1175bSopenharmony_ci    return ecdh_setup_internal(ctx, grp_id);
197a8e1175bSopenharmony_ci#else
198a8e1175bSopenharmony_ci    switch (grp_id) {
199a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
200a8e1175bSopenharmony_ci        case MBEDTLS_ECP_DP_CURVE25519:
201a8e1175bSopenharmony_ci            ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
202a8e1175bSopenharmony_ci            ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
203a8e1175bSopenharmony_ci            ctx->grp_id = grp_id;
204a8e1175bSopenharmony_ci            return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
205a8e1175bSopenharmony_ci#endif
206a8e1175bSopenharmony_ci        default:
207a8e1175bSopenharmony_ci            ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
208a8e1175bSopenharmony_ci            ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
209a8e1175bSopenharmony_ci            ctx->grp_id = grp_id;
210a8e1175bSopenharmony_ci            ecdh_init_internal(&ctx->ctx.mbed_ecdh);
211a8e1175bSopenharmony_ci            return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
212a8e1175bSopenharmony_ci    }
213a8e1175bSopenharmony_ci#endif
214a8e1175bSopenharmony_ci}
215a8e1175bSopenharmony_ci
216a8e1175bSopenharmony_cistatic void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
217a8e1175bSopenharmony_ci{
218a8e1175bSopenharmony_ci    mbedtls_ecp_group_free(&ctx->grp);
219a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->d);
220a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&ctx->Q);
221a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&ctx->Qp);
222a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->z);
223a8e1175bSopenharmony_ci
224a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
225a8e1175bSopenharmony_ci    mbedtls_ecp_restart_free(&ctx->rs);
226a8e1175bSopenharmony_ci#endif
227a8e1175bSopenharmony_ci}
228a8e1175bSopenharmony_ci
229a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
230a8e1175bSopenharmony_ci/*
231a8e1175bSopenharmony_ci * Enable restartable operations for context
232a8e1175bSopenharmony_ci */
233a8e1175bSopenharmony_civoid mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
234a8e1175bSopenharmony_ci{
235a8e1175bSopenharmony_ci    ctx->restart_enabled = 1;
236a8e1175bSopenharmony_ci}
237a8e1175bSopenharmony_ci#endif
238a8e1175bSopenharmony_ci
239a8e1175bSopenharmony_ci/*
240a8e1175bSopenharmony_ci * Free context
241a8e1175bSopenharmony_ci */
242a8e1175bSopenharmony_civoid mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
243a8e1175bSopenharmony_ci{
244a8e1175bSopenharmony_ci    if (ctx == NULL) {
245a8e1175bSopenharmony_ci        return;
246a8e1175bSopenharmony_ci    }
247a8e1175bSopenharmony_ci
248a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
249a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&ctx->Vi);
250a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&ctx->Vf);
251a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->_d);
252a8e1175bSopenharmony_ci    ecdh_free_internal(ctx);
253a8e1175bSopenharmony_ci#else
254a8e1175bSopenharmony_ci    switch (ctx->var) {
255a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
256a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_EVEREST:
257a8e1175bSopenharmony_ci            mbedtls_everest_free(&ctx->ctx.everest_ecdh);
258a8e1175bSopenharmony_ci            break;
259a8e1175bSopenharmony_ci#endif
260a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
261a8e1175bSopenharmony_ci            ecdh_free_internal(&ctx->ctx.mbed_ecdh);
262a8e1175bSopenharmony_ci            break;
263a8e1175bSopenharmony_ci        default:
264a8e1175bSopenharmony_ci            break;
265a8e1175bSopenharmony_ci    }
266a8e1175bSopenharmony_ci
267a8e1175bSopenharmony_ci    ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
268a8e1175bSopenharmony_ci    ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
269a8e1175bSopenharmony_ci    ctx->grp_id = MBEDTLS_ECP_DP_NONE;
270a8e1175bSopenharmony_ci#endif
271a8e1175bSopenharmony_ci}
272a8e1175bSopenharmony_ci
273a8e1175bSopenharmony_cistatic int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
274a8e1175bSopenharmony_ci                                     size_t *olen, int point_format,
275a8e1175bSopenharmony_ci                                     unsigned char *buf, size_t blen,
276a8e1175bSopenharmony_ci                                     int (*f_rng)(void *,
277a8e1175bSopenharmony_ci                                                  unsigned char *,
278a8e1175bSopenharmony_ci                                                  size_t),
279a8e1175bSopenharmony_ci                                     void *p_rng,
280a8e1175bSopenharmony_ci                                     int restart_enabled)
281a8e1175bSopenharmony_ci{
282a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
283a8e1175bSopenharmony_ci    size_t grp_len, pt_len;
284a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
285a8e1175bSopenharmony_ci    mbedtls_ecp_restart_ctx *rs_ctx = NULL;
286a8e1175bSopenharmony_ci#endif
287a8e1175bSopenharmony_ci
288a8e1175bSopenharmony_ci    if (ctx->grp.pbits == 0) {
289a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
290a8e1175bSopenharmony_ci    }
291a8e1175bSopenharmony_ci
292a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
293a8e1175bSopenharmony_ci    if (restart_enabled) {
294a8e1175bSopenharmony_ci        rs_ctx = &ctx->rs;
295a8e1175bSopenharmony_ci    }
296a8e1175bSopenharmony_ci#else
297a8e1175bSopenharmony_ci    (void) restart_enabled;
298a8e1175bSopenharmony_ci#endif
299a8e1175bSopenharmony_ci
300a8e1175bSopenharmony_ci
301a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
302a8e1175bSopenharmony_ci    if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
303a8e1175bSopenharmony_ci                                           f_rng, p_rng, rs_ctx)) != 0) {
304a8e1175bSopenharmony_ci        return ret;
305a8e1175bSopenharmony_ci    }
306a8e1175bSopenharmony_ci#else
307a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
308a8e1175bSopenharmony_ci                                       f_rng, p_rng)) != 0) {
309a8e1175bSopenharmony_ci        return ret;
310a8e1175bSopenharmony_ci    }
311a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECP_RESTARTABLE */
312a8e1175bSopenharmony_ci
313a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
314a8e1175bSopenharmony_ci                                           blen)) != 0) {
315a8e1175bSopenharmony_ci        return ret;
316a8e1175bSopenharmony_ci    }
317a8e1175bSopenharmony_ci
318a8e1175bSopenharmony_ci    buf += grp_len;
319a8e1175bSopenharmony_ci    blen -= grp_len;
320a8e1175bSopenharmony_ci
321a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
322a8e1175bSopenharmony_ci                                           &pt_len, buf, blen)) != 0) {
323a8e1175bSopenharmony_ci        return ret;
324a8e1175bSopenharmony_ci    }
325a8e1175bSopenharmony_ci
326a8e1175bSopenharmony_ci    *olen = grp_len + pt_len;
327a8e1175bSopenharmony_ci    return 0;
328a8e1175bSopenharmony_ci}
329a8e1175bSopenharmony_ci
330a8e1175bSopenharmony_ci/*
331a8e1175bSopenharmony_ci * Setup and write the ServerKeyExchange parameters (RFC 4492)
332a8e1175bSopenharmony_ci *      struct {
333a8e1175bSopenharmony_ci *          ECParameters    curve_params;
334a8e1175bSopenharmony_ci *          ECPoint         public;
335a8e1175bSopenharmony_ci *      } ServerECDHParams;
336a8e1175bSopenharmony_ci */
337a8e1175bSopenharmony_ciint mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
338a8e1175bSopenharmony_ci                             unsigned char *buf, size_t blen,
339a8e1175bSopenharmony_ci                             int (*f_rng)(void *, unsigned char *, size_t),
340a8e1175bSopenharmony_ci                             void *p_rng)
341a8e1175bSopenharmony_ci{
342a8e1175bSopenharmony_ci    int restart_enabled = 0;
343a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
344a8e1175bSopenharmony_ci    restart_enabled = ctx->restart_enabled;
345a8e1175bSopenharmony_ci#else
346a8e1175bSopenharmony_ci    (void) restart_enabled;
347a8e1175bSopenharmony_ci#endif
348a8e1175bSopenharmony_ci
349a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
350a8e1175bSopenharmony_ci    return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
351a8e1175bSopenharmony_ci                                     f_rng, p_rng, restart_enabled);
352a8e1175bSopenharmony_ci#else
353a8e1175bSopenharmony_ci    switch (ctx->var) {
354a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
355a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_EVEREST:
356a8e1175bSopenharmony_ci            return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
357a8e1175bSopenharmony_ci                                               buf, blen, f_rng, p_rng);
358a8e1175bSopenharmony_ci#endif
359a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
360a8e1175bSopenharmony_ci            return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
361a8e1175bSopenharmony_ci                                             ctx->point_format, buf, blen,
362a8e1175bSopenharmony_ci                                             f_rng, p_rng,
363a8e1175bSopenharmony_ci                                             restart_enabled);
364a8e1175bSopenharmony_ci        default:
365a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
366a8e1175bSopenharmony_ci    }
367a8e1175bSopenharmony_ci#endif
368a8e1175bSopenharmony_ci}
369a8e1175bSopenharmony_ci
370a8e1175bSopenharmony_cistatic int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
371a8e1175bSopenharmony_ci                                     const unsigned char **buf,
372a8e1175bSopenharmony_ci                                     const unsigned char *end)
373a8e1175bSopenharmony_ci{
374a8e1175bSopenharmony_ci    return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
375a8e1175bSopenharmony_ci                                      (size_t) (end - *buf));
376a8e1175bSopenharmony_ci}
377a8e1175bSopenharmony_ci
378a8e1175bSopenharmony_ci/*
379a8e1175bSopenharmony_ci * Read the ServerKeyExchange parameters (RFC 4492)
380a8e1175bSopenharmony_ci *      struct {
381a8e1175bSopenharmony_ci *          ECParameters    curve_params;
382a8e1175bSopenharmony_ci *          ECPoint         public;
383a8e1175bSopenharmony_ci *      } ServerECDHParams;
384a8e1175bSopenharmony_ci */
385a8e1175bSopenharmony_ciint mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
386a8e1175bSopenharmony_ci                             const unsigned char **buf,
387a8e1175bSopenharmony_ci                             const unsigned char *end)
388a8e1175bSopenharmony_ci{
389a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
390a8e1175bSopenharmony_ci    mbedtls_ecp_group_id grp_id;
391a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
392a8e1175bSopenharmony_ci        != 0) {
393a8e1175bSopenharmony_ci        return ret;
394a8e1175bSopenharmony_ci    }
395a8e1175bSopenharmony_ci
396a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
397a8e1175bSopenharmony_ci        return ret;
398a8e1175bSopenharmony_ci    }
399a8e1175bSopenharmony_ci
400a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
401a8e1175bSopenharmony_ci    return ecdh_read_params_internal(ctx, buf, end);
402a8e1175bSopenharmony_ci#else
403a8e1175bSopenharmony_ci    switch (ctx->var) {
404a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
405a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_EVEREST:
406a8e1175bSopenharmony_ci            return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
407a8e1175bSopenharmony_ci                                               buf, end);
408a8e1175bSopenharmony_ci#endif
409a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
410a8e1175bSopenharmony_ci            return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
411a8e1175bSopenharmony_ci                                             buf, end);
412a8e1175bSopenharmony_ci        default:
413a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
414a8e1175bSopenharmony_ci    }
415a8e1175bSopenharmony_ci#endif
416a8e1175bSopenharmony_ci}
417a8e1175bSopenharmony_ci
418a8e1175bSopenharmony_cistatic int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
419a8e1175bSopenharmony_ci                                    const mbedtls_ecp_keypair *key,
420a8e1175bSopenharmony_ci                                    mbedtls_ecdh_side side)
421a8e1175bSopenharmony_ci{
422a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
423a8e1175bSopenharmony_ci
424a8e1175bSopenharmony_ci    /* If it's not our key, just import the public part as Qp */
425a8e1175bSopenharmony_ci    if (side == MBEDTLS_ECDH_THEIRS) {
426a8e1175bSopenharmony_ci        return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
427a8e1175bSopenharmony_ci    }
428a8e1175bSopenharmony_ci
429a8e1175bSopenharmony_ci    /* Our key: import public (as Q) and private parts */
430a8e1175bSopenharmony_ci    if (side != MBEDTLS_ECDH_OURS) {
431a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
432a8e1175bSopenharmony_ci    }
433a8e1175bSopenharmony_ci
434a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
435a8e1175bSopenharmony_ci        (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
436a8e1175bSopenharmony_ci        return ret;
437a8e1175bSopenharmony_ci    }
438a8e1175bSopenharmony_ci
439a8e1175bSopenharmony_ci    return 0;
440a8e1175bSopenharmony_ci}
441a8e1175bSopenharmony_ci
442a8e1175bSopenharmony_ci/*
443a8e1175bSopenharmony_ci * Get parameters from a keypair
444a8e1175bSopenharmony_ci */
445a8e1175bSopenharmony_ciint mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
446a8e1175bSopenharmony_ci                            const mbedtls_ecp_keypair *key,
447a8e1175bSopenharmony_ci                            mbedtls_ecdh_side side)
448a8e1175bSopenharmony_ci{
449a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
450a8e1175bSopenharmony_ci    if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
451a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
452a8e1175bSopenharmony_ci    }
453a8e1175bSopenharmony_ci
454a8e1175bSopenharmony_ci    if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
455a8e1175bSopenharmony_ci        /* This is the first call to get_params(). Set up the context
456a8e1175bSopenharmony_ci         * for use with the group. */
457a8e1175bSopenharmony_ci        if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
458a8e1175bSopenharmony_ci            return ret;
459a8e1175bSopenharmony_ci        }
460a8e1175bSopenharmony_ci    } else {
461a8e1175bSopenharmony_ci        /* This is not the first call to get_params(). Check that the
462a8e1175bSopenharmony_ci         * current key's group is the same as the context's, which was set
463a8e1175bSopenharmony_ci         * from the first key's group. */
464a8e1175bSopenharmony_ci        if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
465a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
466a8e1175bSopenharmony_ci        }
467a8e1175bSopenharmony_ci    }
468a8e1175bSopenharmony_ci
469a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
470a8e1175bSopenharmony_ci    return ecdh_get_params_internal(ctx, key, side);
471a8e1175bSopenharmony_ci#else
472a8e1175bSopenharmony_ci    switch (ctx->var) {
473a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
474a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_EVEREST:
475a8e1175bSopenharmony_ci        {
476a8e1175bSopenharmony_ci            mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
477a8e1175bSopenharmony_ci                                          MBEDTLS_EVEREST_ECDH_OURS :
478a8e1175bSopenharmony_ci                                          MBEDTLS_EVEREST_ECDH_THEIRS;
479a8e1175bSopenharmony_ci            return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
480a8e1175bSopenharmony_ci                                              key, s);
481a8e1175bSopenharmony_ci        }
482a8e1175bSopenharmony_ci#endif
483a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
484a8e1175bSopenharmony_ci            return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
485a8e1175bSopenharmony_ci                                            key, side);
486a8e1175bSopenharmony_ci        default:
487a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
488a8e1175bSopenharmony_ci    }
489a8e1175bSopenharmony_ci#endif
490a8e1175bSopenharmony_ci}
491a8e1175bSopenharmony_ci
492a8e1175bSopenharmony_cistatic int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
493a8e1175bSopenharmony_ci                                     size_t *olen, int point_format,
494a8e1175bSopenharmony_ci                                     unsigned char *buf, size_t blen,
495a8e1175bSopenharmony_ci                                     int (*f_rng)(void *,
496a8e1175bSopenharmony_ci                                                  unsigned char *,
497a8e1175bSopenharmony_ci                                                  size_t),
498a8e1175bSopenharmony_ci                                     void *p_rng,
499a8e1175bSopenharmony_ci                                     int restart_enabled)
500a8e1175bSopenharmony_ci{
501a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
502a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
503a8e1175bSopenharmony_ci    mbedtls_ecp_restart_ctx *rs_ctx = NULL;
504a8e1175bSopenharmony_ci#endif
505a8e1175bSopenharmony_ci
506a8e1175bSopenharmony_ci    if (ctx->grp.pbits == 0) {
507a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
508a8e1175bSopenharmony_ci    }
509a8e1175bSopenharmony_ci
510a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
511a8e1175bSopenharmony_ci    if (restart_enabled) {
512a8e1175bSopenharmony_ci        rs_ctx = &ctx->rs;
513a8e1175bSopenharmony_ci    }
514a8e1175bSopenharmony_ci#else
515a8e1175bSopenharmony_ci    (void) restart_enabled;
516a8e1175bSopenharmony_ci#endif
517a8e1175bSopenharmony_ci
518a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
519a8e1175bSopenharmony_ci    if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
520a8e1175bSopenharmony_ci                                           f_rng, p_rng, rs_ctx)) != 0) {
521a8e1175bSopenharmony_ci        return ret;
522a8e1175bSopenharmony_ci    }
523a8e1175bSopenharmony_ci#else
524a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
525a8e1175bSopenharmony_ci                                       f_rng, p_rng)) != 0) {
526a8e1175bSopenharmony_ci        return ret;
527a8e1175bSopenharmony_ci    }
528a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECP_RESTARTABLE */
529a8e1175bSopenharmony_ci
530a8e1175bSopenharmony_ci    return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
531a8e1175bSopenharmony_ci                                       buf, blen);
532a8e1175bSopenharmony_ci}
533a8e1175bSopenharmony_ci
534a8e1175bSopenharmony_ci/*
535a8e1175bSopenharmony_ci * Setup and export the client public value
536a8e1175bSopenharmony_ci */
537a8e1175bSopenharmony_ciint mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
538a8e1175bSopenharmony_ci                             unsigned char *buf, size_t blen,
539a8e1175bSopenharmony_ci                             int (*f_rng)(void *, unsigned char *, size_t),
540a8e1175bSopenharmony_ci                             void *p_rng)
541a8e1175bSopenharmony_ci{
542a8e1175bSopenharmony_ci    int restart_enabled = 0;
543a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
544a8e1175bSopenharmony_ci    restart_enabled = ctx->restart_enabled;
545a8e1175bSopenharmony_ci#endif
546a8e1175bSopenharmony_ci
547a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
548a8e1175bSopenharmony_ci    return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
549a8e1175bSopenharmony_ci                                     f_rng, p_rng, restart_enabled);
550a8e1175bSopenharmony_ci#else
551a8e1175bSopenharmony_ci    switch (ctx->var) {
552a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
553a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_EVEREST:
554a8e1175bSopenharmony_ci            return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
555a8e1175bSopenharmony_ci                                               buf, blen, f_rng, p_rng);
556a8e1175bSopenharmony_ci#endif
557a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
558a8e1175bSopenharmony_ci            return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
559a8e1175bSopenharmony_ci                                             ctx->point_format, buf, blen,
560a8e1175bSopenharmony_ci                                             f_rng, p_rng,
561a8e1175bSopenharmony_ci                                             restart_enabled);
562a8e1175bSopenharmony_ci        default:
563a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
564a8e1175bSopenharmony_ci    }
565a8e1175bSopenharmony_ci#endif
566a8e1175bSopenharmony_ci}
567a8e1175bSopenharmony_ci
568a8e1175bSopenharmony_cistatic int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
569a8e1175bSopenharmony_ci                                     const unsigned char *buf, size_t blen)
570a8e1175bSopenharmony_ci{
571a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
572a8e1175bSopenharmony_ci    const unsigned char *p = buf;
573a8e1175bSopenharmony_ci
574a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
575a8e1175bSopenharmony_ci                                          blen)) != 0) {
576a8e1175bSopenharmony_ci        return ret;
577a8e1175bSopenharmony_ci    }
578a8e1175bSopenharmony_ci
579a8e1175bSopenharmony_ci    if ((size_t) (p - buf) != blen) {
580a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
581a8e1175bSopenharmony_ci    }
582a8e1175bSopenharmony_ci
583a8e1175bSopenharmony_ci    return 0;
584a8e1175bSopenharmony_ci}
585a8e1175bSopenharmony_ci
586a8e1175bSopenharmony_ci/*
587a8e1175bSopenharmony_ci * Parse and import the client's public value
588a8e1175bSopenharmony_ci */
589a8e1175bSopenharmony_ciint mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
590a8e1175bSopenharmony_ci                             const unsigned char *buf, size_t blen)
591a8e1175bSopenharmony_ci{
592a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
593a8e1175bSopenharmony_ci    return ecdh_read_public_internal(ctx, buf, blen);
594a8e1175bSopenharmony_ci#else
595a8e1175bSopenharmony_ci    switch (ctx->var) {
596a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
597a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_EVEREST:
598a8e1175bSopenharmony_ci            return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
599a8e1175bSopenharmony_ci                                               buf, blen);
600a8e1175bSopenharmony_ci#endif
601a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
602a8e1175bSopenharmony_ci            return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
603a8e1175bSopenharmony_ci                                             buf, blen);
604a8e1175bSopenharmony_ci        default:
605a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
606a8e1175bSopenharmony_ci    }
607a8e1175bSopenharmony_ci#endif
608a8e1175bSopenharmony_ci}
609a8e1175bSopenharmony_ci
610a8e1175bSopenharmony_cistatic int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
611a8e1175bSopenharmony_ci                                     size_t *olen, unsigned char *buf,
612a8e1175bSopenharmony_ci                                     size_t blen,
613a8e1175bSopenharmony_ci                                     int (*f_rng)(void *,
614a8e1175bSopenharmony_ci                                                  unsigned char *,
615a8e1175bSopenharmony_ci                                                  size_t),
616a8e1175bSopenharmony_ci                                     void *p_rng,
617a8e1175bSopenharmony_ci                                     int restart_enabled)
618a8e1175bSopenharmony_ci{
619a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
620a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
621a8e1175bSopenharmony_ci    mbedtls_ecp_restart_ctx *rs_ctx = NULL;
622a8e1175bSopenharmony_ci#endif
623a8e1175bSopenharmony_ci
624a8e1175bSopenharmony_ci    if (ctx == NULL || ctx->grp.pbits == 0) {
625a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
626a8e1175bSopenharmony_ci    }
627a8e1175bSopenharmony_ci
628a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
629a8e1175bSopenharmony_ci    if (restart_enabled) {
630a8e1175bSopenharmony_ci        rs_ctx = &ctx->rs;
631a8e1175bSopenharmony_ci    }
632a8e1175bSopenharmony_ci#else
633a8e1175bSopenharmony_ci    (void) restart_enabled;
634a8e1175bSopenharmony_ci#endif
635a8e1175bSopenharmony_ci
636a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
637a8e1175bSopenharmony_ci    if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
638a8e1175bSopenharmony_ci                                               &ctx->d, f_rng, p_rng,
639a8e1175bSopenharmony_ci                                               rs_ctx)) != 0) {
640a8e1175bSopenharmony_ci        return ret;
641a8e1175bSopenharmony_ci    }
642a8e1175bSopenharmony_ci#else
643a8e1175bSopenharmony_ci    if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
644a8e1175bSopenharmony_ci                                           &ctx->d, f_rng, p_rng)) != 0) {
645a8e1175bSopenharmony_ci        return ret;
646a8e1175bSopenharmony_ci    }
647a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECP_RESTARTABLE */
648a8e1175bSopenharmony_ci
649a8e1175bSopenharmony_ci    if (mbedtls_mpi_size(&ctx->z) > blen) {
650a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651a8e1175bSopenharmony_ci    }
652a8e1175bSopenharmony_ci
653a8e1175bSopenharmony_ci    *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
654a8e1175bSopenharmony_ci
655a8e1175bSopenharmony_ci    if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
656a8e1175bSopenharmony_ci        return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
657a8e1175bSopenharmony_ci    }
658a8e1175bSopenharmony_ci
659a8e1175bSopenharmony_ci    return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
660a8e1175bSopenharmony_ci}
661a8e1175bSopenharmony_ci
662a8e1175bSopenharmony_ci/*
663a8e1175bSopenharmony_ci * Derive and export the shared secret
664a8e1175bSopenharmony_ci */
665a8e1175bSopenharmony_ciint mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
666a8e1175bSopenharmony_ci                             unsigned char *buf, size_t blen,
667a8e1175bSopenharmony_ci                             int (*f_rng)(void *, unsigned char *, size_t),
668a8e1175bSopenharmony_ci                             void *p_rng)
669a8e1175bSopenharmony_ci{
670a8e1175bSopenharmony_ci    int restart_enabled = 0;
671a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECP_RESTARTABLE)
672a8e1175bSopenharmony_ci    restart_enabled = ctx->restart_enabled;
673a8e1175bSopenharmony_ci#endif
674a8e1175bSopenharmony_ci
675a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
676a8e1175bSopenharmony_ci    return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
677a8e1175bSopenharmony_ci                                     restart_enabled);
678a8e1175bSopenharmony_ci#else
679a8e1175bSopenharmony_ci    switch (ctx->var) {
680a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
681a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_EVEREST:
682a8e1175bSopenharmony_ci            return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
683a8e1175bSopenharmony_ci                                               buf, blen, f_rng, p_rng);
684a8e1175bSopenharmony_ci#endif
685a8e1175bSopenharmony_ci        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
686a8e1175bSopenharmony_ci            return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
687a8e1175bSopenharmony_ci                                             blen, f_rng, p_rng,
688a8e1175bSopenharmony_ci                                             restart_enabled);
689a8e1175bSopenharmony_ci        default:
690a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
691a8e1175bSopenharmony_ci    }
692a8e1175bSopenharmony_ci#endif
693a8e1175bSopenharmony_ci}
694a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECDH_C */
695