Merge branch 'refactor/merge_esp_hmac_headers_into_one' into 'master'

esp_hw_support: Merge HMAC layer into one

Closes IDF-3803

See merge request espressif/esp-idf!18742
This commit is contained in:
Aditya Patwardhan
2022-10-27 16:39:32 +08:00
32 changed files with 175 additions and 1101 deletions

View File

@@ -18,6 +18,9 @@
#if __has_include("esp_dpp.h") #if __has_include("esp_dpp.h")
#include "esp_dpp.h" #include "esp_dpp.h"
#endif #endif
#if __has_include("esp_ds_err.h")
#include "esp_ds_err.h"
#endif
#if __has_include("esp_efuse.h") #if __has_include("esp_efuse.h")
#include "esp_efuse.h" #include "esp_efuse.h"
#endif #endif
@@ -69,9 +72,6 @@
#if __has_include("nvs.h") #if __has_include("nvs.h")
#include "nvs.h" #include "nvs.h"
#endif #endif
#if __has_include("soc/esp32s2/esp_ds.h")
#include "soc/esp32s2/esp_ds.h"
#endif
#if __has_include("spi_flash_mmap.h") #if __has_include("spi_flash_mmap.h")
#include "spi_flash_mmap.h" #include "spi_flash_mmap.h"
#endif #endif
@@ -767,7 +767,7 @@ static const esp_err_msg_t esp_err_msg_table[] = {
ERR_TBL_IT(ESP_ERR_HW_CRYPTO_BASE), /* 49152 0xc000 Starting number of HW cryptography ERR_TBL_IT(ESP_ERR_HW_CRYPTO_BASE), /* 49152 0xc000 Starting number of HW cryptography
module error codes */ module error codes */
# endif # endif
// components/esp_hw_support/include/soc/esp32s2/esp_ds.h // components/esp_hw_support/include/esp_ds_err.h
# ifdef ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL # ifdef ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL
ERR_TBL_IT(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL), /* 49153 0xc001 HMAC peripheral problem */ ERR_TBL_IT(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL), /* 49153 0xc001 HMAC peripheral problem */
# endif # endif

View File

@@ -45,6 +45,10 @@ if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "port/${target}/systimer.c") list(APPEND srcs "port/${target}/systimer.c")
endif() endif()
if(CONFIG_SOC_HMAC_SUPPORTED)
list(APPEND srcs "esp_hmac.c")
endif()
# ESP32C6-TODO # ESP32C6-TODO
if(CONFIG_IDF_TARGET_ESP32C6) if(CONFIG_IDF_TARGET_ESP32C6)
list(REMOVE_ITEM srcs list(REMOVE_ITEM srcs

View File

@@ -1,41 +1,51 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#include <string.h> #include <string.h>
#include "esp_private/periph_ctrl.h" #include "rom/efuse.h"
#include "esp32s3/rom/efuse.h" #include "rom/hmac.h"
#include "esp32s3/rom/hmac.h" #include "rom/ets_sys.h"
#include "esp32s3/rom/ets_sys.h"
#include "esp_efuse.h" #include "esp_efuse.h"
#include "esp_efuse_table.h" #include "esp_efuse_table.h"
#include "esp_hmac.h" #include "esp_hmac.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_crypto_lock.h" #include "esp_crypto_lock.h"
#include "soc/hwcrypto_reg.h" #include "soc/hwcrypto_reg.h"
#include "soc/system_reg.h"
#if !CONFIG_IDF_TARGET_ESP32S2
#include "hal/hmac_hal.h" #include "hal/hmac_hal.h"
#include "esp_private/periph_ctrl.h"
#endif
#define SHA256_BLOCK_SZ 64 #define SHA256_BLOCK_SZ 64
#define SHA256_PAD_SZ 8 #define SHA256_PAD_SZ 8
#if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2)
#define JTAG_STATUS_BIT ESP_EFUSE_HARD_DIS_JTAG
#else
/* For ESP32C3, ESP32C6, ESP32H2 */
#define JTAG_STATUS_BIT ESP_EFUSE_DIS_PAD_JTAG
#endif
static const char *TAG = "esp_hmac"; static const char *TAG = "esp_hmac";
#if !CONFIG_IDF_TARGET_ESP32S2
/** /**
* @brief Apply the HMAC padding without the embedded length. * @brief Apply the HMAC padding without the embedded length.
* *
* @note This function does not check the data length, it is the responsibility of the other functions in this * @note This function does not check the data length, it is the responsibility of the other functions in this
* module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in. * module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in.
* Otherwise, this function has undefined behavior. * Otherwise, this function has undefined behavior.
* Note however, that for the actual HMAC implementation on ESP32S3, the length also needs to be applied at the end * Note however, that for the actual HMAC implementation, the length also needs to be applied at the end
* of the block. This function alone deosn't do that. * of the block. This function alone deosn't do that.
*/ */
static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len) static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len)
{ {
memcpy(block, data, data_len); memcpy(block, data, data_len);
// Apply a one bit, followed by zero bits (refer to the ESP32S3 TRM). // Apply a one bit, followed by zero bits (refer to the TRM of respective target).
block[data_len] = 0x80; block[data_len] = 0x80;
bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1); bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1);
} }
@@ -143,7 +153,7 @@ esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
/* Check if JTAG is permanently disabled by HW Disable eFuse */ /* Check if JTAG is permanently disabled by HW Disable eFuse */
if (esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG)) { if (esp_efuse_read_field_bit(JTAG_STATUS_BIT)) {
ESP_LOGE(TAG, "JTAG disabled permanently."); ESP_LOGE(TAG, "JTAG disabled permanently.");
return ESP_FAIL; return ESP_FAIL;
} }
@@ -170,12 +180,94 @@ esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
esp_err_t esp_hmac_jtag_disable() esp_err_t esp_hmac_jtag_disable()
{ {
esp_crypto_hmac_lock_acquire(); esp_crypto_hmac_lock_acquire();
REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1);
REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG);
esp_crypto_hmac_lock_release(); esp_crypto_hmac_lock_release();
ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled."); ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled.");
return ESP_OK; return ESP_OK;
} }
#else /* !CONFIG_IDF_TARGET_ESP32S2 */
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_calculate(hmac_key_id_t key_id,
const void *message,
size_t message_len,
uint8_t *hmac)
{
int hmac_ret;
if (!message || !hmac) return ESP_ERR_INVALID_ARG;
if (key_id >= HMAC_KEY_MAX) return ESP_ERR_INVALID_ARG;
esp_crypto_dma_lock_acquire();
ets_hmac_enable();
hmac_ret = ets_hmac_calculate_message(convert_key_type(key_id), message, message_len, hmac);
ets_hmac_disable();
esp_crypto_dma_lock_release();
if (hmac_ret != 0) {
return ESP_FAIL;
} else {
return ESP_OK;
}
}
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_dma_lock_acquire();
ets_hmac_enable();
/* Token updating into HMAC module. */
for (int i = 0; i < 32; i += 4) {
uint32_t key_word;
memcpy(&key_word, &token[i], 4);
REG_WRITE(DPORT_JTAG_CTRL_0_REG + i, __builtin_bswap32(key_word));
}
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.");
ets_hmac_disable();
esp_crypto_dma_lock_release();
return err;
}
esp_err_t esp_hmac_jtag_disable()
{
esp_crypto_dma_lock_acquire();
REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1);
esp_crypto_dma_lock_release();
ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled.");
return ESP_OK;
}
#endif /* CONFIG_IDF_TARGET_ESP32S2*/

View File

@@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL (ESP_ERR_HW_CRYPTO_BASE + 0x1) /*!< HMAC peripheral problem */
#define ESP_ERR_HW_CRYPTO_DS_INVALID_KEY (ESP_ERR_HW_CRYPTO_BASE + 0x2) /*!< given HMAC key isn't correct,
HMAC peripheral problem */
#define ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST (ESP_ERR_HW_CRYPTO_BASE + 0x4) /*!< message digest check failed,
result is invalid */
#define ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING (ESP_ERR_HW_CRYPTO_BASE + 0x5) /*!< padding check failed, but result
is produced anyway and can be read*/
#ifdef __cplusplus
}
#endif

View File

@@ -4,11 +4,15 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#ifndef _ESP_HMAC_H_ #pragma once
#define _ESP_HMAC_H_
#include <stdbool.h> #include <stdbool.h>
#include "esp_err.h" #include "esp_err.h"
#include "soc/soc_caps.h"
#if !SOC_HMAC_SUPPORTED && !CI_HEADER_CHECK
#error "HMAC peripheral is not supported for the selected target"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -32,7 +36,7 @@ typedef enum {
* Calculate the HMAC of a given message. * Calculate the HMAC of a given message.
* *
* Calculate the HMAC \c hmac of a given message \c message with length \c message_len. * Calculate the HMAC \c hmac of a given message \c message with length \c message_len.
* SHA256 is used for the calculation (fixed on ESP32S2). * SHA256 is used for the calculation.
* *
* @note Uses the HMAC peripheral in "upstream" mode. * @note Uses the HMAC peripheral in "upstream" mode.
* *
@@ -40,7 +44,7 @@ typedef enum {
* The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value. * The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
* @param message the message for which to calculate the HMAC * @param message the message for which to calculate the HMAC
* @param message_len message length * @param message_len message length
* return ESP_ERR_INVALID_STATE if unsuccessful * return ESP_ERR_INVALID_STATE if unsuccessful
* @param [out] hmac the hmac result; the buffer behind the provided pointer must be a writeable buffer of 32 bytes * @param [out] hmac the hmac result; the buffer behind the provided pointer must be a writeable buffer of 32 bytes
* *
* @return * @return
@@ -49,9 +53,9 @@ typedef enum {
* * ESP_FAIL, if the hmac calculation failed * * ESP_FAIL, if the hmac calculation failed
*/ */
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id, esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
const void *message, const void *message,
size_t message_len, size_t message_len,
uint8_t *hmac); uint8_t *hmac);
/** /**
* @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW. * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW.
@@ -88,5 +92,3 @@ esp_err_t esp_hmac_jtag_disable(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif // _ESP_HMAC_H_

View File

@@ -8,19 +8,12 @@
#include "esp_hmac.h" #include "esp_hmac.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_ds_err.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define ESP32C3_ERR_HW_CRYPTO_DS_HMAC_FAIL ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */
#define ESP32C3_ERR_HW_CRYPTO_DS_INVALID_KEY ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct,
HMAC peripheral problem */
#define ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed,
result is invalid */
#define ESP32C3_ERR_HW_CRYPTO_DS_INVALID_PADDING ESP_ERR_HW_CRYPTO_BASE + 0x5 /*!< padding check failed, but result
is produced anyway and can be read*/
#define ESP_DS_IV_BIT_LEN 128 #define ESP_DS_IV_BIT_LEN 128
#define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8) #define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8)
#define ESP_DS_SIGNATURE_MAX_BIT_LEN 3072 #define ESP_DS_SIGNATURE_MAX_BIT_LEN 3072

View File

@@ -8,19 +8,12 @@
#include "esp_hmac.h" #include "esp_hmac.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_ds_err.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define ESP32C6_ERR_HW_CRYPTO_DS_HMAC_FAIL ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */
#define ESP32C6_ERR_HW_CRYPTO_DS_INVALID_KEY ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct,
HMAC peripheral problem */
#define ESP32C6_ERR_HW_CRYPTO_DS_INVALID_DIGEST ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed,
result is invalid */
#define ESP32C6_ERR_HW_CRYPTO_DS_INVALID_PADDING ESP_ERR_HW_CRYPTO_BASE + 0x5 /*!< padding check failed, but result
is produced anyway and can be read*/
#define ESP_DS_IV_BIT_LEN 128 #define ESP_DS_IV_BIT_LEN 128
#define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8) #define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8)
#define ESP_DS_SIGNATURE_MAX_BIT_LEN 3072 #define ESP_DS_SIGNATURE_MAX_BIT_LEN 3072

View File

@@ -1,92 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ESP_HMAC_H_
#define _ESP_HMAC_H_
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* The possible efuse keys for the HMAC peripheral
*/
typedef enum {
HMAC_KEY0 = 0,
HMAC_KEY1,
HMAC_KEY2,
HMAC_KEY3,
HMAC_KEY4,
HMAC_KEY5,
HMAC_KEY_MAX
} hmac_key_id_t;
/**
* @brief
* Calculate the HMAC of a given message.
*
* Calculate the HMAC \c hmac of a given message \c message with length \c message_len.
* SHA256 is used for the calculation (fixed on ESP32S2).
*
* @note Uses the HMAC peripheral in "upstream" mode.
*
* @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calcuation.
* The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
* @param message the message for which to calculate the HMAC
* @param message_len message length
* return ESP_ERR_INVALID_STATE if unsuccessful
* @param [out] hmac the hmac result; the buffer behind the provided pointer must be a writeable buffer of 32 bytes
*
* @return
* * ESP_OK, if the calculation was successful,
* * ESP_ERR_INVALID_ARG if message or hmac is a nullptr or if key_id out of range
* * ESP_FAIL, if the hmac calculation failed
*/
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
const void *message,
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 key_purpose of the key_id matches to HMAC downstread mode,
* The API returns success even if calculated HMAC does not match with the provided token.
* However, The JTAG will be re-enabled only if the calculated HMAC value matches with provided token,
* otherwise JTAG will remain disabled.
* * ESP_FAIL, if the key_purpose of the key_id is not set to HMAC downstream purpose
* or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter.
* * ESP_ERR_INVALID_ARG, invalid input arguments
*
* @note Return value of the API does not indicate the JTAG status.
*/
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
#endif // _ESP_HMAC_H_

View File

@@ -8,18 +8,12 @@
#include "esp_hmac.h" #include "esp_hmac.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_ds_err.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define ESP32H2_ERR_HW_CRYPTO_DS_HMAC_FAIL ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */
#define ESP32H2_ERR_HW_CRYPTO_DS_INVALID_KEY ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct,
HMAC peripheral problem */
#define ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed,
result is invalid */
#define ESP32H2_ERR_HW_CRYPTO_DS_INVALID_PADDING ESP_ERR_HW_CRYPTO_BASE + 0x5 /*!< padding check failed, but result
is produced anyway and can be read*/
#define ESP_DS_IV_BIT_LEN 128 #define ESP_DS_IV_BIT_LEN 128
#define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8) #define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8)

View File

@@ -1,92 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ESP_HMAC_H_
#define _ESP_HMAC_H_
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* The possible efuse keys for the HMAC peripheral
*/
typedef enum {
HMAC_KEY0 = 0,
HMAC_KEY1,
HMAC_KEY2,
HMAC_KEY3,
HMAC_KEY4,
HMAC_KEY5,
HMAC_KEY_MAX
} hmac_key_id_t;
/**
* @brief
* Calculate the HMAC of a given message.
*
* Calculate the HMAC \c hmac of a given message \c message with length \c message_len.
* SHA256 is used for the calculation (fixed on ESP32S2).
*
* @note Uses the HMAC peripheral in "upstream" mode.
*
* @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calcuation.
* The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
* @param message the message for which to calculate the HMAC
* @param message_len message length
* return ESP_ERR_INVALID_STATE if unsuccessful
* @param [out] hmac the hmac result; the buffer behind the provided pointer must be a writeable buffer of 32 bytes
*
* @return
* * ESP_OK, if the calculation was successful,
* * ESP_ERR_INVALID_ARG if message or hmac is a nullptr or if key_id out of range
* * ESP_FAIL, if the hmac calculation failed
*/
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
const void *message,
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 key_purpose of the key_id matches to HMAC downstread mode,
* The API returns success even if calculated HMAC does not match with the provided token.
* However, The JTAG will be re-enabled only if the calculated HMAC value matches with provided token,
* otherwise JTAG will remain disabled.
* * ESP_FAIL, if the key_purpose of the key_id is not set to HMAC downstream purpose
* or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter.
* * ESP_ERR_INVALID_ARG, invalid input arguments
*
* @note Return value of the API does not indicate the JTAG status.
*/
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
#endif // _ESP_HMAC_H_

View File

@@ -8,19 +8,12 @@
#include "esp_hmac.h" #include "esp_hmac.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_ds_err.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */
#define ESP_ERR_HW_CRYPTO_DS_INVALID_KEY ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct,
HMAC peripheral problem */
#define ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed,
result is invalid */
#define ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING ESP_ERR_HW_CRYPTO_BASE + 0x5 /*!< padding check failed, but result
is produced anyway and can be read*/
#define ESP_DS_IV_LEN 16 #define ESP_DS_IV_LEN 16
/* Length of parameter 'C' stored in flash */ /* Length of parameter 'C' stored in flash */

View File

@@ -1,95 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _ESP_HMAC_H_
#define _ESP_HMAC_H_
#include "esp_err.h"
#include "stdbool.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* The possible efuse keys for the HMAC peripheral
*/
typedef enum {
HMAC_KEY0 = 0,
HMAC_KEY1,
HMAC_KEY2,
HMAC_KEY3,
HMAC_KEY4,
HMAC_KEY5,
HMAC_KEY_MAX
} hmac_key_id_t;
/**
* @brief
* Calculate the HMAC of a given message.
*
* Calculate the HMAC \c hmac of a given message \c message with length \c message_len.
* SHA256 is used for the calculation (fixed on ESP32S2).
*
* @note Uses the HMAC peripheral in "upstream" mode.
*
* @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calcuation.
* The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
* @param message the message for which to calculate the HMAC
* @param message_len message length
* return ESP_ERR_INVALID_STATE if unsuccessful
* @param [out] hmac the hmac result; the buffer behind the provided pointer must be a writeable buffer of 32 bytes
*
* @return
* * ESP_OK, if the calculation was successful,
* * ESP_ERR_INVALID_ARG if message or hmac is a nullptr or if key_id out of range
* * ESP_FAIL, if the hmac calculation failed
*/
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
const void *message,
size_t message_len,
uint8_t *hmac);
/**
* @brief
* Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disable by HW.
* In downstream mode HMAC calculations perfomred by peripheral 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 key_purpose of the key_id matches to HMAC downstread mode,
* The API returns success even if calculated HMAC does not match with the provided token.
* However, The JTAG will be re-enabled only if the calculated HMAC value matches with provided token,
* otherwise JTAG will remain disabled.
* * ESP_FAIL, if the key_purpose of the key_id is not set to HMAC downstream purpose
* or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter.
* * ESP_ERR_INVALID_ARG, invalid input arguments
*
* @note Return value of the API does not indicate the JTAG status.
*/
esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id,
const uint8_t *token);
/**
* @brief
* Disable the JTAG which might be enable using the HMAC downstream mode. This function just clear the result generated by
* JTAG key 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
#endif // _ESP_HMAC_H_

View File

@@ -10,19 +10,12 @@
#include "esp_hmac.h" #include "esp_hmac.h"
#include "esp_err.h" #include "esp_err.h"
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "esp_ds_err.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#define ESP32S3_ERR_HW_CRYPTO_DS_HMAC_FAIL ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */
#define ESP32S3_ERR_HW_CRYPTO_DS_INVALID_KEY ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct,
HMAC peripheral problem */
#define ESP32S3_ERR_HW_CRYPTO_DS_INVALID_DIGEST ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed,
result is invalid */
#define ESP32S3_ERR_HW_CRYPTO_DS_INVALID_PADDING ESP_ERR_HW_CRYPTO_BASE + 0x5 /*!< padding check failed, but result
is produced anyway and can be read*/
#define ESP_DS_IV_LEN 16 #define ESP_DS_IV_LEN 16
/* Length of parameter 'C' stored in flash */ /* Length of parameter 'C' stored in flash */

View File

@@ -1,87 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* The possible efuse keys for the HMAC peripheral
*/
typedef enum {
HMAC_KEY0 = 0,
HMAC_KEY1,
HMAC_KEY2,
HMAC_KEY3,
HMAC_KEY4,
HMAC_KEY5,
HMAC_KEY_MAX
} hmac_key_id_t;
/**
* @brief
* Calculate the HMAC of a given message.
*
* Calculate the HMAC \c hmac of a given message \c message with length \c message_len.
* SHA256 is used for the calculation (fixed on ESP32S3).
*
* @note Uses the HMAC peripheral in "upstream" mode.
*
* @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calcuation.
* The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
* @param message the message for which to calculate the HMAC
* @param message_len message length
* @param [out] hmac the hmac result; the buffer behind the provided pointer must be a writeable buffer of 32 bytes
*
* @return
* * ESP_OK, if the calculation was successful,
* * ESP_ERR_INVALID_ARG if message or hmac is a nullptr or if key_id out of range
* * ESP_FAIL, if the hmac calculation failed
*/
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
const void *message,
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 key_purpose of the key_id matches to HMAC downstread mode,
* The API returns success even if calculated HMAC does not match with the provided token.
* However, The JTAG will be re-enabled only if the calculated HMAC value matches with provided token,
* otherwise JTAG will remain disabled.
* * ESP_FAIL, if the key_purpose of the key_id is not set to HMAC downstream purpose
* or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter.
* * ESP_ERR_INVALID_ARG, invalid input arguments
*
* @note Return value of the API does not indicate the JTAG status.
*/
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,8 +8,7 @@ set(srcs "rtc_clk_init.c"
) )
if(NOT BOOTLOADER_BUILD) if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "esp_hmac.c" list(APPEND srcs "esp_crypto_lock.c"
"esp_crypto_lock.c"
"esp_ds.c") "esp_ds.c")
# init constructor for wifi # init constructor for wifi

View File

@@ -115,7 +115,7 @@ esp_err_t esp_ds_start_sign(const void *message,
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id); uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
if (conf_error) { if (conf_error) {
ds_disable_release(); ds_disable_release();
return ESP32C3_ERR_HW_CRYPTO_DS_HMAC_FAIL; return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
} }
ds_hal_start(); ds_hal_start();
@@ -125,7 +125,7 @@ esp_err_t esp_ds_start_sign(const void *message,
while (ds_ll_busy() != 0) { while (ds_ll_busy() != 0) {
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) { if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
ds_disable_release(); ds_disable_release();
return ESP32C3_ERR_HW_CRYPTO_DS_INVALID_KEY; return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
} }
} }
@@ -170,11 +170,11 @@ esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
esp_err_t return_value = ESP_OK; esp_err_t return_value = ESP_OK;
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) { if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
return_value = ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST; return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
} }
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) { if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
return_value = ESP32C3_ERR_HW_CRYPTO_DS_INVALID_PADDING; return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
} }
free(esp_ds_ctx); free(esp_ds_ctx);

View File

@@ -1,180 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "esp_private/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.
*
* @note This function does not check the data length, it is the responsibility of the other functions in this
* module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in.
* Otherwise, this function has undefined behavior.
* Note however, that for the actual HMAC implementation on ESP32C3, the length also needs to be applied at the end
* of the block. This function alone deosn't do that.
*/
static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len)
{
memcpy(block, data, data_len);
// Apply a one bit, followed by zero bits (refer to the ESP32C3 TRM).
block[data_len] = 0x80;
bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1);
}
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
const void *message,
size_t message_len,
uint8_t *hmac)
{
const uint8_t *message_bytes = (const uint8_t *)message;
if (!message || !hmac) {
return ESP_ERR_INVALID_ARG;
}
if (key_id >= HMAC_KEY_MAX) {
return ESP_ERR_INVALID_ARG;
}
esp_crypto_hmac_lock_acquire();
// We also enable SHA and DS here. SHA is used by HMAC, DS will otherwise hold SHA in reset state.
periph_module_enable(PERIPH_HMAC_MODULE);
periph_module_enable(PERIPH_SHA_MODULE);
periph_module_enable(PERIPH_DS_MODULE);
hmac_hal_start();
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_USER, key_id);
if (conf_error) {
esp_crypto_hmac_lock_release();
return ESP_FAIL;
}
if (message_len + 1 + SHA256_PAD_SZ <= SHA256_BLOCK_SZ) {
// If message including padding is only one block...
// Last message block, so apply SHA-256 padding rules in software
uint8_t block[SHA256_BLOCK_SZ];
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
write_and_padd(block, message_bytes, message_len);
// Final block: append the bit length in this block and signal padding to peripheral
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
&bit_len, sizeof(bit_len));
hmac_hal_write_one_block_512(block);
} else {
// If message including padding is needs more than one block
// write all blocks without padding except the last one
size_t remaining_blocks = message_len / SHA256_BLOCK_SZ;
for (int i = 1; i < remaining_blocks; i++) {
hmac_hal_write_block_512(message_bytes);
message_bytes += SHA256_BLOCK_SZ;
hmac_hal_next_block_normal();
}
// If message fits into one block but without padding, we must not write another block.
if (remaining_blocks) {
hmac_hal_write_block_512(message_bytes);
message_bytes += SHA256_BLOCK_SZ;
}
size_t remaining = message_len % SHA256_BLOCK_SZ;
// Last message block, so apply SHA-256 padding rules in software
uint8_t block[SHA256_BLOCK_SZ];
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
// If the remaining message and appended padding doesn't fit into a single block, we have to write an
// extra block with the rest of the message and potential padding first.
if (remaining >= SHA256_BLOCK_SZ - SHA256_PAD_SZ) {
write_and_padd(block, message_bytes, remaining);
hmac_hal_next_block_normal();
hmac_hal_write_block_512(block);
bzero(block, SHA256_BLOCK_SZ);
} else {
write_and_padd(block, message_bytes, remaining);
}
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
&bit_len, sizeof(bit_len));
hmac_hal_next_block_padding();
hmac_hal_write_block_512(block);
}
// Read back result (bit swapped)
hmac_hal_read_result_256(hmac);
periph_module_disable(PERIPH_DS_MODULE);
periph_module_disable(PERIPH_SHA_MODULE);
periph_module_disable(PERIPH_HMAC_MODULE);
esp_crypto_hmac_lock_release();
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

@@ -115,7 +115,7 @@ esp_err_t esp_ds_start_sign(const void *message,
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id); uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
if (conf_error) { if (conf_error) {
ds_disable_release(); ds_disable_release();
return ESP32C6_ERR_HW_CRYPTO_DS_HMAC_FAIL; return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
} }
ds_hal_start(); ds_hal_start();
@@ -125,7 +125,7 @@ esp_err_t esp_ds_start_sign(const void *message,
while (ds_ll_busy() != 0) { while (ds_ll_busy() != 0) {
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) { if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
ds_disable_release(); ds_disable_release();
return ESP32C6_ERR_HW_CRYPTO_DS_INVALID_KEY; return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
} }
} }
@@ -170,11 +170,11 @@ esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
esp_err_t return_value = ESP_OK; esp_err_t return_value = ESP_OK;
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) { if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
return_value = ESP32C6_ERR_HW_CRYPTO_DS_INVALID_DIGEST; return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
} }
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) { if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
return_value = ESP32C6_ERR_HW_CRYPTO_DS_INVALID_PADDING; return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
} }
free(esp_ds_ctx); free(esp_ds_ctx);

View File

@@ -1,182 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// TODO: IDF-5355 Copy frome C3
#include <string.h>
#include "esp_private/periph_ctrl.h"
#include "esp32c6/rom/hmac.h"
#include "esp32c6/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.
*
* @note This function does not check the data length, it is the responsibility of the other functions in this
* module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in.
* Otherwise, this function has undefined behavior.
* Note however, that for the actual HMAC implementation on ESP32C6, the length also needs to be applied at the end
* of the block. This function alone deosn't do that.
*/
static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len)
{
memcpy(block, data, data_len);
// Apply a one bit, followed by zero bits (refer to the ESP32C6 TRM).
block[data_len] = 0x80;
bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1);
}
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
const void *message,
size_t message_len,
uint8_t *hmac)
{
const uint8_t *message_bytes = (const uint8_t *)message;
if (!message || !hmac) {
return ESP_ERR_INVALID_ARG;
}
if (key_id >= HMAC_KEY_MAX) {
return ESP_ERR_INVALID_ARG;
}
esp_crypto_hmac_lock_acquire();
// We also enable SHA and DS here. SHA is used by HMAC, DS will otherwise hold SHA in reset state.
periph_module_enable(PERIPH_HMAC_MODULE);
periph_module_enable(PERIPH_SHA_MODULE);
periph_module_enable(PERIPH_DS_MODULE);
hmac_hal_start();
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_USER, key_id);
if (conf_error) {
esp_crypto_hmac_lock_release();
return ESP_FAIL;
}
if (message_len + 1 + SHA256_PAD_SZ <= SHA256_BLOCK_SZ) {
// If message including padding is only one block...
// Last message block, so apply SHA-256 padding rules in software
uint8_t block[SHA256_BLOCK_SZ];
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
write_and_padd(block, message_bytes, message_len);
// Final block: append the bit length in this block and signal padding to peripheral
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
&bit_len, sizeof(bit_len));
hmac_hal_write_one_block_512(block);
} else {
// If message including padding is needs more than one block
// write all blocks without padding except the last one
size_t remaining_blocks = message_len / SHA256_BLOCK_SZ;
for (int i = 1; i < remaining_blocks; i++) {
hmac_hal_write_block_512(message_bytes);
message_bytes += SHA256_BLOCK_SZ;
hmac_hal_next_block_normal();
}
// If message fits into one block but without padding, we must not write another block.
if (remaining_blocks) {
hmac_hal_write_block_512(message_bytes);
message_bytes += SHA256_BLOCK_SZ;
}
size_t remaining = message_len % SHA256_BLOCK_SZ;
// Last message block, so apply SHA-256 padding rules in software
uint8_t block[SHA256_BLOCK_SZ];
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
// If the remaining message and appended padding doesn't fit into a single block, we have to write an
// extra block with the rest of the message and potential padding first.
if (remaining >= SHA256_BLOCK_SZ - SHA256_PAD_SZ) {
write_and_padd(block, message_bytes, remaining);
hmac_hal_next_block_normal();
hmac_hal_write_block_512(block);
bzero(block, SHA256_BLOCK_SZ);
} else {
write_and_padd(block, message_bytes, remaining);
}
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
&bit_len, sizeof(bit_len));
hmac_hal_next_block_padding();
hmac_hal_write_block_512(block);
}
// Read back result (bit swapped)
hmac_hal_read_result_256(hmac);
periph_module_disable(PERIPH_DS_MODULE);
periph_module_disable(PERIPH_SHA_MODULE);
periph_module_disable(PERIPH_HMAC_MODULE);
esp_crypto_hmac_lock_release();
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_SET_INVALIDATE_JTAG);
esp_crypto_hmac_lock_release();
ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled.");
return ESP_OK;
}

View File

@@ -8,8 +8,7 @@ set(srcs "rtc_clk_init.c"
) )
if(NOT BOOTLOADER_BUILD) if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "esp_hmac.c" list(APPEND srcs "esp_crypto_lock.c"
"esp_crypto_lock.c"
"esp_ds.c") "esp_ds.c")
if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE) if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)

View File

@@ -115,7 +115,7 @@ esp_err_t esp_ds_start_sign(const void *message,
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id); uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
if (conf_error) { if (conf_error) {
ds_disable_release(); ds_disable_release();
return ESP32H2_ERR_HW_CRYPTO_DS_HMAC_FAIL; return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
} }
ds_hal_start(); ds_hal_start();
@@ -125,7 +125,7 @@ esp_err_t esp_ds_start_sign(const void *message,
while (ds_ll_busy() != 0) { while (ds_ll_busy() != 0) {
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) { if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
ds_disable_release(); ds_disable_release();
return ESP32H2_ERR_HW_CRYPTO_DS_INVALID_KEY; return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
} }
} }
@@ -170,11 +170,11 @@ esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
esp_err_t return_value = ESP_OK; esp_err_t return_value = ESP_OK;
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) { if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
return_value = ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST; return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
} }
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) { if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
return_value = ESP32H2_ERR_HW_CRYPTO_DS_INVALID_PADDING; return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
} }
free(esp_ds_ctx); free(esp_ds_ctx);

View File

@@ -1,180 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "esp_private/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.
*
* @note This function does not check the data length, it is the responsibility of the other functions in this
* module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in.
* Otherwise, this function has undefined behavior.
* Note however, that for the actual HMAC implementation on ESP32H2, the length also needs to be applied at the end
* of the block. This function alone deosn't do that.
*/
static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len)
{
memcpy(block, data, data_len);
// Apply a one bit, followed by zero bits (refer to the ESP32H2 TRM).
block[data_len] = 0x80;
bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1);
}
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
const void *message,
size_t message_len,
uint8_t *hmac)
{
const uint8_t *message_bytes = (const uint8_t *)message;
if (!message || !hmac) {
return ESP_ERR_INVALID_ARG;
}
if (key_id >= HMAC_KEY_MAX) {
return ESP_ERR_INVALID_ARG;
}
esp_crypto_hmac_lock_acquire();
// We also enable SHA and DS here. SHA is used by HMAC, DS will otherwise hold SHA in reset state.
periph_module_enable(PERIPH_HMAC_MODULE);
periph_module_enable(PERIPH_SHA_MODULE);
periph_module_enable(PERIPH_DS_MODULE);
hmac_hal_start();
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_USER, key_id);
if (conf_error) {
esp_crypto_hmac_lock_release();
return ESP_FAIL;
}
if (message_len + 1 + SHA256_PAD_SZ <= SHA256_BLOCK_SZ) {
// If message including padding is only one block...
// Last message block, so apply SHA-256 padding rules in software
uint8_t block[SHA256_BLOCK_SZ];
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
write_and_padd(block, message_bytes, message_len);
// Final block: append the bit length in this block and signal padding to peripheral
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
&bit_len, sizeof(bit_len));
hmac_hal_write_one_block_512(block);
} else {
// If message including padding is needs more than one block
// write all blocks without padding except the last one
size_t remaining_blocks = message_len / SHA256_BLOCK_SZ;
for (int i = 1; i < remaining_blocks; i++) {
hmac_hal_write_block_512(message_bytes);
message_bytes += SHA256_BLOCK_SZ;
hmac_hal_next_block_normal();
}
// If message fits into one block but without padding, we must not write another block.
if (remaining_blocks) {
hmac_hal_write_block_512(message_bytes);
message_bytes += SHA256_BLOCK_SZ;
}
size_t remaining = message_len % SHA256_BLOCK_SZ;
// Last message block, so apply SHA-256 padding rules in software
uint8_t block[SHA256_BLOCK_SZ];
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
// If the remaining message and appended padding doesn't fit into a single block, we have to write an
// extra block with the rest of the message and potential padding first.
if (remaining >= SHA256_BLOCK_SZ - SHA256_PAD_SZ) {
write_and_padd(block, message_bytes, remaining);
hmac_hal_next_block_normal();
hmac_hal_write_block_512(block);
bzero(block, SHA256_BLOCK_SZ);
} else {
write_and_padd(block, message_bytes, remaining);
}
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
&bit_len, sizeof(bit_len));
hmac_hal_next_block_padding();
hmac_hal_write_block_512(block);
}
// Read back result (bit swapped)
hmac_hal_read_result_256(hmac);
periph_module_disable(PERIPH_DS_MODULE);
periph_module_disable(PERIPH_SHA_MODULE);
periph_module_disable(PERIPH_HMAC_MODULE);
esp_crypto_hmac_lock_release();
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

@@ -13,7 +13,6 @@ set(srcs
if(NOT BOOTLOADER_BUILD) if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "memprot.c" list(APPEND srcs "memprot.c"
"esp_hmac.c"
"esp_crypto_lock.c" "esp_crypto_lock.c"
"esp_ds.c") "esp_ds.c")

View File

@@ -1,100 +0,0 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "esp32s2/rom/ets_sys.h"
#include "esp32s2/rom/hmac.h"
#include "esp_hmac.h"
#include "esp_crypto_lock.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "soc/hwcrypto_reg.h"
#include "soc/system_reg.h"
#include "esp_log.h"
static const char *TAG = "esp_hmac";
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_calculate(hmac_key_id_t key_id,
const void *message,
size_t message_len,
uint8_t *hmac)
{
int hmac_ret;
if (!message || !hmac) return ESP_ERR_INVALID_ARG;
if (key_id >= HMAC_KEY_MAX) return ESP_ERR_INVALID_ARG;
esp_crypto_dma_lock_acquire();
ets_hmac_enable();
hmac_ret = ets_hmac_calculate_message(convert_key_type(key_id), message, message_len, hmac);
ets_hmac_disable();
esp_crypto_dma_lock_release();
if (hmac_ret != 0) {
return ESP_FAIL;
} else {
return ESP_OK;
}
}
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_dma_lock_acquire();
ets_hmac_enable();
/* Token updating into HMAC module. */
for (int i = 0; i < 32; i += 4) {
uint32_t key_word;
memcpy(&key_word, &token[i], 4);
REG_WRITE(DPORT_JTAG_CTRL_0_REG + i, __builtin_bswap32(key_word));
}
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.");
ets_hmac_disable();
esp_crypto_dma_lock_release();
return err;
}
esp_err_t esp_hmac_jtag_disable()
{
esp_crypto_dma_lock_acquire();
REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1);
esp_crypto_dma_lock_release();
ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled.");
return ESP_OK;
}

View File

@@ -12,8 +12,7 @@ set(srcs
) )
if(NOT BOOTLOADER_BUILD) if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "esp_hmac.c" list(APPEND srcs "esp_ds.c"
"esp_ds.c"
"esp_crypto_lock.c") "esp_crypto_lock.c")
if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE) if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)

View File

@@ -119,7 +119,7 @@ esp_err_t esp_ds_start_sign(const void *message,
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id); uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
if (conf_error) { if (conf_error) {
ds_disable_release(); ds_disable_release();
return ESP32S3_ERR_HW_CRYPTO_DS_HMAC_FAIL; return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
} }
ds_hal_start(); ds_hal_start();
@@ -129,7 +129,7 @@ esp_err_t esp_ds_start_sign(const void *message,
while (ds_ll_busy() != 0) { while (ds_ll_busy() != 0) {
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) { if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
ds_disable_release(); ds_disable_release();
return ESP32S3_ERR_HW_CRYPTO_DS_INVALID_KEY; return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
} }
} }
@@ -174,11 +174,11 @@ esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
esp_err_t return_value = ESP_OK; esp_err_t return_value = ESP_OK;
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) { if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
return_value = ESP32S3_ERR_HW_CRYPTO_DS_INVALID_DIGEST; return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
} }
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) { if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
return_value = ESP32S3_ERR_HW_CRYPTO_DS_INVALID_PADDING; return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
} }
free(esp_ds_ctx); free(esp_ds_ctx);

View File

@@ -133,6 +133,7 @@ INPUT = \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_chip_info.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_chip_info.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_cpu.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_cpu.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_crc.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_crc.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_hmac.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_alloc.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_alloc.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_mac.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_mac.h \
$(PROJECT_PATH)/components/esp_hw_support/include/esp_random.h \ $(PROJECT_PATH)/components/esp_hw_support/include/esp_random.h \

View File

@@ -1,3 +1,2 @@
INPUT += \ INPUT += \
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32c3/esp_ds.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32c3/esp_hmac.h \

View File

@@ -1 +1,2 @@
INPUT += \ INPUT += \
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \

View File

@@ -1,3 +1,2 @@
INPUT += \ INPUT += \
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32h2/esp_ds.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32h2/esp_hmac.h \

View File

@@ -1,7 +1,6 @@
INPUT += \ INPUT += \
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_ds.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
$(PROJECT_PATH)/components/esp_hw_support/include/soc/esp32s2/esp_hmac.h \
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \

View File

@@ -1,7 +1,6 @@
INPUT += \ INPUT += \
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \ $(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_hmac.h \
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
$(PROJECT_PATH)/components/ulp/ulp_common/include/$(IDF_TARGET)/ulp_common_defs.h \ $(PROJECT_PATH)/components/ulp/ulp_common/include/$(IDF_TARGET)/ulp_common_defs.h \
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \ $(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \