-
Notifications
You must be signed in to change notification settings - Fork 7.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/esp32h2_sha_aes_support' into 'master'
esp32h2: add support for sha and aes peripherals Closes IDF-6275 and IDF-6280 See merge request espressif/esp-idf!22154
- Loading branch information
Showing
7 changed files
with
464 additions
and
5 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
components/esp_hw_support/include/soc/esp32h2/esp_crypto_lock.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* 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: | ||
SHA: peripheral independent, but DMA is shared with AES | ||
AES: peripheral independent, but DMA is shared with SHA | ||
MPI/RSA: independent | ||
HMAC: needs SHA | ||
DS: needs HMAC (which needs SHA), AES and MPI | ||
*/ | ||
|
||
/* Lock for DS peripheral */ | ||
static _lock_t s_crypto_ds_lock; | ||
|
||
/* Lock for HMAC peripheral */ | ||
static _lock_t s_crypto_hmac_lock; | ||
|
||
/* Lock for the MPI/RSA peripheral, also used by the DS peripheral */ | ||
static _lock_t s_crypto_mpi_lock; | ||
|
||
/* Single lock for SHA and AES, sharing a reserved GDMA channel */ | ||
static _lock_t s_crypto_sha_aes_lock; | ||
|
||
void esp_crypto_hmac_lock_acquire(void) | ||
{ | ||
_lock_acquire(&s_crypto_hmac_lock); | ||
esp_crypto_sha_aes_lock_acquire(); | ||
} | ||
|
||
void esp_crypto_hmac_lock_release(void) | ||
{ | ||
esp_crypto_sha_aes_lock_release(); | ||
_lock_release(&s_crypto_hmac_lock); | ||
} | ||
|
||
void esp_crypto_ds_lock_acquire(void) | ||
{ | ||
_lock_acquire(&s_crypto_ds_lock); | ||
esp_crypto_hmac_lock_acquire(); | ||
esp_crypto_mpi_lock_acquire(); | ||
} | ||
|
||
void esp_crypto_ds_lock_release(void) | ||
{ | ||
esp_crypto_mpi_lock_release(); | ||
esp_crypto_hmac_lock_release(); | ||
_lock_release(&s_crypto_ds_lock); | ||
} | ||
|
||
void esp_crypto_sha_aes_lock_acquire(void) | ||
{ | ||
_lock_acquire(&s_crypto_sha_aes_lock); | ||
} | ||
|
||
void esp_crypto_sha_aes_lock_release(void) | ||
{ | ||
_lock_release(&s_crypto_sha_aes_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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <stdbool.h> | ||
#include <string.h> | ||
#include "soc/hwcrypto_reg.h" | ||
#include "hal/aes_types.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @brief State of AES accelerator, busy, idle or done | ||
* | ||
*/ | ||
typedef enum { | ||
ESP_AES_STATE_IDLE = 0, /* AES accelerator is idle */ | ||
ESP_AES_STATE_BUSY, /* Transform in progress */ | ||
ESP_AES_STATE_DONE, /* Transform completed */ | ||
} esp_aes_state_t; | ||
|
||
|
||
/** | ||
* @brief Write the encryption/decryption key to hardware | ||
* | ||
* @param key Key to be written to the AES hardware | ||
* @param key_word_len Number of words in the key | ||
* | ||
* @return Number of bytes written to hardware, used for fault injection check | ||
*/ | ||
static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) | ||
{ | ||
/* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ | ||
volatile uint8_t key_in_hardware = 0; | ||
/* Memcpy to avoid potential unaligned access */ | ||
uint32_t key_word; | ||
for (int i = 0; i < key_word_len; i++) { | ||
memcpy(&key_word, key + 4 * i, 4); | ||
REG_WRITE(AES_KEY_0_REG + i * 4, key_word); | ||
key_in_hardware += 4; | ||
} | ||
return key_in_hardware; | ||
} | ||
|
||
/** | ||
* @brief Sets the mode | ||
* | ||
* @param mode ESP_AES_ENCRYPT = 1, or ESP_AES_DECRYPT = 0 | ||
* @param key_bytes Number of bytes in the key | ||
*/ | ||
static inline void aes_ll_set_mode(int mode, uint8_t key_bytes) | ||
{ | ||
const uint32_t MODE_DECRYPT_BIT = 4; | ||
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT; | ||
|
||
/* See TRM for the mapping between keylength and mode bit */ | ||
REG_WRITE(AES_MODE_REG, mode_reg_base + ((key_bytes / 8) - 2)); | ||
} | ||
|
||
/** | ||
* @brief Writes message block to AES hardware | ||
* | ||
* @param input Block to be written | ||
*/ | ||
static inline void aes_ll_write_block(const void *input) | ||
{ | ||
uint32_t input_word; | ||
|
||
for (int i = 0; i < AES_BLOCK_WORDS; i++) { | ||
memcpy(&input_word, (uint8_t*)input + 4 * i, 4); | ||
REG_WRITE(AES_TEXT_IN_0_REG + i * 4, input_word); | ||
} | ||
} | ||
|
||
/** | ||
* @brief Read the AES block | ||
* | ||
* @param output the output of the transform, length = AES_BLOCK_BYTES | ||
*/ | ||
static inline void aes_ll_read_block(void *output) | ||
{ | ||
uint32_t output_word; | ||
const size_t REG_WIDTH = sizeof(uint32_t); | ||
|
||
for (size_t i = 0; i < AES_BLOCK_WORDS; i++) { | ||
output_word = REG_READ(AES_TEXT_OUT_0_REG + (i * REG_WIDTH)); | ||
/* Memcpy to avoid potential unaligned access */ | ||
memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word)); | ||
} | ||
} | ||
|
||
/** | ||
* @brief Starts block transform | ||
* | ||
*/ | ||
static inline void aes_ll_start_transform(void) | ||
{ | ||
REG_WRITE(AES_TRIGGER_REG, 1); | ||
} | ||
|
||
|
||
/** | ||
* @brief Read state of AES accelerator | ||
* | ||
* @return esp_aes_state_t | ||
*/ | ||
static inline esp_aes_state_t aes_ll_get_state(void) | ||
{ | ||
return REG_READ(AES_STATE_REG); | ||
} | ||
|
||
|
||
/** | ||
* @brief Set mode of operation | ||
* | ||
* @note Only used for DMA transforms | ||
* | ||
* @param mode | ||
*/ | ||
static inline void aes_ll_set_block_mode(esp_aes_mode_t mode) | ||
{ | ||
REG_WRITE(AES_BLOCK_MODE_REG, mode); | ||
} | ||
|
||
/** | ||
* @brief Set AES-CTR counter to INC32 | ||
* | ||
* @note Only affects AES-CTR mode | ||
* | ||
*/ | ||
static inline void aes_ll_set_inc(void) | ||
{ | ||
REG_WRITE(AES_INC_SEL_REG, 0); | ||
} | ||
|
||
/** | ||
* @brief Release the DMA | ||
* | ||
*/ | ||
static inline void aes_ll_dma_exit(void) | ||
{ | ||
REG_WRITE(AES_DMA_EXIT_REG, 0); | ||
} | ||
|
||
/** | ||
* @brief Sets the number of blocks to be transformed | ||
* | ||
* @note Only used for DMA transforms | ||
* | ||
* @param num_blocks Number of blocks to transform | ||
*/ | ||
static inline void aes_ll_set_num_blocks(size_t num_blocks) | ||
{ | ||
REG_WRITE(AES_BLOCK_NUM_REG, num_blocks); | ||
} | ||
|
||
/* | ||
* Write IV to hardware iv registers | ||
*/ | ||
static inline void aes_ll_set_iv(const uint8_t *iv) | ||
{ | ||
uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_MEM); | ||
uint32_t iv_word; | ||
|
||
for (int i = 0; i < IV_WORDS; i++ ) { | ||
/* Memcpy to avoid potential unaligned access */ | ||
memcpy(&iv_word, iv + 4 * i, sizeof(iv_word)); | ||
REG_WRITE(®_addr_buf[i], iv_word); | ||
} | ||
} | ||
|
||
/* | ||
* Read IV from hardware iv registers | ||
*/ | ||
static inline void aes_ll_read_iv(uint8_t *iv) | ||
{ | ||
uint32_t iv_word; | ||
const size_t REG_WIDTH = sizeof(uint32_t); | ||
|
||
for (size_t i = 0; i < IV_WORDS; i++) { | ||
iv_word = REG_READ(AES_IV_MEM + (i * REG_WIDTH)); | ||
/* Memcpy to avoid potential unaligned access */ | ||
memcpy(iv + i * 4, &iv_word, sizeof(iv_word)); | ||
} | ||
} | ||
|
||
/** | ||
* @brief Enable or disable DMA mode | ||
* | ||
* @param enable true to enable, false to disable. | ||
*/ | ||
static inline void aes_ll_dma_enable(bool enable) | ||
{ | ||
REG_WRITE(AES_DMA_ENABLE_REG, enable); | ||
} | ||
|
||
/** | ||
* @brief Enable or disable transform completed interrupt | ||
* | ||
* @param enable true to enable, false to disable. | ||
*/ | ||
static inline void aes_ll_interrupt_enable(bool enable) | ||
{ | ||
REG_WRITE(AES_INT_ENA_REG, enable); | ||
} | ||
|
||
/** | ||
* @brief Clears the interrupt | ||
* | ||
*/ | ||
static inline void aes_ll_interrupt_clear(void) | ||
{ | ||
REG_WRITE(AES_INT_CLEAR_REG, 1); | ||
} | ||
|
||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
Oops, something went wrong.