forked from espressif/esp-idf
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:
@@ -57,6 +57,10 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
list(APPEND srcs "esp_etm.c")
|
list(APPEND srcs "esp_etm.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_SOC_DIG_SIGN_SUPPORTED)
|
||||||
|
list(APPEND srcs "esp_ds.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
# ESP32C6-TODO
|
# ESP32C6-TODO
|
||||||
if(CONFIG_IDF_TARGET_ESP32C6)
|
if(CONFIG_IDF_TARGET_ESP32C6)
|
||||||
list(REMOVE_ITEM srcs
|
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
|
#pragma once
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "esp_hmac.h"
|
#include "esp_hmac.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_ds_err.h"
|
#include "esp_ds_err.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define ESP_DS_IV_BIT_LEN 128
|
#define ESP_DS_IV_BIT_LEN 128
|
||||||
#define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8)
|
#define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8)
|
||||||
#define ESP_DS_SIGNATURE_MAX_BIT_LEN 3072
|
#define ESP_DS_SIGNATURE_MAX_BIT_LEN SOC_RSA_MAX_BIT_LEN
|
||||||
#define ESP_DS_SIGNATURE_MD_BIT_LEN 256
|
#define ESP_DS_SIGNATURE_MD_BIT_LEN 256
|
||||||
#define ESP_DS_SIGNATURE_M_PRIME_BIT_LEN 32
|
#define ESP_DS_SIGNATURE_M_PRIME_BIT_LEN 32
|
||||||
#define ESP_DS_SIGNATURE_L_BIT_LEN 32
|
#define ESP_DS_SIGNATURE_L_BIT_LEN 32
|
||||||
#define ESP_DS_SIGNATURE_PADDING_BIT_LEN 64
|
#define ESP_DS_SIGNATURE_PADDING_BIT_LEN 64
|
||||||
|
|
||||||
/* Length of parameter 'C' stored in flash, in bytes
|
/* 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
|
- Operand MD (message digest); 256 bits
|
||||||
- Operands M' and L; each 32 bits
|
- Operands M' and L; each 32 bits
|
||||||
- Operand beta (padding value; 64 bits
|
- Operand beta (padding value; 64 bits
|
||||||
@@ -40,7 +41,8 @@ typedef struct esp_ds_context esp_ds_context_t;
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
ESP_DS_RSA_1024 = (1024 / 32) - 1,
|
ESP_DS_RSA_1024 = (1024 / 32) - 1,
|
||||||
ESP_DS_RSA_2048 = (2048 / 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;
|
} esp_digital_signature_length_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,8 +55,6 @@ typedef struct esp_digital_signature_data {
|
|||||||
* RSA LENGTH register parameters
|
* RSA LENGTH register parameters
|
||||||
* (number of words in RSA key & operands, minus one).
|
* (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',
|
* This value must match the length field encrypted and stored in 'c',
|
||||||
* or invalid results will be returned. (The DS peripheral will
|
* or invalid results will be returned. (The DS peripheral will
|
||||||
* always use the value in 'c', not this value, so an attacker can't
|
* always use the value in 'c', not this value, so an attacker can't
|
||||||
@@ -105,7 +105,8 @@ typedef struct {
|
|||||||
* in parallel.
|
* in parallel.
|
||||||
* It blocks until the signing is finished and then returns the signature.
|
* 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 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 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
|
* This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing
|
||||||
* process.
|
* process.
|
||||||
*
|
|
||||||
* The function calculates a plain RSA signature with help of the DS peripheral.
|
* The function calculates a plain RSA signature with help of the DS peripheral.
|
||||||
* The RSA encryption operation is as follows:
|
* The RSA encryption operation is as follows:
|
||||||
* Z = XY mod M where,
|
* Z = XY mod M where,
|
||||||
* Z is the signature, X is the input message,
|
* Z is the signature, X is the input message,
|
||||||
* Y and M are the RSA private key parameters.
|
* 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
|
* @note
|
||||||
* \c esp_ds_finish_sign() in a timely manner.
|
* 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 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 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
|
* @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.
|
* 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
|
* @return
|
||||||
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
* - 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_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_pm.c"
|
||||||
"rtc_sleep.c"
|
"rtc_sleep.c"
|
||||||
"rtc_time.c"
|
"rtc_time.c"
|
||||||
"chip_info.c")
|
"chip_info.c"
|
||||||
|
)
|
||||||
|
|
||||||
if(NOT BOOTLOADER_BUILD)
|
if(NOT BOOTLOADER_BUILD)
|
||||||
list(APPEND srcs "esp_crypto_lock.c"
|
list(APPEND srcs "esp_crypto_lock.c"
|
||||||
"esp_ds.c"
|
|
||||||
"sar_periph_ctrl.c")
|
"sar_periph_ctrl.c")
|
||||||
|
|
||||||
# init constructor for wifi
|
# 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_pm.c"
|
||||||
"rtc_sleep.c"
|
"rtc_sleep.c"
|
||||||
"rtc_time.c"
|
"rtc_time.c"
|
||||||
"chip_info.c")
|
"chip_info.c"
|
||||||
|
)
|
||||||
|
|
||||||
if(NOT BOOTLOADER_BUILD)
|
if(NOT BOOTLOADER_BUILD)
|
||||||
list(APPEND srcs "esp_crypto_lock.c"
|
list(APPEND srcs "esp_crypto_lock.c"
|
||||||
"esp_ds.c"
|
|
||||||
"sar_periph_ctrl.c")
|
"sar_periph_ctrl.c")
|
||||||
|
|
||||||
if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
|
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)
|
if(NOT BOOTLOADER_BUILD)
|
||||||
list(APPEND srcs "memprot.c"
|
list(APPEND srcs "memprot.c"
|
||||||
"esp_crypto_lock.c"
|
"esp_crypto_lock.c"
|
||||||
"esp_ds.c"
|
|
||||||
"sar_periph_ctrl.c")
|
"sar_periph_ctrl.c")
|
||||||
|
|
||||||
# init constructor for wifi
|
# 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_pm.c"
|
||||||
"rtc_sleep.c"
|
"rtc_sleep.c"
|
||||||
"rtc_time.c"
|
"rtc_time.c"
|
||||||
"chip_info.c")
|
"chip_info.c"
|
||||||
|
)
|
||||||
|
|
||||||
if(NOT BOOTLOADER_BUILD)
|
if(NOT BOOTLOADER_BUILD)
|
||||||
list(APPEND srcs "esp_ds.c"
|
list(APPEND srcs "esp_crypto_lock.c"
|
||||||
"esp_crypto_lock.c"
|
|
||||||
"sar_periph_ctrl.c")
|
"sar_periph_ctrl.c")
|
||||||
|
|
||||||
if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
|
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"
|
"xt_wdt_hal.c"
|
||||||
"aes_hal.c"
|
"aes_hal.c"
|
||||||
"esp32s3/brownout_hal.c"
|
"esp32s3/brownout_hal.c"
|
||||||
"esp32s3/hmac_hal.c"
|
"hmac_hal.c"
|
||||||
"esp32s3/touch_sensor_hal.c"
|
"esp32s3/touch_sensor_hal.c"
|
||||||
"esp32s3/rtc_cntl_hal.c"
|
"esp32s3/rtc_cntl_hal.c"
|
||||||
"usb_dwc_hal.c")
|
"usb_dwc_hal.c")
|
||||||
@@ -155,7 +155,7 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
"xt_wdt_hal.c"
|
"xt_wdt_hal.c"
|
||||||
"aes_hal.c"
|
"aes_hal.c"
|
||||||
"esp32c3/brownout_hal.c"
|
"esp32c3/brownout_hal.c"
|
||||||
"esp32c3/hmac_hal.c"
|
"hmac_hal.c"
|
||||||
"esp32c3/rtc_cntl_hal.c")
|
"esp32c3/rtc_cntl_hal.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
"spi_slave_hd_hal.c"
|
"spi_slave_hd_hal.c"
|
||||||
"aes_hal.c"
|
"aes_hal.c"
|
||||||
"esp32h4/brownout_hal.c"
|
"esp32h4/brownout_hal.c"
|
||||||
"esp32h4/hmac_hal.c"
|
"hmac_hal.c"
|
||||||
"esp32h4/rtc_cntl_hal.c")
|
"esp32h4/rtc_cntl_hal.c")
|
||||||
endif()
|
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
|
* - 1 or greater on error
|
||||||
* - 0 on success
|
* - 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);
|
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.
|
* @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.
|
* @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.
|
* @param key_id The ID of the hardware key slot to be used.
|
||||||
*
|
*
|
||||||
* @return 0 if the configuration was successful, non-zero if not.
|
* @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
|
* 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.
|
* 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);
|
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
|
* 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.
|
* 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);
|
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_cpu.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_crc.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/esp_crc.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_etm.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_hmac.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_alloc.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/esp_intr_alloc.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_mac.h \
|
$(PROJECT_PATH)/components/esp_hw_support/include/esp_mac.h \
|
||||||
|
@@ -1,2 +1 @@
|
|||||||
INPUT += \
|
INPUT += \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
|
||||||
|
@@ -1,2 +1 @@
|
|||||||
INPUT += \
|
INPUT += \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
|
||||||
|
@@ -1,2 +1 @@
|
|||||||
INPUT += \
|
INPUT += \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
INPUT += \
|
INPUT += \
|
||||||
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
|
||||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \
|
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/dac_channel.h \
|
||||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \
|
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/rtc_io_channel.h \
|
||||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
|
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
INPUT += \
|
INPUT += \
|
||||||
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
$(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \
|
||||||
$(PROJECT_PATH)/components/esp_hw_support/include/soc/$(IDF_TARGET)/esp_ds.h \
|
|
||||||
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
|
$(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \
|
||||||
$(PROJECT_PATH)/components/ulp/ulp_common/include/$(IDF_TARGET)/ulp_common_defs.h \
|
$(PROJECT_PATH)/components/ulp/ulp_common/include/$(IDF_TARGET)/ulp_common_defs.h \
|
||||||
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \
|
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/$(IDF_TARGET)/ulp.h \
|
||||||
|
Reference in New Issue
Block a user