mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-04 06:11:06 +00:00 
			
		
		
		
	feat(bt): support hardware ecc acceleration for bt tinycrypt
This commit is contained in:
		@@ -545,6 +545,7 @@ if(CONFIG_BT_ENABLED)
 | 
			
		||||
    if(NOT (CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS OR CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS))
 | 
			
		||||
        list(APPEND include_dirs
 | 
			
		||||
                common/tinycrypt/include
 | 
			
		||||
                common/tinycrypt/port
 | 
			
		||||
            )
 | 
			
		||||
        list(APPEND srcs "common/tinycrypt/src/utils.c"
 | 
			
		||||
                "common/tinycrypt/src/sha256.c"
 | 
			
		||||
@@ -560,7 +561,8 @@ if(CONFIG_BT_ENABLED)
 | 
			
		||||
                "common/tinycrypt/src/hmac_prng.c"
 | 
			
		||||
                "common/tinycrypt/src/ecc_platform_specific.c"
 | 
			
		||||
                "common/tinycrypt/src/hmac.c"
 | 
			
		||||
                "common/tinycrypt/src/cbc_mode.c")
 | 
			
		||||
                "common/tinycrypt/src/cbc_mode.c"
 | 
			
		||||
                "common/tinycrypt/port/esp_tinycrypt_port.c")
 | 
			
		||||
    endif()
 | 
			
		||||
 | 
			
		||||
    if(CONFIG_BT_NIMBLE_ENABLED)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										78
									
								
								components/bt/common/tinycrypt/port/esp_tinycrypt_port.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								components/bt/common/tinycrypt/port/esp_tinycrypt_port.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
#include "esp_tinycrypt_port.h"
 | 
			
		||||
#if SOC_ECC_SUPPORTED
 | 
			
		||||
#include "esp_crypto_lock.h"
 | 
			
		||||
#include "esp_private/periph_ctrl.h"
 | 
			
		||||
 | 
			
		||||
#include "hal/ecc_hal.h"
 | 
			
		||||
#include "hal/ecc_ll.h"
 | 
			
		||||
 | 
			
		||||
static void  esp_tinycrypt_acquire_ecc_hardware(void)
 | 
			
		||||
{
 | 
			
		||||
    esp_crypto_ecc_lock_acquire();
 | 
			
		||||
 | 
			
		||||
    periph_module_enable(PERIPH_ECC_MODULE);
 | 
			
		||||
    ecc_ll_power_up();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void  esp_tinycrypt_release_ecc_hardware(void)
 | 
			
		||||
{
 | 
			
		||||
    periph_module_disable(PERIPH_ECC_MODULE);
 | 
			
		||||
    ecc_ll_power_down();
 | 
			
		||||
 | 
			
		||||
    esp_crypto_ecc_lock_release();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length)
 | 
			
		||||
{
 | 
			
		||||
    int result;
 | 
			
		||||
 | 
			
		||||
    esp_tinycrypt_acquire_ecc_hardware();
 | 
			
		||||
 | 
			
		||||
    ecc_hal_write_verify_param(pk_x, pk_y, length);
 | 
			
		||||
    ecc_hal_set_mode(ECC_MODE_VERIFY);
 | 
			
		||||
    ecc_hal_start_calc();
 | 
			
		||||
    while (!ecc_hal_is_calc_finished());
 | 
			
		||||
    result = ecc_hal_read_verify_result();
 | 
			
		||||
 | 
			
		||||
    esp_tinycrypt_release_ecc_hardware();
 | 
			
		||||
 | 
			
		||||
    if (result == 1) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    } else {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar,
 | 
			
		||||
                                uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first)
 | 
			
		||||
{
 | 
			
		||||
    int ret = -1;
 | 
			
		||||
    ecc_mode_t work_mode = verify_first ? ECC_MODE_VERIFY_THEN_POINT_MUL : ECC_MODE_POINT_MUL;
 | 
			
		||||
 | 
			
		||||
    esp_tinycrypt_acquire_ecc_hardware();
 | 
			
		||||
 | 
			
		||||
    ecc_hal_write_mul_param(scalar, p_x, p_y, num_bytes);
 | 
			
		||||
    ecc_hal_set_mode(work_mode);
 | 
			
		||||
    /*
 | 
			
		||||
     * Enable constant-time point multiplication operations for the ECC hardware accelerator,
 | 
			
		||||
     * if supported for the given target. This protects the ECC multiplication operation from
 | 
			
		||||
     * timing attacks. This increases the time taken (by almost 50%) for some point
 | 
			
		||||
     * multiplication operations performed by the ECC hardware accelerator.
 | 
			
		||||
     */
 | 
			
		||||
    ecc_hal_enable_constant_time_point_mul(true);
 | 
			
		||||
    ecc_hal_start_calc();
 | 
			
		||||
 | 
			
		||||
    while (!ecc_hal_is_calc_finished());
 | 
			
		||||
 | 
			
		||||
    ret = ecc_hal_read_mul_result(r_x, r_y, num_bytes);
 | 
			
		||||
 | 
			
		||||
    esp_tinycrypt_release_ecc_hardware();
 | 
			
		||||
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
#endif /* SOC_ECC_SUPPORTED */
 | 
			
		||||
							
								
								
									
										15
									
								
								components/bt/common/tinycrypt/port/esp_tinycrypt_port.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								components/bt/common/tinycrypt/port/esp_tinycrypt_port.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
/*
 | 
			
		||||
 * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 */
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include "soc/soc_caps.h"
 | 
			
		||||
 | 
			
		||||
#if SOC_ECC_SUPPORTED
 | 
			
		||||
int esp_tinycrypt_verify_ecc_point(const uint8_t *pk_x, const uint8_t *pk_y, uint8_t length);
 | 
			
		||||
 | 
			
		||||
int esp_tinycrypt_calc_ecc_mult(const uint8_t *p_x, const uint8_t *p_y, const uint8_t *scalar,
 | 
			
		||||
                                uint8_t *r_x, uint8_t *r_y, uint8_t num_bytes, bool verify_first);
 | 
			
		||||
#endif /* SOC_ECC_SUPPORTED */
 | 
			
		||||
@@ -59,6 +59,9 @@
 | 
			
		||||
#include <tinycrypt/ecc.h>
 | 
			
		||||
#include <tinycrypt/ecc_platform_specific.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include "esp_tinycrypt_port.h"
 | 
			
		||||
 | 
			
		||||
/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
 | 
			
		||||
 * has access to enough entropy in order to feed the PRNG regularly. */
 | 
			
		||||
@@ -639,6 +642,7 @@ void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
 | 
			
		||||
	uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if !SOC_ECC_SUPPORTED
 | 
			
		||||
/* P = (x1, y1) => 2P, (x2, y2) => P' */
 | 
			
		||||
static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
 | 
			
		||||
				uECC_word_t * X2, uECC_word_t * Y2,
 | 
			
		||||
@@ -662,31 +666,6 @@ static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
 | 
			
		||||
	apply_z(X2, Y2, z, curve);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
 | 
			
		||||
	      uECC_word_t * X2, uECC_word_t * Y2,
 | 
			
		||||
	      uECC_Curve curve)
 | 
			
		||||
{
 | 
			
		||||
	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
 | 
			
		||||
	uECC_word_t t5[NUM_ECC_WORDS];
 | 
			
		||||
	wordcount_t num_words = curve->num_words;
 | 
			
		||||
 | 
			
		||||
	uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
 | 
			
		||||
	uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
 | 
			
		||||
	uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
 | 
			
		||||
	uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
 | 
			
		||||
	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
 | 
			
		||||
	uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
 | 
			
		||||
 | 
			
		||||
	uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
 | 
			
		||||
	uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
 | 
			
		||||
	uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
 | 
			
		||||
	uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
 | 
			
		||||
	uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
 | 
			
		||||
	uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
 | 
			
		||||
	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
 | 
			
		||||
 | 
			
		||||
	uECC_vli_set(X2, t5, num_words);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
 | 
			
		||||
   Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
 | 
			
		||||
@@ -729,12 +708,49 @@ static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
 | 
			
		||||
 | 
			
		||||
	uECC_vli_set(X1, t7, num_words);
 | 
			
		||||
}
 | 
			
		||||
#endif /* !SOC_ECC_SUPPORTED */
 | 
			
		||||
 | 
			
		||||
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
 | 
			
		||||
	      uECC_word_t * X2, uECC_word_t * Y2,
 | 
			
		||||
	      uECC_Curve curve)
 | 
			
		||||
{
 | 
			
		||||
	/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
 | 
			
		||||
	uECC_word_t t5[NUM_ECC_WORDS];
 | 
			
		||||
	wordcount_t num_words = curve->num_words;
 | 
			
		||||
 | 
			
		||||
	uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
 | 
			
		||||
	uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
 | 
			
		||||
	uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
 | 
			
		||||
	uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
 | 
			
		||||
	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
 | 
			
		||||
	uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
 | 
			
		||||
 | 
			
		||||
	uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
 | 
			
		||||
	uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
 | 
			
		||||
	uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
 | 
			
		||||
	uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
 | 
			
		||||
	uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
 | 
			
		||||
	uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
 | 
			
		||||
	uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
 | 
			
		||||
 | 
			
		||||
	uECC_vli_set(X2, t5, num_words);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
 | 
			
		||||
		   const uECC_word_t * scalar,
 | 
			
		||||
		   const uECC_word_t * initial_Z,
 | 
			
		||||
		   bitcount_t num_bits, uECC_Curve curve)
 | 
			
		||||
{
 | 
			
		||||
#if SOC_ECC_SUPPORTED
 | 
			
		||||
    wordcount_t num_words = curve->num_words;
 | 
			
		||||
 | 
			
		||||
    /* Only p256r1 is supported currently. */
 | 
			
		||||
    assert (curve == uECC_secp256r1());
 | 
			
		||||
 | 
			
		||||
    esp_tinycrypt_calc_ecc_mult((const uint8_t *)&point[0], (const uint8_t *)&point[num_words],
 | 
			
		||||
                                (uint8_t *)scalar, (uint8_t *)&result[0], (uint8_t *)&result[num_words],
 | 
			
		||||
                                num_words * uECC_WORD_SIZE, false);
 | 
			
		||||
#else
 | 
			
		||||
	/* R0 and R1 */
 | 
			
		||||
	uECC_word_t Rx[2][NUM_ECC_WORDS];
 | 
			
		||||
	uECC_word_t Ry[2][NUM_ECC_WORDS];
 | 
			
		||||
@@ -773,6 +789,7 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
 | 
			
		||||
 | 
			
		||||
	uECC_vli_set(result, Rx[0], num_words);
 | 
			
		||||
	uECC_vli_set(result + num_words, Ry[0], num_words);
 | 
			
		||||
#endif /* SOC_ECC_SUPPORTED */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
 | 
			
		||||
@@ -866,8 +883,6 @@ int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
 | 
			
		||||
 | 
			
		||||
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
 | 
			
		||||
{
 | 
			
		||||
	uECC_word_t tmp1[NUM_ECC_WORDS];
 | 
			
		||||
	uECC_word_t tmp2[NUM_ECC_WORDS];
 | 
			
		||||
	wordcount_t num_words = curve->num_words;
 | 
			
		||||
 | 
			
		||||
	/* The point at infinity is invalid. */
 | 
			
		||||
@@ -881,19 +896,34 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
 | 
			
		||||
		return -2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if SOC_ECC_SUPPORTED
 | 
			
		||||
    /* Only p256r1 is supported currently. */
 | 
			
		||||
    if (curve != uECC_secp256r1()) {
 | 
			
		||||
        return -5;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (esp_tinycrypt_verify_ecc_point((const uint8_t *)&point[0],
 | 
			
		||||
                                       (const uint8_t *)&point[num_words],
 | 
			
		||||
                                       num_words * uECC_WORD_SIZE)) {
 | 
			
		||||
        return -3;
 | 
			
		||||
    }
 | 
			
		||||
#else
 | 
			
		||||
	uECC_word_t tmp1[NUM_ECC_WORDS];
 | 
			
		||||
	uECC_word_t tmp2[NUM_ECC_WORDS];
 | 
			
		||||
 | 
			
		||||
	uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
 | 
			
		||||
	curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
 | 
			
		||||
 | 
			
		||||
	/* Make sure that y^2 == x^3 + ax + b */
 | 
			
		||||
	if (uECC_vli_equal(tmp1, tmp2, num_words) != 0)
 | 
			
		||||
		return -3;
 | 
			
		||||
#endif /* SOC_ECC_SUPPORTED */
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	uECC_word_t _public[NUM_ECC_WORDS * 2];
 | 
			
		||||
 | 
			
		||||
	uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
 | 
			
		||||
@@ -912,7 +942,6 @@ int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve)
 | 
			
		||||
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
 | 
			
		||||
			    uECC_Curve curve)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	uECC_word_t _private[NUM_ECC_WORDS];
 | 
			
		||||
	uECC_word_t _public[NUM_ECC_WORDS * 2];
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user