1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * Elliptic curve Diffie-Hellman 3817466cbSJens Wiklander * 4*7901324dSJerome Forissier * Copyright The Mbed TLS Contributors 5*7901324dSJerome 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 27*7901324dSJerome 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 /* 402817466cbSJens Wiklander * Read the ServerKeyExhange 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