304 lines
8.9 KiB
C
304 lines
8.9 KiB
C
/*
|
|
* Copyright 2017, 2019 NXP
|
|
* All rights reserved.
|
|
*
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "fsl_bee.h"
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
/* Component ID definition, used by tools. */
|
|
#ifndef FSL_COMPONENT_ID
|
|
#define FSL_COMPONENT_ID "platform.drivers.bee"
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
|
|
static void aligned_memcpy(void *dst, const void *src, size_t size)
|
|
{
|
|
register uint32_t *to32 = (uint32_t *)(uint32_t *)dst;
|
|
register const uint32_t *from32 = (const uint32_t *)(const uint32_t *)src;
|
|
|
|
while (size >= sizeof(uint32_t))
|
|
{
|
|
*to32 = *from32;
|
|
size -= sizeof(uint32_t);
|
|
to32++;
|
|
from32++;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* brief Resets BEE module to factory default values.
|
|
*
|
|
* This function performs hardware reset of BEE module. Attributes and keys from software for both regions are cleared.
|
|
*
|
|
* param base BEE peripheral address.
|
|
*/
|
|
void BEE_Init(BEE_Type *base)
|
|
{
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_EnableClock(kCLOCK_Bee);
|
|
#endif
|
|
|
|
base->CTRL = BEE_CTRL_CTRL_SFTRST_N_MASK | BEE_CTRL_CTRL_CLK_EN_MASK;
|
|
}
|
|
|
|
/*!
|
|
* brief Resets BEE module, clears keys for both regions and disables clock to the BEE.
|
|
*
|
|
* This function performs hardware reset of BEE module and disables clocks. Attributes and keys from software for both
|
|
* regions are cleared.
|
|
*
|
|
* param base BEE peripheral address.
|
|
*/
|
|
void BEE_Deinit(BEE_Type *base)
|
|
{
|
|
base->CTRL &=
|
|
~(BEE_CTRL_BEE_ENABLE_MASK | BEE_CTRL_CTRL_SFTRST_N_MASK | BEE_CTRL_CTRL_CLK_EN_MASK | BEE_CTRL_KEY_VALID_MASK);
|
|
|
|
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
|
|
CLOCK_DisableClock(kCLOCK_Bee);
|
|
#endif
|
|
}
|
|
|
|
/*!
|
|
* brief Loads default values to the BEE region configuration structure.
|
|
*
|
|
* Loads default values to the BEE region configuration structure. The default values are as follows:
|
|
* code
|
|
* config->region0Mode = kBEE_AesCtrMode;
|
|
* config->region1Mode = kBEE_AesCtrMode;
|
|
* config->region0AddrOffset = 0U;
|
|
* config->region1AddrOffset = 0U;
|
|
* config->region0SecLevel = kBEE_SecurityLevel3;
|
|
* config->region1SecLevel = kBEE_SecurityLevel3;
|
|
* config->region1Bot = 0U;
|
|
* config->region1Top = 0U;
|
|
* config->accessPermission = kBEE_AccessProtDisabled;
|
|
* config->endianSwapEn = kBEE_EndianSwapEnabled;
|
|
* endcode
|
|
*
|
|
* param config Configuration structure for BEE peripheral.
|
|
*/
|
|
void BEE_GetDefaultConfig(bee_region_config_t *config)
|
|
{
|
|
assert(config);
|
|
|
|
/* Initializes the configure structure to zero. */
|
|
(void)memset(config, 0, sizeof(*config));
|
|
|
|
config->region0Mode = kBEE_AesCtrMode;
|
|
config->region1Mode = kBEE_AesCtrMode;
|
|
config->region0AddrOffset = 0U;
|
|
config->region1AddrOffset = 0U;
|
|
config->region0SecLevel = kBEE_SecurityLevel3;
|
|
config->region1SecLevel = kBEE_SecurityLevel3;
|
|
config->region1Bot = 0U;
|
|
config->region1Top = 0U;
|
|
config->accessPermission = kBEE_AccessProtDisabled;
|
|
config->endianSwapEn = kBEE_EndianSwapEnabled;
|
|
}
|
|
|
|
/*!
|
|
* brief Sets BEE configuration.
|
|
*
|
|
* This function sets BEE peripheral and BEE region settings accorging to given configuration structure.
|
|
*
|
|
* param base BEE peripheral address.
|
|
* param config Configuration structure for BEE.
|
|
*/
|
|
void BEE_SetConfig(BEE_Type *base, const bee_region_config_t *config)
|
|
{
|
|
uint32_t beeCtrlVal;
|
|
bool reenable = false;
|
|
|
|
/* Wait until BEE is in idle state */
|
|
while (0U == (BEE_GetStatusFlags(base) & (uint32_t)kBEE_IdleFlag))
|
|
{
|
|
}
|
|
|
|
/* Disable BEE before region configuration in case it is enabled. */
|
|
if ((base->CTRL & BEE_CTRL_BEE_ENABLE_MASK) != 0U)
|
|
{
|
|
BEE_Disable(base);
|
|
reenable = true;
|
|
}
|
|
|
|
/* Preserve CTRL bit values that are not set by this function */
|
|
beeCtrlVal = base->CTRL & 0xFFFF0037U;
|
|
|
|
/* Set variable according to configuration */
|
|
beeCtrlVal |= BEE_CTRL_AC_PROT_EN(config->accessPermission) | BEE_CTRL_LITTLE_ENDIAN(config->endianSwapEn) |
|
|
BEE_CTRL_SECURITY_LEVEL_R0(config->region0SecLevel) | BEE_CTRL_CTRL_AES_MODE_R0(config->region0Mode) |
|
|
BEE_CTRL_SECURITY_LEVEL_R1(config->region1SecLevel) | BEE_CTRL_CTRL_AES_MODE_R1(config->region1Mode);
|
|
|
|
/* Load values to registers */
|
|
base->CTRL = beeCtrlVal;
|
|
base->ADDR_OFFSET0 = config->region0AddrOffset;
|
|
base->ADDR_OFFSET1 = config->region1AddrOffset;
|
|
base->REGION1_BOT = config->region1Bot;
|
|
base->REGION1_TOP = config->region1Top;
|
|
|
|
/* Reenable BEE if it was enabled before. */
|
|
if (reenable)
|
|
{
|
|
BEE_Enable(base);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* brief Loads the AES key for selected region into BEE key registers.
|
|
*
|
|
* This function loads given AES key to BEE register for the given region.
|
|
* The key must be 32-bit aligned and stored in little-endian format.
|
|
*
|
|
* Please note, that eFuse BEE_KEYx_SEL must be set accordingly to be able to load and use key loaded in BEE registers.
|
|
* Otherwise, key cannot loaded and BEE will use key from OTPMK or SW_GP2.
|
|
*
|
|
* param base BEE peripheral address.
|
|
* param region Selection of the BEE region to be configured.
|
|
* param key AES key (in little-endian format).
|
|
* param keySize Size of AES key.
|
|
*/
|
|
status_t BEE_SetRegionKey(BEE_Type *base, bee_region_t region, const uint8_t *key, size_t keySize)
|
|
{
|
|
bool redisable = false;
|
|
|
|
/* Key must be 32-bit aligned */
|
|
if ((0U != ((uintptr_t)key & 0x3u)) || (keySize != 16U))
|
|
{
|
|
return kStatus_InvalidArgument;
|
|
}
|
|
|
|
/* Wait until BEE is in idle state */
|
|
while (0U == (BEE_GetStatusFlags(base) & (uint32_t)kBEE_IdleFlag))
|
|
{
|
|
}
|
|
|
|
/* Clear KEY_VALID bit before new key is loaded */
|
|
base->CTRL &= ~BEE_CTRL_KEY_VALID_MASK;
|
|
|
|
/* Write key registers, key is stored in little-endian format in memory */
|
|
aligned_memcpy((uint32_t *)(uint32_t)&base->AES_KEY0_W0, key, keySize);
|
|
|
|
/* Enable BEE before key configuration. */
|
|
if (0U == (base->CTRL & BEE_CTRL_BEE_ENABLE_MASK))
|
|
{
|
|
BEE_Enable(base);
|
|
redisable = true;
|
|
}
|
|
|
|
if (region == kBEE_Region0)
|
|
{
|
|
base->CTRL &= ~BEE_CTRL_KEY_REGION_SEL_MASK;
|
|
}
|
|
|
|
else if (region == kBEE_Region1)
|
|
{
|
|
base->CTRL |= BEE_CTRL_KEY_REGION_SEL_MASK;
|
|
}
|
|
|
|
else
|
|
{
|
|
return kStatus_InvalidArgument;
|
|
}
|
|
|
|
/* Set KEY_VALID bit to trigger key loading */
|
|
base->CTRL |= BEE_CTRL_KEY_VALID_MASK;
|
|
/* Wait until key is ready */
|
|
while (0U == (base->CTRL & BEE_CTRL_KEY_VALID_MASK))
|
|
{
|
|
}
|
|
|
|
/* Redisable BEE if it was disabled before this function call. */
|
|
if (redisable)
|
|
{
|
|
BEE_Disable(base);
|
|
}
|
|
|
|
return kStatus_Success;
|
|
}
|
|
|
|
/*!
|
|
* brief Loads the nonce for selected region into BEE nonce registers.
|
|
*
|
|
* This function loads given nonce(only AES CTR mode) to BEE register for the given region.
|
|
* The nonce must be 32-bit aligned and stored in little-endian format.
|
|
*
|
|
* param base BEE peripheral address.
|
|
* param region Selection of the BEE region to be configured.
|
|
* param nonce AES nonce (in little-endian format).
|
|
* param nonceSize Size of AES nonce.
|
|
*/
|
|
status_t BEE_SetRegionNonce(BEE_Type *base, bee_region_t region, const uint8_t *nonce, size_t nonceSize)
|
|
{
|
|
/* Nonce must be 32-bit aligned */
|
|
if ((0U != ((uintptr_t)nonce & 0x3u)) || (nonceSize != 16U))
|
|
{
|
|
return kStatus_InvalidArgument;
|
|
}
|
|
|
|
/* Wait until BEE is in idle state */
|
|
while (0U == (BEE_GetStatusFlags(base) & (uint32_t)kBEE_IdleFlag))
|
|
{
|
|
}
|
|
|
|
/* Write nonce registers, nonce is stored in little-endian format in memory */
|
|
if (region == kBEE_Region0)
|
|
{
|
|
aligned_memcpy((uint32_t *)(uint32_t)&base->CTR_NONCE0_W0, nonce, nonceSize);
|
|
}
|
|
|
|
else if (region == kBEE_Region1)
|
|
{
|
|
aligned_memcpy((uint32_t *)(uint32_t)&base->CTR_NONCE1_W0, nonce, nonceSize);
|
|
}
|
|
|
|
else
|
|
{
|
|
return kStatus_InvalidArgument;
|
|
}
|
|
|
|
return kStatus_Success;
|
|
}
|
|
|
|
/*!
|
|
* brief Gets the BEE status flags.
|
|
*
|
|
* This function returns status of BEE peripheral.
|
|
*
|
|
* param base BEE peripheral address.
|
|
*
|
|
* return The status flags. This is the logical OR of members of the
|
|
* enumeration ::bee_status_flags_t
|
|
*/
|
|
uint32_t BEE_GetStatusFlags(BEE_Type *base)
|
|
{
|
|
return base->STATUS;
|
|
}
|
|
|
|
/*!
|
|
* brief Clears the BEE status flags.
|
|
*
|
|
* param base BEE peripheral base address.
|
|
* param mask The status flags to clear. This is a logical OR of members of the
|
|
* enumeration ::bee_status_flags_t
|
|
*/
|
|
void BEE_ClearStatusFlags(BEE_Type *base, uint32_t mask)
|
|
{
|
|
/* w1c */
|
|
base->STATUS |= mask;
|
|
}
|