diff --git a/boards/nxp/s32z2xxdc2/doc/index.rst b/boards/nxp/s32z2xxdc2/doc/index.rst index 9cb0972bf8fc7e..786cd8342f3de3 100644 --- a/boards/nxp/s32z2xxdc2/doc/index.rst +++ b/boards/nxp/s32z2xxdc2/doc/index.rst @@ -170,6 +170,19 @@ EDMA The EDMA modules feature four EDMA3 instances: Instance 0 with 32 channels, and instances 1, 4, and 5, each with 16 channels. +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 070c33e6bfd323..f9899392691106 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0.yaml @@ -19,4 +19,5 @@ supported: - adc - i2c - dma + - crypto vendor: nxp diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml index 9d692144a76c21..4f48af57c6d52f 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu0_D.yaml @@ -19,4 +19,5 @@ supported: - adc - i2c - dma + - crypto vendor: nxp diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml index 3de95effa80035..3e2fa028c484c5 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1.yaml @@ -19,4 +19,5 @@ supported: - adc - i2c - dma + - crypto vendor: nxp diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml index ef45138807edae..0be14d625db604 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270_rtu1_D.yaml @@ -19,4 +19,5 @@ supported: - adc - i2c - dma + - crypto vendor: nxp diff --git a/drivers/crypto/CMakeLists.txt b/drivers/crypto/CMakeLists.txt index 59d02d44ad9739..f89e97e08545f8 100644 --- a/drivers/crypto/CMakeLists.txt +++ b/drivers/crypto/CMakeLists.txt @@ -14,4 +14,5 @@ zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA crypto_it8xxx2_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA_V2 crypto_it8xxx2_sha_v2.c) 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_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 964e9439db0415..a767018a87dfde 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -84,5 +84,6 @@ source "drivers/crypto/Kconfig.it8xxx2" source "drivers/crypto/Kconfig.mcux_dcp" source "drivers/crypto/Kconfig.si32" source "drivers/crypto/Kconfig.smartbond" +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 00000000000000..1d9358514aae2a --- /dev/null +++ b/drivers/crypto/Kconfig.nxp_s32_hse @@ -0,0 +1,33 @@ +# Copyright 2024 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 "The output buffer size for storing the output data of HSE crypto service" + default 128 + help + The output buffer size for storing the output data of HSE crypto service. + +config CRYPTO_NXP_S32_HSE_AES_KEY_SIZE + int "The size of the key used in cryptographic algorithms, measured 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 00000000000000..ebe0b26ccbf6c5 --- /dev/null +++ b/drivers/crypto/crypto_nxp_s32_hse.c @@ -0,0 +1,658 @@ +/* + * Copyright 2024 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 1000000000 +#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 crypto_nxp_s32_hse_session *crypto_nxp_s32_hse_get_session(const struct device *dev) +{ + struct crypto_nxp_s32_hse_data *data = dev->data; + const struct crypto_nxp_s32_hse_config *config = dev->config; + uint8_t mu_channel = Hse_Ip_GetFreeChannel(config->mu_instance); + struct crypto_nxp_s32_hse_session *session; + + if (mu_channel != HSE_IP_INVALID_MU_CHANNEL_U8) { + session = &data->sessions[mu_channel - 1]; + session->in_use = true; + return session; + } + + return NULL; +} + +static inline void free_session(struct crypto_nxp_s32_hse_session *session) +{ + session->in_use = false; +} + +static int crypto_nxp_s32_hse_aes_ecb_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt) +{ + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + 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) +{ + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + 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) +{ + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + 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) +{ + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + 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) +{ + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + 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) +{ + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + 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; + + session->crypto_serv_desc.srvId = HSE_SRV_ID_IMPORT_KEY; + + session->key_infor.keyType = HSE_KEY_TYPE_AES; + session->key_infor.keyBitLen = HSE_KEY128_BITS; + 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; + struct k_mutex crypto_lock; + + 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; + } + + k_mutex_init(&crypto_lock); + k_mutex_lock(&crypto_lock, K_FOREVER); + session = crypto_nxp_s32_hse_get_session(dev); + k_mutex_unlock(&crypto_lock); + + 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(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; + 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; + const struct crypto_nxp_s32_hse_config *config = dev->config; + + session = ctx->drv_sessn_state; + 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)); + Hse_Ip_ReleaseChannel(config->mu_instance, session->channel); + free_session(session); + k_mutex_unlock(&session->crypto_lock); + + return 0; +} + +static int crypto_nxp_s32_hse_sha(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish) +{ + struct crypto_nxp_s32_hse_session *session = ctx->drv_sessn_state; + const struct crypto_nxp_s32_hse_config *config = ctx->device->config; + 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; + struct k_mutex crypto_lock; + + if (ctx->flags & ~(CRYPTO_NXP_S32_HSE_HASH_CAPS)) { + return -ENOTSUP; + } + + k_mutex_init(&crypto_lock); + k_mutex_lock(&crypto_lock, K_FOREVER); + session = crypto_nxp_s32_hse_get_session(dev); + k_mutex_unlock(&crypto_lock); + + if (session == NULL) { + return -ENOSPC; + } + + session->req_type.eReqType = HSE_IP_REQTYPE_SYNC; + session->req_type.u32Timeout = CRYPTO_NXP_S32_HSE_SERVICE_TIMEOUT; + + 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; + const struct crypto_nxp_s32_hse_config *config = dev->config; + + session = ctx->drv_sessn_state; + 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)); + Hse_Ip_ReleaseChannel(config->mu_instance, session->channel); + free_session(session); + k_mutex_unlock(&session->crypto_lock); + + 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); + } + + 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 a04d5a01022d17..2425f79fb0bb32 100644 --- a/dts/arm/nxp/nxp_s32z27x_r52.dtsi +++ b/dts/arm/nxp/nxp_s32z27x_r52.dtsi @@ -1127,6 +1127,7 @@ status = "disabled"; }; +<<<<<<< HEAD edma0: dma-controller@405d0000 { compatible = "nxp,mcux-edma-v3"; reg = <0x405d0000 0x10000>, <0x405a0000 0x10000>, <0x405b0000 0x100000>; @@ -1255,5 +1256,60 @@ 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"; + }; + }; +>>>>>>> 7c4bd5845ad (driver: crypto: add NXP S32 CRYPTO HSE driver) }; }; 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 00000000000000..c01e9b1d4a5ee5 --- /dev/null +++ b/dts/bindings/crypto/nxp,s32-crypto-hse-mu.yaml @@ -0,0 +1,19 @@ +# Copyright 2024 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/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu0.overlay b/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu0.overlay new file mode 100644 index 00000000000000..a28a85a5fe4396 --- /dev/null +++ b/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu0.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2024 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 00000000000000..757d788314269c --- /dev/null +++ b/samples/drivers/crypto/boards/s32z2xxdc2_s32z270_rtu1.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2024 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 ef0d248c365670..400b5877f2bcb4 100644 --- a/samples/drivers/crypto/src/main.c +++ b/samples/drivers/crypto/src/main.c @@ -27,6 +27,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 00000000000000..a28a85a5fe4396 --- /dev/null +++ b/tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu0.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2024 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 00000000000000..757d788314269c --- /dev/null +++ b/tests/crypto/crypto_hash/boards/s32z2xxdc2_s32z270_rtu1.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2024 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 ea1229dda6df5f..c32bd543c61dc2 100644 --- a/tests/crypto/crypto_hash/src/main.c +++ b/tests/crypto/crypto_hash/src/main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Intel Corporation + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +14,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 diff --git a/west.yml b/west.yml index 5d50af436004e6..6f64372ad63fb1 100644 --- a/west.yml +++ b/west.yml @@ -198,7 +198,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 4a4741fa2be33f6b638a49e357c5e33bb7ad0544 + revision: pull/443/head path: modules/hal/nxp groups: - hal