1 /* USER CODE BEGIN Header */
2 /**
3 ******************************************************************************
4 * @file hw_aes.c
5 * @author MCD Application Team
6 * @brief This file contains the AES driver for STM32WBA
7 ******************************************************************************
8 * @attention
9 *
10 * Copyright (c) 2024 STMicroelectronics.
11 * All rights reserved.
12 *
13 * This software is licensed under terms that can be found in the LICENSE file
14 * in the root directory of this software component.
15 * If no LICENSE file comes with this software, it is provided AS-IS.
16 *
17 ******************************************************************************
18 */
19 /* USER CODE END Header */
20
21 #include "app_common.h"
22 #include "stm32wbaxx_ll_bus.h"
23
24 /*****************************************************************************/
25
26 #define HW_AESX AES
27
28 #define HW_AES_CLOCK_ENABLE( ) LL_AHB2_GRP1_EnableClock( LL_AHB2_GRP1_PERIPH_AES )
29 #define HW_AES_CLOCK_DISABLE( ) LL_AHB2_GRP1_DisableClock( LL_AHB2_GRP1_PERIPH_AES )
30
31 #define HW_AES_CLOCK_IS_ENABLE( ) LL_AHB2_GRP1_IsEnabledClock( LL_AHB2_GRP1_PERIPH_AES )
32
33 /*****************************************************************************/
34
35 typedef struct
36 {
37 uint8_t run;
38 } HW_AES_VAR_T;
39
40 /*****************************************************************************/
41
42 static HW_AES_VAR_T HW_AES_var;
43
44 /*****************************************************************************/
45
HW_AES_Enable(void)46 int HW_AES_Enable( void )
47 {
48 HW_AES_VAR_T* av = &HW_AES_var;
49
50 /* Test if the driver is not already in use */
51
52 if ( HW_AES_CLOCK_IS_ENABLE() )
53 {
54 return FALSE;
55 }
56 av->run = TRUE;
57
58 UTILS_ENTER_CRITICAL_SECTION( );
59
60 /* Enable AES clock */
61 HW_AES_CLOCK_ENABLE( );
62
63 UTILS_EXIT_CRITICAL_SECTION( );
64
65 return TRUE;
66 }
67
68 /*****************************************************************************/
69
HW_AES_SetKey(uint32_t mode,const uint8_t * key)70 void HW_AES_SetKey( uint32_t mode,
71 const uint8_t* key )
72 {
73 uint32_t tmp[4];
74
75 /* Retrieve all bytes of key */
76 memcpy( tmp, key, 16 );
77
78 /* Initialize the AES peripheral with default values:
79 - Processing: disabled
80 - Data type: 32-bit
81 - Operating mode: encryption
82 - Chaining mode: ECB
83 - Key size: 128-bit
84 */
85 HW_AESX->CR = 0;
86
87 /* Copy key bytes to the AES registers */
88
89 if ( mode & HW_AES_REV )
90 {
91 HW_AESX->KEYR0 = tmp[0];
92 HW_AESX->KEYR1 = tmp[1];
93 HW_AESX->KEYR2 = tmp[2];
94 HW_AESX->KEYR3 = tmp[3];
95 }
96 else
97 {
98 HW_AESX->KEYR3 = __REV( tmp[0] );
99 HW_AESX->KEYR2 = __REV( tmp[1] );
100 HW_AESX->KEYR1 = __REV( tmp[2] );
101 HW_AESX->KEYR0 = __REV( tmp[3] );
102 }
103
104 if ( !(mode & HW_AES_ENC) )
105 {
106 /* Set key preparation mode */
107 HW_AESX->CR = AES_CR_MODE_0;
108
109 /* Enable AES processing */
110 HW_AESX->CR |= AES_CR_EN;
111
112 /* Wait for CCF flag to be raised */
113 while ( ! (HW_AESX->SR & AES_SR_CCF) );
114
115 /* Clear CCF Flag */
116 HW_AESX->ICR |= AES_ICR_CCF;
117
118 /* Set decryption mode */
119 HW_AESX->CR = AES_CR_MODE_1;
120 }
121
122 /* Enable byte swapping if needed */
123 if ( mode & HW_AES_SWAP )
124 HW_AESX->CR |= AES_CR_DATATYPE_1;
125
126 /* Wait until KEYVALID is set */
127 while ( !(HW_AESX->SR & AES_SR_KEYVALID) );
128
129 /* Enable AES processing */
130 HW_AESX->CR |= AES_CR_EN;
131 }
132
133 /*****************************************************************************/
134
HW_AES_Crypt(const uint32_t * input,uint32_t * output)135 void HW_AES_Crypt( const uint32_t* input,
136 uint32_t* output )
137 {
138 /* Write the input block into the input FIFO */
139 HW_AESX->DINR = input[0];
140 HW_AESX->DINR = input[1];
141 HW_AESX->DINR = input[2];
142 HW_AESX->DINR = input[3];
143
144 /* Wait for CCF flag to be raised */
145 while ( !(HW_AESX->SR & AES_SR_CCF) );
146
147 /* Read the output block from the output FIFO */
148 output[0] = HW_AESX->DOUTR;
149 output[1] = HW_AESX->DOUTR;
150 output[2] = HW_AESX->DOUTR;
151 output[3] = HW_AESX->DOUTR;
152
153 /* Clear CCF Flag */
154 HW_AESX->ICR |= AES_ICR_CCF;
155 }
156
157 /*****************************************************************************/
158
HW_AES_Disable(void)159 void HW_AES_Disable( void )
160 {
161 HW_AES_VAR_T* av = &HW_AES_var;
162
163 if ( av->run )
164 {
165 /* Disable AES processing */
166 HW_AESX->CR = 0;
167
168 UTILS_ENTER_CRITICAL_SECTION( );
169
170 /* Disable AES clock */
171 HW_AES_CLOCK_DISABLE( );
172
173 UTILS_EXIT_CRITICAL_SECTION( );
174
175 av->run = FALSE;
176 }
177 }
178
179 /*****************************************************************************/
180
HW_AES_InitCcm(uint8_t decrypt,const uint8_t * key,const uint32_t * b0,const uint32_t * b1)181 void HW_AES_InitCcm( uint8_t decrypt,
182 const uint8_t* key,
183 const uint32_t* b0,
184 const uint32_t* b1 )
185 {
186 uint32_t tmp[4], mode = decrypt ? AES_CR_MODE_1 : 0;
187
188 /* CCM init phase */
189 HW_AESX->CR = AES_CR_CHMOD_2 | mode;
190
191 /* Copy key bytes to the AES registers */
192 memcpy( tmp, key, 16 );
193 HW_AESX->KEYR0 = tmp[0];
194 HW_AESX->KEYR1 = tmp[1];
195 HW_AESX->KEYR2 = tmp[2];
196 HW_AESX->KEYR3 = tmp[3];
197
198 /* Copy B0 bytes to the AES registers */
199 HW_AESX->IVR3 = __REV( b0[0] );
200 HW_AESX->IVR2 = __REV( b0[1] );
201 HW_AESX->IVR1 = __REV( b0[2] );
202 HW_AESX->IVR0 = __REV( b0[3] );
203
204 /* Enable AES processing */
205 HW_AESX->CR |= AES_CR_EN;
206
207 /* Wait for CCF flag to be raised */
208 while ( ! (HW_AESX->SR & AES_SR_CCF) );
209
210 /* Clear CCF Flag */
211 HW_AESX->ICR |= AES_ICR_CCF;
212
213 /* CCM header phase */
214 HW_AESX->CR = AES_CR_CHMOD_2 | AES_CR_GCMPH_0 | AES_CR_DATATYPE_1;
215
216 /* Enable AES processing */
217 HW_AESX->CR |= AES_CR_EN;
218
219 /* Write the header block B1 into the input FIFO */
220 HW_AESX->DINR = b1[0];
221 HW_AESX->DINR = b1[1];
222 HW_AESX->DINR = b1[2];
223 HW_AESX->DINR = b1[3];
224
225 /* Wait for CCF flag to be raised */
226 while ( !(HW_AESX->SR & AES_SR_CCF) );
227
228 /* Clear CCF Flag */
229 HW_AESX->ICR |= AES_ICR_CCF;
230
231 /* CCM payload phase */
232 HW_AESX->CR = (AES_CR_EN | AES_CR_CHMOD_2 |
233 AES_CR_GCMPH_1 | AES_CR_DATATYPE_1 | mode);
234 }
235
236 /*****************************************************************************/
237
HW_AES_EndCcm(uint8_t tag_length,uint8_t * tag)238 void HW_AES_EndCcm( uint8_t tag_length,
239 uint8_t* tag )
240 {
241 uint32_t tmp[4];
242
243 /* CCM final phase */
244 HW_AESX->CR = (AES_CR_EN | AES_CR_CHMOD_2 |
245 AES_CR_GCMPH_0 | AES_CR_GCMPH_1 | AES_CR_DATATYPE_1);
246
247 /* Wait for CCF flag to be raised */
248 while ( !(HW_AESX->SR & AES_SR_CCF) );
249
250 /* Read the output block from the output FIFO */
251 tmp[0] = HW_AESX->DOUTR;
252 tmp[1] = HW_AESX->DOUTR;
253 tmp[2] = HW_AESX->DOUTR;
254 tmp[3] = HW_AESX->DOUTR;
255 memcpy( tag, tmp, tag_length );
256
257 /* Clear CCF Flag */
258 HW_AESX->ICR |= AES_ICR_CCF;
259 }
260
261 /*****************************************************************************/
262
HW_AES_SetLast(uint8_t left_length)263 void HW_AES_SetLast( uint8_t left_length )
264 {
265 HW_AESX->CR |= (16UL - left_length) << AES_CR_NPBLB_Pos;
266 }
267
268 /*****************************************************************************/
269