Skip to content

Commit

Permalink
feat(hal): Add LL and HAL layer support for deterministic ECDSA
Browse files Browse the repository at this point in the history
  • Loading branch information
Harshal5 committed Mar 29, 2024
1 parent 95fac15 commit cd98dfc
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 18 deletions.
17 changes: 17 additions & 0 deletions components/hal/ecdsa_hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ static void configure_ecdsa_periph(ecdsa_hal_config_t *conf)
if (conf->mode != ECDSA_MODE_EXPORT_PUBKEY) {
ecdsa_ll_set_z_mode(conf->sha_mode);
}

#if SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
ecdsa_ll_set_k_type(conf->sign_type);

if (conf->sign_type == ECDSA_K_TYPE_DETERMINISITIC) {
ecdsa_ll_set_deterministic_loop(conf->loop_number);
}
#endif
}

bool ecdsa_hal_get_operation_result(void)
Expand Down Expand Up @@ -157,3 +165,12 @@ void ecdsa_hal_export_pubkey(ecdsa_hal_config_t *conf, uint8_t *pub_x, uint8_t *
}
}
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */

#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE

bool ecdsa_hal_det_signature_k_check(void)
{
return (ecdsa_ll_check_k_value() == 0);
}

#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
54 changes: 47 additions & 7 deletions components/hal/esp32p4/include/hal/ecdsa_ll.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -10,6 +10,7 @@
#include "hal/assert.h"
#include "soc/ecdsa_reg.h"
#include "soc/hp_sys_clkrst_struct.h"
#include "soc/soc_caps.h"
#include "hal/ecdsa_types.h"

#ifdef __cplusplus
Expand Down Expand Up @@ -216,6 +217,36 @@ static inline void ecdsa_ll_set_z_mode(ecdsa_ll_sha_mode_t mode)
}
}

/**
* @brief Set the signature generation type of ECDSA operation
*
* @param type Type of the ECDSA signature
*/
static inline void ecdsa_ll_set_k_type(ecdsa_sign_type_t type)
{
switch (type) {
case ECDSA_K_TYPE_TRNG:
REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_DETERMINISTIC_K);
break;
case ECDSA_K_TYPE_DETERMINISITIC:
REG_SET_BIT(ECDSA_CONF_REG, ECDSA_DETERMINISTIC_K);
break;
default:
HAL_ASSERT(false && "Unsupported K type");
break;
}
}

/**
* @brief Set the loop number value that is used for deterministic derivation of K
*
* @param loop_number Loop number for deterministic K
*/
static inline void ecdsa_ll_set_deterministic_loop(uint16_t loop_number)
{
REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_DETERMINISTIC_LOOP, loop_number);
}

/**
* @brief Set the stage of ECDSA operation
*
Expand Down Expand Up @@ -303,7 +334,7 @@ static inline bool ecdsa_ll_sha_is_busy(void)
/**
* @brief Write the ECDSA parameter
*
* @param param Parameter to be writen
* @param param Parameter to be written
* @param buf Buffer containing data
* @param len Length of buffer
*/
Expand Down Expand Up @@ -373,18 +404,27 @@ static inline void ecdsa_ll_read_param(ecdsa_ll_param_t param, uint8_t *buf, uin
}

/**
* @brief Get result of ECDSA verification operation
*
* This is only valid for ECDSA verify mode
* @brief Check if the ECDSA operation is successful
*
* @return - 1, if signature verification succeeds
* @return - 1, if ECDSA operation succeeds
* - 0, otherwise
*/
static inline int ecdsa_ll_get_verification_result(void)
static inline int ecdsa_ll_get_operation_result(void)
{
return REG_GET_BIT(ECDSA_RESULT_REG, ECDSA_OPERATION_RESULT);
}

/**
* @brief Check if the k value is greater than the curve order.
*
* @return 0, k value is not greater than the curve order. In this case, the k value is the set k value.
* @return 1, k value is greater than than the curve order. In this case, the k value is the set (k mod n).
*/
static inline int ecdsa_ll_check_k_value(void)
{
return REG_GET_BIT(ECDSA_RESULT_REG, ECDSA_K_VALUE_WARNING);
}

#ifdef __cplusplus
}
#endif
16 changes: 16 additions & 0 deletions components/hal/include/hal/ecdsa_hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ typedef struct {
ecdsa_sha_mode_t sha_mode; /* Source of SHA that needs to be signed */
int efuse_key_blk; /* Efuse block to use as ECDSA key (The purpose of the efuse block must be ECDSA_KEY) */
bool use_km_key; /* Use an ECDSA key from the Key Manager peripheral */
ecdsa_sign_type_t sign_type; /* Type of signature generation */
uint16_t loop_number; /* Determines the loop number value in deterministic derivation algorithm to derive K.
* This member of the config does not need any explicit initialisation as it is
* used and handled internally by the HAL layer.
*/
} ecdsa_hal_config_t;

/**
Expand Down Expand Up @@ -81,6 +86,17 @@ void ecdsa_hal_export_pubkey(ecdsa_hal_config_t *conf, uint8_t *pub_x, uint8_t *
*/
bool ecdsa_hal_get_operation_result(void);

#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
/**
* @brief Check if the K value derived by the peripheral during deterministic signature generation is valid
*
* @return true, if the derived K value is valid
* @return false, if the derived K value is invalid
*/
bool ecdsa_hal_det_signature_k_check(void);

#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */

#ifdef __cplusplus
}
#endif
14 changes: 13 additions & 1 deletion components/hal/include/hal/ecdsa_types.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include "soc/soc_caps.h"

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -34,6 +36,16 @@ typedef enum {
ECDSA_Z_USER_PROVIDED,
} ecdsa_sha_mode_t;

/**
* @brief ECDSA signature type
*/
typedef enum {
ECDSA_K_TYPE_TRNG,
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
ECDSA_K_TYPE_DETERMINISITIC,
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
} ecdsa_sign_type_t;

#ifdef __cplusplus
}
#endif
4 changes: 4 additions & 0 deletions components/hal/test_apps/crypto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ This contains tests for the following features of the crypto peripherals:
- ECDSA P256 signature generation
- ECDSA P192 signature verification
- ECDSA P256 signature verification
- ECDSA P192 export public key
- ECDSA P256 export public key
- ECDSA P192 deterministic signature generation
- ECDSA P256 deterministic signature generation

- AES peripheral
- Block Mode
Expand Down
48 changes: 38 additions & 10 deletions components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,21 @@ static void test_ecdsa_corrupt_data(bool is_p256, uint8_t* sha, uint8_t* r_le, u

}

static void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key)
static void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key, ecdsa_sign_type_t k_type)
{
uint8_t sha_le[32] = {0};
uint8_t zeroes[32] = {0};
uint16_t len;

#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
uint16_t det_loop_number = 1;
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */

ecdsa_hal_config_t conf = {
.mode = ECDSA_MODE_SIGN_GEN,
.sha_mode = ECDSA_Z_USER_PROVIDED,
.use_km_key = use_km_key,
.sign_type = k_type,
};

if (is_p256) {
Expand All @@ -161,23 +166,35 @@ static void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t*
bool process_again = false;

do {
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
if (k_type == ECDSA_K_TYPE_DETERMINISITIC) {
conf.loop_number = det_loop_number++;
}
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */

ecdsa_hal_gen_signature(&conf, sha_le, r_le, s_le, len);

process_again = !ecdsa_hal_get_operation_result()
|| !memcmp(r_le, zeroes, len)
|| !memcmp(s_le, zeroes, len);

#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
if (k_type == ECDSA_K_TYPE_DETERMINISITIC) {
process_again |= !ecdsa_hal_det_signature_k_check();
}
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */

} while(process_again);

ecdsa_disable();
}

static void test_ecdsa_sign_and_verify(bool is_p256, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key)
static void test_ecdsa_sign_and_verify(bool is_p256, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key, ecdsa_sign_type_t k_type)
{
uint8_t r_le[32] = {0};
uint8_t s_le[32] = {0};

test_ecdsa_sign(is_p256, sha, r_le, s_le, use_km_key);
test_ecdsa_sign(is_p256, sha, r_le, s_le, use_km_key, k_type);
TEST_ASSERT_EQUAL(0, test_ecdsa_verify(is_p256, sha, r_le, s_le, pub_x, pub_y));
}

Expand Down Expand Up @@ -253,36 +270,43 @@ TEST(ecdsa, ecdsa_SECP192R1_signature_verification)
TEST_ASSERT_EQUAL(0, test_ecdsa_verify(0, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y));
}


TEST(ecdsa, ecdsa_SECP192R1_sign_and_verify)
{
test_ecdsa_sign_and_verify(0, sha, ecdsa192_pub_x, ecdsa192_pub_y, 0);
test_ecdsa_sign_and_verify(0, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_TRNG);
}


TEST(ecdsa, ecdsa_SECP192R1_corrupt_signature)
{
test_ecdsa_corrupt_data(0, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y);
}


TEST(ecdsa, ecdsa_SECP256R1_signature_verification)
{
TEST_ASSERT_EQUAL(0, test_ecdsa_verify(1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y));
}


TEST(ecdsa, ecdsa_SECP256R1_sign_and_verify)
{
test_ecdsa_sign_and_verify(1, sha, ecdsa256_pub_x, ecdsa256_pub_y, 0);
test_ecdsa_sign_and_verify(1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_TRNG);
}


TEST(ecdsa, ecdsa_SECP256R1_corrupt_signature)
{
test_ecdsa_corrupt_data(1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y);
}

#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
TEST(ecdsa, ecdsa_SECP192R1_det_sign_and_verify)
{
test_ecdsa_sign_and_verify(0, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC);
}

TEST(ecdsa, ecdsa_SECP256R1_det_sign_and_verify)
{
test_ecdsa_sign_and_verify(1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC);
}
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */

#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
TEST(ecdsa, ecdsa_SECP192R1_export_pubkey)
{
Expand All @@ -303,6 +327,10 @@ TEST_GROUP_RUNNER(ecdsa)
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_signature_verification)
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_sign_and_verify)
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_corrupt_signature)
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_det_sign_and_verify)
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_det_sign_and_verify)
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_export_pubkey)
RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_export_pubkey)
Expand Down
4 changes: 4 additions & 0 deletions components/soc/esp32p4/include/soc/Kconfig.soc_caps.in
Original file line number Diff line number Diff line change
Expand Up @@ -1051,6 +1051,10 @@ config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
bool
default y

config SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
bool
default y

config SOC_SDM_GROUPS
int
default 1
Expand Down
1 change: 1 addition & 0 deletions components/soc/esp32p4/include/soc/soc_caps.h
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@

/*--------------------------- ECDSA CAPS ---------------------------------------*/
#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1)
#define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1)

/*-------------------------- Sigma Delta Modulator CAPS -----------------*/
#define SOC_SDM_GROUPS 1U
Expand Down

0 comments on commit cd98dfc

Please sign in to comment.