Skip to content

Commit

Permalink
Merge branch 'feature/esp32c6_enable_hmac_and_ds_support' into 'master'
Browse files Browse the repository at this point in the history
Feature/esp32c6 enable hmac and ds support

Closes IDF-5355 and IDF-5360

See merge request espressif/esp-idf!21761
  • Loading branch information
mahavirj committed Jan 20, 2023
2 parents 7943a92 + 45c6631 commit e7ca2f2
Show file tree
Hide file tree
Showing 13 changed files with 393 additions and 17 deletions.
2 changes: 0 additions & 2 deletions components/esp_hw_support/port/esp32c6/CMakeLists.txt
Expand Up @@ -7,8 +7,6 @@ set(srcs "rtc_clk_init.c"
"chip_info.c")

if(NOT BOOTLOADER_BUILD)
# list(APPEND srcs "esp_hmac.c" // TODO: IDF-5355
# "esp_ds.c") // TODO: IDF-5360
list(APPEND srcs "sar_periph_ctrl.c"
"esp_crypto_lock.c")

Expand Down
Expand Up @@ -24,6 +24,11 @@
#include "esp32s3/rom/digital_signature.h"
#include "esp32s3/rom/aes.h"
#include "esp32s3/rom/sha.h"
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/efuse.h"
#include "esp32c6/rom/digital_signature.h"
#include "esp32c6/rom/aes.h"
#include "esp32c6/rom/sha.h"
#endif

#include "esp_ds.h"
Expand All @@ -32,7 +37,7 @@

#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define DS_MAX_BITS (4096)
#elif CONFIG_IDF_TARGET_ESP32C3
#else
#define DS_MAX_BITS (ETS_DS_MAX_BITS)
#endif

Expand Down
Expand Up @@ -16,10 +16,11 @@
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.utils import int_to_bytes

supported_targets = {'esp32s2', 'esp32c3', 'esp32s3'}
supported_targets = {'esp32s2', 'esp32c3', 'esp32s3', 'esp32c6'}
supported_key_size = {'esp32s2':[4096, 3072, 2048, 1024],
'esp32c3':[3072, 2048, 1024],
'esp32s3':[4096, 3072, 2048, 1024]}
'esp32s3':[4096, 3072, 2048, 1024],
'esp32c6':[3072, 2048, 1024]}

NUM_HMAC_KEYS = 3
NUM_MESSAGES = 10
Expand Down
Expand Up @@ -24,6 +24,11 @@
#include "esp32s3/rom/digital_signature.h"
#include "esp32s3/rom/aes.h"
#include "esp32s3/rom/sha.h"
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/efuse.h"
#include "esp32c6/rom/digital_signature.h"
#include "esp32c6/rom/aes.h"
#include "esp32c6/rom/sha.h"
#endif

#include "esp_ds.h"
Expand All @@ -32,7 +37,7 @@

#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define DS_MAX_BITS (4096)
#elif CONFIG_IDF_TARGET_ESP32C3
#else
#define DS_MAX_BITS (ETS_DS_MAX_BITS)
#endif

Expand Down
3 changes: 2 additions & 1 deletion components/hal/CMakeLists.txt
Expand Up @@ -199,7 +199,8 @@ if(NOT BOOTLOADER_BUILD)
list(APPEND srcs
"spi_flash_hal_gpspi.c"
"esp32c6/rtc_cntl_hal.c"
)
"hmac_hal.c"
"ds_hal.c")

endif()

Expand Down
167 changes: 167 additions & 0 deletions components/hal/esp32c6/include/hal/ds_ll.h
@@ -0,0 +1,167 @@
/*
* SPDX-FileCopyrightText: 2023 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.
******************************************************************************/

#pragma once

#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "soc/hwcrypto_reg.h"
#include "soc/soc_caps.h"

#ifdef __cplusplus
extern "C" {
#endif

static inline void ds_ll_start(void)
{
REG_WRITE(DS_SET_START_REG, 1);
}

/**
* @brief Wait until DS peripheral has finished any outstanding operation.
*/
static inline bool ds_ll_busy(void)
{
return (REG_READ(DS_QUERY_BUSY_REG) > 0) ? true : false;
}

/**
* @brief Busy wait until the hardware is ready.
*/
static inline void ds_ll_wait_busy(void)
{
while (ds_ll_busy());
}

/**
* @brief In case of a key error, check what caused it.
*/
static inline ds_key_check_t ds_ll_key_error_source(void)
{
uint32_t key_error = REG_READ(DS_QUERY_KEY_WRONG_REG);
if (key_error == 0) {
return DS_NO_KEY_INPUT;
} else {
return DS_OTHER_WRONG;
}
}

/**
* @brief Write the initialization vector to the corresponding register field.
*/
static inline void ds_ll_configure_iv(const uint32_t *iv)
{
for (size_t i = 0; i < (SOC_DS_KEY_PARAM_MD_IV_LENGTH / sizeof(uint32_t)); i++) {
REG_WRITE(DS_IV_MEM + (i * 4) , iv[i]);
}
}

/**
* @brief Write the message which should be signed.
*
* @param msg Pointer to the message.
* @param size Length of msg in bytes. It is the RSA signature length in bytes.
*/
static inline void ds_ll_write_message(const uint8_t *msg, size_t size)
{
memcpy((uint8_t*) DS_X_MEM, msg, size);
asm volatile ("fence");
}

/**
* @brief Write the encrypted private key parameters.
*/
static inline void ds_ll_write_private_key_params(const uint8_t *encrypted_key_params)
{
/* Note: as the internal peripheral still has RSA 4096 structure,
but C is encrypted based on the actual max RSA length (ETS_DS_MAX_BITS), need to fragment it
when copying to hardware...
(note if ETS_DS_MAX_BITS == 4096, this should be the same as copying data->c to hardware in one fragment)
*/
typedef struct { uint32_t addr; size_t len; } frag_t;
const frag_t frags[] = {
{DS_Y_MEM, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8},
{DS_M_MEM, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8},
{DS_RB_MEM, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8},
{DS_BOX_MEM, DS_IV_MEM - DS_BOX_MEM},
};
const size_t NUM_FRAGS = sizeof(frags)/sizeof(frag_t);
const uint8_t *from = encrypted_key_params;

for (int i = 0; i < NUM_FRAGS; i++) {
memcpy((uint8_t *)frags[i].addr, from, frags[i].len);
asm volatile ("fence");
from += frags[i].len;
}
}

/**
* @brief Begin signing procedure.
*/
static inline void ds_ll_start_sign(void)
{
REG_WRITE(DS_SET_CONTINUE_REG, 1);
}

/**
* @brief check the calculated signature.
*
* @return
* - DS_SIGNATURE_OK if no issue is detected with the signature.
* - DS_SIGNATURE_PADDING_FAIL if the padding of the private key parameters is wrong.
* - DS_SIGNATURE_MD_FAIL if the message digest check failed. This means that the message digest calculated using
* the private key parameters fails, i.e., the integrity of the private key parameters is not protected.
* - DS_SIGNATURE_PADDING_AND_MD_FAIL if both padding and message digest check fail.
*/
static inline ds_signature_check_t ds_ll_check_signature(void)
{
uint32_t result = REG_READ(DS_QUERY_CHECK_REG);
switch(result) {
case 0:
return DS_SIGNATURE_OK;
case 1:
return DS_SIGNATURE_MD_FAIL;
case 2:
return DS_SIGNATURE_PADDING_FAIL;
default:
return DS_SIGNATURE_PADDING_AND_MD_FAIL;
}
}

/**
* @brief Read the signature from the hardware.
*
* @param result The signature result.
* @param size Length of signature result in bytes. It is the RSA signature length in bytes.
*/
static inline void ds_ll_read_result(uint8_t *result, size_t size)
{
memcpy(result, (uint8_t*) DS_Z_MEM, size);
asm volatile ("fence");
}

/**
* @brief Exit the signature operation.
*
* @note This does not deactivate the module. Corresponding clock/reset bits have to be triggered for deactivation.
*/
static inline void ds_ll_finish(void)
{
REG_WRITE(DS_SET_FINISH_REG, 1);
ds_ll_wait_busy();
}

#ifdef __cplusplus
}
#endif

0 comments on commit e7ca2f2

Please sign in to comment.