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

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

commit c8145313aeef7d5ee1d41c2c8c82ed6be4523e54
Author: makejian <[email protected]>
AuthorDate: Tue Jan 27 00:06:42 2026 +0800

    crypto: support software key management based on MTD
    
    This patch adds support for managing cryptographic keys using MTD storage.
    
    It enables the persistence of keys across reboots using a software-based 
key management system.
    
    Includes fixes for compilation warnings and validation logic.
    
    Signed-off-by: makejian <[email protected]>
---
 boards/sim/sim/sim/configs/crypto/defconfig |   2 +-
 crypto/CMakeLists.txt                       |   3 +-
 crypto/Kconfig                              |  29 +-
 crypto/Makefile                             |   2 +-
 crypto/crypto.c                             |  15 +
 crypto/cryptodev.c                          |   8 +-
 crypto/cryptosoft.c                         | 780 ++++++++++++++++++++++++++++
 include/crypto/cryptodev.h                  |   2 +
 include/crypto/cryptosoft.h                 |   8 +
 9 files changed, 842 insertions(+), 7 deletions(-)

diff --git a/boards/sim/sim/sim/configs/crypto/defconfig 
b/boards/sim/sim/sim/configs/crypto/defconfig
index bda6bd4d8b6..489695d9e41 100644
--- a/boards/sim/sim/sim/configs/crypto/defconfig
+++ b/boards/sim/sim/sim/configs/crypto/defconfig
@@ -20,7 +20,7 @@ CONFIG_BOOT_RUNFROMEXTSRAM=y
 CONFIG_BUILTIN=y
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_CRYPTODEV=y
-CONFIG_CRYPTO_CRYPTODEV_SOFTWARE=y
+CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO=y
 CONFIG_CRYPTO_MBEDTLS=y
 CONFIG_CRYPTO_RANDOM_POOL=y
 CONFIG_CRYPTO_SW_AES=y
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index ea47feefc10..84ca74307a5 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -28,7 +28,8 @@ if(CONFIG_CRYPTO)
 
   if(CONFIG_CRYPTO_CRYPTODEV)
     list(APPEND SRCS cryptodev.c)
-    if(CONFIG_CRYPTO_CRYPTODEV_SOFTWARE)
+    if(CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO
+       OR CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT)
       list(APPEND SRCS cryptosoft.c)
       list(APPEND SRCS xform.c)
     endif()
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 7ce0ebf33b9..6bf77de0800 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -40,11 +40,36 @@ config CRYPTO_CRYPTODEV
        depends on ALLOW_BSD_COMPONENTS
        default n
 
-config CRYPTO_CRYPTODEV_SOFTWARE
-       bool "cryptodev software support"
+config CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO
+       bool "cryptodev software cipher support"
        depends on CRYPTO_CRYPTODEV && CRYPTO_SW_AES
        default n
 
+config CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT
+       bool "cryptodev software key management support"
+       depends on CRYPTO_CRYPTODEV && !MTD_CONFIG_NONE
+       default n
+
+if CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT
+
+config CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_DEVICE
+       string "device of trusted storage"
+       default "/dev/nvs"
+
+config CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_NSLOTS
+       int "Maximum number of key in cache"
+       default 4
+
+config CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_BUFSIZE
+       int "Maximum size of key buffer in cache (bytes)"
+       default 64
+
+config CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_NKEYS
+       int "Maximum number of key in flash"
+       default 32
+
+endif # CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT
+
 config CRYPTO_CRYPTODEV_HARDWARE
        bool "cryptodev hardware support"
        depends on CRYPTO_CRYPTODEV
diff --git a/crypto/Makefile b/crypto/Makefile
index 3c879e6c504..be3812ba8df 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -32,7 +32,7 @@ CRYPTO_CSRCS += crypto.c testmngr.c
 
 ifeq ($(CONFIG_CRYPTO_CRYPTODEV),y)
   CRYPTO_CSRCS += cryptodev.c
-ifeq ($(CONFIG_CRYPTO_CRYPTODEV_SOFTWARE),y)
+ifneq 
($(CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO)$(CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT),)
   CRYPTO_CSRCS += cryptosoft.c
   CRYPTO_CSRCS += xform.c
 endif
diff --git a/crypto/crypto.c b/crypto/crypto.c
index e463f3204cb..d1ad24784cf 100644
--- a/crypto/crypto.c
+++ b/crypto/crypto.c
@@ -344,6 +344,21 @@ int crypto_get_driverid(uint8_t flags)
   return -1;
 }
 
+int crypto_find_driverid(uint8_t flags)
+{
+  int i;
+
+  for (i = 0; i < crypto_drivers_num; i++)
+    {
+      if (crypto_drivers[i].cc_flags & flags)
+        {
+          return i;
+        }
+    }
+
+  return -EINVAL;
+}
+
 /* Register a crypto driver. It should be called once for each algorithm
  * supported by the driver.
  */
diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c
index ea63a2253af..b5aabfbe7e5 100644
--- a/crypto/cryptodev.c
+++ b/crypto/cryptodev.c
@@ -60,7 +60,7 @@ extern FAR struct cryptocap *crypto_drivers;
 extern int crypto_drivers_num;
 int usercrypto = 1;         /* userland may do crypto requests */
 int userasymcrypto = 1;     /* userland may do asymmetric crypto reqs */
-#ifdef CONFIG_CRYPTO_CRYPTODEV_SOFTWARE
+#ifdef CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO
 int cryptodevallowsoft = 1; /* 0 is only use hardware crypto
                              * 1 is use hardware & software crypto
                              */
@@ -1155,10 +1155,14 @@ void devcrypto_register(void)
 {
   register_driver("/dev/crypto", &g_cryptoops, 0666, NULL);
 
-#ifdef CONFIG_CRYPTO_CRYPTODEV_SOFTWARE
+#ifdef CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO
   swcr_init();
 #endif
 
+#ifdef CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT
+  swkey_init();
+#endif
+
 #ifdef CONFIG_CRYPTO_CRYPTODEV_HARDWARE
   hwcr_init();
 #endif
diff --git a/crypto/cryptosoft.c b/crypto/cryptosoft.c
index fd4f01cb8b7..ec2d4116f7e 100644
--- a/crypto/cryptosoft.c
+++ b/crypto/cryptosoft.c
@@ -29,7 +29,12 @@
 #include <assert.h>
 #include <errno.h>
 #include <endian.h>
+#include <fcntl.h>
+#include <stdio.h>
 #include <strings.h>
+#include <unistd.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/mtd/configdata.h>
 #include <nuttx/kmalloc.h>
 #include <nuttx/lib/math32.h>
 #include <crypto/bn.h>
@@ -44,18 +49,791 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+#ifdef CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT
+
+#define SWKEY_MAGIC_STRING  "SWKEYMGMT"
+#define SWKEY_FILL_NAME(name, keyid, type)       \
+  do                                             \
+    {                                            \
+      snprintf(name, sizeof(name), "%s.%lu.%s",  \
+               SWKEY_MAGIC_STRING, keyid, type); \
+    }                                            \
+  while (0)
+
+/****************************************************************************
+ * Private Type Definitions
+ ****************************************************************************/
+
+struct swkey_data_s
+{
+  uint32_t id;
+  uint32_t size;
+  uint32_t flags;
+  uint8_t buf[CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_BUFSIZE];
+  TAILQ_ENTRY(swkey_data_s) next;
+};
+
+struct swkey_context_s
+{
+  struct file file;
+  TAILQ_HEAD(swkey_list, swkey_data_s) head;
+};
+
+#endif /* CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT */
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
 
+#ifdef CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO
+
 FAR struct swcr_data **swcr_sessions = NULL;
 uint32_t swcr_sesnum = 0;
 int swcr_id = -1;
 
+#endif /* CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO */
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifdef CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT
+
+/* key data operations in flash */
+
+/****************************************************************************
+ * Name: swkey_write
+ *
+ * Description:
+ *   Storing key data into flash and mapping it to the keyid
+ *
+ ****************************************************************************/
+
+static int swkey_write(FAR struct file *filep, uint32_t keyid,
+                       FAR const void *data, uint32_t len, int flags)
+{
+  struct config_data_s config;
+  int ret;
+
+  if (keyid == 0 || data == NULL || len == 0)
+    {
+      return -EINVAL;
+    }
+
+  /* Write the data and flags to the Flash */
+
+  memset(&config, 0, sizeof(config));
+  SWKEY_FILL_NAME(config.name, keyid, "data");
+  config.len = len;
+  config.configdata = (uint8_t *)data;
+  ret = file_ioctl(filep, CFGDIOC_SETCONFIG, &config);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  SWKEY_FILL_NAME(config.name, keyid, "flags");
+  config.len = sizeof(uint32_t);
+  config.configdata = (uint8_t *)&flags;
+  return file_ioctl(filep, CFGDIOC_SETCONFIG, &config);
+}
+
+/****************************************************************************
+ * Name: swkey_remove
+ *
+ * Description:
+ *   Removing key data from flash
+ *
+ ****************************************************************************/
+
+static int swkey_remove(FAR struct file *filep, uint32_t keyid)
+{
+  struct config_data_s config;
+  int ret;
+
+  if (keyid == 0)
+    {
+      return -EINVAL;
+    }
+
+  /* Remove the flags and data */
+
+  memset(&config, 0, sizeof(config));
+  SWKEY_FILL_NAME(config.name, keyid, "flags");
+  ret = file_ioctl(filep, CFGDIOC_DELCONFIG, &config);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  memset(config.name, 0, sizeof(config.name));
+  SWKEY_FILL_NAME(config.name, keyid, "data");
+  return file_ioctl(filep, CFGDIOC_DELCONFIG, &config);
+}
+
+/****************************************************************************
+ * Name: swkey_get_flags
+ *
+ * Description:
+ *   Getting key flags from flash
+ *
+ ****************************************************************************/
+
+static int swkey_get_flags(FAR struct file *filep, uint32_t keyid,
+                           FAR uint32_t *flags)
+{
+  struct config_data_s config;
+
+  if (keyid == 0 || flags == NULL)
+    {
+      return -EINVAL;
+    }
+
+  memset(&config, 0, sizeof(config));
+  SWKEY_FILL_NAME(config.name, keyid, "flags");
+  config.len = sizeof(uint32_t);
+  config.configdata = (uint8_t *)flags;
+  return file_ioctl(filep, CFGDIOC_GETCONFIG, &config);
+}
+
+/****************************************************************************
+ * Name: swkey_read
+ *
+ * Description:
+ *   Getting key data from flash
+ *
+ ****************************************************************************/
+
+static int swkey_read(FAR struct file *filep, uint32_t keyid,
+                      FAR void *buf, uint32_t buflen)
+{
+  struct config_data_s config;
+  int ret;
+
+  if (keyid == 0 || buf == NULL)
+    {
+      return -EINVAL;
+    }
+
+  memset(&config, 0, sizeof(config));
+  SWKEY_FILL_NAME(config.name, keyid, "data");
+  config.len = buflen;
+  config.configdata = buf;
+  ret = file_ioctl(filep, CFGDIOC_GETCONFIG, &config);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  return config.len;
+}
+
+/* key data operations in cache */
+
+/****************************************************************************
+ * Name: swkey_get_context
+ *
+ * Description:
+ *   Access key cache list entries
+ *
+ ****************************************************************************/
+
+static FAR struct swkey_context_s *swkey_get_context(void)
+{
+  FAR struct swkey_context_s *ctx;
+  int swkey_id;
+
+  swkey_id = crypto_find_driverid(CRYPTOCAP_F_KEY_MGMT);
+  if (swkey_id < 0)
+    {
+      return NULL;
+    }
+
+  ctx = (FAR struct swkey_context_s *)crypto_driver_get_priv(swkey_id);
+  if (ctx == NULL)
+    {
+      return NULL;
+    }
+
+  if (ctx->file.f_inode == NULL)
+    {
+      if (file_open(&ctx->file,
+                    CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_DEVICE,
+                    O_RDWR | O_CLOEXEC) < 0)
+        {
+          return NULL;
+        }
+    }
+
+  return ctx;
+}
+
+/****************************************************************************
+ * Name: swkey_get_cache_data
+ *
+ * Description:
+ *   Acquire an available key slot in cache. If the key exists in the cache,
+ * utilize that slot immediately; otherwise, locate the last slot.
+ *
+ ****************************************************************************/
+
+static FAR struct swkey_data_s *
+swkey_get_cache_data(FAR struct swkey_context_s *ctx, uint32_t keyid)
+{
+  FAR struct swkey_data_s *data;
+
+  TAILQ_FOREACH(data, &ctx->head, next)
+    {
+      if (data->id == keyid)
+        {
+          break;
+        }
+    }
+
+  if (data == NULL)
+    {
+      data = TAILQ_LAST(&ctx->head, swkey_list);
+      if (data->id)
+        {
+          swkey_write(&ctx->file, data->id, data->buf,
+                      data->size, data->flags);
+        }
+    }
+
+  return data;
+}
+
+/****************************************************************************
+ * Name: swkey_promote_cache_data
+ *
+ * Description:
+ *   Update the key cache linked list.
+ *   Move the accessed key cache to the head position to ensure
+ *   the most frequently used keys remain cached.
+ *
+ ****************************************************************************/
+
+static void swkey_promote_cache_data(FAR struct swkey_context_s *ctx,
+                                     FAR struct swkey_data_s *data)
+{
+  TAILQ_REMOVE(&ctx->head, data, next);
+  TAILQ_INSERT_HEAD(&ctx->head, data, next);
+}
+
+/* key management operations */
+
+/****************************************************************************
+ * Name: swkey_clean_cache_data
+ *
+ * Description:
+ *   Clean the cache slot
+ *
+ ****************************************************************************/
+
+static void swkey_clean_cache_data(FAR struct swkey_data_s *data)
+{
+  explicit_bzero(data->buf, sizeof(data->buf));
+  data->id = 0;
+  data->size = 0;
+  data->flags = 0;
+}
+
+/****************************************************************************
+ * Name: swkey_is_valid
+ *
+ * Description:
+ *   Check whether the given keyid is available in the driver
+ *
+ ****************************************************************************/
+
+static int swkey_is_valid(FAR struct swkey_context_s *ctx, uint32_t keyid)
+{
+  uint32_t flags;
+  int ret;
+
+  if (keyid == 0)
+    {
+      return -EINVAL;
+    }
+
+  ret = swkey_get_flags(&ctx->file, keyid, &flags);
+  if (ret == -ENOENT)
+    {
+      /* No such file means keyid unused and available
+       * and occupied this keyid with MAGIC-STRING
+       */
+
+      return swkey_write(&ctx->file, keyid, SWKEY_MAGIC_STRING,
+                                     sizeof(SWKEY_MAGIC_STRING), 0);
+    }
+  else if (ret == 0)
+    {
+      /* success means keyid used and unavailable */
+
+      return -EEXIST;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: swkey_alloc
+ *
+ * Description:
+ *   Acquire an available key ID from the driver
+ *
+ ****************************************************************************/
+
+static int swkey_alloc(FAR struct swkey_context_s *ctx,
+                       FAR uint32_t *keyid)
+{
+  int i;
+
+  for (i = 1; i <= CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_NKEYS; i++)
+    {
+      if (swkey_is_valid(ctx, i) == 0)
+        {
+          *keyid = i;
+          return OK;
+        }
+    }
+
+  return -ENOMEM;
+}
+
+/****************************************************************************
+ * Name: swkey_import
+ *
+ * Description:
+ *   Import key data into cache key slot and bind to the keyid
+ *
+ ****************************************************************************/
+
+static int swkey_import(FAR struct swkey_context_s *ctx,
+                        uint32_t keyid, FAR void *buf,
+                        uint32_t buflen, uint32_t flags)
+{
+  FAR struct swkey_data_s *data;
+
+  if (keyid == 0)
+    {
+      return -EINVAL;
+    }
+
+  if (buflen > CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_BUFSIZE)
+    {
+      return swkey_write(&ctx->file, keyid, buf, buflen, flags);
+    }
+
+  data = swkey_get_cache_data(ctx, keyid);
+  data->id = keyid;
+  data->size = buflen;
+  memcpy(data->buf, buf, data->size);
+  if (flags & CRYPTO_F_NOT_EXPORTABLE)
+    {
+      data->flags |= CRYPTO_F_NOT_EXPORTABLE;
+    }
+  else
+    {
+      data->flags &= ~CRYPTO_F_NOT_EXPORTABLE;
+    }
+
+  swkey_promote_cache_data(ctx, data);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: swkey_delete
+ *
+ * Description:
+ *   Remove a specific key by keyid
+ *
+ ****************************************************************************/
+
+static int swkey_delete(FAR struct swkey_context_s *ctx, uint32_t keyid)
+{
+  FAR struct swkey_data_s *data;
+
+  if (keyid == 0)
+    {
+      return -EINVAL;
+    }
+
+  data = swkey_get_cache_data(ctx, keyid);
+  if (data->id == keyid)
+    {
+      swkey_clean_cache_data(data);
+    }
+
+  return swkey_remove(&ctx->file, keyid);
+}
+
+/****************************************************************************
+ * Name: swkey_export
+ *
+ * Description:
+ *   Export key data by keyid
+ *
+ ****************************************************************************/
+
+static int swkey_export(FAR struct swkey_context_s *ctx,
+                        uint32_t keyid, FAR void *buf,
+                        uint32_t buflen)
+{
+  FAR struct swkey_data_s *data;
+  uint32_t flags;
+  int ret;
+
+  if (keyid == 0)
+    {
+      return -EINVAL;
+    }
+
+  data = swkey_get_cache_data(ctx, keyid);
+  if (data->id == keyid)
+    {
+      /* Key in cache, export data and update cache */
+
+      if (data->flags & CRYPTO_F_NOT_EXPORTABLE)
+        {
+          return -EACCES;
+        }
+
+      if (buflen < data->size)
+        {
+          return -ENOBUFS;
+        }
+
+      memcpy(buf, data->buf, buflen);
+      swkey_promote_cache_data(ctx, data);
+      return OK;
+    }
+
+  /* Key not in cache, get key from flash */
+
+  ret = swkey_get_flags(&ctx->file, keyid, &flags);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  if (flags & CRYPTO_F_NOT_EXPORTABLE)
+    {
+      return -EACCES;
+    }
+
+  ret = swkey_read(&ctx->file, keyid, buf, buflen);
+  if (ret < 0)
+    {
+      return ret;
+    }
+  else if (ret > buflen)
+    {
+      return -ENOBUFS;
+    }
+  else if (memcmp(buf, SWKEY_MAGIC_STRING, ret) == 0)
+    {
+      return -ENOENT;
+    }
+
+  if (ret < CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_BUFSIZE)
+    {
+      data->id = keyid;
+      data->size = ret;
+      data->flags = flags;
+      memcpy(data->buf, buf, ret);
+      swkey_promote_cache_data(ctx, data);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: swkey_save
+ *
+ * Description:
+ *   Write key from cache to Flash
+ *
+ ****************************************************************************/
+
+static int swkey_save(FAR struct swkey_context_s *ctx, uint32_t keyid)
+{
+  FAR struct swkey_data_s *data;
+  int ret = -EINVAL;
+
+  if (keyid == 0)
+    {
+      return ret;
+    }
+
+  data = swkey_get_cache_data(ctx, keyid);
+  if (data->id == keyid)
+    {
+      ret = swkey_write(&ctx->file, keyid, data->buf,
+                        data->size, data->flags);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      swkey_promote_cache_data(ctx, data);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: crypto_load_key
+ *
+ * Description:
+ *   Load key data from Flash to cache
+ *
+ ****************************************************************************/
+
+static int swkey_load(FAR struct swkey_context_s *ctx, uint32_t keyid)
+{
+  FAR struct swkey_data_s *data;
+  char buf[CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_BUFSIZE];
+  int readlen;
+
+  if (keyid == 0)
+    {
+      return -EINVAL;
+    }
+
+  readlen = swkey_read(&ctx->file, keyid, buf, sizeof(buf));
+  if (readlen < 0)
+    {
+      return readlen;
+    }
+  else if (readlen > CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_BUFSIZE)
+    {
+      return -EFBIG;
+    }
+
+  data = swkey_get_cache_data(ctx, keyid);
+  data->id = keyid;
+  data->size = readlen;
+  swkey_get_flags(&ctx->file, keyid, &data->flags);
+  memcpy(data->buf, buf, data->size);
+  swkey_promote_cache_data(ctx, data);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: swkey_unload
+ *
+ * Description:
+ *   Unload key data from cache
+ *
+ ****************************************************************************/
+
+static int swkey_unload(FAR struct swkey_context_s *ctx, uint32_t keyid)
+{
+  FAR struct swkey_data_s *data;
+  int ret = -EINVAL;
+
+  if (keyid == 0)
+    {
+      return ret;
+    }
+
+  data = swkey_get_cache_data(ctx, keyid);
+  if (data->id == keyid)
+    {
+      ret = swkey_write(&ctx->file, data->id, data->buf,
+                        data->size, data->flags);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
+      swkey_clean_cache_data(data);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: swkey_kprocess
+ *
+ * Description:
+ *   Key management process function in crypto driver
+ *
+ ****************************************************************************/
+
+static int swkey_kprocess(FAR struct cryptkop *krp)
+{
+  FAR struct swkey_context_s *ctx;
+  uint32_t keyid;
+
+  /* Sanity check */
+
+  if (krp == NULL)
+    {
+      return -EINVAL;
+    }
+
+  ctx = swkey_get_context();
+  if (ctx == NULL)
+    {
+      return -EINVAL;
+    }
+
+  if (krp->krp_param[0].crp_nbits != sizeof(uint32_t) * 8)
+    {
+      return -EINVAL;
+    }
+
+  keyid = *(uint32_t *)krp->krp_param[0].crp_p;
+
+  /* Go through crypto descriptors, processing as we go */
+
+  switch (krp->krp_op)
+    {
+      case CRK_ALLOCATE_KEY:
+        krp->krp_status = swkey_alloc(ctx, &keyid);
+        if (krp->krp_status == 0)
+          {
+            memcpy(krp->krp_param[0].crp_p, &keyid, sizeof(uint32_t));
+          }
+
+        break;
+      case CRK_VALIDATE_KEYID:
+        krp->krp_status = swkey_is_valid(ctx, keyid);
+        break;
+      case CRK_IMPORT_KEY:
+        krp->krp_status = swkey_import(ctx, keyid,
+                                       krp->krp_param[1].crp_p,
+                                       krp->krp_param[1].crp_nbits / 8,
+                                       krp->krp_flags);
+        break;
+      case CRK_DELETE_KEY:
+        krp->krp_status = swkey_delete(ctx, keyid);
+        break;
+      case CRK_EXPORT_KEY:
+        krp->krp_status = swkey_export(ctx, keyid,
+                                       krp->krp_param[1].crp_p,
+                                       krp->krp_param[1].crp_nbits / 8);
+        break;
+      case CRK_SAVE_KEY:
+        krp->krp_status = swkey_save(ctx, keyid);
+        break;
+      case CRK_LOAD_KEY:
+        krp->krp_status = swkey_load(ctx, keyid);
+        break;
+      case CRK_UNLOAD_KEY:
+        krp->krp_status = swkey_unload(ctx, keyid);
+        break;
+      default:
+
+        /* Unknown/unsupported operation */
+
+        krp->krp_status = -EINVAL;
+        break;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: swkey_context_init
+ *
+ * Description:
+ *   Init software key ctx
+ *
+ ****************************************************************************/
+
+static int swkey_context_init(FAR struct swkey_context_s *ctx)
+{
+  FAR struct swkey_data_s *data;
+  int i;
+
+  TAILQ_INIT(&ctx->head);
+  for (i = 0; i < CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT_NSLOTS; i++)
+    {
+      data = (FAR struct swkey_data_s *)kmm_zalloc(sizeof(*data));
+      if (data == NULL)
+        {
+          return -ENOMEM;
+        }
+
+      TAILQ_INSERT_HEAD(&ctx->head, data, next);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: swkey_context_cleanup
+ *
+ * Description:
+ *   Cleanup software key ctx
+ *
+ ****************************************************************************/
+
+static void swkey_context_cleanup(FAR struct swkey_context_s *ctx)
+{
+  FAR struct swkey_data_s *data;
+
+  TAILQ_FOREACH(data, &ctx->head, next)
+    {
+      memset(data, 0, sizeof(struct swkey_data_s));
+      kmm_free(data);
+    }
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
+/* key management operations */
+
+/****************************************************************************
+ * Name: swkey_init
+ *
+ * Description:
+ *   Register software key management driver
+ *
+ ****************************************************************************/
+
+void swkey_init(void)
+{
+  int swkey_id = crypto_get_driverid(CRYPTOCAP_F_KEY_MGMT);
+  FAR struct swkey_context_s *ctx;
+  int kalgs[CRK_ALGORITHM_MAX + 1];
+
+  ctx = (FAR struct swkey_context_s *)kmm_zalloc(sizeof(*ctx));
+  if (ctx == NULL)
+    {
+      return;
+    }
+
+  if (swkey_context_init(ctx))
+    {
+      swkey_context_cleanup(ctx);
+      kmm_free(ctx);
+      return;
+    }
+
+  crypto_driver_set_priv(swkey_id, ctx);
+
+  kalgs[CRK_ALLOCATE_KEY] = CRYPTO_ALG_FLAG_SUPPORTED;
+  kalgs[CRK_VALIDATE_KEYID] = CRYPTO_ALG_FLAG_SUPPORTED;
+  kalgs[CRK_IMPORT_KEY] = CRYPTO_ALG_FLAG_SUPPORTED;
+  kalgs[CRK_DELETE_KEY] = CRYPTO_ALG_FLAG_SUPPORTED;
+  kalgs[CRK_EXPORT_KEY] = CRYPTO_ALG_FLAG_SUPPORTED;
+  kalgs[CRK_SAVE_KEY] = CRYPTO_ALG_FLAG_SUPPORTED;
+  kalgs[CRK_LOAD_KEY] = CRYPTO_ALG_FLAG_SUPPORTED;
+  kalgs[CRK_UNLOAD_KEY] = CRYPTO_ALG_FLAG_SUPPORTED;
+
+  crypto_kregister(swkey_id, kalgs, swkey_kprocess);
+}
+
+#endif /* CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_KEYMGMT */
+
+#ifdef CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO
+
 /* Apply a symmetric encryption/decryption algorithm. */
 
 int swcr_encdec(FAR struct cryptop *crp, FAR struct cryptodesc *crd,
@@ -1434,3 +2212,5 @@ void swcr_init(void)
   kalgs[CRK_ECDSA_SECP256R1_GENKEY] = CRYPTO_ALG_FLAG_SUPPORTED;
   crypto_kregister(swcr_id, kalgs, swcr_kprocess);
 }
+
+#endif /* CONFIG_CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO */
diff --git a/include/crypto/cryptodev.h b/include/crypto/cryptodev.h
index 969b9202e51..049b7f41f3e 100644
--- a/include/crypto/cryptodev.h
+++ b/include/crypto/cryptodev.h
@@ -361,6 +361,7 @@ struct cryptocap
 #define CRYPTOCAP_F_ENCRYPT_MAC 0x04 /* Can do encrypt-then-MAC (IPsec) */
 #define CRYPTOCAP_F_MAC_ENCRYPT 0x08 /* Can do MAC-then-encrypt (TLS) */
 #define CRYPTOCAP_F_REMOTE      0x10 /* Remote core driver  */
+#define CRYPTOCAP_F_KEY_MGMT    0x20 /* Key management */
 
   CODE int (*cc_newsession)(FAR uint32_t *, FAR struct cryptoini *);
   CODE int (*cc_process)(FAR struct cryptop *);
@@ -449,6 +450,7 @@ int crypto_kregister(uint32_t, FAR int *,
                      CODE int (*)(FAR struct cryptkop *));
 int crypto_unregister(uint32_t, int);
 int crypto_get_driverid(uint8_t);
+int crypto_find_driverid(uint8_t);
 int crypto_invoke(FAR struct cryptop *);
 int crypto_kinvoke(FAR struct cryptkop *);
 int crypto_getfeat(FAR int *);
diff --git a/include/crypto/cryptosoft.h b/include/crypto/cryptosoft.h
index d6603c40ca5..1523a8bf497 100644
--- a/include/crypto/cryptosoft.h
+++ b/include/crypto/cryptosoft.h
@@ -37,6 +37,10 @@
 #include <crypto/cryptodev.h>
 #include <crypto/xform.h>
 
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
 /* Software session entry */
 
 struct swcr_data
@@ -93,4 +97,8 @@ int swcr_newsession(FAR uint32_t *, FAR struct cryptoini *);
 int swcr_freesession(uint64_t);
 void swcr_init(void);
 
+/* Software key management */
+
+void swkey_init(void);
+
 #endif /* __INCLUDE_CRYPTO_CRYPTOSOFT_H */

Reply via email to