1 /*
2  * Copyright 2017, 2019 NXP
3  * All rights reserved.
4  *
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_bee.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.bee"
18 #endif
19 
20 /*******************************************************************************
21  * Variables
22  ******************************************************************************/
23 
24 /*******************************************************************************
25  * Code
26  ******************************************************************************/
27 
aligned_memcpy(void * dst,const void * src,size_t size)28 static void aligned_memcpy(void *dst, const void *src, size_t size)
29 {
30     register uint32_t *to32         = (uint32_t *)(uint32_t *)dst;
31     register const uint32_t *from32 = (const uint32_t *)(const uint32_t *)src;
32 
33     while (size >= sizeof(uint32_t))
34     {
35         *to32 = *from32;
36         size -= sizeof(uint32_t);
37         to32++;
38         from32++;
39     }
40 }
41 
42 /*!
43  * brief Resets BEE module to factory default values.
44  *
45  * This function performs hardware reset of BEE module. Attributes and keys from software for both regions are cleared.
46  *
47  * param base BEE peripheral address.
48  */
BEE_Init(BEE_Type * base)49 void BEE_Init(BEE_Type *base)
50 {
51 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
52     CLOCK_EnableClock(kCLOCK_Bee);
53 #endif
54 
55     base->CTRL = BEE_CTRL_CTRL_SFTRST_N_MASK | BEE_CTRL_CTRL_CLK_EN_MASK;
56 }
57 
58 /*!
59  * brief Resets BEE module, clears keys for both regions and disables clock to the BEE.
60  *
61  * This function performs hardware reset of BEE module and disables clocks. Attributes and keys from software for both
62  * regions are cleared.
63  *
64  * param base BEE peripheral address.
65  */
BEE_Deinit(BEE_Type * base)66 void BEE_Deinit(BEE_Type *base)
67 {
68     base->CTRL &=
69         ~(BEE_CTRL_BEE_ENABLE_MASK | BEE_CTRL_CTRL_SFTRST_N_MASK | BEE_CTRL_CTRL_CLK_EN_MASK | BEE_CTRL_KEY_VALID_MASK);
70 
71 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
72     CLOCK_DisableClock(kCLOCK_Bee);
73 #endif
74 }
75 
76 /*!
77  * brief Loads default values to the BEE region configuration structure.
78  *
79  * Loads default values to the BEE region configuration structure. The default values are as follows:
80  * code
81  *   config->region0Mode = kBEE_AesCtrMode;
82  *   config->region1Mode = kBEE_AesCtrMode;
83  *   config->region0AddrOffset = 0U;
84  *   config->region1AddrOffset = 0U;
85  *   config->region0SecLevel = kBEE_SecurityLevel3;
86  *   config->region1SecLevel = kBEE_SecurityLevel3;
87  *   config->region1Bot = 0U;
88  *   config->region1Top = 0U;
89  *   config->accessPermission = kBEE_AccessProtDisabled;
90  *   config->endianSwapEn = kBEE_EndianSwapEnabled;
91  * endcode
92  *
93  * param config Configuration structure for BEE peripheral.
94  */
BEE_GetDefaultConfig(bee_region_config_t * config)95 void BEE_GetDefaultConfig(bee_region_config_t *config)
96 {
97     assert(config);
98 
99     /* Initializes the configure structure to zero. */
100     (void)memset(config, 0, sizeof(*config));
101 
102     config->region0Mode       = kBEE_AesCtrMode;
103     config->region1Mode       = kBEE_AesCtrMode;
104     config->region0AddrOffset = 0U;
105     config->region1AddrOffset = 0U;
106     config->region0SecLevel   = kBEE_SecurityLevel3;
107     config->region1SecLevel   = kBEE_SecurityLevel3;
108     config->region1Bot        = 0U;
109     config->region1Top        = 0U;
110     config->accessPermission  = kBEE_AccessProtDisabled;
111     config->endianSwapEn      = kBEE_EndianSwapEnabled;
112 }
113 
114 /*!
115  * brief Sets BEE configuration.
116  *
117  * This function sets BEE peripheral and BEE region settings accorging to given configuration structure.
118  *
119  * param base BEE peripheral address.
120  * param config Configuration structure for BEE.
121  */
BEE_SetConfig(BEE_Type * base,const bee_region_config_t * config)122 void BEE_SetConfig(BEE_Type *base, const bee_region_config_t *config)
123 {
124     uint32_t beeCtrlVal;
125     bool reenable = false;
126 
127     /* Wait until BEE is in idle state */
128     while (0U == (BEE_GetStatusFlags(base) & (uint32_t)kBEE_IdleFlag))
129     {
130     }
131 
132     /* Disable BEE before region configuration in case it is enabled. */
133     if ((base->CTRL & BEE_CTRL_BEE_ENABLE_MASK) != 0U)
134     {
135         BEE_Disable(base);
136         reenable = true;
137     }
138 
139     /* Preserve CTRL bit values that are not set by this function */
140     beeCtrlVal = base->CTRL & 0xFFFF0037U;
141 
142     /* Set variable according to configuration */
143     beeCtrlVal |= BEE_CTRL_AC_PROT_EN(config->accessPermission) | BEE_CTRL_LITTLE_ENDIAN(config->endianSwapEn) |
144                   BEE_CTRL_SECURITY_LEVEL_R0(config->region0SecLevel) | BEE_CTRL_CTRL_AES_MODE_R0(config->region0Mode) |
145                   BEE_CTRL_SECURITY_LEVEL_R1(config->region1SecLevel) | BEE_CTRL_CTRL_AES_MODE_R1(config->region1Mode);
146 
147     /* Load values to registers */
148     base->CTRL         = beeCtrlVal;
149     base->ADDR_OFFSET0 = config->region0AddrOffset;
150     base->ADDR_OFFSET1 = config->region1AddrOffset;
151     base->REGION1_BOT  = config->region1Bot;
152     base->REGION1_TOP  = config->region1Top;
153 
154     /* Reenable BEE if it was enabled before. */
155     if (reenable)
156     {
157         BEE_Enable(base);
158     }
159 }
160 
161 /*!
162  * brief Loads the AES key for selected region into BEE key registers.
163  *
164  * This function loads given AES key to BEE register for the given region.
165  * The key must be 32-bit aligned and stored in little-endian format.
166  *
167  * Please note, that eFuse BEE_KEYx_SEL must be set accordingly to be able to load and use key loaded in BEE registers.
168  * Otherwise, key cannot loaded and BEE will use key from OTPMK or SW_GP2.
169  *
170  * param base BEE peripheral address.
171  * param region Selection of the BEE region to be configured.
172  * param key AES key (in little-endian format).
173  * param keySize Size of AES key.
174  */
BEE_SetRegionKey(BEE_Type * base,bee_region_t region,const uint8_t * key,size_t keySize)175 status_t BEE_SetRegionKey(BEE_Type *base, bee_region_t region, const uint8_t *key, size_t keySize)
176 {
177     bool redisable = false;
178 
179     /* Key must be 32-bit aligned */
180     if ((0U != ((uintptr_t)key & 0x3u)) || (keySize != 16U))
181     {
182         return kStatus_InvalidArgument;
183     }
184 
185     /* Wait until BEE is in idle state */
186     while (0U == (BEE_GetStatusFlags(base) & (uint32_t)kBEE_IdleFlag))
187     {
188     }
189 
190     /* Clear KEY_VALID bit before new key is loaded */
191     base->CTRL &= ~BEE_CTRL_KEY_VALID_MASK;
192 
193     /* Write key registers, key is stored in little-endian format in memory */
194     aligned_memcpy((uint32_t *)(uint32_t)&base->AES_KEY0_W0, key, keySize);
195 
196     /* Enable BEE before key configuration. */
197     if (0U == (base->CTRL & BEE_CTRL_BEE_ENABLE_MASK))
198     {
199         BEE_Enable(base);
200         redisable = true;
201     }
202 
203     if (region == kBEE_Region0)
204     {
205         base->CTRL &= ~BEE_CTRL_KEY_REGION_SEL_MASK;
206     }
207 
208     else if (region == kBEE_Region1)
209     {
210         base->CTRL |= BEE_CTRL_KEY_REGION_SEL_MASK;
211     }
212 
213     else
214     {
215         return kStatus_InvalidArgument;
216     }
217 
218     /* Set KEY_VALID bit to trigger key loading */
219     base->CTRL |= BEE_CTRL_KEY_VALID_MASK;
220     /* Wait until key is ready */
221     while (0U == (base->CTRL & BEE_CTRL_KEY_VALID_MASK))
222     {
223     }
224 
225     /* Redisable BEE if it was disabled before this function call. */
226     if (redisable)
227     {
228         BEE_Disable(base);
229     }
230 
231     return kStatus_Success;
232 }
233 
234 /*!
235  * brief Loads the nonce for selected region into BEE nonce registers.
236  *
237  * This function loads given nonce(only AES CTR mode) to BEE register for the given region.
238  * The nonce must be 32-bit aligned and stored in little-endian format.
239  *
240  * param base BEE peripheral address.
241  * param region Selection of the BEE region to be configured.
242  * param nonce AES nonce (in little-endian format).
243  * param nonceSize Size of AES nonce.
244  */
BEE_SetRegionNonce(BEE_Type * base,bee_region_t region,const uint8_t * nonce,size_t nonceSize)245 status_t BEE_SetRegionNonce(BEE_Type *base, bee_region_t region, const uint8_t *nonce, size_t nonceSize)
246 {
247     /* Nonce must be 32-bit aligned */
248     if ((0U != ((uintptr_t)nonce & 0x3u)) || (nonceSize != 16U))
249     {
250         return kStatus_InvalidArgument;
251     }
252 
253     /* Wait until BEE is in idle state */
254     while (0U == (BEE_GetStatusFlags(base) & (uint32_t)kBEE_IdleFlag))
255     {
256     }
257 
258     /* Write nonce registers, nonce is stored in little-endian format in memory */
259     if (region == kBEE_Region0)
260     {
261         aligned_memcpy((uint32_t *)(uint32_t)&base->CTR_NONCE0_W0, nonce, nonceSize);
262     }
263 
264     else if (region == kBEE_Region1)
265     {
266         aligned_memcpy((uint32_t *)(uint32_t)&base->CTR_NONCE1_W0, nonce, nonceSize);
267     }
268 
269     else
270     {
271         return kStatus_InvalidArgument;
272     }
273 
274     return kStatus_Success;
275 }
276 
277 /*!
278  * brief Gets the BEE status flags.
279  *
280  * This function returns status of BEE peripheral.
281  *
282  * param base BEE peripheral address.
283  *
284  * return The status flags. This is the logical OR of members of the
285  *         enumeration ::bee_status_flags_t
286  */
BEE_GetStatusFlags(BEE_Type * base)287 uint32_t BEE_GetStatusFlags(BEE_Type *base)
288 {
289     return base->STATUS;
290 }
291 
292 /*!
293  * brief Clears the BEE status flags.
294  *
295  * param base BEE peripheral base address.
296  * param mask The status flags to clear. This is a logical OR of members of the
297  *             enumeration ::bee_status_flags_t
298  */
BEE_ClearStatusFlags(BEE_Type * base,uint32_t mask)299 void BEE_ClearStatusFlags(BEE_Type *base, uint32_t mask)
300 {
301     /* w1c */
302     base->STATUS |= mask;
303 }
304