drivers: crypto: SHA: npcx: add support for SHA hardware accelerator
NPCX9 series chips include a SHA hardware accelerator, which supports SHA256/SHA384/SHA512 hashing and a library (APIs) in the on-chip ROM. This commit adds the driver support by wrapping the on-chip ROM APIs. Signed-off-by: Jun Lin <CHLin56@nuvoton.com>
This commit is contained in:
parent
bd766d0489
commit
885695f425
4 changed files with 234 additions and 0 deletions
|
|
@ -7,4 +7,5 @@ zephyr_library_sources_ifdef(CONFIG_CRYPTO_MBEDTLS_SHIM crypto_mtls_shim.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_CRYPTO_STM32 crypto_stm32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CRYPTO_NRF_ECB crypto_nrf_ecb.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CRYPTO_INTEL_SHA crypto_intel_sha.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_CRYPTO_NPCX_SHA crypto_npcx_sha.c)
|
||||
zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)
|
||||
|
|
|
|||
|
|
@ -76,5 +76,6 @@ source "drivers/crypto/Kconfig.ataes132a"
|
|||
source "drivers/crypto/Kconfig.stm32"
|
||||
source "drivers/crypto/Kconfig.nrf_ecb"
|
||||
source "drivers/crypto/Kconfig.intel"
|
||||
source "drivers/crypto/Kconfig.npcx"
|
||||
|
||||
endif # CRYPTO
|
||||
|
|
|
|||
11
drivers/crypto/Kconfig.npcx
Normal file
11
drivers/crypto/Kconfig.npcx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# NPCX SHA driver configuration options
|
||||
|
||||
# Copyright (c) 2022 Nuvoton Technology Corporation.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config CRYPTO_NPCX_SHA
|
||||
bool "NPCX SHA driver"
|
||||
default y
|
||||
depends on DT_HAS_NUVOTON_NPCX_SHA_ENABLED
|
||||
help
|
||||
Enable NPCX SHA driver.
|
||||
221
drivers/crypto/crypto_npcx_sha.c
Normal file
221
drivers/crypto/crypto_npcx_sha.c
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Nuvoton Technology Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT nuvoton_npcx_sha
|
||||
|
||||
#include <errno.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/crypto/crypto.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(sha_npcx, CONFIG_CRYPTO_LOG_LEVEL);
|
||||
|
||||
#define NPCX_HASH_CAPS_SUPPORT (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS)
|
||||
#define NPCX_SHA256_HANDLE_SIZE 212
|
||||
#define NPCX_SHA_MAX_SESSION 1
|
||||
|
||||
/* The status code returns from Nuvoton Cryptographic Library ROM APIs */
|
||||
enum ncl_status {
|
||||
NCL_STATUS_OK = 0xA5A5,
|
||||
NCL_STATUS_FAIL = 0x5A5A,
|
||||
NCL_STATUS_INVALID_PARAM = 0x02,
|
||||
NCL_STATUS_PARAM_NOT_SUPPORTED,
|
||||
NCL_STATUS_SYSTEM_BUSY,
|
||||
NCL_STATUS_AUTHENTICATION_FAIL,
|
||||
NCL_STATUS_NO_RESPONSE,
|
||||
NCL_STATUS_HARDWARE_ERROR,
|
||||
};
|
||||
enum ncl_sha_type {
|
||||
NCL_SHA_TYPE_2_256 = 0,
|
||||
NCL_SHA_TYPE_2_384 = 1,
|
||||
NCL_SHA_TYPE_2_512 = 2,
|
||||
NCL_SHA_TYPE_NUM
|
||||
};
|
||||
|
||||
/* The following table holds the function pointer for each SHA API in NPCX ROM. */
|
||||
struct npcx_ncl_sha {
|
||||
/* Get the SHA context size required by SHA APIs. */
|
||||
uint32_t (*get_context_size)(void);
|
||||
/* Initial SHA context. */
|
||||
enum ncl_status (*init_context)(void *ctx);
|
||||
/* Finalize SHA context. */
|
||||
enum ncl_status (*finalize_context)(void *ctx);
|
||||
/* Initiate the SHA hardware module and setups needed parameters. */
|
||||
enum ncl_status (*init)(void *ctx);
|
||||
/*
|
||||
* Prepare the context buffer for a SHA calculation - by loading the
|
||||
* initial SHA-256/384/512 parameters.
|
||||
*/
|
||||
enum ncl_status (*start)(void *ctx, enum ncl_sha_type type);
|
||||
/*
|
||||
* Updates the SHA calculation with the additional data. When the
|
||||
* function returns, the hardware and memory buffer shall be ready to
|
||||
* accept new data * buffers for SHA calculation and changes to the data
|
||||
* in data buffer should no longer effect the SHA calculation.
|
||||
*/
|
||||
enum ncl_status (*update)(void *ctx, const uint8_t *data, uint32_t Len);
|
||||
/* Return the SHA result (digest.) */
|
||||
enum ncl_status (*finish)(void *ctx, uint8_t *hashDigest);
|
||||
/* Perform a complete SHA calculation */
|
||||
enum ncl_status (*calc)(void *ctx, enum ncl_sha_type type, const uint8_t *data,
|
||||
uint32_t Len, uint8_t *hashDigest);
|
||||
/* Power on/off the SHA module. */
|
||||
enum ncl_status (*power)(void *ctx, uint8_t enable);
|
||||
/* Reset the SHA hardware and terminate any in-progress operations. */
|
||||
enum ncl_status (*reset)(void *ctx);
|
||||
};
|
||||
|
||||
/* The start address of the SHA API table. */
|
||||
#define NPCX_NCL_SHA ((const struct npcx_ncl_sha *)DT_INST_REG_ADDR(0))
|
||||
|
||||
struct npcx_sha_context {
|
||||
uint8_t handle[NPCX_SHA256_HANDLE_SIZE];
|
||||
} __aligned(4);
|
||||
|
||||
struct npcx_sha_session {
|
||||
struct npcx_sha_context npcx_sha_ctx;
|
||||
enum hash_algo algo;
|
||||
bool in_use;
|
||||
};
|
||||
|
||||
struct npcx_sha_session npcx_sessions[NPCX_SHA_MAX_SESSION];
|
||||
|
||||
static int npcx_get_unused_session_index(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NPCX_SHA_MAX_SESSION; i++) {
|
||||
if (!npcx_sessions[i].in_use) {
|
||||
npcx_sessions[i].in_use = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
static int npcx_sha_compute(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish)
|
||||
{
|
||||
enum ncl_status ret;
|
||||
struct npcx_sha_session *npcx_session = ctx->drv_sessn_state;
|
||||
struct npcx_sha_context *npcx_ctx = &npcx_session->npcx_sha_ctx;
|
||||
enum ncl_sha_type sha_type;
|
||||
|
||||
switch (npcx_session->algo) {
|
||||
case CRYPTO_HASH_ALGO_SHA256:
|
||||
sha_type = NCL_SHA_TYPE_2_256;
|
||||
break;
|
||||
case CRYPTO_HASH_ALGO_SHA384:
|
||||
sha_type = NCL_SHA_TYPE_2_384;
|
||||
break;
|
||||
case CRYPTO_HASH_ALGO_SHA512:
|
||||
sha_type = NCL_SHA_TYPE_2_512;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Unexpected algo: %d", npcx_session->algo);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!ctx->started) {
|
||||
ret = NPCX_NCL_SHA->start(npcx_ctx->handle, sha_type);
|
||||
if (ret != NCL_STATUS_OK) {
|
||||
LOG_ERR("Could not compute the hash, err:%d", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
ctx->started = true;
|
||||
}
|
||||
|
||||
if (pkt->in_len != 0) {
|
||||
ret = NPCX_NCL_SHA->update(npcx_ctx->handle, pkt->in_buf, pkt->in_len);
|
||||
if (ret != NCL_STATUS_OK) {
|
||||
LOG_ERR("Could not update the hash, err:%d", ret);
|
||||
ctx->started = false;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (finish) {
|
||||
ctx->started = false;
|
||||
ret = NPCX_NCL_SHA->finish(npcx_ctx->handle, pkt->out_buf);
|
||||
if (ret != NCL_STATUS_OK) {
|
||||
LOG_ERR("Could not compute the hash, err:%d", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int npcx_hash_session_setup(const struct device *dev, struct hash_ctx *ctx,
|
||||
enum hash_algo algo)
|
||||
{
|
||||
int ctx_idx;
|
||||
struct npcx_sha_context *npcx_ctx;
|
||||
|
||||
if (ctx->flags & ~(NPCX_HASH_CAPS_SUPPORT)) {
|
||||
LOG_ERR("Unsupported flag");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((algo != CRYPTO_HASH_ALGO_SHA256) && (algo != CRYPTO_HASH_ALGO_SHA384) &&
|
||||
(algo != CRYPTO_HASH_ALGO_SHA512)) {
|
||||
LOG_ERR("Unsupported algo: %d", algo);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx_idx = npcx_get_unused_session_index();
|
||||
if (ctx_idx < 0) {
|
||||
LOG_ERR("No free session for now");
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
npcx_sessions[ctx_idx].algo = algo;
|
||||
|
||||
ctx->drv_sessn_state = &npcx_sessions[ctx_idx];
|
||||
ctx->started = false;
|
||||
ctx->hash_hndlr = npcx_sha_compute;
|
||||
|
||||
npcx_ctx = &npcx_sessions[ctx_idx].npcx_sha_ctx;
|
||||
NPCX_NCL_SHA->init_context(npcx_ctx->handle);
|
||||
NPCX_NCL_SHA->power(npcx_ctx->handle, 1);
|
||||
NPCX_NCL_SHA->init(npcx_ctx->handle);
|
||||
NPCX_NCL_SHA->reset(npcx_ctx->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int npcx_hash_session_free(const struct device *dev, struct hash_ctx *ctx)
|
||||
{
|
||||
struct npcx_sha_session *npcx_session = ctx->drv_sessn_state;
|
||||
struct npcx_sha_context *npcx_ctx = &npcx_session->npcx_sha_ctx;
|
||||
|
||||
NPCX_NCL_SHA->reset(npcx_ctx->handle);
|
||||
NPCX_NCL_SHA->power(npcx_ctx->handle, 0);
|
||||
NPCX_NCL_SHA->finalize_context(npcx_ctx->handle);
|
||||
npcx_session->in_use = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int npcx_query_caps(const struct device *dev)
|
||||
{
|
||||
return NPCX_HASH_CAPS_SUPPORT;
|
||||
}
|
||||
|
||||
static int sha_npcx_init(const struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct crypto_driver_api npcx_crypto_api = {
|
||||
.hash_begin_session = npcx_hash_session_setup,
|
||||
.hash_free_session = npcx_hash_session_free,
|
||||
.query_hw_caps = npcx_query_caps,
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, &sha_npcx_init, NULL, NULL, NULL, POST_KERNEL, CONFIG_CRYPTO_INIT_PRIORITY,
|
||||
&npcx_crypto_api);
|
||||
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
|
||||
"only one 'nuvoton,npcx-sha' compatible node can be supported");
|
||||
Loading…
Reference in a new issue