This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 82effd4b2f xtensa/esp32: Add support for hardware accelerated SHA
82effd4b2f is described below

commit 82effd4b2f3e9ad78f38e41beb22b7703a4e6986
Author: Vlad Pruteanu <pruteanuvlad1...@yahoo.com>
AuthorDate: Sat Mar 8 18:26:33 2025 +0200

    xtensa/esp32: Add support for hardware accelerated SHA
    
    This enables the use of the cryptographic accelerator within
    the ESP32. The support algorithms are: SHA1, SHA256, SHA384
    and SHA512.
    
    Signed-off-by: Vlad Pruteanu <pruteanuvlad1...@yahoo.com>
---
 .../xtensa/esp32/boards/esp32-devkitc/index.rst    |   7 +
 Documentation/platforms/xtensa/esp32/index.rst     |   2 +-
 arch/xtensa/src/esp32/Kconfig                      |   5 +
 arch/xtensa/src/esp32/Make.defs                    |   8 +
 arch/xtensa/src/esp32/esp32_crypto.c               | 567 +++++++++++++++++++++
 arch/xtensa/src/esp32/esp32_sha.c                  | 399 +++++++++++++++
 arch/xtensa/src/esp32/esp32_sha.h                  | 226 ++++++++
 arch/xtensa/src/esp32/hal.mk                       |   2 +
 .../esp32/esp32-devkitc/configs/crypto/defconfig   |  57 +++
 9 files changed, 1272 insertions(+), 1 deletion(-)

diff --git 
a/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst 
b/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst
index 8aaba387e0..30c69266cc 100644
--- a/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst
+++ b/Documentation/platforms/xtensa/esp32/boards/esp32-devkitc/index.rst
@@ -360,6 +360,13 @@ disables the NuttShell to get the best possible score.
 .. note:: As the NSH is disabled, the application will start as soon as the
   system is turned on.
 
+crypto
+--------
+
+This configuration enables support for the cryptographic hardware and
+the /dev/crypto device file. Currently, only the hashing operation is
+supported.
+
 cxx
 ---
 
diff --git a/Documentation/platforms/xtensa/esp32/index.rst 
b/Documentation/platforms/xtensa/esp32/index.rst
index 534cb9de66..fec15b9745 100644
--- a/Documentation/platforms/xtensa/esp32/index.rst
+++ b/Documentation/platforms/xtensa/esp32/index.rst
@@ -417,7 +417,7 @@ RSA          No
 RTC          Yes
 SD/MMC       No
 SDIO         No
-SHA          No
+SHA          Yes
 SPI          Yes
 SPIFLASH     Yes
 SPIRAM       Yes
diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig
index 4d7bcb2b8a..4cdf20047b 100644
--- a/arch/xtensa/src/esp32/Kconfig
+++ b/arch/xtensa/src/esp32/Kconfig
@@ -794,6 +794,11 @@ config ESP32_TWAI0
 config ESP32_AES_ACCELERATOR
        bool "AES Accelerator"
        default n
+config ESP32_SHA_ACCELERATOR
+       bool "SHA Accelerator"
+       default n
+       ---help---
+               Enable ESP32 SHA accelerator support.
 
 config ESP32_PID
        bool "PID Controller"
diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs
index c0fd584a23..2ed06ab631 100644
--- a/arch/xtensa/src/esp32/Make.defs
+++ b/arch/xtensa/src/esp32/Make.defs
@@ -192,6 +192,14 @@ ifeq ($(CONFIG_ESP32_AES_ACCELERATOR),y)
 CHIP_CSRCS += esp32_aes.c
 endif
 
+ifeq ($(CONFIG_ESP32_SHA_ACCELERATOR),y)
+CHIP_CSRCS += esp32_sha.c
+endif
+
+ifeq ($(CONFIG_CRYPTO_CRYPTODEV_HARDWARE),y)
+CHIP_CSRCS += esp32_crypto.c
+endif
+
 ifeq ($(CONFIG_ESP32_RTC),y)
 CHIP_CSRCS += esp32_rtc.c
 ifeq ($(CONFIG_RTC_DRIVER),y)
diff --git a/arch/xtensa/src/esp32/esp32_crypto.c 
b/arch/xtensa/src/esp32/esp32_crypto.c
new file mode 100644
index 0000000000..6ec2f4e605
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_crypto.c
@@ -0,0 +1,567 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_crypto.c
+ *
+ * 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 "esp32_sha.h"
+#include <stdio.h>
+
+/****************************************************************************
+ * Private Functions Prototypes
+ ****************************************************************************/
+
+static void sha1_init(void *ctx);
+static void sha256_init(void *ctx);
+static void sha384_init(void *ctx);
+static void sha512_init(void *ctx);
+static int sha_update(void *ctx, const uint8_t *in, size_t len);
+static void sha_final(uint8_t *out, void *ctx);
+static int esp32_freesession(uint64_t sid);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+SLIST_HEAD(esp32_crypto_list, esp32_crypto_data);
+static struct esp32_crypto_list *g_esp32_sessions = NULL;
+static uint32_t g_esp32_sesnum = 0;
+
+const struct auth_hash g_auth_hash_sha1_esp32 =
+{
+  CRYPTO_SHA1, "SHA1",
+  0, 20, 12, sizeof(struct esp32_sha_context_s),
+  0,
+  sha1_init, NULL, NULL,
+  sha_update,
+  sha_final
+};
+
+const struct auth_hash g_auth_hash_sha2_256_esp32 =
+{
+  CRYPTO_SHA2_256, "SHA256",
+  0, 32, 12, sizeof(struct esp32_sha_context_s),
+  0,
+  sha256_init, NULL, NULL,
+  sha_update,
+  sha_final
+};
+
+const struct auth_hash g_auth_hash_sha2_384_esp32 =
+{
+  CRYPTO_SHA2_384, "SHA384",
+  0, 48, 12, sizeof(struct esp32_sha_context_s),
+  0,
+  sha384_init, NULL, NULL,
+  sha_update,
+  sha_final
+};
+
+const struct auth_hash g_auth_hash_sha2_512_esp32 =
+{
+  CRYPTO_SHA2_512, "SHA512",
+  0, 64, 12, sizeof(struct esp32_sha_context_s),
+  0,
+  sha512_init, NULL, NULL,
+  sha_update,
+  sha_final
+};
+
+struct esp32_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(esp32_crypto_data) next;
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sha1_init
+ *
+ * Description:
+ *   Initialize the SHA-1 context.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA-1 context to be initialized
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void sha1_init(void *ctx)
+{
+  esp32_sha1_starts(ctx);
+}
+
+/****************************************************************************
+ * Name: sha256_init
+ *
+ * Description:
+ *   Initialize the SHA-256 context.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA-256 context to be initialized
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void sha256_init(void *ctx)
+{
+  esp32_sha256_starts(ctx);
+}
+
+/****************************************************************************
+ * Name: sha384_init
+ *
+ * Description:
+ *   Initialize the SHA-384 context.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA-384 context to be initialized
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void sha384_init(void *ctx)
+{
+  esp32_sha384_starts(ctx);
+}
+
+/****************************************************************************
+ * Name: sha512_init
+ *
+ * Description:
+ *   Initialize the SHA-512 context.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA-512 context to be initialized
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void sha512_init(void *ctx)
+{
+  esp32_sha512_starts(ctx);
+}
+
+/****************************************************************************
+ * Name: sha_update
+ *
+ * Description:
+ *   Feeds an input buffer into an ongoing SHA checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA 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 sha_update(void *ctx, const uint8_t *in, size_t len)
+{
+  return esp32_sha_update((struct esp32_sha_context_s *)ctx,
+                          (const unsigned char *)in,
+                          (size_t)len);
+}
+
+/****************************************************************************
+ * Name: sha_final
+ *
+ * Description:
+ *   Finishes the SHA operation, and writes the result to the output buffer.
+ *
+ * Input Parameters:
+ *   out      - The SHA checksum result
+ *   ctx      - The SHA context to use
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *   Otherwise, a negated errno value is returned.
+ *
+ ****************************************************************************/
+
+static void sha_final(uint8_t *out, void *ctx)
+{
+  esp32_sha_finish((struct esp32_sha_context_s *)ctx,
+                   (unsigned char *)out);
+}
+
+/****************************************************************************
+ * Name: hash
+ *
+ * Description:
+ *   Calculate the hash.
+ *
+ * Input Parameters:
+ *   crp      - The description of the crypto operation
+ *   crd      - Boundaries of the crypto operation
+ *   data     - ESP32 specific crypto operation data
+ *   buf      - Input data to be hashed
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *   Otherwise, a negated errno value is returned.
+ *
+ ****************************************************************************/
+
+static int hash(struct cryptop *crp,
+                struct cryptodesc *crd,
+                struct esp32_crypto_data *data,
+                caddr_t buf)
+{
+  const struct auth_hash *axf;
+
+  if (data->hw_ictx == 0)
+    {
+      return -EINVAL;
+    }
+
+  axf = data->hw_axf;
+
+  if (crd->crd_flags & CRD_F_UPDATE)
+    {
+      return axf->update(data->hw_ictx, (uint8_t *)buf, crd->crd_len);
+    }
+  else
+    {
+      axf->final((uint8_t *)crp->crp_mac, data->hw_ictx);
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_newsession
+ *
+ * Description:
+ *   create new session for crypto.
+ *
+ * Input Parameters:
+ *   sid      - Session id
+ *   cri      - Initialization structure
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *   Otherwise, a negated errno value is returned.
+ *
+ ****************************************************************************/
+
+static int esp32_newsession(uint32_t *sid, struct cryptoini *cri)
+{
+  struct esp32_crypto_list *session;
+  struct esp32_crypto_data *prev = NULL;
+  struct esp32_crypto_data *data;
+  const struct auth_hash *axf;
+  int i;
+  int k;
+
+  if (sid == NULL || cri == NULL)
+    {
+      return -EINVAL;
+    }
+
+  for (i = 0; i < g_esp32_sesnum; i++)
+    {
+      if (SLIST_EMPTY(&g_esp32_sessions[i]))
+        {
+          break;
+        }
+    }
+
+  if (i >= g_esp32_sesnum)
+    {
+      if (g_esp32_sessions == NULL)
+        {
+          g_esp32_sesnum = 1;
+        }
+      else
+        {
+          g_esp32_sesnum *= 2;
+        }
+
+      session = kmm_calloc(g_esp32_sesnum,
+                           sizeof(struct esp32_crypto_list));
+      if (session == NULL)
+        {
+          g_esp32_sesnum /= 2;
+          return -ENOBUFS;
+        }
+
+      if (g_esp32_sessions != NULL)
+        {
+          bcopy(g_esp32_sessions, session, (g_esp32_sesnum / 2) *
+                sizeof(struct esp32_crypto_list));
+          kmm_free(g_esp32_sessions);
+        }
+
+      g_esp32_sessions = session;
+    }
+
+  session = &g_esp32_sessions[i];
+  *sid = i;
+
+  while (cri)
+    {
+      data = kmm_malloc(sizeof(struct esp32_crypto_data));
+
+      if (data == NULL)
+        {
+          esp32_freesession(i);
+          return -ENOBUFS;
+        }
+
+      switch (cri->cri_alg)
+        {
+          case CRYPTO_SHA1:
+            axf = &g_auth_hash_sha1_esp32;
+            goto common;
+          case CRYPTO_SHA2_256:
+            axf = &g_auth_hash_sha2_256_esp32;
+            goto common;
+          case CRYPTO_SHA2_384:
+            axf = &g_auth_hash_sha2_384_esp32;
+            goto common;
+          case CRYPTO_SHA2_512:
+            axf = &g_auth_hash_sha2_512_esp32;
+            goto common;
+            common:
+              data->hw_ictx = kmm_malloc(axf->ctxsize);
+              if (data->hw_ictx == NULL)
+                {
+                  kmm_free(data);
+                  return -ENOBUFS;
+                }
+
+              axf->init(data->hw_ictx);
+              data->hw_axf = axf;
+            break;
+
+          default:
+            esp32_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: esp32_freesession
+ *
+ * Description:
+ *   free session.
+ *
+ * Input Parameters:
+ *   sid      - Session id
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *   Otherwise, a negated errno value is returned.
+ *
+ ****************************************************************************/
+
+static int esp32_freesession(uint64_t sid)
+{
+  struct esp32_crypto_list *session;
+  struct esp32_crypto_data *data;
+  const struct auth_hash *axf;
+
+  if (sid > g_esp32_sesnum || SLIST_EMPTY(&g_esp32_sessions[sid]))
+    {
+      return -EINVAL;
+    }
+
+  session = &g_esp32_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 0;
+}
+
+/****************************************************************************
+ * Name: esp32_process
+ *
+ * Description:
+ *   process session to use hardware algorithm.
+ *
+ * Input Parameters:
+ *   crp      - The description of the crypto operation
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *   Otherwise, a negated errno value is returned.
+ *
+ ****************************************************************************/
+
+static int esp32_process(struct cryptop *crp)
+{
+  struct cryptodesc *crd;
+  struct esp32_crypto_list *session;
+  struct esp32_crypto_data *data;
+  uint8_t iv[AESCTR_BLOCKSIZE];
+  uint32_t lid;
+  int err = 0;
+  lid = crp->crp_sid & 0xffffffff;
+
+  /* Go through crypto descriptors, processing as we go */
+
+  session = &g_esp32_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:
+          case CRYPTO_SHA2_256:
+          case CRYPTO_SHA2_384:
+          case CRYPTO_SHA2_512:
+            if ((crp->crp_etype = hash(crp, crd, data,
+                crp->crp_buf)) != 0)
+              {
+                return 0;
+              }
+
+            break;
+          default:
+            return -EINVAL;
+        }
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: hwcr_init
+ *
+ * Description:
+ *   register the hardware crypto driver.
+ *
+ ****************************************************************************/
+
+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] = CRYPTO_ALG_FLAG_SUPPORTED;
+  algs[CRYPTO_SHA2_256] = CRYPTO_ALG_FLAG_SUPPORTED;
+  algs[CRYPTO_SHA2_384] = CRYPTO_ALG_FLAG_SUPPORTED;
+  algs[CRYPTO_SHA2_512] = CRYPTO_ALG_FLAG_SUPPORTED;
+
+  esp32_sha_init();
+  crypto_register(hwcr_id, algs, esp32_newsession,
+                  esp32_freesession, esp32_process);
+}
diff --git a/arch/xtensa/src/esp32/esp32_sha.c 
b/arch/xtensa/src/esp32/esp32_sha.c
new file mode 100644
index 0000000000..6e2caf0697
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_sha.c
@@ -0,0 +1,399 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_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_ESP32_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 "xtensa.h"
+
+#include "hal/sha_hal.h"
+#include "periph_ctrl.h"
+
+#include "esp32_sha.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static bool g_sha_inited;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_sha_block
+ *
+ * Description:
+ *   Performs SHA on multiple blocks at a time.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context
+ *   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 esp32_sha_block(struct esp32_sha_context_s *ctx,
+                              const unsigned char *buffer)
+{
+  sha_hal_hash_block(ctx->mode, (const void *)buffer,
+                     ctx->block_size / 32, ctx->first_block);
+
+  ctx->first_block = false;
+  sha_hal_wait_idle();
+  if (ctx->final_block)
+    {
+      sha_hal_read_digest(ctx->mode, ctx->state);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_sha1_starts
+ *
+ * Description:
+ *   Starts a SHA-1 checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to initialize
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *
+ ****************************************************************************/
+
+int esp32_sha1_starts(struct esp32_sha_context_s *ctx)
+{
+  memset(ctx, 0, sizeof(struct esp32_sha_context_s));
+  ctx->mode = ESP32_SHA1_1;
+  ctx->output_size = 160;
+  ctx->block_size = 512;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_sha_update
+ *
+ * Description:
+ *   Feeds an input buffer into an ongoing SHA checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA 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 esp32_sha_update(struct esp32_sha_context_s *ctx,
+                     const unsigned char *input,
+                     size_t ilen)
+{
+  unsigned int i;
+  unsigned int j;
+
+  j = (uint32_t)((ctx->count[0] >> 3) & ((ctx->block_size >> 3) - 1));
+  ctx->count[0] += (ilen << 3);
+  if (ctx->count[0] < (ilen << 3))
+    {
+      if (ctx->mode == ESP32_SHA1_1 || ctx->mode == ESP32_SHA2_256)
+          return ERROR;
+
+      ctx->count[1]++;
+    }
+
+  if ((j + ilen) > ((ctx->block_size >> 3) - 1))
+    {
+      memcpy(&ctx->buffer[j], input, (i = (ctx->block_size >> 3) - j));
+      if (ctx->sha_state == ESP32_SHA_STATE_INIT)
+        {
+          ctx->first_block = true;
+          ctx->sha_state = ESP32_SHA_STATE_IN_PROCESS;
+        }
+      else if (ctx->sha_state == ESP32_SHA_STATE_IN_PROCESS)
+        {
+          ctx->first_block = false;
+        }
+
+      esp32_sha_block(ctx, ctx->buffer);
+      for (; i + ((ctx->block_size >> 3) - 1) < ilen;
+            i += (ctx->block_size >> 3))
+          esp32_sha_block(ctx, &input[i]);
+
+      j = 0;
+    }
+  else
+    {
+      i = 0;
+    }
+
+  memcpy(&ctx->buffer[j], &input[i], ilen - i);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_sha_finish
+ *
+ * Description:
+ *   Finishes the SHA operation,
+ *   and writes the result to the output buffer.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to use
+ *   output   - The SHA-1 checksum result
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *   Otherwise, a negated errno value is returned.
+ *
+ ****************************************************************************/
+
+int esp32_sha_finish(struct esp32_sha_context_s *ctx,
+                     unsigned char output[64])
+{
+  uint32_t aux;
+  unsigned int i;
+  unsigned char finalcount[16];
+
+  if (ctx->mode == ESP32_SHA1_1 || ctx->mode == ESP32_SHA2_256)
+      for (i = 0; i < 8; i++)
+          finalcount[i] = (unsigned char)((ctx->count[0] >>
+              ((8 - 1 - i) * 8)) & 255);
+
+  /* SHA384 and SHA512 use 1024 bits to store the message length */
+
+  else
+    {
+      for (i = 0; i < 8; i++)
+          finalcount[i] = (unsigned char)((ctx->count[1] >>
+              ((8 - 1 - i) * 8)) & 255);
+      for (i = 8; i < 16; i++)
+          finalcount[i] = (unsigned char)((ctx->count[0] >>
+              ((16 - 1 - i) * 8)) & 255);
+    }
+
+  esp32_sha_update(ctx, (unsigned char *)"\200", 1);
+
+  while ((ctx->count[0] & (ctx->block_size - 8)) !=
+          ctx->block_size - (ctx->block_size >> 3))
+      esp32_sha_update(ctx, (unsigned char *)"\0", 1);
+
+  ctx->final_block = true;
+
+  if (ctx->mode == ESP32_SHA1_1 || ctx->mode == ESP32_SHA2_256)
+      esp32_sha_update(ctx, finalcount, 8);
+
+  /* SHA384 and SHA512 use 1024 bits to store the message length */
+
+  else
+      esp32_sha_update(ctx, finalcount, 16);
+
+  if (ctx->mode == ESP32_SHA3_384 || ctx->mode == ESP32_SHA3_512)
+    {
+      /* For these ciphers swap each pair of words */
+
+      for (i = 0; i < ctx->output_size / 32; i += 2)
+        {
+          aux = ctx->state[i + 1];
+          ctx->state[i + 1] = ctx->state[i];
+          ctx->state[i] = aux;
+        }
+    }
+
+  for (i = 0; i <  ctx->output_size / 8; i++)
+    {
+      output[i] = (unsigned char)((ctx->state[i >> 2] >>
+        ((3 - (i & 3)) * 8)) & 255);
+    }
+
+  explicit_bzero(&finalcount, sizeof(finalcount));
+  explicit_bzero(ctx, sizeof(*ctx));
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32_sha1_free
+ *
+ * Description:
+ *   Clears a SHA context.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to clear
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp32_sha1_free(struct esp32_sha_context_s *ctx)
+{
+  if (ctx == NULL)
+      return;
+
+  memset(ctx, 0, sizeof(struct esp32_sha_context_s));
+}
+
+/****************************************************************************
+ * Name: esp32_sha256_starts
+ *
+ * Description:
+ *   Starts a SHA-256 checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to initialize
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *
+ ****************************************************************************/
+
+int esp32_sha256_starts(struct esp32_sha_context_s *ctx)
+{
+  memset(ctx, 0, sizeof(struct esp32_sha_context_s));
+  ctx->mode = ESP32_SHA2_256;
+  ctx->output_size = 256;
+  ctx->block_size = 512;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_sha384_starts
+ *
+ * Description:
+ *   Starts a SHA-384 checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to initialize
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *
+ ****************************************************************************/
+
+int esp32_sha384_starts(struct esp32_sha_context_s *ctx)
+{
+  memset(ctx, 0, sizeof(struct esp32_sha_context_s));
+  ctx->mode = ESP32_SHA3_384;
+  ctx->output_size = 384;
+  ctx->block_size = 1024;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_sha512_starts
+ *
+ * Description:
+ *   Starts a SHA-512 checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to initialize
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *
+ ****************************************************************************/
+
+int esp32_sha512_starts(struct esp32_sha_context_s *ctx)
+{
+  memset(ctx, 0, sizeof(struct esp32_sha_context_s));
+  ctx->mode = ESP32_SHA3_512;
+  ctx->output_size = 512;
+  ctx->block_size = 1024;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: esp32_sha_init
+ *
+ * Description:
+ *   Initialize ESP32 SHA hardware.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *   Otherwise, a negated errno value is returned.
+ *
+ ****************************************************************************/
+
+int esp32_sha_init(void)
+{
+  if (!g_sha_inited)
+    {
+      periph_module_enable(PERIPH_SHA_MODULE);
+      g_sha_inited = true;
+    }
+  else
+    {
+      return -EBUSY;
+    }
+
+  return OK;
+}
+
+#endif
+
diff --git a/arch/xtensa/src/esp32/esp32_sha.h 
b/arch/xtensa/src/esp32/esp32_sha.h
new file mode 100644
index 0000000000..8e7b491385
--- /dev/null
+++ b/arch/xtensa/src/esp32/esp32_sha.h
@@ -0,0 +1,226 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32/esp32_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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_XTENSA_SRC_ESP32_ESP32_SHA_H
+#define __ARCH_XTENSA_SRC_ESP32_ESP32_SHA_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+#ifndef __ASSEMBLY__
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <nuttx/config.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+enum esp32_sha_type_e
+{
+    ESP32_SHA1_1 = 0,
+    ESP32_SHA2_256,
+    ESP32_SHA3_384,
+    ESP32_SHA3_512,
+    ESP32_SHA_TYPE_MAX
+};
+
+enum esp32_sha_state_e
+{
+    ESP32_SHA_STATE_INIT,
+    ESP32_SHA_STATE_IN_PROCESS
+};
+
+/* SHA context structure */
+
+struct esp32_sha_context_s
+{
+    uint64_t count[2];           /* number of bits processed  */
+    uint32_t state[16];          /* intermediate digest state  */
+    bool final_block;
+    unsigned char buffer[128];   /* data block being processed */
+    bool first_block;            /* if first then true else false */
+    uint16_t output_size;
+    uint16_t block_size;
+    enum esp32_sha_type_e mode;
+    enum esp32_sha_state_e sha_state;
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32_sha_init
+ *
+ * Description:
+ *   Initialize ESP32 SHA hardware.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   OK is returned on success. Otherwise, a negated errno value is returned.
+ *
+ ****************************************************************************/
+
+int esp32_sha_init(void);
+
+/****************************************************************************
+ * Name: esp32_sha1_init
+ *
+ * Description:
+ *   Initializes a SHA context.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to initialize
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void esp32_sha1_init(struct esp32_sha_context_s *ctx);
+
+/****************************************************************************
+ * Name: esp32_sha1_starts
+ *
+ * Description:
+ *   Starts a SHA checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to initialize
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *
+ ****************************************************************************/
+
+int esp32_sha1_starts(struct esp32_sha_context_s *ctx);
+
+/****************************************************************************
+ * Name: esp32_sha_update
+ *
+ * Description:
+ *   Feeds an input buffer into an ongoing SHA checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA 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 esp32_sha_update(struct esp32_sha_context_s *ctx,
+                     const unsigned char *input,
+                     size_t ilen);
+
+/****************************************************************************
+ * Name: esp32_sha_finish
+ *
+ * Description:
+ *   Finishes the SHA operation,
+ *   and writes the result to the output buffer.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to use
+ *   output   - The SHA checksum result
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *   Otherwise, a negated errno value is returned.
+ *
+ ****************************************************************************/
+
+int esp32_sha_finish(struct esp32_sha_context_s *ctx,
+                     unsigned char output[64]);
+
+/****************************************************************************
+ * Name: esp32_sha256_starts
+ *
+ * Description:
+ *   Starts a SHA-256 checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to initialize
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *
+ ****************************************************************************/
+
+int esp32_sha256_starts(struct esp32_sha_context_s *ctx);
+
+/****************************************************************************
+ * Name: esp32_sha384_starts
+ *
+ * Description:
+ *   Starts a SHA-384 checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to initialize
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *
+ ****************************************************************************/
+
+int esp32_sha384_starts(struct esp32_sha_context_s *ctx);
+
+/****************************************************************************
+ * Name: esp32_sha512_starts
+ *
+ * Description:
+ *   Starts a SHA-512 checksum calculation.
+ *
+ * Input Parameters:
+ *   ctx      - The SHA context to initialize
+ *
+ * Returned Value:
+ *   OK is returned on success.
+ *
+ ****************************************************************************/
+
+int esp32_sha512_starts(struct esp32_sha_context_s *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_SHA_H */
diff --git a/arch/xtensa/src/esp32/hal.mk b/arch/xtensa/src/esp32/hal.mk
index f7f712879e..10b3ea5c5e 100644
--- a/arch/xtensa/src/esp32/hal.mk
+++ b/arch/xtensa/src/esp32/hal.mk
@@ -128,8 +128,10 @@ 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)uart_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)i2c_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)log$(DELIM)log_noos.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)log$(DELIM)log.c
+CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)dport_access_common.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)adc_periph.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)gpio_periph.c
 CHIP_CSRCS += 
chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)ledc_periph.c
diff --git a/boards/xtensa/esp32/esp32-devkitc/configs/crypto/defconfig 
b/boards/xtensa/esp32/esp32-devkitc/configs/crypto/defconfig
new file mode 100644
index 0000000000..600c1ac3e6
--- /dev/null
+++ b/boards/xtensa/esp32/esp32-devkitc/configs/crypto/defconfig
@@ -0,0 +1,57 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed 
.config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that 
includes your
+# modifications.
+#
+# CONFIG_ARCH_LEDS is not set
+# CONFIG_NSH_ARGCAT is not set
+# CONFIG_NSH_CMDOPT_HEXDUMP is not set
+CONFIG_ALLOW_BSD_COMPONENTS=y
+CONFIG_ARCH="xtensa"
+CONFIG_ARCH_BOARD="esp32-devkitc"
+CONFIG_ARCH_BOARD_COMMON=y
+CONFIG_ARCH_BOARD_ESP32_DEVKITC=y
+CONFIG_ARCH_CHIP="esp32"
+CONFIG_ARCH_CHIP_ESP32=y
+CONFIG_ARCH_CHIP_ESP32WROVER=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_XTENSA=y
+CONFIG_BOARD_LOOPSPERMSEC=16717
+CONFIG_BUILTIN=y
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_CRYPTODEV=y
+CONFIG_CRYPTO_CRYPTODEV_HARDWARE=y
+CONFIG_CRYPTO_RANDOM_POOL=y
+CONFIG_DEFAULT_TASK_STACKSIZE=8192
+CONFIG_ESP32_SHA_ACCELERATOR=y
+CONFIG_ESP32_UART0=y
+CONFIG_FS_PROCFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_IDLETHREAD_STACKSIZE=3072
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_STACKSIZE=6096
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_RAM_SIZE=314688
+CONFIG_RAM_START=0x20000000
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=3
+CONFIG_START_MONTH=5
+CONFIG_START_YEAR=2025
+CONFIG_SYSLOG_BUFFER=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TESTING_CRYPTO=y
+CONFIG_TESTING_CRYPTO_HASH=y
+CONFIG_UART0_SERIAL_CONSOLE=y


Reply via email to