Merge branch 'feature/enable_hmac_and_ds_support_for_c5' into 'master'

feat: enabled hmac and ds peripheral support for c5

Closes IDF-8619, IDF-8616, IDF-9479, and IDF-9481

See merge request espressif/esp-idf!29287
This commit is contained in:
Mahavir Jain
2024-05-29 12:50:25 +08:00
11 changed files with 470 additions and 19 deletions

View File

@@ -1,7 +1,6 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import argparse
import datetime
import hashlib
@@ -13,16 +12,19 @@ import struct
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric.rsa import _modinv as modinv # type: ignore
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives.ciphers import algorithms
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers import modes
from cryptography.utils import int_to_bytes
supported_targets = {'esp32s2', 'esp32c3', 'esp32s3', 'esp32c6', 'esp32h2', 'esp32p4'}
supported_targets = {'esp32s2', 'esp32c3', 'esp32s3', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5'}
supported_key_size = {'esp32s2':[4096, 3072, 2048, 1024],
'esp32c3':[3072, 2048, 1024],
'esp32s3':[4096, 3072, 2048, 1024],
'esp32c6':[3072, 2048, 1024],
'esp32h2':[3072, 2048, 1024],
'esp32p4':[4096, 3072, 2048, 1024]}
'esp32p4':[4096, 3072, 2048, 1024],
'esp32c5':[3072, 2048, 1024]}
NUM_HMAC_KEYS = 3
NUM_MESSAGES = 10
@@ -41,12 +43,12 @@ def number_as_bignum_words(number): # type: (int) -> str
return '{ ' + ', '.join(result) + ' }'
def number_as_bytes(number, pad_bits=None): # type: (int, int) -> bytes
def number_as_bytes(number, pad_bits=0): # type: (int, int) -> bytes
"""
Given a number, format as a little endian array of bytes
"""
result = int_to_bytes(number)[::-1] # type: bytes
while pad_bits is not None and len(result) < (pad_bits // 8):
while pad_bits != 0 and len(result) < (pad_bits // 8):
result += b'\x00'
return result

View File

@@ -34,6 +34,10 @@
#include "esp32p4/rom/digital_signature.h"
#include "esp32p4/rom/aes.h"
#include "esp32p4/rom/sha.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/digital_signature.h"
#include "esp32c5/rom/aes.h"
#include "esp32c5/rom/sha.h"
#endif
#include "esp_ds.h"

View File

@@ -0,0 +1,189 @@
/*
* SPDX-FileCopyrightText: 2023-2024 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"
#include "soc/pcr_struct.h"
#include "hal/ds_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable the bus clock for Digital Signature peripheral module
*
* @param true to enable the module, false to disable the module
*/
static inline void ds_ll_enable_bus_clock(bool enable)
{
PCR.ds_conf.ds_clk_en = enable;
}
/**
* @brief Reset the Digital Signature peripheral module
*/
static inline void ds_ll_reset_register(void)
{
PCR.ds_conf.ds_rst_en = 1;
PCR.ds_conf.ds_rst_en = 0;
}
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

View File

@@ -0,0 +1,212 @@
/*
* SPDX-FileCopyrightText: 2023-2024 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 <string.h>
#include <stdbool.h>
#include "soc/system_reg.h"
#include "soc/hwcrypto_reg.h"
#include "soc/pcr_struct.h"
#include "hal/hmac_types.h"
#define SHA256_BLOCK_SZ 64
#define SHA256_DIGEST_SZ 32
#define EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG 6
#define EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE 7
#define EFUSE_KEY_PURPOSE_HMAC_UP 8
#define EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL 5
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable the bus clock for HMAC peripheral module
*
* @param true to enable the module, false to disable the module
*/
static inline void hmac_ll_enable_bus_clock(bool enable)
{
PCR.hmac_conf.hmac_clk_en = enable;
}
/**
* @brief Reset the HMAC peripheral module
*/
static inline void hmac_ll_reset_register(void)
{
PCR.hmac_conf.hmac_rst_en = 1;
PCR.hmac_conf.hmac_rst_en = 0;
}
/**
* Makes the peripheral ready for use, after enabling it.
*/
static inline void hmac_ll_start(void)
{
REG_WRITE(HMAC_SET_START_REG, 1);
}
/**
* @brief Determine where the HMAC output should go.
*
* 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.
*/
static inline void hmac_ll_config_output(hmac_hal_output_t config)
{
switch(config) {
case HMAC_OUTPUT_USER:
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_UP);
break;
case HMAC_OUTPUT_DS:
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
break;
case HMAC_OUTPUT_JTAG_ENABLE:
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG);
break;
case HMAC_OUTPUT_ALL:
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL);
break;
default:
; // do nothing, error will be indicated by hmac_hal_config_error()
}
}
/**
* @brief Selects which hardware key should be used.
*/
static inline void hmac_ll_config_hw_key_id(uint32_t key_id)
{
REG_WRITE(HMAC_SET_PARA_KEY_REG, key_id);
}
/**
* @brief Apply and check configuration.
*
* Afterwards, the configuration can be checked for errors with hmac_hal_config_error().
*/
static inline void hmac_ll_config_finish(void)
{
REG_WRITE(HMAC_SET_PARA_FINISH_REG, 1);
}
/**
*
* @brief Query HMAC error state after configuration actions.
*
* @return
* - 1 or greater on error
* - 0 on success
*/
static inline uint32_t hmac_ll_config_error(void)
{
return REG_READ(HMAC_QUERY_ERROR_REG);
}
/**
* Wait until the HAL is ready for the next interaction.
*/
static inline void hmac_ll_wait_idle(void)
{
uint32_t query;
do {
query = REG_READ(HMAC_QUERY_BUSY_REG);
} while(query != 0);
}
/**
* @brief Write a message block of 512 bits to the HMAC peripheral.
*/
static inline void hmac_ll_write_block_512(const uint32_t *block)
{
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < SHA256_BLOCK_SZ / REG_WIDTH; i++) {
REG_WRITE(HMAC_WR_MESSAGE_MEM + (i * REG_WIDTH), block[i]);
}
REG_WRITE(HMAC_SET_MESSAGE_ONE_REG, 1);
}
/**
* @brief Read the 256 bit HMAC.
*/
static inline void hmac_ll_read_result_256(uint32_t *result)
{
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < SHA256_DIGEST_SZ / REG_WIDTH; i++) {
result[i] = REG_READ(HMAC_RD_RESULT_MEM + (i * REG_WIDTH));
}
}
/**
* @brief Clean the HMAC result provided to other hardware.
*/
static inline void hmac_ll_clean(void)
{
REG_WRITE(HMAC_SET_INVALIDATE_DS_REG, 1);
REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1);
}
/**
* @brief Signals that the following block will be the padded last block.
*/
static inline void hmac_ll_msg_padding(void)
{
REG_WRITE(HMAC_SET_MESSAGE_PAD_REG, 1);
}
/**
* @brief Signals that all blocks have been written and a padding block will automatically be applied by hardware.
*
* Only applies if the message length is a multiple of 512 bits.
* See the chip TRM HMAC chapter for more details.
*/
static inline void hmac_ll_msg_end(void)
{
REG_WRITE(HMAC_SET_MESSAGE_END_REG, 1);
}
/**
* @brief The message including padding fits into one block, so no further action needs to be taken.
*
* This is called after the one-block-message has been written.
*/
static inline void hmac_ll_msg_one_block(void)
{
REG_WRITE(HMAC_ONE_BLOCK_REG, 1);
}
/**
* @brief Indicate that more blocks will be written after the last block.
*/
static inline void hmac_ll_msg_continue(void)
{
REG_WRITE(HMAC_SET_MESSAGE_ING_REG, 1);
}
/**
* @brief Clear the HMAC result.
*
* Use this after reading the HMAC result or if aborting after any of the other steps above.
*/
static inline void hmac_ll_calc_finish(void)
{
REG_WRITE(HMAC_SET_RESULT_FINISH_REG, 2);
}
#ifdef __cplusplus
}
#endif

View File

@@ -42,6 +42,10 @@ const static char *TAG = "test_ds";
#include "esp32p4/rom/digital_signature.h"
#include "esp32p4/rom/aes.h"
#include "esp32p4/rom/sha.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/digital_signature.h"
#include "esp32c5/rom/aes.h"
#include "esp32c5/rom/sha.h"
#endif
#define ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL (0x1) /*!< HMAC peripheral problem */

View File

@@ -20,6 +20,8 @@
#include "esp32h2/rom/digital_signature.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/digital_signature.h"
#elif CONFIG_IDF_TARGET_ESP32C5
#include "esp32c5/rom/digital_signature.h"
#else
#error "Selected target does not support esp_rsa_sign_alt (for DS)"
#endif

View File

@@ -91,6 +91,14 @@ config SOC_RSA_SUPPORTED
bool
default y
config SOC_HMAC_SUPPORTED
bool
default y
config SOC_DIG_SIGN_SUPPORTED
bool
default y
config SOC_ECC_SUPPORTED
bool
default y
@@ -235,6 +243,18 @@ config SOC_CPU_IDRAM_SPLIT_USING_PMP
bool
default y
config SOC_DS_SIGNATURE_MAX_BIT_LEN
int
default 3072
config SOC_DS_KEY_PARAM_MD_IV_LENGTH
int
default 16
config SOC_DS_KEY_CHECK_MAX_WAIT_US
int
default 1100
config SOC_AHB_GDMA_VERSION
int
default 1

View File

@@ -51,8 +51,8 @@
#define SOC_MPI_SUPPORTED 1
#define SOC_SHA_SUPPORTED 1
#define SOC_RSA_SUPPORTED 1
// #define SOC_HMAC_SUPPORTED 1 // TODO: [ESP32C5] IDF-8616
// #define SOC_DIG_SIGN_SUPPORTED 1 // TODO: [ESP32C5] IDF-8619
#define SOC_HMAC_SUPPORTED 1
#define SOC_DIG_SIGN_SUPPORTED 1
#define SOC_ECC_SUPPORTED 1
#define SOC_ECC_EXTENDED_MODES_SUPPORTED 1
#define SOC_FLASH_ENC_SUPPORTED 1 // TODO: [ESP32C5] IDF-8622
@@ -164,14 +164,14 @@
/*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/
/** The maximum length of a Digital Signature in bits. */
// #define SOC_DS_SIGNATURE_MAX_BIT_LEN (3072)
#define SOC_DS_SIGNATURE_MAX_BIT_LEN (3072)
/** Initialization vector (IV) length for the RSA key parameter message digest (MD) in bytes. */
// #define SOC_DS_KEY_PARAM_MD_IV_LENGTH (16)
#define SOC_DS_KEY_PARAM_MD_IV_LENGTH (16)
/** Maximum wait time for DS parameter decryption key. If overdue, then key error.
See TRM DS chapter for more details */
// #define SOC_DS_KEY_CHECK_MAX_WAIT_US (1100)
#define SOC_DS_KEY_CHECK_MAX_WAIT_US (1100)
/*-------------------------- GDMA CAPS -------------------------------------*/
#define SOC_AHB_GDMA_VERSION 1U

View File

@@ -87,6 +87,14 @@ config SOC_RSA_SUPPORTED
bool
default y
config SOC_HMAC_SUPPORTED
bool
default y
config SOC_DIG_SIGN_SUPPORTED
bool
default y
config SOC_ECC_SUPPORTED
bool
default y
@@ -187,6 +195,18 @@ config SOC_CPU_IDRAM_SPLIT_USING_PMP
bool
default y
config SOC_DS_SIGNATURE_MAX_BIT_LEN
int
default 3072
config SOC_DS_KEY_PARAM_MD_IV_LENGTH
int
default 16
config SOC_DS_KEY_CHECK_MAX_WAIT_US
int
default 1100
config SOC_DMA_CAN_ACCESS_FLASH
bool
default y

View File

@@ -49,8 +49,8 @@
#define SOC_MPI_SUPPORTED 1
#define SOC_SHA_SUPPORTED 1
#define SOC_RSA_SUPPORTED 1
// #define SOC_HMAC_SUPPORTED 1 // TODO: [ESP32C5] IDF-8616
// #define SOC_DIG_SIGN_SUPPORTED 1 // TODO: [ESP32C5] IDF-8619
#define SOC_HMAC_SUPPORTED 1
#define SOC_DIG_SIGN_SUPPORTED 1
#define SOC_ECC_SUPPORTED 1
#define SOC_ECC_EXTENDED_MODES_SUPPORTED 1
#define SOC_FLASH_ENC_SUPPORTED 1 // TODO: [ESP32C5] IDF-8622
@@ -156,14 +156,14 @@
/*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/
/** The maximum length of a Digital Signature in bits. */
// #define SOC_DS_SIGNATURE_MAX_BIT_LEN (3072)
#define SOC_DS_SIGNATURE_MAX_BIT_LEN (3072)
/** Initialization vector (IV) length for the RSA key parameter message digest (MD) in bytes. */
// #define SOC_DS_KEY_PARAM_MD_IV_LENGTH (16)
#define SOC_DS_KEY_PARAM_MD_IV_LENGTH (16)
/** Maximum wait time for DS parameter decryption key. If overdue, then key error.
See TRM DS chapter for more details */
// #define SOC_DS_KEY_CHECK_MAX_WAIT_US (1100)
#define SOC_DS_KEY_CHECK_MAX_WAIT_US (1100)
/*-------------------------- DMA Common CAPS ----------------------------------------*/
#define SOC_DMA_CAN_ACCESS_FLASH 1 /*!< DMA can access Flash memory */

View File

@@ -106,7 +106,6 @@ api-reference/peripherals/usb_host/usb_host_notes_index.rst
api-reference/peripherals/usb_host/usb_host_notes_dwc_otg.rst
api-reference/peripherals/usb_host/usb_host_notes_design.rst
api-reference/peripherals/usb_host/usb_host_notes_usbh.rst
api-reference/peripherals/hmac.rst
api-reference/peripherals/usb_device.rst
api-reference/peripherals/sdspi_host.rst
api-reference/peripherals/spi_slave.rst
@@ -128,7 +127,6 @@ api-reference/peripherals/touch_pad.rst
api-reference/peripherals/adc_calibration.rst
api-reference/peripherals/spi_slave_hd.rst
api-reference/peripherals/parlio.rst
api-reference/peripherals/ds.rst
api-reference/peripherals/i2c.rst
api-reference/peripherals/dedic_gpio.rst
api-reference/peripherals/sd_pullup_requirements.rst