1 /**
2   ******************************************************************************
3   * @file    stm32l5xx_hal_cryp_ex.c
4   * @author  MCD Application Team
5   * @brief   CRYPEx HAL module driver.
6   *          This file provides firmware functions to manage the extended
7   *          functionalities of the Cryptography (CRYP) peripheral.
8   *
9   ******************************************************************************
10   * @attention
11   *
12   * Copyright (c) 2019 STMicroelectronics.
13   * All rights reserved.
14   *
15   * This software is licensed under terms that can be found in the LICENSE file
16   * in the root directory of this software component.
17   * If no LICENSE file comes with this software, it is provided AS-IS.
18   *
19   ******************************************************************************
20   */
21 
22 /* Includes ------------------------------------------------------------------*/
23 #include "stm32l5xx_hal.h"
24 
25 /** @addtogroup STM32L5xx_HAL_Driver
26   * @{
27   */
28 
29 /** @addtogroup CRYPEx
30   * @{
31   */
32 
33 #if defined(AES)
34 
35 #ifdef HAL_CRYP_MODULE_ENABLED
36 
37 /* Private typedef -----------------------------------------------------------*/
38 /* Private define ------------------------------------------------------------*/
39 /** @addtogroup CRYPEx_Private_Defines
40   * @{
41   */
42 
43 #define CRYP_PHASE_INIT                              0x00000000U             /*!< GCM/GMAC (or CCM) init phase */
44 #define CRYP_PHASE_HEADER                            AES_CR_GCMPH_0          /*!< GCM/GMAC or CCM header phase */
45 #define CRYP_PHASE_PAYLOAD                           AES_CR_GCMPH_1          /*!< GCM(/CCM) payload phase   */
46 #define CRYP_PHASE_FINAL                             AES_CR_GCMPH            /*!< GCM/GMAC or CCM  final phase  */
47 
48 #define CRYP_OPERATINGMODE_ENCRYPT                   0x00000000U             /*!< Encryption mode   */
49 #define CRYP_OPERATINGMODE_KEYDERIVATION             AES_CR_MODE_0           /*!< Key derivation mode  only used when performing ECB and CBC decryptions  */
50 #define CRYP_OPERATINGMODE_DECRYPT                   AES_CR_MODE_1           /*!< Decryption       */
51 #define CRYP_OPERATINGMODE_KEYDERIVATION_DECRYPT     AES_CR_MODE             /*!< Key derivation and decryption only used when performing ECB and CBC decryptions  */
52 
53 #define  CRYPEx_PHASE_PROCESS       0x02U     /*!< CRYP peripheral is in processing phase */
54 #define  CRYPEx_PHASE_FINAL         0x03U     /*!< CRYP peripheral is in final phase this is relevant only with CCM and GCM modes */
55 
56 /*  CTR0 information to use in CCM algorithm */
57 #define CRYP_CCM_CTR0_0            0x07FFFFFFU
58 #define CRYP_CCM_CTR0_3            0xFFFFFF00U
59 
60 /**
61   * @}
62   */
63 
64 /* Private macro -------------------------------------------------------------*/
65 /* Private variables ---------------------------------------------------------*/
66 /* Private function prototypes -----------------------------------------------*/
67 
68 /* Exported functions---------------------------------------------------------*/
69 /** @addtogroup CRYPEx_Exported_Functions
70   * @{
71   */
72 
73 /** @defgroup CRYPEx_Exported_Functions_Group1 Extended AES processing functions
74  *  @brief   Extended processing functions.
75  *
76 @verbatim
77   ==============================================================================
78               ##### Extended AES processing functions #####
79   ==============================================================================
80     [..]  This section provides functions allowing to generate the authentication
81           TAG in Polling mode
82       (#)HAL_CRYPEx_AESGCM_GenerateAuthTAG
83       (#)HAL_CRYPEx_AESCCM_GenerateAuthTAG
84          they should be used after Encrypt/Decrypt operation.
85 
86 @endverbatim
87   * @{
88   */
89 
90 /**
91   * @brief  generate the GCM authentication TAG.
92   * @param  hcryp pointer to a CRYP_HandleTypeDef structure that contains
93   *         the configuration information for CRYP module
94   * @param  AuthTag Pointer to the authentication buffer
95   * @param  Timeout Timeout duration
96   * @retval HAL status
97   */
HAL_CRYPEx_AESGCM_GenerateAuthTAG(CRYP_HandleTypeDef * hcryp,uint32_t * AuthTag,uint32_t Timeout)98 HAL_StatusTypeDef HAL_CRYPEx_AESGCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout)
99 {
100   uint32_t tickstart;
101   /* Assume first Init.HeaderSize is in words */
102   uint64_t headerlength = (uint64_t)hcryp->Init.HeaderSize * 32U; /* Header length in bits */
103   uint64_t inputlength = (uint64_t)hcryp->SizesSum * 8U; /* Input length in bits */
104   uint32_t tagaddr = (uint32_t)AuthTag;
105 
106   /* Correct headerlength if Init.HeaderSize is actually in bytes */
107   if (hcryp->Init.HeaderWidthUnit == CRYP_HEADERWIDTHUNIT_BYTE)
108   {
109     headerlength /= 4U;
110   }
111 
112   if (hcryp->State == HAL_CRYP_STATE_READY)
113   {
114     /* Process locked */
115     __HAL_LOCK(hcryp);
116 
117     /* Change the CRYP peripheral state */
118     hcryp->State = HAL_CRYP_STATE_BUSY;
119 
120     /* Check if initialization phase has already been performed */
121     if (hcryp->Phase == CRYPEx_PHASE_PROCESS)
122     {
123       /* Change the CRYP phase */
124       hcryp->Phase = CRYPEx_PHASE_FINAL;
125     }
126     else /* Initialization phase has not been performed*/
127     {
128       /* Disable the Peripheral */
129       __HAL_CRYP_DISABLE(hcryp);
130 
131       /* Sequence error code field */
132       hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE;
133 
134       /* Change the CRYP peripheral state */
135       hcryp->State = HAL_CRYP_STATE_READY;
136 
137       /* Process unlocked */
138       __HAL_UNLOCK(hcryp);
139       return HAL_ERROR;
140     }
141 
142     /* Select final phase */
143     MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_PHASE_FINAL);
144 
145     /* Set the encrypt operating mode*/
146     MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_ENCRYPT);
147 
148     /*TinyAES peripheral from V3.1.1 : data has to be inserted normally (no swapping)*/
149     /* Write into the AES_DINR register the number of bits in header (64 bits)
150     followed by the number of bits in the payload */
151 
152     hcryp->Instance->DINR = 0U;
153     hcryp->Instance->DINR = (uint32_t)(headerlength);
154     hcryp->Instance->DINR = 0U;
155     hcryp->Instance->DINR = (uint32_t)(inputlength);
156 
157     /* Wait for CCF flag to be raised */
158     tickstart = HAL_GetTick();
159     while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF))
160     {
161       /* Check for the Timeout */
162       if (Timeout != HAL_MAX_DELAY)
163       {
164         if (((HAL_GetTick() - tickstart) > Timeout)||(Timeout == 0U))
165         {
166           /* Disable the CRYP peripheral clock */
167           __HAL_CRYP_DISABLE(hcryp);
168 
169           /* Change state */
170           hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
171           hcryp->State = HAL_CRYP_STATE_READY;
172 
173           /* Process unlocked */
174           __HAL_UNLOCK(hcryp);
175           return HAL_ERROR;
176         }
177       }
178     }
179 
180     /* Read the authentication TAG in the output FIFO */
181     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR;
182     tagaddr += 4U;
183     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR;
184     tagaddr += 4U;
185     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR;
186     tagaddr += 4U;
187     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR;
188 
189     /* Clear CCF flag */
190     __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR);
191 
192     /* Disable the peripheral */
193     __HAL_CRYP_DISABLE(hcryp);
194 
195     /* Change the CRYP peripheral state */
196     hcryp->State = HAL_CRYP_STATE_READY;
197 
198     /* Process unlocked */
199     __HAL_UNLOCK(hcryp);
200   }
201   else
202   {
203     /* Busy error code field */
204     hcryp->ErrorCode |= HAL_CRYP_ERROR_BUSY;
205     return HAL_ERROR;
206   }
207   /* Return function status */
208   return HAL_OK;
209 }
210 
211 /**
212   * @brief  AES CCM Authentication TAG generation.
213   * @param  hcryp pointer to a CRYP_HandleTypeDef structure that contains
214   *         the configuration information for CRYP module
215   * @param  AuthTag Pointer to the authentication buffer
216   * @param  Timeout Timeout duration
217   * @retval HAL status
218   */
HAL_CRYPEx_AESCCM_GenerateAuthTAG(CRYP_HandleTypeDef * hcryp,uint32_t * AuthTag,uint32_t Timeout)219 HAL_StatusTypeDef HAL_CRYPEx_AESCCM_GenerateAuthTAG(CRYP_HandleTypeDef *hcryp, uint32_t *AuthTag, uint32_t Timeout)
220 {
221   uint32_t tagaddr = (uint32_t)AuthTag;
222   uint32_t tickstart;
223 
224   if (hcryp->State == HAL_CRYP_STATE_READY)
225   {
226     /* Process locked */
227     __HAL_LOCK(hcryp);
228 
229     /* Disable interrupts in case they were kept enabled to proceed
230        a single message in several iterations */
231     __HAL_CRYP_DISABLE_IT(hcryp, CRYP_IT_CCFIE | CRYP_IT_ERRIE);
232 
233     /* Change the CRYP peripheral state */
234     hcryp->State = HAL_CRYP_STATE_BUSY;
235 
236     /* Check if initialization phase has already been performed */
237     if (hcryp->Phase == CRYPEx_PHASE_PROCESS)
238     {
239       /* Change the CRYP phase */
240       hcryp->Phase = CRYPEx_PHASE_FINAL;
241     }
242     else /* Initialization phase has not been performed*/
243     {
244       /* Disable the peripheral */
245       __HAL_CRYP_DISABLE(hcryp);
246 
247       /* Sequence error code field */
248       hcryp->ErrorCode |= HAL_CRYP_ERROR_AUTH_TAG_SEQUENCE;
249 
250       /* Change the CRYP peripheral state */
251       hcryp->State = HAL_CRYP_STATE_READY;
252 
253       /* Process unlocked */
254       __HAL_UNLOCK(hcryp);
255       return HAL_ERROR;
256     }
257     /* Select final phase */
258     MODIFY_REG(hcryp->Instance->CR, AES_CR_GCMPH, CRYP_PHASE_FINAL);
259 
260     /* Set encrypt  operating mode*/
261     MODIFY_REG(hcryp->Instance->CR, AES_CR_MODE, CRYP_OPERATINGMODE_ENCRYPT);
262 
263     /* Wait for CCF flag to be raised */
264     tickstart = HAL_GetTick();
265     while (HAL_IS_BIT_CLR(hcryp->Instance->SR, AES_SR_CCF))
266     {
267       /* Check for the Timeout */
268       if (Timeout != HAL_MAX_DELAY)
269       {
270         if (((HAL_GetTick() - tickstart) > Timeout) ||(Timeout == 0U))
271         {
272           /* Disable the CRYP peripheral Clock */
273           __HAL_CRYP_DISABLE(hcryp);
274 
275           /* Change state */
276           hcryp->ErrorCode |= HAL_CRYP_ERROR_TIMEOUT;
277           hcryp->State = HAL_CRYP_STATE_READY;
278 
279           /* Process unlocked */
280           __HAL_UNLOCK(hcryp);
281           return HAL_ERROR;
282         }
283       }
284     }
285 
286     /* Read the authentication TAG in the output FIFO */
287     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR;
288     tagaddr += 4U;
289     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR;
290     tagaddr += 4U;
291     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR;
292     tagaddr += 4U;
293     *(uint32_t *)(tagaddr) = hcryp->Instance->DOUTR;
294 
295     /* Clear CCF Flag */
296     __HAL_CRYP_CLEAR_FLAG(hcryp, CRYP_CCF_CLEAR);
297 
298 
299     /* Change the CRYP peripheral state */
300     hcryp->State = HAL_CRYP_STATE_READY;
301 
302     /* Process unlocked */
303     __HAL_UNLOCK(hcryp);
304 
305     /* Disable CRYP  */
306     __HAL_CRYP_DISABLE(hcryp);
307   }
308   else
309   {
310     /* Busy error code field */
311     hcryp->ErrorCode = HAL_CRYP_ERROR_BUSY;
312     return HAL_ERROR;
313   }
314   /* Return function status */
315   return HAL_OK;
316 }
317 
318 /**
319   * @}
320   */
321 
322 /** @defgroup CRYPEx_Exported_Functions_Group2 Extended AES Key Derivations functions
323   * @brief   Extended Key Derivations functions.
324   *
325 @verbatim
326   ==============================================================================
327               ##### Key Derivation functions #####
328   ==============================================================================
329     [..]  This section provides functions allowing to Enable or Disable the
330           the AutoKeyDerivation parameter in CRYP_HandleTypeDef structure
331           These function are allowed only in TinyAES peripheral.
332 @endverbatim
333   * @{
334   */
335 
336 /**
337   * @brief  AES enable key derivation functions
338   * @param  hcryp pointer to a CRYP_HandleTypeDef structure.
339   */
HAL_CRYPEx_EnableAutoKeyDerivation(CRYP_HandleTypeDef * hcryp)340 void  HAL_CRYPEx_EnableAutoKeyDerivation(CRYP_HandleTypeDef *hcryp)
341 {
342   if (hcryp->State == HAL_CRYP_STATE_READY)
343   {
344     hcryp->AutoKeyDerivation = ENABLE;
345   }
346   else
347   {
348     /* Busy error code field */
349     hcryp->ErrorCode = HAL_CRYP_ERROR_BUSY;
350   }
351 }
352 /**
353   * @brief  AES disable key derivation functions
354   * @param  hcryp pointer to a CRYP_HandleTypeDef structure.
355   */
HAL_CRYPEx_DisableAutoKeyDerivation(CRYP_HandleTypeDef * hcryp)356 void  HAL_CRYPEx_DisableAutoKeyDerivation(CRYP_HandleTypeDef *hcryp)
357 {
358   if (hcryp->State == HAL_CRYP_STATE_READY)
359   {
360     hcryp->AutoKeyDerivation = DISABLE;
361   }
362   else
363   {
364     /* Busy error code field */
365     hcryp->ErrorCode = HAL_CRYP_ERROR_BUSY;
366   }
367 }
368 
369 /**
370   * @}
371   */
372 
373 /**
374   * @}
375   */
376 
377 #endif /* HAL_CRYP_MODULE_ENABLED */
378 
379 #endif /* AES */
380 /**
381   * @}
382   */
383 
384 /**
385   * @}
386   */
387