Merge branch 'feature/hmac_downstream_jtag' into 'master'

hmac: Added Downstream JTAG enable mode for esp32c3 and esp32s3

Closes IDF-3664

See merge request espressif/esp-idf!15034
This commit is contained in:
Mahavir Jain 2021-09-07 03:34:22 +00:00
commit 0c027cf4d2
11 changed files with 281 additions and 46 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -6,16 +6,22 @@
#include <string.h>
#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;
}

View File

@ -47,7 +47,8 @@ esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
{
esp_err_t err;
int ets_status;
esp_err_t err = ESP_OK;
if ((!token) || (key_id >= HMAC_KEY_MAX))
return ESP_ERR_INVALID_ARG;
@ -69,10 +70,10 @@ esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
REG_WRITE(DPORT_JTAG_CTRL_0_REG + i, __builtin_bswap32(key_word));
}
err = ets_hmac_calculate_downstream(convert_key_type(key_id), ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG);
if (err != ETS_OK) {
ESP_LOGE(TAG, "HMAC downstream JTAG enable mode setting failed.");
return ESP_FAIL;
ets_status = ets_hmac_calculate_downstream(convert_key_type(key_id), ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG);
if (ets_status != ETS_OK) {
err = ESP_FAIL;
ESP_LOGE(TAG, "HMAC downstream JTAG enable mode setting failed. (%d)", err);
}
ESP_LOGD(TAG, "HMAC computation in downstream mode is completed.");
@ -81,7 +82,7 @@ esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
esp_crypto_dma_lock_release();
return ESP_OK;
return err;
}
esp_err_t esp_hmac_jtag_disable()

View File

@ -6,16 +6,23 @@
#include <string.h>
#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;
}

View File

@ -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 },

View File

@ -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)

View File

@ -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)

View File

@ -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)