1 /**
2   ******************************************************************************
3   * @file    stm32h7xx_hal_cryp_ex.c
4   * @author  MCD Application Team
5   * @brief   Extended CRYP HAL module driver
6   *          This file provides firmware functions to manage the following
7   *          functionalities of CRYP extension peripheral:
8   *           + Extended AES processing functions
9   *
10   ******************************************************************************
11   * @attention
12   *
13   * Copyright (c) 2017 STMicroelectronics.
14   * All rights reserved.
15   *
16   * This software is licensed under terms that can be found in the LICENSE file
17   * in the root directory of this software component.
18   * If no LICENSE file comes with this software, it is provided AS-IS.
19   *
20   ******************************************************************************
21   @verbatim
22   ==============================================================================
23                      ##### How to use this driver #####
24   ==============================================================================
25     [..]
26     The CRYP extension HAL driver can be used after AES-GCM or AES-CCM
27     Encryption/Decryption to get the authentication messages.
28 
29   @endverbatim
30   */
31 
32 /* Includes ------------------------------------------------------------------*/
33 #include "stm32h7xx_hal.h"
34 
35 /** @addtogroup STM32H7xx_HAL_Driver
36   * @{
37   */
38 #if defined (CRYP)
39 /** @defgroup CRYPEx CRYPEx
40   * @brief CRYP Extension HAL module driver.
41   * @{
42   */
43 
44 #ifdef HAL_CRYP_MODULE_ENABLED
45 
46 /* Private typedef -----------------------------------------------------------*/
47 /* Private define ------------------------------------------------------------*/
48 /** @addtogroup CRYPEx_Private_Defines
49   * @{
50   */
51 
52 #define CRYP_PHASE_INIT                 0x00000000U
53 #define CRYP_PHASE_HEADER               CRYP_CR_GCM_CCMPH_0
54 #define CRYP_PHASE_PAYLOAD              CRYP_CR_GCM_CCMPH_1
55 #define CRYP_PHASE_FINAL                CRYP_CR_GCM_CCMPH
56 
57 #define CRYP_OPERATINGMODE_ENCRYPT      0x00000000U
58 #define CRYP_OPERATINGMODE_DECRYPT      CRYP_CR_ALGODIR
59 
60 #define  CRYPEx_PHASE_PROCESS       0x02U     /*!< CRYP peripheral is in processing phase */
61 #define  CRYPEx_PHASE_FINAL         0x03U     /*!< CRYP peripheral is in final phase this is relevant only with CCM and GCM modes */
62 
63 /*  CTR0 information to use in CCM algorithm */
64 #define CRYP_CCM_CTR0_0            0x07FFFFFFU
65 #define CRYP_CCM_CTR0_3            0xFFFFFF00U
66 
67 /**
68   * @}
69   */
70 
71 /* Private macro -------------------------------------------------------------*/
72 /* Private variables ---------------------------------------------------------*/
73 /* Private function prototypes -----------------------------------------------*/
74 
75 
76 
77 /* Exported functions---------------------------------------------------------*/
78 /** @addtogroup CRYPEx_Exported_Functions
79   * @{
80   */
81 
82 /** @defgroup CRYPEx_Exported_Functions_Group1 Extended AES processing functions
83   *  @brief    CRYPEx Extended processing functions.
84   *
85 @verbatim
86   ==============================================================================
87               ##### Extended AES processing functions #####
88   ==============================================================================
89     [..]  This section provides functions allowing to generate the authentication
90           TAG in Polling mode
91       (+)HAL_CRYPEx_AESGCM_GenerateAuthTAG
92       (+)HAL_CRYPEx_AESCCM_GenerateAuthTAG
93          they should be used after Encrypt/Decrypt operation.
94 
95 @endverbatim
96   * @{
97   */
98 
99 
100 /**
101   * @brief  generate the GCM authentication TAG.
102   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
103   *         the configuration information for CRYP module
104   * @param  AuthTag: Pointer to the authentication buffer
105   *         the AuthTag generated here is 128bits length, if the TAG length is
106   *         less than 128bits, user should consider only the valid part of AuthTag
107   *         buffer which correspond exactly to TAG length.
108   * @param  Timeout: Timeout duration
109   * @retval HAL status
110   */
HAL_CRYPEx_AESGCM_GenerateAuthTAG(CRYP_HandleTypeDef * hcryp,uint32_t * AuthTag,uint32_t Timeout)111 HAL_StatusTypeDef HAL_CRYPEx_AESGCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout)
112 {
113   uint32_t tickstart;
114   uint64_t headerlength = (uint64_t)(hcryp->Init.HeaderSize) * 32U; /* Header length in bits */
115   uint64_t inputlength = (uint64_t)hcryp->SizesSum * 8U; /* Input length in bits */
116   uint32_t tagaddr = (uint32_t)AuthTag;
117 
118   /* Correct header length if Init.HeaderSize is actually in bytes */
119   if (hcryp->Init.HeaderWidthUnit == CRYP_HEADERWIDTHUNIT_BYTE)
120   {
121     headerlength /= 4U;
122   }
123 
124   if (hcryp->State == HAL_CRYP_STATE_READY)
125   {
126     /* Process locked */
127     __HAL_LOCK(hcryp);
128 
129     /* Change the CRYP peripheral state */
130     hcryp->State = HAL_CRYP_STATE_BUSY;
131 
132     /* Check if initialization phase has already been performed */
133     if (hcryp->Phase == CRYPEx_PHASE_PROCESS)
134     {
135       /* Change the CRYP phase */
136       hcryp->Phase = CRYPEx_PHASE_FINAL;
137     }
138     else /* Initialization phase has not been performed*/
139     {
140       /* Disable the Peripheral */
141       __HAL_CRYP_DISABLE(hcryp);
142 
143       /* Sequence error code field */
144       hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE;
145 
146       /* Change the CRYP peripheral state */
147       hcryp->State = HAL_CRYP_STATE_READY;
148 
149       /* Process unlocked */
150       __HAL_UNLOCK(hcryp);
151       return HAL_ERROR;
152     }
153 
154     /* Disable CRYP to start the final phase */
155     __HAL_CRYP_DISABLE(hcryp);
156 
157     /* Select final phase */
158     MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH, CRYP_PHASE_FINAL);
159 
160     /*ALGODIR bit must be set to '0'.*/
161     hcryp->Instance->CR &=  ~CRYP_CR_ALGODIR;
162 
163     /* Enable the CRYP peripheral */
164     __HAL_CRYP_ENABLE(hcryp);
165 
166     /* Write the number of bits in header (64 bits) followed by the number of bits
167     in the payload */
168 #if !defined (CRYP_VER_2_2)
169     /* STM32H7 rev.B and above : data has to be inserted normally (no swapping)*/
170     if (hcryp->Version >= REV_ID_B)
171 #endif /*End of not defined CRYP_VER_2_2*/
172     {
173       hcryp->Instance->DIN = 0U;
174       hcryp->Instance->DIN = (uint32_t)(headerlength);
175       hcryp->Instance->DIN = 0U;
176       hcryp->Instance->DIN = (uint32_t)(inputlength);
177     }
178 #if !defined (CRYP_VER_2_2)
179     else/* data has to be swapped according to the DATATYPE */
180     {
181       if (hcryp->Init.DataType == CRYP_BIT_SWAP)
182       {
183         hcryp->Instance->DIN = 0U;
184         hcryp->Instance->DIN = __RBIT((uint32_t)(headerlength));
185         hcryp->Instance->DIN = 0U;
186         hcryp->Instance->DIN = __RBIT((uint32_t)(inputlength));
187       }
188       else if (hcryp->Init.DataType == CRYP_BYTE_SWAP)
189       {
190         hcryp->Instance->DIN = 0U;
191         hcryp->Instance->DIN = __REV((uint32_t)(headerlength));
192         hcryp->Instance->DIN = 0U;
193         hcryp->Instance->DIN = __REV((uint32_t)(inputlength));
194       }
195       else if (hcryp->Init.DataType == CRYP_HALFWORD_SWAP)
196       {
197         hcryp->Instance->DIN = 0U;
198         hcryp->Instance->DIN = __ROR((uint32_t)headerlength, 16U);
199         hcryp->Instance->DIN = 0U;
200         hcryp->Instance->DIN = __ROR((uint32_t)inputlength, 16U);
201       }
202       else if (hcryp->Init.DataType == CRYP_NO_SWAP)
203       {
204         hcryp->Instance->DIN = 0U;
205         hcryp->Instance->DIN = (uint32_t)(headerlength);
206         hcryp->Instance->DIN = 0U;
207         hcryp->Instance->DIN = (uint32_t)(inputlength);
208       }
209       else
210       {
211         /* Nothing to do */
212       }
213     }
214 #endif /*End of not defined CRYP_VER_2_2*/
215     /* Wait for OFNE flag to be raised */
216     tickstart = HAL_GetTick();
217     while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE))
218     {
219       /* Check for the Timeout */
220       if (Timeout != HAL_MAX_DELAY)
221       {
222         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
223         {
224           /* Disable the CRYP Peripheral Clock */
225           __HAL_CRYP_DISABLE(hcryp);
226 
227           /* Change state */
228           hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
229           hcryp->State = HAL_CRYP_STATE_READY;
230 
231           /* Process unlocked */
232           __HAL_UNLOCK(hcryp);
233           return HAL_ERROR;
234         }
235       }
236     }
237 
238     /* Read the authentication TAG in the output FIFO */
239     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
240     tagaddr += 4U;
241     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
242     tagaddr += 4U;
243     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
244     tagaddr += 4U;
245     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
246 
247     /* Disable the peripheral */
248     __HAL_CRYP_DISABLE(hcryp);
249 
250     /* Change the CRYP peripheral state */
251     hcryp->State = HAL_CRYP_STATE_READY;
252 
253     /* Process unlocked */
254     __HAL_UNLOCK(hcryp);
255   }
256   else
257   {
258     /* Busy error code field */
259     hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
260     return HAL_ERROR;
261   }
262   /* Return function status */
263   return HAL_OK;
264 }
265 
266 /**
267   * @brief  AES CCM Authentication TAG generation.
268   * @param  hcryp: pointer to a CRYP_HandleTypeDef structure that contains
269   *         the configuration information for CRYP module
270   * @param  AuthTag: Pointer to the authentication buffer
271   *         the AuthTag generated here is 128bits length, if the TAG length is
272   *         less than 128bits, user should consider only the valid part of AuthTag
273   *         buffer which correspond exactly to TAG length.
274   * @param  Timeout: Timeout duration
275   * @retval HAL status
276   */
HAL_CRYPEx_AESCCM_GenerateAuthTAG(CRYP_HandleTypeDef * hcryp,uint32_t * AuthTag,uint32_t Timeout)277 HAL_StatusTypeDef HAL_CRYPEx_AESCCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout)
278 {
279   uint32_t tagaddr = (uint32_t)AuthTag;
280   uint32_t ctr0 [4] = {0};
281   uint32_t ctr0addr = (uint32_t)ctr0;
282   uint32_t tickstart;
283 
284   if (hcryp->State == HAL_CRYP_STATE_READY)
285   {
286     /* Process locked */
287     __HAL_LOCK(hcryp);
288 
289     /* Change the CRYP peripheral state */
290     hcryp->State = HAL_CRYP_STATE_BUSY;
291 
292     /* Check if initialization phase has already been performed */
293     if (hcryp->Phase == CRYPEx_PHASE_PROCESS)
294     {
295       /* Change the CRYP phase */
296       hcryp->Phase = CRYPEx_PHASE_FINAL;
297     }
298     else /* Initialization phase has not been performed*/
299     {
300       /* Disable the peripheral */
301       __HAL_CRYP_DISABLE(hcryp);
302 
303       /* Sequence error code field */
304       hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE;
305 
306       /* Change the CRYP peripheral state */
307       hcryp->State = HAL_CRYP_STATE_READY;
308 
309       /* Process unlocked */
310       __HAL_UNLOCK(hcryp);
311       return HAL_ERROR;
312     }
313 
314     /* Disable CRYP to start the final phase */
315     __HAL_CRYP_DISABLE(hcryp);
316 
317     /* Select final phase & ALGODIR bit must be set to '0'. */
318     MODIFY_REG(hcryp->Instance->CR, CRYP_CR_GCM_CCMPH | CRYP_CR_ALGODIR, CRYP_PHASE_FINAL | CRYP_OPERATINGMODE_ENCRYPT);
319 
320     /* Enable the CRYP peripheral */
321     __HAL_CRYP_ENABLE(hcryp);
322 
323     /* Write the counter block in the IN FIFO, CTR0 information from B0
324     data has to be swapped according to the DATATYPE*/
325     ctr0[0] = (hcryp->Init.B0[0]) & CRYP_CCM_CTR0_0;
326     ctr0[1] = hcryp->Init.B0[1];
327     ctr0[2] = hcryp->Init.B0[2];
328     ctr0[3] = hcryp->Init.B0[3] &  CRYP_CCM_CTR0_3;
329 
330 #if !defined (CRYP_VER_2_2)
331     /*STM32H7 rev.B and above : data has to be inserted normally (no swapping)*/
332     if (hcryp->Version >= REV_ID_B)
333 #endif /*End of not defined CRYP_VER_2_2*/
334     {
335       hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
336       ctr0addr += 4U;
337       hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
338       ctr0addr += 4U;
339       hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
340       ctr0addr += 4U;
341       hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
342     }
343 #if !defined (CRYP_VER_2_2)
344     else /* data has to be swapped according to the DATATYPE */
345     {
346       if (hcryp->Init.DataType == CRYP_BYTE_SWAP)
347       {
348         hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr));
349         ctr0addr += 4U;
350         hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr));
351         ctr0addr += 4U;
352         hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr));
353         ctr0addr += 4U;
354         hcryp->Instance->DIN = __REV(*(uint32_t *)(ctr0addr));
355       }
356       else if (hcryp->Init.DataType == CRYP_HALFWORD_SWAP)
357       {
358         hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U);
359         ctr0addr += 4U;
360         hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U);
361         ctr0addr += 4U;
362         hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U);
363         ctr0addr += 4U;
364         hcryp->Instance->DIN = __ROR(*(uint32_t *)(ctr0addr), 16U);
365       }
366       else if (hcryp->Init.DataType == CRYP_BIT_SWAP)
367       {
368         hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr));
369         ctr0addr += 4U;
370         hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr));
371         ctr0addr += 4U;
372         hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr));
373         ctr0addr += 4U;
374         hcryp->Instance->DIN = __RBIT(*(uint32_t *)(ctr0addr));
375       }
376       else
377       {
378         hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
379         ctr0addr += 4U;
380         hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
381         ctr0addr += 4U;
382         hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
383         ctr0addr += 4U;
384         hcryp->Instance->DIN = *(uint32_t *)(ctr0addr);
385       }
386     }
387 #endif /*End of not defined CRYP_VER_2_2*/
388     /* Wait for OFNE flag to be raised */
389     tickstart = HAL_GetTick();
390     while (HAL_IS_BIT_CLR(hcryp->Instance->SR, CRYP_FLAG_OFNE))
391     {
392       /* Check for the Timeout */
393       if (Timeout != HAL_MAX_DELAY)
394       {
395         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
396         {
397           /* Disable the CRYP peripheral Clock */
398           __HAL_CRYP_DISABLE(hcryp);
399 
400           /* Change state */
401           hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
402           hcryp->State = HAL_CRYP_STATE_READY;
403 
404           /* Process unlocked */
405           __HAL_UNLOCK(hcryp);
406           return HAL_ERROR;
407         }
408       }
409     }
410 
411     /* Read the Auth TAG in the IN FIFO */
412     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
413     tagaddr += 4U;
414     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
415     tagaddr += 4U;
416     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
417     tagaddr += 4U;
418     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUT;
419 
420     /* Change the CRYP peripheral state */
421     hcryp->State = HAL_CRYP_STATE_READY;
422 
423     /* Process unlocked */
424     __HAL_UNLOCK(hcryp);
425 
426     /* Disable CRYP  */
427     __HAL_CRYP_DISABLE(hcryp);
428   }
429   else
430   {
431     /* Busy error code field */
432     hcryp->ErrorCode = HAL_CRYP_ERROR_BUSY;
433     return HAL_ERROR;
434   }
435   /* Return function status */
436   return HAL_OK;
437 }
438 
439 /**
440   * @}
441   */
442 
443 
444 #endif /* HAL_CRYP_MODULE_ENABLED */
445 
446 /**
447   * @}
448   */
449 #endif /* CRYP */
450 /**
451   * @}
452   */
453 
454 /**
455   * @}
456   */
457