diff --git a/components/hal/.build-test-rules.yml b/components/hal/.build-test-rules.yml new file mode 100644 index 0000000000..4e02657514 --- /dev/null +++ b/components/hal/.build-test-rules.yml @@ -0,0 +1,9 @@ +# Documentation: .gitlab/ci/README.md#manifest-file-to-control-the-buildtest-apps + +components/hal/test_apps/ecc: + disable: + - if: SOC_ECC_SUPPORTED != 1 + disable_test: + - if: IDF_TARGET == "esp32c2" + temporary: true + reason: C2 ECC peripheral has a bug in ECC point verification, if value of K is zero the verification fails diff --git a/components/hal/ecc_hal.c b/components/hal/ecc_hal.c index c4063e1357..18ca952f8e 100644 --- a/components/hal/ecc_hal.c +++ b/components/hal/ecc_hal.c @@ -5,6 +5,7 @@ */ #include "hal/ecc_hal.h" #include "hal/ecc_ll.h" +#include "soc/soc_caps.h" void ecc_hal_set_mode(ecc_mode_t mode) { @@ -34,6 +35,11 @@ static void clear_param_registers(void) ecc_ll_write_param(ECC_PARAM_PX, buf, sizeof(buf)); ecc_ll_write_param(ECC_PARAM_PY, buf, sizeof(buf)); ecc_ll_write_param(ECC_PARAM_K, buf, sizeof(buf)); +#if SOC_ECC_EXTENDED_MODES_SUPPORTED + ecc_ll_write_param(ECC_PARAM_QX, buf, sizeof(buf)); + ecc_ll_write_param(ECC_PARAM_QY, buf, sizeof(buf)); + ecc_ll_write_param(ECC_PARAM_QZ, buf, sizeof(buf)); +#endif } void ecc_hal_write_mul_param(const uint8_t *k, const uint8_t *px, const uint8_t *py, uint16_t len) @@ -80,3 +86,94 @@ int ecc_hal_read_verify_result(void) { return ecc_ll_get_verification_result(); } + +#if SOC_ECC_EXTENDED_MODES_SUPPORTED + +void ecc_hal_set_mod_base(ecc_mod_base_t base) +{ + ecc_ll_set_mod_base(base); +} + +void ecc_hal_write_jacob_verify_param(const uint8_t *qx, const uint8_t *qy, const uint8_t *qz, uint16_t len) +{ + ecc_curve_t curve = len == 32 ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1; + ecc_ll_set_curve(curve); + + clear_param_registers(); + + ecc_ll_write_param(ECC_PARAM_QX, qx, len); + ecc_ll_write_param(ECC_PARAM_QY, qy, len); + ecc_ll_write_param(ECC_PARAM_QZ, qz, len); +} + +int ecc_hal_read_jacob_mul_result(uint8_t *rx, uint8_t *ry, uint8_t *rz, uint16_t len) +{ + ecc_mode_t mode = ecc_ll_get_mode(); + + if (mode == ECC_MODE_POINT_VERIFY_JACOBIAN_MUL) { + if (!ecc_ll_get_verification_result()) { + memset(rx, 0x0, len); + memset(ry, 0x0, len); + memset(rz, 0x0, len); + return -1; + } + } + + ecc_ll_read_param(ECC_PARAM_QX, rx, len); + ecc_ll_read_param(ECC_PARAM_QY, ry, len); + ecc_ll_read_param(ECC_PARAM_QZ, rz, len); + return 0; +} + +void ecc_hal_write_point_add_param(const uint8_t *px, const uint8_t *py, const uint8_t *qx, const uint8_t *qy, const uint8_t *qz, uint16_t len) +{ + ecc_curve_t curve = len == 32 ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1; + ecc_ll_set_curve(curve); + + clear_param_registers(); + + ecc_ll_write_param(ECC_PARAM_PX, px, len); + ecc_ll_write_param(ECC_PARAM_PY, py, len); + ecc_ll_write_param(ECC_PARAM_QX, qx, len); + ecc_ll_write_param(ECC_PARAM_QY, qy, len); + ecc_ll_write_param(ECC_PARAM_QZ, qz, len); +} + +int ecc_hal_read_point_add_result(uint8_t *rx, uint8_t *ry, uint8_t *rz, uint16_t len, bool read_jacob) +{ + if (read_jacob) { + ecc_ll_read_param(ECC_PARAM_QX, rx, len); + ecc_ll_read_param(ECC_PARAM_QY, ry, len); + ecc_ll_read_param(ECC_PARAM_QZ, rz, len); + } else { + ecc_ll_read_param(ECC_PARAM_PX, rx, len); + ecc_ll_read_param(ECC_PARAM_PY, ry, len); + } + return 0; +} + +void ecc_hal_write_mod_op_param(const uint8_t *a, const uint8_t *b, uint16_t len) +{ + ecc_curve_t curve = len == 32 ? ECC_CURVE_SECP256R1 : ECC_CURVE_SECP192R1; + ecc_ll_set_curve(curve); + + clear_param_registers(); + + ecc_ll_write_param(ECC_PARAM_PX, a, len); + ecc_ll_write_param(ECC_PARAM_PY, b, len); +} + +int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len) +{ + ecc_mode_t mode = ecc_ll_get_mode(); + if (mode == ECC_MODE_MOD_ADD || mode == ECC_MODE_MOD_SUB) { + ecc_ll_read_param(ECC_PARAM_PX, r, len); + } else if (mode == ECC_MODE_MOD_MUL || mode == ECC_MODE_INVERSE_MUL) { + ecc_ll_read_param(ECC_PARAM_PY, r, len); + } else { + return -1; + } + return 0; +} + +#endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */ diff --git a/components/hal/esp32c2/include/hal/ecc_ll.h b/components/hal/esp32c2/include/hal/ecc_ll.h index ce7829a432..8a7c57a04a 100644 --- a/components/hal/esp32c2/include/hal/ecc_ll.h +++ b/components/hal/esp32c2/include/hal/ecc_ll.h @@ -41,9 +41,6 @@ static inline void ecc_ll_set_mode(ecc_mode_t mode) case ECC_MODE_POINT_MUL: REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 0); break; - case ECC_MODE_INVERSE_MUL: - REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 1); - break; case ECC_MODE_VERIFY: REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 2); break; diff --git a/components/hal/esp32c6/include/hal/ecc_ll.h b/components/hal/esp32c6/include/hal/ecc_ll.h index 24e07dff94..9df9655e5d 100644 --- a/components/hal/esp32c6/include/hal/ecc_ll.h +++ b/components/hal/esp32c6/include/hal/ecc_ll.h @@ -41,9 +41,6 @@ static inline void ecc_ll_set_mode(ecc_mode_t mode) case ECC_MODE_POINT_MUL: REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 0); break; - case ECC_MODE_INVERSE_MUL: - REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 1); - break; case ECC_MODE_VERIFY: REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 2); break; diff --git a/components/hal/esp32h2/include/hal/clk_gate_ll.h b/components/hal/esp32h2/include/hal/clk_gate_ll.h index d5da31a927..3ffd6c51e0 100644 --- a/components/hal/esp32h2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32h2/include/hal/clk_gate_ll.h @@ -63,6 +63,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return PCR_AES_CLK_EN; case PERIPH_SHA_MODULE: return PCR_SHA_CLK_EN; + case PERIPH_ECC_MODULE: + return PCR_ECC_CLK_EN; case PERIPH_RSA_MODULE: return PCR_RSA_CLK_EN; case PERIPH_HMAC_MODULE: @@ -136,6 +138,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return PCR_PARL_RST_EN; case PERIPH_TEMPSENSOR_MODULE: return PCR_TSENS_RST_EN; + case PERIPH_ECC_MODULE: + return PCR_ECC_RST_EN; case PERIPH_AES_MODULE: if (enable == true) { // Clear reset on digital signature, otherwise AES unit is held in reset @@ -231,6 +235,8 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) return PCR_AES_CONF_REG; case PERIPH_SHA_MODULE: return PCR_SHA_CONF_REG; + case PERIPH_ECC_MODULE: + return PCR_ECC_CONF_REG; case PERIPH_RSA_MODULE: return PCR_RSA_CONF_REG; case PERIPH_HMAC_MODULE: @@ -292,6 +298,8 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) return PCR_AES_CONF_REG; case PERIPH_SHA_MODULE: return PCR_SHA_CONF_REG; + case PERIPH_ECC_MODULE: + return PCR_ECC_CONF_REG; case PERIPH_RSA_MODULE: return PCR_RSA_CONF_REG; case PERIPH_HMAC_MODULE: diff --git a/components/hal/esp32h2/include/hal/ecc_ll.h b/components/hal/esp32h2/include/hal/ecc_ll.h new file mode 100644 index 0000000000..967d9857ef --- /dev/null +++ b/components/hal/esp32h2/include/hal/ecc_ll.h @@ -0,0 +1,209 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "hal/assert.h" +#include "soc/ecc_mult_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ECC_PARAM_PX = 0x0, + ECC_PARAM_PY, + ECC_PARAM_K, + ECC_PARAM_QX, + ECC_PARAM_QY, + ECC_PARAM_QZ, +} ecc_ll_param_t; + +static inline void ecc_ll_enable_interrupt(void) +{ + REG_SET_FIELD(ECC_MULT_INT_ENA_REG, ECC_MULT_CALC_DONE_INT_ENA, 1); +} + +static inline void ecc_ll_disable_interrupt(void) +{ + REG_SET_FIELD(ECC_MULT_INT_ENA_REG, ECC_MULT_CALC_DONE_INT_ENA, 0); +} + +static inline void ecc_ll_clear_interrupt(void) +{ + REG_SET_FIELD(ECC_MULT_INT_CLR_REG, ECC_MULT_CALC_DONE_INT_CLR, 1); +} + +static inline void ecc_ll_set_mode(ecc_mode_t mode) +{ + switch(mode) { + case ECC_MODE_POINT_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 0); + break; + case ECC_MODE_VERIFY: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 2); + break; + case ECC_MODE_VERIFY_THEN_POINT_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 3); + break; + case ECC_MODE_JACOBIAN_POINT_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 4); + break; + case ECC_MODE_POINT_ADD: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 5); + break; + case ECC_MODE_JACOBIAN_POINT_VERIFY: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 6); + break; + case ECC_MODE_POINT_VERIFY_JACOBIAN_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 7); + break; + case ECC_MODE_MOD_ADD: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 8); + break; + case ECC_MODE_MOD_SUB: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 9); + break; + case ECC_MODE_MOD_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 10); + break; + case ECC_MODE_INVERSE_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 11); + break; + default: + HAL_ASSERT(false && "Unsupported mode"); + break; + } +} + +static inline void ecc_ll_set_curve(ecc_curve_t curve) +{ + switch(curve) { + case ECC_CURVE_SECP256R1: + REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH); + break; + case ECC_CURVE_SECP192R1: + REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + return; + } +} + +static inline void ecc_ll_set_mod_base(ecc_mod_base_t base) +{ + switch(base) { + case ECC_MOD_N: + REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE); + break; + case ECC_MOD_P: + REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + return; + } +} + +static inline void ecc_ll_write_param(ecc_ll_param_t param, const uint8_t *buf, uint16_t len) +{ + uint32_t reg; + uint32_t word; + switch (param) { + case ECC_PARAM_PX: + reg = ECC_MULT_PX_MEM; + break; + case ECC_PARAM_PY: + reg = ECC_MULT_PY_MEM; + break; + case ECC_PARAM_K: + reg = ECC_MULT_K_MEM; + break; + case ECC_PARAM_QX: + reg = ECC_MULT_QX_MEM; + break; + case ECC_PARAM_QY: + reg = ECC_MULT_QY_MEM; + break; + case ECC_PARAM_QZ: + reg = ECC_MULT_QZ_MEM; + break; + default: + HAL_ASSERT(false && "Invalid parameter"); + return; + } + + for (int i = 0; i < len; i += 4) { + memcpy(&word, buf + i, 4); + REG_WRITE(reg + i, word); + } +} + +static inline void ecc_ll_start_calc(void) +{ + REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_START); +} + +static inline int ecc_ll_is_calc_finished(void) +{ + return REG_GET_FIELD(ECC_MULT_INT_RAW_REG, ECC_MULT_CALC_DONE_INT_RAW); +} + +static inline ecc_mode_t ecc_ll_get_mode(void) +{ + return REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE); +} + +static inline int ecc_ll_get_verification_result(void) +{ + return REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_VERIFICATION_RESULT); +} + +static inline ecc_curve_t ecc_ll_get_curve(void) +{ + return REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH); +} + +static inline ecc_mod_base_t ecc_ll_get_mod_base(void) +{ + return REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE); +} + +static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_t len) +{ + uint32_t reg; + switch (param) { + case ECC_PARAM_PX: + reg = ECC_MULT_PX_MEM; + break; + case ECC_PARAM_PY: + reg = ECC_MULT_PY_MEM; + break; + case ECC_PARAM_K: + reg = ECC_MULT_K_MEM; + break; + case ECC_PARAM_QX: + reg = ECC_MULT_QX_MEM; + break; + case ECC_PARAM_QY: + reg = ECC_MULT_QY_MEM; + break; + case ECC_PARAM_QZ: + reg = ECC_MULT_QZ_MEM; + break; + default: + HAL_ASSERT(false && "Invalid parameter"); + return; + } + + memcpy(buf, (void *)reg, len); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/include/hal/ecc_hal.h b/components/hal/include/hal/ecc_hal.h index 6b466718a0..23cfbbbda1 100644 --- a/components/hal/include/hal/ecc_hal.h +++ b/components/hal/include/hal/ecc_hal.h @@ -13,6 +13,8 @@ #pragma once #include "stdint.h" +#include +#include "soc/soc_caps.h" #include "hal/ecc_types.h" #ifdef __cplusplus @@ -96,6 +98,103 @@ int ecc_hal_read_mul_result(uint8_t *rx, uint8_t *ry, uint16_t len); */ int ecc_hal_read_verify_result(void); +#if SOC_ECC_EXTENDED_MODES_SUPPORTED +/** + * @brief Set the mod base value used in MOD operation + * + * @param base Identifier of the base to use + */ +void ecc_hal_set_mod_base(ecc_mod_base_t base); + +/** + * @brief Write parameters for Jacobian verification + * i.e Check whether (Qx, Qy, Qz) is a point on selected curve + * + * @param qx X coordinate of the ECC point in jacobian form + * @param qy Y coordinate of the ECC point in jacobian form + * @param qz Z coordinate of the ECC point in jacobian form + * @param len Length (in bytes) of the ECC point + * - 32 bytes for SECP256R1 + * - 24 bytes for SECP192R1 + */ +void ecc_hal_write_jacob_verify_param(const uint8_t *qx, const uint8_t *qy, const uint8_t *qz, uint16_t len); + +/** + * @brief Read ECC point multiplication result in jacobian form + * + * @param rx X coordinate of the multiplication result + * @param ry Y coordinate of the multiplication result + * @param rz Z coordinate of the multiplication result + * @param len Length (in bytes) of the ECC point + * - 32 for SECP256R1 + * - 24 for SECP192R1 + * + * @return - 0 if the operation was successful + * - -1 if the operation was not successful + * + * In case the operation is not successful, rx, ry, and rz will contain + * all zeros + */ +int ecc_hal_read_jacob_mul_result(uint8_t *rx, uint8_t *ry, uint8_t *rz, uint16_t len); + +/** + * @brief Write parameters for ECC point addition ((Px, Py, 1) + (Qx, Qy, Qz)) + * + * @param px X coordinate of the 1st addend ECC point + * @param py Y coordinate of the 1st addend ECC point + * @param qx X coordinate of the 2nd addend ECC point in jacobian form + * @param qy Y coordinate of the 2nd addend ECC point in jacobian form + * @param qz Z coordinate of the 2nd addend ECC point in jacobian form + * @param len Length (in bytes) of the ECC point + * - 32 bytes for SECP256R1 + * - 24 bytes for SECP192R1 + */ +void ecc_hal_write_point_add_param(const uint8_t *px, const uint8_t *py, const uint8_t *qx, const uint8_t *qy, const uint8_t *qz, uint16_t len); + +/** + * @brief Read ECC point addition result + * + * @param rx X coordinate of the addition result + * @param ry Y coordinate of the addition result + * @param rz Z coordinate of the addition result + * @param len Length (in bytes) of the ECC point + * - 32 for SECP256R1 + * - 24 for SECP192R1 + * @param read_jacob Read the result in Jacobian form + * + * @return - 0 if the operation was successful + * - -1 otherwise + */ +int ecc_hal_read_point_add_result(uint8_t *rx, uint8_t *ry, uint8_t *rz, uint16_t len, bool read_jacob); + +/** + * @brief Write parameters for mod operations + * i.e mod add, mod sub, mod mul, mod inverse mul (or mod division) + * + * @param a Value of operand 1 + * @param b Value of operand 2 + * @param len Length (in bytes) of the ECC point + * - 32 bytes for SECP256R1 + * - 24 bytes for SECP192R1 + */ +void ecc_hal_write_mod_op_param(const uint8_t *a, const uint8_t *b, uint16_t len); + +/** + * @brief Read result of mod operations + * i.e mod add, mod sub, mod mul, mod inverse mul (or mod division) + * + * @param r Result of the mod operation + * @param len Length (in bytes) of the ECC point + * - 32 bytes for SECP256R1 + * - 24 bytes for SECP192R1 + * + * @return - 0 if operation successful + * - -1 otherwise + */ +int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len); + +#endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */ + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/ecc_types.h b/components/hal/include/hal/ecc_types.h index 4abea16f6e..17ce834917 100644 --- a/components/hal/include/hal/ecc_types.h +++ b/components/hal/include/hal/ecc_types.h @@ -6,13 +6,25 @@ #pragma once typedef enum { - ECC_MODE_POINT_MUL = 0x0, // (Rx, Ry) = K * (Px, Py) - ECC_MODE_INVERSE_MUL, // R = K^(-1) * Py - ECC_MODE_VERIFY, // Check if (Px, Py) are points on the curve - ECC_MODE_VERIFY_THEN_POINT_MUL, // Verify and then perform point multiplication + ECC_MODE_POINT_MUL = 0x0, // (Rx, Ry) = K * (Px, Py) + ECC_MODE_INVERSE_MUL, // R = K^(-1) * Py + ECC_MODE_VERIFY, // Check if (Px, Py) are points on the curve + ECC_MODE_VERIFY_THEN_POINT_MUL, // Verify and then perform point multiplication + ECC_MODE_JACOBIAN_POINT_MUL, + ECC_MODE_POINT_ADD, + ECC_MODE_JACOBIAN_POINT_VERIFY, + ECC_MODE_POINT_VERIFY_JACOBIAN_MUL, + ECC_MODE_MOD_ADD, + ECC_MODE_MOD_SUB, + ECC_MODE_MOD_MUL, } ecc_mode_t; typedef enum { ECC_CURVE_SECP192R1 = 0x0, ECC_CURVE_SECP256R1, } ecc_curve_t; + +typedef enum { + ECC_MOD_N, // Order of the curve + ECC_MOD_P, // Prime modulus +} ecc_mod_base_t; diff --git a/components/hal/test_apps/ecc/CMakeLists.txt b/components/hal/test_apps/ecc/CMakeLists.txt new file mode 100644 index 0000000000..5ca38f39c4 --- /dev/null +++ b/components/hal/test_apps/ecc/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.16) + +set(COMPONENTS main) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +project(ecc_test) diff --git a/components/hal/test_apps/ecc/README.md b/components/hal/test_apps/ecc/README.md new file mode 100644 index 0000000000..51c6228f80 --- /dev/null +++ b/components/hal/test_apps/ecc/README.md @@ -0,0 +1,43 @@ +| Supported Targets | ESP32-C2 | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | -------- | + +## ECC peripheral test + +This application contains basic test cases for the ECC peripheral without using any OS functionality or higher abstraction layer. + +This contains tests for the following features of ECC peripheral: + +- ECC Point multiplication for P192 and P256 curve +- ECC Point verification for P192 and P256 curve +- ECC Point verify and multiply for P192 and P256 curve +- ECC Inverse multiplication for P192 and P256 + +If the hardware supports extended work modes then it also tests: +- ECC Jacobian multiplication for P192 and P256 curve +- ECC Jacobian verification for P192 and P256 curve +- ECC Point verification and Jacobian multiplication for P192 and P256 curve +- ECC Point addition for P192 and P256 curve +- Mod addition +- Mod subtraction +- Mod multiplication + +# Building + +```bash +idf.py set-target +idf.py build +``` + +# Running the app manually + +```bash +idf.py flash monitor +``` + +Enter the test that you want to run locally + +# Running tests + +```bash +pytest --target +``` diff --git a/components/hal/test_apps/ecc/main/CMakeLists.txt b/components/hal/test_apps/ecc/main/CMakeLists.txt new file mode 100644 index 0000000000..668d5be1ed --- /dev/null +++ b/components/hal/test_apps/ecc/main/CMakeLists.txt @@ -0,0 +1,6 @@ +set(srcs "app_main.c" + "test_ecc.c") + +idf_component_register(SRCS ${srcs} + REQUIRES unity + WHOLE_ARCHIVE) diff --git a/components/hal/test_apps/ecc/main/app_main.c b/components/hal/test_apps/ecc/main/app_main.c new file mode 100644 index 0000000000..ecde0a6c5d --- /dev/null +++ b/components/hal/test_apps/ecc/main/app_main.c @@ -0,0 +1,13 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" + +void app_main(void) +{ + unity_run_menu(); +} diff --git a/components/hal/test_apps/ecc/main/test_ecc.c b/components/hal/test_apps/ecc/main/test_ecc.c new file mode 100644 index 0000000000..a42ca80fe4 --- /dev/null +++ b/components/hal/test_apps/ecc/main/test_ecc.c @@ -0,0 +1,450 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "esp_log.h" +#include "test_params.h" +#include "soc/soc_caps.h" +#include "hal/ecc_hal.h" +#include "hal/clk_gate_ll.h" + +#include "unity.h" + +#define _DEBUG_ 0 +#define SOC_ECC_SUPPORT_POINT_MULT 1 +#define SOC_ECC_SUPPORT_POINT_VERIFY 1 + +#if SOC_ECC_EXTENDED_MODES_SUPPORTED +#define SOC_ECC_SUPPORT_POINT_DIVISION 1 +#define SOC_ECC_SUPPORT_JACOB_POINT_MULT 1 +#define SOC_ECC_SUPPORT_JACOB_POINT_VERIFY 1 +#define SOC_ECC_SUPPORT_POINT_ADDITION 1 +#define SOC_ECC_SUPPORT_MOD_ADD 1 +#define SOC_ECC_SUPPORT_MOD_SUB 1 +#define SOC_ECC_SUPPORT_MOD_MUL 1 +#endif + +static void ecc_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) +{ + /* When the size is 24 bytes, it should be padded with 0 bytes*/ + memset(le_point, 0x0, 32); + + for (int i = 0; i < len; i++) { + le_point[i] = be_point[len - i - 1]; + } +} + +static void ecc_enable_and_reset(void) +{ + periph_ll_enable_clk_clear_rst(PERIPH_ECC_MODULE); +} + +#if SOC_ECC_SUPPORT_POINT_MULT +static void ecc_point_mul(const uint8_t *k_le, const uint8_t *x_le, const uint8_t *y_le, uint8_t len, bool verify_first, + uint8_t *res_x_le, uint8_t *res_y_le) +{ + ecc_enable_and_reset(); + + ecc_hal_write_mul_param(k_le, x_le, y_le, len); + if (verify_first) { + ecc_hal_set_mode(ECC_MODE_VERIFY_THEN_POINT_MUL); + } else { + ecc_hal_set_mode(ECC_MODE_POINT_MUL); + } + ecc_hal_start_calc(); + + while (!ecc_hal_is_calc_finished()) { + ; + } + + ecc_hal_read_mul_result(res_x_le, res_y_le, len); +} + +static void test_ecc_point_mul_inner(bool verify_first) +{ + uint8_t scalar_le[32]; + uint8_t x_le[32]; + uint8_t y_le[32]; + + /* P256 */ + ecc_be_to_le(ecc_p256_scalar, scalar_le, 32); + ecc_be_to_le(ecc_p256_point_x, x_le, 32); + ecc_be_to_le(ecc_p256_point_y, y_le, 32); + + uint8_t x_res_le[32]; + uint8_t y_res_le[32]; + + ecc_point_mul(scalar_le, x_le, y_le, 32, verify_first, x_res_le, y_res_le); + + uint8_t x_mul_le[32]; + uint8_t y_mul_le[32]; + + ecc_be_to_le(ecc_p256_mul_res_x, x_mul_le, 32); + ecc_be_to_le(ecc_p256_mul_res_y, y_mul_le, 32); + +#if _DEBUG_ + ESP_LOG_BUFFER_HEX("Expected X:", x_mul_le, 32); + ESP_LOG_BUFFER_HEX("Got X:", x_res_le, 32); + + ESP_LOG_BUFFER_HEX("Expected Y:", y_mul_le, 32); + ESP_LOG_BUFFER_HEX("Got Y:", y_res_le, 32); +#endif + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, 32, "X coordinate of P256 point multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_mul_le, y_res_le, 32, "Y coordinate of P256 point multiplication "); + + memset(x_res_le, 0x0, 32); + memset(y_res_le, 0x0, 32); + memset(x_mul_le, 0x0, 32); + memset(y_mul_le, 0x0, 32); + + /* P192 */ + ecc_be_to_le(ecc_p192_scalar, scalar_le, 24); + ecc_be_to_le(ecc_p192_point_x, x_le, 24); + ecc_be_to_le(ecc_p192_point_y, y_le, 24); + + ecc_point_mul(scalar_le, x_le, y_le, 24, verify_first, x_res_le, y_res_le); + + ecc_be_to_le(ecc_p192_mul_res_x, x_mul_le, 24); + ecc_be_to_le(ecc_p192_mul_res_y, y_mul_le, 24); + +#if _DEBUG_ + ESP_LOG_BUFFER_HEX("Expected X:", x_mul_le, 32); + ESP_LOG_BUFFER_HEX("Got X:", x_res_le, 32); + + ESP_LOG_BUFFER_HEX("Expected Y:", y_mul_le, 32); + ESP_LOG_BUFFER_HEX("Got Y:", y_res_le, 32); +#endif + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_mul_le, x_res_le, 24, "X coordinate of P192 point multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_mul_le, y_res_le, 24, "Y coordinate of P192 point multiplication "); +} + +TEST_CASE("ECC point multiplication on SECP192R1 and SECP256R1", "[ecc][hal]") +{ + test_ecc_point_mul_inner(false); +} +#endif + +#if SOC_ECC_SUPPORT_POINT_VERIFY +static int ecc_point_verify(const uint8_t *x_le, const uint8_t *y_le, uint8_t len) +{ + ecc_enable_and_reset(); + + ecc_hal_write_verify_param(x_le, y_le, len); + ecc_hal_set_mode(ECC_MODE_VERIFY); + ecc_hal_start_calc(); + + while (!ecc_hal_is_calc_finished()) { + ; + } + + return ecc_hal_read_verify_result(); +} + +TEST_CASE("ECC point verification on SECP192R1 and SECP256R1", "[ecc][hal]") +{ + int res; + uint8_t x_le[32]; + uint8_t y_le[32]; + + /* P256 */ + ecc_be_to_le(ecc_p256_point_x, x_le, 32); + ecc_be_to_le(ecc_p256_point_y, y_le, 32); + + // Case 1: Correct point on curve + res = ecc_point_verify(x_le, y_le, 32); + TEST_ASSERT_EQUAL(1, res); + + // Case 2: Modify one byte from the point + x_le[6] = x_le[6] ^ 0xFF; + res = ecc_point_verify(x_le, y_le, 32); + TEST_ASSERT_EQUAL(0, res); + + /* P192 */ + ecc_be_to_le(ecc_p192_point_x, x_le, 24); + ecc_be_to_le(ecc_p192_point_y, y_le, 24); + + // Case 1: Correct point on curve + res = ecc_point_verify(x_le, y_le, 24); + TEST_ASSERT_EQUAL(1, res); + + // Case 2: Modify one byte from the point + x_le[6] = x_le[6] ^ 0xFF; + res = ecc_point_verify(x_le, y_le, 24); + TEST_ASSERT_EQUAL(0, res); +} +#endif + +#if SOC_ECC_SUPPORT_POINT_MULT && SOC_ECC_SUPPORT_POINT_VERIFY +TEST_CASE("ECC point verification and multiplication on SECP192R1 and SECP256R1", "[ecc][hal]") +{ + test_ecc_point_mul_inner(true); +} +#endif + +#if SOC_ECC_SUPPORT_POINT_DIVISION +static void ecc_point_inv_mul(const uint8_t *num_le, const uint8_t *deno_le, uint8_t len, uint8_t *res_le) +{ + ecc_enable_and_reset(); + + uint8_t zero[32] = {0}; + ecc_hal_write_mul_param(zero, num_le, deno_le, len); + + ecc_hal_set_mode(ECC_MODE_INVERSE_MUL); + + ecc_hal_start_calc(); + + while (!ecc_hal_is_calc_finished()) { + ; + } + + ecc_hal_read_mul_result(zero, res_le, len); +} + +TEST_CASE("ECC inverse multiplication (or mod division) using SECP192R1 and SECP256R1 order of curve", "[ecc][hal]") +{ + uint8_t res[32] = {0}; + ecc_point_inv_mul(ecc256_num, ecc256_den, 32, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_inv_mul_res, res, 32, "P256 Inverse multiplication (or Mod division)"); + + ecc_point_inv_mul(ecc192_num, ecc192_den, 24, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_inv_mul_res, res, 24, "P192 Inverse multiplication (or Mod division)"); +} +#endif + +#if SOC_ECC_SUPPORT_JACOB_POINT_MULT +static void ecc_jacob_mul(uint8_t *k_le, uint8_t *x_le, uint8_t *y_le, uint8_t len, bool verify_first, + uint8_t *res_x_le, uint8_t *res_y_le, uint8_t *res_z_le) +{ + ecc_enable_and_reset(); + + ecc_hal_write_mul_param(k_le, x_le, y_le, len); + if (verify_first) { + ecc_hal_set_mode(ECC_MODE_POINT_VERIFY_JACOBIAN_MUL); + } else { + ecc_hal_set_mode(ECC_MODE_JACOBIAN_POINT_MUL); + } + ecc_hal_start_calc(); + + while (!ecc_hal_is_calc_finished()) { + ; + } + + ecc_hal_read_jacob_mul_result(res_x_le, res_y_le, res_z_le, len); +} + +static void test_ecc_jacob_mul_inner(bool verify_first) +{ + uint8_t scalar_le[32]; + uint8_t x_le[32]; + uint8_t y_le[32]; + + /* P256 */ + ecc_be_to_le(ecc_p256_scalar, scalar_le, 32); + ecc_be_to_le(ecc_p256_point_x, x_le, 32); + ecc_be_to_le(ecc_p256_point_y, y_le, 32); + + uint8_t x_res_le[32]; + uint8_t y_res_le[32]; + uint8_t z_res_le[32]; + + ecc_jacob_mul(scalar_le, x_le, y_le, 32, verify_first, x_res_le, y_res_le, z_res_le); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p256_jacob_mul_res_x_le, x_res_le, 32, "X coordinate of P256 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p256_jacob_mul_res_y_le, y_res_le, 32, "Y coordinate of P256 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p256_jacob_mul_res_z_le, z_res_le, 32, "Z coordinate of P256 point jacobian multiplication "); + + memset(x_res_le, 0x0, 32); + memset(y_res_le, 0x0, 32); + memset(z_res_le, 0x0, 32); + + /* P192 */ + ecc_be_to_le(ecc_p192_scalar, scalar_le, 24); + ecc_be_to_le(ecc_p192_point_x, x_le, 24); + ecc_be_to_le(ecc_p192_point_y, y_le, 24); + + ecc_jacob_mul(scalar_le, x_le, y_le, 24, verify_first, x_res_le, y_res_le, z_res_le); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p192_jacob_mul_res_x_le, x_res_le, 24, "X coordinate of P192 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p192_jacob_mul_res_y_le, y_res_le, 24, "Y coordinate of P192 point jacobian multiplication "); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc_p192_jacob_mul_res_z_le, z_res_le, 24, "Z coordinate of P192 point jacobian multiplication "); +} + +TEST_CASE("ECC jacobian point multiplication on SECP192R1 and SECP256R1", "[ecc][hal]") +{ + test_ecc_jacob_mul_inner(false); +} +#endif + +#if SOC_ECC_SUPPORT_JACOB_POINT_VERIFY +static int ecc_jacob_verify(const uint8_t *x_le, const uint8_t *y_le, const uint8_t *z_le, uint8_t len) +{ + ecc_enable_and_reset(); + + ecc_hal_write_jacob_verify_param(x_le, y_le, z_le, len); + + ecc_hal_set_mode(ECC_MODE_JACOBIAN_POINT_VERIFY); + + ecc_hal_start_calc(); + + while (!ecc_hal_is_calc_finished()) { + ; + } + + return ecc_hal_read_verify_result(); +} + +TEST_CASE("ECC jacobian point verification on SECP192R1 and SECP256R1", "[ecc][hal]") +{ + int res; + /* P256 */ + res = ecc_jacob_verify(ecc_p256_jacob_mul_res_x_le, ecc_p256_jacob_mul_res_y_le, ecc_p256_jacob_mul_res_z_le, 32); + TEST_ASSERT_EQUAL(1, res); + + /* P192 */ + res = ecc_jacob_verify(ecc_p192_jacob_mul_res_x_le, ecc_p192_jacob_mul_res_y_le, ecc_p192_jacob_mul_res_z_le, 24); + TEST_ASSERT_EQUAL(1, res); +} +#endif + +#if SOC_ECC_SUPPORT_JACOB_POINT_MULT && SOC_ECC_SUPPORT_JACOB_POINT_VERIFY +TEST_CASE("ECC point verification and Jacobian point multiplication on SECP192R1 and SECP256R1", "[ecc][hal]") +{ + test_ecc_jacob_mul_inner(true); +} +#endif + +#if SOC_ECC_SUPPORT_POINT_ADDITION +static void ecc_point_addition(uint8_t *px_le, uint8_t *py_le, uint8_t *qx_le, uint8_t *qy_le, uint8_t *qz_le, + uint8_t len, bool jacob_output, + uint8_t *x_res_le, uint8_t *y_res_le, uint8_t *z_res_le) +{ + ecc_enable_and_reset(); + + ecc_hal_write_point_add_param(px_le, py_le, qx_le, qy_le, qz_le, len); + + ecc_hal_set_mode(ECC_MODE_POINT_ADD); + + ecc_hal_start_calc(); + + while (!ecc_hal_is_calc_finished()) { + ; + } + + ecc_hal_read_point_add_result(x_res_le, y_res_le, z_res_le, len, jacob_output); +} + +TEST_CASE("ECC point addition on SECP192R1 and SECP256R1", "[ecc][hal]") +{ + uint8_t scalar_le[32] = {0}; + uint8_t x_le[32] = {0}; + uint8_t y_le[32] = {0}; + uint8_t z_le[32] = {0}; + + /* P256 + * R = 2 * P + */ + ecc_be_to_le(ecc_p256_point_x, x_le, 32); + ecc_be_to_le(ecc_p256_point_y, y_le, 32); + + scalar_le[0] = 0x2; + + uint8_t x_res_le[32]; + uint8_t y_res_le[32]; + uint8_t z_res_le[32]; + + ecc_jacob_mul(scalar_le, x_le, y_le, 32, 0, x_res_le, y_res_le, z_res_le); + + uint8_t x_add_le[32]; + uint8_t y_add_le[32]; + uint8_t z_add_le[32]; + + z_le[0] = 0x1; + + ecc_point_addition(x_le, y_le, x_le, y_le, z_le, 32, 1, x_add_le, y_add_le, z_add_le); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_add_le, x_res_le, 32, "X coordinate of P256 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_add_le, y_res_le, 32, "Y coordinate of P256 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(z_add_le, z_res_le, 32, "Z coordinate of P256 point addition"); + + /* P192 + * R = 2 * P + */ + ecc_be_to_le(ecc_p192_point_x, x_le, 24); + ecc_be_to_le(ecc_p192_point_y, y_le, 24); + + scalar_le[0] = 0x2; + + ecc_jacob_mul(scalar_le, x_le, y_le, 24, 0, x_res_le, y_res_le, z_res_le); + + z_le[0] = 0x1; + + ecc_point_addition(x_le, y_le, x_le, y_le, z_le, 24, 1, x_add_le, y_add_le, z_add_le); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(x_add_le, x_res_le, 24, "X coordinate of P192 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(y_add_le, y_res_le, 24, "Y coordinate of P192 point addition"); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(z_add_le, z_res_le, 24, "Z coordinate of P192 point addition"); +} +#endif + +#if SOC_ECC_SUPPORT_MOD_ADD || SOC_ECC_SUPPORT_MOD_SUB || SOC_ECC_SUPPORT_MOD_MUL +static void ecc_mod_op(ecc_mode_t mode, const uint8_t *a, const uint8_t *b, uint8_t len, uint8_t *res_le) +{ + ecc_enable_and_reset(); + + ecc_hal_write_mod_op_param(a, b, len); + + ecc_hal_set_mode(mode); + + ecc_hal_start_calc(); + + while (!ecc_hal_is_calc_finished()) { + ; + } + + ecc_hal_read_mod_op_result(res_le, len); +} +#endif + +#if SOC_ECC_SUPPORT_MOD_ADD +TEST_CASE("ECC mod addition using SECP192R1 and SECP256R1 order of curve", "[ecc][hal]") +{ + uint8_t res[32] = {0}; + ecc_mod_op(ECC_MODE_MOD_ADD, ecc256_x, ecc256_y, 32, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_add_res, res, 32, "P256 mod addition"); + + ecc_mod_op(ECC_MODE_MOD_ADD, ecc192_x, ecc192_y, 24, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_add_res, res, 24, "P192 mod addition"); +} +#endif + +#if SOC_ECC_SUPPORT_MOD_SUB +TEST_CASE("ECC mod subtraction using SECP192R1 and SECP256R1 order of curve", "[ecc][hal]") +{ + uint8_t res[32] = {0}; + ecc_mod_op(ECC_MODE_MOD_SUB, ecc256_x, ecc256_y, 32, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_sub_res, res, 32, "P256 mod subtraction"); + + ecc_mod_op(ECC_MODE_MOD_SUB, ecc192_x, ecc192_y, 24, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_sub_res, res, 24, "P192 mod subtraction"); +} +#endif + +#if SOC_ECC_SUPPORT_MOD_MUL +TEST_CASE("ECC mod multiplication using SECP192R1 and SECP256R1 order of curve", "[ecc][hal]") +{ + uint8_t res[32] = {0}; + ecc_mod_op(ECC_MODE_MOD_MUL, ecc256_x, ecc256_y, 32, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc256_mul_res, res, 32, "P256 mod multiplication"); + + ecc_mod_op(ECC_MODE_MOD_MUL, ecc192_x, ecc192_y, 24, res); + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(ecc192_mul_res, res, 24, "P192 mod multiplication"); +} +#endif diff --git a/components/hal/test_apps/ecc/main/test_params.h b/components/hal/test_apps/ecc/main/test_params.h new file mode 100644 index 0000000000..77aecedda9 --- /dev/null +++ b/components/hal/test_apps/ecc/main/test_params.h @@ -0,0 +1,222 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +static const uint8_t ecc_p192_point_x[] = { + 0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, + 0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00, + 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12 +}; + +static const uint8_t ecc_p192_point_y[] = { + 0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78, + 0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5, + 0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11 +}; + +static const uint8_t ecc_p192_scalar[] = { + 0x6f, 0x18, 0x34, 0xeb, 0x16, 0xb7, 0xac, 0x9f, + 0x3c, 0x77, 0x71, 0xb3, 0x02, 0x30, 0x70, 0x48, + 0x75, 0x87, 0xbb, 0x6f, 0x80, 0x34, 0x8d, 0x5e +}; + +static const uint8_t ecc_p192_mul_res_x[] = { + 0x3F, 0xEE, 0x6F, 0x1F, 0x99, 0xDC, 0xCB, 0x78, + 0xB7, 0x47, 0x1C, 0x2A, 0xF5, 0xA0, 0xAC, 0xE6, + 0xEC, 0x24, 0x82, 0x37, 0x6C, 0xC0, 0x27, 0xC5, +}; + +static const uint8_t ecc_p192_mul_res_y[] = { + 0xDF, 0xF3, 0x9E, 0x76, 0x24, 0xF4, 0xF6, 0xB4, + 0xF0, 0x0A, 0x18, 0xE1, 0x0B, 0xD2, 0xD9, 0x83, + 0xE8, 0x29, 0x5E, 0xD9, 0x46, 0x54, 0xC3, 0xE1 +}; + +static const uint8_t ecc_p256_point_x[] = { + 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, + 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, + 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, + 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 +}; + +static const uint8_t ecc_p256_point_y[] = { + 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, + 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, + 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, + 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 +}; + +static const uint8_t ecc_p256_scalar[] = { + 0xB2, 0xC5, 0x9E, 0x92, 0x64, 0xCD, 0x5F, 0x66, + 0x9E, 0xC8, 0x83, 0x6D, 0x99, 0x61, 0x18, 0x72, + 0xC8, 0x60, 0x83, 0x1E, 0xE5, 0x79, 0xCC, 0x73, + 0xA9, 0xB4, 0x74, 0x85, 0x70, 0x11, 0x2D, 0xA2, +}; + +static const uint8_t ecc_p256_mul_res_x[] = { + 0x26, 0x1A, 0x0F, 0xBD, 0xA5, 0xE5, 0x1E, 0xE7, + 0xB3, 0xC3, 0xB7, 0x09, 0xD1, 0x4A, 0x7A, 0x2A, + 0x16, 0x69, 0x4B, 0xAF, 0x76, 0x5C, 0xD4, 0x0E, + 0x93, 0x57, 0xB8, 0x67, 0xF9, 0xA1, 0xE5, 0xE8 +}; + +static const uint8_t ecc_p256_mul_res_y[] = { + 0xA0, 0xF4, 0x2E, 0x62, 0x36, 0x25, 0x9F, 0xE0, + 0xF2, 0xA0, 0x41, 0x42, 0xD2, 0x95, 0x89, 0x41, + 0x38, 0xF0, 0xEB, 0x6E, 0xA7, 0x96, 0x29, 0x24, + 0xC7, 0xD4, 0x0C, 0x90, 0xA1, 0xC9, 0xD3, 0x3A +}; + +static const uint8_t ecc_p256_jacob_mul_res_x_le[] = { + 0x9C, 0x79, 0x11, 0x19, 0x1B, 0x49, 0xAB, 0x51, + 0x5C, 0x57, 0x71, 0x7B, 0x14, 0x4A, 0xD4, 0xA8, + 0x70, 0xEA, 0x0E, 0x7D, 0x3A, 0x20, 0x94, 0x03, + 0xA3, 0x9E, 0x2D, 0x95, 0xAD, 0xC1, 0xD0, 0xB4 +}; + +static const uint8_t ecc_p256_jacob_mul_res_y_le[] = { + 0xA4, 0x46, 0xBA, 0x75, 0x20, 0x19, 0xF2, 0xDB, + 0x5D, 0x99, 0x3F, 0xE3, 0x8C, 0xDF, 0xFE, 0x6E, + 0xD9, 0x1F, 0x63, 0x63, 0xDB, 0x6F, 0xD6, 0xAF, + 0xE8, 0x5E, 0xED, 0x4F, 0x99, 0x05, 0x3C, 0x5A +}; + +static const uint8_t ecc_p256_jacob_mul_res_z_le[] = { + 0x7C, 0x7A, 0xB4, 0xBA, 0xD4, 0xB7, 0x86, 0xEB, + 0xDA, 0x79, 0x0F, 0xA1, 0xA8, 0xAB, 0x6A, 0xAB, + 0xCB, 0xF9, 0x05, 0xBE, 0x5C, 0x90, 0x15, 0x0E, + 0xA7, 0x2D, 0x6F, 0x0C, 0xAE, 0x68, 0xBB, 0x4A +}; + +static const uint8_t ecc_p192_jacob_mul_res_x_le[] = { + 0xE1, 0xB5, 0x3E, 0xB2, 0x85, 0xCA, 0x93, 0x25, + 0xCA, 0xB1, 0x6B, 0xCF, 0xC3, 0x6E, 0xB7, 0x66, + 0x9C, 0xB4, 0x83, 0x98, 0x8E, 0x7A, 0xA1, 0x55 +}; + +static const uint8_t ecc_p192_jacob_mul_res_y_le[] = { + 0xC7, 0xD3, 0xEA, 0x97, 0x87, 0x92, 0x98, 0xE5, + 0xA5, 0x30, 0xB1, 0xE4, 0x92, 0xD9, 0x71, 0x11, + 0x16, 0x63, 0x37, 0x56, 0x8D, 0xB1, 0xD4, 0xB8 +}; + +static const uint8_t ecc_p192_jacob_mul_res_z_le[] = { + 0xD1, 0xA5, 0x8D, 0x76, 0x17, 0x7B, 0xB3, 0x9F, + 0x0D, 0x78, 0x1B, 0x36, 0x59, 0x18, 0xD0, 0xF1, + 0x38, 0x8C, 0xD7, 0x13, 0xCB, 0x7A, 0x9B, 0xBF +}; + +/* Little endian */ +static const uint8_t ecc256_num[] = { + 0x20, 0x56, 0x14, 0xB6, 0xAF, 0x94, 0xA0, 0xB6, + 0x0C, 0xDF, 0x13, 0x1A, 0xE6, 0xBF, 0x57, 0x87, + 0xF1, 0x02, 0x73, 0x96, 0x53, 0x1A, 0xBC, 0xA9, + 0x0F, 0x5E, 0xA1, 0xFC, 0x0E, 0xFC, 0x9D, 0x9B +}; + +/* Little endian */ +static const uint8_t ecc256_den[] = { + 0x54, 0x3B, 0x11, 0x78, 0xC4, 0xCA, 0x52, 0xFD, + 0xCC, 0x89, 0x51, 0x0F, 0xFE, 0x7D, 0x37, 0x83, + 0x81, 0xD5, 0x2E, 0x58, 0x42, 0xF9, 0x4F, 0x19, + 0x9A, 0x79, 0x78, 0x98, 0xFA, 0x95, 0x40, 0x2E +}; + +/* Little endian */ +static const uint8_t ecc256_inv_mul_res[] = { + 0x33, 0xF3, 0x55, 0x3B, 0x46, 0x8A, 0x13, 0xC0, + 0x1D, 0x7E, 0x41, 0xA6, 0xFF, 0x53, 0xFD, 0x78, + 0xD5, 0xC0, 0xE5, 0x9F, 0x78, 0xD1, 0x86, 0x66, + 0x77, 0x3C, 0x6E, 0xEF, 0x58, 0xF6, 0x29, 0x34 +}; + +static const uint8_t ecc192_num[] = { + 0xBA, 0x0F, 0x2C, 0xD8, 0xBE, 0xCC, 0x2D, 0xD3, + 0xD5, 0x74, 0xBD, 0x8C, 0xF3, 0x3E, 0x3B, 0x7A, + 0xA4, 0xD0, 0x71, 0xEC, 0x85, 0xF6, 0x70, 0x00 +}; + +static const uint8_t ecc192_den[] = { + 0x15, 0xF9, 0x20, 0xD8, 0x46, 0x5C, 0x03, 0x97, + 0x4A, 0x10, 0xEF, 0x8A, 0xFB, 0x12, 0x2E, 0x65, + 0x6E, 0xD6, 0x79, 0x1E, 0x65, 0x6F, 0x3E, 0x64 +}; + +static const uint8_t ecc192_inv_mul_res[] = { + 0x6B, 0xB3, 0x6B, 0x2B, 0x56, 0x6A, 0xE5, 0xF7, + 0x75, 0x82, 0xF0, 0xCC, 0x93, 0x63, 0x40, 0xF8, + 0xEF, 0x35, 0x2A, 0xAF, 0xBD, 0x56, 0xE9, 0x29 +}; + +/* Little endian */ +static const uint8_t ecc256_x[] = { + 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4, + 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77, + 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8, + 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B +}; + +/* Little endian */ +static const uint8_t ecc256_y[] = { + 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB, + 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B, + 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E, + 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F +}; + +/* Little endian */ +static const uint8_t ecc256_add_res[] = { + 0x8B, 0x14, 0x58, 0x10, 0xAE, 0x79, 0x57, 0xC0, + 0x6F, 0x92, 0x1C, 0x99, 0xD8, 0xB0, 0xD1, 0xA2, + 0x08, 0xDF, 0xB3, 0xDF, 0x2F, 0xD2, 0xA4, 0x87, + 0xE3, 0xC1, 0x46, 0xDF, 0xD5, 0x14, 0xFB, 0xBA +}; + +/* Little endian */ +static const uint8_t ecc256_sub_res[] = { + 0xA1, 0x70, 0xD9, 0xA0, 0xDD, 0xF8, 0xEA, 0x28, + 0xD2, 0xD4, 0xB9, 0xC2, 0x29, 0x4A, 0x35, 0x4B, + 0xDC, 0xA2, 0x94, 0xE7, 0x9A, 0xFB, 0xD4, 0x69, + 0xAC, 0xC2, 0x11, 0xE3, 0x0F, 0x8F, 0x34, 0x1B +}; + +/* Little endian */ +static const uint8_t ecc256_mul_res[] = { + 0x18, 0x4D, 0xCE, 0xCC, 0x1A, 0xA8, 0xEC, 0x72, + 0xD7, 0x31, 0xDA, 0x41, 0x8C, 0x75, 0x6B, 0xF1, + 0x2A, 0x2E, 0x5B, 0x53, 0x8D, 0xCA, 0x79, 0x61, + 0x6B, 0x46, 0xF9, 0x2E, 0x27, 0xB5, 0x43, 0x15 +}; + +static const uint8_t ecc192_x[] = { + 0x1A, 0x80, 0xA1, 0x5F, 0x1F, 0xB7, 0x59, 0x1B, + 0x9F, 0xD7, 0xFB, 0xAE, 0xA9, 0xF9, 0x1E, 0xBA, + 0x67, 0xAE, 0x57, 0xB7, 0x27, 0x80, 0x9E, 0x1A +}; + +static const uint8_t ecc192_y[] = { + 0x59, 0xC6, 0x3D, 0xD3, 0xD7, 0xDF, 0xA3, 0x44, + 0x7C, 0x75, 0x52, 0xB4, 0x42, 0xF3, 0xFC, 0xA6, + 0x0F, 0xA8, 0x8A, 0x8D, 0x1F, 0xA3, 0xDF, 0x54 +}; + +static const uint8_t ecc192_add_res[] = { + 0x73, 0x46, 0xDF, 0x32, 0xF7, 0x96, 0xFD, 0x5F, + 0x1B, 0x4D, 0x4E, 0x63, 0xEC, 0xEC, 0x1B, 0x61, + 0x77, 0x56, 0xE2, 0x44, 0x47, 0x23, 0x7E, 0x6F +}; + +static const uint8_t ecc192_sub_res[] = { + 0xF2, 0xE1, 0x35, 0x41, 0xF9, 0xA0, 0x21, 0xEB, + 0x58, 0x5A, 0x88, 0x94, 0x66, 0x06, 0x22, 0x13, + 0x58, 0x06, 0xCD, 0x29, 0x08, 0xDD, 0xBE, 0xC5 +}; + +static const uint8_t ecc192_mul_res[] = { + 0xB5, 0xB9, 0xFF, 0xBC, 0x52, 0xC8, 0xB8, 0x36, + 0x8C, 0xFB, 0xA5, 0xCE, 0x1E, 0x7B, 0xE6, 0xF3, + 0x8F, 0x79, 0x71, 0xCF, 0xD6, 0xF3, 0x41, 0xE6 +}; diff --git a/components/hal/test_apps/ecc/pytest_ecc.py b/components/hal/test_apps/ecc/pytest_ecc.py new file mode 100644 index 0000000000..4210c9aa88 --- /dev/null +++ b/components/hal/test_apps/ecc/pytest_ecc.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +import pytest +from pytest_embedded import Dut + + +@pytest.mark.esp32c6 +@pytest.mark.esp32h2 +@pytest.mark.generic +def test_ecc(dut: Dut) -> None: + dut.run_all_single_board_cases() diff --git a/components/hal/test_apps/ecc/sdkconfig.defaults b/components/hal/test_apps/ecc/sdkconfig.defaults new file mode 100644 index 0000000000..a4ba403514 --- /dev/null +++ b/components/hal/test_apps/ecc/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=n diff --git a/components/idf_test/include/esp32h2/idf_performance_target.h b/components/idf_test/include/esp32h2/idf_performance_target.h index 07f23711eb..33f100aa54 100644 --- a/components/idf_test/include/esp32h2/idf_performance_target.h +++ b/components/idf_test/include/esp32h2/idf_performance_target.h @@ -18,6 +18,14 @@ #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PUBLIC_OP 45000 #define IDF_PERFORMANCE_MAX_RSA_3072KEY_PRIVATE_OP 670000 +#define IDF_PERFORMANCE_MAX_ECP_P192_POINT_MULTIPLY_OP 11000 +#define IDF_PERFORMANCE_MAX_ECP_P192_POINT_VERIFY_OP 300 +#define IDF_PERFORMANCE_MAX_ECP_P256_POINT_MULTIPLY_OP 19000 +#define IDF_PERFORMANCE_MAX_ECP_P256_POINT_VERIFY_OP 300 + +#define IDF_PERFORMANCE_MAX_ECDSA_P192_VERIFY_OP 44000 +#define IDF_PERFORMANCE_MAX_ECDSA_P256_VERIFY_OP 67000 + #define IDF_PERFORMANCE_MAX_SPI_CLK_FREQ 26*1000*1000 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING 28 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_POLLING_NO_DMA 24 diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index eea30cc633..d342077dd8 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -131,6 +131,14 @@ config SOC_DIG_SIGN_SUPPORTED bool default y +config SOC_ECC_SUPPORTED + bool + default y + +config SOC_ECC_EXTENDED_MODES_SUPPORTED + bool + default y + config SOC_FLASH_ENC_SUPPORTED bool default y diff --git a/components/soc/esp32h2/include/soc/ecc_mult_reg.h b/components/soc/esp32h2/include/soc/ecc_mult_reg.h index 4060ce107d..5d7fa6c1c3 100644 --- a/components/soc/esp32h2/include/soc/ecc_mult_reg.h +++ b/components/soc/esp32h2/include/soc/ecc_mult_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -162,6 +162,24 @@ extern "C" { #define ECC_MULT_PY_MEM (DR_REG_ECC_MULT_BASE + 0x140) #define ECC_MULT_PY_MEM_SIZE_BYTES 32 +/** ECC_MULT_QX_MEM register + * The memory that stores Qx. + */ +#define ECC_MULT_QX_MEM (DR_REG_ECC_MULT_BASE + 0x160) +#define ECC_MULT_QX_MEM_SIZE_BYTES 32 + +/** ECC_MULT_QY_MEM register + * The memory that stores Qy. + */ +#define ECC_MULT_QY_MEM (DR_REG_ECC_MULT_BASE + 0x180) +#define ECC_MULT_QY_MEM_SIZE_BYTES 32 + +/** ECC_MULT_QZ_MEM register + * The memory that stores Qz. + */ +#define ECC_MULT_QZ_MEM (DR_REG_ECC_MULT_BASE + 0x1A0) +#define ECC_MULT_QZ_MEM_SIZE_BYTES 32 + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32h2/include/soc/ecc_mult_struct.h b/components/soc/esp32h2/include/soc/ecc_mult_struct.h index dd71b8b917..f1596693a8 100644 --- a/components/soc/esp32h2/include/soc/ecc_mult_struct.h +++ b/components/soc/esp32h2/include/soc/ecc_mult_struct.h @@ -1,11 +1,13 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include +#include "esp_assert.h" + #ifdef __cplusplus extern "C" { #endif @@ -151,12 +153,15 @@ typedef struct { volatile uint32_t k[8]; volatile uint32_t px[8]; volatile uint32_t py[8]; + volatile uint32_t qx[8]; + volatile uint32_t qy[8]; + volatile uint32_t qz[8]; } ecc_mult_dev_t; extern ecc_mult_dev_t ECC; #ifndef __cplusplus -_Static_assert(sizeof(ecc_mult_dev_t) == 0x160, "Invalid size of ecc_mult_dev_t structure"); +_Static_assert(sizeof(ecc_mult_dev_t) == 0x1C0, "Invalid size of ecc_mult_dev_t structure"); #endif #ifdef __cplusplus diff --git a/components/soc/esp32h2/include/soc/periph_defs.h b/components/soc/esp32h2/include/soc/periph_defs.h index 502ca39bd4..2f1789caba 100644 --- a/components/soc/esp32h2/include/soc/periph_defs.h +++ b/components/soc/esp32h2/include/soc/periph_defs.h @@ -35,6 +35,7 @@ typedef enum { PERIPH_RSA_MODULE, PERIPH_AES_MODULE, PERIPH_SHA_MODULE, + PERIPH_ECC_MODULE, PERIPH_HMAC_MODULE, PERIPH_DS_MODULE, PERIPH_GDMA_MODULE, diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index d24600c4ca..abb72b6a14 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -58,6 +58,8 @@ #define SOC_SHA_SUPPORTED 1 #define SOC_HMAC_SUPPORTED 1 #define SOC_DIG_SIGN_SUPPORTED 1 +#define SOC_ECC_SUPPORTED 1 +#define SOC_ECC_EXTENDED_MODES_SUPPORTED 1 #define SOC_FLASH_ENC_SUPPORTED 1 #define SOC_SECURE_BOOT_SUPPORTED 1 #define SOC_BOD_SUPPORTED 1