From fd5a7df404cbda926a79a0af1ff9797bdca1da7f Mon Sep 17 00:00:00 2001 From: Sachin Parekh Date: Fri, 3 Sep 2021 17:07:26 +0530 Subject: [PATCH] esp32h2: Replicated HMAC JTAG downstream enable mode implementation --- .../include/soc/esp32h2/esp_hmac.h | 29 +++++++++ .../esp_hw_support/port/esp32h2/esp_hmac.c | 60 ++++++++++++++++++- .../soc/esp32h2/include/soc/hwcrypto_reg.h | 1 + 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h b/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h index cea11ee1ba..26e2bc71a0 100644 --- a/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h +++ b/components/esp_hw_support/include/soc/esp32h2/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/port/esp32h2/esp_hmac.c b/components/esp_hw_support/port/esp32h2/esp_hmac.c index d655dbf9d3..84340d8164 100644 --- a/components/esp_hw_support/port/esp32h2/esp_hmac.c +++ b/components/esp_hw_support/port/esp32h2/esp_hmac.c @@ -6,16 +6,22 @@ #include #include "driver/periph_ctrl.h" -#include "esp32h2/rom/hmac.h" -#include "esp32h2/rom/ets_sys.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/soc/esp32h2/include/soc/hwcrypto_reg.h b/components/soc/esp32h2/include/soc/hwcrypto_reg.h index 6844627388..474b07faa3 100644 --- a/components/soc/esp32h2/include/soc/hwcrypto_reg.h +++ b/components/soc/esp32h2/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)