/* * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include #include "soc/hwcrypto_periph.h" #include "ecc_impl.h" /* TBD: Remove this and use proper getter/setter methods to access * private members of EC data structures once they are available * in mbedTLS stack */ #define MBEDTLS_ALLOW_PRIVATE_ACCESS #include "mbedtls/ecp.h" #include "mbedtls/platform_util.h" #define ECP_VALIDATE_RET( cond ) \ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) #define ECP_VALIDATE( cond ) \ MBEDTLS_INTERNAL_VALIDATE( cond ) #if defined(MBEDTLS_ECP_MUL_ALT) || defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK) #define MAX_SIZE 32 // 256 bits static int esp_mbedtls_ecp_point_multiply(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P) { int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; uint8_t x_tmp[MAX_SIZE]; uint8_t y_tmp[MAX_SIZE]; ecc_point_t p_pt = {0}; ecc_point_t r_pt = {0}; p_pt.len = grp->pbits / 8; memcpy(&p_pt.x, P->X.p, mbedtls_mpi_size(&P->X)); memcpy(&p_pt.y, P->Y.p, mbedtls_mpi_size(&P->Y)); ret = esp_ecc_point_multiply(&p_pt, (uint8_t *)m->p, &r_pt, false); for (int i = 0; i < MAX_SIZE; i++) { x_tmp[MAX_SIZE - i - 1] = r_pt.x[i]; y_tmp[MAX_SIZE - i - 1] = r_pt.y[i]; } mbedtls_mpi_read_binary(&R->X, x_tmp, MAX_SIZE); mbedtls_mpi_read_binary(&R->Y, y_tmp, MAX_SIZE); mbedtls_mpi_lset(&R->Z, 1); return ret; } /* * Restartable multiplication R = m * P */ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx ) { int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; if (grp->id != MBEDTLS_ECP_DP_SECP192R1 && grp->id != MBEDTLS_ECP_DP_SECP256R1) { #if defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK) return mbedtls_ecp_mul_restartable_soft(grp, R, m, P, f_rng, p_rng, rs_ctx); #else return ret; #endif } ECP_VALIDATE_RET( grp != NULL ); ECP_VALIDATE_RET( R != NULL ); ECP_VALIDATE_RET( m != NULL ); ECP_VALIDATE_RET( P != NULL ); /* Common sanity checks */ MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; /* MBEDTLS_MPI_CHK macro assigns the return value of the function to * `ret` variable */ MBEDTLS_MPI_CHK( esp_mbedtls_ecp_point_multiply(grp, R, m, P) ); cleanup: return( ret ); } #endif /* defined(MBEDTLS_ECP_MUL_ALT) || defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK) */ #if defined(MBEDTLS_ECP_VERIFY_ALT) || defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK) int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) { int res; ecc_point_t point; if (grp->id != MBEDTLS_ECP_DP_SECP192R1 && grp->id != MBEDTLS_ECP_DP_SECP256R1) { #if defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK) return mbedtls_ecp_check_pubkey_soft(grp, pt); #else return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #endif } ECP_VALIDATE_RET( grp != NULL ); ECP_VALIDATE_RET( pt != NULL ); /* Must use affine coordinates */ if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) return( MBEDTLS_ERR_ECP_INVALID_KEY ); mbedtls_platform_zeroize((void *)&point, sizeof(ecc_point_t)); memcpy(&point.x, pt->X.p, mbedtls_mpi_size(&pt->X)); memcpy(&point.y, pt->Y.p, mbedtls_mpi_size(&pt->Y)); point.len = grp->pbits / 8; res = esp_ecc_point_verify(&point); if (res == 1) { return 0; } else { return MBEDTLS_ERR_ECP_INVALID_KEY; } } #endif /* defined(MBEDTLS_ECP_VERIFY_ALT) || defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK) */