rt-thread/bsp/nuvoton/libraries/m2354/StdDriver/src/nu_keystore.c

562 lines
17 KiB
C
Raw Normal View History

/**************************************************************************//**
* @file keystore.c
* @version V3.00
* @brief Key store driver source file
*
* @copyright SPDX-License-Identifier: Apache-2.0
* @copyright Copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include "NuMicro.h"
/** @addtogroup Standard_Driver Standard Driver
@{
*/
/** @addtogroup KS_Driver Key Store Driver
@{
*/
/** @addtogroup KS_EXPORTED_FUNCTIONS Key Store Exported Functions
@{
*/
/**
* @brief Initial key store
* @return None
* @details This function is used to initial the key store.
* It is necessary to be called before using other APIs of Key Store.
*/
void KS_Open(void)
{
if((KS->STS & KS_STS_INITDONE_Msk) == 0)
{
/* Waiting for busy */
while(KS->STS & KS_STS_BUSY_Msk) {}
/* Start Key Store Initial */
KS->CTL = KS_CTL_INIT_Msk | KS_CTL_START_Msk;
/* Waiting for initilization */
while((KS->STS & KS_STS_INITDONE_Msk) == 0);
}
/* Waiting busy to make sure KS is ready. */
while(KS->STS & KS_STS_BUSY_Msk);
}
/**
* @brief Read key from key store
* @param[in] eType The memory type. It could be:
\ref KS_SRAM
\ref KS_FLASH
\ref KS_OTP
* @param[in] i32KeyIdx The key index to read
* @param[out] au32Key The buffer to store the key
* @param[in] u32WordCnt The word (32-bit) count of the key buffer size
* @retval 0 Successful
* @retval -1 Fail
* @details This function is used to read the key.
*/
int32_t KS_Read(KS_MEM_Type eType, int32_t i32KeyIdx, uint32_t au32Key[], uint32_t u32WordCnt)
{
int32_t i32Cnt;
uint32_t u32Cont;
int32_t offset, i, cnt;
/* Just return when key store is in busy */
if(KS->STS & KS_STS_BUSY_Msk)
return -1;
/* Specify the key address */
KS->METADATA = ((uint32_t)eType << KS_METADATA_DST_Pos) | KS_TOMETAKEY(i32KeyIdx);
/* Clear error flag */
KS->STS = KS_STS_EIF_Msk;
offset = 0;
u32Cont = 0;
i32Cnt = (int32_t)u32WordCnt;
do
{
/* Clear Status */
KS->STS = KS_STS_EIF_Msk | KS_STS_IF_Msk;
/* Trigger to read the key */
KS->CTL = u32Cont | KS_OP_READ | KS_CTL_START_Msk | (KS->CTL & (KS_CTL_SILENT_Msk | KS_CTL_SCMB_Msk));
/* Waiting for key store processing */
while(KS->STS & KS_STS_BUSY_Msk);
/* Read the key to key buffer */
cnt = i32Cnt;
if(cnt > 8)
cnt = 8;
for(i = 0; i < cnt; i++)
{
au32Key[offset + i] = KS->KEY[i];
//printf("R[%d]:0x%08x\n", i, au32Key[offset+i]);
}
u32Cont = KS_CTL_CONT_Msk;
i32Cnt -= 8;
offset += 8;
}
while(i32Cnt > 0);
/* Check error flag */
if(KS->STS & KS_STS_EIF_Msk)
return -1;
return 0;
}
/**
* @brief Get the word count of the specified Metadata key length
* @param[in] u32Meta The metadata define of the key length. It could be
\ref KS_META_128
\ref KS_META_163
\ref KS_META_192
\ref KS_META_224
\ref KS_META_233
\ref KS_META_255
\ref KS_META_256
\ref KS_META_283
\ref KS_META_384
\ref KS_META_409
\ref KS_META_512
\ref KS_META_521
\ref KS_META_571
\ref KS_META_1024
\ref KS_META_2048
\ref KS_META_4096
* @return The word (32-bit) count of the key
* @details This function is used to get word counts of the specified metadata key length.
* It could be used to know how may words needs to allocate for the key.
*/
uint32_t KS_GetKeyWordCnt(uint32_t u32Meta)
{
const uint16_t au8CntTbl[21] = { 4, 6, 6, 7, 8, 8, 8, 9, 12, 13, 16, 17, 18, 0, 0, 0, 32, 48, 64, 96, 128 };
return au8CntTbl[((u32Meta & KS_METADATA_SIZE_Msk) >> KS_METADATA_SIZE_Pos)];
}
/**
* @brief Write key to key store
* @param[in] eType The memory type. It could be:
\ref KS_SRAM
\ref KS_FLASH
* @param[in] u32Meta The metadata of the key. It could be the combine of
\ref KS_META_AES
\ref KS_META_HMAC
\ref KS_META_RSA_EXP
\ref KS_META_RSA_MID
\ref KS_META_ECC
\ref KS_META_CPU
\ref KS_META_128
\ref KS_META_163
\ref KS_META_192
\ref KS_META_224
\ref KS_META_233
\ref KS_META_255
\ref KS_META_256
\ref KS_META_283
\ref KS_META_384
\ref KS_META_409
\ref KS_META_512
\ref KS_META_521
\ref KS_META_571
\ref KS_META_1024
\ref KS_META_2048
\ref KS_META_4096
\ref KS_META_BOOT
\ref KS_META_READABLE
\ref KS_META_PRIV
\ref KS_META_NONPRIV
\ref KS_META_SECURE
\ref KS_META_NONSECUR
* @param[out] au32Key The buffer to store the key
* @param[in] u32WordCnt The word (32-bit) count of the key buffer size
* @return Index of the key. Failed when index < 0.
* @details This function is used to write a key to key store.
*/
int32_t KS_Write(KS_MEM_Type eType, uint32_t u32Meta, uint32_t au32Key[])
{
int32_t i32Cnt;
uint32_t u32Cont;
int32_t offset, i, cnt;
/* Just return when key store is in busy */
if(KS->STS & KS_STS_BUSY_Msk)
return -1;
/* Specify the key address */
KS->METADATA = (eType << KS_METADATA_DST_Pos) | u32Meta;
/* Get size index */
i32Cnt = (int32_t)KS_GetKeyWordCnt(u32Meta);
/* Invalid key length */
if(i32Cnt == 0)
return -1;
/* OTP only support maximum 256 bits */
if((eType == KS_OTP) && (i32Cnt > 8))
return -1;
/* Clear error flag */
KS->STS = KS_STS_EIF_Msk;
offset = 0;
u32Cont = 0;
do
{
/* Prepare the key to write */
cnt = i32Cnt;
if(cnt > 8)
cnt = 8;
for(i = 0; i < cnt; i++)
{
KS->KEY[i] = au32Key[offset + i];
}
/* Clear Status */
KS->STS = KS_STS_EIF_Msk | KS_STS_IF_Msk;
/* Write the key */
KS->CTL = u32Cont | KS_OP_WRITE | KS_CTL_START_Msk | (KS->CTL & (KS_CTL_SILENT_Msk | KS_CTL_SCMB_Msk));
u32Cont = KS_CTL_CONT_Msk;
i32Cnt -= 8;
offset += 8;
/* Waiting for key store processing */
while(KS->STS & KS_STS_BUSY_Msk);
}
while(i32Cnt > 0);
/* Check error flag */
if(KS->STS & KS_STS_EIF_Msk)
{
//printf("KS_Write. EIF!\n");
return -1;
}
return KS_TOKEYIDX(KS->METADATA);
}
/**
* @brief Erase a key from key store
* @param[in] i32KeyIdx The key index to read
* @retval 0 Successful
* @retval -1 Fail
* @details This function is used to erase a key from SRAM of key store.
*/
int32_t KS_EraseKey(int32_t i32KeyIdx)
{
/* Just return when key store is in busy */
if(KS->STS & KS_STS_BUSY_Msk)
return -1;
/* Clear error flag */
KS->STS = KS_STS_EIF_Msk;
/* Specify the key address */
KS->METADATA = (KS_SRAM << KS_METADATA_DST_Pos) | KS_TOMETAKEY(i32KeyIdx);
/* Clear Status */
KS->STS = KS_STS_EIF_Msk | KS_STS_IF_Msk;
/* Erase the key */
KS->CTL = KS_OP_ERASE | KS_CTL_START_Msk | (KS->CTL & (KS_CTL_SILENT_Msk | KS_CTL_SCMB_Msk));
/* Waiting for processing */
while(KS->STS & KS_STS_BUSY_Msk);
/* Check error flag */
if(KS->STS & KS_STS_EIF_Msk)
return -1;
return 0;
}
/**
* @brief Erase all keys from key store
* @param[in] eType The memory type. It could be:
\ref KS_SRAM
\ref KS_FLASH
\ref KS_OTP
* @param[in] i32KeyIdx The key index to read
* @retval 0 Successful
* @retval -1 Fail
* @details This function is used to erase all keys in SRAM or Flash of key store.
*/
int32_t KS_EraseAll(KS_MEM_Type eType)
{
/* Just return when key store is in busy */
if(KS->STS & KS_STS_BUSY_Msk)
return -1;
/* Clear error flag */
KS->STS = KS_STS_EIF_Msk;
/* Specify the key address */
KS->METADATA = (eType << KS_METADATA_DST_Pos);
/* Clear Status */
KS->STS = KS_STS_EIF_Msk | KS_STS_IF_Msk;
/* Erase the key */
KS->CTL = KS_OP_ERASE_ALL | KS_CTL_START_Msk | (KS->CTL & (KS_CTL_SILENT_Msk | KS_CTL_SCMB_Msk));
/* Waiting for processing */
while(KS->STS & KS_STS_BUSY_Msk);
/* Check error flag */
if(KS->STS & KS_STS_EIF_Msk)
return -1;
return 0;
}
/**
* @brief Revoke a key in key store
* @param[in] eType The memory type. It could be:
\ref KS_SRAM
\ref KS_FLASH
\ref KS_OTP
* @param[in] i32KeyIdx The key index to read
* @retval 0 Successful
* @retval -1 Fail
* @details This function is used to revoke a key in key store.
*/
int32_t KS_RevokeKey(KS_MEM_Type eType, int32_t i32KeyIdx)
{
/* Just return when key store is in busy */
if(KS->STS & KS_STS_BUSY_Msk)
return -1;
/* Clear error flag */
KS->STS = KS_STS_EIF_Msk;
/* Specify the key address */
KS->METADATA = (eType << KS_METADATA_DST_Pos) | KS_TOMETAKEY(i32KeyIdx);
/* Clear Status */
KS->STS = KS_STS_EIF_Msk | KS_STS_IF_Msk;
/* Erase the key */
KS->CTL = KS_OP_REVOKE | KS_CTL_START_Msk | (KS->CTL & (KS_CTL_SILENT_Msk | KS_CTL_SCMB_Msk));
/* Waiting for processing */
while(KS->STS & KS_STS_BUSY_Msk);
/* Check error flag */
if(KS->STS & KS_STS_EIF_Msk)
return -1;
return 0;
}
/**
* @brief Get remain size of specified Key Store memory
* @param[in] eType The memory type. It could be:
\ref KS_SRAM
\ref KS_FLASH
* @retval remain size of specified Key Store memory
* @details This function is used to get remain size of Key Store.
*/
uint32_t KS_GetRemainSize(KS_MEM_Type mem)
{
uint32_t u32Reg;
uint32_t u32SramRemain, u32FlashRemain;
u32Reg = KS->REMAIN;
//printf("KS Remain 0x%08x\n", u32Reg);
//printf("SRAM remain %lu bytes, Flash remain %lu bytes\n",(u32Reg&KS_REMAIN_RRMNG_Msk) >> KS_REMAIN_RRMNG_Pos, (u32Reg&KS_REMAIN_FRMNG_Msk) >> KS_REMAIN_FRMNG_Pos);
u32SramRemain = (u32Reg & KS_REMAIN_RRMNG_Msk) >> KS_REMAIN_RRMNG_Pos;
u32FlashRemain = (u32Reg & KS_REMAIN_FRMNG_Msk) >> KS_REMAIN_FRMNG_Pos;
if(mem == KS_SRAM)
return u32SramRemain;
else
return u32FlashRemain;
}
/**
* @brief Get remain key count of specified Key Store memory
* @param[in] eType The memory type. It could be:
\ref KS_SRAM
\ref KS_FLASH
* @retval Remain key count in the specified key store memory
* @details This function is used to get remain key count in specified key store memory.
*/
uint32_t KS_GetRemainKeyCount(KS_MEM_Type mem)
{
uint32_t u32Reg;
uint32_t u32SramRemain, u32FlashRemain;
u32Reg = KS->REMKCNT;
u32SramRemain = (u32Reg & KS_REMKCNT_RRMKCNT_Msk) >> KS_REMKCNT_RRMKCNT_Pos;
u32FlashRemain = (u32Reg & KS_REMKCNT_FRMKCNT_Msk) >> KS_REMKCNT_FRMKCNT_Pos;
if(mem == KS_SRAM)
return u32SramRemain;
else
return u32FlashRemain;
}
/**
* @brief Write OTP key to key store
* @param[in] i32KeyIdx The OTP key index to store the key. It could be 0~7.
OTP key index 0 is default for ROTPK.
* @param[in] u32Meta The metadata of the key. It could be the combine of
\ref KS_META_AES
\ref KS_META_HMAC
\ref KS_META_RSA_EXP
\ref KS_META_RSA_MID
\ref KS_META_ECC
\ref KS_META_CPU
\ref KS_META_128
\ref KS_META_163
\ref KS_META_192
\ref KS_META_224
\ref KS_META_233
\ref KS_META_255
\ref KS_META_256
\ref KS_META_BOOT
\ref KS_META_READABLE
\ref KS_META_PRIV
\ref KS_META_NONPRIV
\ref KS_META_SECURE
\ref KS_META_NONSECUR
* @param[out] au32Key The buffer to store the key
* @param[in] u32WordCnt The word (32-bit) count of the key buffer size
* @retval 0 Successful
* @retval -1 Fail
* @details This function is used to write a key to OTP key store.
*/
int32_t KS_WriteOTP(int32_t i32KeyIdx, uint32_t u32Meta, uint32_t au32Key[])
{
const uint16_t au8CntTbl[7] = {4, 6, 6, 7, 8, 8, 8};
int32_t i32Cnt;
uint32_t u32Cont;
int32_t offset, i, cnt, sidx;
/* Just return when key store is in busy */
if(KS->STS & KS_STS_BUSY_Msk)
return -1;
/* Specify the key address */
KS->METADATA = ((uint32_t)KS_OTP << KS_METADATA_DST_Pos) | u32Meta | KS_TOMETAKEY(i32KeyIdx);
/* Get size index */
sidx = (u32Meta >> KS_METADATA_SIZE_Pos) & 0xful;
/* OTP only support maximum 256 bits */
if(sidx >= 7)
return -1;
i32Cnt = au8CntTbl[sidx];
/* Clear error flag */
KS->STS = KS_STS_EIF_Msk;
offset = 0;
u32Cont = 0;
do
{
/* Prepare the key to write */
cnt = i32Cnt;
if(cnt > 8)
cnt = 8;
for(i = 0; i < cnt; i++)
{
KS->KEY[i] = au32Key[offset + i];
}
/* Clear Status */
KS->STS = KS_STS_EIF_Msk | KS_STS_IF_Msk;
/* Write the key */
KS->CTL = u32Cont | KS_OP_WRITE | KS_CTL_START_Msk | (KS->CTL & (KS_CTL_SILENT_Msk | KS_CTL_SCMB_Msk));
u32Cont = KS_CTL_CONT_Msk;
i32Cnt -= 8;
offset += 8;
/* Waiting for key store processing */
while(KS->STS & KS_STS_BUSY_Msk);
}
while(i32Cnt > 0);
/* Check error flag */
if(KS->STS & KS_STS_EIF_Msk)
{
//printf("KS_WriteOTP. EIF!\n");
return -1;
}
return i32KeyIdx;
}
/**
* @brief Trigger to inverse the date in KS_SRAM.
* @retval 1 The data in KS SRAM is inverted.
* @retval 0 The data in KS SRAM is non-inverted.
* @retval -1 Fail to invert the date in KS SRAM.
* @details This function is used to trigger anti-remanence procedure by inverse the data in SRAM.
* This won't change the reading key.
*/
int32_t KS_ToggleSRAM(void)
{
/* Just return when key store is in busy */
if(KS->STS & KS_STS_BUSY_Msk)
return -1;
/* Specify the key address */
KS->METADATA = ((uint32_t)KS_SRAM << KS_METADATA_DST_Pos);
/* Clear error flag */
KS->STS = KS_STS_EIF_Msk | KS_STS_IF_Msk;
/* Trigger to do anti-remanence procedure */
KS->CTL = KS_OP_REMAN | KS_CTL_START_Msk;
/* Waiting for key store processing */
while(KS->STS & KS_STS_BUSY_Msk);
/* Check error flag */
if(KS->STS & KS_STS_EIF_Msk)
return -1;
return ((KS->STS & KS_STS_RAMINV_Msk) > 0);
}
/**@}*/ /* end of group KS_EXPORTED_FUNCTIONS */
/**@}*/ /* end of group KS_Driver */
/**@}*/ /* end of group Standard_Driver */