mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'refactor/merge_esp_ds_code_between_targets' into 'master'
Merge esp_ds and hmac_hal layers for different targets Closes IDF-3803, IDF-6144, and DOC-3973 See merge request espressif/esp-idf!21187
This commit is contained in:
commit
22ad083ccd
@ -57,6 +57,10 @@ if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "esp_etm.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_DIG_SIGN_SUPPORTED)
|
||||
list(APPEND srcs "esp_ds.c")
|
||||
endif()
|
||||
|
||||
# ESP32C6-TODO
|
||||
if(CONFIG_IDF_TARGET_ESP32C6)
|
||||
list(REMOVE_ITEM srcs
|
||||
|
439
components/esp_hw_support/esp_ds.c
Normal file
439
components/esp_hw_support/esp_ds.c
Normal file
@ -0,0 +1,439 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "esp_timer.h"
|
||||
#include "esp_ds.h"
|
||||
#include "esp_crypto_lock.h"
|
||||
#include "esp_hmac.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/aes.h"
|
||||
#include "esp32s2/rom/sha.h"
|
||||
#include "esp32s2/rom/hmac.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#else /* CONFIG_IDF_TARGET_ESP32S2 */
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "hal/ds_hal.h"
|
||||
#include "hal/ds_ll.h"
|
||||
#include "hal/hmac_hal.h"
|
||||
#endif /* !CONFIG_IDF_TARGET_ESP32S2 */
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/digital_signature.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/digital_signature.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/digital_signature.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/digital_signature.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32H4
|
||||
#include "esp32h4/rom/digital_signature.h"
|
||||
#endif
|
||||
|
||||
|
||||
struct esp_ds_context {
|
||||
const ets_ds_data_t *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation.
|
||||
*/
|
||||
#define ESP_DS_SIGN_TASK_DELAY_MS 10
|
||||
|
||||
#define RSA_LEN_MAX ((SOC_RSA_MAX_BIT_LEN/8) - 1)
|
||||
|
||||
/*
|
||||
* Check that the size of esp_ds_data_t and ets_ds_data_t is the same because both structs are converted using
|
||||
* raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t),
|
||||
"The size and structure of esp_ds_data_t and ets_ds_data_t must match exactly, they're used in raw casts");
|
||||
|
||||
/*
|
||||
* esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used.
|
||||
* Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned),
|
||||
"The size of esp_digital_signature_length_t and unsigned has to be the same");
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
|
||||
static void ds_acquire_enable(void)
|
||||
{
|
||||
/* Lock AES, SHA and RSA peripheral */
|
||||
esp_crypto_dma_lock_acquire();
|
||||
esp_crypto_mpi_lock_acquire();
|
||||
ets_hmac_enable();
|
||||
ets_ds_enable();
|
||||
}
|
||||
|
||||
static void ds_disable_release(void)
|
||||
{
|
||||
ets_ds_disable();
|
||||
ets_hmac_disable();
|
||||
esp_crypto_mpi_lock_release();
|
||||
esp_crypto_dma_lock_release();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature)
|
||||
{
|
||||
// Need to check signature here, otherwise the signature is only checked when the signing has finished and fails
|
||||
// but the signing isn't uninitialized and the mutex is still locked.
|
||||
if (!signature) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_ds_context_t *context;
|
||||
esp_err_t result = esp_ds_start_sign(message, data, key_id, &context);
|
||||
if (result != ESP_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
while (esp_ds_is_busy()) {
|
||||
vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
return esp_ds_finish_sign(signature, context);
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx)
|
||||
{
|
||||
if (!message || !data || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (key_id >= HMAC_KEY_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!(data->rsa_length == ESP_DS_RSA_1024
|
||||
|| data->rsa_length == ESP_DS_RSA_2048
|
||||
|| data->rsa_length == ESP_DS_RSA_3072
|
||||
#if SOC_RSA_MAX_BIT_LEN == 4096
|
||||
|| data->rsa_length == ESP_DS_RSA_4096
|
||||
#endif
|
||||
)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ds_acquire_enable();
|
||||
|
||||
// initiate hmac
|
||||
int r = ets_hmac_calculate_downstream(ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id,
|
||||
ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
|
||||
if (r != ETS_OK) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
|
||||
}
|
||||
|
||||
esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t));
|
||||
if (!context) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
ets_ds_data_t *ds_data = (ets_ds_data_t *) data;
|
||||
|
||||
// initiate signing
|
||||
ets_ds_result_t result = ets_ds_start_sign(message, ds_data);
|
||||
|
||||
// ETS_DS_INVALID_PARAM only happens if a parameter is NULL or data->rsa_length is wrong
|
||||
// We checked all of that already
|
||||
assert(result != ETS_DS_INVALID_PARAM);
|
||||
|
||||
if (result == ETS_DS_INVALID_KEY) {
|
||||
ds_disable_release();
|
||||
free(context);
|
||||
return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
|
||||
}
|
||||
|
||||
context->data = (const ets_ds_data_t *)ds_data;
|
||||
*esp_ds_ctx = context;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool esp_ds_is_busy(void)
|
||||
{
|
||||
return ets_ds_is_busy();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
{
|
||||
if (!signature || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const ets_ds_data_t *ds_data = esp_ds_ctx->data;
|
||||
|
||||
ets_ds_result_t result = ets_ds_finish_sign(signature, ds_data);
|
||||
|
||||
esp_err_t return_value = ESP_OK;
|
||||
|
||||
// we checked all the parameters
|
||||
assert(result != ETS_DS_INVALID_PARAM);
|
||||
|
||||
if (result == ETS_DS_INVALID_DIGEST) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||
}
|
||||
if (result == ETS_DS_INVALID_PADDING) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||
}
|
||||
|
||||
free(esp_ds_ctx);
|
||||
|
||||
int res = ets_hmac_invalidate_downstream(ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
|
||||
assert(res == ETS_OK); // should not fail if called with correct purpose
|
||||
(void)res;
|
||||
|
||||
ds_disable_release();
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key)
|
||||
{
|
||||
// p_data has to be valid, in internal memory and word aligned
|
||||
if (!p_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
assert(esp_ptr_internal(p_data) && esp_ptr_word_aligned(p_data));
|
||||
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
esp_crypto_dma_lock_acquire();
|
||||
ets_aes_enable();
|
||||
ets_sha_enable();
|
||||
|
||||
ets_ds_data_t *ds_data = (ets_ds_data_t *) data;
|
||||
const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t *) p_data;
|
||||
|
||||
ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC);
|
||||
|
||||
if (ets_result == ETS_DS_INVALID_PARAM) {
|
||||
result = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ets_sha_disable();
|
||||
ets_aes_disable();
|
||||
esp_crypto_dma_lock_release();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#else /* !CONFIG_IDF_TARGET_ESP32S2 (targets other than esp32s2) */
|
||||
|
||||
static void ds_acquire_enable(void)
|
||||
{
|
||||
esp_crypto_ds_lock_acquire();
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_crypto_mpi_lock_acquire();
|
||||
#endif
|
||||
// We also enable SHA and HMAC here. SHA is used by HMAC, HMAC is used by DS.
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
|
||||
hmac_hal_start();
|
||||
}
|
||||
|
||||
static void ds_disable_release(void)
|
||||
{
|
||||
ds_hal_finish();
|
||||
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_crypto_mpi_lock_release();
|
||||
#endif
|
||||
esp_crypto_ds_lock_release();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature)
|
||||
{
|
||||
// Need to check signature here, otherwise the signature is only checked when the signing has finished and fails
|
||||
// but the signing isn't uninitialized and the mutex is still locked.
|
||||
if (!signature) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_ds_context_t *context;
|
||||
esp_err_t result = esp_ds_start_sign(message, data, key_id, &context);
|
||||
if (result != ESP_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
while (esp_ds_is_busy()) {
|
||||
vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
return esp_ds_finish_sign(signature, context);
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx)
|
||||
{
|
||||
if (!message || !data || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (key_id >= HMAC_KEY_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!(data->rsa_length == ESP_DS_RSA_1024
|
||||
|| data->rsa_length == ESP_DS_RSA_2048
|
||||
|| data->rsa_length == ESP_DS_RSA_3072
|
||||
#if SOC_RSA_MAX_BIT_LEN == 4096
|
||||
|| data->rsa_length == ESP_DS_RSA_4096
|
||||
#endif
|
||||
)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ds_acquire_enable();
|
||||
|
||||
// initiate hmac
|
||||
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
|
||||
if (conf_error) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
|
||||
}
|
||||
|
||||
ds_hal_start();
|
||||
|
||||
// check encryption key from HMAC
|
||||
int64_t start_time = esp_timer_get_time();
|
||||
while (ds_ll_busy() != 0) {
|
||||
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t));
|
||||
if (!context) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
size_t rsa_len = (data->rsa_length + 1) * 4;
|
||||
ds_hal_write_private_key_params(data->c);
|
||||
ds_hal_configure_iv((uint32_t *)data->iv);
|
||||
ds_hal_write_message(message, rsa_len);
|
||||
|
||||
// initiate signing
|
||||
ds_hal_start_sign();
|
||||
|
||||
context->data = (const ets_ds_data_t *)data;
|
||||
*esp_ds_ctx = context;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool esp_ds_is_busy(void)
|
||||
{
|
||||
return ds_hal_busy();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
{
|
||||
if (!signature || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_ds_data_t *data = (const esp_ds_data_t *)esp_ds_ctx->data;
|
||||
unsigned rsa_len = (data->rsa_length + 1) * 4;
|
||||
|
||||
while (ds_hal_busy()) { }
|
||||
|
||||
ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t *) signature, (size_t) rsa_len);
|
||||
|
||||
esp_err_t return_value = ESP_OK;
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||
}
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||
}
|
||||
|
||||
free(esp_ds_ctx);
|
||||
|
||||
hmac_hal_clean();
|
||||
|
||||
ds_disable_release();
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key)
|
||||
{
|
||||
if (!p_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
esp_crypto_ds_lock_acquire();
|
||||
periph_module_enable(PERIPH_AES_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_RSA_MODULE);
|
||||
|
||||
ets_ds_data_t *ds_data = (ets_ds_data_t *) data;
|
||||
const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t *) p_data;
|
||||
|
||||
ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC);
|
||||
|
||||
if (ets_result == ETS_DS_INVALID_PARAM) {
|
||||
result = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
periph_module_disable(PERIPH_RSA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_AES_MODULE);
|
||||
esp_crypto_ds_lock_release();
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
@ -5,26 +5,27 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_hmac.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_ds_err.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define ESP_DS_IV_BIT_LEN 128
|
||||
#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 SOC_RSA_MAX_BIT_LEN
|
||||
#define ESP_DS_SIGNATURE_MD_BIT_LEN 256
|
||||
#define ESP_DS_SIGNATURE_M_PRIME_BIT_LEN 32
|
||||
#define ESP_DS_SIGNATURE_L_BIT_LEN 32
|
||||
#define ESP_DS_SIGNATURE_PADDING_BIT_LEN 64
|
||||
|
||||
/* Length of parameter 'C' stored in flash, in bytes
|
||||
- Operands Y, M and r_bar; each 3072 bits
|
||||
- Operands Y, M and r_bar; each equal to maximum RSA bit length
|
||||
- Operand MD (message digest); 256 bits
|
||||
- Operands M' and L; each 32 bits
|
||||
- Operand beta (padding value; 64 bits
|
||||
@ -40,7 +41,8 @@ typedef struct esp_ds_context esp_ds_context_t;
|
||||
typedef enum {
|
||||
ESP_DS_RSA_1024 = (1024 / 32) - 1,
|
||||
ESP_DS_RSA_2048 = (2048 / 32) - 1,
|
||||
ESP_DS_RSA_3072 = (3072 / 32) - 1
|
||||
ESP_DS_RSA_3072 = (3072 / 32) - 1,
|
||||
ESP_DS_RSA_4096 = (4096 / 32) - 1
|
||||
} esp_digital_signature_length_t;
|
||||
|
||||
/**
|
||||
@ -53,8 +55,6 @@ typedef struct esp_digital_signature_data {
|
||||
* RSA LENGTH register parameters
|
||||
* (number of words in RSA key & operands, minus one).
|
||||
*
|
||||
* Max value 127 (for RSA 3072).
|
||||
*
|
||||
* This value must match the length field encrypted and stored in 'c',
|
||||
* or invalid results will be returned. (The DS peripheral will
|
||||
* always use the value in 'c', not this value, so an attacker can't
|
||||
@ -105,7 +105,8 @@ typedef struct {
|
||||
* in parallel.
|
||||
* It blocks until the signing is finished and then returns the signature.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components during its entire execution time.
|
||||
* @note
|
||||
* Please see note section of \c esp_ds_start_sign() for more details about the input parameters.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
@ -133,15 +134,20 @@ esp_err_t esp_ds_sign(const void *message,
|
||||
*
|
||||
* This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing
|
||||
* process.
|
||||
*
|
||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||
* The RSA encryption operation is as follows:
|
||||
* Z = XY mod M where,
|
||||
* Z is the signature, X is the input message,
|
||||
* Y and M are the RSA private key parameters.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call
|
||||
* \c esp_ds_finish_sign() in a timely manner.
|
||||
* @note
|
||||
* This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call
|
||||
* \c esp_ds_finish_sign() in a timely manner.
|
||||
* The numbers Y, M, Rb which are a part of esp_ds_data_t should be provided in little endian format
|
||||
* and should be of length equal to the RSA private key bit length
|
||||
* The message length in bits should also be equal to the RSA private key bit length.
|
||||
* No padding is applied to the message automatically, Please ensure the message is appropriate padded before
|
||||
* calling the API.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
@ -199,6 +205,13 @@ esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx);
|
||||
* @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the
|
||||
* corresponding HMAC key will be stored to efuse and then permanently erased.
|
||||
*
|
||||
* @note
|
||||
* The numbers Y, M, Rb which are a part of esp_ds_data_t should be provided in little endian format
|
||||
* and should be of length equal to the RSA private key bit length
|
||||
* The message length in bits should also be equal to the RSA private key bit length.
|
||||
* No padding is applied to the message automatically, Please ensure the message is appropriate padded before
|
||||
* calling the API.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long
|
@ -1,211 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_hmac.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_ds_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_DS_IV_BIT_LEN 128
|
||||
#define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8)
|
||||
#define ESP_DS_SIGNATURE_MAX_BIT_LEN 3072
|
||||
#define ESP_DS_SIGNATURE_MD_BIT_LEN 256
|
||||
#define ESP_DS_SIGNATURE_M_PRIME_BIT_LEN 32
|
||||
#define ESP_DS_SIGNATURE_L_BIT_LEN 32
|
||||
#define ESP_DS_SIGNATURE_PADDING_BIT_LEN 64
|
||||
|
||||
/* Length of parameter 'C' stored in flash, in bytes
|
||||
- Operands Y, M and r_bar; each 3072 bits
|
||||
- Operand MD (message digest); 256 bits
|
||||
- Operands M' and L; each 32 bits
|
||||
- Operand beta (padding value; 64 bits
|
||||
*/
|
||||
#define ESP_DS_C_LEN (((ESP_DS_SIGNATURE_MAX_BIT_LEN * 3 \
|
||||
+ ESP_DS_SIGNATURE_MD_BIT_LEN \
|
||||
+ ESP_DS_SIGNATURE_M_PRIME_BIT_LEN \
|
||||
+ ESP_DS_SIGNATURE_L_BIT_LEN \
|
||||
+ ESP_DS_SIGNATURE_PADDING_BIT_LEN) / 8))
|
||||
|
||||
typedef struct esp_ds_context esp_ds_context_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_DS_RSA_1024 = (1024 / 32) - 1,
|
||||
ESP_DS_RSA_2048 = (2048 / 32) - 1,
|
||||
ESP_DS_RSA_3072 = (3072 / 32) - 1
|
||||
} esp_digital_signature_length_t;
|
||||
|
||||
/**
|
||||
* Encrypted private key data. Recommended to store in flash in this format.
|
||||
*
|
||||
* @note This struct has to match to one from the ROM code! This documentation is mostly taken from there.
|
||||
*/
|
||||
typedef struct esp_digital_signature_data {
|
||||
/**
|
||||
* RSA LENGTH register parameters
|
||||
* (number of words in RSA key & operands, minus one).
|
||||
*
|
||||
* Max value 127 (for RSA 3072).
|
||||
*
|
||||
* This value must match the length field encrypted and stored in 'c',
|
||||
* or invalid results will be returned. (The DS peripheral will
|
||||
* always use the value in 'c', not this value, so an attacker can't
|
||||
* alter the DS peripheral results this way, it will just truncate or
|
||||
* extend the message and the resulting signature in software.)
|
||||
*
|
||||
* @note In IDF, the enum type length is the same as of type unsigned, so they can be used interchangably.
|
||||
* See the ROM code for the original declaration of struct \c ets_ds_data_t.
|
||||
*/
|
||||
esp_digital_signature_length_t rsa_length;
|
||||
|
||||
/**
|
||||
* IV value used to encrypt 'c'
|
||||
*/
|
||||
uint32_t iv[ESP_DS_IV_BIT_LEN / 32];
|
||||
|
||||
/**
|
||||
* Encrypted Digital Signature parameters. Result of AES-CBC encryption
|
||||
* of plaintext values. Includes an encrypted message digest.
|
||||
*/
|
||||
uint8_t c[ESP_DS_C_LEN];
|
||||
} esp_ds_data_t;
|
||||
|
||||
/**
|
||||
* Plaintext parameters used by Digital Signature.
|
||||
*
|
||||
* This is only used for encrypting the RSA parameters by calling esp_ds_encrypt_params().
|
||||
* Afterwards, the result can be stored in flash or in other persistent memory.
|
||||
* The encryption is a prerequisite step before any signature operation can be done.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t Y[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA exponent
|
||||
uint32_t M[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA modulus
|
||||
uint32_t Rb[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA r inverse operand
|
||||
uint32_t M_prime; //!< RSA M prime operand
|
||||
uint32_t length; //!< RSA length in words (32 bit)
|
||||
} esp_ds_p_data_t;
|
||||
|
||||
/**
|
||||
* @brief Sign the message with a hardware key from specific key slot.
|
||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||
* The RSA encryption operation is as follows:
|
||||
* Z = XY mod M where,
|
||||
* Z is the signature, X is the input message,
|
||||
* Y and M are the RSA private key parameters.
|
||||
*
|
||||
* This function is a wrapper around \c esp_ds_finish_sign() and \c esp_ds_start_sign(), so do not use them
|
||||
* in parallel.
|
||||
* It blocks until the signing is finished and then returns the signature.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components during its entire execution time.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||
* signing key data
|
||||
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the signature was written to the parameter \c signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||
* since the message digest matches.
|
||||
*/
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature);
|
||||
|
||||
/**
|
||||
* @brief Start the signing process.
|
||||
*
|
||||
* This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing
|
||||
* process.
|
||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||
* The RSA encryption operation is as follows:
|
||||
* Z = XY mod M where,
|
||||
* Z is the signature, X is the input message,
|
||||
* Y and M are the RSA private key parameters.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call
|
||||
* \c esp_ds_finish_sign() in a timely manner.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||
* signing key data
|
||||
* @param esp_ds_ctx the context object which is needed for finishing the signing process later
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation was started now and has to be finished with \c esp_ds_finish_sign()
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||
*/
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx);
|
||||
|
||||
/**
|
||||
* Return true if the DS peripheral is busy, otherwise false.
|
||||
*
|
||||
* @note Only valid if \c esp_ds_start_sign() was called before.
|
||||
*/
|
||||
bool esp_ds_is_busy(void);
|
||||
|
||||
/**
|
||||
* @brief Finish the signing process.
|
||||
*
|
||||
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||
* @param esp_ds_ctx the context object retreived by \c esp_ds_start_sign()
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||
* This means that the encrypted RSA key parameters are invalid, indicating that they may have been tampered
|
||||
* with or indicating a flash error, etc.
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||
* since the message digest matches (see TRM for more details).
|
||||
*/
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx);
|
||||
|
||||
/**
|
||||
* @brief Encrypt the private key parameters.
|
||||
*
|
||||
* The encryption is a prerequisite step before any signature operation can be done.
|
||||
* It is not strictly necessary to use this encryption function, the encryption could also happen on an external
|
||||
* device.
|
||||
*
|
||||
* @param data Output buffer to store encrypted data, suitable for later use generating signatures.
|
||||
* @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time.
|
||||
* @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process
|
||||
* is done and 'data' is stored.
|
||||
* @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the
|
||||
* corresponding HMAC key will be stored to efuse and then permanently erased.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long
|
||||
*/
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,211 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_hmac.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_ds_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_DS_IV_BIT_LEN 128
|
||||
#define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8)
|
||||
#define ESP_DS_SIGNATURE_MAX_BIT_LEN 3072
|
||||
#define ESP_DS_SIGNATURE_MD_BIT_LEN 256
|
||||
#define ESP_DS_SIGNATURE_M_PRIME_BIT_LEN 32
|
||||
#define ESP_DS_SIGNATURE_L_BIT_LEN 32
|
||||
#define ESP_DS_SIGNATURE_PADDING_BIT_LEN 64
|
||||
|
||||
/* Length of parameter 'C' stored in flash, in bytes
|
||||
- Operands Y, M and r_bar; each 3072 bits
|
||||
- Operand MD (message digest); 256 bits
|
||||
- Operands M' and L; each 32 bits
|
||||
- Operand beta (padding value; 64 bits
|
||||
*/
|
||||
#define ESP_DS_C_LEN (((ESP_DS_SIGNATURE_MAX_BIT_LEN * 3 \
|
||||
+ ESP_DS_SIGNATURE_MD_BIT_LEN \
|
||||
+ ESP_DS_SIGNATURE_M_PRIME_BIT_LEN \
|
||||
+ ESP_DS_SIGNATURE_L_BIT_LEN \
|
||||
+ ESP_DS_SIGNATURE_PADDING_BIT_LEN) / 8))
|
||||
|
||||
typedef struct esp_ds_context esp_ds_context_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_DS_RSA_1024 = (1024 / 32) - 1,
|
||||
ESP_DS_RSA_2048 = (2048 / 32) - 1,
|
||||
ESP_DS_RSA_3072 = (3072 / 32) - 1
|
||||
} esp_digital_signature_length_t;
|
||||
|
||||
/**
|
||||
* Encrypted private key data. Recommended to store in flash in this format.
|
||||
*
|
||||
* @note This struct has to match to one from the ROM code! This documentation is mostly taken from there.
|
||||
*/
|
||||
typedef struct esp_digital_signature_data {
|
||||
/**
|
||||
* RSA LENGTH register parameters
|
||||
* (number of words in RSA key & operands, minus one).
|
||||
*
|
||||
* Max value 127 (for RSA 3072).
|
||||
*
|
||||
* This value must match the length field encrypted and stored in 'c',
|
||||
* or invalid results will be returned. (The DS peripheral will
|
||||
* always use the value in 'c', not this value, so an attacker can't
|
||||
* alter the DS peripheral results this way, it will just truncate or
|
||||
* extend the message and the resulting signature in software.)
|
||||
*
|
||||
* @note In IDF, the enum type length is the same as of type unsigned, so they can be used interchangably.
|
||||
* See the ROM code for the original declaration of struct \c ets_ds_data_t.
|
||||
*/
|
||||
esp_digital_signature_length_t rsa_length;
|
||||
|
||||
/**
|
||||
* IV value used to encrypt 'c'
|
||||
*/
|
||||
uint32_t iv[ESP_DS_IV_BIT_LEN / 32];
|
||||
|
||||
/**
|
||||
* Encrypted Digital Signature parameters. Result of AES-CBC encryption
|
||||
* of plaintext values. Includes an encrypted message digest.
|
||||
*/
|
||||
uint8_t c[ESP_DS_C_LEN];
|
||||
} esp_ds_data_t;
|
||||
|
||||
/**
|
||||
* Plaintext parameters used by Digital Signature.
|
||||
*
|
||||
* This is only used for encrypting the RSA parameters by calling esp_ds_encrypt_params().
|
||||
* Afterwards, the result can be stored in flash or in other persistent memory.
|
||||
* The encryption is a prerequisite step before any signature operation can be done.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t Y[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA exponent
|
||||
uint32_t M[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA modulus
|
||||
uint32_t Rb[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA r inverse operand
|
||||
uint32_t M_prime; //!< RSA M prime operand
|
||||
uint32_t length; //!< RSA length in words (32 bit)
|
||||
} esp_ds_p_data_t;
|
||||
|
||||
/**
|
||||
* @brief Sign the message with a hardware key from specific key slot.
|
||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||
* The RSA encryption operation is as follows:
|
||||
* Z = XY mod M where,
|
||||
* Z is the signature, X is the input message,
|
||||
* Y and M are the RSA private key parameters.
|
||||
*
|
||||
* This function is a wrapper around \c esp_ds_finish_sign() and \c esp_ds_start_sign(), so do not use them
|
||||
* in parallel.
|
||||
* It blocks until the signing is finished and then returns the signature.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components during its entire execution time.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||
* signing key data
|
||||
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the signature was written to the parameter \c signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||
* since the message digest matches.
|
||||
*/
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature);
|
||||
|
||||
/**
|
||||
* @brief Start the signing process.
|
||||
*
|
||||
* This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing
|
||||
* process.
|
||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||
* The RSA encryption operation is as follows:
|
||||
* Z = XY mod M where,
|
||||
* Z is the signature, X is the input message,
|
||||
* Y and M are the RSA private key parameters.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call
|
||||
* \c esp_ds_finish_sign() in a timely manner.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||
* signing key data
|
||||
* @param esp_ds_ctx the context object which is needed for finishing the signing process later
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation was started now and has to be finished with \c esp_ds_finish_sign()
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||
*/
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx);
|
||||
|
||||
/**
|
||||
* Return true if the DS peripheral is busy, otherwise false.
|
||||
*
|
||||
* @note Only valid if \c esp_ds_start_sign() was called before.
|
||||
*/
|
||||
bool esp_ds_is_busy(void);
|
||||
|
||||
/**
|
||||
* @brief Finish the signing process.
|
||||
*
|
||||
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||
* @param esp_ds_ctx the context object retreived by \c esp_ds_start_sign()
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||
* This means that the encrypted RSA key parameters are invalid, indicating that they may have been tampered
|
||||
* with or indicating a flash error, etc.
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||
* since the message digest matches (see TRM for more details).
|
||||
*/
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx);
|
||||
|
||||
/**
|
||||
* @brief Encrypt the private key parameters.
|
||||
*
|
||||
* The encryption is a prerequisite step before any signature operation can be done.
|
||||
* It is not strictly necessary to use this encryption function, the encryption could also happen on an external
|
||||
* device.
|
||||
*
|
||||
* @param data Output buffer to store encrypted data, suitable for later use generating signatures.
|
||||
* @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time.
|
||||
* @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process
|
||||
* is done and 'data' is stored.
|
||||
* @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the
|
||||
* corresponding HMAC key will be stored to efuse and then permanently erased.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long
|
||||
*/
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_hmac.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_ds_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_DS_IV_LEN 16
|
||||
|
||||
/* Length of parameter 'C' stored in flash */
|
||||
#define ESP_DS_C_LEN (12672 / 8)
|
||||
|
||||
typedef struct esp_ds_context esp_ds_context_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_DS_RSA_1024 = (1024 / 32) - 1,
|
||||
ESP_DS_RSA_2048 = (2048 / 32) - 1,
|
||||
ESP_DS_RSA_3072 = (3072 / 32) - 1,
|
||||
ESP_DS_RSA_4096 = (4096 / 32) - 1
|
||||
} esp_digital_signature_length_t;
|
||||
|
||||
/**
|
||||
* Encrypted private key data. Recommended to store in flash in this format.
|
||||
*
|
||||
* @note This struct has to match to one from the ROM code! This documentation is mostly taken from there.
|
||||
*/
|
||||
typedef struct esp_digital_signature_data {
|
||||
/**
|
||||
* RSA LENGTH register parameters
|
||||
* (number of words in RSA key & operands, minus one).
|
||||
*
|
||||
* Max value 127 (for RSA 4096).
|
||||
*
|
||||
* This value must match the length field encrypted and stored in 'c',
|
||||
* or invalid results will be returned. (The DS peripheral will
|
||||
* always use the value in 'c', not this value, so an attacker can't
|
||||
* alter the DS peripheral results this way, it will just truncate or
|
||||
* extend the message and the resulting signature in software.)
|
||||
*
|
||||
* @note In IDF, the enum type length is the same as of type unsigned, so they can be used interchangably.
|
||||
* See the ROM code for the original declaration of struct \c ets_ds_data_t.
|
||||
*/
|
||||
esp_digital_signature_length_t rsa_length;
|
||||
|
||||
/**
|
||||
* IV value used to encrypt 'c'
|
||||
*/
|
||||
uint8_t iv[ESP_DS_IV_LEN];
|
||||
|
||||
/**
|
||||
* Encrypted Digital Signature parameters. Result of AES-CBC encryption
|
||||
* of plaintext values. Includes an encrypted message digest.
|
||||
*/
|
||||
uint8_t c[ESP_DS_C_LEN];
|
||||
} esp_ds_data_t;
|
||||
|
||||
/** Plaintext parameters used by Digital Signature.
|
||||
*
|
||||
* Not used for signing with DS peripheral, but can be encrypted
|
||||
* in-device by calling esp_ds_encrypt_params()
|
||||
*
|
||||
* @note This documentation is mostly taken from the ROM code.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t Y[4096/32]; //!< RSA exponent
|
||||
uint32_t M[4096/32]; //!< RSA modulus
|
||||
uint32_t Rb[4096/32]; //!< RSA r inverse operand
|
||||
uint32_t M_prime; //!< RSA M prime operand
|
||||
esp_digital_signature_length_t length; //!< RSA length
|
||||
} esp_ds_p_data_t;
|
||||
|
||||
/**
|
||||
* Sign the message.
|
||||
*
|
||||
* This function is a wrapper around \c esp_ds_finish_sign() and \c esp_ds_start_sign(), so do not use them
|
||||
* in parallel.
|
||||
* It blocks until the signing is finished and then returns the signature.
|
||||
*
|
||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||
* The RSA encryption operation is as follows:
|
||||
* Z = XY mod M where,
|
||||
* Z is the signature, X is the input message,
|
||||
* Y and M are the RSA private key parameters.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components during its entire execution time.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||
* signing key data
|
||||
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the signature was written to the parameter \c signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||
* since the message digest matches.
|
||||
*/
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature);
|
||||
|
||||
/**
|
||||
* Start the signing process.
|
||||
*
|
||||
* This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing
|
||||
* process.
|
||||
*
|
||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||
* The RSA encryption operation is as follows:
|
||||
* Z = XY mod M where,
|
||||
* Z is the signature, X is the input message,
|
||||
* Y and M are the RSA private key parameters.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call
|
||||
* \c esp_ds_finish_sign() in a timely manner.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||
* signing key data
|
||||
* @param esp_ds_ctx the context object which is needed for finishing the signing process later
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation was started now and has to be finished with \c esp_ds_finish_sign()
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||
*/
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx);
|
||||
|
||||
/**
|
||||
* Return true if the DS peripheral is busy, otherwise false.
|
||||
*
|
||||
* @note Only valid if \c esp_ds_start_sign() was called before.
|
||||
*/
|
||||
bool esp_ds_is_busy(void);
|
||||
|
||||
/**
|
||||
* Finish the signing process.
|
||||
*
|
||||
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||
* @param esp_ds_ctx the context object retreived by \c esp_ds_start_sign()
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||
* since the message digest matches.
|
||||
*/
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx);
|
||||
|
||||
/**
|
||||
* Encrypt the private key parameters.
|
||||
*
|
||||
* @param data Output buffer to store encrypted data, suitable for later use generating signatures.
|
||||
* The allocated memory must be in internal memory and word aligned since it's filled by DMA. Both is asserted
|
||||
* at run time.
|
||||
* @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time.
|
||||
* @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process
|
||||
* is done and 'data' is stored.
|
||||
* @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the
|
||||
* corresponding HMAC key will be stored to efuse and then permanently erased.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long
|
||||
*/
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_hmac.h"
|
||||
#include "esp_err.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_ds_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_DS_IV_LEN 16
|
||||
|
||||
/* Length of parameter 'C' stored in flash */
|
||||
#define ESP_DS_C_LEN (12672 / 8)
|
||||
|
||||
typedef struct esp_ds_context esp_ds_context_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_DS_RSA_1024 = (1024 / 32) - 1,
|
||||
ESP_DS_RSA_2048 = (2048 / 32) - 1,
|
||||
ESP_DS_RSA_3072 = (3072 / 32) - 1,
|
||||
ESP_DS_RSA_4096 = (4096 / 32) - 1
|
||||
} esp_digital_signature_length_t;
|
||||
|
||||
/**
|
||||
* Encrypted private key data. Recommended to store in flash in this format.
|
||||
*
|
||||
* @note This struct has to match to one from the ROM code! This documentation is mostly taken from there.
|
||||
*/
|
||||
typedef struct esp_digital_signature_data {
|
||||
/**
|
||||
* RSA LENGTH register parameters
|
||||
* (number of words in RSA key & operands, minus one).
|
||||
*
|
||||
* Max value 127 (for RSA 4096).
|
||||
*
|
||||
* This value must match the length field encrypted and stored in 'c',
|
||||
* or invalid results will be returned. (The DS peripheral will
|
||||
* always use the value in 'c', not this value, so an attacker can't
|
||||
* alter the DS peripheral results this way, it will just truncate or
|
||||
* extend the message and the resulting signature in software.)
|
||||
*
|
||||
* @note In IDF, the enum type length is the same as of type unsigned, so they can be used interchangably.
|
||||
* See the ROM code for the original declaration of struct \c ets_ds_data_t.
|
||||
*/
|
||||
esp_digital_signature_length_t rsa_length;
|
||||
|
||||
/**
|
||||
* IV value used to encrypt 'c'
|
||||
*/
|
||||
uint8_t iv[ESP_DS_IV_LEN];
|
||||
|
||||
/**
|
||||
* Encrypted Digital Signature parameters. Result of AES-CBC encryption
|
||||
* of plaintext values. Includes an encrypted message digest.
|
||||
*/
|
||||
uint8_t c[ESP_DS_C_LEN];
|
||||
} esp_ds_data_t;
|
||||
|
||||
/** Plaintext parameters used by Digital Signature.
|
||||
*
|
||||
* Not used for signing with DS peripheral, but can be encrypted
|
||||
* in-device by calling esp_ds_encrypt_params()
|
||||
*
|
||||
* @note This documentation is mostly taken from the ROM code.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t Y[SOC_RSA_MAX_BIT_LEN / 32]; //!< RSA exponent
|
||||
uint32_t M[SOC_RSA_MAX_BIT_LEN / 32]; //!< RSA modulus
|
||||
uint32_t Rb[SOC_RSA_MAX_BIT_LEN / 32]; //!< RSA r inverse operand
|
||||
uint32_t M_prime; //!< RSA M prime operand
|
||||
esp_digital_signature_length_t length; //!< RSA length
|
||||
} esp_ds_p_data_t;
|
||||
|
||||
/**
|
||||
* Sign the message.
|
||||
*
|
||||
* This function is a wrapper around \c esp_ds_finish_sign() and \c esp_ds_start_sign(), so do not use them
|
||||
* in parallel.
|
||||
* It blocks until the signing is finished and then returns the signature.
|
||||
*
|
||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||
* The RSA encryption operation is as follows:
|
||||
* Z = XY mod M where,
|
||||
* Z is the signature, X is the input message,
|
||||
* Y and M are the RSA private key parameters.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components during its entire execution time.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||
* signing key data
|
||||
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the signature was written to the parameter \c signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||
* since the message digest matches.
|
||||
*/
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature);
|
||||
|
||||
/**
|
||||
* Start the signing process.
|
||||
*
|
||||
* This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing
|
||||
* process.
|
||||
*
|
||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||
* The RSA encryption operation is as follows:
|
||||
* Z = XY mod M where,
|
||||
* Z is the signature, X is the input message,
|
||||
* Y and M are the RSA private key parameters.
|
||||
*
|
||||
* @note This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call
|
||||
* \c esp_ds_finish_sign() in a timely manner.
|
||||
*
|
||||
* @param message the message to be signed; its length should be (data->rsa_length +1 )*4 bytes
|
||||
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||
* signing key data
|
||||
* @param esp_ds_ctx the context object which is needed for finishing the signing process later
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation was started now and has to be finished with \c esp_ds_finish_sign()
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||
*/
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx);
|
||||
|
||||
/**
|
||||
* Return true if the DS peripheral is busy, otherwise false.
|
||||
*
|
||||
* @note Only valid if \c esp_ds_start_sign() was called before.
|
||||
*/
|
||||
bool esp_ds_is_busy(void);
|
||||
|
||||
/**
|
||||
* Finish the signing process.
|
||||
*
|
||||
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||
* @param esp_ds_ctx the context object retreived by \c esp_ds_start_sign()
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||
* since the message digest matches.
|
||||
*/
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx);
|
||||
|
||||
/**
|
||||
* Encrypt the private key parameters.
|
||||
*
|
||||
* @param data Output buffer to store encrypted data, suitable for later use generating signatures.
|
||||
* @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time.
|
||||
* @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process
|
||||
* is done and 'data' is stored.
|
||||
* @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the
|
||||
* corresponding HMAC key will be stored to efuse and then permanently erased.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long
|
||||
*/
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -4,11 +4,11 @@ set(srcs "rtc_clk_init.c"
|
||||
"rtc_pm.c"
|
||||
"rtc_sleep.c"
|
||||
"rtc_time.c"
|
||||
"chip_info.c")
|
||||
"chip_info.c"
|
||||
)
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "esp_crypto_lock.c"
|
||||
"esp_ds.c"
|
||||
"sar_periph_ctrl.c")
|
||||
|
||||
# init constructor for wifi
|
||||
|
@ -1,224 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_crypto_lock.h"
|
||||
#include "hal/ds_hal.h"
|
||||
#include "hal/ds_ll.h"
|
||||
#include "hal/hmac_hal.h"
|
||||
#include "esp32c3/rom/digital_signature.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_ds.h"
|
||||
|
||||
struct esp_ds_context {
|
||||
const esp_ds_data_t *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation.
|
||||
*/
|
||||
#define ESP_DS_SIGN_TASK_DELAY_MS 10
|
||||
|
||||
#define RSA_LEN_MAX 127
|
||||
|
||||
/*
|
||||
* esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used.
|
||||
* Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned),
|
||||
"The size of esp_digital_signature_length_t and unsigned has to be the same");
|
||||
|
||||
/*
|
||||
* esp_ds_data_t is used in the encryption function but casted to ets_ds_data_t.
|
||||
* Check esp_ds_data_t's width here because it's converted using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t),
|
||||
"The size of esp_ds_data_t and ets_ds_data_t has to be the same");
|
||||
|
||||
static void ds_acquire_enable(void)
|
||||
{
|
||||
esp_crypto_ds_lock_acquire();
|
||||
|
||||
// We also enable SHA and HMAC here. SHA is used by HMAC, HMAC is used by DS.
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
|
||||
hmac_hal_start();
|
||||
}
|
||||
|
||||
static void ds_disable_release(void)
|
||||
{
|
||||
ds_hal_finish();
|
||||
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
|
||||
esp_crypto_ds_lock_release();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature)
|
||||
{
|
||||
// Need to check signature here, otherwise the signature is only checked when the signing has finished and fails
|
||||
// but the signing isn't uninitialized and the mutex is still locked.
|
||||
if (!signature) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_ds_context_t *context;
|
||||
esp_err_t result = esp_ds_start_sign(message, data, key_id, &context);
|
||||
if (result != ESP_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
while (esp_ds_is_busy())
|
||||
vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS);
|
||||
|
||||
return esp_ds_finish_sign(signature, context);
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx)
|
||||
{
|
||||
if (!message || !data || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (key_id >= HMAC_KEY_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!(data->rsa_length == ESP_DS_RSA_1024
|
||||
|| data->rsa_length == ESP_DS_RSA_2048
|
||||
|| data->rsa_length == ESP_DS_RSA_3072)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ds_acquire_enable();
|
||||
|
||||
// initiate hmac
|
||||
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
|
||||
if (conf_error) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
|
||||
}
|
||||
|
||||
ds_hal_start();
|
||||
|
||||
// check encryption key from HMAC
|
||||
int64_t start_time = esp_timer_get_time();
|
||||
while (ds_ll_busy() != 0) {
|
||||
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t));
|
||||
if (!context) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
size_t rsa_len = (data->rsa_length + 1) * 4;
|
||||
ds_hal_write_private_key_params(data->c);
|
||||
ds_hal_configure_iv(data->iv);
|
||||
ds_hal_write_message(message, rsa_len);
|
||||
|
||||
// initiate signing
|
||||
ds_hal_start_sign();
|
||||
|
||||
context->data = data;
|
||||
*esp_ds_ctx = context;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool esp_ds_is_busy(void)
|
||||
{
|
||||
return ds_hal_busy();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
{
|
||||
if (!signature || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_ds_data_t *data = esp_ds_ctx->data;
|
||||
unsigned rsa_len = (data->rsa_length + 1) * 4;
|
||||
|
||||
while (ds_hal_busy()) { }
|
||||
|
||||
ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t*) signature, (size_t) rsa_len);
|
||||
|
||||
esp_err_t return_value = ESP_OK;
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||
}
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||
}
|
||||
|
||||
free(esp_ds_ctx);
|
||||
|
||||
hmac_hal_clean();
|
||||
|
||||
ds_disable_release();
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key)
|
||||
{
|
||||
if (!p_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
esp_crypto_ds_lock_acquire();
|
||||
periph_module_enable(PERIPH_AES_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_RSA_MODULE);
|
||||
|
||||
ets_ds_data_t *ds_data = (ets_ds_data_t*) data;
|
||||
const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t*) p_data;
|
||||
|
||||
ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC);
|
||||
|
||||
if (ets_result == ETS_DS_INVALID_PARAM) {
|
||||
result = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
periph_module_disable(PERIPH_RSA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_AES_MODULE);
|
||||
esp_crypto_ds_lock_release();
|
||||
|
||||
return result;
|
||||
}
|
@ -1,224 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_crypto_lock.h"
|
||||
#include "hal/ds_hal.h"
|
||||
#include "hal/ds_ll.h"
|
||||
#include "hal/hmac_hal.h"
|
||||
#include "esp32c6/rom/digital_signature.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_ds.h"
|
||||
|
||||
struct esp_ds_context {
|
||||
const esp_ds_data_t *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation.
|
||||
*/
|
||||
#define ESP_DS_SIGN_TASK_DELAY_MS 10
|
||||
|
||||
#define RSA_LEN_MAX 127
|
||||
|
||||
/*
|
||||
* esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used.
|
||||
* Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned),
|
||||
"The size of esp_digital_signature_length_t and unsigned has to be the same");
|
||||
|
||||
/*
|
||||
* esp_ds_data_t is used in the encryption function but casted to ets_ds_data_t.
|
||||
* Check esp_ds_data_t's width here because it's converted using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t),
|
||||
"The size of esp_ds_data_t and ets_ds_data_t has to be the same");
|
||||
|
||||
static void ds_acquire_enable(void)
|
||||
{
|
||||
esp_crypto_ds_lock_acquire();
|
||||
|
||||
// We also enable SHA and HMAC here. SHA is used by HMAC, HMAC is used by DS.
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
|
||||
hmac_hal_start();
|
||||
}
|
||||
|
||||
static void ds_disable_release(void)
|
||||
{
|
||||
ds_hal_finish();
|
||||
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
|
||||
esp_crypto_ds_lock_release();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature)
|
||||
{
|
||||
// Need to check signature here, otherwise the signature is only checked when the signing has finished and fails
|
||||
// but the signing isn't uninitialized and the mutex is still locked.
|
||||
if (!signature) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_ds_context_t *context;
|
||||
esp_err_t result = esp_ds_start_sign(message, data, key_id, &context);
|
||||
if (result != ESP_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
while (esp_ds_is_busy())
|
||||
vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS);
|
||||
|
||||
return esp_ds_finish_sign(signature, context);
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx)
|
||||
{
|
||||
if (!message || !data || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (key_id >= HMAC_KEY_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!(data->rsa_length == ESP_DS_RSA_1024
|
||||
|| data->rsa_length == ESP_DS_RSA_2048
|
||||
|| data->rsa_length == ESP_DS_RSA_3072)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ds_acquire_enable();
|
||||
|
||||
// initiate hmac
|
||||
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
|
||||
if (conf_error) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
|
||||
}
|
||||
|
||||
ds_hal_start();
|
||||
|
||||
// check encryption key from HMAC
|
||||
int64_t start_time = esp_timer_get_time();
|
||||
while (ds_ll_busy() != 0) {
|
||||
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t));
|
||||
if (!context) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
size_t rsa_len = (data->rsa_length + 1) * 4;
|
||||
ds_hal_write_private_key_params(data->c);
|
||||
ds_hal_configure_iv(data->iv);
|
||||
ds_hal_write_message(message, rsa_len);
|
||||
|
||||
// initiate signing
|
||||
ds_hal_start_sign();
|
||||
|
||||
context->data = data;
|
||||
*esp_ds_ctx = context;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool esp_ds_is_busy(void)
|
||||
{
|
||||
return ds_hal_busy();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
{
|
||||
if (!signature || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_ds_data_t *data = esp_ds_ctx->data;
|
||||
unsigned rsa_len = (data->rsa_length + 1) * 4;
|
||||
|
||||
while (ds_hal_busy()) { }
|
||||
|
||||
ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t*) signature, (size_t) rsa_len);
|
||||
|
||||
esp_err_t return_value = ESP_OK;
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||
}
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||
}
|
||||
|
||||
free(esp_ds_ctx);
|
||||
|
||||
hmac_hal_clean();
|
||||
|
||||
ds_disable_release();
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key)
|
||||
{
|
||||
if (!p_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
esp_crypto_ds_lock_acquire();
|
||||
periph_module_enable(PERIPH_AES_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_RSA_MODULE);
|
||||
|
||||
ets_ds_data_t *ds_data = (ets_ds_data_t*) data;
|
||||
const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t*) p_data;
|
||||
|
||||
ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC);
|
||||
|
||||
if (ets_result == ETS_DS_INVALID_PARAM) {
|
||||
result = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
periph_module_disable(PERIPH_RSA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_AES_MODULE);
|
||||
esp_crypto_ds_lock_release();
|
||||
|
||||
return result;
|
||||
}
|
@ -4,11 +4,11 @@ set(srcs "rtc_clk_init.c"
|
||||
"rtc_pm.c"
|
||||
"rtc_sleep.c"
|
||||
"rtc_time.c"
|
||||
"chip_info.c")
|
||||
"chip_info.c"
|
||||
)
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "esp_crypto_lock.c"
|
||||
"esp_ds.c"
|
||||
"sar_periph_ctrl.c")
|
||||
|
||||
if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
|
||||
|
@ -1,224 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_crypto_lock.h"
|
||||
#include "hal/ds_hal.h"
|
||||
#include "hal/ds_ll.h"
|
||||
#include "hal/hmac_hal.h"
|
||||
#include "esp32h4/rom/digital_signature.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_ds.h"
|
||||
|
||||
struct esp_ds_context {
|
||||
const esp_ds_data_t *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation.
|
||||
*/
|
||||
#define ESP_DS_SIGN_TASK_DELAY_MS 10
|
||||
|
||||
#define RSA_LEN_MAX 127
|
||||
|
||||
/*
|
||||
* esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used.
|
||||
* Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned),
|
||||
"The size of esp_digital_signature_length_t and unsigned has to be the same");
|
||||
|
||||
/*
|
||||
* esp_ds_data_t is used in the encryption function but casted to ets_ds_data_t.
|
||||
* Check esp_ds_data_t's width here because it's converted using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t),
|
||||
"The size of esp_ds_data_t and ets_ds_data_t has to be the same");
|
||||
|
||||
static void ds_acquire_enable(void)
|
||||
{
|
||||
esp_crypto_ds_lock_acquire();
|
||||
|
||||
// We also enable SHA and HMAC here. SHA is used by HMAC, HMAC is used by DS.
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
|
||||
hmac_hal_start();
|
||||
}
|
||||
|
||||
static void ds_disable_release(void)
|
||||
{
|
||||
ds_hal_finish();
|
||||
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
|
||||
esp_crypto_ds_lock_release();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature)
|
||||
{
|
||||
// Need to check signature here, otherwise the signature is only checked when the signing has finished and fails
|
||||
// but the signing isn't uninitialized and the mutex is still locked.
|
||||
if (!signature) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_ds_context_t *context;
|
||||
esp_err_t result = esp_ds_start_sign(message, data, key_id, &context);
|
||||
if (result != ESP_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
while (esp_ds_is_busy())
|
||||
vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS);
|
||||
|
||||
return esp_ds_finish_sign(signature, context);
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx)
|
||||
{
|
||||
if (!message || !data || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (key_id >= HMAC_KEY_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!(data->rsa_length == ESP_DS_RSA_1024
|
||||
|| data->rsa_length == ESP_DS_RSA_2048
|
||||
|| data->rsa_length == ESP_DS_RSA_3072)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ds_acquire_enable();
|
||||
|
||||
// initiate hmac
|
||||
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
|
||||
if (conf_error) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
|
||||
}
|
||||
|
||||
ds_hal_start();
|
||||
|
||||
// check encryption key from HMAC
|
||||
int64_t start_time = esp_timer_get_time();
|
||||
while (ds_ll_busy() != 0) {
|
||||
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t));
|
||||
if (!context) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
size_t rsa_len = (data->rsa_length + 1) * 4;
|
||||
ds_hal_write_private_key_params(data->c);
|
||||
ds_hal_configure_iv(data->iv);
|
||||
ds_hal_write_message(message, rsa_len);
|
||||
|
||||
// initiate signing
|
||||
ds_hal_start_sign();
|
||||
|
||||
context->data = data;
|
||||
*esp_ds_ctx = context;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool esp_ds_is_busy(void)
|
||||
{
|
||||
return ds_hal_busy();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
{
|
||||
if (!signature || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_ds_data_t *data = esp_ds_ctx->data;
|
||||
unsigned rsa_len = (data->rsa_length + 1) * 4;
|
||||
|
||||
while (ds_hal_busy()) { }
|
||||
|
||||
ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t*) signature, (size_t) rsa_len);
|
||||
|
||||
esp_err_t return_value = ESP_OK;
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||
}
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||
}
|
||||
|
||||
free(esp_ds_ctx);
|
||||
|
||||
hmac_hal_clean();
|
||||
|
||||
ds_disable_release();
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key)
|
||||
{
|
||||
if (!p_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
esp_crypto_ds_lock_acquire();
|
||||
periph_module_enable(PERIPH_AES_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_RSA_MODULE);
|
||||
|
||||
ets_ds_data_t *ds_data = (ets_ds_data_t*) data;
|
||||
const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t*) p_data;
|
||||
|
||||
ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC);
|
||||
|
||||
if (ets_result == ETS_DS_INVALID_PARAM) {
|
||||
result = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
periph_module_disable(PERIPH_RSA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_AES_MODULE);
|
||||
esp_crypto_ds_lock_release();
|
||||
|
||||
return result;
|
||||
}
|
@ -13,7 +13,6 @@ set(srcs
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "memprot.c"
|
||||
"esp_crypto_lock.c"
|
||||
"esp_ds.c"
|
||||
"sar_periph_ctrl.c")
|
||||
|
||||
# init constructor for wifi
|
||||
|
@ -1,193 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "esp32s2/rom/aes.h"
|
||||
#include "esp32s2/rom/sha.h"
|
||||
#include "esp32s2/rom/hmac.h"
|
||||
#include "esp32s2/rom/digital_signature.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "esp_crypto_lock.h"
|
||||
#include "esp_hmac.h"
|
||||
|
||||
#include "esp_ds.h"
|
||||
|
||||
struct esp_ds_context {
|
||||
const ets_ds_data_t *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation.
|
||||
*/
|
||||
#define ESP_DS_SIGN_TASK_DELAY_MS 10
|
||||
|
||||
#define RSA_LEN_MAX 127
|
||||
|
||||
/*
|
||||
* Check that the size of esp_ds_data_t and ets_ds_data_t is the same because both structs are converted using
|
||||
* raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t),
|
||||
"The size and structure of esp_ds_data_t and ets_ds_data_t must match exactly, they're used in raw casts");
|
||||
|
||||
/*
|
||||
* esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used.
|
||||
* Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned),
|
||||
"The size of esp_digital_signature_length_t and unsigned has to be the same");
|
||||
|
||||
static void ds_acquire_enable(void) {
|
||||
/* Lock AES, SHA and RSA peripheral */
|
||||
esp_crypto_dma_lock_acquire();
|
||||
esp_crypto_mpi_lock_acquire();
|
||||
ets_hmac_enable();
|
||||
ets_ds_enable();
|
||||
}
|
||||
|
||||
static void ds_disable_release(void) {
|
||||
ets_ds_disable();
|
||||
ets_hmac_disable();
|
||||
esp_crypto_mpi_lock_release();
|
||||
esp_crypto_dma_lock_release();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature)
|
||||
{
|
||||
// Need to check signature here, otherwise the signature is only checked when the signing has finished and fails
|
||||
// but the signing isn't uninitialized and the mutex is still locked.
|
||||
if (!signature) return ESP_ERR_INVALID_ARG;
|
||||
|
||||
esp_ds_context_t *context;
|
||||
esp_err_t result = esp_ds_start_sign(message, data, key_id, &context);
|
||||
if (result != ESP_OK) return result;
|
||||
|
||||
while (esp_ds_is_busy())
|
||||
vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS);
|
||||
|
||||
return esp_ds_finish_sign(signature, context);
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx)
|
||||
{
|
||||
if (!message || !data || !esp_ds_ctx) return ESP_ERR_INVALID_ARG;
|
||||
if (key_id >= HMAC_KEY_MAX) return ESP_ERR_INVALID_ARG;
|
||||
if (!(data->rsa_length == ESP_DS_RSA_1024
|
||||
|| data->rsa_length == ESP_DS_RSA_2048
|
||||
|| data->rsa_length == ESP_DS_RSA_3072
|
||||
|| data->rsa_length == ESP_DS_RSA_4096)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ds_acquire_enable();
|
||||
|
||||
// initiate hmac
|
||||
int r = ets_hmac_calculate_downstream(ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id,
|
||||
ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
|
||||
if (r != ETS_OK) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
|
||||
}
|
||||
|
||||
esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t));
|
||||
if (!context) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
ets_ds_data_t *ds_data = (ets_ds_data_t*) data;
|
||||
|
||||
// initiate signing
|
||||
ets_ds_result_t result = ets_ds_start_sign(message, ds_data);
|
||||
|
||||
// ETS_DS_INVALID_PARAM only happens if a parameter is NULL or data->rsa_length is wrong
|
||||
// We checked all of that already
|
||||
assert(result != ETS_DS_INVALID_PARAM);
|
||||
|
||||
if (result == ETS_DS_INVALID_KEY) {
|
||||
ds_disable_release();
|
||||
free(context);
|
||||
return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
|
||||
}
|
||||
|
||||
context->data = ds_data;
|
||||
*esp_ds_ctx = context;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool esp_ds_is_busy(void)
|
||||
{
|
||||
return ets_ds_is_busy();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
{
|
||||
if (!signature || !esp_ds_ctx) return ESP_ERR_INVALID_ARG;
|
||||
|
||||
const ets_ds_data_t *ds_data = esp_ds_ctx->data;
|
||||
|
||||
ets_ds_result_t result = ets_ds_finish_sign(signature, ds_data);
|
||||
|
||||
esp_err_t return_value = ESP_OK;
|
||||
|
||||
// we checked all the parameters
|
||||
assert(result != ETS_DS_INVALID_PARAM);
|
||||
|
||||
if (result == ETS_DS_INVALID_DIGEST) return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||
if (result == ETS_DS_INVALID_PADDING) return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||
|
||||
free(esp_ds_ctx);
|
||||
|
||||
int res = ets_hmac_invalidate_downstream(ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
|
||||
assert(res == ETS_OK); // should not fail if called with correct purpose
|
||||
(void)res;
|
||||
|
||||
ds_disable_release();
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key)
|
||||
{
|
||||
// p_data has to be valid, in internal memory and word aligned
|
||||
if (!p_data) return ESP_ERR_INVALID_ARG;
|
||||
assert(esp_ptr_internal(p_data) && esp_ptr_word_aligned(p_data));
|
||||
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
esp_crypto_dma_lock_acquire();
|
||||
ets_aes_enable();
|
||||
ets_sha_enable();
|
||||
|
||||
ets_ds_data_t *ds_data = (ets_ds_data_t*) data;
|
||||
const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t*) p_data;
|
||||
|
||||
ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC);
|
||||
|
||||
if (ets_result == ETS_DS_INVALID_PARAM) result = ESP_ERR_INVALID_ARG;
|
||||
|
||||
ets_sha_disable();
|
||||
ets_aes_disable();
|
||||
esp_crypto_dma_lock_release();
|
||||
|
||||
return result;
|
||||
}
|
@ -8,11 +8,11 @@ set(srcs
|
||||
"rtc_pm.c"
|
||||
"rtc_sleep.c"
|
||||
"rtc_time.c"
|
||||
"chip_info.c")
|
||||
"chip_info.c"
|
||||
)
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "esp_ds.c"
|
||||
"esp_crypto_lock.c"
|
||||
list(APPEND srcs "esp_crypto_lock.c"
|
||||
"sar_periph_ctrl.c")
|
||||
|
||||
if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
|
||||
|
@ -1,228 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_crypto_lock.h"
|
||||
#include "hal/ds_hal.h"
|
||||
#include "hal/ds_ll.h"
|
||||
#include "hal/hmac_hal.h"
|
||||
#include "esp32s3/rom/digital_signature.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_ds.h"
|
||||
|
||||
struct esp_ds_context {
|
||||
const esp_ds_data_t *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation.
|
||||
*/
|
||||
#define ESP_DS_SIGN_TASK_DELAY_MS 10
|
||||
|
||||
#define RSA_LEN_MAX 127
|
||||
|
||||
/*
|
||||
* esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used.
|
||||
* Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned),
|
||||
"The size of esp_digital_signature_length_t and unsigned has to be the same");
|
||||
|
||||
/*
|
||||
* esp_ds_data_t is used in the encryption function but casted to ets_ds_data_t.
|
||||
* Check esp_ds_data_t's width here because it's converted using raw casts.
|
||||
*/
|
||||
_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t),
|
||||
"The size of esp_ds_data_t and ets_ds_data_t has to be the same");
|
||||
|
||||
static void ds_acquire_enable(void)
|
||||
{
|
||||
esp_crypto_ds_lock_acquire();
|
||||
esp_crypto_mpi_lock_acquire();
|
||||
|
||||
// We also enable SHA and HMAC here. SHA is used by HMAC, HMAC is used by DS.
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
|
||||
hmac_hal_start();
|
||||
}
|
||||
|
||||
static void ds_disable_release(void)
|
||||
{
|
||||
ds_hal_finish();
|
||||
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
|
||||
esp_crypto_mpi_lock_release();
|
||||
esp_crypto_ds_lock_release();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
void *signature)
|
||||
{
|
||||
// Need to check signature here, otherwise the signature is only checked when the signing has finished and fails
|
||||
// but the signing isn't uninitialized and the mutex is still locked.
|
||||
if (!signature) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_ds_context_t *context;
|
||||
esp_err_t result = esp_ds_start_sign(message, data, key_id, &context);
|
||||
if (result != ESP_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
while (esp_ds_is_busy()) {
|
||||
vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
return esp_ds_finish_sign(signature, context);
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_start_sign(const void *message,
|
||||
const esp_ds_data_t *data,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx)
|
||||
{
|
||||
if (!message || !data || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (key_id >= HMAC_KEY_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!(data->rsa_length == ESP_DS_RSA_1024
|
||||
|| data->rsa_length == ESP_DS_RSA_2048
|
||||
|| data->rsa_length == ESP_DS_RSA_3072
|
||||
|| data->rsa_length == ESP_DS_RSA_4096)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ds_acquire_enable();
|
||||
|
||||
// initiate hmac
|
||||
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
|
||||
if (conf_error) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL;
|
||||
}
|
||||
|
||||
ds_hal_start();
|
||||
|
||||
// check encryption key from HMAC
|
||||
int64_t start_time = esp_timer_get_time();
|
||||
while (ds_ll_busy() != 0) {
|
||||
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_HW_CRYPTO_DS_INVALID_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t));
|
||||
if (!context) {
|
||||
ds_disable_release();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
size_t rsa_len = (data->rsa_length + 1) * 4;
|
||||
ds_hal_write_private_key_params(data->c);
|
||||
ds_hal_configure_iv((uint32_t *)data->iv);
|
||||
ds_hal_write_message(message, rsa_len);
|
||||
|
||||
// initiate signing
|
||||
ds_hal_start_sign();
|
||||
|
||||
context->data = data;
|
||||
*esp_ds_ctx = context;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool esp_ds_is_busy(void)
|
||||
{
|
||||
return ds_hal_busy();
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
{
|
||||
if (!signature || !esp_ds_ctx) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_ds_data_t *data = esp_ds_ctx->data;
|
||||
unsigned rsa_len = (data->rsa_length + 1) * 4;
|
||||
|
||||
while (ds_hal_busy()) { }
|
||||
|
||||
ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t *) signature, (size_t) rsa_len);
|
||||
|
||||
esp_err_t return_value = ESP_OK;
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||
}
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||
}
|
||||
|
||||
free(esp_ds_ctx);
|
||||
|
||||
hmac_hal_clean();
|
||||
|
||||
ds_disable_release();
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
const void *iv,
|
||||
const esp_ds_p_data_t *p_data,
|
||||
const void *key)
|
||||
{
|
||||
if (!p_data) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t result = ESP_OK;
|
||||
|
||||
esp_crypto_ds_lock_acquire();
|
||||
periph_module_enable(PERIPH_AES_MODULE);
|
||||
periph_module_enable(PERIPH_DS_MODULE);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||
periph_module_enable(PERIPH_RSA_MODULE);
|
||||
|
||||
ets_ds_data_t *ds_data = (ets_ds_data_t *) data;
|
||||
const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t *) p_data;
|
||||
|
||||
ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC);
|
||||
|
||||
if (ets_result == ETS_DS_INVALID_PARAM) {
|
||||
result = ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
periph_module_disable(PERIPH_RSA_MODULE);
|
||||
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
periph_module_disable(PERIPH_DS_MODULE);
|
||||
periph_module_disable(PERIPH_AES_MODULE);
|
||||
esp_crypto_ds_lock_release();
|
||||
|
||||
return result;
|
||||
}
|
@ -141,7 +141,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"xt_wdt_hal.c"
|
||||
"aes_hal.c"
|
||||
"esp32s3/brownout_hal.c"
|
||||
"esp32s3/hmac_hal.c"
|
||||
"hmac_hal.c"
|
||||
"esp32s3/touch_sensor_hal.c"
|
||||
"esp32s3/rtc_cntl_hal.c"
|
||||
"usb_dwc_hal.c")
|
||||
@ -155,7 +155,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"xt_wdt_hal.c"
|
||||
"aes_hal.c"
|
||||
"esp32c3/brownout_hal.c"
|
||||
"esp32c3/hmac_hal.c"
|
||||
"hmac_hal.c"
|
||||
"esp32c3/rtc_cntl_hal.c")
|
||||
endif()
|
||||
|
||||
@ -166,7 +166,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"spi_slave_hd_hal.c"
|
||||
"aes_hal.c"
|
||||
"esp32h4/brownout_hal.c"
|
||||
"esp32h4/hmac_hal.c"
|
||||
"hmac_hal.c"
|
||||
"esp32h4/rtc_cntl_hal.c")
|
||||
endif()
|
||||
|
||||
|
@ -1,83 +0,0 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "stdio.h"
|
||||
#include "hal/hmac_hal.h"
|
||||
#include "hal/hmac_ll.h"
|
||||
|
||||
void hmac_hal_start(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_start();
|
||||
}
|
||||
|
||||
uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_config_output(config);
|
||||
hmac_ll_config_hw_key_id(key_id);
|
||||
hmac_ll_config_finish();
|
||||
hmac_ll_wait_idle();
|
||||
|
||||
uint32_t conf_error = hmac_ll_config_error();
|
||||
if (conf_error) {
|
||||
hmac_ll_calc_finish();
|
||||
return 1;
|
||||
} else if (config != HMAC_OUTPUT_USER) {
|
||||
// In "downstream" mode, this will be the last hmac operation. Make sure HMAC is ready for
|
||||
// the other peripheral.
|
||||
hmac_ll_wait_idle();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hmac_hal_write_one_block_512(const void *block)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_write_block_512(block);
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_msg_one_block();
|
||||
}
|
||||
|
||||
void hmac_hal_write_block_512(const void *block)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_write_block_512(block);
|
||||
}
|
||||
|
||||
void hmac_hal_next_block_padding(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_msg_padding();
|
||||
}
|
||||
|
||||
void hmac_hal_next_block_normal(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_msg_continue();
|
||||
}
|
||||
|
||||
void hmac_hal_read_result_256(void *result)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_read_result_256(result);
|
||||
hmac_ll_calc_finish();
|
||||
}
|
||||
|
||||
void hmac_hal_clean(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_clean();
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use it in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The HMAC peripheral can be configured to deliver its output to the user directly, or to deliver
|
||||
* the output directly to another peripheral instead, e.g. the Digital Signature peripheral.
|
||||
*/
|
||||
typedef enum {
|
||||
HMAC_OUTPUT_USER = 0, /**< Let user provide a message and read the HMAC result */
|
||||
HMAC_OUTPUT_DS = 1, /**< HMAC is provided to the DS peripheral to decrypt DS private key parameters */
|
||||
HMAC_OUTPUT_JTAG_ENABLE = 2, /**< HMAC is used to enable JTAG after soft-disabling it */
|
||||
HMAC_OUTPUT_ALL = 3 /**< HMAC is used for both as DS input for or enabling JTAG */
|
||||
} hmac_hal_output_t;
|
||||
|
||||
/**
|
||||
* @brief Make the peripheral ready for use.
|
||||
*
|
||||
* This triggers any further steps necessary after enabling the device
|
||||
*/
|
||||
void hmac_hal_start(void);
|
||||
|
||||
/**
|
||||
* @brief Configure which hardware key slot should be used and configure the target of the HMAC output.
|
||||
*
|
||||
* @note Writing out-of-range values is undefined behavior. The user has to ensure that the parameters are in range.
|
||||
*
|
||||
* @param config The target of the HMAC. Possible targets are described in \c hmac_hal_output_t.
|
||||
* See the ESP32C3 TRM for more details.
|
||||
* @param key_id The ID of the hardware key slot to be used.
|
||||
*
|
||||
* @return 0 if the configuration was successful, non-zero if not.
|
||||
* An unsuccessful configuration means that the purpose value in the eFuse of the corresponding key slot
|
||||
* doesn't match to supplied value of \c config.
|
||||
*/
|
||||
uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id);
|
||||
|
||||
/**
|
||||
* @brief Write a padded single-block message of 512 bits to the HMAC peripheral.
|
||||
*
|
||||
* The message must not be longer than one block (512 bits) and the padding has to be applied by software before
|
||||
* writing. The padding has to be able to fit into the block after the message.
|
||||
* For more information on HMAC padding, see the ESP32C3 TRM.
|
||||
*/
|
||||
void hmac_hal_write_one_block_512(const void *block);
|
||||
|
||||
/**
|
||||
* @brief Write a message block of 512 bits to the HMAC peripheral.
|
||||
*
|
||||
* This function must be used incombination with \c hmac_hal_next_block_normal() or \c hmac_hal_next_block_padding().
|
||||
* The first message block is written without any prerequisite.
|
||||
* All message blocks which are not the last one, need a call to \c hmac_hal_next_block_normal() before, indicating
|
||||
* to the hardware that a "normal", i.e. non-padded block will follow. This is even the case for a block which begins
|
||||
* padding already but where the padding doesn't fit in (remaining message size > (block size - padding size)).
|
||||
* Before writing the last block which contains the padding, a call to \c hmac_hal_next_block_padding() is necessary
|
||||
* to indicate to the hardware that a block with padding will be written.
|
||||
*
|
||||
* For more information on HMAC padding, see the ESP32C3 TRM.
|
||||
*/
|
||||
void hmac_hal_write_block_512(const void *block);
|
||||
|
||||
/**
|
||||
* @brief Indicate to the hardware that a normal block will be written.
|
||||
*/
|
||||
void hmac_hal_next_block_normal(void);
|
||||
|
||||
/**
|
||||
* @brief Indicate to the hardware that a block with padding will be written.
|
||||
*/
|
||||
void hmac_hal_next_block_padding(void);
|
||||
|
||||
/**
|
||||
* @brief Read the 256 bit HMAC result from the hardware.
|
||||
*/
|
||||
void hmac_hal_read_result_256(void *result);
|
||||
|
||||
/**
|
||||
* @brief Clear (invalidate) the HMAC result provided to other hardware.
|
||||
*/
|
||||
void hmac_hal_clean(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "hal/hmac_hal.h"
|
||||
#include "hal/hmac_ll.h"
|
||||
|
||||
void hmac_hal_start(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_start();
|
||||
}
|
||||
|
||||
uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_config_output(config);
|
||||
hmac_ll_config_hw_key_id(key_id);
|
||||
hmac_ll_config_finish();
|
||||
hmac_ll_wait_idle();
|
||||
|
||||
uint32_t conf_error = hmac_ll_query_config_error();
|
||||
if (conf_error) {
|
||||
hmac_ll_calc_finish();
|
||||
return 1;
|
||||
} else if (config != HMAC_OUTPUT_USER) {
|
||||
// In "downstream" mode, this will be the last hmac operation. Make sure HMAC is ready for
|
||||
// the other peripheral.
|
||||
hmac_ll_wait_idle();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hmac_hal_write_one_block_512(const void *block)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_write_block_512(block);
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_msg_one_block();
|
||||
}
|
||||
|
||||
void hmac_hal_write_block_512(const void *block)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_write_block_512(block);
|
||||
}
|
||||
|
||||
void hmac_hal_next_block_padding(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_msg_padding();
|
||||
}
|
||||
|
||||
void hmac_hal_next_block_normal(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_msg_continue();
|
||||
}
|
||||
|
||||
void hmac_hal_read_result_256(void *result)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_read_result_256(result);
|
||||
hmac_ll_calc_finish();
|
||||
}
|
||||
|
||||
void hmac_hal_clean(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_clean();
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use it in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The HMAC peripheral can be configured to deliver its output to the user directly, or to deliver
|
||||
* the output directly to another peripheral instead, e.g. the Digital Signature peripheral.
|
||||
*/
|
||||
typedef enum {
|
||||
HMAC_OUTPUT_USER = 0, /**< Let user provide a message and read the HMAC result */
|
||||
HMAC_OUTPUT_DS = 1, /**< HMAC is provided to the DS peripheral to decrypt DS private key parameters */
|
||||
HMAC_OUTPUT_JTAG_ENABLE = 2, /**< HMAC is used to enable JTAG after soft-disabling it */
|
||||
HMAC_OUTPUT_ALL = 3 /**< HMAC is used for both as DS input for or enabling JTAG */
|
||||
} hmac_hal_output_t;
|
||||
|
||||
/**
|
||||
* @brief Make the peripheral ready for use.
|
||||
*
|
||||
* This triggers any further steps necessary after enabling the device
|
||||
*/
|
||||
void hmac_hal_start(void);
|
||||
|
||||
/**
|
||||
* @brief Configure which hardware key slot should be used and configure the target of the HMAC output.
|
||||
*
|
||||
* @note Writing out-of-range values is undefined behavior. The user has to ensure that the parameters are in range.
|
||||
*
|
||||
* @param config The target of the HMAC. Possible targets are described in \c hmac_hal_output_t.
|
||||
* See the ESP32S3 TRM for more details.
|
||||
* @param key_id The ID of the hardware key slot to be used.
|
||||
*
|
||||
* @return 0 if the configuration was successful, non-zero if not.
|
||||
* An unsuccessful configuration means that the purpose value in the eFuse of the corresponding key slot
|
||||
* doesn't match to supplied value of \c config.
|
||||
*/
|
||||
uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id);
|
||||
|
||||
/**
|
||||
* @brief Write a padded single-block message of 512 bits to the HMAC peripheral.
|
||||
*
|
||||
* The message must not be longer than one block (512 bits) and the padding has to be applied by software before
|
||||
* writing. The padding has to be able to fit into the block after the message.
|
||||
* For more information on HMAC padding, see the ESP32S3 TRM.
|
||||
*/
|
||||
void hmac_hal_write_one_block_512(const void *block);
|
||||
|
||||
/**
|
||||
* @brief Write a message block of 512 bits to the HMAC peripheral.
|
||||
*
|
||||
* This function must be used incombination with \c hmac_hal_next_block_normal() or \c hmac_hal_next_block_padding().
|
||||
* The first message block is written without any prerequisite.
|
||||
* All message blocks which are not the last one, need a call to \c hmac_hal_next_block_normal() before, indicating
|
||||
* to the hardware that a "normal", i.e. non-padded block will follow. This is even the case for a block which begins
|
||||
* padding already but where the padding doesn't fit in (remaining message size > (block size - padding size)).
|
||||
* Before writing the last block which contains the padding, a call to \c hmac_hal_next_block_padding() is necessary
|
||||
* to indicate to the hardware that a block with padding will be written.
|
||||
*
|
||||
* For more information on HMAC padding, see the ESP32S3 TRM.
|
||||
*/
|
||||
void hmac_hal_write_block_512(const void *block);
|
||||
|
||||
/**
|
||||
* @brief Indicate to the hardware that a normal block will be written.
|
||||
*/
|
||||
void hmac_hal_next_block_normal(void);
|
||||
|
||||
/**
|
||||
* @brief Indicate to the hardware that a block with padding will be written.
|
||||
*/
|
||||
void hmac_hal_next_block_padding(void);
|
||||
|
||||
/**
|
||||
* @brief Read the 256 bit HMAC result from the hardware.
|
||||
*/
|
||||
void hmac_hal_read_result_256(void *result);
|
||||
|
||||
/**
|
||||
* @brief Clear (invalidate) the HMAC result provided to other hardware.
|
||||
*/
|
||||
void hmac_hal_clean(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -87,7 +87,7 @@ static inline void hmac_ll_config_finish(void)
|
||||
* - 1 or greater on error
|
||||
* - 0 on success
|
||||
*/
|
||||
static inline uint32_t hmac_ll_query_config_error(void)
|
||||
static inline uint32_t hmac_ll_config_error(void)
|
||||
{
|
||||
return REG_READ(HMAC_QUERY_ERROR_REG);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ void hmac_hal_start(void);
|
||||
* @note Writing out-of-range values is undefined behavior. The user has to ensure that the parameters are in range.
|
||||
*
|
||||
* @param config The target of the HMAC. Possible targets are described in \c hmac_hal_output_t.
|
||||
* See the ESP32H4 TRM for more details.
|
||||
* See the TRM of your target chip for more details.
|
||||
* @param key_id The ID of the hardware key slot to be used.
|
||||
*
|
||||
* @return 0 if the configuration was successful, non-zero if not.
|
||||
@ -57,7 +57,7 @@ uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id);
|
||||
*
|
||||
* The message must not be longer than one block (512 bits) and the padding has to be applied by software before
|
||||
* writing. The padding has to be able to fit into the block after the message.
|
||||
* For more information on HMAC padding, see the ESP32H4 TRM.
|
||||
* For more information on HMAC padding, see the TRM of your target chip.
|
||||
*/
|
||||
void hmac_hal_write_one_block_512(const void *block);
|
||||
|
||||
@ -72,7 +72,7 @@ void hmac_hal_write_one_block_512(const void *block);
|
||||
* Before writing the last block which contains the padding, a call to \c hmac_hal_next_block_padding() is necessary
|
||||
* to indicate to the hardware that a block with padding will be written.
|
||||
*
|
||||
* For more information on HMAC padding, see the ESP32H4 TRM.
|
||||
* For more information on HMAC padding, see the TRM of your target chip for more details.
|
||||
*/
|
||||
void hmac_hal_write_block_512(const void *block);
|
||||
|
@ -137,6 +137,7 @@ INPUT = \
|
||||
$(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_etm.h \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_ds.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_mac.h \
|
||||
|
@ -1,2 +1 @@
|
||||
INPUT += \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
||||
|
@ -1,2 +1 @@
|
||||
INPUT += \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
||||
|
@ -1,2 +1 @@
|
||||
INPUT += \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
||||
|
@ -1,6 +1,5 @@
|
||||
INPUT += \
|
||||
$(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/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/touch_sensor_channel.h \
|
||||
|
@ -1,6 +1,5 @@
|
||||
INPUT += \
|
||||
$(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/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_fsm/include/$(IDF_TARGET)/ulp.h \
|
||||
|
Loading…
Reference in New Issue
Block a user