diff --git a/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h b/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h index cea11ee1ba..26e2bc71a0 100644 --- a/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h +++ b/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h @@ -52,6 +52,35 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, size_t message_len, uint8_t *hmac); +/** + * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW. + * In downstream mode, HMAC calculations performed by peripheral are used internally and not provided back to user. + * + * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calculation. + * The corresponding purpose field of the key block in the efuse must be set to HMAC downstream purpose. + * + * @param token Pre calculated HMAC value of the 32-byte 0x00 using SHA-256 and the known private HMAC key. The key is already + * programmed to a eFuse key block. The key block number is provided as the first parameter to this function. + * + * @return + * * ESP_OK, if the calculation was successful, + * if the calculated HMAC value matches with provided token, + * JTAG will be re-enable otherwise JTAG will remain disabled. + * Return value does not indicate the JTAG status. + * * ESP_FAIL, if the hmac calculation failed or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter. + * * ESP_ERR_INVALID_ARG, invalid input arguments + */ +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token); + +/** + * @brief Disable the JTAG which might be enabled using the HMAC downstream mode. This function just clears the result generated + * by calling esp_hmac_jtag_enable() API. + * + * @return + * * ESP_OK return ESP_OK after writing the HMAC_SET_INVALIDATE_JTAG_REG with value 1. + */ +esp_err_t esp_hmac_jtag_disable(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h b/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h index 8f8677e38c..101dce556b 100644 --- a/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h +++ b/components/esp_hw_support/include/soc/esp32s3/esp_hmac.h @@ -50,6 +50,35 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, size_t message_len, uint8_t *hmac); +/** + * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW. + * In downstream mode, HMAC calculations performed by peripheral are used internally and not provided back to user. + * + * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calculation. + * The corresponding purpose field of the key block in the efuse must be set to HMAC downstream purpose. + * + * @param token Pre calculated HMAC value of the 32-byte 0x00 using SHA-256 and the known private HMAC key. The key is already + * programmed to a eFuse key block. The key block number is provided as the first parameter to this function. + * + * @return + * * ESP_OK, if the calculation was successful, + * if the calculated HMAC value matches with provided token, + * JTAG will be re-enable otherwise JTAG will remain disabled. + * Return value does not indicate the JTAG status. + * * ESP_FAIL, if the hmac calculation failed or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter. + * * ESP_ERR_INVALID_ARG, invalid input arguments + */ +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token); + +/** + * @brief Disable the JTAG which might be enabled using the HMAC downstream mode. This function just clears the result generated + * by calling esp_hmac_jtag_enable() API. + * + * @return + * * ESP_OK return ESP_OK after writing the HMAC_SET_INVALIDATE_JTAG_REG with value 1. + */ +esp_err_t esp_hmac_jtag_disable(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32c3/esp_hmac.c b/components/esp_hw_support/port/esp32c3/esp_hmac.c index 4c6daeac6b..0c85d7429c 100644 --- a/components/esp_hw_support/port/esp32c3/esp_hmac.c +++ b/components/esp_hw_support/port/esp32c3/esp_hmac.c @@ -8,14 +8,20 @@ #include "driver/periph_ctrl.h" #include "esp32c3/rom/hmac.h" #include "esp32c3/rom/ets_sys.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #include "esp_hmac.h" +#include "esp_log.h" #include "esp_crypto_lock.h" +#include "soc/hwcrypto_reg.h" #include "hal/hmac_hal.h" #define SHA256_BLOCK_SZ 64 #define SHA256_PAD_SZ 8 +static const char *TAG = "esp_hmac"; + /** * @brief Apply the HMAC padding without the embedded length. * @@ -122,3 +128,53 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, return ESP_OK; } + +static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) { + return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id; +} + +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) +{ + int ets_status; + esp_err_t err = ESP_OK; + + if ((!token) || (key_id >= HMAC_KEY_MAX)) + return ESP_ERR_INVALID_ARG; + + /* Check if JTAG is permanently disabled by HW Disable eFuse */ + if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG)) { + ESP_LOGE(TAG, "JTAG disabled permanently."); + return ESP_FAIL; + } + + esp_crypto_hmac_lock_acquire(); + + ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id)); + + if (ets_status != ETS_OK) { + // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL + err = ESP_FAIL; + ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err); + } + + ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); + + ets_hmac_disable(); + + esp_crypto_hmac_lock_release(); + + return err; +} + +esp_err_t esp_hmac_jtag_disable() +{ + esp_crypto_hmac_lock_acquire(); + + REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG); + + esp_crypto_hmac_lock_release(); + + ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); + + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32s3/esp_hmac.c b/components/esp_hw_support/port/esp32s3/esp_hmac.c index 54ec775625..73c3193a8d 100644 --- a/components/esp_hw_support/port/esp32s3/esp_hmac.c +++ b/components/esp_hw_support/port/esp32s3/esp_hmac.c @@ -6,16 +6,23 @@ #include #include "driver/periph_ctrl.h" +#include "esp32s3/rom/efuse.h" #include "esp32s3/rom/hmac.h" #include "esp32s3/rom/ets_sys.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #include "esp_hmac.h" +#include "esp_log.h" #include "esp_crypto_lock.h" +#include "soc/hwcrypto_reg.h" #include "hal/hmac_hal.h" #define SHA256_BLOCK_SZ 64 #define SHA256_PAD_SZ 8 +static const char *TAG = "esp_hmac"; + /** * @brief Apply the HMAC padding without the embedded length. * @@ -122,3 +129,53 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, return ESP_OK; } + +static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) { + return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id; +} + +esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token) +{ + int ets_status; + esp_err_t err = ESP_OK; + + if ((!token) || (key_id >= HMAC_KEY_MAX)) + return ESP_ERR_INVALID_ARG; + + /* Check if JTAG is permanently disabled by HW Disable eFuse */ + if (esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG)) { + ESP_LOGE(TAG, "JTAG disabled permanently."); + return ESP_FAIL; + } + + esp_crypto_hmac_lock_acquire(); + + ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id)); + + if (ets_status != ETS_OK) { + // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL + err = ESP_FAIL; + ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err); + } + + ESP_LOGD(TAG, "HMAC computation in downstream mode is completed."); + + ets_hmac_disable(); + + esp_crypto_hmac_lock_release(); + + return err; +} + +esp_err_t esp_hmac_jtag_disable() +{ + esp_crypto_hmac_lock_acquire(); + + REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG); + + esp_crypto_hmac_lock_release(); + + ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); + + return ESP_OK; +} diff --git a/components/esp_hw_support/test/test_hmac.c b/components/esp_hw_support/test/test_hmac.c index fee1f8d4f6..cf49bc19e3 100644 --- a/components/esp_hw_support/test/test_hmac.c +++ b/components/esp_hw_support/test/test_hmac.c @@ -21,16 +21,12 @@ typedef struct { uint8_t result[32]; } hmac_result; -static const esp_efuse_block_t key_block = EFUSE_BLK_KEY0; - -static void setup_keyblock(void) { +static void setup_keyblock(esp_efuse_block_t key_block, esp_efuse_purpose_t purpose) { const uint8_t key_data[32] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31,32 }; - esp_err_t status = esp_efuse_write_key(key_block, - ESP_EFUSE_KEY_PURPOSE_HMAC_UP, - key_data, sizeof(key_data)); + esp_err_t status = esp_efuse_write_key(key_block, purpose, key_data, sizeof(key_data)); if (status == ESP_OK) { printf("Written key!\n"); @@ -41,17 +37,11 @@ static void setup_keyblock(void) { } } -#if !CONFIG_IDF_TARGET_ESP32S3 // TODO: IDF-3664: S3 JTAG enable hasn't been implemented yet -#include "esp32s2/rom/efuse.h" -static const char *TAG = "test_hmac"; TEST_CASE("HMAC 'downstream' JTAG Enable mode", "[hw_crypto]") { int ets_status; - const uint8_t key_data[32] = { - 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31,32 - }; + setup_keyblock(EFUSE_BLK_KEY3, ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG); // Results calculated with Python: // @@ -63,31 +53,13 @@ TEST_CASE("HMAC 'downstream' JTAG Enable mode", "[hw_crypto]") 0x8e, 0x6c, 0x3e, 0x8e, 0x6e, 0x17, 0x62, 0x5c, 0x50, 0xac, 0x66, 0xa9, 0xa8, 0x57, 0x94, 0x9b }; - ets_status = ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY3, - ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG, - key_data, sizeof(key_data)); - - if (ets_status == ESP_OK) { - ESP_LOGI(TAG, "HMAC_DOWN_JTAG key programmed!"); - } else { - ESP_LOGW(TAG, "HMAC_DOWN_JTAG key programming failed, \ - maybe written already. Continuing"); - } - TEST_ASSERT_MESSAGE(ESP_OK == esp_efuse_batch_write_begin(), "Error programming security efuse.\n"); - ets_status = esp_efuse_set_read_protect(ETS_EFUSE_BLOCK_KEY3); - if (ets_status != ESP_OK) { - ESP_LOGW(TAG, "EFUSE_BLOCK read protect setting failed. \ - Not a must prerequisite to run this test case. Continuing"); - } + ets_status = esp_efuse_write_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count); - ets_status = esp_efuse_write_field_bit(ESP_EFUSE_SOFT_DIS_JTAG); - if (ets_status != ESP_OK) { - ESP_LOGI(TAG, "JTAG Disable temporarily failed. \ - May be disabled already. Continuing the test."); - } + TEST_ASSERT_MESSAGE(ets_status == ESP_OK || ets_status == ESP_ERR_EFUSE_CNT_IS_FULL, + "JTAG Disable temporarily failed.\n"); TEST_ASSERT_MESSAGE(ESP_OK == esp_efuse_batch_write_commit(), "Error programming security efuse.\n"); @@ -101,13 +73,12 @@ TEST_CASE("HMAC 'downstream' JTAG Disable", "[hw_crypto]") TEST_ASSERT_EQUAL_HEX32_MESSAGE(ESP_OK, esp_hmac_jtag_disable(), "JTAG should be disabled now, please manually verify"); } -#endif TEST_CASE("HMAC 'upstream' MAC generation with zeroes", "[hw_crypto]") { uint8_t hmac[32]; - setup_keyblock(); + setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP); const uint8_t zeroes[128] = { }; // Produce the HMAC of various numbers of zeroes @@ -202,7 +173,7 @@ TEST_CASE("HMAC 'upstream' MAC generation from data", "[hw_crypto]") { uint8_t hmac[32]; - setup_keyblock(); + setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP); // 257 characters of pseudo-Latin from lipsum.com (not Copyright) const char *message = "Deleniti voluptas explicabo et assumenda. Sed et aliquid minus quis. Praesentium cupiditate quia nemo est. Laboriosam pariatur ut distinctio tenetur. Sunt architecto iure aspernatur soluta ut recusandae. Ut quibusdam occaecati ut qui sit dignissimos eaque.."; @@ -1002,7 +973,8 @@ TEST_CASE("HMAC 'upstream' wait lock", "[hw_crypto]") // 257 characters of pseudo-Latin from lipsum.com (not Copyright) const char *message = "Deleniti voluptas explicabo et assumenda. Sed et aliquid minus quis. Praesentium cupiditate quia nemo est. Laboriosam pariatur ut distinctio tenetur. Sunt architecto iure aspernatur soluta ut recusandae. Ut quibusdam occaecati ut qui sit dignissimos eaque.."; - setup_keyblock(); + setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP); + static const hmac_result results[] = { { .msglen = 255, .result = { 0x59, 0x52, 0x50, 0x4, 0xb6, 0x28, 0xf9, 0x28, 0x7f, 0x6c, 0x37, 0xba, 0xfb, 0xb2, 0x58, 0xe7, 0xa, 0xac, 0x6c, 0x4a, 0xef, 0x66, 0x6, 0x7b, 0x1, 0x1f, 0x4c, 0xa4, 0xe5, 0xe5, 0x29, 0x5d }, diff --git a/components/soc/esp32c3/include/soc/hwcrypto_reg.h b/components/soc/esp32c3/include/soc/hwcrypto_reg.h index 6844627388..474b07faa3 100644 --- a/components/soc/esp32c3/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32c3/include/soc/hwcrypto_reg.h @@ -133,6 +133,7 @@ #define HMAC_SET_MESSAGE_END_REG ((DR_REG_HMAC_BASE) + 0x58) #define HMAC_SET_RESULT_FINISH_REG ((DR_REG_HMAC_BASE) + 0x5c) #define HMAC_SET_INVALIDATE_JTAG_REG ((DR_REG_HMAC_BASE) + 0x60) +#define HMAC_INVALIDATE_JTAG BIT(0) #define HMAC_SET_INVALIDATE_DS_REG ((DR_REG_HMAC_BASE) + 0x64) #define HMAC_QUERY_ERROR_REG ((DR_REG_HMAC_BASE) + 0x68) #define HMAC_QUERY_BUSY_REG ((DR_REG_HMAC_BASE) + 0x6c) diff --git a/components/soc/esp32s3/include/soc/hwcrypto_reg.h b/components/soc/esp32s3/include/soc/hwcrypto_reg.h index 09011285fd..a4b93fb81b 100644 --- a/components/soc/esp32s3/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32s3/include/soc/hwcrypto_reg.h @@ -99,6 +99,7 @@ #define HMAC_SET_MESSAGE_END_REG ((DR_REG_HMAC_BASE) + 0x58) #define HMAC_SET_RESULT_FINISH_REG ((DR_REG_HMAC_BASE) + 0x5c) #define HMAC_SET_INVALIDATE_JTAG_REG ((DR_REG_HMAC_BASE) + 0x60) +#define HMAC_INVALIDATE_JTAG BIT(0) #define HMAC_SET_INVALIDATE_DS_REG ((DR_REG_HMAC_BASE) + 0x64) #define HMAC_QUERY_ERROR_REG ((DR_REG_HMAC_BASE) + 0x68) #define HMAC_QUERY_BUSY_REG ((DR_REG_HMAC_BASE) + 0x6c) @@ -107,6 +108,9 @@ #define HMAC_RDATA_BASE ((DR_REG_HMAC_BASE) + 0xC0) #define HMAC_SET_MESSAGE_PAD_REG ((DR_REG_HMAC_BASE) + 0xF0) #define HMAC_ONE_BLOCK_REG ((DR_REG_HMAC_BASE) + 0xF4) +#define HMAC_SOFT_JTAG_CTRL_REG ((DR_REG_HMAC_BASE) + 0xF8) +#define HMAC_SOFT_JTAG_CTRL BIT((0) +#define HMAC_WR_JTAG_REG ((DR_REG_HMAC_BASE) + 0xFC) /* AES-XTS registers */ #define AES_XTS_PLAIN_BASE ((DR_REG_EXT_MEM_ENC) + 0x00)