From 2386c97c788625349f20d3a25cfe9f05cb488900 Mon Sep 17 00:00:00 2001 From: Ha Duong Quang Date: Sat, 8 Nov 2025 20:21:18 +0700 Subject: [PATCH 1/2] driver: crypto: add NXP S32 CRYPTO HSE driver Add device tree node for MU instances that will be used by HSE and RTU for s32z270. Add support hash crypto for NXP S32 with Algo 2: SHA224, SHA256, SHA384 and SHA512. Add support cipher crypto with ECB, CBC and CTR mode by using ram key catalog. Add support 128/256 bits ram key length. Signed-off-by: Ha Duong Quang --- drivers/crypto/CMakeLists.txt | 1 + drivers/crypto/Kconfig | 1 + drivers/crypto/Kconfig.nxp_s32_hse | 33 + drivers/crypto/crypto_nxp_s32_hse.c | 660 ++++++++++++++++++ dts/arm/nxp/nxp_s32z27x_r52.dtsi | 54 ++ .../crypto/nxp,s32-crypto-hse-mu.yaml | 19 + west.yml | 2 +- 7 files changed, 769 insertions(+), 1 deletion(-) create mode 100644 drivers/crypto/Kconfig.nxp_s32_hse create mode 100644 drivers/crypto/crypto_nxp_s32_hse.c create mode 100644 dts/bindings/crypto/nxp,s32-crypto-hse-mu.yaml diff --git a/drivers/crypto/CMakeLists.txt b/drivers/crypto/CMakeLists.txt index f6dfd465ef533..c7e4d9023d717 100644 --- a/drivers/crypto/CMakeLists.txt +++ b/drivers/crypto/CMakeLists.txt @@ -19,4 +19,5 @@ zephyr_library_sources_ifdef(CONFIG_CRYPTO_CC23X0 crypto_cc23x0.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_RTS5912_SHA crypto_rts5912_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_ESP32_SHA crypto_esp32_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_ESP32_AES crypto_esp32_aes.c) +zephyr_library_sources_ifdef(CONFIG_CRYPTO_NXP_S32_HSE crypto_nxp_s32_hse.c) zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 8510762e5d880..10382a0c87019 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -64,5 +64,6 @@ source "drivers/crypto/Kconfig.smartbond" source "drivers/crypto/Kconfig.cc23x0" source "drivers/crypto/Kconfig.rts5912" source "drivers/crypto/Kconfig.esp32" +source "drivers/crypto/Kconfig.nxp_s32_hse" endif # CRYPTO diff --git a/drivers/crypto/Kconfig.nxp_s32_hse b/drivers/crypto/Kconfig.nxp_s32_hse new file mode 100644 index 0000000000000..8b7cda8fc4ece --- /dev/null +++ b/drivers/crypto/Kconfig.nxp_s32_hse @@ -0,0 +1,33 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +menuconfig CRYPTO_NXP_S32_HSE + bool "NXP S32 HSE crypto driver" + default y + depends on DT_HAS_NXP_S32_CRYPTO_HSE_MU_ENABLED + help + Enable NXP HSE crypto driver. + +if CRYPTO_NXP_S32_HSE + +config CRYPTO_NXP_S32_HSE_OUTPUT_BUFFER_SIZE + int "HSE crypto service output buffer size in bytes" + default 128 + help + The output buffer size for storing the output data of HSE crypto service, measured in bytes. + +config CRYPTO_NXP_S32_HSE_AES_KEY_SIZE + int "Key size in bits" + default 128 + help + The size of the key used in cryptographic algorithms, measured in bits. + Only support for 128 bits or 256 bits. + +config CRYPTO_NXP_S32_HSE_AES_KEY_GROUP_ID + int "The AES Key Group ID within RAM Key Catalog." + range 0 255 + default 0 + help + The AES Key Group ID within RAM Key Catalog. + +endif #CRYPTO_NXP_S32_HSE diff --git a/drivers/crypto/crypto_nxp_s32_hse.c b/drivers/crypto/crypto_nxp_s32_hse.c new file mode 100644 index 0000000000000..978e005b01e4c --- /dev/null +++ b/drivers/crypto/crypto_nxp_s32_hse.c @@ -0,0 +1,660 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_s32_crypto_hse_mu + +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_CRYPTO_LOG_LEVEL +#include +LOG_MODULE_REGISTER(crypto_nxp_s32_hse); + +#if (CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE != 128) && \ + (CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE != 256) +#error "CRYPTO_NXP_S32_HSE_AES_KEY_SIZE must be 128 or 256" +#endif + +#define CRYPTO_NXP_S32_HSE_SERVICE_TIMEOUT_TICKS 10000000 +#define CRYPTO_NXP_S32_HSE_INIT_TIMEOUT_MS 10000 + +#define CRYPTO_NXP_S32_HSE_CIPHER_CAPS \ + (CAP_RAW_KEY | CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS | CAP_NO_IV_PREFIX) + +#define CRYPTO_NXP_S32_HSE_HASH_CAPS (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS) + +#define CRYPTO_NXP_S32_HSE_MU_INSTANCE_CHECK(indx, n) \ + ((DT_INST_REG_ADDR(n) == IP_MU##indx##__MUB_BASE) ? indx : 0) + +#define CRYPTO_NXP_S32_HSE_MU_GET_INSTANCE(n) \ + LISTIFY(__DEBRACKET HSE_IP_NUM_OF_MU_INSTANCES, \ + CRYPTO_NXP_S32_HSE_MU_INSTANCE_CHECK, (|), n) + +struct crypto_nxp_s32_hse_session { + hseSrvDescriptor_t crypto_serv_desc; + Hse_Ip_ReqType req_type; + bool in_use; + uint8_t channel; + uint8_t *out_buff; + struct k_mutex crypto_lock; + hseKeyHandle_t key_handle; + hseKeyInfo_t key_info; +}; + +struct crypto_nxp_s32_hse_data { + struct crypto_nxp_s32_hse_session sessions[HSE_IP_NUM_OF_CHANNELS_PER_MU]; + Hse_Ip_MuStateType mu_state; +}; + +struct crypto_nxp_s32_hse_config { + uint8_t mu_instance; +}; + +static struct k_mutex crypto_nxp_s32_lock; + +static struct crypto_nxp_s32_hse_session *crypto_nxp_s32_hse_get_session(const struct device *dev) +{ + const struct crypto_nxp_s32_hse_config *config = dev->config; + struct crypto_nxp_s32_hse_data *data = dev->data; + struct crypto_nxp_s32_hse_session *session; + uint8_t mu_channel; + + k_mutex_lock(&crypto_nxp_s32_lock, K_FOREVER); + mu_channel = Hse_Ip_GetFreeChannel(config->mu_instance); + + if (mu_channel != HSE_IP_INVALID_MU_CHANNEL_U8) { + session = &data->sessions[mu_channel - 1]; + session->in_use = true; + k_mutex_unlock(&crypto_nxp_s32_lock); + return session; + } + + k_mutex_unlock(&crypto_nxp_s32_lock); + return NULL; +} + +static inline void free_session(const struct device *dev, + struct crypto_nxp_s32_hse_session *session) +{ + const struct crypto_nxp_s32_hse_config *config = dev->config; + + k_mutex_lock(&session->crypto_lock, K_FOREVER); + memset(&session->req_type, 0, sizeof(Hse_Ip_ReqType)); + memset(&session->crypto_serv_desc, 0, sizeof(hseSrvDescriptor_t)); + memset(&session->key_info, 0, sizeof(hseKeyInfo_t)); + Hse_Ip_ReleaseChannel(config->mu_instance, session->channel); + session->in_use = false; + k_mutex_unlock(&session->crypto_lock); +} + +static int crypto_nxp_s32_hse_aes_ecb_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt) +{ + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + hseSymCipherSrv_t *cipher_serv = &(session->crypto_serv_desc.hseSrv.symCipherReq); + + __ASSERT_NO_MSG(pkt->in_len <= pkt->out_buf_max && + pkt->out_buf_max <= CONFIG_CRYPTO_NXP_S32_HSE_OUTPUT_BUFFER_SIZE); + + k_mutex_lock(&session->crypto_lock, K_FOREVER); + + /* Update HSE descriptor */ + cipher_serv->cipherBlockMode = HSE_CIPHER_BLOCK_MODE_ECB; + cipher_serv->cipherDir = HSE_CIPHER_DIR_ENCRYPT; + cipher_serv->pInput = HSE_PTR_TO_HOST_ADDR(pkt->in_buf); + cipher_serv->inputLength = pkt->in_len; + cipher_serv->pOutput = HSE_PTR_TO_HOST_ADDR(session->out_buff); + + if (Hse_Ip_ServiceRequest( + config->mu_instance, session->channel, (Hse_Ip_ReqType *)&session->req_type, + (hseSrvDescriptor_t *)&session->crypto_serv_desc) != HSE_SRV_RSP_OK) { + k_mutex_unlock(&session->crypto_lock); + return -EIO; + } + + pkt->out_len = pkt->in_len; + + memcpy(pkt->out_buf, session->out_buff, pkt->out_buf_max); + + k_mutex_unlock(&session->crypto_lock); + + return 0; +} + +static int crypto_nxp_s32_hse_aes_ecb_decrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt) +{ + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + hseSymCipherSrv_t *cipher_serv = &(session->crypto_serv_desc.hseSrv.symCipherReq); + + __ASSERT_NO_MSG(pkt->in_len <= pkt->out_buf_max && + pkt->out_buf_max <= CONFIG_CRYPTO_NXP_S32_HSE_OUTPUT_BUFFER_SIZE); + + k_mutex_lock(&session->crypto_lock, K_FOREVER); + + /* Update HSE descriptor */ + cipher_serv->cipherBlockMode = HSE_CIPHER_BLOCK_MODE_ECB; + cipher_serv->cipherDir = HSE_CIPHER_DIR_DECRYPT; + cipher_serv->pInput = HSE_PTR_TO_HOST_ADDR(pkt->in_buf); + cipher_serv->inputLength = pkt->in_len; + cipher_serv->pOutput = HSE_PTR_TO_HOST_ADDR(session->out_buff); + + if (Hse_Ip_ServiceRequest( + config->mu_instance, session->channel, (Hse_Ip_ReqType *)&session->req_type, + (hseSrvDescriptor_t *)&session->crypto_serv_desc) != HSE_SRV_RSP_OK) { + k_mutex_unlock(&session->crypto_lock); + return -EIO; + } + + pkt->out_len = pkt->in_len; + + memcpy(pkt->out_buf, session->out_buff, pkt->out_buf_max); + + k_mutex_unlock(&session->crypto_lock); + + return 0; +} + +static int crypto_nxp_s32_hse_aes_cbc_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt, + uint8_t *iv) +{ + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + hseSymCipherSrv_t *cipher_serv = &(session->crypto_serv_desc.hseSrv.symCipherReq); + size_t iv_bytes; + + __ASSERT_NO_MSG(pkt->in_len <= pkt->out_buf_max && + pkt->out_buf_max <= CONFIG_CRYPTO_NXP_S32_HSE_OUTPUT_BUFFER_SIZE); + + if (ctx->flags & CAP_NO_IV_PREFIX) { + iv_bytes = 0; + } else { + iv_bytes = HSE_BITS_TO_BYTES(CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE); + memcpy(pkt->out_buf, iv, HSE_BITS_TO_BYTES(CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE)); + } + + k_mutex_lock(&session->crypto_lock, K_FOREVER); + + /* Update HSE descriptor */ + cipher_serv->cipherBlockMode = HSE_CIPHER_BLOCK_MODE_CBC; + cipher_serv->cipherDir = HSE_CIPHER_DIR_ENCRYPT; + cipher_serv->pIV = HSE_PTR_TO_HOST_ADDR(iv); + cipher_serv->pInput = HSE_PTR_TO_HOST_ADDR(pkt->in_buf); + cipher_serv->inputLength = pkt->in_len; + cipher_serv->pOutput = HSE_PTR_TO_HOST_ADDR(session->out_buff); + + if (Hse_Ip_ServiceRequest( + config->mu_instance, session->channel, (Hse_Ip_ReqType *)&session->req_type, + (hseSrvDescriptor_t *)&session->crypto_serv_desc) != HSE_SRV_RSP_OK) { + k_mutex_unlock(&session->crypto_lock); + return -EIO; + } + + pkt->out_len = pkt->in_len + iv_bytes; + + memcpy(pkt->out_buf + iv_bytes, session->out_buff, pkt->out_buf_max - iv_bytes); + + k_mutex_unlock(&session->crypto_lock); + + return 0; +} + +static int crypto_nxp_s32_hse_aes_cbc_decrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt, + uint8_t *iv) +{ + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + hseSymCipherSrv_t *cipher_serv = &(session->crypto_serv_desc.hseSrv.symCipherReq); + size_t iv_bytes; + + if (ctx->flags & CAP_NO_IV_PREFIX) { + iv_bytes = 0; + } else { + iv_bytes = HSE_BITS_TO_BYTES(CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE); + } + + __ASSERT_NO_MSG(pkt->in_len - iv_bytes <= pkt->out_buf_max && + pkt->out_buf_max <= CONFIG_CRYPTO_NXP_S32_HSE_OUTPUT_BUFFER_SIZE); + + k_mutex_lock(&session->crypto_lock, K_FOREVER); + + /* Update HSE descriptor */ + cipher_serv->cipherBlockMode = HSE_CIPHER_BLOCK_MODE_CBC; + cipher_serv->cipherDir = HSE_CIPHER_DIR_DECRYPT; + cipher_serv->pIV = HSE_PTR_TO_HOST_ADDR(iv); + cipher_serv->pInput = HSE_PTR_TO_HOST_ADDR(pkt->in_buf + iv_bytes); + cipher_serv->inputLength = pkt->in_len - iv_bytes; + cipher_serv->pOutput = HSE_PTR_TO_HOST_ADDR(session->out_buff); + + if (Hse_Ip_ServiceRequest( + config->mu_instance, session->channel, (Hse_Ip_ReqType *)&session->req_type, + (hseSrvDescriptor_t *)&session->crypto_serv_desc) != HSE_SRV_RSP_OK) { + k_mutex_unlock(&session->crypto_lock); + return -EIO; + } + + pkt->out_len = pkt->in_len; + + memcpy(pkt->out_buf, session->out_buff, pkt->out_buf_max); + + k_mutex_unlock(&session->crypto_lock); + + return 0; +} + +static int crypto_nxp_s32_hse_aes_ctr_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt, + uint8_t *iv) +{ + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + hseSymCipherSrv_t *cipher_serv = &(session->crypto_serv_desc.hseSrv.symCipherReq); + uint8_t iv_key[HSE_BITS_TO_BYTES(CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE)] = {0}; + int iv_len = ctx->keylen - HSE_BITS_TO_BYTES(ctx->mode_params.ctr_info.ctr_len); + + __ASSERT_NO_MSG(pkt->in_len <= pkt->out_buf_max && + pkt->out_buf_max <= CONFIG_CRYPTO_NXP_S32_HSE_OUTPUT_BUFFER_SIZE); + + /* takes the last 4 bytes of the counter parameter as the true + * counter start. IV forms the first 12 bytes of the split counter. + */ + memcpy(iv_key, iv, iv_len); + + k_mutex_lock(&session->crypto_lock, K_FOREVER); + + /* Update HSE descriptor */ + cipher_serv->cipherBlockMode = HSE_CIPHER_BLOCK_MODE_CTR; + cipher_serv->cipherDir = HSE_CIPHER_DIR_ENCRYPT; + cipher_serv->pIV = HSE_PTR_TO_HOST_ADDR(&iv_key); + cipher_serv->pInput = HSE_PTR_TO_HOST_ADDR(pkt->in_buf); + cipher_serv->inputLength = pkt->in_len; + cipher_serv->pOutput = HSE_PTR_TO_HOST_ADDR(session->out_buff); + + if (Hse_Ip_ServiceRequest( + config->mu_instance, session->channel, (Hse_Ip_ReqType *)&session->req_type, + (hseSrvDescriptor_t *)&session->crypto_serv_desc) != HSE_SRV_RSP_OK) { + k_mutex_unlock(&session->crypto_lock); + return -EIO; + } + + pkt->out_len = pkt->in_len; + + memcpy(pkt->out_buf, session->out_buff, pkt->out_buf_max); + + k_mutex_unlock(&session->crypto_lock); + + return 0; +} + +static int crypto_nxp_s32_hse_aes_ctr_decrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt, + uint8_t *iv) +{ + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + hseSymCipherSrv_t *cipher_serv = &(session->crypto_serv_desc.hseSrv.symCipherReq); + uint8_t iv_key[HSE_BITS_TO_BYTES(CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE)] = {0}; + int iv_len = ctx->keylen - HSE_BITS_TO_BYTES(ctx->mode_params.ctr_info.ctr_len); + + __ASSERT_NO_MSG(pkt->in_len <= pkt->out_buf_max && + pkt->out_buf_max <= CONFIG_CRYPTO_NXP_S32_HSE_OUTPUT_BUFFER_SIZE); + + memcpy(iv_key, iv, iv_len); + + k_mutex_lock(&session->crypto_lock, K_FOREVER); + + /* Update HSE descriptor */ + cipher_serv->cipherBlockMode = HSE_CIPHER_BLOCK_MODE_CTR; + cipher_serv->cipherDir = HSE_CIPHER_DIR_DECRYPT; + cipher_serv->pIV = HSE_PTR_TO_HOST_ADDR(&iv_key); + cipher_serv->pInput = HSE_PTR_TO_HOST_ADDR(pkt->in_buf); + cipher_serv->inputLength = pkt->in_len; + cipher_serv->pOutput = HSE_PTR_TO_HOST_ADDR(session->out_buff); + + if (Hse_Ip_ServiceRequest( + config->mu_instance, session->channel, (Hse_Ip_ReqType *)&session->req_type, + (hseSrvDescriptor_t *)&session->crypto_serv_desc) != HSE_SRV_RSP_OK) { + k_mutex_unlock(&session->crypto_lock); + return -EIO; + } + + pkt->out_len = pkt->in_len; + + memcpy(pkt->out_buf, session->out_buff, pkt->out_buf_max); + + k_mutex_unlock(&session->crypto_lock); + + return 0; +} + +static int crypto_nxp_s32_hse_cipher_key_element_set(const struct device *dev, + struct crypto_nxp_s32_hse_session *session, + struct cipher_ctx *ctx) +{ + const struct crypto_nxp_s32_hse_config *config = dev->config; + hseImportKeySrv_t *import_key_serv = &(session->crypto_serv_desc.hseSrv.importKeyReq); + + k_mutex_lock(&session->crypto_lock, K_FOREVER); + + session->req_type.eReqType = HSE_IP_REQTYPE_SYNC; + session->req_type.u32Timeout = CRYPTO_NXP_S32_HSE_SERVICE_TIMEOUT_TICKS; + + session->crypto_serv_desc.srvId = HSE_SRV_ID_IMPORT_KEY; + + session->key_info.keyType = HSE_KEY_TYPE_AES; + session->key_info.keyBitLen = CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE; + session->key_info.keyFlags = HSE_KF_USAGE_ENCRYPT | HSE_KF_USAGE_DECRYPT; + session->key_info.keyCounter = 0U; + session->key_info.smrFlags = 0U; + session->key_info.specific.aesBlockModeMask = HSE_KU_AES_BLOCK_MODE_ANY; + session->key_info.specific.aesBlockModeMask = (hseAesBlockModeMask_t)0U; + session->key_info.hseReserved[0U] = 0U; + session->key_info.hseReserved[1U] = 0U; + + /* The key import is not encrypted, nor authenticated */ + import_key_serv->cipher.cipherKeyHandle = HSE_INVALID_KEY_HANDLE; + import_key_serv->keyContainer.authKeyHandle = HSE_INVALID_KEY_HANDLE; + import_key_serv->pKeyInfo = HSE_PTR_TO_HOST_ADDR(&session->key_info); + import_key_serv->pKey[2] = HSE_PTR_TO_HOST_ADDR(ctx->key.bit_stream); + import_key_serv->keyLen[2] = (uint16_t)ctx->keylen; + import_key_serv->targetKeyHandle = (hseKeyHandle_t)session->key_handle; + + if (Hse_Ip_ServiceRequest( + config->mu_instance, session->channel, (Hse_Ip_ReqType *)&session->req_type, + (hseSrvDescriptor_t *)&session->crypto_serv_desc) != HSE_SRV_RSP_OK) { + k_mutex_unlock(&session->crypto_lock); + return -EIO; + } + + k_mutex_unlock(&session->crypto_lock); + + return 0; +} + +static int crypto_nxp_s32_hse_cipher_begin_session(const struct device *dev, struct cipher_ctx *ctx, + enum cipher_algo algo, enum cipher_mode mode, + enum cipher_op op_type) +{ + struct crypto_nxp_s32_hse_session *session; + + if (algo != CRYPTO_CIPHER_ALGO_AES) { + LOG_ERR("Unsupported algorithm"); + return -ENOTSUP; + } + + if (ctx->flags & ~(CRYPTO_NXP_S32_HSE_CIPHER_CAPS)) { + LOG_ERR("Unsupported flag"); + return -ENOTSUP; + } + + if (mode != CRYPTO_CIPHER_MODE_ECB && mode != CRYPTO_CIPHER_MODE_CBC && + mode != CRYPTO_CIPHER_MODE_CTR) { + LOG_ERR("Unsupported mode"); + return -ENOTSUP; + } + + if (ctx->keylen != HSE_BITS_TO_BYTES(CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE)) { + LOG_ERR("%u key size is not supported", ctx->keylen); + return -EINVAL; + } + + session = crypto_nxp_s32_hse_get_session(dev); + + if (session == NULL) { + LOG_ERR("No free session"); + return -ENOSPC; + } + + if (op_type == CRYPTO_CIPHER_OP_ENCRYPT) { + switch (mode) { + case CRYPTO_CIPHER_MODE_ECB: + ctx->ops.block_crypt_hndlr = crypto_nxp_s32_hse_aes_ecb_encrypt; + break; + case CRYPTO_CIPHER_MODE_CBC: + ctx->ops.cbc_crypt_hndlr = crypto_nxp_s32_hse_aes_cbc_encrypt; + break; + case CRYPTO_CIPHER_MODE_CTR: + ctx->ops.ctr_crypt_hndlr = crypto_nxp_s32_hse_aes_ctr_encrypt; + break; + default: + break; + } + } else { + switch (mode) { + case CRYPTO_CIPHER_MODE_ECB: + ctx->ops.block_crypt_hndlr = crypto_nxp_s32_hse_aes_ecb_decrypt; + break; + case CRYPTO_CIPHER_MODE_CBC: + ctx->ops.cbc_crypt_hndlr = crypto_nxp_s32_hse_aes_cbc_decrypt; + break; + case CRYPTO_CIPHER_MODE_CTR: + ctx->ops.ctr_crypt_hndlr = crypto_nxp_s32_hse_aes_ctr_decrypt; + break; + default: + break; + } + } + + /* Load the key in plain */ + if (crypto_nxp_s32_hse_cipher_key_element_set(dev, session, ctx)) { + free_session(dev, session); + LOG_ERR("Failed to import key catalog"); + return -EIO; + } + + /* Update HSE descriptor */ + session->req_type.eReqType = HSE_IP_REQTYPE_SYNC; + session->req_type.u32Timeout = CRYPTO_NXP_S32_HSE_SERVICE_TIMEOUT_TICKS; + session->crypto_serv_desc.srvId = HSE_SRV_ID_SYM_CIPHER; + session->crypto_serv_desc.hseSrv.symCipherReq.accessMode = HSE_ACCESS_MODE_ONE_PASS; + session->crypto_serv_desc.hseSrv.symCipherReq.cipherAlgo = HSE_CIPHER_ALGO_AES; + session->crypto_serv_desc.hseSrv.symCipherReq.keyHandle = session->key_handle; + session->crypto_serv_desc.hseSrv.symCipherReq.sgtOption = HSE_SGT_OPTION_NONE; + + ctx->drv_sessn_state = session; + ctx->device = dev; + + return 0; +} + +static int crypto_nxp_s32_hse_cipher_free_session(const struct device *dev, struct cipher_ctx *ctx) +{ + struct crypto_nxp_s32_hse_session *session; + + session = ctx->drv_sessn_state; + free_session(dev, session); + + return 0; +} + +static int crypto_nxp_s32_hse_sha(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish) +{ + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + hseHashSrv_t *hash_serv = &(session->crypto_serv_desc.hseSrv.hashReq); + + if (!finish) { + return 0; + } + + /* Update HSE descriptor */ + hash_serv->pInput = HSE_PTR_TO_HOST_ADDR(pkt->in_buf); + hash_serv->inputLength = pkt->in_len; + + k_mutex_lock(&session->crypto_lock, K_FOREVER); + + if (Hse_Ip_ServiceRequest( + config->mu_instance, session->channel, (Hse_Ip_ReqType *)&session->req_type, + (hseSrvDescriptor_t *)&session->crypto_serv_desc) != HSE_SRV_RSP_OK) { + k_mutex_unlock(&session->crypto_lock); + return -EIO; + } + + memcpy(pkt->out_buf, session->out_buff, + *(uint32_t *)(session->crypto_serv_desc.hseSrv.hashReq.pHashLength)); + + k_mutex_unlock(&session->crypto_lock); + + return 0; +} + +static int crypto_nxp_s32_hse_hash_begin_session(const struct device *dev, struct hash_ctx *ctx, + enum hash_algo algo) +{ + struct crypto_nxp_s32_hse_session *session; + static uint32_t out_len; + hseHashSrv_t *hash_serv; + + if (ctx->flags & ~(CRYPTO_NXP_S32_HSE_HASH_CAPS)) { + return -ENOTSUP; + } + + session = crypto_nxp_s32_hse_get_session(dev); + + if (session == NULL) { + return -ENOSPC; + } + + session->req_type.eReqType = HSE_IP_REQTYPE_SYNC; + session->req_type.u32Timeout = CRYPTO_NXP_S32_HSE_SERVICE_TIMEOUT_TICKS; + + hash_serv = &(session->crypto_serv_desc.hseSrv.hashReq); + + switch (algo) { + case CRYPTO_HASH_ALGO_SHA224: { + hash_serv->hashAlgo = HSE_HASH_ALGO_SHA2_224; + out_len = HSE_BITS_TO_BYTES(224); + break; + } + case CRYPTO_HASH_ALGO_SHA256: { + hash_serv->hashAlgo = HSE_HASH_ALGO_SHA2_256; + out_len = HSE_BITS_TO_BYTES(256); + break; + } + case CRYPTO_HASH_ALGO_SHA384: { + hash_serv->hashAlgo = HSE_HASH_ALGO_SHA2_384; + out_len = HSE_BITS_TO_BYTES(384); + break; + } + case CRYPTO_HASH_ALGO_SHA512: { + hash_serv->hashAlgo = HSE_HASH_ALGO_SHA2_512; + out_len = HSE_BITS_TO_BYTES(512); + break; + } + default: { + return -ENOTSUP; + } + } + + session->crypto_serv_desc.srvId = HSE_SRV_ID_HASH; + hash_serv->accessMode = HSE_ACCESS_MODE_ONE_PASS; + hash_serv->pHashLength = HSE_PTR_TO_HOST_ADDR(&out_len); + hash_serv->pHash = HSE_PTR_TO_HOST_ADDR(session->out_buff); + + ctx->drv_sessn_state = session; + ctx->hash_hndlr = crypto_nxp_s32_hse_sha; + ctx->device = dev; + + return 0; +} + +static int crypto_nxp_s32_hse_hash_free_session(const struct device *dev, struct hash_ctx *ctx) +{ + struct crypto_nxp_s32_hse_session *session; + + session = ctx->drv_sessn_state; + free_session(dev, session); + + return 0; +} + +static int crypto_nxp_s32_hse_query_caps(const struct device *dev) +{ + return CRYPTO_NXP_S32_HSE_HASH_CAPS | CRYPTO_NXP_S32_HSE_CIPHER_CAPS; +} + +static int crypto_nxp_s32_hse_init(const struct device *dev) +{ + const struct crypto_nxp_s32_hse_config *config = dev->config; + struct crypto_nxp_s32_hse_data *data = dev->data; + struct crypto_nxp_s32_hse_session *session; + hseStatus_t status; + + k_timeout_t timeout = K_MSEC(CRYPTO_NXP_S32_HSE_INIT_TIMEOUT_MS); + int64_t start_time = k_uptime_ticks(); + + do { + status = Hse_Ip_GetHseStatus(config->mu_instance); + } while (!(status & (HSE_STATUS_INIT_OK | HSE_STATUS_INSTALL_OK)) || + (k_uptime_ticks() - start_time < timeout.ticks)); + + if (!(status & HSE_STATUS_INIT_OK)) { + LOG_ERR("HSE initialization has not been completed or " + "MU%d is not activated", config->mu_instance); + return -EIO; + } + + if (!(status & HSE_STATUS_INSTALL_OK)) { + LOG_ERR("Key catalogs has not been formatted"); + return -EIO; + } + + if (Hse_Ip_Init(config->mu_instance, &data->mu_state) != HSE_IP_STATUS_SUCCESS) { + LOG_ERR("Failed to initialize MU%d", config->mu_instance); + return -EIO; + } + + for (size_t i = 0; i < HSE_IP_NUM_OF_CHANNELS_PER_MU; i++) { + session = &data->sessions[i]; + k_mutex_init(&session->crypto_lock); + } + + k_mutex_init(&crypto_nxp_s32_lock); + + return 0; +} + +static struct crypto_driver_api crypto_nxp_s32_hse_api = { + .cipher_begin_session = crypto_nxp_s32_hse_cipher_begin_session, + .cipher_free_session = crypto_nxp_s32_hse_cipher_free_session, + .query_hw_caps = crypto_nxp_s32_hse_query_caps, + .hash_begin_session = crypto_nxp_s32_hse_hash_begin_session, + .hash_free_session = crypto_nxp_s32_hse_hash_free_session, +}; + +#define CRYPTO_NXP_S32_HSE_SESSION_CFG(indx, n) \ + { \ + .channel = indx + 1, \ + .out_buff = &crypto_out_buff_##n[indx][0], \ + .key_handle = GET_KEY_HANDLE(HSE_KEY_CATALOG_ID_RAM, \ + CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_GROUP_ID, indx), \ + } + +#define CRYPTO_NXP_S32_HSE_INIT_SESSION(n) \ + LISTIFY(__DEBRACKET HSE_IP_NUM_OF_CHANNELS_PER_MU, CRYPTO_NXP_S32_HSE_SESSION_CFG, (,), n) + +#define CRYPTO_NXP_S32_HSE_INIT_DEVICE(n) \ + static __nocache uint8_t \ + crypto_out_buff_##n[HSE_IP_NUM_OF_CHANNELS_PER_MU] \ + [CONFIG_CRYPTO_NXP_S32_HSE_OUTPUT_BUFFER_SIZE]; \ + \ + static struct crypto_nxp_s32_hse_data crypto_nxp_s32_hse_data_##n = { \ + .sessions = \ + { \ + CRYPTO_NXP_S32_HSE_INIT_SESSION(n), \ + }, \ + }; \ + \ + static const struct crypto_nxp_s32_hse_config crypto_nxp_s32_hse_config_##n = { \ + .mu_instance = CRYPTO_NXP_S32_HSE_MU_GET_INSTANCE(n), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &crypto_nxp_s32_hse_init, NULL, &crypto_nxp_s32_hse_data_##n, \ + &crypto_nxp_s32_hse_config_##n, POST_KERNEL, \ + CONFIG_CRYPTO_INIT_PRIORITY, &crypto_nxp_s32_hse_api); + +DT_INST_FOREACH_STATUS_OKAY(CRYPTO_NXP_S32_HSE_INIT_DEVICE) diff --git a/dts/arm/nxp/nxp_s32z27x_r52.dtsi b/dts/arm/nxp/nxp_s32z27x_r52.dtsi index 8395982969c23..c0cc83de710ca 100644 --- a/dts/arm/nxp/nxp_s32z27x_r52.dtsi +++ b/dts/arm/nxp/nxp_s32z27x_r52.dtsi @@ -1892,5 +1892,59 @@ }; }; }; + + hse: crypto { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + + mub0: mu@42200000 { + compatible = "nxp,s32-crypto-hse-mu"; + reg = <0x42200000 0x10000>; + status = "disabled"; + }; + + mub1: mu@42210000 { + compatible = "nxp,s32-crypto-hse-mu"; + reg = <0x42210000 0x10000>; + status = "disabled"; + }; + + mub2: mu@42220000 { + compatible = "nxp,s32-crypto-hse-mu"; + reg = <0x42220000 0x10000>; + status = "disabled"; + }; + + mub3: mu@42230000 { + compatible = "nxp,s32-crypto-hse-mu"; + reg = <0x42230000 0x10000>; + status = "disabled"; + }; + + mub4: mu@42240000 { + compatible = "nxp,s32-crypto-hse-mu"; + reg = <0x42240000 0x10000>; + status = "disabled"; + }; + + mub5: mu@42250000 { + compatible = "nxp,s32-crypto-hse-mu"; + reg = <0x42250000 0x10000>; + status = "disabled"; + }; + + mub6: mu@42260000 { + compatible = "nxp,s32-crypto-hse-mu"; + reg = <0x42260000 0x10000>; + status = "disabled"; + }; + + mub7: mu@42270000 { + compatible = "nxp,s32-crypto-hse-mu"; + reg = <0x42270000 0x10000>; + status = "disabled"; + }; + }; }; }; diff --git a/dts/bindings/crypto/nxp,s32-crypto-hse-mu.yaml b/dts/bindings/crypto/nxp,s32-crypto-hse-mu.yaml new file mode 100644 index 0000000000000..0b919440bd8f5 --- /dev/null +++ b/dts/bindings/crypto/nxp,s32-crypto-hse-mu.yaml @@ -0,0 +1,19 @@ +# Copyright 2025 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP S32 HSE Messaging Unit. The Messaging Unit (MU) module facilitates communication between + HSE processor core and application processor core (e.g any of RTU core) on a chip. + Processors side-A inside the MU is accessible only by HSE core, whether side-B is accessible + by application core. To enable a dedicated MU instance for Crypto operation: + &mub0 { + status = "okay"; + }; + +compatible: "nxp,s32-crypto-hse-mu" + +include: base.yaml + +properties: + reg: + required: true diff --git a/west.yml b/west.yml index cafcb2a1b39ea..cd1f38240a6f2 100644 --- a/west.yml +++ b/west.yml @@ -210,7 +210,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 6d6ab91d5cc71c872353af1957d19f3d930df0fd + revision: pull/443/head path: modules/hal/nxp groups: - hal From a81799ac1c91cf0e81356e6de7745c763905c1d2 Mon Sep 17 00:00:00 2001 From: Ha Duong Quang Date: Sat, 8 Nov 2025 20:22:36 +0700 Subject: [PATCH 2/2] boards: enables support for s32z270 hse crypto Enable test for s32z270 hash crypto. Enable samples for cipher cryptoEndable samples for EBC, CBC, CTR mode of cipher crypto. Signed-off-by: Ha Duong Quang --- boards/nxp/s32z2xxdc2/doc/index.rst | 13 +++++++++++++ boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0.yaml | 1 + .../nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml | 1 + boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml | 1 + .../nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml | 1 + .../crypto/boards/s32z2xxdc2_s32z270_rtu0.overlay | 9 +++++++++ .../crypto/boards/s32z2xxdc2_s32z270_rtu1.overlay | 9 +++++++++ samples/drivers/crypto/src/main.c | 3 +++ .../boards/s32z2xxdc2_s32z270_rtu0.overlay | 9 +++++++++ .../boards/s32z2xxdc2_s32z270_rtu1.overlay | 9 +++++++++ tests/crypto/crypto_hash/src/main.c | 2 ++ 11 files changed, 58 insertions(+) create mode 100644 samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu0.overlay create mode 100644 samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu1.overlay create mode 100644 tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu0.overlay create mode 100644 tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu1.overlay diff --git a/boards/nxp/s32z2xxdc2/doc/index.rst b/boards/nxp/s32z2xxdc2/doc/index.rst index 17ed94e9e8334..6b197e8e21d19 100644 --- a/boards/nxp/s32z2xxdc2/doc/index.rst +++ b/boards/nxp/s32z2xxdc2/doc/index.rst @@ -136,6 +136,19 @@ External Flash The on-board S26HS512T 512M-bit HyperFlash memory is connected to the QSPI controller port A1. This board configuration selects it as the default flash controller. +CRYPTO +====== + +The Hardware Security Engine (HSE) supports cryptographic operations, including hashing and +symmetric ciphers, with capabilities for ECB, CBC, and CTR modes using RAM-based key catalogs +with 128-bit or 256-bit key lengths. + +.. note:: + The driver assumes that the HSE Firmware has been installed and configured (i.e the key catalogs + has been formatted, used MU instances has been activated, etc). HSE Firmware installation and + configuration phase documented in HSE Firmware User Manual. Please contact NXP sales person or + NXP distributor in order to have access to that document. + Programming and Debugging ************************* diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0.yaml index fada2cf5ea9de..769f72b1ed771 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0.yaml @@ -22,4 +22,5 @@ supported: - pwm - sent - psi5 + - crypto vendor: nxp diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml index e5593f47784f5..34802a6f9161c 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml @@ -22,4 +22,5 @@ supported: - pwm - sent - psi5 + - crypto vendor: nxp diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml index b2030af22d191..66b62a746683a 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml @@ -22,4 +22,5 @@ supported: - pwm - sent - psi5 + - crypto vendor: nxp diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml index 993bc5d8ecb1e..05573133c2227 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml @@ -22,4 +22,5 @@ supported: - pwm - sent - psi5 + - crypto vendor: nxp diff --git a/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu0.overlay b/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu0.overlay new file mode 100644 index 0000000000000..bc755ce32e223 --- /dev/null +++ b/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu0.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mub0 { + status = "okay"; +}; diff --git a/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu1.overlay b/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu1.overlay new file mode 100644 index 0000000000000..5c6b155ae7a44 --- /dev/null +++ b/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu1.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mub2 { + status = "okay"; +}; diff --git a/samples/drivers/crypto/src/main.c b/samples/drivers/crypto/src/main.c index 9cda5b1a58a3a..3c182a85f221c 100644 --- a/samples/drivers/crypto/src/main.c +++ b/samples/drivers/crypto/src/main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016 Intel Corporation. + * Copyright 2025 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,6 +25,8 @@ LOG_MODULE_REGISTER(main); #define CRYPTO_DEV_COMPAT st_stm32_aes #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_mcux_dcp) #define CRYPTO_DEV_COMPAT nxp_mcux_dcp +#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_crypto_hse_mu) +#define CRYPTO_DEV_COMPAT nxp_s32_crypto_hse_mu #elif CONFIG_CRYPTO_NRF_ECB #define CRYPTO_DEV_COMPAT nordic_nrf_ecb #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_smartbond_crypto) diff --git a/tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu0.overlay b/tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu0.overlay new file mode 100644 index 0000000000000..bc755ce32e223 --- /dev/null +++ b/tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu0.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mub0 { + status = "okay"; +}; diff --git a/tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu1.overlay b/tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu1.overlay new file mode 100644 index 0000000000000..5c6b155ae7a44 --- /dev/null +++ b/tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu1.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mub2 { + status = "okay"; +}; diff --git a/tests/crypto/crypto_hash/src/main.c b/tests/crypto/crypto_hash/src/main.c index fa04afc7df968..dc11e070b8a8f 100644 --- a/tests/crypto/crypto_hash/src/main.c +++ b/tests/crypto/crypto_hash/src/main.c @@ -17,6 +17,8 @@ #define CRYPTO_DEV_COMPAT st_stm32_hash #elif DT_HAS_COMPAT_STATUS_OKAY(espressif_esp32_sha) #define CRYPTO_DEV_COMPAT espressif_esp32_sha +#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_crypto_hse_mu) +#define CRYPTO_DEV_COMPAT nxp_s32_crypto_hse_mu #else #error "You need to enable one crypto device" #endif