mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
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 <makejian@xiaomi.com>
This commit is contained in:
parent
9205c60f01
commit
c8145313ae
9 changed files with 842 additions and 7 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue