Files
hc32f460_boot/mcu/lib/src/hc32_ll_aes.c
T
2026-04-23 13:49:53 +08:00

308 lines
9.2 KiB
C

/**
*******************************************************************************
* @file hc32_ll_aes.c
* @brief This file provides firmware functions to manage the Advanced Encryption
* Standard(AES).
@verbatim
Change Logs:
Date Author Notes
2022-03-31 CDT First version
2023-06-30 CDT Add API AES_DeInit()
@endverbatim
*******************************************************************************
* Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by XHSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32_ll_aes.h"
#include "hc32_ll_utility.h"
/**
* @addtogroup LL_Driver
* @{
*/
/**
* @defgroup LL_AES AES
* @brief AES Driver Library
* @{
*/
#if (LL_AES_ENABLE == DDL_ON)
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/**
* @defgroup AES_Local_Macros AES Local Macros
* @{
*/
/* Delay count for timeout */
#define AES_TIMEOUT (30000UL)
/* AES block size */
#define AES_BLOCK_SIZE (16U)
/**
* @defgroup AES_Check_Parameters_Validity AES Check Parameters Validity
* @{
*/
#define IS_AES_KEY_SIZE(x) ((x) == AES_KEY_SIZE_16BYTE)
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
* @defgroup AES_Local_Functions AES Local Functions
* @{
*/
/**
* @brief Write the input buffer in data register.
* @param [in] pu8SrcData Point to the source data buffer.
* @retval None
*/
static void AES_WriteData(const uint8_t *pu8SrcData)
{
uint8_t i;
__IO uint32_t *regDR = &CM_AES->DR0;
const uint32_t *pu32Data = (const uint32_t *)((uint32_t)pu8SrcData);
for (i = 0U; i < 4U; i++) {
regDR[i] = pu32Data[i];
}
}
/**
* @brief Read the from data register.
* @param [out] pu8Result Point to the result buffer.
* @retval None
*/
static void AES_ReadData(uint8_t *pu8Result)
{
uint8_t i;
__IO uint32_t *regDR = &CM_AES->DR0;
uint32_t *pu32Result = (uint32_t *)((uint32_t)pu8Result);
for (i = 0U; i < 4U; i++) {
pu32Result[i] = regDR[i];
}
}
/**
* @brief Write the input buffer in key register.
* @param [in] pu8Key Pointer to the key buffer.
* @param [in] u8KeySize AES key size. This parameter can be a value of @ref AES_Key_Size
* @retval None
*/
static void AES_WriteKey(const uint8_t *pu8Key, uint8_t u8KeySize)
{
uint8_t i;
uint8_t u8KeyWordSize = u8KeySize / 4U;
__IO uint32_t *regKR = &CM_AES->KR0;
const uint32_t *pu32Key = (const uint32_t *)((uint32_t)pu8Key);
for (i = 0U; i < u8KeyWordSize; i++) {
regKR[i] = pu32Key[i];
}
}
/**
* @brief Wait AES operation done.
* @param None
* @retval None
*/
static int32_t AES_WaitDone(void)
{
__IO uint32_t u32TimeCount = 0UL;
int32_t i32Ret = LL_OK;
while (bCM_AES->CR_b.START != 0UL) {
if (u32TimeCount++ >= AES_TIMEOUT) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
}
return i32Ret;
}
/**
* @}
*/
/**
* @defgroup AES_Global_Functions AES Global Functions
* @{
*/
/**
* @brief AES encryption.
* @param [in] pu8Plaintext Buffer of the plaintext(the source data which will be encrypted).
* @param [in] u32PlaintextSize Length of plaintext in bytes.
* @param [in] pu8Key Pointer to the AES key.
* @param [in] u8KeySize AES key size. This parameter can be a value of @ref AES_Key_Size
* @param [out] pu8Ciphertext Buffer of the ciphertext.
* @retval int32_t:
* - LL_OK: Encrypt successfully.
* - LL_ERR_INVD_PARAM: Invalid parameter.
* - LL_TIMEOUT: Encrypt timeout.
*/
int32_t AES_Encrypt(const uint8_t *pu8Plaintext, uint32_t u32PlaintextSize,
const uint8_t *pu8Key, uint8_t u8KeySize,
uint8_t *pu8Ciphertext)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
uint32_t u32Index = 0UL;
DDL_ASSERT(IS_AES_KEY_SIZE(u8KeySize));
DDL_ASSERT((u32PlaintextSize % AES_BLOCK_SIZE) == 0U);
if ((pu8Plaintext != NULL) && (u32PlaintextSize > 0UL) && \
(pu8Key != NULL) && (pu8Ciphertext != NULL)) {
AES_WriteKey(pu8Key, u8KeySize);
/* Set AES encrypt. */
WRITE_REG32(bCM_AES->CR_b.MODE, 0UL);
while (u32Index < u32PlaintextSize) {
AES_WriteData(&pu8Plaintext[u32Index]);
/* Start AES calculating. */
WRITE_REG32(bCM_AES->CR_b.START, 1UL);
/* Wait for AES to stop */
i32Ret = AES_WaitDone();
if (i32Ret != LL_OK) {
break;
}
AES_ReadData(&pu8Ciphertext[u32Index]);
u32Index += AES_BLOCK_SIZE;
}
}
return i32Ret;
}
/**
* @brief AES decryption.
* @param [in] pu8Ciphertext Buffer of the Ciphertext(the source data which will be decrypted).
* @param [in] u32CiphertextSize Length of ciphertext in bytes.
* @param [in] pu8Key Pointer to the AES key.
* @param [in] u8KeySize AES key size. This parameter can be a value of @ref AES_Key_Size
* @param [out] pu8Plaintext Buffer of the plaintext.
* @retval int32_t:
* - LL_OK: Decrypt successfully.
* - LL_ERR_INVD_PARAM: Invalid parameter.
* - LL_TIMEOUT: Decrypt timeout.
*/
int32_t AES_Decrypt(const uint8_t *pu8Ciphertext, uint32_t u32CiphertextSize,
const uint8_t *pu8Key, uint8_t u8KeySize,
uint8_t *pu8Plaintext)
{
int32_t i32Ret = LL_ERR_INVD_PARAM;
uint32_t u32Index = 0UL;
DDL_ASSERT(IS_AES_KEY_SIZE(u8KeySize));
DDL_ASSERT((u32CiphertextSize % AES_BLOCK_SIZE) == 0U);
if ((pu8Plaintext != NULL) && (u32CiphertextSize > 0UL) && \
(pu8Key != NULL) && (pu8Ciphertext != NULL)) {
AES_WriteKey(pu8Key, u8KeySize);
/* Set AES decrypt. */
WRITE_REG32(bCM_AES->CR_b.MODE, 1UL);
while (u32Index < u32CiphertextSize) {
AES_WriteData(&pu8Ciphertext[u32Index]);
/* Start AES calculating. */
WRITE_REG32(bCM_AES->CR_b.START, 1UL);
/* Wait for AES to stop */
i32Ret = AES_WaitDone();
if (i32Ret != LL_OK) {
break;
}
AES_ReadData(&pu8Plaintext[u32Index]);
u32Index += AES_BLOCK_SIZE;
}
}
return i32Ret;
}
/**
* @brief De-Initialize AES function.
* @param None
* @retval int32_t:
* - LL_OK: De-Initialize success.
* - LL_ERR_TIMEOUT: Timeout.
*/
int32_t AES_DeInit(void)
{
int32_t i32Ret = LL_OK;
__IO uint32_t u32TimeOut = 0U;
uint8_t i;
__IO uint32_t *regDR = &CM_AES->DR0;
__IO uint32_t *regKR = &CM_AES->KR0;
/* Wait generating done */
while (0UL != READ_REG32(bCM_AES->CR_b.START)) {
u32TimeOut++;
if (u32TimeOut > AES_TIMEOUT) {
i32Ret = LL_ERR_TIMEOUT;
break;
}
}
if (LL_OK == i32Ret) {
/* Configures the registers to reset value. */
WRITE_REG32(CM_AES->CR, 0x00000000UL);
for (i = 0U; i < 4U; i++) {
regDR[i] = 0x00000000UL;
}
for (i = 0U; i < 8U; i++) {
regKR[i] = 0x00000000UL;
}
}
return i32Ret;
}
/**
* @}
*/
#endif /* LL_AES_ENABLE */
/**
* @}
*/
/**
* @}
*/
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/