308 lines
9.2 KiB
C
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)
|
|
******************************************************************************/
|
|
|