2 * Elliptic curve Diffie-Hellman
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
23 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
29 #if defined(MBEDTLS_ECDH_C)
31 #include "mbedtls/ecdh.h"
32 #include "mbedtls/platform_util.h"
33 #include "mbedtls/error.h"
37 /* Parameter validation macros based on platform_util.h */
38 #define ECDH_VALIDATE_RET( cond ) \
39 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
40 #define ECDH_VALIDATE( cond ) \
41 MBEDTLS_INTERNAL_VALIDATE( cond )
43 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
44 typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed
;
47 static mbedtls_ecp_group_id
mbedtls_ecdh_grp_id(
48 const mbedtls_ecdh_context
*ctx
) {
49 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
56 int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid
) {
57 /* At this time, all groups support ECDH. */
62 #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
64 * Generate public key (restartable version)
66 * Note: this internal function relies on its caller preserving the value of
67 * the output parameter 'd' across continuation calls. This would not be
68 * acceptable for a public function but is OK here as we control call sites.
70 static int ecdh_gen_public_restartable(mbedtls_ecp_group
*grp
,
71 mbedtls_mpi
*d
, mbedtls_ecp_point
*Q
,
72 int (*f_rng
)(void *, unsigned char *, size_t),
74 mbedtls_ecp_restart_ctx
*rs_ctx
) {
75 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
77 /* If multiplication is in progress, we already generated a privkey */
78 #if defined(MBEDTLS_ECP_RESTARTABLE)
79 if (rs_ctx
== NULL
|| rs_ctx
->rsm
== NULL
)
81 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp
, d
, f_rng
, p_rng
));
83 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp
, Q
, d
, &grp
->G
,
84 f_rng
, p_rng
, rs_ctx
));
93 int mbedtls_ecdh_gen_public(mbedtls_ecp_group
*grp
, mbedtls_mpi
*d
, mbedtls_ecp_point
*Q
,
94 int (*f_rng
)(void *, unsigned char *, size_t),
96 ECDH_VALIDATE_RET(grp
!= NULL
);
97 ECDH_VALIDATE_RET(d
!= NULL
);
98 ECDH_VALIDATE_RET(Q
!= NULL
);
99 ECDH_VALIDATE_RET(f_rng
!= NULL
);
100 return (ecdh_gen_public_restartable(grp
, d
, Q
, f_rng
, p_rng
, NULL
));
102 #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
104 #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
106 * Compute shared secret (SEC1 3.3.1)
108 static int ecdh_compute_shared_restartable(mbedtls_ecp_group
*grp
,
110 const mbedtls_ecp_point
*Q
, const mbedtls_mpi
*d
,
111 int (*f_rng
)(void *, unsigned char *, size_t),
113 mbedtls_ecp_restart_ctx
*rs_ctx
) {
114 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
117 mbedtls_ecp_point_init(&P
);
119 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp
, &P
, d
, Q
,
120 f_rng
, p_rng
, rs_ctx
));
122 if (mbedtls_ecp_is_zero(&P
)) {
123 ret
= MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
127 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z
, &P
.X
));
130 mbedtls_ecp_point_free(&P
);
136 * Compute shared secret (SEC1 3.3.1)
138 int mbedtls_ecdh_compute_shared(mbedtls_ecp_group
*grp
, mbedtls_mpi
*z
,
139 const mbedtls_ecp_point
*Q
, const mbedtls_mpi
*d
,
140 int (*f_rng
)(void *, unsigned char *, size_t),
142 ECDH_VALIDATE_RET(grp
!= NULL
);
143 ECDH_VALIDATE_RET(Q
!= NULL
);
144 ECDH_VALIDATE_RET(d
!= NULL
);
145 ECDH_VALIDATE_RET(z
!= NULL
);
146 return (ecdh_compute_shared_restartable(grp
, z
, Q
, d
,
147 f_rng
, p_rng
, NULL
));
149 #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
151 static void ecdh_init_internal(mbedtls_ecdh_context_mbed
*ctx
) {
152 mbedtls_ecp_group_init(&ctx
->grp
);
153 mbedtls_mpi_init(&ctx
->d
);
154 mbedtls_ecp_point_init(&ctx
->Q
);
155 mbedtls_ecp_point_init(&ctx
->Qp
);
156 mbedtls_mpi_init(&ctx
->z
);
158 #if defined(MBEDTLS_ECP_RESTARTABLE)
159 mbedtls_ecp_restart_init(&ctx
->rs
);
166 void mbedtls_ecdh_init(mbedtls_ecdh_context
*ctx
) {
167 ECDH_VALIDATE(ctx
!= NULL
);
169 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
170 ecdh_init_internal(ctx
);
171 mbedtls_ecp_point_init(&ctx
->Vi
);
172 mbedtls_ecp_point_init(&ctx
->Vf
);
173 mbedtls_mpi_init(&ctx
->_d
);
175 memset(ctx
, 0, sizeof(mbedtls_ecdh_context
));
177 ctx
->var
= MBEDTLS_ECDH_VARIANT_NONE
;
179 ctx
->point_format
= MBEDTLS_ECP_PF_UNCOMPRESSED
;
180 #if defined(MBEDTLS_ECP_RESTARTABLE)
181 ctx
->restart_enabled
= 0;
185 static int ecdh_setup_internal(mbedtls_ecdh_context_mbed
*ctx
,
186 mbedtls_ecp_group_id grp_id
) {
187 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
189 ret
= mbedtls_ecp_group_load(&ctx
->grp
, grp_id
);
191 return (MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
);
200 int mbedtls_ecdh_setup(mbedtls_ecdh_context
*ctx
, mbedtls_ecp_group_id grp_id
) {
201 ECDH_VALIDATE_RET(ctx
!= NULL
);
203 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
204 return (ecdh_setup_internal(ctx
, grp_id
));
207 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
208 case MBEDTLS_ECP_DP_CURVE25519
:
209 ctx
->point_format
= MBEDTLS_ECP_PF_COMPRESSED
;
210 ctx
->var
= MBEDTLS_ECDH_VARIANT_EVEREST
;
211 ctx
->grp_id
= grp_id
;
212 return (mbedtls_everest_setup(&ctx
->ctx
.everest_ecdh
, grp_id
));
215 ctx
->point_format
= MBEDTLS_ECP_PF_UNCOMPRESSED
;
216 ctx
->var
= MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0
;
217 ctx
->grp_id
= grp_id
;
218 ecdh_init_internal(&ctx
->ctx
.mbed_ecdh
);
219 return (ecdh_setup_internal(&ctx
->ctx
.mbed_ecdh
, grp_id
));
224 static void ecdh_free_internal(mbedtls_ecdh_context_mbed
*ctx
) {
225 mbedtls_ecp_group_free(&ctx
->grp
);
226 mbedtls_mpi_free(&ctx
->d
);
227 mbedtls_ecp_point_free(&ctx
->Q
);
228 mbedtls_ecp_point_free(&ctx
->Qp
);
229 mbedtls_mpi_free(&ctx
->z
);
231 #if defined(MBEDTLS_ECP_RESTARTABLE)
232 mbedtls_ecp_restart_free(&ctx
->rs
);
236 #if defined(MBEDTLS_ECP_RESTARTABLE)
238 * Enable restartable operations for context
240 void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context
*ctx
) {
241 ECDH_VALIDATE(ctx
!= NULL
);
243 ctx
->restart_enabled
= 1;
250 void mbedtls_ecdh_free(mbedtls_ecdh_context
*ctx
) {
254 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
255 mbedtls_ecp_point_free(&ctx
->Vi
);
256 mbedtls_ecp_point_free(&ctx
->Vf
);
257 mbedtls_mpi_free(&ctx
->_d
);
258 ecdh_free_internal(ctx
);
261 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
262 case MBEDTLS_ECDH_VARIANT_EVEREST
:
263 mbedtls_everest_free(&ctx
->ctx
.everest_ecdh
);
266 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0
:
267 ecdh_free_internal(&ctx
->ctx
.mbed_ecdh
);
273 ctx
->point_format
= MBEDTLS_ECP_PF_UNCOMPRESSED
;
274 ctx
->var
= MBEDTLS_ECDH_VARIANT_NONE
;
275 ctx
->grp_id
= MBEDTLS_ECP_DP_NONE
;
279 static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed
*ctx
,
280 size_t *olen
, int point_format
,
281 unsigned char *buf
, size_t blen
,
286 int restart_enabled
) {
287 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
288 size_t grp_len
, pt_len
;
289 #if defined(MBEDTLS_ECP_RESTARTABLE)
290 mbedtls_ecp_restart_ctx
*rs_ctx
= NULL
;
293 if (ctx
->grp
.pbits
== 0)
294 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
296 #if defined(MBEDTLS_ECP_RESTARTABLE)
300 (void) restart_enabled
;
304 #if defined(MBEDTLS_ECP_RESTARTABLE)
305 if ((ret
= ecdh_gen_public_restartable(&ctx
->grp
, &ctx
->d
, &ctx
->Q
,
306 f_rng
, p_rng
, rs_ctx
)) != 0)
309 if ((ret
= mbedtls_ecdh_gen_public(&ctx
->grp
, &ctx
->d
, &ctx
->Q
,
312 #endif /* MBEDTLS_ECP_RESTARTABLE */
314 if ((ret
= mbedtls_ecp_tls_write_group(&ctx
->grp
, &grp_len
, buf
,
321 if ((ret
= mbedtls_ecp_tls_write_point(&ctx
->grp
, &ctx
->Q
, point_format
,
322 &pt_len
, buf
, blen
)) != 0)
325 *olen
= grp_len
+ pt_len
;
330 * Setup and write the ServerKeyExchange parameters (RFC 4492)
332 * ECParameters curve_params;
334 * } ServerECDHParams;
336 int mbedtls_ecdh_make_params(mbedtls_ecdh_context
*ctx
, size_t *olen
,
337 unsigned char *buf
, size_t blen
,
338 int (*f_rng
)(void *, unsigned char *, size_t),
340 int restart_enabled
= 0;
341 ECDH_VALIDATE_RET(ctx
!= NULL
);
342 ECDH_VALIDATE_RET(olen
!= NULL
);
343 ECDH_VALIDATE_RET(buf
!= NULL
);
344 ECDH_VALIDATE_RET(f_rng
!= NULL
);
346 #if defined(MBEDTLS_ECP_RESTARTABLE)
347 restart_enabled
= ctx
->restart_enabled
;
349 (void) restart_enabled
;
352 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
353 return (ecdh_make_params_internal(ctx
, olen
, ctx
->point_format
, buf
, blen
,
354 f_rng
, p_rng
, restart_enabled
));
357 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
358 case MBEDTLS_ECDH_VARIANT_EVEREST
:
359 return (mbedtls_everest_make_params(&ctx
->ctx
.everest_ecdh
, olen
,
360 buf
, blen
, f_rng
, p_rng
));
362 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0
:
363 return (ecdh_make_params_internal(&ctx
->ctx
.mbed_ecdh
, olen
,
364 ctx
->point_format
, buf
, blen
,
368 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
373 static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed
*ctx
,
374 const unsigned char **buf
,
375 const unsigned char *end
) {
376 return (mbedtls_ecp_tls_read_point(&ctx
->grp
, &ctx
->Qp
, buf
,
381 * Read the ServerKeyExhange parameters (RFC 4492)
383 * ECParameters curve_params;
385 * } ServerECDHParams;
387 int mbedtls_ecdh_read_params(mbedtls_ecdh_context
*ctx
,
388 const unsigned char **buf
,
389 const unsigned char *end
) {
390 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
391 mbedtls_ecp_group_id grp_id
;
392 ECDH_VALIDATE_RET(ctx
!= NULL
);
393 ECDH_VALIDATE_RET(buf
!= NULL
);
394 ECDH_VALIDATE_RET(*buf
!= NULL
);
395 ECDH_VALIDATE_RET(end
!= NULL
);
397 if ((ret
= mbedtls_ecp_tls_read_group_id(&grp_id
, buf
, end
- *buf
))
401 if ((ret
= mbedtls_ecdh_setup(ctx
, grp_id
)) != 0)
404 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
405 return (ecdh_read_params_internal(ctx
, buf
, end
));
408 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
409 case MBEDTLS_ECDH_VARIANT_EVEREST
:
410 return (mbedtls_everest_read_params(&ctx
->ctx
.everest_ecdh
,
413 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0
:
414 return (ecdh_read_params_internal(&ctx
->ctx
.mbed_ecdh
,
417 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
422 static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed
*ctx
,
423 const mbedtls_ecp_keypair
*key
,
424 mbedtls_ecdh_side side
) {
425 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
427 /* If it's not our key, just import the public part as Qp */
428 if (side
== MBEDTLS_ECDH_THEIRS
)
429 return (mbedtls_ecp_copy(&ctx
->Qp
, &key
->Q
));
431 /* Our key: import public (as Q) and private parts */
432 if (side
!= MBEDTLS_ECDH_OURS
)
433 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
435 if ((ret
= mbedtls_ecp_copy(&ctx
->Q
, &key
->Q
)) != 0 ||
436 (ret
= mbedtls_mpi_copy(&ctx
->d
, &key
->d
)) != 0)
443 * Get parameters from a keypair
445 int mbedtls_ecdh_get_params(mbedtls_ecdh_context
*ctx
,
446 const mbedtls_ecp_keypair
*key
,
447 mbedtls_ecdh_side side
) {
448 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
449 ECDH_VALIDATE_RET(ctx
!= NULL
);
450 ECDH_VALIDATE_RET(key
!= NULL
);
451 ECDH_VALIDATE_RET(side
== MBEDTLS_ECDH_OURS
||
452 side
== MBEDTLS_ECDH_THEIRS
);
454 if (mbedtls_ecdh_grp_id(ctx
) == MBEDTLS_ECP_DP_NONE
) {
455 /* This is the first call to get_params(). Set up the context
456 * for use with the group. */
457 if ((ret
= mbedtls_ecdh_setup(ctx
, key
->grp
.id
)) != 0)
460 /* This is not the first call to get_params(). Check that the
461 * current key's group is the same as the context's, which was set
462 * from the first key's group. */
463 if (mbedtls_ecdh_grp_id(ctx
) != key
->grp
.id
)
464 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
467 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
468 return (ecdh_get_params_internal(ctx
, key
, side
));
471 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
472 case MBEDTLS_ECDH_VARIANT_EVEREST
: {
473 mbedtls_everest_ecdh_side s
= side
== MBEDTLS_ECDH_OURS
?
474 MBEDTLS_EVEREST_ECDH_OURS
:
475 MBEDTLS_EVEREST_ECDH_THEIRS
;
476 return (mbedtls_everest_get_params(&ctx
->ctx
.everest_ecdh
,
480 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0
:
481 return (ecdh_get_params_internal(&ctx
->ctx
.mbed_ecdh
,
484 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
489 static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed
*ctx
,
490 size_t *olen
, int point_format
,
491 unsigned char *buf
, size_t blen
,
496 int restart_enabled
) {
497 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
498 #if defined(MBEDTLS_ECP_RESTARTABLE)
499 mbedtls_ecp_restart_ctx
*rs_ctx
= NULL
;
502 if (ctx
->grp
.pbits
== 0)
503 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
505 #if defined(MBEDTLS_ECP_RESTARTABLE)
509 (void) restart_enabled
;
512 #if defined(MBEDTLS_ECP_RESTARTABLE)
513 if ((ret
= ecdh_gen_public_restartable(&ctx
->grp
, &ctx
->d
, &ctx
->Q
,
514 f_rng
, p_rng
, rs_ctx
)) != 0)
517 if ((ret
= mbedtls_ecdh_gen_public(&ctx
->grp
, &ctx
->d
, &ctx
->Q
,
520 #endif /* MBEDTLS_ECP_RESTARTABLE */
522 return mbedtls_ecp_tls_write_point(&ctx
->grp
, &ctx
->Q
, point_format
, olen
,
527 * Setup and export the client public value
529 int mbedtls_ecdh_make_public(mbedtls_ecdh_context
*ctx
, size_t *olen
,
530 unsigned char *buf
, size_t blen
,
531 int (*f_rng
)(void *, unsigned char *, size_t),
533 int restart_enabled
= 0;
534 ECDH_VALIDATE_RET(ctx
!= NULL
);
535 ECDH_VALIDATE_RET(olen
!= NULL
);
536 ECDH_VALIDATE_RET(buf
!= NULL
);
537 ECDH_VALIDATE_RET(f_rng
!= NULL
);
539 #if defined(MBEDTLS_ECP_RESTARTABLE)
540 restart_enabled
= ctx
->restart_enabled
;
543 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
544 return (ecdh_make_public_internal(ctx
, olen
, ctx
->point_format
, buf
, blen
,
545 f_rng
, p_rng
, restart_enabled
));
548 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
549 case MBEDTLS_ECDH_VARIANT_EVEREST
:
550 return (mbedtls_everest_make_public(&ctx
->ctx
.everest_ecdh
, olen
,
551 buf
, blen
, f_rng
, p_rng
));
553 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0
:
554 return (ecdh_make_public_internal(&ctx
->ctx
.mbed_ecdh
, olen
,
555 ctx
->point_format
, buf
, blen
,
559 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
564 static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed
*ctx
,
565 const unsigned char *buf
, size_t blen
) {
566 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
567 const unsigned char *p
= buf
;
569 if ((ret
= mbedtls_ecp_tls_read_point(&ctx
->grp
, &ctx
->Qp
, &p
,
573 if ((size_t)(p
- buf
) != blen
)
574 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
580 * Parse and import the client's public value
582 int mbedtls_ecdh_read_public(mbedtls_ecdh_context
*ctx
,
583 const unsigned char *buf
, size_t blen
) {
584 ECDH_VALIDATE_RET(ctx
!= NULL
);
585 ECDH_VALIDATE_RET(buf
!= NULL
);
587 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
588 return (ecdh_read_public_internal(ctx
, buf
, blen
));
591 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
592 case MBEDTLS_ECDH_VARIANT_EVEREST
:
593 return (mbedtls_everest_read_public(&ctx
->ctx
.everest_ecdh
,
596 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0
:
597 return (ecdh_read_public_internal(&ctx
->ctx
.mbed_ecdh
,
600 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
605 static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed
*ctx
,
606 size_t *olen
, unsigned char *buf
,
612 int restart_enabled
) {
613 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
614 #if defined(MBEDTLS_ECP_RESTARTABLE)
615 mbedtls_ecp_restart_ctx
*rs_ctx
= NULL
;
618 if (ctx
== NULL
|| ctx
->grp
.pbits
== 0)
619 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
621 #if defined(MBEDTLS_ECP_RESTARTABLE)
625 (void) restart_enabled
;
628 #if defined(MBEDTLS_ECP_RESTARTABLE)
629 if ((ret
= ecdh_compute_shared_restartable(&ctx
->grp
, &ctx
->z
, &ctx
->Qp
,
630 &ctx
->d
, f_rng
, p_rng
,
635 if ((ret
= mbedtls_ecdh_compute_shared(&ctx
->grp
, &ctx
->z
, &ctx
->Qp
,
636 &ctx
->d
, f_rng
, p_rng
)) != 0) {
639 #endif /* MBEDTLS_ECP_RESTARTABLE */
641 if (mbedtls_mpi_size(&ctx
->z
) > blen
)
642 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
644 *olen
= ctx
->grp
.pbits
/ 8 + ((ctx
->grp
.pbits
% 8) != 0);
646 if (mbedtls_ecp_get_type(&ctx
->grp
) == MBEDTLS_ECP_TYPE_MONTGOMERY
)
647 return mbedtls_mpi_write_binary_le(&ctx
->z
, buf
, *olen
);
649 return mbedtls_mpi_write_binary(&ctx
->z
, buf
, *olen
);
653 * Derive and export the shared secret
655 int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context
*ctx
, size_t *olen
,
656 unsigned char *buf
, size_t blen
,
657 int (*f_rng
)(void *, unsigned char *, size_t),
659 int restart_enabled
= 0;
660 ECDH_VALIDATE_RET(ctx
!= NULL
);
661 ECDH_VALIDATE_RET(olen
!= NULL
);
662 ECDH_VALIDATE_RET(buf
!= NULL
);
664 #if defined(MBEDTLS_ECP_RESTARTABLE)
665 restart_enabled
= ctx
->restart_enabled
;
668 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
669 return (ecdh_calc_secret_internal(ctx
, olen
, buf
, blen
, f_rng
, p_rng
,
673 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
674 case MBEDTLS_ECDH_VARIANT_EVEREST
:
675 return (mbedtls_everest_calc_secret(&ctx
->ctx
.everest_ecdh
, olen
,
676 buf
, blen
, f_rng
, p_rng
));
678 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0
:
679 return (ecdh_calc_secret_internal(&ctx
->ctx
.mbed_ecdh
, olen
, buf
,
683 return (MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
688 #endif /* MBEDTLS_ECDH_C */