xref: /optee_os/lib/libmbedtls/mbedtls/library/ecdh.c (revision 039e02df2716a0ed886b56e1e07b7ac1d8597228)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  Elliptic curve Diffie-Hellman
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander 
20817466cbSJens Wiklander /*
21817466cbSJens Wiklander  * References:
22817466cbSJens Wiklander  *
23817466cbSJens Wiklander  * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
24817466cbSJens Wiklander  * RFC 4492
25817466cbSJens Wiklander  */
26817466cbSJens Wiklander 
277901324dSJerome Forissier #include "common.h"
28817466cbSJens Wiklander 
29817466cbSJens Wiklander #if defined(MBEDTLS_ECDH_C)
30817466cbSJens Wiklander 
31817466cbSJens Wiklander #include "mbedtls/ecdh.h"
323d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
3311fa71b9SJerome Forissier #include "mbedtls/error.h"
34817466cbSJens Wiklander 
35817466cbSJens Wiklander #include <string.h>
36817466cbSJens Wiklander 
373d3b0591SJens Wiklander /* Parameter validation macros based on platform_util.h */
383d3b0591SJens Wiklander #define ECDH_VALIDATE_RET( cond )    \
393d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
403d3b0591SJens Wiklander #define ECDH_VALIDATE( cond )        \
413d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE( cond )
423d3b0591SJens Wiklander 
433d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
443d3b0591SJens Wiklander typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
453d3b0591SJens Wiklander #endif
463d3b0591SJens Wiklander 
475b25c76aSJerome Forissier static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
485b25c76aSJerome Forissier     const mbedtls_ecdh_context *ctx )
495b25c76aSJerome Forissier {
505b25c76aSJerome Forissier #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
515b25c76aSJerome Forissier     return( ctx->grp.id );
525b25c76aSJerome Forissier #else
535b25c76aSJerome Forissier     return( ctx->grp_id );
545b25c76aSJerome Forissier #endif
555b25c76aSJerome Forissier }
565b25c76aSJerome Forissier 
5711fa71b9SJerome Forissier int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
5811fa71b9SJerome Forissier {
5911fa71b9SJerome Forissier     /* At this time, all groups support ECDH. */
6011fa71b9SJerome Forissier     (void) gid;
6111fa71b9SJerome Forissier     return( 1 );
6211fa71b9SJerome Forissier }
6311fa71b9SJerome Forissier 
643d3b0591SJens Wiklander #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
65817466cbSJens Wiklander /*
663d3b0591SJens Wiklander  * Generate public key (restartable version)
673d3b0591SJens Wiklander  *
683d3b0591SJens Wiklander  * Note: this internal function relies on its caller preserving the value of
693d3b0591SJens Wiklander  * the output parameter 'd' across continuation calls. This would not be
703d3b0591SJens Wiklander  * acceptable for a public function but is OK here as we control call sites.
713d3b0591SJens Wiklander  */
723d3b0591SJens Wiklander static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
733d3b0591SJens Wiklander                     mbedtls_mpi *d, mbedtls_ecp_point *Q,
743d3b0591SJens Wiklander                     int (*f_rng)(void *, unsigned char *, size_t),
753d3b0591SJens Wiklander                     void *p_rng,
763d3b0591SJens Wiklander                     mbedtls_ecp_restart_ctx *rs_ctx )
773d3b0591SJens Wiklander {
7811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
793d3b0591SJens Wiklander 
803d3b0591SJens Wiklander     /* If multiplication is in progress, we already generated a privkey */
813d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
823d3b0591SJens Wiklander     if( rs_ctx == NULL || rs_ctx->rsm == NULL )
833d3b0591SJens Wiklander #endif
843d3b0591SJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
853d3b0591SJens Wiklander 
863d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
873d3b0591SJens Wiklander                                                   f_rng, p_rng, rs_ctx ) );
883d3b0591SJens Wiklander 
893d3b0591SJens Wiklander cleanup:
903d3b0591SJens Wiklander     return( ret );
913d3b0591SJens Wiklander }
923d3b0591SJens Wiklander 
933d3b0591SJens Wiklander /*
943d3b0591SJens Wiklander  * Generate public key
95817466cbSJens Wiklander  */
96817466cbSJens Wiklander int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
97817466cbSJens Wiklander                      int (*f_rng)(void *, unsigned char *, size_t),
98817466cbSJens Wiklander                      void *p_rng )
99817466cbSJens Wiklander {
1003d3b0591SJens Wiklander     ECDH_VALIDATE_RET( grp != NULL );
1013d3b0591SJens Wiklander     ECDH_VALIDATE_RET( d != NULL );
1023d3b0591SJens Wiklander     ECDH_VALIDATE_RET( Q != NULL );
1033d3b0591SJens Wiklander     ECDH_VALIDATE_RET( f_rng != NULL );
1043d3b0591SJens Wiklander     return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
105817466cbSJens Wiklander }
1063d3b0591SJens Wiklander #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
107817466cbSJens Wiklander 
1083d3b0591SJens Wiklander #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
109817466cbSJens Wiklander /*
110817466cbSJens Wiklander  * Compute shared secret (SEC1 3.3.1)
111817466cbSJens Wiklander  */
1123d3b0591SJens Wiklander static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
1133d3b0591SJens Wiklander                          mbedtls_mpi *z,
114817466cbSJens Wiklander                          const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
115817466cbSJens Wiklander                          int (*f_rng)(void *, unsigned char *, size_t),
1163d3b0591SJens Wiklander                          void *p_rng,
1173d3b0591SJens Wiklander                          mbedtls_ecp_restart_ctx *rs_ctx )
118817466cbSJens Wiklander {
11911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
120817466cbSJens Wiklander     mbedtls_ecp_point P;
121817466cbSJens Wiklander 
122817466cbSJens Wiklander     mbedtls_ecp_point_init( &P );
123817466cbSJens Wiklander 
1243d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
1253d3b0591SJens Wiklander                                                   f_rng, p_rng, rs_ctx ) );
126817466cbSJens Wiklander 
127817466cbSJens Wiklander     if( mbedtls_ecp_is_zero( &P ) )
128817466cbSJens Wiklander     {
129817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
130817466cbSJens Wiklander         goto cleanup;
131817466cbSJens Wiklander     }
132817466cbSJens Wiklander 
133817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
134817466cbSJens Wiklander 
135817466cbSJens Wiklander cleanup:
136817466cbSJens Wiklander     mbedtls_ecp_point_free( &P );
137817466cbSJens Wiklander 
138817466cbSJens Wiklander     return( ret );
139817466cbSJens Wiklander }
140817466cbSJens Wiklander 
141817466cbSJens Wiklander /*
1423d3b0591SJens Wiklander  * Compute shared secret (SEC1 3.3.1)
1433d3b0591SJens Wiklander  */
1443d3b0591SJens Wiklander int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
1453d3b0591SJens Wiklander                          const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
1463d3b0591SJens Wiklander                          int (*f_rng)(void *, unsigned char *, size_t),
1473d3b0591SJens Wiklander                          void *p_rng )
1483d3b0591SJens Wiklander {
1493d3b0591SJens Wiklander     ECDH_VALIDATE_RET( grp != NULL );
1503d3b0591SJens Wiklander     ECDH_VALIDATE_RET( Q != NULL );
1513d3b0591SJens Wiklander     ECDH_VALIDATE_RET( d != NULL );
1523d3b0591SJens Wiklander     ECDH_VALIDATE_RET( z != NULL );
1533d3b0591SJens Wiklander     return( ecdh_compute_shared_restartable( grp, z, Q, d,
1543d3b0591SJens Wiklander                                              f_rng, p_rng, NULL ) );
1553d3b0591SJens Wiklander }
1563d3b0591SJens Wiklander #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
1573d3b0591SJens Wiklander 
1583d3b0591SJens Wiklander static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
1593d3b0591SJens Wiklander {
1603d3b0591SJens Wiklander     mbedtls_ecp_group_init( &ctx->grp );
1613d3b0591SJens Wiklander     mbedtls_mpi_init( &ctx->d  );
1623d3b0591SJens Wiklander     mbedtls_ecp_point_init( &ctx->Q   );
1633d3b0591SJens Wiklander     mbedtls_ecp_point_init( &ctx->Qp  );
1643d3b0591SJens Wiklander     mbedtls_mpi_init( &ctx->z  );
1653d3b0591SJens Wiklander 
1663d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
1673d3b0591SJens Wiklander     mbedtls_ecp_restart_init( &ctx->rs );
1683d3b0591SJens Wiklander #endif
1693d3b0591SJens Wiklander }
1703d3b0591SJens Wiklander 
1713d3b0591SJens Wiklander /*
172817466cbSJens Wiklander  * Initialize context
173817466cbSJens Wiklander  */
174817466cbSJens Wiklander void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
175817466cbSJens Wiklander {
1763d3b0591SJens Wiklander     ECDH_VALIDATE( ctx != NULL );
1773d3b0591SJens Wiklander 
1783d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
1793d3b0591SJens Wiklander     ecdh_init_internal( ctx );
1803d3b0591SJens Wiklander     mbedtls_ecp_point_init( &ctx->Vi  );
1813d3b0591SJens Wiklander     mbedtls_ecp_point_init( &ctx->Vf  );
1823d3b0591SJens Wiklander     mbedtls_mpi_init( &ctx->_d );
1833d3b0591SJens Wiklander #else
184817466cbSJens Wiklander     memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
1853d3b0591SJens Wiklander 
1863d3b0591SJens Wiklander     ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
1873d3b0591SJens Wiklander #endif
1883d3b0591SJens Wiklander     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
1893d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
1903d3b0591SJens Wiklander     ctx->restart_enabled = 0;
1913d3b0591SJens Wiklander #endif
192817466cbSJens Wiklander }
193817466cbSJens Wiklander 
1943d3b0591SJens Wiklander static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
1953d3b0591SJens Wiklander                                 mbedtls_ecp_group_id grp_id )
1963d3b0591SJens Wiklander {
19711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1983d3b0591SJens Wiklander 
1993d3b0591SJens Wiklander     ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
2003d3b0591SJens Wiklander     if( ret != 0 )
2013d3b0591SJens Wiklander     {
2023d3b0591SJens Wiklander         return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
2033d3b0591SJens Wiklander     }
2043d3b0591SJens Wiklander 
2053d3b0591SJens Wiklander     return( 0 );
2063d3b0591SJens Wiklander }
2073d3b0591SJens Wiklander 
2083d3b0591SJens Wiklander /*
2093d3b0591SJens Wiklander  * Setup context
2103d3b0591SJens Wiklander  */
2113d3b0591SJens Wiklander int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
2123d3b0591SJens Wiklander {
2133d3b0591SJens Wiklander     ECDH_VALIDATE_RET( ctx != NULL );
2143d3b0591SJens Wiklander 
2153d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
2163d3b0591SJens Wiklander     return( ecdh_setup_internal( ctx, grp_id ) );
2173d3b0591SJens Wiklander #else
2183d3b0591SJens Wiklander     switch( grp_id )
2193d3b0591SJens Wiklander     {
22011fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
22111fa71b9SJerome Forissier         case MBEDTLS_ECP_DP_CURVE25519:
22211fa71b9SJerome Forissier             ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
22311fa71b9SJerome Forissier             ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
22411fa71b9SJerome Forissier             ctx->grp_id = grp_id;
22511fa71b9SJerome Forissier             return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) );
22611fa71b9SJerome Forissier #endif
2273d3b0591SJens Wiklander         default:
2283d3b0591SJens Wiklander             ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
2293d3b0591SJens Wiklander             ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
2303d3b0591SJens Wiklander             ctx->grp_id = grp_id;
2313d3b0591SJens Wiklander             ecdh_init_internal( &ctx->ctx.mbed_ecdh );
2323d3b0591SJens Wiklander             return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
2333d3b0591SJens Wiklander     }
2343d3b0591SJens Wiklander #endif
2353d3b0591SJens Wiklander }
2363d3b0591SJens Wiklander 
2373d3b0591SJens Wiklander static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
2383d3b0591SJens Wiklander {
2393d3b0591SJens Wiklander     mbedtls_ecp_group_free( &ctx->grp );
2403d3b0591SJens Wiklander     mbedtls_mpi_free( &ctx->d  );
2413d3b0591SJens Wiklander     mbedtls_ecp_point_free( &ctx->Q   );
2423d3b0591SJens Wiklander     mbedtls_ecp_point_free( &ctx->Qp  );
2433d3b0591SJens Wiklander     mbedtls_mpi_free( &ctx->z  );
2443d3b0591SJens Wiklander 
2453d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
2463d3b0591SJens Wiklander     mbedtls_ecp_restart_free( &ctx->rs );
2473d3b0591SJens Wiklander #endif
2483d3b0591SJens Wiklander }
2493d3b0591SJens Wiklander 
2503d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
2513d3b0591SJens Wiklander /*
2523d3b0591SJens Wiklander  * Enable restartable operations for context
2533d3b0591SJens Wiklander  */
2543d3b0591SJens Wiklander void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
2553d3b0591SJens Wiklander {
2563d3b0591SJens Wiklander     ECDH_VALIDATE( ctx != NULL );
2573d3b0591SJens Wiklander 
2583d3b0591SJens Wiklander     ctx->restart_enabled = 1;
2593d3b0591SJens Wiklander }
2603d3b0591SJens Wiklander #endif
2613d3b0591SJens Wiklander 
262817466cbSJens Wiklander /*
263817466cbSJens Wiklander  * Free context
264817466cbSJens Wiklander  */
265817466cbSJens Wiklander void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
266817466cbSJens Wiklander {
267817466cbSJens Wiklander     if( ctx == NULL )
268817466cbSJens Wiklander         return;
269817466cbSJens Wiklander 
2703d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
271817466cbSJens Wiklander     mbedtls_ecp_point_free( &ctx->Vi );
272817466cbSJens Wiklander     mbedtls_ecp_point_free( &ctx->Vf );
273817466cbSJens Wiklander     mbedtls_mpi_free( &ctx->_d );
2743d3b0591SJens Wiklander     ecdh_free_internal( ctx );
2753d3b0591SJens Wiklander #else
2763d3b0591SJens Wiklander     switch( ctx->var )
2773d3b0591SJens Wiklander     {
27811fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
27911fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
28011fa71b9SJerome Forissier             mbedtls_everest_free( &ctx->ctx.everest_ecdh );
28111fa71b9SJerome Forissier             break;
28211fa71b9SJerome Forissier #endif
2833d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
2843d3b0591SJens Wiklander             ecdh_free_internal( &ctx->ctx.mbed_ecdh );
2853d3b0591SJens Wiklander             break;
2863d3b0591SJens Wiklander         default:
2873d3b0591SJens Wiklander             break;
2883d3b0591SJens Wiklander     }
2893d3b0591SJens Wiklander 
2903d3b0591SJens Wiklander     ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
2913d3b0591SJens Wiklander     ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
2923d3b0591SJens Wiklander     ctx->grp_id = MBEDTLS_ECP_DP_NONE;
2933d3b0591SJens Wiklander #endif
2943d3b0591SJens Wiklander }
2953d3b0591SJens Wiklander 
2963d3b0591SJens Wiklander static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
2973d3b0591SJens Wiklander                                       size_t *olen, int point_format,
2983d3b0591SJens Wiklander                                       unsigned char *buf, size_t blen,
2993d3b0591SJens Wiklander                                       int (*f_rng)(void *,
3003d3b0591SJens Wiklander                                                    unsigned char *,
3013d3b0591SJens Wiklander                                                    size_t),
3023d3b0591SJens Wiklander                                       void *p_rng,
3033d3b0591SJens Wiklander                                       int restart_enabled )
3043d3b0591SJens Wiklander {
30511fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
3063d3b0591SJens Wiklander     size_t grp_len, pt_len;
3073d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
3083d3b0591SJens Wiklander     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
3093d3b0591SJens Wiklander #endif
3103d3b0591SJens Wiklander 
3113d3b0591SJens Wiklander     if( ctx->grp.pbits == 0 )
3123d3b0591SJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
3133d3b0591SJens Wiklander 
3143d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
3153d3b0591SJens Wiklander     if( restart_enabled )
3163d3b0591SJens Wiklander         rs_ctx = &ctx->rs;
3173d3b0591SJens Wiklander #else
3183d3b0591SJens Wiklander     (void) restart_enabled;
3193d3b0591SJens Wiklander #endif
3203d3b0591SJens Wiklander 
3213d3b0591SJens Wiklander 
3223d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
3233d3b0591SJens Wiklander     if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
3243d3b0591SJens Wiklander                                              f_rng, p_rng, rs_ctx ) ) != 0 )
3253d3b0591SJens Wiklander         return( ret );
3263d3b0591SJens Wiklander #else
3273d3b0591SJens Wiklander     if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
3283d3b0591SJens Wiklander                                          f_rng, p_rng ) ) != 0 )
3293d3b0591SJens Wiklander         return( ret );
3303d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
3313d3b0591SJens Wiklander 
3323d3b0591SJens Wiklander     if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
3333d3b0591SJens Wiklander                                              blen ) ) != 0 )
3343d3b0591SJens Wiklander         return( ret );
3353d3b0591SJens Wiklander 
3363d3b0591SJens Wiklander     buf += grp_len;
3373d3b0591SJens Wiklander     blen -= grp_len;
3383d3b0591SJens Wiklander 
3393d3b0591SJens Wiklander     if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
3403d3b0591SJens Wiklander                                              &pt_len, buf, blen ) ) != 0 )
3413d3b0591SJens Wiklander         return( ret );
3423d3b0591SJens Wiklander 
3433d3b0591SJens Wiklander     *olen = grp_len + pt_len;
3443d3b0591SJens Wiklander     return( 0 );
345817466cbSJens Wiklander }
346817466cbSJens Wiklander 
347817466cbSJens Wiklander /*
34811fa71b9SJerome Forissier  * Setup and write the ServerKeyExchange parameters (RFC 4492)
349817466cbSJens Wiklander  *      struct {
350817466cbSJens Wiklander  *          ECParameters    curve_params;
351817466cbSJens Wiklander  *          ECPoint         public;
352817466cbSJens Wiklander  *      } ServerECDHParams;
353817466cbSJens Wiklander  */
354817466cbSJens Wiklander int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
355817466cbSJens Wiklander                               unsigned char *buf, size_t blen,
356817466cbSJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t),
357817466cbSJens Wiklander                               void *p_rng )
358817466cbSJens Wiklander {
3593d3b0591SJens Wiklander     int restart_enabled = 0;
3603d3b0591SJens Wiklander     ECDH_VALIDATE_RET( ctx != NULL );
3613d3b0591SJens Wiklander     ECDH_VALIDATE_RET( olen != NULL );
3623d3b0591SJens Wiklander     ECDH_VALIDATE_RET( buf != NULL );
3633d3b0591SJens Wiklander     ECDH_VALIDATE_RET( f_rng != NULL );
364817466cbSJens Wiklander 
3653d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
3663d3b0591SJens Wiklander     restart_enabled = ctx->restart_enabled;
3673d3b0591SJens Wiklander #else
3683d3b0591SJens Wiklander     (void) restart_enabled;
3693d3b0591SJens Wiklander #endif
370817466cbSJens Wiklander 
3713d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
3723d3b0591SJens Wiklander     return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
3733d3b0591SJens Wiklander                                        f_rng, p_rng, restart_enabled ) );
3743d3b0591SJens Wiklander #else
3753d3b0591SJens Wiklander     switch( ctx->var )
3763d3b0591SJens Wiklander     {
37711fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
37811fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
37911fa71b9SJerome Forissier             return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen,
38011fa71b9SJerome Forissier                                                  buf, blen, f_rng, p_rng ) );
38111fa71b9SJerome Forissier #endif
3823d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
3833d3b0591SJens Wiklander             return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
3843d3b0591SJens Wiklander                                                ctx->point_format, buf, blen,
3853d3b0591SJens Wiklander                                                f_rng, p_rng,
3863d3b0591SJens Wiklander                                                restart_enabled ) );
3873d3b0591SJens Wiklander         default:
3883d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
3893d3b0591SJens Wiklander     }
3903d3b0591SJens Wiklander #endif
3913d3b0591SJens Wiklander }
392817466cbSJens Wiklander 
3933d3b0591SJens Wiklander static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
3943d3b0591SJens Wiklander                                       const unsigned char **buf,
3953d3b0591SJens Wiklander                                       const unsigned char *end )
3963d3b0591SJens Wiklander {
3973d3b0591SJens Wiklander     return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
3983d3b0591SJens Wiklander                                         end - *buf ) );
399817466cbSJens Wiklander }
400817466cbSJens Wiklander 
401817466cbSJens Wiklander /*
402*039e02dfSJerome Forissier  * Read the ServerKeyExchange parameters (RFC 4492)
403817466cbSJens Wiklander  *      struct {
404817466cbSJens Wiklander  *          ECParameters    curve_params;
405817466cbSJens Wiklander  *          ECPoint         public;
406817466cbSJens Wiklander  *      } ServerECDHParams;
407817466cbSJens Wiklander  */
408817466cbSJens Wiklander int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
4093d3b0591SJens Wiklander                               const unsigned char **buf,
4103d3b0591SJens Wiklander                               const unsigned char *end )
411817466cbSJens Wiklander {
41211fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4133d3b0591SJens Wiklander     mbedtls_ecp_group_id grp_id;
4143d3b0591SJens Wiklander     ECDH_VALIDATE_RET( ctx != NULL );
4153d3b0591SJens Wiklander     ECDH_VALIDATE_RET( buf != NULL );
4163d3b0591SJens Wiklander     ECDH_VALIDATE_RET( *buf != NULL );
4173d3b0591SJens Wiklander     ECDH_VALIDATE_RET( end != NULL );
418817466cbSJens Wiklander 
4193d3b0591SJens Wiklander     if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
420817466cbSJens Wiklander             != 0 )
421817466cbSJens Wiklander         return( ret );
422817466cbSJens Wiklander 
4233d3b0591SJens Wiklander     if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
4243d3b0591SJens Wiklander         return( ret );
4253d3b0591SJens Wiklander 
4263d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
4273d3b0591SJens Wiklander     return( ecdh_read_params_internal( ctx, buf, end ) );
4283d3b0591SJens Wiklander #else
4293d3b0591SJens Wiklander     switch( ctx->var )
4303d3b0591SJens Wiklander     {
43111fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
43211fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
43311fa71b9SJerome Forissier             return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh,
43411fa71b9SJerome Forissier                                                  buf, end) );
43511fa71b9SJerome Forissier #endif
4363d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
4373d3b0591SJens Wiklander             return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
4383d3b0591SJens Wiklander                                                buf, end ) );
4393d3b0591SJens Wiklander         default:
4403d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
4413d3b0591SJens Wiklander     }
4423d3b0591SJens Wiklander #endif
443817466cbSJens Wiklander }
444817466cbSJens Wiklander 
4453d3b0591SJens Wiklander static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
4463d3b0591SJens Wiklander                                      const mbedtls_ecp_keypair *key,
447817466cbSJens Wiklander                                      mbedtls_ecdh_side side )
448817466cbSJens Wiklander {
44911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
450817466cbSJens Wiklander 
451817466cbSJens Wiklander     /* If it's not our key, just import the public part as Qp */
452817466cbSJens Wiklander     if( side == MBEDTLS_ECDH_THEIRS )
453817466cbSJens Wiklander         return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
454817466cbSJens Wiklander 
455817466cbSJens Wiklander     /* Our key: import public (as Q) and private parts */
456817466cbSJens Wiklander     if( side != MBEDTLS_ECDH_OURS )
457817466cbSJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
458817466cbSJens Wiklander 
459817466cbSJens Wiklander     if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
460817466cbSJens Wiklander         ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
461817466cbSJens Wiklander         return( ret );
462817466cbSJens Wiklander 
463817466cbSJens Wiklander     return( 0 );
464817466cbSJens Wiklander }
465817466cbSJens Wiklander 
466817466cbSJens Wiklander /*
4673d3b0591SJens Wiklander  * Get parameters from a keypair
4683d3b0591SJens Wiklander  */
4693d3b0591SJens Wiklander int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
4703d3b0591SJens Wiklander                              const mbedtls_ecp_keypair *key,
4713d3b0591SJens Wiklander                              mbedtls_ecdh_side side )
4723d3b0591SJens Wiklander {
47311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4743d3b0591SJens Wiklander     ECDH_VALIDATE_RET( ctx != NULL );
4753d3b0591SJens Wiklander     ECDH_VALIDATE_RET( key != NULL );
4763d3b0591SJens Wiklander     ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
4773d3b0591SJens Wiklander                        side == MBEDTLS_ECDH_THEIRS );
4783d3b0591SJens Wiklander 
4795b25c76aSJerome Forissier     if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
4805b25c76aSJerome Forissier     {
4815b25c76aSJerome Forissier         /* This is the first call to get_params(). Set up the context
4825b25c76aSJerome Forissier          * for use with the group. */
4833d3b0591SJens Wiklander         if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
4843d3b0591SJens Wiklander             return( ret );
4855b25c76aSJerome Forissier     }
4865b25c76aSJerome Forissier     else
4875b25c76aSJerome Forissier     {
4885b25c76aSJerome Forissier         /* This is not the first call to get_params(). Check that the
4895b25c76aSJerome Forissier          * current key's group is the same as the context's, which was set
4905b25c76aSJerome Forissier          * from the first key's group. */
4915b25c76aSJerome Forissier         if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id )
4925b25c76aSJerome Forissier             return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
4935b25c76aSJerome Forissier     }
4943d3b0591SJens Wiklander 
4953d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
4963d3b0591SJens Wiklander     return( ecdh_get_params_internal( ctx, key, side ) );
4973d3b0591SJens Wiklander #else
4983d3b0591SJens Wiklander     switch( ctx->var )
4993d3b0591SJens Wiklander     {
50011fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
50111fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
50211fa71b9SJerome Forissier         {
50311fa71b9SJerome Forissier             mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
50411fa71b9SJerome Forissier                                                    MBEDTLS_EVEREST_ECDH_OURS :
50511fa71b9SJerome Forissier                                                    MBEDTLS_EVEREST_ECDH_THEIRS;
50611fa71b9SJerome Forissier             return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh,
50711fa71b9SJerome Forissier                                                 key, s) );
50811fa71b9SJerome Forissier         }
50911fa71b9SJerome Forissier #endif
5103d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
5113d3b0591SJens Wiklander             return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
5123d3b0591SJens Wiklander                                               key, side ) );
5133d3b0591SJens Wiklander         default:
5143d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
5153d3b0591SJens Wiklander     }
5163d3b0591SJens Wiklander #endif
5173d3b0591SJens Wiklander }
5183d3b0591SJens Wiklander 
5193d3b0591SJens Wiklander static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
5203d3b0591SJens Wiklander                                       size_t *olen, int point_format,
5213d3b0591SJens Wiklander                                       unsigned char *buf, size_t blen,
5223d3b0591SJens Wiklander                                       int (*f_rng)(void *,
5233d3b0591SJens Wiklander                                                    unsigned char *,
5243d3b0591SJens Wiklander                                                    size_t),
5253d3b0591SJens Wiklander                                       void *p_rng,
5263d3b0591SJens Wiklander                                       int restart_enabled )
5273d3b0591SJens Wiklander {
52811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
5293d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
5303d3b0591SJens Wiklander     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
5313d3b0591SJens Wiklander #endif
5323d3b0591SJens Wiklander 
5333d3b0591SJens Wiklander     if( ctx->grp.pbits == 0 )
5343d3b0591SJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
5353d3b0591SJens Wiklander 
5363d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
5373d3b0591SJens Wiklander     if( restart_enabled )
5383d3b0591SJens Wiklander         rs_ctx = &ctx->rs;
5393d3b0591SJens Wiklander #else
5403d3b0591SJens Wiklander     (void) restart_enabled;
5413d3b0591SJens Wiklander #endif
5423d3b0591SJens Wiklander 
5433d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
5443d3b0591SJens Wiklander     if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
5453d3b0591SJens Wiklander                                              f_rng, p_rng, rs_ctx ) ) != 0 )
5463d3b0591SJens Wiklander         return( ret );
5473d3b0591SJens Wiklander #else
5483d3b0591SJens Wiklander     if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
5493d3b0591SJens Wiklander                                          f_rng, p_rng ) ) != 0 )
5503d3b0591SJens Wiklander         return( ret );
5513d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
5523d3b0591SJens Wiklander 
5533d3b0591SJens Wiklander     return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
5543d3b0591SJens Wiklander                                         buf, blen );
5553d3b0591SJens Wiklander }
5563d3b0591SJens Wiklander 
5573d3b0591SJens Wiklander /*
558817466cbSJens Wiklander  * Setup and export the client public value
559817466cbSJens Wiklander  */
560817466cbSJens Wiklander int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
561817466cbSJens Wiklander                               unsigned char *buf, size_t blen,
562817466cbSJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t),
563817466cbSJens Wiklander                               void *p_rng )
564817466cbSJens Wiklander {
5653d3b0591SJens Wiklander     int restart_enabled = 0;
5663d3b0591SJens Wiklander     ECDH_VALIDATE_RET( ctx != NULL );
5673d3b0591SJens Wiklander     ECDH_VALIDATE_RET( olen != NULL );
5683d3b0591SJens Wiklander     ECDH_VALIDATE_RET( buf != NULL );
5693d3b0591SJens Wiklander     ECDH_VALIDATE_RET( f_rng != NULL );
5703d3b0591SJens Wiklander 
5713d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
5723d3b0591SJens Wiklander     restart_enabled = ctx->restart_enabled;
5733d3b0591SJens Wiklander #endif
5743d3b0591SJens Wiklander 
5753d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
5763d3b0591SJens Wiklander     return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
5773d3b0591SJens Wiklander                                        f_rng, p_rng, restart_enabled ) );
5783d3b0591SJens Wiklander #else
5793d3b0591SJens Wiklander     switch( ctx->var )
5803d3b0591SJens Wiklander     {
58111fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
58211fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
58311fa71b9SJerome Forissier             return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen,
58411fa71b9SJerome Forissier                                                  buf, blen, f_rng, p_rng ) );
58511fa71b9SJerome Forissier #endif
5863d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
5873d3b0591SJens Wiklander             return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
5883d3b0591SJens Wiklander                                                ctx->point_format, buf, blen,
5893d3b0591SJens Wiklander                                                f_rng, p_rng,
5903d3b0591SJens Wiklander                                                restart_enabled ) );
5913d3b0591SJens Wiklander         default:
5923d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
5933d3b0591SJens Wiklander     }
5943d3b0591SJens Wiklander #endif
5953d3b0591SJens Wiklander }
5963d3b0591SJens Wiklander 
5973d3b0591SJens Wiklander static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
5983d3b0591SJens Wiklander                                       const unsigned char *buf, size_t blen )
5993d3b0591SJens Wiklander {
60011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
6013d3b0591SJens Wiklander     const unsigned char *p = buf;
602817466cbSJens Wiklander 
6033d3b0591SJens Wiklander     if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
6043d3b0591SJens Wiklander                                             blen ) ) != 0 )
605817466cbSJens Wiklander         return( ret );
606817466cbSJens Wiklander 
6073d3b0591SJens Wiklander     if( (size_t)( p - buf ) != blen )
6083d3b0591SJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
6093d3b0591SJens Wiklander 
6103d3b0591SJens Wiklander     return( 0 );
611817466cbSJens Wiklander }
612817466cbSJens Wiklander 
613817466cbSJens Wiklander /*
614817466cbSJens Wiklander  * Parse and import the client's public value
615817466cbSJens Wiklander  */
616817466cbSJens Wiklander int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
617817466cbSJens Wiklander                               const unsigned char *buf, size_t blen )
618817466cbSJens Wiklander {
6193d3b0591SJens Wiklander     ECDH_VALIDATE_RET( ctx != NULL );
6203d3b0591SJens Wiklander     ECDH_VALIDATE_RET( buf != NULL );
6213d3b0591SJens Wiklander 
6223d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
6233d3b0591SJens Wiklander     return( ecdh_read_public_internal( ctx, buf, blen ) );
6243d3b0591SJens Wiklander #else
6253d3b0591SJens Wiklander     switch( ctx->var )
6263d3b0591SJens Wiklander     {
62711fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
62811fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
62911fa71b9SJerome Forissier             return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh,
63011fa71b9SJerome Forissier                                                  buf, blen ) );
63111fa71b9SJerome Forissier #endif
6323d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
6333d3b0591SJens Wiklander             return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
6343d3b0591SJens Wiklander                                                        buf, blen ) );
6353d3b0591SJens Wiklander         default:
6363d3b0591SJens Wiklander             return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
6373d3b0591SJens Wiklander     }
6383d3b0591SJens Wiklander #endif
6393d3b0591SJens Wiklander }
6403d3b0591SJens Wiklander 
6413d3b0591SJens Wiklander static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
6423d3b0591SJens Wiklander                                       size_t *olen, unsigned char *buf,
6433d3b0591SJens Wiklander                                       size_t blen,
6443d3b0591SJens Wiklander                                       int (*f_rng)(void *,
6453d3b0591SJens Wiklander                                                    unsigned char *,
6463d3b0591SJens Wiklander                                                    size_t),
6473d3b0591SJens Wiklander                                       void *p_rng,
6483d3b0591SJens Wiklander                                       int restart_enabled )
6493d3b0591SJens Wiklander {
65011fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
6513d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
6523d3b0591SJens Wiklander     mbedtls_ecp_restart_ctx *rs_ctx = NULL;
6533d3b0591SJens Wiklander #endif
654817466cbSJens Wiklander 
6553d3b0591SJens Wiklander     if( ctx == NULL || ctx->grp.pbits == 0 )
656817466cbSJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
657817466cbSJens Wiklander 
6583d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
6593d3b0591SJens Wiklander     if( restart_enabled )
6603d3b0591SJens Wiklander         rs_ctx = &ctx->rs;
6613d3b0591SJens Wiklander #else
6623d3b0591SJens Wiklander     (void) restart_enabled;
6633d3b0591SJens Wiklander #endif
6643d3b0591SJens Wiklander 
6653d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
6663d3b0591SJens Wiklander     if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
6673d3b0591SJens Wiklander                                                  &ctx->d, f_rng, p_rng,
6683d3b0591SJens Wiklander                                                  rs_ctx ) ) != 0 )
6693d3b0591SJens Wiklander     {
670817466cbSJens Wiklander         return( ret );
6713d3b0591SJens Wiklander     }
6723d3b0591SJens Wiklander #else
6733d3b0591SJens Wiklander     if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
6743d3b0591SJens Wiklander                                              &ctx->d, f_rng, p_rng ) ) != 0 )
6753d3b0591SJens Wiklander     {
6763d3b0591SJens Wiklander         return( ret );
6773d3b0591SJens Wiklander     }
6783d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
679817466cbSJens Wiklander 
6803d3b0591SJens Wiklander     if( mbedtls_mpi_size( &ctx->z ) > blen )
681817466cbSJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
682817466cbSJens Wiklander 
6833d3b0591SJens Wiklander     *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
68411fa71b9SJerome Forissier 
68511fa71b9SJerome Forissier     if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
68611fa71b9SJerome Forissier         return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen );
68711fa71b9SJerome Forissier 
6883d3b0591SJens Wiklander     return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
689817466cbSJens Wiklander }
690817466cbSJens Wiklander 
691817466cbSJens Wiklander /*
692817466cbSJens Wiklander  * Derive and export the shared secret
693817466cbSJens Wiklander  */
694817466cbSJens Wiklander int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
695817466cbSJens Wiklander                               unsigned char *buf, size_t blen,
696817466cbSJens Wiklander                               int (*f_rng)(void *, unsigned char *, size_t),
697817466cbSJens Wiklander                               void *p_rng )
698817466cbSJens Wiklander {
6993d3b0591SJens Wiklander     int restart_enabled = 0;
7003d3b0591SJens Wiklander     ECDH_VALIDATE_RET( ctx != NULL );
7013d3b0591SJens Wiklander     ECDH_VALIDATE_RET( olen != NULL );
7023d3b0591SJens Wiklander     ECDH_VALIDATE_RET( buf != NULL );
703817466cbSJens Wiklander 
7043d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
7053d3b0591SJens Wiklander     restart_enabled = ctx->restart_enabled;
7063d3b0591SJens Wiklander #endif
707817466cbSJens Wiklander 
7083d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
7093d3b0591SJens Wiklander     return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
7103d3b0591SJens Wiklander                                        restart_enabled ) );
7113d3b0591SJens Wiklander #else
7123d3b0591SJens Wiklander     switch( ctx->var )
713817466cbSJens Wiklander     {
71411fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
71511fa71b9SJerome Forissier         case MBEDTLS_ECDH_VARIANT_EVEREST:
71611fa71b9SJerome Forissier             return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen,
71711fa71b9SJerome Forissier                                                  buf, blen, f_rng, p_rng ) );
71811fa71b9SJerome Forissier #endif
7193d3b0591SJens Wiklander         case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
7203d3b0591SJens Wiklander             return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
7213d3b0591SJens Wiklander                                                blen, f_rng, p_rng,
7223d3b0591SJens Wiklander                                                restart_enabled ) );
7233d3b0591SJens Wiklander         default:
724817466cbSJens Wiklander             return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
7253d3b0591SJens Wiklander     }
7263d3b0591SJens Wiklander #endif
727817466cbSJens Wiklander }
728817466cbSJens Wiklander 
729817466cbSJens Wiklander #endif /* MBEDTLS_ECDH_C */
730