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