1c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0 2817466cbSJens Wiklander /* 3817466cbSJens Wiklander * Elliptic curve Diffie-Hellman 4817466cbSJens Wiklander * 5817466cbSJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 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 * This file is part of mbed TLS (https://tls.mbed.org) 20817466cbSJens Wiklander */ 21817466cbSJens Wiklander 22817466cbSJens Wiklander /* 23817466cbSJens Wiklander * References: 24817466cbSJens Wiklander * 25817466cbSJens Wiklander * SEC1 http://www.secg.org/index.php?action=secg,docs_secg 26817466cbSJens Wiklander * RFC 4492 27817466cbSJens Wiklander */ 28817466cbSJens Wiklander 29817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 30817466cbSJens Wiklander #include "mbedtls/config.h" 31817466cbSJens Wiklander #else 32817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 33817466cbSJens Wiklander #endif 34817466cbSJens Wiklander 35817466cbSJens Wiklander #if defined(MBEDTLS_ECDH_C) 36817466cbSJens Wiklander 37817466cbSJens Wiklander #include "mbedtls/ecdh.h" 383d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 39*11fa71b9SJerome Forissier #include "mbedtls/error.h" 40817466cbSJens Wiklander 41817466cbSJens Wiklander #include <string.h> 42817466cbSJens Wiklander 433d3b0591SJens Wiklander /* Parameter validation macros based on platform_util.h */ 443d3b0591SJens Wiklander #define ECDH_VALIDATE_RET( cond ) \ 453d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) 463d3b0591SJens Wiklander #define ECDH_VALIDATE( cond ) \ 473d3b0591SJens Wiklander MBEDTLS_INTERNAL_VALIDATE( cond ) 483d3b0591SJens Wiklander 493d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 503d3b0591SJens Wiklander typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; 513d3b0591SJens Wiklander #endif 523d3b0591SJens Wiklander 535b25c76aSJerome Forissier static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( 545b25c76aSJerome Forissier const mbedtls_ecdh_context *ctx ) 555b25c76aSJerome Forissier { 565b25c76aSJerome Forissier #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 575b25c76aSJerome Forissier return( ctx->grp.id ); 585b25c76aSJerome Forissier #else 595b25c76aSJerome Forissier return( ctx->grp_id ); 605b25c76aSJerome Forissier #endif 615b25c76aSJerome Forissier } 625b25c76aSJerome Forissier 63*11fa71b9SJerome Forissier int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid ) 64*11fa71b9SJerome Forissier { 65*11fa71b9SJerome Forissier /* At this time, all groups support ECDH. */ 66*11fa71b9SJerome Forissier (void) gid; 67*11fa71b9SJerome Forissier return( 1 ); 68*11fa71b9SJerome Forissier } 69*11fa71b9SJerome Forissier 703d3b0591SJens Wiklander #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) 71817466cbSJens Wiklander /* 723d3b0591SJens Wiklander * Generate public key (restartable version) 733d3b0591SJens Wiklander * 743d3b0591SJens Wiklander * Note: this internal function relies on its caller preserving the value of 753d3b0591SJens Wiklander * the output parameter 'd' across continuation calls. This would not be 763d3b0591SJens Wiklander * acceptable for a public function but is OK here as we control call sites. 773d3b0591SJens Wiklander */ 783d3b0591SJens Wiklander static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, 793d3b0591SJens Wiklander mbedtls_mpi *d, mbedtls_ecp_point *Q, 803d3b0591SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 813d3b0591SJens Wiklander void *p_rng, 823d3b0591SJens Wiklander mbedtls_ecp_restart_ctx *rs_ctx ) 833d3b0591SJens Wiklander { 84*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 853d3b0591SJens Wiklander 863d3b0591SJens Wiklander /* If multiplication is in progress, we already generated a privkey */ 873d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 883d3b0591SJens Wiklander if( rs_ctx == NULL || rs_ctx->rsm == NULL ) 893d3b0591SJens Wiklander #endif 903d3b0591SJens Wiklander MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); 913d3b0591SJens Wiklander 923d3b0591SJens Wiklander MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, 933d3b0591SJens Wiklander f_rng, p_rng, rs_ctx ) ); 943d3b0591SJens Wiklander 953d3b0591SJens Wiklander cleanup: 963d3b0591SJens Wiklander return( ret ); 973d3b0591SJens Wiklander } 983d3b0591SJens Wiklander 993d3b0591SJens Wiklander /* 1003d3b0591SJens Wiklander * Generate public key 101817466cbSJens Wiklander */ 102817466cbSJens Wiklander int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, 103817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 104817466cbSJens Wiklander void *p_rng ) 105817466cbSJens Wiklander { 1063d3b0591SJens Wiklander ECDH_VALIDATE_RET( grp != NULL ); 1073d3b0591SJens Wiklander ECDH_VALIDATE_RET( d != NULL ); 1083d3b0591SJens Wiklander ECDH_VALIDATE_RET( Q != NULL ); 1093d3b0591SJens Wiklander ECDH_VALIDATE_RET( f_rng != NULL ); 1103d3b0591SJens Wiklander return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); 111817466cbSJens Wiklander } 1123d3b0591SJens Wiklander #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ 113817466cbSJens Wiklander 1143d3b0591SJens Wiklander #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) 115817466cbSJens Wiklander /* 116817466cbSJens Wiklander * Compute shared secret (SEC1 3.3.1) 117817466cbSJens Wiklander */ 1183d3b0591SJens Wiklander static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, 1193d3b0591SJens Wiklander mbedtls_mpi *z, 120817466cbSJens Wiklander const mbedtls_ecp_point *Q, const mbedtls_mpi *d, 121817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1223d3b0591SJens Wiklander void *p_rng, 1233d3b0591SJens Wiklander mbedtls_ecp_restart_ctx *rs_ctx ) 124817466cbSJens Wiklander { 125*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 126817466cbSJens Wiklander mbedtls_ecp_point P; 127817466cbSJens Wiklander 128817466cbSJens Wiklander mbedtls_ecp_point_init( &P ); 129817466cbSJens Wiklander 1303d3b0591SJens Wiklander MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, 1313d3b0591SJens Wiklander f_rng, p_rng, rs_ctx ) ); 132817466cbSJens Wiklander 133817466cbSJens Wiklander if( mbedtls_ecp_is_zero( &P ) ) 134817466cbSJens Wiklander { 135817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 136817466cbSJens Wiklander goto cleanup; 137817466cbSJens Wiklander } 138817466cbSJens Wiklander 139817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); 140817466cbSJens Wiklander 141817466cbSJens Wiklander cleanup: 142817466cbSJens Wiklander mbedtls_ecp_point_free( &P ); 143817466cbSJens Wiklander 144817466cbSJens Wiklander return( ret ); 145817466cbSJens Wiklander } 146817466cbSJens Wiklander 147817466cbSJens Wiklander /* 1483d3b0591SJens Wiklander * Compute shared secret (SEC1 3.3.1) 1493d3b0591SJens Wiklander */ 1503d3b0591SJens Wiklander int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, 1513d3b0591SJens Wiklander const mbedtls_ecp_point *Q, const mbedtls_mpi *d, 1523d3b0591SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 1533d3b0591SJens Wiklander void *p_rng ) 1543d3b0591SJens Wiklander { 1553d3b0591SJens Wiklander ECDH_VALIDATE_RET( grp != NULL ); 1563d3b0591SJens Wiklander ECDH_VALIDATE_RET( Q != NULL ); 1573d3b0591SJens Wiklander ECDH_VALIDATE_RET( d != NULL ); 1583d3b0591SJens Wiklander ECDH_VALIDATE_RET( z != NULL ); 1593d3b0591SJens Wiklander return( ecdh_compute_shared_restartable( grp, z, Q, d, 1603d3b0591SJens Wiklander f_rng, p_rng, NULL ) ); 1613d3b0591SJens Wiklander } 1623d3b0591SJens Wiklander #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ 1633d3b0591SJens Wiklander 1643d3b0591SJens Wiklander static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx ) 1653d3b0591SJens Wiklander { 1663d3b0591SJens Wiklander mbedtls_ecp_group_init( &ctx->grp ); 1673d3b0591SJens Wiklander mbedtls_mpi_init( &ctx->d ); 1683d3b0591SJens Wiklander mbedtls_ecp_point_init( &ctx->Q ); 1693d3b0591SJens Wiklander mbedtls_ecp_point_init( &ctx->Qp ); 1703d3b0591SJens Wiklander mbedtls_mpi_init( &ctx->z ); 1713d3b0591SJens Wiklander 1723d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 1733d3b0591SJens Wiklander mbedtls_ecp_restart_init( &ctx->rs ); 1743d3b0591SJens Wiklander #endif 1753d3b0591SJens Wiklander } 1763d3b0591SJens Wiklander 1773d3b0591SJens Wiklander /* 178817466cbSJens Wiklander * Initialize context 179817466cbSJens Wiklander */ 180817466cbSJens Wiklander void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) 181817466cbSJens Wiklander { 1823d3b0591SJens Wiklander ECDH_VALIDATE( ctx != NULL ); 1833d3b0591SJens Wiklander 1843d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 1853d3b0591SJens Wiklander ecdh_init_internal( ctx ); 1863d3b0591SJens Wiklander mbedtls_ecp_point_init( &ctx->Vi ); 1873d3b0591SJens Wiklander mbedtls_ecp_point_init( &ctx->Vf ); 1883d3b0591SJens Wiklander mbedtls_mpi_init( &ctx->_d ); 1893d3b0591SJens Wiklander #else 190817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); 1913d3b0591SJens Wiklander 1923d3b0591SJens Wiklander ctx->var = MBEDTLS_ECDH_VARIANT_NONE; 1933d3b0591SJens Wiklander #endif 1943d3b0591SJens Wiklander ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 1953d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 1963d3b0591SJens Wiklander ctx->restart_enabled = 0; 1973d3b0591SJens Wiklander #endif 198817466cbSJens Wiklander } 199817466cbSJens Wiklander 2003d3b0591SJens Wiklander static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, 2013d3b0591SJens Wiklander mbedtls_ecp_group_id grp_id ) 2023d3b0591SJens Wiklander { 203*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 2043d3b0591SJens Wiklander 2053d3b0591SJens Wiklander ret = mbedtls_ecp_group_load( &ctx->grp, grp_id ); 2063d3b0591SJens Wiklander if( ret != 0 ) 2073d3b0591SJens Wiklander { 2083d3b0591SJens Wiklander return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); 2093d3b0591SJens Wiklander } 2103d3b0591SJens Wiklander 2113d3b0591SJens Wiklander return( 0 ); 2123d3b0591SJens Wiklander } 2133d3b0591SJens Wiklander 2143d3b0591SJens Wiklander /* 2153d3b0591SJens Wiklander * Setup context 2163d3b0591SJens Wiklander */ 2173d3b0591SJens Wiklander int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) 2183d3b0591SJens Wiklander { 2193d3b0591SJens Wiklander ECDH_VALIDATE_RET( ctx != NULL ); 2203d3b0591SJens Wiklander 2213d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 2223d3b0591SJens Wiklander return( ecdh_setup_internal( ctx, grp_id ) ); 2233d3b0591SJens Wiklander #else 2243d3b0591SJens Wiklander switch( grp_id ) 2253d3b0591SJens Wiklander { 226*11fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 227*11fa71b9SJerome Forissier case MBEDTLS_ECP_DP_CURVE25519: 228*11fa71b9SJerome Forissier ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED; 229*11fa71b9SJerome Forissier ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST; 230*11fa71b9SJerome Forissier ctx->grp_id = grp_id; 231*11fa71b9SJerome Forissier return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) ); 232*11fa71b9SJerome Forissier #endif 2333d3b0591SJens Wiklander default: 2343d3b0591SJens Wiklander ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 2353d3b0591SJens Wiklander ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; 2363d3b0591SJens Wiklander ctx->grp_id = grp_id; 2373d3b0591SJens Wiklander ecdh_init_internal( &ctx->ctx.mbed_ecdh ); 2383d3b0591SJens Wiklander return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); 2393d3b0591SJens Wiklander } 2403d3b0591SJens Wiklander #endif 2413d3b0591SJens Wiklander } 2423d3b0591SJens Wiklander 2433d3b0591SJens Wiklander static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) 2443d3b0591SJens Wiklander { 2453d3b0591SJens Wiklander mbedtls_ecp_group_free( &ctx->grp ); 2463d3b0591SJens Wiklander mbedtls_mpi_free( &ctx->d ); 2473d3b0591SJens Wiklander mbedtls_ecp_point_free( &ctx->Q ); 2483d3b0591SJens Wiklander mbedtls_ecp_point_free( &ctx->Qp ); 2493d3b0591SJens Wiklander mbedtls_mpi_free( &ctx->z ); 2503d3b0591SJens Wiklander 2513d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 2523d3b0591SJens Wiklander mbedtls_ecp_restart_free( &ctx->rs ); 2533d3b0591SJens Wiklander #endif 2543d3b0591SJens Wiklander } 2553d3b0591SJens Wiklander 2563d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 2573d3b0591SJens Wiklander /* 2583d3b0591SJens Wiklander * Enable restartable operations for context 2593d3b0591SJens Wiklander */ 2603d3b0591SJens Wiklander void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) 2613d3b0591SJens Wiklander { 2623d3b0591SJens Wiklander ECDH_VALIDATE( ctx != NULL ); 2633d3b0591SJens Wiklander 2643d3b0591SJens Wiklander ctx->restart_enabled = 1; 2653d3b0591SJens Wiklander } 2663d3b0591SJens Wiklander #endif 2673d3b0591SJens Wiklander 268817466cbSJens Wiklander /* 269817466cbSJens Wiklander * Free context 270817466cbSJens Wiklander */ 271817466cbSJens Wiklander void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) 272817466cbSJens Wiklander { 273817466cbSJens Wiklander if( ctx == NULL ) 274817466cbSJens Wiklander return; 275817466cbSJens Wiklander 2763d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 277817466cbSJens Wiklander mbedtls_ecp_point_free( &ctx->Vi ); 278817466cbSJens Wiklander mbedtls_ecp_point_free( &ctx->Vf ); 279817466cbSJens Wiklander mbedtls_mpi_free( &ctx->_d ); 2803d3b0591SJens Wiklander ecdh_free_internal( ctx ); 2813d3b0591SJens Wiklander #else 2823d3b0591SJens Wiklander switch( ctx->var ) 2833d3b0591SJens Wiklander { 284*11fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 285*11fa71b9SJerome Forissier case MBEDTLS_ECDH_VARIANT_EVEREST: 286*11fa71b9SJerome Forissier mbedtls_everest_free( &ctx->ctx.everest_ecdh ); 287*11fa71b9SJerome Forissier break; 288*11fa71b9SJerome Forissier #endif 2893d3b0591SJens Wiklander case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 2903d3b0591SJens Wiklander ecdh_free_internal( &ctx->ctx.mbed_ecdh ); 2913d3b0591SJens Wiklander break; 2923d3b0591SJens Wiklander default: 2933d3b0591SJens Wiklander break; 2943d3b0591SJens Wiklander } 2953d3b0591SJens Wiklander 2963d3b0591SJens Wiklander ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 2973d3b0591SJens Wiklander ctx->var = MBEDTLS_ECDH_VARIANT_NONE; 2983d3b0591SJens Wiklander ctx->grp_id = MBEDTLS_ECP_DP_NONE; 2993d3b0591SJens Wiklander #endif 3003d3b0591SJens Wiklander } 3013d3b0591SJens Wiklander 3023d3b0591SJens Wiklander static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, 3033d3b0591SJens Wiklander size_t *olen, int point_format, 3043d3b0591SJens Wiklander unsigned char *buf, size_t blen, 3053d3b0591SJens Wiklander int (*f_rng)(void *, 3063d3b0591SJens Wiklander unsigned char *, 3073d3b0591SJens Wiklander size_t), 3083d3b0591SJens Wiklander void *p_rng, 3093d3b0591SJens Wiklander int restart_enabled ) 3103d3b0591SJens Wiklander { 311*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 3123d3b0591SJens Wiklander size_t grp_len, pt_len; 3133d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 3143d3b0591SJens Wiklander mbedtls_ecp_restart_ctx *rs_ctx = NULL; 3153d3b0591SJens Wiklander #endif 3163d3b0591SJens Wiklander 3173d3b0591SJens Wiklander if( ctx->grp.pbits == 0 ) 3183d3b0591SJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 3193d3b0591SJens Wiklander 3203d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 3213d3b0591SJens Wiklander if( restart_enabled ) 3223d3b0591SJens Wiklander rs_ctx = &ctx->rs; 3233d3b0591SJens Wiklander #else 3243d3b0591SJens Wiklander (void) restart_enabled; 3253d3b0591SJens Wiklander #endif 3263d3b0591SJens Wiklander 3273d3b0591SJens Wiklander 3283d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 3293d3b0591SJens Wiklander if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, 3303d3b0591SJens Wiklander f_rng, p_rng, rs_ctx ) ) != 0 ) 3313d3b0591SJens Wiklander return( ret ); 3323d3b0591SJens Wiklander #else 3333d3b0591SJens Wiklander if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, 3343d3b0591SJens Wiklander f_rng, p_rng ) ) != 0 ) 3353d3b0591SJens Wiklander return( ret ); 3363d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */ 3373d3b0591SJens Wiklander 3383d3b0591SJens Wiklander if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, 3393d3b0591SJens Wiklander blen ) ) != 0 ) 3403d3b0591SJens Wiklander return( ret ); 3413d3b0591SJens Wiklander 3423d3b0591SJens Wiklander buf += grp_len; 3433d3b0591SJens Wiklander blen -= grp_len; 3443d3b0591SJens Wiklander 3453d3b0591SJens Wiklander if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, 3463d3b0591SJens Wiklander &pt_len, buf, blen ) ) != 0 ) 3473d3b0591SJens Wiklander return( ret ); 3483d3b0591SJens Wiklander 3493d3b0591SJens Wiklander *olen = grp_len + pt_len; 3503d3b0591SJens Wiklander return( 0 ); 351817466cbSJens Wiklander } 352817466cbSJens Wiklander 353817466cbSJens Wiklander /* 354*11fa71b9SJerome Forissier * Setup and write the ServerKeyExchange parameters (RFC 4492) 355817466cbSJens Wiklander * struct { 356817466cbSJens Wiklander * ECParameters curve_params; 357817466cbSJens Wiklander * ECPoint public; 358817466cbSJens Wiklander * } ServerECDHParams; 359817466cbSJens Wiklander */ 360817466cbSJens Wiklander int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, 361817466cbSJens Wiklander unsigned char *buf, size_t blen, 362817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 363817466cbSJens Wiklander void *p_rng ) 364817466cbSJens Wiklander { 3653d3b0591SJens Wiklander int restart_enabled = 0; 3663d3b0591SJens Wiklander ECDH_VALIDATE_RET( ctx != NULL ); 3673d3b0591SJens Wiklander ECDH_VALIDATE_RET( olen != NULL ); 3683d3b0591SJens Wiklander ECDH_VALIDATE_RET( buf != NULL ); 3693d3b0591SJens Wiklander ECDH_VALIDATE_RET( f_rng != NULL ); 370817466cbSJens Wiklander 3713d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 3723d3b0591SJens Wiklander restart_enabled = ctx->restart_enabled; 3733d3b0591SJens Wiklander #else 3743d3b0591SJens Wiklander (void) restart_enabled; 3753d3b0591SJens Wiklander #endif 376817466cbSJens Wiklander 3773d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 3783d3b0591SJens Wiklander return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen, 3793d3b0591SJens Wiklander f_rng, p_rng, restart_enabled ) ); 3803d3b0591SJens Wiklander #else 3813d3b0591SJens Wiklander switch( ctx->var ) 3823d3b0591SJens Wiklander { 383*11fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 384*11fa71b9SJerome Forissier case MBEDTLS_ECDH_VARIANT_EVEREST: 385*11fa71b9SJerome Forissier return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen, 386*11fa71b9SJerome Forissier buf, blen, f_rng, p_rng ) ); 387*11fa71b9SJerome Forissier #endif 3883d3b0591SJens Wiklander case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 3893d3b0591SJens Wiklander return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen, 3903d3b0591SJens Wiklander ctx->point_format, buf, blen, 3913d3b0591SJens Wiklander f_rng, p_rng, 3923d3b0591SJens Wiklander restart_enabled ) ); 3933d3b0591SJens Wiklander default: 3943d3b0591SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 3953d3b0591SJens Wiklander } 3963d3b0591SJens Wiklander #endif 3973d3b0591SJens Wiklander } 398817466cbSJens Wiklander 3993d3b0591SJens Wiklander static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, 4003d3b0591SJens Wiklander const unsigned char **buf, 4013d3b0591SJens Wiklander const unsigned char *end ) 4023d3b0591SJens Wiklander { 4033d3b0591SJens Wiklander return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, 4043d3b0591SJens Wiklander end - *buf ) ); 405817466cbSJens Wiklander } 406817466cbSJens Wiklander 407817466cbSJens Wiklander /* 408817466cbSJens Wiklander * Read the ServerKeyExhange parameters (RFC 4492) 409817466cbSJens Wiklander * struct { 410817466cbSJens Wiklander * ECParameters curve_params; 411817466cbSJens Wiklander * ECPoint public; 412817466cbSJens Wiklander * } ServerECDHParams; 413817466cbSJens Wiklander */ 414817466cbSJens Wiklander int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, 4153d3b0591SJens Wiklander const unsigned char **buf, 4163d3b0591SJens Wiklander const unsigned char *end ) 417817466cbSJens Wiklander { 418*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 4193d3b0591SJens Wiklander mbedtls_ecp_group_id grp_id; 4203d3b0591SJens Wiklander ECDH_VALIDATE_RET( ctx != NULL ); 4213d3b0591SJens Wiklander ECDH_VALIDATE_RET( buf != NULL ); 4223d3b0591SJens Wiklander ECDH_VALIDATE_RET( *buf != NULL ); 4233d3b0591SJens Wiklander ECDH_VALIDATE_RET( end != NULL ); 424817466cbSJens Wiklander 4253d3b0591SJens Wiklander if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) 426817466cbSJens Wiklander != 0 ) 427817466cbSJens Wiklander return( ret ); 428817466cbSJens Wiklander 4293d3b0591SJens Wiklander if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) 4303d3b0591SJens Wiklander return( ret ); 4313d3b0591SJens Wiklander 4323d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 4333d3b0591SJens Wiklander return( ecdh_read_params_internal( ctx, buf, end ) ); 4343d3b0591SJens Wiklander #else 4353d3b0591SJens Wiklander switch( ctx->var ) 4363d3b0591SJens Wiklander { 437*11fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 438*11fa71b9SJerome Forissier case MBEDTLS_ECDH_VARIANT_EVEREST: 439*11fa71b9SJerome Forissier return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh, 440*11fa71b9SJerome Forissier buf, end) ); 441*11fa71b9SJerome Forissier #endif 4423d3b0591SJens Wiklander case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 4433d3b0591SJens Wiklander return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh, 4443d3b0591SJens Wiklander buf, end ) ); 4453d3b0591SJens Wiklander default: 4463d3b0591SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 4473d3b0591SJens Wiklander } 4483d3b0591SJens Wiklander #endif 449817466cbSJens Wiklander } 450817466cbSJens Wiklander 4513d3b0591SJens Wiklander static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, 4523d3b0591SJens Wiklander const mbedtls_ecp_keypair *key, 453817466cbSJens Wiklander mbedtls_ecdh_side side ) 454817466cbSJens Wiklander { 455*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 456817466cbSJens Wiklander 457817466cbSJens Wiklander /* If it's not our key, just import the public part as Qp */ 458817466cbSJens Wiklander if( side == MBEDTLS_ECDH_THEIRS ) 459817466cbSJens Wiklander return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); 460817466cbSJens Wiklander 461817466cbSJens Wiklander /* Our key: import public (as Q) and private parts */ 462817466cbSJens Wiklander if( side != MBEDTLS_ECDH_OURS ) 463817466cbSJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 464817466cbSJens Wiklander 465817466cbSJens Wiklander if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || 466817466cbSJens Wiklander ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) 467817466cbSJens Wiklander return( ret ); 468817466cbSJens Wiklander 469817466cbSJens Wiklander return( 0 ); 470817466cbSJens Wiklander } 471817466cbSJens Wiklander 472817466cbSJens Wiklander /* 4733d3b0591SJens Wiklander * Get parameters from a keypair 4743d3b0591SJens Wiklander */ 4753d3b0591SJens Wiklander int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, 4763d3b0591SJens Wiklander const mbedtls_ecp_keypair *key, 4773d3b0591SJens Wiklander mbedtls_ecdh_side side ) 4783d3b0591SJens Wiklander { 479*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 4803d3b0591SJens Wiklander ECDH_VALIDATE_RET( ctx != NULL ); 4813d3b0591SJens Wiklander ECDH_VALIDATE_RET( key != NULL ); 4823d3b0591SJens Wiklander ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || 4833d3b0591SJens Wiklander side == MBEDTLS_ECDH_THEIRS ); 4843d3b0591SJens Wiklander 4855b25c76aSJerome Forissier if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE ) 4865b25c76aSJerome Forissier { 4875b25c76aSJerome Forissier /* This is the first call to get_params(). Set up the context 4885b25c76aSJerome Forissier * for use with the group. */ 4893d3b0591SJens Wiklander if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) 4903d3b0591SJens Wiklander return( ret ); 4915b25c76aSJerome Forissier } 4925b25c76aSJerome Forissier else 4935b25c76aSJerome Forissier { 4945b25c76aSJerome Forissier /* This is not the first call to get_params(). Check that the 4955b25c76aSJerome Forissier * current key's group is the same as the context's, which was set 4965b25c76aSJerome Forissier * from the first key's group. */ 4975b25c76aSJerome Forissier if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id ) 4985b25c76aSJerome Forissier return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 4995b25c76aSJerome Forissier } 5003d3b0591SJens Wiklander 5013d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 5023d3b0591SJens Wiklander return( ecdh_get_params_internal( ctx, key, side ) ); 5033d3b0591SJens Wiklander #else 5043d3b0591SJens Wiklander switch( ctx->var ) 5053d3b0591SJens Wiklander { 506*11fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 507*11fa71b9SJerome Forissier case MBEDTLS_ECDH_VARIANT_EVEREST: 508*11fa71b9SJerome Forissier { 509*11fa71b9SJerome Forissier mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ? 510*11fa71b9SJerome Forissier MBEDTLS_EVEREST_ECDH_OURS : 511*11fa71b9SJerome Forissier MBEDTLS_EVEREST_ECDH_THEIRS; 512*11fa71b9SJerome Forissier return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh, 513*11fa71b9SJerome Forissier key, s) ); 514*11fa71b9SJerome Forissier } 515*11fa71b9SJerome Forissier #endif 5163d3b0591SJens Wiklander case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 5173d3b0591SJens Wiklander return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh, 5183d3b0591SJens Wiklander key, side ) ); 5193d3b0591SJens Wiklander default: 5203d3b0591SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 5213d3b0591SJens Wiklander } 5223d3b0591SJens Wiklander #endif 5233d3b0591SJens Wiklander } 5243d3b0591SJens Wiklander 5253d3b0591SJens Wiklander static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, 5263d3b0591SJens Wiklander size_t *olen, int point_format, 5273d3b0591SJens Wiklander unsigned char *buf, size_t blen, 5283d3b0591SJens Wiklander int (*f_rng)(void *, 5293d3b0591SJens Wiklander unsigned char *, 5303d3b0591SJens Wiklander size_t), 5313d3b0591SJens Wiklander void *p_rng, 5323d3b0591SJens Wiklander int restart_enabled ) 5333d3b0591SJens Wiklander { 534*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 5353d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 5363d3b0591SJens Wiklander mbedtls_ecp_restart_ctx *rs_ctx = NULL; 5373d3b0591SJens Wiklander #endif 5383d3b0591SJens Wiklander 5393d3b0591SJens Wiklander if( ctx->grp.pbits == 0 ) 5403d3b0591SJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 5413d3b0591SJens Wiklander 5423d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 5433d3b0591SJens Wiklander if( restart_enabled ) 5443d3b0591SJens Wiklander rs_ctx = &ctx->rs; 5453d3b0591SJens Wiklander #else 5463d3b0591SJens Wiklander (void) restart_enabled; 5473d3b0591SJens Wiklander #endif 5483d3b0591SJens Wiklander 5493d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 5503d3b0591SJens Wiklander if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, 5513d3b0591SJens Wiklander f_rng, p_rng, rs_ctx ) ) != 0 ) 5523d3b0591SJens Wiklander return( ret ); 5533d3b0591SJens Wiklander #else 5543d3b0591SJens Wiklander if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, 5553d3b0591SJens Wiklander f_rng, p_rng ) ) != 0 ) 5563d3b0591SJens Wiklander return( ret ); 5573d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */ 5583d3b0591SJens Wiklander 5593d3b0591SJens Wiklander return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen, 5603d3b0591SJens Wiklander buf, blen ); 5613d3b0591SJens Wiklander } 5623d3b0591SJens Wiklander 5633d3b0591SJens Wiklander /* 564817466cbSJens Wiklander * Setup and export the client public value 565817466cbSJens Wiklander */ 566817466cbSJens Wiklander int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, 567817466cbSJens Wiklander unsigned char *buf, size_t blen, 568817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 569817466cbSJens Wiklander void *p_rng ) 570817466cbSJens Wiklander { 5713d3b0591SJens Wiklander int restart_enabled = 0; 5723d3b0591SJens Wiklander ECDH_VALIDATE_RET( ctx != NULL ); 5733d3b0591SJens Wiklander ECDH_VALIDATE_RET( olen != NULL ); 5743d3b0591SJens Wiklander ECDH_VALIDATE_RET( buf != NULL ); 5753d3b0591SJens Wiklander ECDH_VALIDATE_RET( f_rng != NULL ); 5763d3b0591SJens Wiklander 5773d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 5783d3b0591SJens Wiklander restart_enabled = ctx->restart_enabled; 5793d3b0591SJens Wiklander #endif 5803d3b0591SJens Wiklander 5813d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 5823d3b0591SJens Wiklander return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen, 5833d3b0591SJens Wiklander f_rng, p_rng, restart_enabled ) ); 5843d3b0591SJens Wiklander #else 5853d3b0591SJens Wiklander switch( ctx->var ) 5863d3b0591SJens Wiklander { 587*11fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 588*11fa71b9SJerome Forissier case MBEDTLS_ECDH_VARIANT_EVEREST: 589*11fa71b9SJerome Forissier return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen, 590*11fa71b9SJerome Forissier buf, blen, f_rng, p_rng ) ); 591*11fa71b9SJerome Forissier #endif 5923d3b0591SJens Wiklander case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 5933d3b0591SJens Wiklander return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen, 5943d3b0591SJens Wiklander ctx->point_format, buf, blen, 5953d3b0591SJens Wiklander f_rng, p_rng, 5963d3b0591SJens Wiklander restart_enabled ) ); 5973d3b0591SJens Wiklander default: 5983d3b0591SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 5993d3b0591SJens Wiklander } 6003d3b0591SJens Wiklander #endif 6013d3b0591SJens Wiklander } 6023d3b0591SJens Wiklander 6033d3b0591SJens Wiklander static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, 6043d3b0591SJens Wiklander const unsigned char *buf, size_t blen ) 6053d3b0591SJens Wiklander { 606*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 6073d3b0591SJens Wiklander const unsigned char *p = buf; 608817466cbSJens Wiklander 6093d3b0591SJens Wiklander if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, 6103d3b0591SJens Wiklander blen ) ) != 0 ) 611817466cbSJens Wiklander return( ret ); 612817466cbSJens Wiklander 6133d3b0591SJens Wiklander if( (size_t)( p - buf ) != blen ) 6143d3b0591SJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 6153d3b0591SJens Wiklander 6163d3b0591SJens Wiklander return( 0 ); 617817466cbSJens Wiklander } 618817466cbSJens Wiklander 619817466cbSJens Wiklander /* 620817466cbSJens Wiklander * Parse and import the client's public value 621817466cbSJens Wiklander */ 622817466cbSJens Wiklander int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, 623817466cbSJens Wiklander const unsigned char *buf, size_t blen ) 624817466cbSJens Wiklander { 6253d3b0591SJens Wiklander ECDH_VALIDATE_RET( ctx != NULL ); 6263d3b0591SJens Wiklander ECDH_VALIDATE_RET( buf != NULL ); 6273d3b0591SJens Wiklander 6283d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 6293d3b0591SJens Wiklander return( ecdh_read_public_internal( ctx, buf, blen ) ); 6303d3b0591SJens Wiklander #else 6313d3b0591SJens Wiklander switch( ctx->var ) 6323d3b0591SJens Wiklander { 633*11fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 634*11fa71b9SJerome Forissier case MBEDTLS_ECDH_VARIANT_EVEREST: 635*11fa71b9SJerome Forissier return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh, 636*11fa71b9SJerome Forissier buf, blen ) ); 637*11fa71b9SJerome Forissier #endif 6383d3b0591SJens Wiklander case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 6393d3b0591SJens Wiklander return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh, 6403d3b0591SJens Wiklander buf, blen ) ); 6413d3b0591SJens Wiklander default: 6423d3b0591SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 6433d3b0591SJens Wiklander } 6443d3b0591SJens Wiklander #endif 6453d3b0591SJens Wiklander } 6463d3b0591SJens Wiklander 6473d3b0591SJens Wiklander static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, 6483d3b0591SJens Wiklander size_t *olen, unsigned char *buf, 6493d3b0591SJens Wiklander size_t blen, 6503d3b0591SJens Wiklander int (*f_rng)(void *, 6513d3b0591SJens Wiklander unsigned char *, 6523d3b0591SJens Wiklander size_t), 6533d3b0591SJens Wiklander void *p_rng, 6543d3b0591SJens Wiklander int restart_enabled ) 6553d3b0591SJens Wiklander { 656*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 6573d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 6583d3b0591SJens Wiklander mbedtls_ecp_restart_ctx *rs_ctx = NULL; 6593d3b0591SJens Wiklander #endif 660817466cbSJens Wiklander 6613d3b0591SJens Wiklander if( ctx == NULL || ctx->grp.pbits == 0 ) 662817466cbSJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 663817466cbSJens Wiklander 6643d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 6653d3b0591SJens Wiklander if( restart_enabled ) 6663d3b0591SJens Wiklander rs_ctx = &ctx->rs; 6673d3b0591SJens Wiklander #else 6683d3b0591SJens Wiklander (void) restart_enabled; 6693d3b0591SJens Wiklander #endif 6703d3b0591SJens Wiklander 6713d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 6723d3b0591SJens Wiklander if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp, 6733d3b0591SJens Wiklander &ctx->d, f_rng, p_rng, 6743d3b0591SJens Wiklander rs_ctx ) ) != 0 ) 6753d3b0591SJens Wiklander { 676817466cbSJens Wiklander return( ret ); 6773d3b0591SJens Wiklander } 6783d3b0591SJens Wiklander #else 6793d3b0591SJens Wiklander if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, 6803d3b0591SJens Wiklander &ctx->d, f_rng, p_rng ) ) != 0 ) 6813d3b0591SJens Wiklander { 6823d3b0591SJens Wiklander return( ret ); 6833d3b0591SJens Wiklander } 6843d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */ 685817466cbSJens Wiklander 6863d3b0591SJens Wiklander if( mbedtls_mpi_size( &ctx->z ) > blen ) 687817466cbSJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 688817466cbSJens Wiklander 6893d3b0591SJens Wiklander *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); 690*11fa71b9SJerome Forissier 691*11fa71b9SJerome Forissier if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) 692*11fa71b9SJerome Forissier return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen ); 693*11fa71b9SJerome Forissier 6943d3b0591SJens Wiklander return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); 695817466cbSJens Wiklander } 696817466cbSJens Wiklander 697817466cbSJens Wiklander /* 698817466cbSJens Wiklander * Derive and export the shared secret 699817466cbSJens Wiklander */ 700817466cbSJens Wiklander int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, 701817466cbSJens Wiklander unsigned char *buf, size_t blen, 702817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t), 703817466cbSJens Wiklander void *p_rng ) 704817466cbSJens Wiklander { 7053d3b0591SJens Wiklander int restart_enabled = 0; 7063d3b0591SJens Wiklander ECDH_VALIDATE_RET( ctx != NULL ); 7073d3b0591SJens Wiklander ECDH_VALIDATE_RET( olen != NULL ); 7083d3b0591SJens Wiklander ECDH_VALIDATE_RET( buf != NULL ); 709817466cbSJens Wiklander 7103d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE) 7113d3b0591SJens Wiklander restart_enabled = ctx->restart_enabled; 7123d3b0591SJens Wiklander #endif 713817466cbSJens Wiklander 7143d3b0591SJens Wiklander #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 7153d3b0591SJens Wiklander return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, 7163d3b0591SJens Wiklander restart_enabled ) ); 7173d3b0591SJens Wiklander #else 7183d3b0591SJens Wiklander switch( ctx->var ) 719817466cbSJens Wiklander { 720*11fa71b9SJerome Forissier #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 721*11fa71b9SJerome Forissier case MBEDTLS_ECDH_VARIANT_EVEREST: 722*11fa71b9SJerome Forissier return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen, 723*11fa71b9SJerome Forissier buf, blen, f_rng, p_rng ) ); 724*11fa71b9SJerome Forissier #endif 7253d3b0591SJens Wiklander case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 7263d3b0591SJens Wiklander return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf, 7273d3b0591SJens Wiklander blen, f_rng, p_rng, 7283d3b0591SJens Wiklander restart_enabled ) ); 7293d3b0591SJens Wiklander default: 730817466cbSJens Wiklander return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 7313d3b0591SJens Wiklander } 7323d3b0591SJens Wiklander #endif 733817466cbSJens Wiklander } 734817466cbSJens Wiklander 735817466cbSJens Wiklander #endif /* MBEDTLS_ECDH_C */ 736