1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027 |
- /**************************************************************************//**
- *
- * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2020-3-3 CHChen First version
- * 2020-5-3 YCHuang12 Add TDES and SHA
- *
- ******************************************************************************/
- #include <rtconfig.h>
- #if ((defined(BSP_USING_CRYPTO) || defined(BSP_USING_TRNG) || defined(BSP_USING_CRC)) && defined(RT_USING_HWCRYPTO))
- #include <rtdevice.h>
- #include <rtdbg.h>
- #include <board.h>
- #include "NuMicro.h"
- #include <nu_bitutil.h>
- #if defined(BSP_USING_TRNG)
- #include "drv_trng.h"
- #endif
- #if defined(BSP_USING_CRC)
- #include "drv_crc.h"
- #endif
- /* Private typedef --------------------------------------------------------------*/
- typedef struct
- {
- uint8_t *pu8SHATempBuf;
- uint32_t u32SHATempBufLen;
- uint32_t u32DMAMode;
- uint32_t u32BlockSize;
- } S_SHA_CONTEXT;
- /* Private functions ------------------------------------------------------------*/
- static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx);
- static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx);
- static rt_err_t nu_hwcrypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src);
- static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx);
- /* Private variables ------------------------------------------------------------*/
- static const struct rt_hwcrypto_ops nu_hwcrypto_ops =
- {
- .create = nu_hwcrypto_create,
- .destroy = nu_hwcrypto_destroy,
- .copy = nu_hwcrypto_clone,
- .reset = nu_hwcrypto_reset,
- };
- /* Crypto engine operation ------------------------------------------------------------*/
- #if defined(BSP_USING_CRYPTO)
- #define NU_HWCRYPTO_DES_3KEYS 1
- #define NU_HWCRYPTO_DES_NO3KEYS 0
- #define NU_HWCRYPTO_AES_NAME "nu_AES"
- #define NU_HWCRYPTO_TDES_NAME "nu_TDES"
- #define NU_HWCRYPTO_SHA_NAME "nu_SHA"
- #if !defined(BSP_USING_TRNG)
- #define NU_HWCRYPTO_PRNG_NAME "nu_PRNG"
- #endif
- static struct rt_mutex s_AES_mutex;
- static struct rt_mutex s_TDES_mutex;
- static struct rt_mutex s_SHA_mutex;
- #if !defined(BSP_USING_TRNG)
- static struct rt_mutex s_PRNG_mutex;
- #endif
- static rt_err_t nu_crypto_init(void)
- {
- rt_err_t result = RT_EOK;
- /* init cipher mutex */
- #if defined(RT_HWCRYPTO_USING_AES)
- result = rt_mutex_init(&s_AES_mutex, NU_HWCRYPTO_AES_NAME, RT_IPC_FLAG_PRIO);
- RT_ASSERT(result == RT_EOK);
- AES_ENABLE_INT(CRPT);
- #endif
- #if defined(RT_HWCRYPTO_USING_3DES)
- result = rt_mutex_init(&s_TDES_mutex, NU_HWCRYPTO_TDES_NAME, RT_IPC_FLAG_PRIO);
- RT_ASSERT(result == RT_EOK);
- TDES_ENABLE_INT(CRPT);
- #endif
- #if defined(RT_HWCRYPTO_USING_SHA1) || defined(RT_HWCRYPTO_USING_SHA2)
- result = rt_mutex_init(&s_SHA_mutex, NU_HWCRYPTO_SHA_NAME, RT_IPC_FLAG_PRIO);
- RT_ASSERT(result == RT_EOK);
- SHA_ENABLE_INT(CRPT);
- #endif
- #if defined(RT_HWCRYPTO_USING_RNG) && !defined(BSP_USING_TRNG)
- result = rt_mutex_init(&s_PRNG_mutex, NU_HWCRYPTO_PRNG_NAME, RT_IPC_FLAG_PRIO);
- RT_ASSERT(result == RT_EOK);
- PRNG_ENABLE_INT(CRPT);
- #endif
- return result;
- }
- static rt_err_t nu_aes_crypt_run(
- rt_bool_t bEncrypt,
- uint32_t u32OpMode,
- uint8_t *pu8Key,
- uint32_t u32KeySize,
- uint8_t *pu8IV,
- uint8_t *pu8InData,
- uint8_t *pu8OutData,
- uint32_t u32DataLen
- )
- {
- uint32_t au32SwapKey[8];
- uint32_t au32SwapIV[4];
- rt_err_t result;
- au32SwapKey[0] = nu_get32_be(&pu8Key[0]);
- au32SwapKey[1] = nu_get32_be(&pu8Key[4]);
- au32SwapKey[2] = nu_get32_be(&pu8Key[8]);
- au32SwapKey[3] = nu_get32_be(&pu8Key[12]);
- if ((u32KeySize == AES_KEY_SIZE_192) || (u32KeySize == AES_KEY_SIZE_256))
- {
- au32SwapKey[4] = nu_get32_be(&pu8Key[16]);
- au32SwapKey[5] = nu_get32_be(&pu8Key[20]);
- }
- if (u32KeySize == AES_KEY_SIZE_256)
- {
- au32SwapKey[6] = nu_get32_be(&pu8Key[24]);
- au32SwapKey[7] = nu_get32_be(&pu8Key[28]);
- }
- au32SwapIV[0] = nu_get32_be(&pu8IV[0]);
- au32SwapIV[1] = nu_get32_be(&pu8IV[4]);
- au32SwapIV[2] = nu_get32_be(&pu8IV[8]);
- au32SwapIV[3] = nu_get32_be(&pu8IV[12]);
- result = rt_mutex_take(&s_AES_mutex, RT_WAITING_FOREVER);
- RT_ASSERT(result == RT_EOK);
- //Using Channel 0
- AES_Open(CRPT, 0, bEncrypt, u32OpMode, u32KeySize, AES_IN_OUT_SWAP);
- AES_SetKey(CRPT, 0, (uint32_t *)&au32SwapKey[0], u32KeySize);
- AES_SetInitVect(CRPT, 0, (uint32_t *)au32SwapIV);
- //Setup AES DMA
- AES_SetDMATransfer(CRPT, 0, (uint32_t)pu8InData, (uint32_t)pu8OutData, u32DataLen);
- AES_CLR_INT_FLAG(CRPT);
- /* Start AES encryption/decryption */
- AES_Start(CRPT, 0, CRYPTO_DMA_ONE_SHOT);
- /* Wait done */
- while (!(CRPT->INTSTS & CRPT_INTEN_AESIEN_Msk)) {};
- if ((u32DataLen % 16) && (CRPT->AES_STS & (CRPT_AES_STS_OUTBUFEMPTY_Msk | CRPT_AES_STS_INBUFEMPTY_Msk)))
- rt_kprintf("AES WARNING - AES Data length(%d) is not enough. -> %d \n", u32DataLen, RT_ALIGN(u32DataLen, 16));
- else if (CRPT->INTSTS & (CRPT_INTSTS_AESEIF_Msk) || (CRPT->AES_STS & (CRPT_AES_STS_BUSERR_Msk | CRPT_AES_STS_CNTERR_Msk)))
- rt_kprintf("AES ERROR - CRPT->INTSTS-%08x, CRPT->AES_STS-%08x\n", CRPT->INTSTS, CRPT->AES_STS);
- /* Clear AES interrupt status */
- AES_CLR_INT_FLAG(CRPT);
- result = rt_mutex_release(&s_AES_mutex);
- RT_ASSERT(result == RT_EOK);
- return RT_EOK;
- }
- #if !defined(BSP_USING_TRNG)
- //Using PRNG instead of TRNG
- static void nu_prng_open(uint32_t u32Seed)
- {
- rt_err_t result;
- result = rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER);
- RT_ASSERT(result == RT_EOK);
- //Open PRNG 64 bits.
- PRNG_Open(CRPT, PRNG_KEY_SIZE_64, PRNG_SEED_RELOAD, u32Seed);
- result = rt_mutex_release(&s_PRNG_mutex);
- RT_ASSERT(result == RT_EOK);
- }
- static rt_uint32_t nu_prng_run(void)
- {
- uint32_t au32RNGValue[2];
- rt_err_t result;
- result = rt_mutex_take(&s_PRNG_mutex, RT_WAITING_FOREVER);
- RT_ASSERT(result == RT_EOK);
- PRNG_Start(CRPT);
- while ((CRPT->PRNG_CTL & CRPT_PRNG_CTL_BUSY_Msk)) {};
- /* Clear PRNG interrupt status */
- PRNG_CLR_INT_FLAG(CRPT);
- PRNG_Read(CRPT, &au32RNGValue[0]);
- result = rt_mutex_release(&s_PRNG_mutex);
- RT_ASSERT(result == RT_EOK);
- return au32RNGValue[0] ^ au32RNGValue[1];
- }
- #endif
- static rt_err_t nu_aes_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hwcrypto_symmetric_info *symmetric_info)
- {
- uint32_t u32AESOpMode;
- uint32_t u32AESKeySize;
- unsigned char *in, *out;
- unsigned char in_align_flag = 0;
- unsigned char out_align_flag = 0;
- unsigned char iv_temp[16];
- RT_ASSERT(symmetric_ctx != RT_NULL);
- RT_ASSERT(symmetric_info != RT_NULL);
- if ((symmetric_info->length % 4) != 0)
- {
- return -RT_EINVAL;
- }
- //Checking key length
- if (symmetric_ctx->key_bitlen == 128)
- {
- u32AESKeySize = AES_KEY_SIZE_128;
- }
- else if (symmetric_ctx->key_bitlen == 192)
- {
- u32AESKeySize = AES_KEY_SIZE_192;
- }
- else if (symmetric_ctx->key_bitlen == 256)
- {
- u32AESKeySize = AES_KEY_SIZE_256;
- }
- else
- {
- return -RT_EINVAL;
- }
- //Select AES operation mode
- switch (symmetric_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK))
- {
- case HWCRYPTO_TYPE_AES_ECB:
- u32AESOpMode = AES_MODE_ECB;
- break;
- case HWCRYPTO_TYPE_AES_CBC:
- u32AESOpMode = AES_MODE_CBC;
- break;
- case HWCRYPTO_TYPE_AES_CFB:
- u32AESOpMode = AES_MODE_CFB;
- break;
- case HWCRYPTO_TYPE_AES_OFB:
- u32AESOpMode = AES_MODE_OFB;
- break;
- case HWCRYPTO_TYPE_AES_CTR:
- u32AESOpMode = AES_MODE_CTR;
- break;
- default :
- return -RT_ERROR;
- }
- in = (unsigned char *)symmetric_info->in;
- out = (unsigned char *)symmetric_info->out;
- //Checking in/out data buffer address not alignment or out of SRAM
- if (((rt_uint32_t)in % 4) != 0 || ((rt_uint32_t)in < SRAM_BASE) || ((rt_uint32_t)in > SRAM_END))
- {
- in = rt_malloc(symmetric_info->length);
- if (in == RT_NULL)
- {
- LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, symmetric_info->length);
- return -RT_ENOMEM;
- }
- rt_memcpy(in, symmetric_info->in, symmetric_info->length);
- in_align_flag = 1;
- }
- if (((rt_uint32_t)out % 4) != 0 || ((rt_uint32_t)out < SRAM_BASE) || ((rt_uint32_t)out > SRAM_END))
- {
- out = rt_malloc(symmetric_info->length);
- if (out == RT_NULL)
- {
- if (in_align_flag)
- rt_free(in);
- LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, symmetric_info->length);
- return -RT_ENOMEM;
- }
- out_align_flag = 1;
- }
- if ((u32AESOpMode == AES_MODE_CBC) && (symmetric_info->mode == HWCRYPTO_MODE_DECRYPT))
- {
- uint32_t loop;
- loop = (symmetric_info->length - 1) / 16;
- rt_memcpy(iv_temp, in + (loop * 16), 16);
- }
- nu_aes_crypt_run(symmetric_info->mode == HWCRYPTO_MODE_ENCRYPT ? TRUE : FALSE, u32AESOpMode, symmetric_ctx->key, u32AESKeySize, symmetric_ctx->iv, in, out, symmetric_info->length);
- if (u32AESOpMode == AES_MODE_CBC)
- {
- if (symmetric_info->mode == HWCRYPTO_MODE_DECRYPT)
- {
- rt_memcpy(symmetric_ctx->iv, iv_temp, 16);
- }
- else
- {
- uint32_t loop;
- loop = (symmetric_info->length - 1) / 16;
- rt_memcpy(symmetric_ctx->iv, out + (loop * 16), 16);
- }
- }
- if (out_align_flag)
- {
- rt_memcpy(symmetric_info->out, out, symmetric_info->length);
- rt_free(out);
- }
- if (in_align_flag)
- {
- rt_free(in);
- }
- return RT_EOK;
- }
- static rt_err_t nu_des_crypt_run(
- rt_bool_t bEncrypt,
- uint32_t u32OpMode,
- uint8_t *pu8Key,
- uint32_t u32KeySize,
- uint8_t *pu8IV,
- uint8_t *pu8InData,
- uint8_t *pu8OutData,
- uint32_t u32DataLen
- )
- {
- rt_err_t result;
- uint32_t au32SwapKey[3][2];
- uint32_t au32SwapIV[2];
- au32SwapKey[0][0] = nu_get32_be(&pu8Key[0]);
- au32SwapKey[0][1] = nu_get32_be(&pu8Key[4]);
- au32SwapKey[1][0] = nu_get32_be(&pu8Key[8]);
- au32SwapKey[1][1] = nu_get32_be(&pu8Key[12]);
- if (u32KeySize == NU_HWCRYPTO_DES_3KEYS)
- {
- au32SwapKey[2][0] = nu_get32_be(&pu8Key[16]);
- au32SwapKey[2][1] = nu_get32_be(&pu8Key[20]);
- }
- au32SwapIV[0] = nu_get32_be(&pu8IV[0]);
- au32SwapIV[1] = nu_get32_be(&pu8IV[4]);
- result = rt_mutex_take(&s_TDES_mutex, RT_WAITING_FOREVER);
- RT_ASSERT(result == RT_EOK);
- //Using Channel 0
- TDES_Open(CRPT, 0, bEncrypt, (u32OpMode & CRPT_TDES_CTL_TMODE_Msk), u32KeySize, u32OpMode, TDES_IN_OUT_WHL_SWAP);
- TDES_SetKey(CRPT, 0, au32SwapKey);
- TDES_SetInitVect(CRPT, 0, au32SwapIV[0], au32SwapIV[1]);
- //Setup TDES DMA
- TDES_SetDMATransfer(CRPT, 0, (uint32_t)pu8InData, (uint32_t)pu8OutData, u32DataLen);
- TDES_CLR_INT_FLAG(CRPT);
- //Start TDES encryption/decryption
- TDES_Start(CRPT, 0, CRYPTO_DMA_ONE_SHOT);
- /* Wait done */
- while (!(CRPT->INTSTS & CRPT_INTEN_TDESIEN_Msk)) {};
- result = rt_mutex_release(&s_TDES_mutex);
- RT_ASSERT(result == RT_EOK);
- return RT_EOK;
- }
- static rt_err_t nu_des_crypt(struct hwcrypto_symmetric *symmetric_ctx, struct hwcrypto_symmetric_info *symmetric_info)
- {
- uint32_t u32DESOpMode;
- uint32_t u32DESKeySize;
- unsigned char *in, *out;
- unsigned char in_align_flag = 0;
- unsigned char out_align_flag = 0;
- if ((symmetric_info->length % 8) != 0)
- {
- return -RT_EINVAL;
- }
- //Checking key length
- if (symmetric_ctx->key_bitlen == 128 || symmetric_ctx->key_bitlen == 64)
- {
- u32DESKeySize = NU_HWCRYPTO_DES_NO3KEYS;
- }
- else if (symmetric_ctx->key_bitlen == 192)
- {
- u32DESKeySize = NU_HWCRYPTO_DES_3KEYS;
- }
- else
- {
- return -RT_EINVAL;
- }
- //Select DES operation mode
- switch (symmetric_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK))
- {
- case HWCRYPTO_TYPE_DES_ECB:
- u32DESOpMode = DES_MODE_ECB;
- break;
- case HWCRYPTO_TYPE_DES_CBC:
- u32DESOpMode = DES_MODE_CBC;
- break;
- case HWCRYPTO_TYPE_3DES_ECB:
- u32DESOpMode = TDES_MODE_ECB;
- break;
- case HWCRYPTO_TYPE_3DES_CBC:
- u32DESOpMode = TDES_MODE_CBC;
- break;
- default :
- return -RT_ERROR;
- }
- in = (unsigned char *)symmetric_info->in;
- out = (unsigned char *)symmetric_info->out;
- //Checking in/out data buffer address not alignment or out of SRAM
- if (((rt_uint32_t)in % 4) != 0 || ((rt_uint32_t)in < SRAM_BASE) || ((rt_uint32_t)in > SRAM_END))
- {
- in = rt_malloc(symmetric_info->length);
- if (in == RT_NULL)
- {
- LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, symmetric_info->length);
- return -RT_ENOMEM;
- }
- rt_memcpy(in, symmetric_info->in, symmetric_info->length);
- in_align_flag = 1;
- }
- if (((rt_uint32_t)out % 4) != 0 || ((rt_uint32_t)out < SRAM_BASE) || ((rt_uint32_t)out > SRAM_END))
- {
- out = rt_malloc(symmetric_info->length);
- if (out == RT_NULL)
- {
- if (in_align_flag)
- rt_free(in);
- LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, symmetric_info->length);
- return -RT_ENOMEM;
- }
- out_align_flag = 1;
- }
- nu_des_crypt_run(symmetric_info->mode == HWCRYPTO_MODE_ENCRYPT ? TRUE : FALSE, u32DESOpMode, symmetric_ctx->key, u32DESKeySize, symmetric_ctx->iv, in, out, symmetric_info->length);
- if (out_align_flag)
- {
- rt_memcpy(symmetric_info->out, out, symmetric_info->length);
- rt_free(out);
- }
- if (in_align_flag)
- {
- rt_free(in);
- }
- return RT_EOK;
- }
- #define CRPT_HMAC_CTL_DMAFIRST_Pos (4) /*!< CRPT_T::HMAC_CTL: DMAFIRST Position */
- #define CRPT_HMAC_CTL_DMAFIRST_Msk (0x1ul << CRPT_HMAC_CTL_DMAFIRST_Pos) /*!< CRPT_T::HMAC_CTL: DMAFIRST Mask */
- static void SHABlockUpdate(uint32_t u32OpMode, uint32_t u32SrcAddr, uint32_t u32Len, uint32_t u32Mode)
- {
- SHA_Open(CRPT, u32OpMode, SHA_IN_OUT_SWAP, 0);
- //Setup SHA DMA
- SHA_SetDMATransfer(CRPT, u32SrcAddr, u32Len);
- if (u32Mode == CRYPTO_DMA_FIRST)
- {
- if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0)
- {
- //M480MD version
- u32Mode = CRYPTO_DMA_CONTINUE;
- }
- else
- {
- //M480LD version
- CRPT->HMAC_CTL |= CRPT_HMAC_CTL_DMAFIRST_Msk;
- }
- }
- else
- {
- if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) != 0x0)
- {
- //M480LD version
- CRPT->HMAC_CTL &= ~CRPT_HMAC_CTL_DMAFIRST_Msk;
- }
- }
- //Start SHA
- SHA_CLR_INT_FLAG(CRPT);
- SHA_Start(CRPT, u32Mode);
- /* Wait done */
- while (!(CRPT->INTSTS & CRPT_INTSTS_HMACIF_Msk)) {};
- if (CRPT->INTSTS & (CRPT_INTSTS_HMACEIF_Msk) || (CRPT->HMAC_STS & (CRPT_HMAC_STS_DMAERR_Msk)))
- rt_kprintf("SHA ERROR - CRPT->INTSTS-%08x, CRPT->HMAC_STS-%08x\n", CRPT->INTSTS, CRPT->HMAC_STS);
- /* Clear SHA interrupt status */
- SHA_CLR_INT_FLAG(CRPT);
- }
- static rt_err_t nu_sha_hash_run(
- S_SHA_CONTEXT *psSHACtx,
- uint32_t u32OpMode,
- uint8_t *pu8InData,
- uint32_t u32DataLen
- )
- {
- rt_err_t result;
- RT_ASSERT(psSHACtx != RT_NULL);
- RT_ASSERT(pu8InData != RT_NULL);
- result = rt_mutex_take(&s_SHA_mutex, RT_WAITING_FOREVER);
- RT_ASSERT(result == RT_EOK);
- uint8_t *pu8SrcAddr = (uint8_t *)pu8InData;
- uint32_t u32CopyLen = 0;
- while ((psSHACtx->u32SHATempBufLen + u32DataLen) > psSHACtx->u32BlockSize)
- {
- if (psSHACtx->pu8SHATempBuf)
- {
- if (psSHACtx->u32SHATempBufLen == psSHACtx->u32BlockSize)
- {
- //Trigger SHA block update
- SHABlockUpdate(u32OpMode, (uint32_t)psSHACtx->pu8SHATempBuf, psSHACtx->u32BlockSize, psSHACtx->u32DMAMode);
- psSHACtx->u32DMAMode = CRYPTO_DMA_CONTINUE;
- //free SHATempBuff
- rt_free(psSHACtx->pu8SHATempBuf);
- psSHACtx->pu8SHATempBuf = NULL;
- psSHACtx->u32SHATempBufLen = 0;
- continue;
- }
- else
- {
- u32CopyLen = psSHACtx->u32BlockSize - psSHACtx->u32SHATempBufLen;
- if (u32DataLen < u32CopyLen)
- u32CopyLen = u32DataLen;
- rt_memcpy(psSHACtx->pu8SHATempBuf + psSHACtx->u32SHATempBufLen, pu8SrcAddr, u32CopyLen);
- psSHACtx->u32SHATempBufLen += u32CopyLen;
- pu8SrcAddr += u32CopyLen;
- u32DataLen -= u32CopyLen;
- continue;
- }
- }
- if ((uint32_t) pu8SrcAddr & 3) //address not aligned 4
- {
- psSHACtx->pu8SHATempBuf = rt_malloc(psSHACtx->u32BlockSize);
- if (psSHACtx->pu8SHATempBuf == RT_NULL)
- {
- LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize);
- result = rt_mutex_release(&s_SHA_mutex);
- RT_ASSERT(result == RT_EOK);
- return -RT_ENOMEM;
- }
- rt_memcpy(psSHACtx->pu8SHATempBuf, pu8SrcAddr, psSHACtx->u32BlockSize);
- psSHACtx->u32SHATempBufLen = psSHACtx->u32BlockSize;
- pu8SrcAddr += psSHACtx->u32BlockSize;
- u32DataLen -= psSHACtx->u32BlockSize;
- continue;
- }
- //Trigger SHA block update
- SHABlockUpdate(u32OpMode, (uint32_t)pu8SrcAddr, psSHACtx->u32BlockSize, psSHACtx->u32DMAMode);
- psSHACtx->u32DMAMode = CRYPTO_DMA_CONTINUE;
- pu8SrcAddr += psSHACtx->u32BlockSize;
- u32DataLen -= psSHACtx->u32BlockSize;
- }
- if (u32DataLen)
- {
- if (psSHACtx->pu8SHATempBuf == NULL)
- {
- psSHACtx->pu8SHATempBuf = rt_malloc(psSHACtx->u32BlockSize);
- if (psSHACtx->pu8SHATempBuf == RT_NULL)
- {
- LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, psSHACtx->u32BlockSize);
- result = rt_mutex_release(&s_SHA_mutex);
- RT_ASSERT(result == RT_EOK);
- return -RT_ENOMEM;
- }
- psSHACtx->u32SHATempBufLen = 0;
- }
- rt_memcpy(psSHACtx->pu8SHATempBuf, pu8SrcAddr, u32DataLen);
- psSHACtx->u32SHATempBufLen += u32DataLen;
- }
- result = rt_mutex_release(&s_SHA_mutex);
- RT_ASSERT(result == RT_EOK);
- return RT_EOK;
- }
- static rt_err_t nu_sha_update(struct hwcrypto_hash *hash_ctx, const rt_uint8_t *in, rt_size_t length)
- {
- uint32_t u32SHAOpMode;
- unsigned char *nu_in;
- unsigned char in_align_flag = 0;
- RT_ASSERT(hash_ctx != RT_NULL);
- RT_ASSERT(in != RT_NULL);
- //Select SHA operation mode
- switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK))
- {
- case HWCRYPTO_TYPE_SHA1:
- u32SHAOpMode = SHA_MODE_SHA1;
- break;
- case HWCRYPTO_TYPE_SHA224:
- u32SHAOpMode = SHA_MODE_SHA224;
- break;
- case HWCRYPTO_TYPE_SHA256:
- u32SHAOpMode = SHA_MODE_SHA256;
- break;
- case HWCRYPTO_TYPE_SHA384:
- u32SHAOpMode = SHA_MODE_SHA384;
- break;
- case HWCRYPTO_TYPE_SHA512:
- u32SHAOpMode = SHA_MODE_SHA512;
- break;
- default :
- return -RT_ERROR;
- }
- nu_in = (unsigned char *)in;
- //Checking in data buffer address not alignment or out of SRAM
- if (((rt_uint32_t)nu_in % 4) != 0 || ((rt_uint32_t)nu_in < SRAM_BASE) || ((rt_uint32_t)nu_in > SRAM_END))
- {
- nu_in = rt_malloc(length);
- if (nu_in == RT_NULL)
- {
- LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, length);
- return -RT_ENOMEM;
- }
- rt_memcpy(nu_in, in, length);
- in_align_flag = 1;
- }
- nu_sha_hash_run(hash_ctx->parent.contex, u32SHAOpMode, nu_in, length);
- if (in_align_flag)
- {
- rt_free(nu_in);
- }
- return RT_EOK;
- }
- static rt_err_t nu_sha_finish(struct hwcrypto_hash *hash_ctx, rt_uint8_t *out, rt_size_t length)
- {
- unsigned char *nu_out;
- unsigned char out_align_flag = 0;
- uint32_t u32SHAOpMode;
- S_SHA_CONTEXT *psSHACtx = RT_NULL;
- RT_ASSERT(hash_ctx != RT_NULL);
- RT_ASSERT(out != RT_NULL);
- psSHACtx = hash_ctx->parent.contex;
- //Check SHA Hash value buffer length
- switch (hash_ctx->parent.type & (HWCRYPTO_MAIN_TYPE_MASK | HWCRYPTO_SUB_TYPE_MASK))
- {
- case HWCRYPTO_TYPE_SHA1:
- u32SHAOpMode = SHA_MODE_SHA1;
- if (length < 5UL)
- {
- return -RT_EINVAL;
- }
- break;
- case HWCRYPTO_TYPE_SHA224:
- u32SHAOpMode = SHA_MODE_SHA224;
- if (length < 7UL)
- {
- return -RT_EINVAL;
- }
- break;
- case HWCRYPTO_TYPE_SHA256:
- u32SHAOpMode = SHA_MODE_SHA256;
- if (length < 8UL)
- {
- return -RT_EINVAL;
- }
- break;
- case HWCRYPTO_TYPE_SHA384:
- u32SHAOpMode = SHA_MODE_SHA384;
- if (length < 12UL)
- {
- return -RT_EINVAL;
- }
- break;
- case HWCRYPTO_TYPE_SHA512:
- u32SHAOpMode = SHA_MODE_SHA512;
- if (length < 16UL)
- {
- return -RT_EINVAL;
- }
- break;
- default :
- return -RT_ERROR;
- }
- nu_out = (unsigned char *)out;
- //Checking out data buffer address alignment or not
- if (((rt_uint32_t)nu_out % 4) != 0)
- {
- nu_out = rt_malloc(length);
- if (nu_out == RT_NULL)
- {
- LOG_E("fun[%s] memory allocate %d bytes failed!", __FUNCTION__, length);
- return -RT_ENOMEM;
- }
- out_align_flag = 1;
- }
- if (psSHACtx->pu8SHATempBuf)
- {
- if (psSHACtx->u32DMAMode == CRYPTO_DMA_FIRST)
- SHABlockUpdate(u32SHAOpMode, (uint32_t)psSHACtx->pu8SHATempBuf, psSHACtx->u32SHATempBufLen, CRYPTO_DMA_ONE_SHOT);
- else
- SHABlockUpdate(u32SHAOpMode, (uint32_t)psSHACtx->pu8SHATempBuf, psSHACtx->u32SHATempBufLen, CRYPTO_DMA_LAST);
- //free SHATempBuf
- rt_free(psSHACtx->pu8SHATempBuf);
- psSHACtx->pu8SHATempBuf = RT_NULL;
- psSHACtx->u32SHATempBufLen = 0;
- }
- else
- {
- SHABlockUpdate(u32SHAOpMode, (uint32_t)NULL, 0, CRYPTO_DMA_LAST);
- }
- SHA_Read(CRPT, (uint32_t *)nu_out);
- if (out_align_flag)
- {
- rt_memcpy(out, nu_out, length);
- rt_free(nu_out);
- }
- return RT_EOK;
- }
- #if !defined(BSP_USING_TRNG)
- static rt_uint32_t nu_prng_rand(struct hwcrypto_rng *ctx)
- {
- return nu_prng_run();
- }
- #endif
- static const struct hwcrypto_symmetric_ops nu_aes_ops =
- {
- .crypt = nu_aes_crypt,
- };
- static const struct hwcrypto_symmetric_ops nu_des_ops =
- {
- .crypt = nu_des_crypt,
- };
- static const struct hwcrypto_hash_ops nu_sha_ops =
- {
- .update = nu_sha_update,
- .finish = nu_sha_finish,
- };
- #endif
- /* CRC operation ------------------------------------------------------------*/
- #if defined(BSP_USING_CRC)
- static const struct hwcrypto_crc_ops nu_crc_ops =
- {
- .update = nu_crc_update,
- };
- #endif
- /* TRNG operation ------------------------------------------------------------*/
- #if defined(BSP_USING_TRNG)
- static const struct hwcrypto_rng_ops nu_rng_ops =
- {
- .update = nu_trng_rand,
- };
- #elif defined(BSP_USING_CRYPTO)
- static const struct hwcrypto_rng_ops nu_rng_ops =
- {
- .update = nu_prng_rand,
- };
- #endif
- /* Register crypto interface ----------------------------------------------------------*/
- static rt_err_t nu_hwcrypto_create(struct rt_hwcrypto_ctx *ctx)
- {
- rt_err_t res = RT_EOK;
- RT_ASSERT(ctx != RT_NULL);
- switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK)
- {
- #if defined(BSP_USING_TRNG)
- case HWCRYPTO_TYPE_RNG:
- {
- ctx->contex = RT_NULL;
- //Setup RNG operation
- ((struct hwcrypto_rng *)ctx)->ops = &nu_rng_ops;
- break;
- }
- #endif /* BSP_USING_TRNG */
- #if defined(BSP_USING_CRC)
- case HWCRYPTO_TYPE_CRC:
- {
- ctx->contex = RT_NULL;
- //Setup CRC operation
- ((struct hwcrypto_crc *)ctx)->ops = &nu_crc_ops;
- break;
- }
- #endif /* BSP_USING_CRC */
- #if defined(BSP_USING_CRYPTO)
- case HWCRYPTO_TYPE_AES:
- {
- ctx->contex = RT_NULL;
- //Setup AES operation
- ((struct hwcrypto_symmetric *)ctx)->ops = &nu_aes_ops;
- break;
- }
- case HWCRYPTO_TYPE_DES:
- case HWCRYPTO_TYPE_3DES:
- {
- ctx->contex = RT_NULL;
- //Setup operation
- ((struct hwcrypto_symmetric *)ctx)->ops = &nu_des_ops;
- break;
- }
- case HWCRYPTO_TYPE_SHA1:
- case HWCRYPTO_TYPE_SHA2:
- {
- ctx->contex = rt_malloc(sizeof(S_SHA_CONTEXT));
- if (ctx->contex == RT_NULL)
- return -RT_ERROR;
- rt_memset(ctx->contex, 0, sizeof(S_SHA_CONTEXT));
- //Setup operation
- ((struct hwcrypto_hash *)ctx)->ops = &nu_sha_ops;
- break;
- }
- #if !defined(BSP_USING_TRNG)
- case HWCRYPTO_TYPE_RNG:
- {
- ctx->contex = RT_NULL;
- ((struct hwcrypto_rng *)ctx)->ops = &nu_rng_ops;
- #if defined(NU_PRNG_USE_SEED)
- nu_prng_open(NU_PRNG_SEED_VALUE);
- #else
- nu_prng_open(rt_tick_get());
- #endif
- break;
- }
- #endif /* !BSP_USING_TRNG */
- #endif /* BSP_USING_CRYPTO */
- default:
- res = -RT_ERROR;
- break;
- }
- nu_hwcrypto_reset(ctx);
- return res;
- }
- static void nu_hwcrypto_destroy(struct rt_hwcrypto_ctx *ctx)
- {
- RT_ASSERT(ctx != RT_NULL);
- if (ctx->contex)
- rt_free(ctx->contex);
- }
- static rt_err_t nu_hwcrypto_clone(struct rt_hwcrypto_ctx *des, const struct rt_hwcrypto_ctx *src)
- {
- rt_err_t res = RT_EOK;
- RT_ASSERT(des != RT_NULL);
- RT_ASSERT(src != RT_NULL);
- if (des->contex && src->contex)
- {
- rt_memcpy(des->contex, src->contex, sizeof(struct rt_hwcrypto_ctx));
- }
- else
- return -RT_EINVAL;
- return res;
- }
- static void nu_hwcrypto_reset(struct rt_hwcrypto_ctx *ctx)
- {
- switch (ctx->type & HWCRYPTO_MAIN_TYPE_MASK)
- {
- #if !defined(BSP_USING_TRNG)
- case HWCRYPTO_TYPE_RNG:
- {
- #if defined(NU_PRNG_USE_SEED)
- nu_prng_open(NU_PRNG_SEED_VALUE);
- #else
- nu_prng_open(rt_tick_get());
- #endif
- break;
- }
- #endif /* !BSP_USING_TRNG */
- #if defined(BSP_USING_CRYPTO)
- case HWCRYPTO_TYPE_SHA1:
- case HWCRYPTO_TYPE_SHA2:
- {
- S_SHA_CONTEXT *psSHACtx = (S_SHA_CONTEXT *)ctx->contex;
- if (psSHACtx->pu8SHATempBuf)
- {
- rt_free(psSHACtx->pu8SHATempBuf);
- }
- psSHACtx->pu8SHATempBuf = RT_NULL;
- psSHACtx->u32SHATempBufLen = 0;
- psSHACtx->u32DMAMode = CRYPTO_DMA_FIRST;
- if ((ctx->type == HWCRYPTO_TYPE_SHA384) || (ctx->type == HWCRYPTO_TYPE_SHA512))
- {
- psSHACtx->u32BlockSize = 128;
- }
- else
- {
- psSHACtx->u32BlockSize = 64;
- }
- break;
- }
- #endif
- default:
- break;
- }
- }
- /* Init and register nu_hwcrypto_dev */
- int nu_hwcrypto_device_init(void)
- {
- rt_err_t result;
- static struct rt_hwcrypto_device nu_hwcrypto_dev;
- nu_hwcrypto_dev.ops = &nu_hwcrypto_ops;
- nu_hwcrypto_dev.id = 0;
- nu_hwcrypto_dev.user_data = &nu_hwcrypto_dev;
- #if defined(BSP_USING_CRYPTO)
- nu_crypto_init();
- #endif
- #if defined(BSP_USING_CRC)
- nu_crc_init();
- #endif
- #if defined(BSP_USING_TRNG)
- nu_trng_init();
- #endif
- /* register hwcrypto operation */
- result = rt_hwcrypto_register(&nu_hwcrypto_dev, RT_HWCRYPTO_DEFAULT_NAME);
- RT_ASSERT(result == RT_EOK);
- return 0;
- }
- INIT_DEVICE_EXPORT(nu_hwcrypto_device_init);
- #endif //#if ((defined(BSP_USING_CRYPTO) || defined(BSP_USING_TRNG) || defined(BSP_USING_CRC)) && defined(RT_USING_HWCRYPTO))
|