Skip to content

Commit

Permalink
Merge branch 'feature/add_bignum_ll_layer' into 'master'
Browse files Browse the repository at this point in the history
bignum: added bignum hal and ll layer

Closes IDF-7071

See merge request espressif/esp-idf!22823
  • Loading branch information
mahavirj committed Apr 25, 2023
2 parents e2a5c09 + fbb8937 commit a8b6a70
Show file tree
Hide file tree
Showing 51 changed files with 2,345 additions and 1,475 deletions.
27 changes: 27 additions & 0 deletions components/esp_hw_support/include/soc/esp32/esp_crypto_lock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Acquire lock for the mpi cryptography peripheral.
*
*/
void esp_crypto_mpi_lock_acquire(void);

/**
* @brief Release lock for the mpi cryptography peripheral.
*
*/
void esp_crypto_mpi_lock_release(void);

#ifdef __cplusplus
}
#endif
1 change: 1 addition & 0 deletions components/esp_hw_support/port/esp32/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ set(srcs

if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "cache_sram_mmu.c"
"esp_crypto_lock.c"
"sar_periph_ctrl.c")
endif()

Expand Down
27 changes: 27 additions & 0 deletions components/esp_hw_support/port/esp32/esp_crypto_lock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <sys/lock.h>

#include "esp_crypto_lock.h"

/* Lock overview:
MPI/RSA: independent
*/

/* Lock for the MPI/RSA peripheral */

static _lock_t s_crypto_mpi_lock;

void esp_crypto_mpi_lock_acquire(void)
{
_lock_acquire(&s_crypto_mpi_lock);
}

void esp_crypto_mpi_lock_release(void)
{
_lock_release(&s_crypto_mpi_lock);
}
5 changes: 5 additions & 0 deletions components/hal/.build-test-rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ components/hal/test_apps/ecc:
- if: IDF_TARGET == "esp32c2"
temporary: true
reason: C2 ECC peripheral has a bug in ECC point verification, if value of K is zero the verification fails

components/hal/test_apps/mpi:
disable:
- if: SOC_MPI_SUPPORTED != 1
reason: Hardware MPI support not available for such targets.
5 changes: 5 additions & 0 deletions components/hal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

idf_build_get_property(target IDF_TARGET)

# On Linux, there is currently no HAL, hence this simple component registration
Expand Down Expand Up @@ -117,6 +118,10 @@ if(NOT BOOTLOADER_BUILD)
list(APPEND srcs "ecdsa_hal.c")
endif()

if(CONFIG_SOC_MPI_SUPPORTED)
list(APPEND srcs "mpi_hal.c")
endif()

if(CONFIG_SOC_SHA_SUPPORTED)
list(APPEND srcs "sha_hal.c")
endif()
Expand Down
150 changes: 150 additions & 0 deletions components/hal/esp32/include/hal/mpi_ll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include <stdbool.h>
#include <string.h>
#include "hal/assert.h"
#include "soc/dport_reg.h"
#include "soc/hwcrypto_periph.h"
#include "soc/mpi_periph.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Round up number of words to nearest
512 bit (16 word) block count.
*/
static inline size_t mpi_ll_calculate_hardware_words(size_t words)
{
return (words + 0xF) & ~0xF;
}

static inline void mpi_ll_clear_power_control_bit(void)
{
DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
}

static inline void mpi_ll_set_power_control_bit(void)
{
DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
}

static inline void mpi_ll_enable_interrupt(void)
{
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
}

static inline void mpi_ll_disable_interrupt(void)
{
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 0);
}

static inline void mpi_ll_clear_interrupt(void)
{
DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
}

static inline bool mpi_ll_check_memory_init_complete(void)
{
return DPORT_REG_READ(RSA_CLEAN_REG) == 0;
}

static inline void mpi_ll_start_op(mpi_op_t op)
{
DPORT_REG_WRITE(MPI_LL_OPERATIONS[op], 1);
}

static inline bool mpi_ll_get_int_status(void)
{
return DPORT_REG_READ(RSA_INTERRUPT_REG) == 0;
}

/* Copy MPI bignum (p) to hardware memory block at 'mem_base'.
If num_words is higher than the number of words (n) in the bignum then
these additional words will be zeroed in the memory buffer.
*/

/* Please see detailed note inside the function body below.
* Relevant: IDF-6029
https://github.com/espressif/esp-idf/issues/8710
https://github.com/espressif/esp-idf/issues/10403
*/
static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
{
uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
uint32_t copy_words = MIN(num_words, n);

/* Copy MPI data to memory block registers */
for (uint32_t i = 0; i < copy_words; i++) {
DPORT_REG_WRITE(mem_base + i * 4, p[i]);
}

/* Zero any remaining memory block data */
for (uint32_t i = copy_words; i < num_words; i++) {
DPORT_REG_WRITE(mem_base + i * 4, 0);
}
#if _INTERNAL_DEBUG_PURPOSE
/*
* With Xtensa GCC 11.2.0 (from ESP-IDF v5.x), it was observed that above zero initialization
* loop gets optimized to `memset` call from the ROM library. This was causing an issue that
* specific write (store) operation to the MPI peripheral block was getting lost erroneously.
* Following data re-verify loop could catch it during runtime.
*
* As a workaround, we are using DPORT_WRITE_REG (volatile writes) wrappers to write to
* the MPI peripheral.
*
*/

//for (uint32_t i = copy_words; i < hw_words; i++) { assert(pbase[i] == 0); }
#endif
}

static inline void mpi_ll_write_m_prime(uint32_t Mprime)
{
DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
}

static inline void mpi_ll_write_rinv(uint32_t rinv)
{
DPORT_REG_WRITE(MPI_LL_BLOCK_BASES[MPI_PARAM_Z], rinv);
}

static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value)
{
uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
DPORT_REG_WRITE(mem_base, value);
}

/* Read MPI bignum (p) back from hardware memory block.
Reads z_words words from block.
*/
static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words)
{
assert(n >= num_words);
uint32_t mem_base = MPI_LL_BLOCK_BASES[MPI_PARAM_Z];
/* Copy data from memory block registers */
esp_dport_access_read_buffer(p, mem_base, num_words);

/* Zero any remaining limbs in the bignum, if the buffer is bigger
than num_words */
for (size_t i = num_words; i < n; i++) {
p[i] = 0;
}
}

static inline void mpi_ll_set_mode(size_t length)
{
DPORT_REG_WRITE(RSA_MULT_MODE_REG, length);
}

#ifdef __cplusplus
}
#endif
153 changes: 153 additions & 0 deletions components/hal/esp32c3/include/hal/mpi_ll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include <stdbool.h>
#include <string.h>
#include "hal/assert.h"
#include "soc/hwcrypto_periph.h"
#include "soc/system_reg.h"
#include "soc/mpi_periph.h"

#ifdef __cplusplus
extern "C" {
#endif

static inline size_t mpi_ll_calculate_hardware_words(size_t words)
{
return words;
}

static inline void mpi_ll_clear_power_control_bit(void)
{
REG_CLR_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
}

static inline void mpi_ll_set_power_control_bit(void)
{
REG_SET_BIT(SYSTEM_RSA_PD_CTRL_REG, SYSTEM_RSA_MEM_PD);
}

static inline void mpi_ll_enable_interrupt(void)
{
REG_WRITE(RSA_INTERRUPT_REG, 1);
}

static inline void mpi_ll_disable_interrupt(void)
{
REG_WRITE(RSA_INTERRUPT_REG, 0);
}

static inline void mpi_ll_clear_interrupt(void)
{
REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
}

static inline bool mpi_ll_check_memory_init_complete(void)
{
return REG_READ(RSA_QUERY_CLEAN_REG) == 0;
}

static inline void mpi_ll_start_op(mpi_op_t op)
{
REG_WRITE(MPI_LL_OPERATIONS[op], 1);
}

static inline bool mpi_ll_get_int_status(void)
{
return REG_READ(RSA_QUERY_INTERRUPT_REG) == 0;
}

/* Copy MPI bignum (p) to hardware memory block at 'mem_base'.
If num_words is higher than the number of words (n) in the bignum then
these additional words will be zeroed in the memory buffer.
*/
static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
{
uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
uint32_t* pbase = (uint32_t*) mem_base;
uint32_t copy_words = MIN(num_words, n);

/* Copy MPI data to memory block registers */
for (int i = 0; i < copy_words; i++) {
pbase[i] = p[i];
}

/* Zero any remaining memory block data */
for (int i = copy_words; i < num_words; i++) {
pbase[i] = 0;
}
}

static inline void mpi_ll_write_m_prime(uint32_t Mprime)
{
REG_WRITE(RSA_M_DASH_REG, Mprime);
}

static inline void mpi_ll_write_rinv(uint32_t rinv)
{
REG_WRITE(MPI_LL_BLOCK_BASES[MPI_PARAM_Z], rinv);
}

static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value)
{
uint32_t mem_base = MPI_LL_BLOCK_BASES[param] + offset;
REG_WRITE(mem_base, value);
}

/* Read MPI bignum (p) back from hardware memory block.
Reads z_words words from block.
*/
static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words)
{
uint32_t mem_base = MPI_LL_BLOCK_BASES[MPI_PARAM_Z];
/* Copy data from memory block registers */
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < num_words; i++) {
p[i] = REG_READ(mem_base + (i * REG_WIDTH));
}
/* Zero any remaining limbs in the bignum, if the buffer is bigger
than num_words */
for (size_t i = num_words; i < n; i++) {
p[i] = 0;
}
}

static inline void mpi_ll_set_mode(size_t length)
{
REG_WRITE(RSA_LENGTH_REG, length);
}

static inline void mpi_ll_disable_constant_time(void)
{
REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
}

static inline void mpi_ll_enable_constant_time(void)
{
REG_WRITE(RSA_CONSTANT_TIME_REG, 1);
}

static inline void mpi_ll_disable_search(void)
{
REG_WRITE(RSA_SEARCH_ENABLE_REG, 0);
}

static inline void mpi_ll_enable_search(void)
{
REG_WRITE(RSA_SEARCH_ENABLE_REG, 1);
}

static inline void mpi_ll_set_search_position(size_t pos)
{
REG_WRITE(RSA_SEARCH_POS_REG, pos);
}

#ifdef __cplusplus
}
#endif
Loading

0 comments on commit a8b6a70

Please sign in to comment.