From 88f2cc925b1efc0b84d828d7f039e8af5cbdda71 Mon Sep 17 00:00:00 2001 From: Ha Duong Quang Date: Mon, 14 Apr 2025 11:37:55 +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 | 656 ++++++++++++++++++ dts/arm/nxp/nxp_s32z27x_r52.dtsi | 54 ++ .../crypto/nxp,s32-crypto-hse-mu.yaml | 19 + west.yml | 2 +- 7 files changed, 765 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 5094377abb137..1a1b8f505ee2a 100644 --- a/drivers/crypto/CMakeLists.txt +++ b/drivers/crypto/CMakeLists.txt @@ -15,4 +15,5 @@ zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA_V2 crypto_it8xxx2_sha_v2. zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCUX_DCP crypto_mcux_dcp.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_SI32 crypto_si32.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_CC23X0 crypto_cc23x0.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 9a7bdb89b54ee..54427c6d2bcb2 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -85,5 +85,6 @@ source "drivers/crypto/Kconfig.mcux_dcp" source "drivers/crypto/Kconfig.si32" source "drivers/crypto/Kconfig.smartbond" source "drivers/crypto/Kconfig.cc23x0" +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..2b238f6d9d049 --- /dev/null +++ b/drivers/crypto/crypto_nxp_s32_hse.c @@ -0,0 +1,656 @@ +/* + * 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); + +#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_infor; +}; + +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_infor, 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_infor.keyType = HSE_KEY_TYPE_AES; + session->key_infor.keyBitLen = CONFIG_CRYPTO_NXP_S32_HSE_AES_KEY_SIZE; + session->key_infor.keyFlags = HSE_KF_USAGE_ENCRYPT | HSE_KF_USAGE_DECRYPT | + HSE_KF_USAGE_SIGN | HSE_KF_USAGE_VERIFY; + session->key_infor.keyCounter = 0U; + session->key_infor.smrFlags = 0U; + session->key_infor.specific.aesBlockModeMask = HSE_KU_AES_BLOCK_MODE_ANY; + session->key_infor.specific.aesBlockModeMask = (hseAesBlockModeMask_t)0U; + session->key_infor.hseReserved[0U] = 0U; + session->key_infor.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_infor); + 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 0c976a3041874..7016ca2303e31 100644 --- a/dts/arm/nxp/nxp_s32z27x_r52.dtsi +++ b/dts/arm/nxp/nxp_s32z27x_r52.dtsi @@ -1465,5 +1465,59 @@ #size-cells = <0>; status = "disabled"; }; + + 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 10ab107abb617..4527614475fe5 100644 --- a/west.yml +++ b/west.yml @@ -208,7 +208,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 6b11d190e0092aafec81489d0e7045a3bcf80c60 + revision: pull/443/head path: modules/hal/nxp groups: - hal From 1f24a4b782d0089324a31e42a4fa5c3140869b22 Mon Sep 17 00:00:00 2001 From: Ha Duong Quang Date: Fri, 7 Feb 2025 17:15:43 +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 | 3 ++- .../nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml | 3 ++- boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml | 3 ++- .../nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml | 3 ++- .../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, 62 insertions(+), 4 deletions(-) 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 6383dc8ad32a8..50a31268f5294 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 60b258ad5a166..03e0685a60c26 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 NXP +# Copyright 2022-2025 NXP # SPDX-License-Identifier: Apache-2.0 identifier: s32z2xxdc2/s32z270/rtu0 @@ -20,4 +20,5 @@ supported: - i2c - dma - pwm + - crypto vendor: nxp diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml index c35cc47699bd0..16ab4c893a3c6 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml @@ -1,4 +1,4 @@ -# Copyright 2023-2024 NXP +# Copyright 2023-2025 NXP # SPDX-License-Identifier: Apache-2.0 identifier: s32z2xxdc2@D/s32z270/rtu0 @@ -20,4 +20,5 @@ supported: - i2c - dma - pwm + - crypto vendor: nxp diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml index 3d4f2062cc984..19ce9d97729aa 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 NXP +# Copyright 2022-2025 NXP # SPDX-License-Identifier: Apache-2.0 identifier: s32z2xxdc2/s32z270/rtu1 @@ -20,4 +20,5 @@ supported: - i2c - dma - pwm + - crypto vendor: nxp diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml index 334d75319ca05..4a97c7dcb6f21 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml @@ -1,4 +1,4 @@ -# Copyright 2022-2024 NXP +# Copyright 2022-2025 NXP # SPDX-License-Identifier: Apache-2.0 identifier: s32z2xxdc2@D/s32z270/rtu1 @@ -20,4 +20,5 @@ supported: - i2c - dma - pwm + - 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 a5a2fe01fabd8..ca66f1bb51589 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 */ @@ -27,6 +28,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 ea1229dda6df5..2f7241bd1a8ea 100644 --- a/tests/crypto/crypto_hash/src/main.c +++ b/tests/crypto/crypto_hash/src/main.c @@ -13,6 +13,8 @@ #define CRYPTO_DRV_NAME CONFIG_CRYPTO_MBEDTLS_SHIM_DRV_NAME #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_smartbond_crypto) #define CRYPTO_DEV_COMPAT renesas_smartbond_crypto +#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