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