mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-19 23:45:28 +02:00
global: bring up esp32s2(not beta)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -56,15 +56,14 @@ void esp_mpi_acquire_hardware( void )
|
||||
/* newlib locks lazy initialize on ESP-IDF */
|
||||
_lock_acquire(&mpi_lock);
|
||||
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_CLK_EN_RSA);
|
||||
/* also clear reset on digital signature & secure boot, otherwise RSA is held in reset */
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, DPORT_RST_EN_RSA
|
||||
| DPORT_RST_EN_DIGITAL_SIGNATURE
|
||||
| DPORT_RST_EN_SECURE_BOOT);
|
||||
DPORT_REG_SET_BIT(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_RSA_CLK_EN);
|
||||
/* also clear reset on digital signature, otherwise RSA is held in reset */
|
||||
DPORT_REG_CLR_BIT(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_RSA_RST
|
||||
| DPORT_CRYPTO_DS_RST);
|
||||
|
||||
DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_MEM_PD);
|
||||
|
||||
while(DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) {
|
||||
while (DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) {
|
||||
}
|
||||
// Note: from enabling RSA clock to here takes about 1.3us
|
||||
}
|
||||
@@ -74,8 +73,8 @@ void esp_mpi_release_hardware( void )
|
||||
DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
|
||||
|
||||
/* don't reset digital signature unit, as this resets AES also */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA);
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA);
|
||||
DPORT_REG_SET_BIT(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_RSA_RST);
|
||||
DPORT_REG_CLR_BIT(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_RSA_CLK_EN);
|
||||
|
||||
_lock_release(&mpi_lock);
|
||||
}
|
||||
@@ -141,12 +140,12 @@ static inline int mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_wo
|
||||
esp_dport_access_read_buffer(x->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 < x->n; i++) {
|
||||
for (size_t i = num_words; i < x->n; i++) {
|
||||
x->p[i] = 0;
|
||||
}
|
||||
|
||||
asm volatile ("memw");
|
||||
cleanup:
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -200,7 +199,7 @@ static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&RR, num_bits * 2, 1));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(Rinv, &RR, M));
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&RR);
|
||||
return ret;
|
||||
}
|
||||
@@ -213,6 +212,7 @@ static inline void start_op(uint32_t op_reg)
|
||||
{
|
||||
/* Clear interrupt status */
|
||||
DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
|
||||
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
|
||||
|
||||
/* Note: above REG_WRITE includes a memw, so we know any writes
|
||||
to the memory blocks are also complete. */
|
||||
@@ -283,7 +283,7 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi
|
||||
|
||||
esp_mpi_release_hardware();
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&Rinv);
|
||||
return ret;
|
||||
}
|
||||
@@ -298,7 +298,7 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi
|
||||
* (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv)
|
||||
*
|
||||
*/
|
||||
int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi* Y, const mbedtls_mpi* M, mbedtls_mpi* _Rinv )
|
||||
int mbedtls_mpi_exp_mod( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M, mbedtls_mpi *_Rinv )
|
||||
{
|
||||
int ret = 0;
|
||||
size_t y_bits = mbedtls_mpi_bitlen(Y);
|
||||
@@ -379,7 +379,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi
|
||||
Z->s = 1;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
if (_Rinv == NULL) {
|
||||
mbedtls_mpi_free(&Rinv_new);
|
||||
}
|
||||
@@ -509,13 +509,13 @@ static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X,
|
||||
esp_mpi_acquire_hardware();
|
||||
|
||||
/* M = 2^num_words - 1, so block is entirely FF */
|
||||
for(int i = 0; i < num_words; i++) {
|
||||
for (int i = 0; i < num_words; i++) {
|
||||
DPORT_REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX);
|
||||
}
|
||||
|
||||
/* Mprime = 1 */
|
||||
DPORT_REG_WRITE(RSA_M_DASH_REG, 1);
|
||||
DPORT_REG_WRITE(RSA_LENGTH_REG, num_words -1);
|
||||
DPORT_REG_WRITE(RSA_LENGTH_REG, num_words - 1);
|
||||
|
||||
/* Load X & Y */
|
||||
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
|
||||
@@ -523,7 +523,7 @@ static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X,
|
||||
|
||||
/* Rinv = 1 */
|
||||
DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1);
|
||||
for(int i = 1; i < num_words; i++) {
|
||||
for (int i = 1; i < num_words; i++) {
|
||||
DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0);
|
||||
}
|
||||
|
||||
@@ -586,7 +586,7 @@ static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbe
|
||||
/* Z += Ztemp */
|
||||
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi(Z, Z, &Ztemp) );
|
||||
|
||||
cleanup:
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&Ztemp);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -29,29 +29,47 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/lock.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "esp32s2beta/crypto_dma.h"
|
||||
#include "esp32s2beta/sha.h"
|
||||
#include "soc/crypto_dma_reg.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/hwcrypto_reg.h"
|
||||
#include "esp32s2beta/rom/lldesc.h"
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/periph_defs.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
/* Single lock for SHA engine
|
||||
*/
|
||||
static _lock_t s_sha_lock;
|
||||
|
||||
/* This API was designed for ESP32, which has seperate
|
||||
engines for SHA1,256,512. ESP32C has a single engine.
|
||||
*/
|
||||
/* Enable if want to use SHA interrupt */
|
||||
//#define CONFIG_MBEDTLS_SHA_USE_INTERRUPT
|
||||
|
||||
#if defined(CONFIG_MBEDTLS_SHA_USE_INTERRUPT)
|
||||
static SemaphoreHandle_t op_complete_sem;
|
||||
#endif
|
||||
|
||||
/* Return block size (in bytes) for a given SHA type */
|
||||
inline static size_t block_length(esp_sha_type type) {
|
||||
switch(type) {
|
||||
inline static size_t block_length(esp_sha_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SHA1:
|
||||
case SHA2_224:
|
||||
case SHA2_256:
|
||||
return 64;
|
||||
case SHA2_384:
|
||||
case SHA2_512:
|
||||
case SHA2_512224:
|
||||
case SHA2_512256:
|
||||
case SHA2_512T:
|
||||
return 128;
|
||||
default:
|
||||
return 0;
|
||||
@@ -59,50 +77,33 @@ inline static size_t block_length(esp_sha_type type) {
|
||||
}
|
||||
|
||||
/* Return state size (in bytes) for a given SHA type */
|
||||
inline static size_t state_length(esp_sha_type type) {
|
||||
switch(type) {
|
||||
inline static size_t state_length(esp_sha_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SHA1:
|
||||
return 160/8;
|
||||
return 160 / 8;
|
||||
case SHA2_224:
|
||||
case SHA2_256:
|
||||
return 256/8;
|
||||
return 256 / 8;
|
||||
case SHA2_384:
|
||||
case SHA2_512:
|
||||
return 512/8;
|
||||
case SHA2_512224:
|
||||
case SHA2_512256:
|
||||
case SHA2_512T:
|
||||
return 512 / 8;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy words in memory (to/from a memory block), byte swapping as we go. */
|
||||
static void memcpy_endianswap(void *to, const void *from, size_t num_bytes)
|
||||
{
|
||||
uint32_t *to_words = (uint32_t *)to;
|
||||
const uint32_t *from_words = (const uint32_t *)from;
|
||||
assert(num_bytes % 4 == 0);
|
||||
for (int i = 0; i < num_bytes / 4; i++) {
|
||||
to_words[i] = __builtin_bswap32(from_words[i]);
|
||||
}
|
||||
asm volatile ("memw");
|
||||
}
|
||||
|
||||
static void memcpy_swapwords(void *to, const void *from, size_t num_bytes)
|
||||
{
|
||||
uint32_t *to_words = (uint32_t *)to;
|
||||
const uint32_t *from_words = (const uint32_t *)from;
|
||||
assert(num_bytes % 8 == 0);
|
||||
for (int i = 0; i < num_bytes / 4; i += 2) {
|
||||
to_words[i] = from_words[i+1];
|
||||
to_words[i+1] = from_words[i];
|
||||
}
|
||||
asm volatile ("memw");
|
||||
}
|
||||
|
||||
/* This API was designed for ESP32, which has seperate
|
||||
engines for SHA1,256,512. ESP32C has a single engine.
|
||||
*/
|
||||
static void esp_sha_lock_engine_inner(void);
|
||||
|
||||
bool esp_sha_try_lock_engine(esp_sha_type sha_type)
|
||||
{
|
||||
if(_lock_try_acquire(&s_sha_lock) != 0) {
|
||||
if (_lock_try_acquire(&s_sha_lock) != 0) {
|
||||
/* SHA engine is already in use */
|
||||
return false;
|
||||
} else {
|
||||
@@ -117,55 +118,156 @@ void esp_sha_lock_engine(esp_sha_type sha_type)
|
||||
esp_sha_lock_engine_inner();
|
||||
}
|
||||
|
||||
/* Enable SHA block and then lock it */
|
||||
static void esp_sha_lock_engine_inner(void)
|
||||
{
|
||||
ets_sha_enable();
|
||||
/* Need to lock DMA since it is shared with AES block */
|
||||
portENTER_CRITICAL(&crypto_dma_spinlock);
|
||||
|
||||
REG_SET_BIT(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_SHA_CLK_EN | DPORT_CRYPTO_DMA_CLK_EN);
|
||||
REG_CLR_BIT(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_SHA_RST | DPORT_CRYPTO_HMAC_RST |
|
||||
DPORT_CRYPTO_DMA_RST | DPORT_CRYPTO_DS_RST);
|
||||
|
||||
/* DMA for SHA */
|
||||
REG_WRITE(CRYPTO_DMA_AES_SHA_SELECT_REG, 1);
|
||||
}
|
||||
|
||||
/* Disable SHA block and then unlock it */
|
||||
void esp_sha_unlock_engine(esp_sha_type sha_type)
|
||||
{
|
||||
ets_sha_disable();
|
||||
REG_WRITE(CRYPTO_DMA_AES_SHA_SELECT_REG, 0);
|
||||
|
||||
REG_SET_BIT(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_SHA_RST | DPORT_CRYPTO_DMA_RST |
|
||||
DPORT_CRYPTO_DS_RST);
|
||||
REG_CLR_BIT(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_SHA_CLK_EN | DPORT_CRYPTO_DMA_CLK_EN);
|
||||
|
||||
portEXIT_CRITICAL(&crypto_dma_spinlock);
|
||||
|
||||
_lock_release(&s_sha_lock);
|
||||
}
|
||||
|
||||
#if defined (CONFIG_MBEDTLS_SHA_USE_INTERRUPT)
|
||||
static IRAM_ATTR void esp_sha_dma_isr(void *arg)
|
||||
{
|
||||
BaseType_t higher_woken;
|
||||
REG_WRITE(SHA_CLEAR_IRQ_REG, 1);
|
||||
xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
|
||||
if (higher_woken) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check if SHA operation completed */
|
||||
static int esp_sha_dma_complete(void)
|
||||
{
|
||||
#if defined (CONFIG_MBEDTLS_SHA_USE_INTERRUPT)
|
||||
if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) {
|
||||
ESP_LOGE("SHA", "Timed out waiting for completion of SHA Interrupt");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
esp_sha_wait_idle();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait until SHA is busy */
|
||||
void esp_sha_wait_idle(void)
|
||||
{
|
||||
while(DPORT_REG_READ(SHA_BUSY_REG) != 0) { }
|
||||
while (DPORT_REG_READ(SHA_BUSY_REG) != 0) { }
|
||||
}
|
||||
|
||||
/* Read the SHA digest from hardware */
|
||||
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
|
||||
{
|
||||
/* engine should be locked */
|
||||
esp_sha_wait_idle();
|
||||
if (sha_type != SHA2_512 && sha_type != SHA2_384) {
|
||||
/* <SHA-512, read out directly */
|
||||
memcpy(digest_state, (void *)SHA_H_BASE, state_length(sha_type));
|
||||
} else {
|
||||
/* SHA-512, read out with each pair of words swapped */
|
||||
memcpy_swapwords(digest_state, (void *)SHA_H_BASE, state_length(sha_type));
|
||||
}
|
||||
memcpy(digest_state, (void *)SHA_H_BASE, state_length(sha_type));
|
||||
}
|
||||
|
||||
/* Internally calls DMA API for single block */
|
||||
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block)
|
||||
{
|
||||
/* engine should be locked */
|
||||
esp_sha_dma(sha_type, data_block, block_length(sha_type), is_first_block);
|
||||
}
|
||||
|
||||
REG_WRITE(SHA_MODE_REG, sha_type);
|
||||
/* Performs SHA on multiple blocks at a time */
|
||||
int esp_sha_dma(esp_sha_type sha_type, const void *data_block, uint32_t ilen, bool is_first_block)
|
||||
{
|
||||
size_t blk_len = 0;
|
||||
const uint8_t *local_buf = data_block;
|
||||
int ret = 0;
|
||||
volatile lldesc_t dma_descr;
|
||||
|
||||
/* ESP32C SHA unit can be loaded while previous block is processing */
|
||||
memcpy_endianswap((void *)SHA_M_BASE, data_block, block_length(sha_type));
|
||||
|
||||
esp_sha_wait_idle();
|
||||
if (is_first_block) {
|
||||
REG_WRITE(SHA_START_REG, 1);
|
||||
} else {
|
||||
REG_WRITE(SHA_CONTINUE_REG, 1);
|
||||
if (ilen == 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Note: deliberately not waiting for this operation to complete,
|
||||
as a performance tweak - delay waiting until the next time we need the SHA
|
||||
unit, instead.
|
||||
*/
|
||||
blk_len = block_length(sha_type);
|
||||
|
||||
REG_WRITE(SHA_MODE_REG, sha_type);
|
||||
if ((sha_type == SHA2_512T) && (is_first_block == true)) {
|
||||
REG_WRITE(SHA_START_REG, 1);
|
||||
}
|
||||
|
||||
REG_WRITE(SHA_BLOCK_NUM_REG, (ilen / blk_len));
|
||||
|
||||
if ((sha_type == SHA2_512T) && (is_first_block == true)) {
|
||||
esp_sha_wait_idle();
|
||||
is_first_block = false;
|
||||
}
|
||||
|
||||
bzero( (void *)&dma_descr, sizeof( dma_descr ) );
|
||||
|
||||
/* DMA descriptor for Memory to DMA-AES transfer */
|
||||
dma_descr.length = ilen;
|
||||
dma_descr.size = ilen;
|
||||
dma_descr.owner = 1;
|
||||
dma_descr.eof = 1;
|
||||
dma_descr.buf = local_buf;
|
||||
dma_descr.sosf = 0;
|
||||
dma_descr.empty = 0;
|
||||
|
||||
#if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
|
||||
if ((unsigned int)data_block >= SOC_EXTRAM_DATA_LOW && (unsigned int)data_block <= SOC_EXTRAM_DATA_HIGH) {
|
||||
Cache_WriteBack_All();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reset DMA */
|
||||
SET_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
|
||||
CLEAR_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
|
||||
|
||||
/* Set descriptors */
|
||||
CLEAR_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_ADDR);
|
||||
SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, ((uint32_t)(&dma_descr))&OUT_LINK_REG_OUTLINK_ADDR);
|
||||
/* Start transfer */
|
||||
SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_START);
|
||||
|
||||
#if defined (CONFIG_MBEDTLS_SHA_USE_INTERRUPT)
|
||||
REG_WRITE(SHA_CLEAR_IRQ_REG, 1);
|
||||
if (op_complete_sem == NULL) {
|
||||
op_complete_sem = xSemaphoreCreateBinary();
|
||||
esp_intr_alloc(ETS_SHA_INTR_SOURCE, 0, esp_sha_dma_isr, 0, 0);
|
||||
}
|
||||
REG_WRITE(SHA_INT_ENA_REG, 1);
|
||||
#endif
|
||||
|
||||
if (is_first_block) {
|
||||
REG_WRITE(SHA_DMA_START_REG, 1);
|
||||
} else {
|
||||
REG_WRITE(SHA_DMA_CONTINUE_REG, 1);
|
||||
}
|
||||
|
||||
ret = esp_sha_dma_complete();
|
||||
|
||||
#if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
|
||||
if ((unsigned int)data_block >= SOC_EXTRAM_DATA_LOW && (unsigned int)data_block <= SOC_EXTRAM_DATA_HIGH) {
|
||||
Cache_Invalidate_DCache_All();
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_CRYPTO_DMA_H
|
||||
#define ESP_CRYPTO_DMA_H
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Since crypto DMA is shared between DMA-AES and SHA blocks
|
||||
* Needs to be taken by respective blocks before using Crypto DMA
|
||||
*/
|
||||
extern portMUX_TYPE crypto_dma_spinlock;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* crypto_dma.h */
|
||||
@@ -0,0 +1,224 @@
|
||||
/**
|
||||
* \brief AES block cipher, ESP32C hardware accelerated version
|
||||
* Based on mbedTLS FIPS-197 compliant version.
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_GCM_H
|
||||
#define ESP_GCM_H
|
||||
|
||||
#include "aes.h"
|
||||
#include "mbedtls/cipher.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
|
||||
#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function.*/
|
||||
|
||||
/**
|
||||
* \brief The GCM context structure.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t H[16]; /*!< H */
|
||||
size_t iv_len; /*!< The length of IV. */
|
||||
uint64_t aad_len; /*!< The total length of the additional data. */
|
||||
const unsigned char *aad; /*!< The additional data. */
|
||||
esp_aes_context aes_ctx;
|
||||
}
|
||||
esp_aes_gcm_context;
|
||||
|
||||
/**
|
||||
* \brief This function initializes the specified GCM context
|
||||
*
|
||||
* \param ctx The GCM context to initialize.
|
||||
*/
|
||||
void esp_aes_gcm_init( esp_aes_gcm_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief This function associates a GCM context with a
|
||||
* key.
|
||||
*
|
||||
* \param ctx The GCM context to initialize.
|
||||
* \param cipher The 128-bit block cipher to use.
|
||||
* \param key The encryption key.
|
||||
* \param keybits The key size in bits. Valid options are:
|
||||
* <ul><li>128 bits</li>
|
||||
* <li>192 bits</li>
|
||||
* <li>256 bits</li></ul>
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return A cipher-specific error code on failure.
|
||||
*/
|
||||
int esp_aes_gcm_setkey( esp_aes_gcm_context *ctx,
|
||||
mbedtls_cipher_id_t cipher,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief This function starts a GCM encryption or decryption
|
||||
* operation.
|
||||
*
|
||||
* \param ctx The GCM context.
|
||||
* \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
|
||||
* #MBEDTLS_GCM_DECRYPT.
|
||||
* \param iv The initialization vector.
|
||||
* \param iv_len The length of the IV.
|
||||
* \param add The buffer holding the additional data, or NULL
|
||||
* if \p add_len is 0.
|
||||
* \param add_len The length of the additional data. If 0,
|
||||
* \p add is NULL.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
*/
|
||||
int esp_aes_gcm_starts( esp_aes_gcm_context *ctx,
|
||||
int mode,
|
||||
const unsigned char *iv,
|
||||
size_t iv_len,
|
||||
const unsigned char *aad,
|
||||
size_t aad_len );
|
||||
|
||||
/**
|
||||
* \brief This function feeds an input buffer into an ongoing GCM
|
||||
* encryption or decryption operation.
|
||||
*
|
||||
* ` The function expects input to be a multiple of 16
|
||||
* Bytes. Only the last call before calling
|
||||
* mbedtls_gcm_finish() can be less than 16 Bytes.
|
||||
*
|
||||
* \note For decryption, the output buffer cannot be the same as
|
||||
* input buffer. If the buffers overlap, the output buffer
|
||||
* must trail at least 8 Bytes behind the input buffer.
|
||||
*
|
||||
* \param ctx The GCM context.
|
||||
* \param length The length of the input data. This must be a multiple of
|
||||
* 16 except in the last call before mbedtls_gcm_finish().
|
||||
* \param input The buffer holding the input data.
|
||||
* \param output The buffer for holding the output data.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
|
||||
*/
|
||||
int esp_aes_gcm_update( esp_aes_gcm_context *ctx,
|
||||
size_t length,
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief This function finishes the GCM operation and generates
|
||||
* the authentication tag.
|
||||
*
|
||||
* It wraps up the GCM stream, and generates the
|
||||
* tag. The tag can have a maximum length of 16 Bytes.
|
||||
*
|
||||
* \param ctx The GCM context.
|
||||
* \param tag The buffer for holding the tag.
|
||||
* \param tag_len The length of the tag to generate. Must be at least four.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
|
||||
*/
|
||||
int esp_aes_gcm_finish( esp_aes_gcm_context *ctx,
|
||||
unsigned char *tag,
|
||||
size_t tag_len );
|
||||
|
||||
/**
|
||||
* \brief This function clears a GCM context
|
||||
*
|
||||
* \param ctx The GCM context to clear.
|
||||
*/
|
||||
void esp_aes_gcm_free( esp_aes_gcm_context *ctx);
|
||||
|
||||
/**
|
||||
* \brief This function performs GCM encryption or decryption of a buffer.
|
||||
*
|
||||
* \note For encryption, the output buffer can be the same as the
|
||||
* input buffer. For decryption, the output buffer cannot be
|
||||
* the same as input buffer. If the buffers overlap, the output
|
||||
* buffer must trail at least 8 Bytes behind the input buffer.
|
||||
*
|
||||
* \param ctx The GCM context to use for encryption or decryption.
|
||||
* \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
|
||||
* #MBEDTLS_GCM_DECRYPT.
|
||||
* \param length The length of the input data. This must be a multiple of
|
||||
* 16 except in the last call before mbedtls_gcm_finish().
|
||||
* \param iv The initialization vector.
|
||||
* \param iv_len The length of the IV.
|
||||
* \param add The buffer holding the additional data.
|
||||
* \param add_len The length of the additional data.
|
||||
* \param input The buffer holding the input data.
|
||||
* \param output The buffer for holding the output data.
|
||||
* \param tag_len The length of the tag to generate.
|
||||
* \param tag The buffer for holding the tag.
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
*/
|
||||
int esp_aes_gcm_crypt_and_tag( esp_aes_gcm_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
const unsigned char *iv,
|
||||
size_t iv_len,
|
||||
const unsigned char *add,
|
||||
size_t add_len,
|
||||
const unsigned char *input,
|
||||
unsigned char *output,
|
||||
size_t tag_len,
|
||||
unsigned char *tag );
|
||||
|
||||
|
||||
/**
|
||||
* \brief This function performs a GCM authenticated decryption of a
|
||||
* buffer.
|
||||
*
|
||||
* \note For decryption, the output buffer cannot be the same as
|
||||
* input buffer. If the buffers overlap, the output buffer
|
||||
* must trail at least 8 Bytes behind the input buffer.
|
||||
*
|
||||
* \param ctx The GCM context.
|
||||
* \param length The length of the input data. This must be a multiple
|
||||
* of 16 except in the last call before mbedtls_gcm_finish().
|
||||
* \param iv The initialization vector.
|
||||
* \param iv_len The length of the IV.
|
||||
* \param add The buffer holding the additional data.
|
||||
* \param add_len The length of the additional data.
|
||||
* \param tag The buffer holding the tag.
|
||||
* \param tag_len The length of the tag.
|
||||
* \param input The buffer holding the input data.
|
||||
* \param output The buffer for holding the output data.
|
||||
*
|
||||
* \return 0 if successful and authenticated.
|
||||
* \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
|
||||
*/
|
||||
int esp_aes_gcm_auth_decrypt( esp_aes_gcm_context *ctx,
|
||||
size_t length,
|
||||
const unsigned char *iv,
|
||||
size_t iv_len,
|
||||
const unsigned char *add,
|
||||
size_t add_len,
|
||||
const unsigned char *tag,
|
||||
size_t tag_len,
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* gcm.h */
|
||||
@@ -11,6 +11,7 @@
|
||||
// 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.
|
||||
|
||||
#ifndef _ESP_SHA_H_
|
||||
#define _ESP_SHA_H_
|
||||
|
||||
@@ -101,6 +102,31 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
|
||||
*/
|
||||
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block);
|
||||
|
||||
/* @brief Begin to execute SHA block operation using DMA
|
||||
*
|
||||
* @note This is a piece of a SHA algorithm, rather than an entire SHA
|
||||
* algorithm.
|
||||
*
|
||||
* @note Call esp_sha_try_lock_engine() before calling this
|
||||
* function. Do not call esp_sha_lock_memory_block() beforehand, this
|
||||
* is done inside the function.
|
||||
*
|
||||
* @param sha_type SHA algorithm to use.
|
||||
*
|
||||
* @param data_block Pointer to block of data. Block size is
|
||||
* determined by algorithm (SHA1/SHA2_256 = 64 bytes,
|
||||
* SHA2_384/SHA2_512 = 128 bytes)
|
||||
*
|
||||
* @param ilen length of input data should be multiple of block length.
|
||||
*
|
||||
* @param is_first_block If this parameter is true, the SHA state will
|
||||
* be initialised (with the initial state of the given SHA algorithm)
|
||||
* before the block is calculated. If false, the existing state of the
|
||||
* SHA engine will be used.
|
||||
*
|
||||
*/
|
||||
int esp_sha_dma(esp_sha_type sha_type, const void *data_block, uint32_t ilen, bool is_first_block);
|
||||
|
||||
/** @brief Read out the current state of the SHA digest loaded in the engine.
|
||||
*
|
||||
* @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm.
|
||||
|
||||
Reference in New Issue
Block a user