arch/risc-v: Add arch layer SHA accelerator support for esp32[-c3|-c6|-h2]

Add arch layer SHA accelerator support for risc-v based Espressif devices

Signed-off-by: Eren Terzioglu <eren.terzioglu@espressif.com>
This commit is contained in:
Eren Terzioglu 2025-05-19 10:42:54 +02:00 committed by Xiang Xiao
parent 22560958bc
commit 8e44c85a3a
8 changed files with 1487 additions and 0 deletions

View file

@ -345,6 +345,12 @@ config ESPRESSIF_LEDC
select PWM
select ARCH_HAVE_PWM_MULTICHAN
config ESPRESSIF_SHA_ACCELERATOR
bool "SHA Accelerator"
default n
---help---
Enable SHA accelerator support.
config ESPRESSIF_ADC
bool "Analog-to-digital converter (ADC)"
default n

View file

@ -170,6 +170,14 @@ ifeq ($(CONFIG_ESPRESSIF_ADC),y)
CHIP_CSRCS += esp_adc.c
endif
ifeq ($(CONFIG_ESPRESSIF_SHA_ACCELERATOR),y)
CHIP_CSRCS += esp_sha.c
endif
ifeq ($(CONFIG_CRYPTO_CRYPTODEV_HARDWARE),y)
CHIP_CSRCS += esp_crypto.c
endif
#############################################################################
# Espressif HAL for 3rd Party Platforms
#############################################################################

View file

@ -0,0 +1,605 @@
/****************************************************************************
* arch/risc-v/src/common/espressif/esp_crypto.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <errno.h>
#include <stddef.h>
#include <sys/queue.h>
#include <crypto/cryptodev.h>
#include <crypto/xform.h>
#include <nuttx/kmalloc.h>
#include <nuttx/crypto/crypto.h>
#include "esp_sha.h"
/****************************************************************************
* Private Functions Prototypes
****************************************************************************/
static void sha1_init(void *ctx);
static int sha1_update(void *ctx, const uint8_t *in, size_t len);
static void sha1_final(uint8_t *out, void *ctx);
static void sha256_init(void *ctx);
static int sha256_update(void *ctx, const uint8_t *in, size_t len);
static void sha256_final(uint8_t *out, void *ctx);
static int esp_freesession(uint64_t tid);
/****************************************************************************
* Private Data
****************************************************************************/
SLIST_HEAD(esp_crypto_list, esp_crypto_data);
static struct esp_crypto_list *g_esp_sessions = NULL;
static uint32_t g_esp_sesnum = 0;
const struct auth_hash g_auth_hash_hmac_sha1_esp =
{
CRYPTO_SHA1_HMAC, "HMAC-SHA1",
20, 20, 12, sizeof(struct esp_sha1_context_s),
HMAC_SHA1_BLOCK_LEN,
sha1_init, NULL, NULL,
sha1_update,
sha1_final
};
const struct auth_hash g_auth_hash_hmac_sha256_esp =
{
CRYPTO_SHA2_256_HMAC, "HMAC-SHA2-256",
32, 32, 16, sizeof(struct esp_sha256_context_s),
HMAC_SHA2_256_BLOCK_LEN,
sha256_init, NULL, NULL,
sha256_update,
sha256_final
};
struct esp_crypto_data
{
int alg; /* Algorithm */
union
{
struct
{
uint8_t *ictx;
uint8_t *octx;
uint32_t klen;
const struct auth_hash *axf;
} HWCR_AUTH;
} HWCR_UN;
#define hw_ictx HWCR_UN.HWCR_AUTH.ictx
#define hw_octx HWCR_UN.HWCR_AUTH.octx
#define hw_klen HWCR_UN.HWCR_AUTH.klen
#define hw_axf HWCR_UN.HWCR_AUTH.axf
SLIST_ENTRY(esp_crypto_data) next;
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sha1_init
*
* Description:
* Starts a SHA-1 checksum calculation.
*
* Input Parameters:
* ctx - The SHA-1 context to initialize
*
* Returned Value:
* None
*
****************************************************************************/
static void sha1_init(void *ctx)
{
esp_sha1_starts(ctx);
}
/****************************************************************************
* Name: sha1_update
*
* Description:
* Feeds an input buffer into an ongoing SHA-1 checksum calculation.
*
* Input Parameters:
* ctx - The SHA-1 context to use
* in - The buffer holding the input data
* len - The length of the input data in Bytes
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
static int sha1_update(void *ctx, const uint8_t *in, size_t len)
{
return esp_sha1_update((struct esp_sha1_context_s *)ctx,
(const unsigned char *)in,
(size_t)len);
}
/****************************************************************************
* Name: sha1_final
*
* Description:
* Finishes the SHA-1 operation,
* and writes the result to the output buffer.
*
* Input Parameters:
* out - The SHA-1 checksum result
* ctx - The SHA-1 context to use
*
* Returned Value:
* None
*
****************************************************************************/
static void sha1_final(uint8_t *out, void *ctx)
{
esp_sha1_finish((struct esp_sha1_context_s *)ctx,
(unsigned char *)out);
}
/****************************************************************************
* Name: sha256_init
*
* Description:
* Initializes a SHA-256 context.
*
* Input Parameters:
* ctx - The SHA-256 context to initialize
*
* Returned Value:
* None.
*
****************************************************************************/
static void sha256_init(void *ctx)
{
esp_sha256_starts(ctx, false);
}
/****************************************************************************
* Name: sha256_update
*
* Description:
* Feeds an input buffer into an ongoing SHA-224 or SHA-256
* checksum calculation.
*
* Input Parameters:
* ctx - The SHA-256 context to use
* in - The buffer holding the input data
* len - The length of the input data in Bytes
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
static int sha256_update(void *ctx, const uint8_t *in, size_t len)
{
return esp_sha256_update((struct esp_sha256_context_s *)ctx,
(const unsigned char *)in,
(size_t)len);
}
/****************************************************************************
* Name: sha256_final
*
* Description:
* Finishes the SHA-224 or SHA-256 operation, and writes the result to
* the output buffer.
*
* Input Parameters:
* out - The SHA-256 checksum result
* ctx - The SHA-256 context to use
*
* Returned Value:
* None.
*
****************************************************************************/
static void sha256_final(uint8_t *out, void *ctx)
{
esp_sha256_finish((struct esp_sha256_context_s *)ctx,
(unsigned char *)out);
}
/****************************************************************************
* Name: authcompute
*
* Description:
* Calculate the hash.
*
* Input Parameters:
* crp - Pointer of cryptop struct
* crd - Pointer of description struct
* data - Internal struct for crypt
* buf - Buffer to compute
*
* Returned Value:
* OK on success; Negated errno on failure.
*
****************************************************************************/
static int authcompute(struct cryptop *crp, struct cryptodesc *crd,
struct esp_crypto_data *data,
caddr_t buf)
{
unsigned char aalg[AALG_MAX_RESULT_LEN];
const struct auth_hash *axf;
int err = 0;
if (data->hw_ictx == 0)
{
return -EINVAL;
}
axf = data->hw_axf;
err = axf->update(data->hw_ictx, (uint8_t *)buf, crd->crd_len);
if (err)
{
return err;
}
if (crd->crd_flags & CRD_F_ESN)
{
axf->update(data->hw_ictx, crd->crd_esn, 4);
}
switch (data->alg)
{
case CRYPTO_SHA1_HMAC:
case CRYPTO_SHA2_256_HMAC:
if (data->hw_octx == NULL)
{
return -EINVAL;
}
axf->final(aalg, data->hw_ictx);
axf->update(data->hw_octx, aalg, axf->hashsize);
axf->final(aalg, data->hw_octx);
break;
}
/* Inject the authentication data */
bcopy(aalg, crp->crp_mac, axf->hashsize);
return OK;
}
/****************************************************************************
* Name: esp_newsession
*
* Description:
* Create new session for crypto.
*
* Input Parameters:
* sid - Session id
* cri - Pointer of cryptop struct
*
* Returned Value:
* OK on success; Negated errno on failure.
*
****************************************************************************/
static int esp_newsession(uint32_t *sid, struct cryptoini *cri)
{
struct esp_crypto_list *session;
struct esp_crypto_data *prev = NULL;
struct esp_crypto_data *data;
const struct auth_hash *axf;
int i;
int k;
if (sid == NULL || cri == NULL)
{
return -EINVAL;
}
for (i = 0; i < g_esp_sesnum; i++)
{
if (SLIST_EMPTY(&g_esp_sessions[i]))
{
break;
}
}
if (i >= g_esp_sesnum)
{
if (g_esp_sessions == NULL)
{
g_esp_sesnum = 1;
}
else
{
g_esp_sesnum *= 2;
}
session = kmm_calloc(g_esp_sesnum,
sizeof(struct esp_crypto_list));
if (session == NULL)
{
g_esp_sesnum /= 2;
return -ENOBUFS;
}
if (g_esp_sessions != NULL)
{
bcopy(g_esp_sessions, session, (g_esp_sesnum / 2) *
sizeof(struct esp_crypto_list));
kmm_free(g_esp_sessions);
}
g_esp_sessions = session;
}
session = &g_esp_sessions[i];
*sid = i;
while (cri)
{
data = kmm_malloc(sizeof(struct esp_crypto_data));
if (data == NULL)
{
esp_freesession(i);
return -ENOBUFS;
}
switch (cri->cri_alg)
{
case CRYPTO_SHA1_HMAC:
axf = &g_auth_hash_hmac_sha1_esp;
goto common;
case CRYPTO_SHA2_256_HMAC:
axf = &g_auth_hash_hmac_sha256_esp;
goto common;
common:
data->hw_ictx = kmm_malloc(axf->ctxsize);
if (data->hw_ictx == NULL)
{
kmm_free(data);
return -ENOBUFS;
}
data->hw_octx = kmm_malloc(axf->ctxsize);
if (data->hw_octx == NULL)
{
kmm_free(data->hw_ictx);
kmm_free(data);
return -ENOBUFS;
}
for (k = 0; k < cri->cri_klen / 8; k++)
{
cri->cri_key[k] ^= HMAC_IPAD_VAL;
}
axf->init(data->hw_ictx);
axf->update(data->hw_ictx, (uint8_t *)cri->cri_key,
cri->cri_klen / 8);
axf->update(data->hw_ictx, hmac_ipad_buffer,
axf->blocksize - (cri->cri_klen / 8));
for (k = 0; k < cri->cri_klen / 8; k++)
{
cri->cri_key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
}
axf->init(data->hw_octx);
axf->update(data->hw_octx, (uint8_t *)cri->cri_key,
cri->cri_klen / 8);
axf->update(data->hw_octx, hmac_opad_buffer,
axf->blocksize - (cri->cri_klen / 8));
for (k = 0; k < cri->cri_klen / 8; k++)
{
cri->cri_key[k] ^= HMAC_OPAD_VAL;
}
data->hw_axf = axf;
break;
default:
esp_freesession(i);
kmm_free(data);
return -EINVAL;
}
if (prev == NULL)
{
SLIST_INSERT_HEAD(session, data, next);
}
else
{
SLIST_INSERT_AFTER(prev, data, next);
}
data->alg = cri->cri_alg;
cri = cri->cri_next;
prev = data;
}
return OK;
}
/****************************************************************************
* Name: esp_freesession
*
* Description:
* Free session.
*
* Input Parameters:
* tid - Session id
*
* Returned Value:
* OK on success; Negated errno on failure.
*
****************************************************************************/
static int esp_freesession(uint64_t tid)
{
struct esp_crypto_list *session;
struct esp_crypto_data *data;
const struct auth_hash *axf;
uint32_t sid = ((uint32_t)tid) & 0xffffffff;
if (sid > g_esp_sesnum || SLIST_EMPTY(&g_esp_sessions[sid]))
{
return -EINVAL;
}
session = &g_esp_sessions[sid];
while (!SLIST_EMPTY(session))
{
data = SLIST_FIRST(session);
switch (data->alg)
{
case CRYPTO_SHA1_HMAC:
case CRYPTO_SHA2_256_HMAC:
axf = data->hw_axf;
if (data->hw_ictx)
{
explicit_bzero(data->hw_ictx, axf->ctxsize);
kmm_free(data->hw_ictx);
}
if (data->hw_octx)
{
explicit_bzero(data->hw_octx, axf->ctxsize);
kmm_free(data->hw_octx);
}
break;
}
SLIST_REMOVE_HEAD(session, next);
kmm_free(data);
}
return OK;
}
/****************************************************************************
* Name: esp_process
*
* Description:
* Process session to use hardware algorithm.
*
* Input Parameters:
* crp - Pointer of cryptop struct
*
* Returned Value:
* OK on success; Negated errno on failure.
*
****************************************************************************/
static int esp_process(struct cryptop *crp)
{
struct cryptodesc *crd;
struct esp_crypto_list *session;
struct esp_crypto_data *data;
uint32_t lid;
int err = 0;
lid = crp->crp_sid & 0xffffffff;
/* Go through crypto descriptors, processing as we go */
session = &g_esp_sessions[lid];
for (crd = crp->crp_desc; crd; crd = crd->crd_next)
{
SLIST_FOREACH(data, session, next)
{
if (data->alg == crd->crd_alg)
{
break;
}
}
if (data == NULL)
{
crp->crp_etype = EINVAL;
return -EINVAL;
}
switch (data->alg)
{
case CRYPTO_SHA1_HMAC:
case CRYPTO_SHA2_256_HMAC:
if ((crp->crp_etype = authcompute(crp, crd, data,
crp->crp_buf)) != 0)
{
return crp->crp_etype;
}
break;
default:
return -EINVAL;
}
}
return OK;
}
/****************************************************************************
* Name: hwcr_init
*
* Description:
* Register the hardware crypto driver.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void hwcr_init(void)
{
int hwcr_id;
int algs[CRYPTO_ALGORITHM_MAX + 1];
hwcr_id = crypto_get_driverid(0);
DEBUGASSERT(hwcr_id >= 0);
memset(algs, 0, sizeof(algs));
algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
algs[CRYPTO_SHA2_256_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
esp_sha_init();
crypto_register(hwcr_id, algs, esp_newsession,
esp_freesession, esp_process);
}

View file

@ -0,0 +1,607 @@
/****************************************************************************
* arch/risc-v/src/common/espressif/esp_sha.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#ifdef CONFIG_ESPRESSIF_SHA_ACCELERATOR
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <debug.h>
#include <nuttx/mutex.h>
#include "riscv_internal.h"
#include "esp_sha.h"
#include "esp_private/periph_ctrl.h"
#include "soc/periph_defs.h"
#include "hal/sha_hal.h"
#include "soc/soc_caps.h"
#include "rom/cache.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if CONFIG_SOC_SHA_SUPPORT_PARALLEL_ENG
# error "Parallel engine feature is not supported."
#endif
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i)] = (unsigned char) ((n) >> 24); \
(b)[(i) + 1] = (unsigned char) ((n) >> 16); \
(b)[(i) + 2] = (unsigned char) ((n) >> 8); \
(b)[(i) + 3] = (unsigned char) ((n)); \
}
#define SHA1_BLK_SIZE (20)
#define SHA2_BLK_SIZE (32)
/****************************************************************************
* Private Data
****************************************************************************/
static bool g_sha_inited;
static mutex_t g_sha_lock = NXMUTEX_INITIALIZER;
static const unsigned char esp_sha_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: esp_sha_hash_block
*
* Description:
* Performs SHA on multiple blocks at a time.
*
* Input Parameters:
* type - Type of SHA
* first_block - Pointer of the ctx struct about is block first
* state - Pointer of the ctx struct about state
* data - Input message to be hashed on single block
* len - Length of the input message on single block
* buf - Input message to be hashed on multiple blocks
* buf_len - Length of the input message on multiple blocks
*
* Returned Value:
* OK is returned on success.
*
****************************************************************************/
static int esp_sha_hash_block(enum esp_sha_type_e type,
bool *first_block, uint32_t *state,
const uint8_t *data, size_t len,
uint8_t *buf, size_t buf_len)
{
uint32_t *data_words = NULL;
size_t blk_len = 0;
size_t blk_word_len = 0;
int num_block = 0;
int i;
int j;
blk_len = 64;
blk_word_len = blk_len / 4;
num_block = len / blk_len;
if (buf_len != 0)
{
sha_hal_hash_block(type, buf, blk_word_len, (*first_block));
(*first_block) = false;
}
for (j = 0; j < num_block; j++)
{
data_words = (uint32_t *)(data + blk_len * j);
sha_hal_hash_block(type, data_words, blk_word_len, (*first_block));
(*first_block) = false;
}
sha_hal_read_digest(type, state);
return OK;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: esp_sha1_init
*
* Description:
* Initializes a SHA-1 context.
*
* Input Parameters:
* ctx - The SHA-1 context to initialize
*
* Returned Value:
* None.
*
****************************************************************************/
void esp_sha1_init(struct esp_sha1_context_s *ctx)
{
memset(ctx, 0, sizeof(struct esp_sha1_context_s));
}
/****************************************************************************
* Name: esp_sha1_starts
*
* Description:
* Starts a SHA-1 checksum calculation.
*
* Input Parameters:
* ctx - The SHA-1 context to initialize
*
* Returned Value:
* OK is returned on success.
*
****************************************************************************/
int esp_sha1_starts(struct esp_sha1_context_s *ctx)
{
memset(ctx, 0, sizeof(struct esp_sha1_context_s));
ctx->mode = ESP_SHA1_1;
return OK;
}
/****************************************************************************
* Name: esp_sha1_update
*
* Description:
* Feeds an input buffer into an ongoing SHA-1 checksum calculation.
*
* Input Parameters:
* ctx - The SHA-1 context to use
* input - The buffer holding the input data
* ilen - The length of the input data in Bytes
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha1_update(struct esp_sha1_context_s *ctx,
const unsigned char *input,
size_t ilen)
{
int ret;
size_t fill;
uint32_t left;
uint32_t len;
uint32_t local_len = 0;
int i;
if (!ilen || (input == NULL))
{
return OK;
}
left = ctx->total[0] & 0x3f;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= UINT32_MAX;
if (ctx->total[0] < ilen)
{
ctx->total[1]++;
}
if (left && ilen >= fill)
{
memcpy((void *) (ctx->buffer + left), input, fill);
input += fill;
ilen -= fill;
left = 0;
local_len = 64;
}
len = (ilen / 64) * 64;
if (len || local_len)
{
ret = nxmutex_lock(&g_sha_lock);
if (ret < 0)
{
return ret;
}
if (ctx->sha_state == ESP_SHA_STATE_INIT)
{
ctx->first_block = true;
ctx->sha_state = ESP_SHA_STATE_IN_PROCESS;
}
else if (ctx->sha_state == ESP_SHA_STATE_IN_PROCESS)
{
ctx->first_block = false;
sha_hal_write_digest(ctx->mode, ctx->state);
}
ret = esp_sha_hash_block(ctx->mode, &ctx->first_block, ctx->state,
input, len, ctx->buffer, local_len);
ret |= nxmutex_unlock(&g_sha_lock);
if (ret != 0)
{
return ret;
}
}
if (ilen > 0)
{
memcpy((void *) (ctx->buffer + left), input + len, ilen - len);
}
return OK;
}
/****************************************************************************
* Name: esp_sha1_finish
*
* Description:
* Finishes the SHA-1 operation,
* and writes the result to the output buffer.
*
* Input Parameters:
* ctx - The SHA-1 context to use
* output - The SHA-1 checksum result
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha1_finish(struct esp_sha1_context_s *ctx,
unsigned char output[20])
{
int ret;
uint32_t last;
uint32_t padn;
uint32_t high;
uint32_t low;
unsigned char msglen[8];
high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
PUT_UINT32_BE(high, msglen, 0);
PUT_UINT32_BE(low, msglen, 4);
last = ctx->total[0] & 0x3f;
padn = (last < 56) ? (56 - last) : (120 - last);
ret = esp_sha1_update(ctx, esp_sha_padding, padn);
if (ret != 0)
{
return ret;
}
ret = esp_sha1_update(ctx, msglen, 8);
if (ret != 0)
{
return ret;
}
memcpy(output, ctx->state, SHA1_BLK_SIZE);
return ret;
}
/****************************************************************************
* Name: esp_sha1_free
*
* Description:
* Clears a SHA-1 context.
*
* Input Parameters:
* ctx - The SHA-1 context to clear
*
* Returned Value:
* None.
*
****************************************************************************/
void esp_sha1_free(struct esp_sha1_context_s *ctx)
{
if (ctx == NULL)
{
return;
}
memset(ctx, 0, sizeof(struct esp_sha1_context_s));
}
/****************************************************************************
* Name: esp_sha256_init
*
* Description:
* Initializes a SHA-256 context.
*
* Input Parameters:
* ctx - The SHA-256 context to initialize
*
* Returned Value:
* None.
*
****************************************************************************/
void esp_sha256_init(struct esp_sha256_context_s *ctx)
{
memset(ctx, 0, sizeof(struct esp_sha256_context_s));
}
/****************************************************************************
* Name: esp_sha256_starts
*
* Description:
* Starts a SHA-224 or SHA-256 checksum calculation.
*
* Input Parameters:
* ctx - The SHA-256 context to initialize
* is224 - Determines which function to use
*
* Returned Value:
* OK is returned on success.
*
****************************************************************************/
int esp_sha256_starts(struct esp_sha256_context_s *ctx, bool is224)
{
memset(ctx, 0, sizeof(struct esp_sha256_context_s));
if (is224)
{
ctx->mode = ESP_SHA2_224;
}
else
{
ctx->mode = ESP_SHA2_256;
}
return OK;
}
/****************************************************************************
* Name: esp_sha256_update
*
* Description:
* Feeds an input buffer into an ongoing SHA-224 or SHA-256
* checksum calculation.
*
* Input Parameters:
* ctx - The SHA-256 context to use
* input - The buffer holding the input data
* ilen - The length of the input data in Bytes
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha256_update(struct esp_sha256_context_s *ctx,
const unsigned char *input,
size_t ilen)
{
int ret = 0;
size_t fill;
uint32_t left;
uint32_t len;
uint32_t local_len = 0;
int i;
if (ilen == 0)
{
return OK;
}
left = ctx->total[0] & 0x3f;
fill = 64 - left;
ctx->total[0] += ilen;
ctx->total[0] &= UINT32_MAX;
if (ctx->total[0] < ilen)
{
ctx->total[1]++;
}
/* Check if any data pending from previous call to this API */
if (left && ilen >= fill)
{
memcpy((void *) (ctx->buffer + left), input, fill);
input += fill;
ilen -= fill;
left = 0;
local_len = 64;
}
len = (ilen / 64) * 64;
if (len || local_len)
{
ret = nxmutex_lock(&g_sha_lock);
if (ret < 0)
{
return ret;
}
if (ctx->sha_state == ESP_SHA_STATE_INIT)
{
ctx->first_block = true;
ctx->sha_state = ESP_SHA_STATE_IN_PROCESS;
}
else if (ctx->sha_state == ESP_SHA_STATE_IN_PROCESS)
{
ctx->first_block = false;
sha_hal_write_digest(ctx->mode, ctx->state);
}
ret = esp_sha_hash_block(ctx->mode, &ctx->first_block, ctx->state,
input, len, ctx->buffer, local_len);
ret |= nxmutex_unlock(&g_sha_lock);
if (ret != 0)
{
return ret;
}
}
if (ilen > 0)
{
memcpy((void *) (ctx->buffer + left), input + len, ilen - len);
}
return OK;
}
/****************************************************************************
* Name: esp_sha256_finish
*
* Description:
* Finishes the SHA-224 or SHA-256 operation, and writes the result to
* the output buffer.
*
* Input Parameters:
* ctx - The SHA-256 context to use
* output - The SHA-256 checksum result
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha256_finish(struct esp_sha256_context_s *ctx,
unsigned char output[32])
{
int ret;
uint32_t last;
uint32_t padn;
uint32_t high;
uint64_t low;
unsigned char msglen[8];
high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
PUT_UINT32_BE(high, msglen, 0);
PUT_UINT32_BE(low, msglen, 4);
last = ctx->total[0] & 0x3f;
padn = (last < 56) ? (56 - last) : (120 - last);
ret = esp_sha256_update(ctx, esp_sha_padding, padn);
if (ret != 0)
{
return ret;
}
ret = esp_sha256_update(ctx, msglen, 8);
if (ret != 0)
{
return ret;
}
memcpy(output, ctx->state, SHA2_BLK_SIZE);
return ret;
}
/****************************************************************************
* Name: esp_sha256_free
*
* Description:
* Clears a SHA-256 context.
*
* Input Parameters:
*
* Returned Value:
* None.
*
****************************************************************************/
void esp_sha256_free(struct esp_sha256_context_s *ctx)
{
if (ctx == NULL)
{
return;
}
memset(ctx, 0, sizeof(struct esp_sha256_context_s));
}
/****************************************************************************
* Name: esp_sha_init
*
* Description:
* Initialize ESP device SHA hardware.
*
* Input Parameters:
* None
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha_init(void)
{
if (!g_sha_inited)
{
periph_module_enable(PERIPH_SHA_MODULE);
g_sha_inited = true;
}
else
{
return -EBUSY;
}
return OK;
}
#endif

View file

@ -0,0 +1,258 @@
/****************************************************************************
* arch/risc-v/src/common/espressif/esp_sha.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#ifndef __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_SHA_H
#define __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_SHA_H
#include <nuttx/config.h>
#include <stdint.h>
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Types
****************************************************************************/
enum esp_sha_type_e
{
ESP_SHA1_1 = 0,
ESP_SHA2_224,
ESP_SHA2_256,
ESP_SHA3_384,
ESP_SHA3_512,
ESP_SHA_TYPE_MAX
};
enum esp_sha_state_e
{
ESP_SHA_STATE_INIT,
ESP_SHA_STATE_IN_PROCESS
};
/* SHA-1 context structure */
struct esp_sha1_context_s
{
uint32_t total[2]; /* number of bytes processed */
uint32_t state[5]; /* intermediate digest state */
unsigned char buffer[64]; /* data block being processed */
bool first_block; /* if first then true, else false */
enum esp_sha_type_e mode;
enum esp_sha_state_e sha_state;
};
/* SHA-256 context structure */
struct esp_sha256_context_s
{
uint32_t total[2]; /* number of bytes processed */
uint32_t state[8]; /* intermediate digest state */
unsigned char buffer[64]; /* data block being processed */
bool first_block; /* if first then true, else false */
enum esp_sha_type_e mode;
enum esp_sha_state_e sha_state;
};
/****************************************************************************
* Name: esp_sha_init
*
* Description:
* Initialize ESP32-C3 SHA hardware.
*
* Input Parameters:
* None
*
* Returned Value:
* OK is returned on success. Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha_init(void);
/****************************************************************************
* Name: esp_sha1_init
*
* Description:
* Initializes a SHA-1 context.
*
* Input Parameters:
* ctx - The SHA-1 context to initialize
*
* Returned Value:
* None.
*
****************************************************************************/
void esp_sha1_init(struct esp_sha1_context_s *ctx);
/****************************************************************************
* Name: esp_sha1_starts
*
* Description:
* Starts a SHA-1 checksum calculation.
*
* Input Parameters:
* ctx - The SHA-1 context to initialize
*
* Returned Value:
* OK is returned on success.
*
****************************************************************************/
int esp_sha1_starts(struct esp_sha1_context_s *ctx);
/****************************************************************************
* Name: esp_sha1_update
*
* Description:
* Feeds an input buffer into an ongoing SHA-1 checksum calculation.
*
* Input Parameters:
* ctx - The SHA-1 context to use
* input - The buffer holding the input data
* ilen - The length of the input data in Bytes
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha1_update(struct esp_sha1_context_s *ctx,
const unsigned char *input,
size_t ilen);
/****************************************************************************
* Name: esp_sha1_finish
*
* Description:
* Finishes the SHA-1 operation,
* and writes the result to the output buffer.
*
* Input Parameters:
* ctx - The SHA-1 context to use
* output - The SHA-1 checksum result
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha1_finish(struct esp_sha1_context_s *ctx,
unsigned char output[20]);
/****************************************************************************
* Name: esp_sha256_init
*
* Description:
* Initializes a SHA-256 context.
*
* Input Parameters:
* ctx - The SHA-256 context to initialize
*
* Returned Value:
* None.
*
****************************************************************************/
void esp_sha256_init(struct esp_sha256_context_s *ctx);
/****************************************************************************
* Name: esp_sha256_starts
*
* Description:
* Starts a SHA-224 or SHA-256 checksum calculation.
*
* Input Parameters:
* ctx - The SHA-256 context to initialize
* is224 - Determines which function to use
*
* Returned Value:
* OK is returned on success.
*
****************************************************************************/
int esp_sha256_starts(struct esp_sha256_context_s *ctx, bool is224);
/****************************************************************************
* Name: esp_sha256_update
*
* Description:
* Feeds an input buffer into an ongoing SHA-224 or SHA-256
* checksum calculation.
*
* Input Parameters:
* ctx - The SHA-256 context to use
* input - The buffer holding the input data
* ilen - The length of the input data in Bytes
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha256_update(struct esp_sha256_context_s *ctx,
const unsigned char *input,
size_t ilen);
/****************************************************************************
* Name: esp_sha256_finish
*
* Description:
* Finishes the SHA-224 or SHA-256 operation, and writes the result to
* the output buffer.
*
* Input Parameters:
* ctx - The SHA-256 context to use
* output - The SHA-256 checksum result
*
* Returned Value:
* OK is returned on success.
* Otherwise, a negated errno value is returned.
*
****************************************************************************/
int esp_sha256_finish(struct esp_sha256_context_s *ctx,
unsigned char output[32]);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_SHA_H */

View file

@ -162,6 +162,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)sdm_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)i2c_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)i2s_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)sha_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal_iram.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)twai_hal_sja1000.c

View file

@ -169,6 +169,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)sdm_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)i2c_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)i2s_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)sha_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal_iram.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)timer_hal.c

View file

@ -155,6 +155,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)pcnt_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)i2c_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)i2s_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)sha_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)mcpwm_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)mmu_hal.c
CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)rmt_hal.c