1 /**
2   ******************************************************************************
3   * @file    stm32f2xx_hal_hash.c
4   * @author  MCD Application Team
5   * @brief   HASH HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the HASH peripheral:
8   *           + Initialization and de-initialization methods
9   *           + HASH or HMAC processing in polling mode
10   *           + HASH or HMAC processing in interrupt mode
11   *           + HASH or HMAC processing in DMA mode
12   *           + Peripheral State methods
13   *           + HASH or HMAC processing suspension/resumption
14   *
15   ******************************************************************************
16   * @attention
17   *
18   * Copyright (c) 2016 STMicroelectronics.
19   * All rights reserved.
20   *
21   * This software is licensed under terms that can be found in the LICENSE file
22   * in the root directory of this software component.
23   * If no LICENSE file comes with this software, it is provided AS-IS.
24   *
25   ******************************************************************************
26   @verbatim
27  ===============================================================================
28                      ##### How to use this driver #####
29  ===============================================================================
30     [..]
31     The HASH HAL driver can be used as follows:
32 
33     (#)Initialize the HASH low level resources by implementing the HAL_HASH_MspInit():
34         (##) Enable the HASH interface clock using __HASH_CLK_ENABLE()
35         (##) When resorting to interrupt-based APIs (e.g. HAL_HASH_xxx_Start_IT())
36             (+++) Configure the HASH interrupt priority using HAL_NVIC_SetPriority()
37             (+++) Enable the HASH IRQ handler using HAL_NVIC_EnableIRQ()
38             (+++) In HASH IRQ handler, call HAL_HASH_IRQHandler() API
39         (##) When resorting to DMA-based APIs  (e.g. HAL_HASH_xxx_Start_DMA())
40             (+++) Enable the DMAx interface clock using
41                    __DMAx_CLK_ENABLE()
42             (+++) Configure and enable one DMA stream to manage data transfer from
43                 memory to peripheral (input stream). Managing data transfer from
44                 peripheral to memory can be performed only using CPU.
45             (+++) Associate the initialized DMA handle to the HASH DMA handle
46                 using  __HAL_LINKDMA()
47             (+++) Configure the priority and enable the NVIC for the transfer complete
48                 interrupt on the DMA stream: use
49                  HAL_NVIC_SetPriority() and
50                  HAL_NVIC_EnableIRQ()
51 
52     (#)Initialize the HASH HAL using HAL_HASH_Init(). This function:
53         (##) resorts to HAL_HASH_MspInit() for low-level initialization,
54         (##) configures the data type: 1-bit, 8-bit, 16-bit or 32-bit.
55 
56     (#)Three processing schemes are available:
57         (##) Polling mode: processing APIs are blocking functions
58              i.e. they process the data and wait till the digest computation is finished,
59              e.g. HAL_HASH_xxx_Start() for HASH or HAL_HMAC_xxx_Start() for HMAC
60         (##) Interrupt mode: processing APIs are not blocking functions
61                 i.e. they process the data under interrupt,
62                 e.g. HAL_HASH_xxx_Start_IT() for HASH or HAL_HMAC_xxx_Start_IT() for HMAC
63         (##) DMA mode: processing APIs are not blocking functions and the CPU is
64              not used for data transfer i.e. the data transfer is ensured by DMA,
65                 e.g. HAL_HASH_xxx_Start_DMA() for HASH or HAL_HMAC_xxx_Start_DMA()
66                 for HMAC. Note that in DMA mode, a call to HAL_HASH_xxx_Finish()
67                 is then required to retrieve the digest.
68 
69     (#)When the processing function is called after HAL_HASH_Init(), the HASH peripheral is
70        initialized and processes the buffer fed in input. When the input data have all been
71        fed to the Peripheral, the digest computation can start.
72 
73     (#)Multi-buffer processing is possible in polling, interrupt and DMA modes.
74         (##) In polling mode, only multi-buffer HASH processing is possible.
75              API HAL_HASH_xxx_Accumulate() must be called for each input buffer, except for the last one.
76              User must resort to HAL_HASH_xxx_Accumulate_End() to enter the last one and retrieve as
77              well the computed digest.
78 
79         (##) In interrupt mode, API HAL_HASH_xxx_Accumulate_IT() must be called for each input buffer,
80              except for the last one.
81              User must resort to HAL_HASH_xxx_Accumulate_End_IT() to enter the last one and retrieve as
82              well the computed digest.
83 
84         (##) In DMA mode, multi-buffer HASH and HMAC processing are possible.
85               (+++) HASH processing DMA mode: processing APIs are not blocking functions and the CPU is
86              not used for data transfer i.e. the data transfer is ensured by DMA
87                 e.g. HAL_HASH_SHA1_Start_DMA()
88              (+++) HMAC processing (requires to resort to extended functions):
89              after initialization, the key and the first input buffer are entered
90              in the Peripheral with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
91              starts step 2.
92              The following buffers are next entered with the API  HAL_HMACEx_xxx_Step2_DMA(). At this
93              point, the HMAC processing is still carrying out step 2.
94              Then, step 2 for the last input buffer and step 3 are carried out by a single call
95              to HAL_HMACEx_xxx_Step2_3_DMA().
96 
97              The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish().
98 
99 
100     (#)Context swapping.
101         (##) Two APIs are available to suspend HASH or HMAC processing:
102              (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode),
103              (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA.
104 
105         (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows
106             to save in memory the Peripheral context. This context can be restored afterwards
107             to resume the HASH processing thanks to HAL_HASH_ContextRestoring().
108 
109         (##) Once the HASH Peripheral has been restored to the same configuration as that at suspension
110              time, processing can be restarted with the same API call (same API, same handle,
111              same parameters) as done before the suspension. Relevant parameters to restart at
112              the proper location are internally saved in the HASH handle.
113 
114     (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
115 
116      *** Remarks on message length ***
117      ===================================
118      [..]
119       (#) HAL in interruption mode (interruptions driven)
120 
121         (##)Due to HASH peripheral hardware design, the peripheral interruption is triggered every 64 bytes.
122         This is why, for driver implementation simplicity s sake, user is requested to enter a message the
123         length of which is a multiple of 4 bytes.
124 
125         (##) When the message length (in bytes) is not a multiple of words, a specific field exists in HASH_STR
126         to specify which bits to discard at the end of the complete message to process only the message bits
127         and not extra bits.
128 
129         (##) If user needs to perform a hash computation of a large input buffer that is spread around various places
130         in memory and where each piece of this input buffer is not necessarily a multiple of 4 bytes in size, it becomes
131         necessary to use a temporary buffer to format the data accordingly before feeding them to the Peripheral.
132         It is advised to the user to
133        (+++) achieve the first formatting operation by software then enter the data
134        (+++) while the Peripheral is processing the first input set, carry out the second formatting
135         operation by software, to be ready when DINIS occurs.
136        (+++) repeat step 2 until the whole message is processed.
137 
138      [..]
139       (#) HAL in DMA mode
140 
141         (##) Again, due to hardware design, the DMA transfer to feed the data can only be done on a word-basis.
142         The same field described above in HASH_STR is used to specify which bits to discard at the end of the
143         DMA transfer to process only the message bits and not extra bits. Due to hardware implementation,
144         this is possible only at the end of the complete message. When several DMA transfers are needed to
145         enter the message, this is not applicable at the end of the intermediary transfers.
146 
147         (##) Similarly to the interruption-driven mode, it is suggested to the user to format the consecutive
148         chunks of data by software while the DMA transfer and processing is on-going for the first parts of
149         the message. Due to the 32-bit alignment required for the DMA transfer, it is underlined that the
150         software formatting operation is more complex than in the IT mode.
151 
152      *** Callback registration ***
153      ===================================
154      [..]
155       (#) The compilation define  USE_HAL_HASH_REGISTER_CALLBACKS when set to 1
156           allows the user to configure dynamically the driver callbacks.
157           Use function HAL_HASH_RegisterCallback() to register a user callback.
158 
159       (#) Function HAL_HASH_RegisterCallback() allows to register following callbacks:
160             (+) InCpltCallback    : callback for input completion.
161             (+) DgstCpltCallback  : callback for digest computation completion.
162             (+) ErrorCallback     : callback for error.
163             (+) MspInitCallback   : HASH MspInit.
164             (+) MspDeInitCallback : HASH MspDeInit.
165           This function takes as parameters the HAL peripheral handle, the Callback ID
166           and a pointer to the user callback function.
167 
168       (#) Use function HAL_HASH_UnRegisterCallback() to reset a callback to the default
169           weak (surcharged) function.
170           HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle,
171           and the Callback ID.
172           This function allows to reset following callbacks:
173             (+) InCpltCallback    : callback for input completion.
174             (+) DgstCpltCallback  : callback for digest computation completion.
175             (+) ErrorCallback     : callback for error.
176             (+) MspInitCallback   : HASH MspInit.
177             (+) MspDeInitCallback : HASH MspDeInit.
178 
179       (#) By default, after the HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET
180           all callbacks are reset to the corresponding legacy weak (surcharged) functions:
181           examples HAL_HASH_InCpltCallback(), HAL_HASH_DgstCpltCallback()
182           Exception done for MspInit and MspDeInit callbacks that are respectively
183           reset to the legacy weak (surcharged) functions in the HAL_HASH_Init
184           and HAL_HASH_DeInit only when these callbacks are null (not registered beforehand)
185           If not, MspInit or MspDeInit are not null, the HAL_HASH_Init and HAL_HASH_DeInit
186           keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
187 
188           Callbacks can be registered/unregistered in READY state only.
189           Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
190           in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
191           during the Init/DeInit.
192           In that case first register the MspInit/MspDeInit user callbacks
193           using HAL_HASH_RegisterCallback before calling HAL_HASH_DeInit
194           or HAL_HASH_Init function.
195 
196           When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or
197           not defined, the callback registering feature is not available
198           and weak (surcharged) callbacks are used.
199 
200   @endverbatim
201   ******************************************************************************
202   */
203 
204 /* Includes ------------------------------------------------------------------*/
205 #include "stm32f2xx_hal.h"
206 
207 
208 /** @addtogroup STM32F2xx_HAL_Driver
209   * @{
210   */
211 #if defined (HASH)
212 
213 /** @defgroup HASH  HASH
214   * @brief HASH HAL module driver.
215   * @{
216   */
217 
218 #ifdef HAL_HASH_MODULE_ENABLED
219 
220 /* Private typedef -----------------------------------------------------------*/
221 /* Private define ------------------------------------------------------------*/
222 /** @defgroup HASH_Private_Constants HASH Private Constants
223   * @{
224   */
225 
226 /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status
227   * @{
228   */
229 #define HASH_DIGEST_CALCULATION_NOT_STARTED       ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */
230 #define HASH_DIGEST_CALCULATION_STARTED           ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register     */
231 /**
232   * @}
233   */
234 
235 /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers
236   * @{
237   */
238 #define HASH_NUMBER_OF_CSR_REGISTERS              54U     /*!< Number of Context Swap Registers */
239 /**
240   * @}
241   */
242 
243 /** @defgroup HASH_TimeOut_Value HASH TimeOut Value
244   * @{
245   */
246 #define HASH_TIMEOUTVALUE                         1000U   /*!< Time-out value  */
247 /**
248   * @}
249   */
250 
251 /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit
252   * @{
253   */
254 #define HASH_DMA_SUSPENSION_WORDS_LIMIT             20U   /*!< Number of words below which DMA suspension is aborted */
255 /**
256   * @}
257   */
258 
259 /**
260   * @}
261   */
262 
263 /* Private macro -------------------------------------------------------------*/
264 /* Private variables ---------------------------------------------------------*/
265 /* Private function prototypes -----------------------------------------------*/
266 /** @defgroup HASH_Private_Functions HASH Private Functions
267   * @{
268   */
269 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma);
270 static void HASH_DMAError(DMA_HandleTypeDef *hdma);
271 static void HASH_GetDigest(const uint8_t *pMsgDigest, uint8_t Size);
272 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
273                                                      uint32_t Timeout);
274 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size);
275 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash);
276 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash);
277 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout);
278 /**
279   * @}
280   */
281 
282 /** @defgroup HASH_Exported_Functions HASH Exported Functions
283   * @{
284   */
285 
286 /** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions
287   *  @brief    Initialization, configuration and call-back functions.
288   *
289 @verbatim
290  ===============================================================================
291               ##### Initialization and de-initialization functions #####
292  ===============================================================================
293     [..]  This section provides functions allowing to:
294       (+) Initialize the HASH according to the specified parameters
295           in the HASH_InitTypeDef and create the associated handle
296       (+) DeInitialize the HASH peripheral
297       (+) Initialize the HASH MCU Specific Package (MSP)
298       (+) DeInitialize the HASH MSP
299 
300     [..]  This section provides as well call back functions definitions for user
301           code to manage:
302       (+) Input data transfer to Peripheral completion
303       (+) Calculated digest retrieval completion
304       (+) Error management
305 
306 
307 
308 @endverbatim
309   * @{
310   */
311 
312 /**
313   * @brief  Initialize the HASH according to the specified parameters in the
314             HASH_HandleTypeDef and create the associated handle.
315   * @note   Only MDMAT and DATATYPE bits of HASH Peripheral are set by HAL_HASH_Init(),
316   *         other configuration bits are set by HASH or HMAC processing APIs.
317   * @param  hhash HASH handle
318   * @retval HAL status
319   */
HAL_HASH_Init(HASH_HandleTypeDef * hhash)320 HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash)
321 {
322   /* Check the hash handle allocation */
323   if (hhash == NULL)
324   {
325     return HAL_ERROR;
326   }
327 
328   /* Check the parameters */
329   assert_param(IS_HASH_DATATYPE(hhash->Init.DataType));
330 
331 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
332   if (hhash->State == HAL_HASH_STATE_RESET)
333   {
334     /* Allocate lock resource and initialize it */
335     hhash->Lock = HAL_UNLOCKED;
336 
337     /* Reset Callback pointers in HAL_HASH_STATE_RESET only */
338     hhash->InCpltCallback =  HAL_HASH_InCpltCallback;     /* Legacy weak (surcharged) input completion callback */
339     hhash->DgstCpltCallback =  HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation
340                                                              completion callback */
341     hhash->ErrorCallback =  HAL_HASH_ErrorCallback;       /* Legacy weak (surcharged) error callback */
342     if (hhash->MspInitCallback == NULL)
343     {
344       hhash->MspInitCallback = HAL_HASH_MspInit;
345     }
346 
347     /* Init the low level hardware */
348     hhash->MspInitCallback(hhash);
349   }
350 #else
351   if (hhash->State == HAL_HASH_STATE_RESET)
352   {
353     /* Allocate lock resource and initialize it */
354     hhash->Lock = HAL_UNLOCKED;
355 
356     /* Init the low level hardware */
357     HAL_HASH_MspInit(hhash);
358   }
359 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
360 
361   /* Change the HASH state */
362   hhash->State = HAL_HASH_STATE_BUSY;
363 
364   /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */
365   hhash->HashInCount = 0;
366   hhash->HashBuffSize = 0;
367   hhash->HashITCounter = 0;
368   hhash->NbWordsAlreadyPushed = 0;
369   /* Reset digest calculation bridle (MDMAT bit control) */
370   hhash->DigestCalculationDisable = RESET;
371   /* Set phase to READY */
372   hhash->Phase = HAL_HASH_PHASE_READY;
373   /* Reset suspension request flag */
374   hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
375 
376   /* Set the data type bit */
377   MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType);
378   /* Reset HASH handle status */
379   hhash->Status = HAL_OK;
380 
381   /* Set the HASH state to Ready */
382   hhash->State = HAL_HASH_STATE_READY;
383 
384   /* Initialise the error code */
385   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
386 
387   /* Return function status */
388   return HAL_OK;
389 }
390 
391 /**
392   * @brief  DeInitialize the HASH peripheral.
393   * @param  hhash HASH handle.
394   * @retval HAL status
395   */
HAL_HASH_DeInit(HASH_HandleTypeDef * hhash)396 HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash)
397 {
398   /* Check the HASH handle allocation */
399   if (hhash == NULL)
400   {
401     return HAL_ERROR;
402   }
403 
404   /* Change the HASH state */
405   hhash->State = HAL_HASH_STATE_BUSY;
406 
407   /* Set the default HASH phase */
408   hhash->Phase = HAL_HASH_PHASE_READY;
409 
410   /* Reset HashInCount, HashITCounter and HashBuffSize */
411   hhash->HashInCount = 0;
412   hhash->HashBuffSize = 0;
413   hhash->HashITCounter = 0;
414   /* Reset digest calculation bridle (MDMAT bit control) */
415   hhash->DigestCalculationDisable = RESET;
416 
417 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
418   if (hhash->MspDeInitCallback == NULL)
419   {
420     hhash->MspDeInitCallback = HAL_HASH_MspDeInit;
421   }
422 
423   /* DeInit the low level hardware */
424   hhash->MspDeInitCallback(hhash);
425 #else
426   /* DeInit the low level hardware: CLOCK, NVIC */
427   HAL_HASH_MspDeInit(hhash);
428 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
429 
430 
431   /* Reset HASH handle status */
432   hhash->Status = HAL_OK;
433 
434   /* Set the HASH state to Ready */
435   hhash->State = HAL_HASH_STATE_RESET;
436 
437   /* Initialise the error code */
438   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
439 
440   /* Reset multi buffers accumulation flag */
441   hhash->Accumulation = 0U;
442 
443   /* Return function status */
444   return HAL_OK;
445 }
446 
447 /**
448   * @brief  Initialize the HASH MSP.
449   * @param  hhash HASH handle.
450   * @retval None
451   */
HAL_HASH_MspInit(HASH_HandleTypeDef * hhash)452 __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash)
453 {
454   /* Prevent unused argument(s) compilation warning */
455   UNUSED(hhash);
456 
457   /* NOTE : This function should not be modified; when the callback is needed,
458             HAL_HASH_MspInit() can be implemented in the user file.
459    */
460 }
461 
462 /**
463   * @brief  DeInitialize the HASH MSP.
464   * @param  hhash HASH handle.
465   * @retval None
466   */
HAL_HASH_MspDeInit(HASH_HandleTypeDef * hhash)467 __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash)
468 {
469   /* Prevent unused argument(s) compilation warning */
470   UNUSED(hhash);
471 
472   /* NOTE : This function should not be modified; when the callback is needed,
473             HAL_HASH_MspDeInit() can be implemented in the user file.
474    */
475 }
476 
477 /**
478   * @brief  Input data transfer complete call back.
479   * @note   HAL_HASH_InCpltCallback() is called when the complete input message
480   *         has been fed to the Peripheral. This API is invoked only when input data are
481   *         entered under interruption or through DMA.
482   * @param  hhash HASH handle.
483   * @retval None
484   */
HAL_HASH_InCpltCallback(HASH_HandleTypeDef * hhash)485 __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash)
486 {
487   /* Prevent unused argument(s) compilation warning */
488   UNUSED(hhash);
489 
490   /* NOTE : This function should not be modified; when the callback is needed,
491             HAL_HASH_InCpltCallback() can be implemented in the user file.
492    */
493 }
494 
495 /**
496   * @brief  Digest computation complete call back.
497   * @note   HAL_HASH_DgstCpltCallback() is used under interruption, is not
498   *         relevant with DMA.
499   * @param  hhash HASH handle.
500   * @retval None
501   */
HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef * hhash)502 __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash)
503 {
504   /* Prevent unused argument(s) compilation warning */
505   UNUSED(hhash);
506 
507   /* NOTE : This function should not be modified; when the callback is needed,
508             HAL_HASH_DgstCpltCallback() can be implemented in the user file.
509    */
510 }
511 
512 /**
513   * @brief  Error callback.
514   * @note   Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...)
515   *         to retrieve the error type.
516   * @param  hhash HASH handle.
517   * @retval None
518   */
HAL_HASH_ErrorCallback(HASH_HandleTypeDef * hhash)519 __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash)
520 {
521   /* Prevent unused argument(s) compilation warning */
522   UNUSED(hhash);
523 
524   /* NOTE : This function should not be modified; when the callback is needed,
525             HAL_HASH_ErrorCallback() can be implemented in the user file.
526    */
527 }
528 
529 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
530 /**
531   * @brief  Register a User HASH Callback
532   *         To be used instead of the weak (surcharged) predefined callback
533   * @param hhash HASH handle
534   * @param CallbackID ID of the callback to be registered
535   *        This parameter can be one of the following values:
536   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
537   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
538   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
539   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
540   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
541   * @param pCallback pointer to the Callback function
542   * @retval status
543   */
HAL_HASH_RegisterCallback(HASH_HandleTypeDef * hhash,HAL_HASH_CallbackIDTypeDef CallbackID,pHASH_CallbackTypeDef pCallback)544 HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID,
545                                             pHASH_CallbackTypeDef pCallback)
546 {
547   HAL_StatusTypeDef status = HAL_OK;
548 
549   if (pCallback == NULL)
550   {
551     /* Update the error code */
552     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
553     return HAL_ERROR;
554   }
555   /* Process locked */
556   __HAL_LOCK(hhash);
557 
558   if (HAL_HASH_STATE_READY == hhash->State)
559   {
560     switch (CallbackID)
561     {
562       case HAL_HASH_INPUTCPLT_CB_ID :
563         hhash->InCpltCallback = pCallback;
564         break;
565 
566       case HAL_HASH_DGSTCPLT_CB_ID :
567         hhash->DgstCpltCallback = pCallback;
568         break;
569 
570       case HAL_HASH_ERROR_CB_ID :
571         hhash->ErrorCallback = pCallback;
572         break;
573 
574       case HAL_HASH_MSPINIT_CB_ID :
575         hhash->MspInitCallback = pCallback;
576         break;
577 
578       case HAL_HASH_MSPDEINIT_CB_ID :
579         hhash->MspDeInitCallback = pCallback;
580         break;
581 
582       default :
583         /* Update the error code */
584         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
585         /* update return status */
586         status =  HAL_ERROR;
587         break;
588     }
589   }
590   else if (HAL_HASH_STATE_RESET == hhash->State)
591   {
592     switch (CallbackID)
593     {
594       case HAL_HASH_MSPINIT_CB_ID :
595         hhash->MspInitCallback = pCallback;
596         break;
597 
598       case HAL_HASH_MSPDEINIT_CB_ID :
599         hhash->MspDeInitCallback = pCallback;
600         break;
601 
602       default :
603         /* Update the error code */
604         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
605         /* update return status */
606         status =  HAL_ERROR;
607         break;
608     }
609   }
610   else
611   {
612     /* Update the error code */
613     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
614     /* update return status */
615     status =  HAL_ERROR;
616   }
617 
618   /* Release Lock */
619   __HAL_UNLOCK(hhash);
620   return status;
621 }
622 
623 /**
624   * @brief  Unregister a HASH Callback
625   *         HASH Callback is redirected to the weak (surcharged) predefined callback
626   * @param hhash HASH handle
627   * @param CallbackID ID of the callback to be unregistered
628   *        This parameter can be one of the following values:
629   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
630   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
631   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
632   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
633   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
634   * @retval status
635   */
HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef * hhash,HAL_HASH_CallbackIDTypeDef CallbackID)636 HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID)
637 {
638   HAL_StatusTypeDef status = HAL_OK;
639 
640   /* Process locked */
641   __HAL_LOCK(hhash);
642 
643   if (HAL_HASH_STATE_READY == hhash->State)
644   {
645     switch (CallbackID)
646     {
647       case HAL_HASH_INPUTCPLT_CB_ID :
648         hhash->InCpltCallback = HAL_HASH_InCpltCallback;     /* Legacy weak (surcharged) input completion callback */
649         break;
650 
651       case HAL_HASH_DGSTCPLT_CB_ID :
652         hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation
653                                                                 completion callback */
654         break;
655 
656       case HAL_HASH_ERROR_CB_ID :
657         hhash->ErrorCallback = HAL_HASH_ErrorCallback;       /* Legacy weak (surcharged) error callback */
658         break;
659 
660       case HAL_HASH_MSPINIT_CB_ID :
661         hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
662         break;
663 
664       case HAL_HASH_MSPDEINIT_CB_ID :
665         hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
666         break;
667 
668       default :
669         /* Update the error code */
670         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
671         /* update return status */
672         status =  HAL_ERROR;
673         break;
674     }
675   }
676   else if (HAL_HASH_STATE_RESET == hhash->State)
677   {
678     switch (CallbackID)
679     {
680       case HAL_HASH_MSPINIT_CB_ID :
681         hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
682         break;
683 
684       case HAL_HASH_MSPDEINIT_CB_ID :
685         hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
686         break;
687 
688       default :
689         /* Update the error code */
690         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
691         /* update return status */
692         status =  HAL_ERROR;
693         break;
694     }
695   }
696   else
697   {
698     /* Update the error code */
699     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
700     /* update return status */
701     status =  HAL_ERROR;
702   }
703 
704   /* Release Lock */
705   __HAL_UNLOCK(hhash);
706   return status;
707 }
708 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
709 
710 /**
711   * @}
712   */
713 
714 /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode
715   *  @brief   HASH processing functions using polling mode.
716   *
717 @verbatim
718  ===============================================================================
719                  ##### Polling mode HASH processing functions #####
720  ===============================================================================
721     [..]  This section provides functions allowing to calculate in polling mode
722           the hash value using one of the following algorithms:
723       (+) MD5
724          (++) HAL_HASH_MD5_Start()
725          (++) HAL_HASH_MD5_Accmlt()
726          (++) HAL_HASH_MD5_Accmlt_End()
727       (+) SHA1
728          (++) HAL_HASH_SHA1_Start()
729          (++) HAL_HASH_SHA1_Accmlt()
730          (++) HAL_HASH_SHA1_Accmlt_End()
731 
732     [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
733 
734     [..]  In case of multi-buffer HASH processing (a single digest is computed while
735           several buffers are fed to the Peripheral), the user can resort to successive calls
736           to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call
737           to HAL_HASH_xxx_Accumulate_End().
738 
739 @endverbatim
740   * @{
741   */
742 
743 /**
744   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
745   *         read the computed digest.
746   * @note   Digest is available in pOutBuffer.
747   * @param  hhash HASH handle.
748   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
749   * @param  Size length of the input buffer in bytes.
750   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
751   * @param  Timeout Timeout value
752   * @retval HAL status
753   */
HAL_HASH_MD5_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)754 HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
755                                      uint8_t *pOutBuffer,
756                                      uint32_t Timeout)
757 {
758   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
759 }
760 
761 /**
762   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
763   *         processes pInBuffer.
764   * @note   Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed
765   *         several input buffers back-to-back to the Peripheral that will yield a single
766   *         HASH signature once all buffers have been entered. Wrap-up of input
767   *         buffers feeding and retrieval of digest is done by a call to
768   *         HAL_HASH_MD5_Accmlt_End().
769   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
770   *         the Peripheral has already been initialized.
771   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End()
772   *         to read it, feeding at the same time the last input buffer to the Peripheral.
773   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
774   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able
775   *         to manage the ending buffer with a length in bytes not a multiple of 4.
776   * @param  hhash HASH handle.
777   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
778   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
779   * @retval HAL status
780   */
HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)781 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
782 {
783   return  HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
784 }
785 
786 /**
787   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API.
788   * @note   Digest is available in pOutBuffer.
789   * @param  hhash HASH handle.
790   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
791   * @param  Size length of the input buffer in bytes.
792   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
793   * @param  Timeout Timeout value
794   * @retval HAL status
795   */
HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)796 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
797                                           uint8_t *pOutBuffer, uint32_t Timeout)
798 {
799   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
800 }
801 
802 /**
803   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
804   *         read the computed digest.
805   * @note   Digest is available in pOutBuffer.
806   * @param  hhash HASH handle.
807   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
808   * @param  Size length of the input buffer in bytes.
809   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
810   * @param  Timeout Timeout value
811   * @retval HAL status
812   */
HAL_HASH_SHA1_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)813 HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
814                                       uint8_t *pOutBuffer,
815                                       uint32_t Timeout)
816 {
817   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
818 }
819 
820 /**
821   * @brief  If not already done, initialize the HASH peripheral in SHA1 mode then
822   *         processes pInBuffer.
823   * @note   Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed
824   *         several input buffers back-to-back to the Peripheral that will yield a single
825   *         HASH signature once all buffers have been entered. Wrap-up of input
826   *         buffers feeding and retrieval of digest is done by a call to
827   *         HAL_HASH_SHA1_Accmlt_End().
828   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
829   *         the Peripheral has already been initialized.
830   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End()
831   *         to read it, feeding at the same time the last input buffer to the Peripheral.
832   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
833   *         HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able
834   *         to manage the ending buffer with a length in bytes not a multiple of 4.
835   * @param  hhash HASH handle.
836   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
837   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
838   * @retval HAL status
839   */
HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)840 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
841 {
842   return  HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
843 }
844 
845 /**
846   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API.
847   * @note   Digest is available in pOutBuffer.
848   * @param  hhash HASH handle.
849   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
850   * @param  Size length of the input buffer in bytes.
851   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
852   * @param  Timeout Timeout value
853   * @retval HAL status
854   */
HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)855 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
856                                            uint8_t *pOutBuffer, uint32_t Timeout)
857 {
858   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
859 }
860 
861 /**
862   * @}
863   */
864 
865 /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode
866   *  @brief   HASH processing functions using interrupt mode.
867   *
868 @verbatim
869  ===============================================================================
870                  ##### Interruption mode HASH processing functions #####
871  ===============================================================================
872     [..]  This section provides functions allowing to calculate in interrupt mode
873           the hash value using one of the following algorithms:
874       (+) MD5
875          (++) HAL_HASH_MD5_Start_IT()
876          (++) HAL_HASH_MD5_Accmlt_IT()
877          (++) HAL_HASH_MD5_Accmlt_End_IT()
878       (+) SHA1
879          (++) HAL_HASH_SHA1_Start_IT()
880          (++) HAL_HASH_SHA1_Accmlt_IT()
881          (++) HAL_HASH_SHA1_Accmlt_End_IT()
882 
883     [..]  API HAL_HASH_IRQHandler() manages each HASH interruption.
884 
885     [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in
886          HMAC processing mode.
887 
888 
889 @endverbatim
890   * @{
891   */
892 
893 /**
894   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
895   *         read the computed digest in interruption mode.
896   * @note   Digest is available in pOutBuffer.
897   * @param  hhash HASH handle.
898   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
899   * @param  Size length of the input buffer in bytes.
900   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
901   * @retval HAL status
902   */
HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)903 HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
904                                         uint8_t *pOutBuffer)
905 {
906   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
907 }
908 
909 /**
910   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
911   *         processes pInBuffer in interruption mode.
912   * @note   Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed
913   *         several input buffers back-to-back to the Peripheral that will yield a single
914   *         HASH signature once all buffers have been entered. Wrap-up of input
915   *         buffers feeding and retrieval of digest is done by a call to
916   *         HAL_HASH_MD5_Accmlt_End_IT().
917   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
918   *         the Peripheral has already been initialized.
919   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
920   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able
921   *         to manage the ending buffer with a length in bytes not a multiple of 4.
922   * @param  hhash HASH handle.
923   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
924   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
925   * @retval HAL status
926   */
HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)927 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
928 {
929   return  HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
930 }
931 
932 /**
933   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API.
934   * @note   Digest is available in pOutBuffer.
935   * @param  hhash HASH handle.
936   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
937   * @param  Size length of the input buffer in bytes.
938   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
939   * @retval HAL status
940   */
HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)941 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
942                                              uint8_t *pOutBuffer)
943 {
944   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
945 }
946 
947 /**
948   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
949   *         read the computed digest in interruption mode.
950   * @note   Digest is available in pOutBuffer.
951   * @param  hhash HASH handle.
952   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
953   * @param  Size length of the input buffer in bytes.
954   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
955   * @retval HAL status
956   */
HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)957 HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
958                                          uint8_t *pOutBuffer)
959 {
960   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
961 }
962 
963 
964 /**
965   * @brief  If not already done, initialize the HASH peripheral in SHA1 mode then
966   *         processes pInBuffer in interruption mode.
967   * @note   Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed
968   *         several input buffers back-to-back to the Peripheral that will yield a single
969   *         HASH signature once all buffers have been entered. Wrap-up of input
970   *         buffers feeding and retrieval of digest is done by a call to
971   *         HAL_HASH_SHA1_Accmlt_End_IT().
972   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
973   *         the Peripheral has already been initialized.
974   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
975   *         HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able
976   *         to manage the ending buffer with a length in bytes not a multiple of 4.
977   * @param  hhash HASH handle.
978   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
979   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
980   * @retval HAL status
981   */
HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)982 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
983 {
984   return  HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
985 }
986 
987 /**
988   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API.
989   * @note   Digest is available in pOutBuffer.
990   * @param  hhash HASH handle.
991   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
992   * @param  Size length of the input buffer in bytes.
993   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
994   * @retval HAL status
995   */
HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)996 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
997                                               uint8_t *pOutBuffer)
998 {
999   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
1000 }
1001 
1002 /**
1003   * @brief Handle HASH interrupt request.
1004   * @param hhash HASH handle.
1005   * @note  HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well.
1006   * @note  In case of error reported during the HASH interruption processing,
1007   *        HAL_HASH_ErrorCallback() API is called so that user code can
1008   *        manage the error. The error type is available in hhash->Status field.
1009   * @retval None
1010   */
HAL_HASH_IRQHandler(HASH_HandleTypeDef * hhash)1011 void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash)
1012 {
1013   hhash->Status = HASH_IT(hhash);
1014   if (hhash->Status != HAL_OK)
1015   {
1016     hhash->ErrorCode |= HAL_HASH_ERROR_IT;
1017 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1018     hhash->ErrorCallback(hhash);
1019 #else
1020     HAL_HASH_ErrorCallback(hhash);
1021 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1022     /* After error handling by code user, reset HASH handle HAL status */
1023     hhash->Status = HAL_OK;
1024   }
1025 }
1026 
1027 /**
1028   * @}
1029   */
1030 
1031 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode
1032   *  @brief   HASH processing functions using DMA mode.
1033   *
1034 @verbatim
1035  ===============================================================================
1036                     ##### DMA mode HASH processing functions #####
1037  ===============================================================================
1038     [..]  This section provides functions allowing to calculate in DMA mode
1039           the hash value using one of the following algorithms:
1040       (+) MD5
1041          (++) HAL_HASH_MD5_Start_DMA()
1042          (++) HAL_HASH_MD5_Finish()
1043       (+) SHA1
1044          (++) HAL_HASH_SHA1_Start_DMA()
1045          (++) HAL_HASH_SHA1_Finish()
1046 
1047     [..]  When resorting to DMA mode to enter the data in the Peripheral, user must resort
1048           to  HAL_HASH_xxx_Start_DMA() then read the resulting digest with
1049           HAL_HASH_xxx_Finish().
1050 
1051 @endverbatim
1052   * @{
1053   */
1054 
1055 /**
1056   * @brief  Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer
1057   *         to feed the input buffer to the Peripheral.
1058   * @note   Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must
1059   *         be called to retrieve the computed digest.
1060   * @param  hhash HASH handle.
1061   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1062   * @param  Size length of the input buffer in bytes.
1063   * @retval HAL status
1064   */
HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)1065 HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
1066 {
1067   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
1068 }
1069 
1070 /**
1071   * @brief  Return the computed digest in MD5 mode.
1072   * @note   The API waits for DCIS to be set then reads the computed digest.
1073   * @note   HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in
1074   *         HMAC MD5 mode.
1075   * @param  hhash HASH handle.
1076   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1077   * @param  Timeout Timeout value.
1078   * @retval HAL status
1079   */
HAL_HASH_MD5_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)1080 HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
1081 {
1082   return HASH_Finish(hhash, pOutBuffer, Timeout);
1083 }
1084 
1085 /**
1086   * @brief  Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer
1087   *         to feed the input buffer to the Peripheral.
1088   * @note   Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must
1089   *         be called to retrieve the computed digest.
1090   * @param  hhash HASH handle.
1091   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1092   * @param  Size length of the input buffer in bytes.
1093   * @retval HAL status
1094   */
HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)1095 HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
1096 {
1097   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1098 }
1099 
1100 
1101 /**
1102   * @brief  Return the computed digest in SHA1 mode.
1103   * @note   The API waits for DCIS to be set then reads the computed digest.
1104   * @note   HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in
1105   *         HMAC SHA1 mode.
1106   * @param  hhash HASH handle.
1107   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1108   * @param  Timeout Timeout value.
1109   * @retval HAL status
1110   */
HAL_HASH_SHA1_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)1111 HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
1112 {
1113   return HASH_Finish(hhash, pOutBuffer, Timeout);
1114 }
1115 
1116 /**
1117   * @}
1118   */
1119 
1120 /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode
1121   *  @brief   HMAC processing functions using polling mode.
1122   *
1123 @verbatim
1124  ===============================================================================
1125                  ##### Polling mode HMAC processing functions #####
1126  ===============================================================================
1127     [..]  This section provides functions allowing to calculate in polling mode
1128           the HMAC value using one of the following algorithms:
1129       (+) MD5
1130          (++) HAL_HMAC_MD5_Start()
1131       (+) SHA1
1132          (++) HAL_HMAC_SHA1_Start()
1133 
1134 
1135 @endverbatim
1136   * @{
1137   */
1138 
1139 /**
1140   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1141   *         read the computed digest.
1142   * @note   Digest is available in pOutBuffer.
1143   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1144   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1145   * @param  hhash HASH handle.
1146   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1147   * @param  Size length of the input buffer in bytes.
1148   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1149   * @param  Timeout Timeout value.
1150   * @retval HAL status
1151   */
HAL_HMAC_MD5_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)1152 HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
1153                                      uint8_t *pOutBuffer,
1154                                      uint32_t Timeout)
1155 {
1156   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
1157 }
1158 
1159 /**
1160   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1161   *         read the computed digest.
1162   * @note   Digest is available in pOutBuffer.
1163   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1164   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1165   * @param  hhash HASH handle.
1166   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1167   * @param  Size length of the input buffer in bytes.
1168   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1169   * @param  Timeout Timeout value.
1170   * @retval HAL status
1171   */
HAL_HMAC_SHA1_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)1172 HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
1173                                       uint8_t *pOutBuffer,
1174                                       uint32_t Timeout)
1175 {
1176   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
1177 }
1178 
1179 /**
1180   * @}
1181   */
1182 
1183 
1184 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
1185   *  @brief   HMAC processing functions using interrupt mode.
1186   *
1187 @verbatim
1188  ===============================================================================
1189                  ##### Interrupt mode HMAC processing functions #####
1190  ===============================================================================
1191     [..]  This section provides functions allowing to calculate in interrupt mode
1192           the HMAC value using one of the following algorithms:
1193       (+) MD5
1194          (++) HAL_HMAC_MD5_Start_IT()
1195       (+) SHA1
1196          (++) HAL_HMAC_SHA1_Start_IT()
1197 
1198 @endverbatim
1199   * @{
1200   */
1201 
1202 
1203 /**
1204   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1205   *         read the computed digest in interrupt mode.
1206   * @note   Digest is available in pOutBuffer.
1207   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1208   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1209   * @param  hhash HASH handle.
1210   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1211   * @param  Size length of the input buffer in bytes.
1212   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1213   * @retval HAL status
1214   */
HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1215 HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
1216                                         uint8_t *pOutBuffer)
1217 {
1218   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
1219 }
1220 
1221 /**
1222   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1223   *         read the computed digest in interrupt mode.
1224   * @note   Digest is available in pOutBuffer.
1225   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1226   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1227   * @param  hhash HASH handle.
1228   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1229   * @param  Size length of the input buffer in bytes.
1230   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1231   * @retval HAL status
1232   */
HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1233 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
1234                                          uint8_t *pOutBuffer)
1235 {
1236   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
1237 }
1238 
1239 /**
1240   * @}
1241   */
1242 
1243 
1244 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
1245   *  @brief   HMAC processing functions using DMA modes.
1246   *
1247 @verbatim
1248  ===============================================================================
1249                  ##### DMA mode HMAC processing functions #####
1250  ===============================================================================
1251     [..]  This section provides functions allowing to calculate in DMA mode
1252           the HMAC value using one of the following algorithms:
1253       (+) MD5
1254          (++) HAL_HMAC_MD5_Start_DMA()
1255       (+) SHA1
1256          (++) HAL_HMAC_SHA1_Start_DMA()
1257 
1258     [..]  When resorting to DMA mode to enter the data in the Peripheral for HMAC processing,
1259           user must resort to  HAL_HMAC_xxx_Start_DMA() then read the resulting digest
1260           with HAL_HASH_xxx_Finish().
1261 
1262 @endverbatim
1263   * @{
1264   */
1265 
1266 
1267 /**
1268   * @brief  Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
1269   *         DMA transfers to feed the key and the input buffer to the Peripheral.
1270   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1271   *         to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
1272   *         the computed digest.
1273   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1274   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1275   * @param  hhash HASH handle.
1276   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1277   * @param  Size length of the input buffer in bytes.
1278   * @retval HAL status
1279   */
HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)1280 HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
1281 {
1282   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
1283 }
1284 
1285 
1286 /**
1287   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
1288   *         DMA transfers to feed the key and the input buffer to the Peripheral.
1289   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1290   *         to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
1291   *         the computed digest.
1292   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1293   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1294   * @param  hhash HASH handle.
1295   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1296   * @param  Size length of the input buffer in bytes.
1297   * @retval HAL status
1298   */
HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)1299 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
1300 {
1301   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1302 }
1303 
1304 /**
1305   * @}
1306   */
1307 
1308 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
1309   *  @brief   Peripheral State functions.
1310   *
1311 @verbatim
1312  ===============================================================================
1313                       ##### Peripheral State methods #####
1314  ===============================================================================
1315     [..]
1316     This section permits to get in run-time the state and the peripheral handle
1317     status of the peripheral:
1318       (+) HAL_HASH_GetState()
1319       (+) HAL_HASH_GetStatus()
1320 
1321     [..]
1322     Additionally, this subsection provides functions allowing to save and restore
1323     the HASH or HMAC processing context in case of calculation suspension:
1324       (+) HAL_HASH_ContextSaving()
1325       (+) HAL_HASH_ContextRestoring()
1326 
1327     [..]
1328     This subsection provides functions allowing to suspend the HASH processing
1329       (+) when input are fed to the Peripheral by software
1330           (++) HAL_HASH_SwFeed_ProcessSuspend()
1331       (+) when input are fed to the Peripheral by DMA
1332           (++) HAL_HASH_DMAFeed_ProcessSuspend()
1333 
1334 
1335 
1336 @endverbatim
1337   * @{
1338   */
1339 
1340 /**
1341   * @brief  Return the HASH handle state.
1342   * @note   The API yields the current state of the handle (BUSY, READY,...).
1343   * @param  hhash HASH handle.
1344   * @retval HAL HASH state
1345   */
HAL_HASH_GetState(const HASH_HandleTypeDef * hhash)1346 HAL_HASH_StateTypeDef HAL_HASH_GetState(const HASH_HandleTypeDef *hhash)
1347 {
1348   return hhash->State;
1349 }
1350 
1351 
1352 /**
1353   * @brief Return the HASH HAL status.
1354   * @note  The API yields the HAL status of the handle: it is the result of the
1355   *        latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
1356   * @param  hhash HASH handle.
1357   * @retval HAL status
1358   */
HAL_HASH_GetStatus(const HASH_HandleTypeDef * hhash)1359 HAL_StatusTypeDef HAL_HASH_GetStatus(const HASH_HandleTypeDef *hhash)
1360 {
1361   return hhash->Status;
1362 }
1363 
1364 /**
1365   * @brief  Save the HASH context in case of processing suspension.
1366   * @param  hhash HASH handle.
1367   * @param  pMemBuffer pointer to the memory buffer where the HASH context
1368   *         is saved.
1369   * @note   The IMR, STR, CR then all the CSR registers are saved
1370   *         in that order. Only the r/w bits are read to be restored later on.
1371   * @note   By default, all the context swap registers (there are
1372   *         HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
1373   * @note   pMemBuffer points to a buffer allocated by the user. The buffer size
1374   *         must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
1375   * @retval None
1376   */
HAL_HASH_ContextSaving(HASH_HandleTypeDef * hhash,uint8_t * pMemBuffer)1377 void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
1378 {
1379   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1380   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1381   uint32_t i;
1382 
1383   /* Prevent unused argument(s) compilation warning */
1384   UNUSED(hhash);
1385 
1386   /* Save IMR register content */
1387   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->IMR, HASH_IT_DINI | HASH_IT_DCI);
1388   mem_ptr += 4U;
1389   /* Save STR register content */
1390   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->STR, HASH_STR_NBLW);
1391   mem_ptr += 4U;
1392   /* Save CR register content */
1393   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->CR, HASH_CR_DMAE | HASH_CR_DATATYPE | HASH_CR_MODE | HASH_CR_ALGO |
1394                                     HASH_CR_LKEY);
1395   mem_ptr += 4U;
1396   /* By default, save all CSRs registers */
1397   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
1398   {
1399     *(uint32_t *)(mem_ptr) = *(uint32_t *)(csr_ptr);
1400     mem_ptr += 4U;
1401     csr_ptr += 4U;
1402   }
1403 }
1404 
1405 
1406 /**
1407   * @brief  Restore the HASH context in case of processing resumption.
1408   * @param  hhash HASH handle.
1409   * @param  pMemBuffer pointer to the memory buffer where the HASH context
1410   *         is stored.
1411   * @note   The IMR, STR, CR then all the CSR registers are restored
1412   *         in that order. Only the r/w bits are restored.
1413   * @note   By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
1414   *         of those) are restored (all of them have been saved by default
1415   *         beforehand).
1416   * @retval None
1417   */
HAL_HASH_ContextRestoring(HASH_HandleTypeDef * hhash,uint8_t * pMemBuffer)1418 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
1419 {
1420   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1421   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1422   uint32_t i;
1423 
1424   /* Prevent unused argument(s) compilation warning */
1425   UNUSED(hhash);
1426 
1427   /* Restore IMR register content */
1428   WRITE_REG(HASH->IMR, (*(uint32_t *)(mem_ptr)));
1429   mem_ptr += 4U;
1430   /* Restore STR register content */
1431   WRITE_REG(HASH->STR, (*(uint32_t *)(mem_ptr)));
1432   mem_ptr += 4U;
1433   /* Restore CR register content */
1434   WRITE_REG(HASH->CR, (*(uint32_t *)(mem_ptr)));
1435   mem_ptr += 4U;
1436 
1437   /* Reset the HASH processor before restoring the Context
1438   Swap Registers (CSR) */
1439   __HAL_HASH_INIT();
1440 
1441   /* By default, restore all CSR registers */
1442   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
1443   {
1444     WRITE_REG((*(uint32_t *)(csr_ptr)), (*(uint32_t *)(mem_ptr)));
1445     mem_ptr += 4U;
1446     csr_ptr += 4U;
1447   }
1448 }
1449 
1450 
1451 /**
1452   * @brief  Initiate HASH processing suspension when in polling or interruption mode.
1453   * @param  hhash HASH handle.
1454   * @note   Set the handle field SuspendRequest to the appropriate value so that
1455   *         the on-going HASH processing is suspended as soon as the required
1456   *         conditions are met. Note that the actual suspension is carried out
1457   *         by the functions HASH_WriteData() in polling mode and HASH_IT() in
1458   *         interruption mode.
1459   * @retval None
1460   */
HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef * hhash)1461 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1462 {
1463   /* Set Handle Suspend Request field */
1464   hhash->SuspendRequest = HAL_HASH_SUSPEND;
1465 }
1466 
1467 /**
1468   * @brief  Suspend the HASH processing when in DMA mode.
1469   * @param  hhash HASH handle.
1470   * @note   When suspension attempt occurs at the very end of a DMA transfer and
1471   *         all the data have already been entered in the Peripheral, hhash->State is
1472   *         set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
1473   *         recommended to wrap-up the processing in reading the digest as usual.
1474   * @retval HAL status
1475   */
HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef * hhash)1476 HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1477 {
1478   uint32_t tmp_remaining_DMATransferSize_inWords;
1479   uint32_t tmp_initial_DMATransferSize_inWords;
1480   uint32_t tmp_words_already_pushed;
1481 
1482   if (hhash->State == HAL_HASH_STATE_READY)
1483   {
1484     return HAL_ERROR;
1485   }
1486   else
1487   {
1488 
1489     /* Make sure there is enough time to suspend the processing */
1490     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1491 
1492     if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT)
1493     {
1494       /* No suspension attempted since almost to the end of the transferred data. */
1495       /* Best option for user code is to wrap up low priority message hashing     */
1496       return HAL_ERROR;
1497     }
1498 
1499     /* Wait for BUSY flag to be reset */
1500     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1501     {
1502       return HAL_TIMEOUT;
1503     }
1504 
1505     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1506     {
1507       return HAL_ERROR;
1508     }
1509 
1510     /* Wait for BUSY flag to be set */
1511     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK)
1512     {
1513       return HAL_TIMEOUT;
1514     }
1515     /* Disable DMA channel */
1516     /* Note that the Abort function will
1517       - Clear the transfer error flags
1518       - Unlock
1519       - Set the State
1520     */
1521     if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK)
1522     {
1523       return HAL_ERROR;
1524     }
1525 
1526     /* Clear DMAE bit */
1527     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1528 
1529     /* Wait for BUSY flag to be reset */
1530     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1531     {
1532       return HAL_TIMEOUT;
1533     }
1534 
1535     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1536     {
1537       return HAL_ERROR;
1538     }
1539 
1540     /* At this point, DMA interface is disabled and no transfer is on-going */
1541     /* Retrieve from the DMA handle how many words remain to be written */
1542     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1543 
1544     if (tmp_remaining_DMATransferSize_inWords == 0U)
1545     {
1546       /* All the DMA transfer is actually done. Suspension occurred at the very end
1547          of the transfer. Either the digest computation is about to start (HASH case)
1548          or processing is about to move from one step to another (HMAC case).
1549          In both cases, the processing can't be suspended at this point. It is
1550          safer to
1551          - retrieve the low priority block digest before starting the high
1552            priority block processing (HASH case)
1553          - re-attempt a new suspension (HMAC case)
1554          */
1555       return HAL_ERROR;
1556     }
1557     else
1558     {
1559 
1560       /* Compute how many words were supposed to be transferred by DMA */
1561       tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount % 4U) != 0U) ? \
1562                                              ((hhash->HashInCount + 3U) / 4U) : (hhash->HashInCount / 4U));
1563 
1564       /* If discrepancy between the number of words reported by DMA Peripheral and
1565         the numbers of words entered as reported by HASH Peripheral, correct it */
1566       /* tmp_words_already_pushed reflects the number of words that were already pushed before
1567          the start of DMA transfer (multi-buffer processing case) */
1568       tmp_words_already_pushed = hhash->NbWordsAlreadyPushed;
1569       if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - \
1570             tmp_remaining_DMATransferSize_inWords) % 16U) != HASH_NBW_PUSHED())
1571       {
1572         tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */
1573       }
1574 
1575       /* Accordingly, update the input pointer that points at the next word to be
1576          transferred to the Peripheral by DMA */
1577       hhash->pHashInBuffPtr +=  4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ;
1578 
1579       /* And store in HashInCount the remaining size to transfer (in bytes) */
1580       hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords;
1581 
1582     }
1583 
1584     /* Set State as suspended */
1585     hhash->State = HAL_HASH_STATE_SUSPENDED;
1586 
1587     return HAL_OK;
1588 
1589   }
1590 }
1591 
1592 /**
1593   * @brief  Return the HASH handle error code.
1594   * @param  hhash pointer to a HASH_HandleTypeDef structure.
1595   * @retval HASH Error Code
1596   */
HAL_HASH_GetError(const HASH_HandleTypeDef * hhash)1597 uint32_t HAL_HASH_GetError(const HASH_HandleTypeDef *hhash)
1598 {
1599   /* Return HASH Error Code */
1600   return hhash->ErrorCode;
1601 }
1602 /**
1603   * @}
1604   */
1605 
1606 
1607 /**
1608   * @}
1609   */
1610 
1611 /** @defgroup HASH_Private_Functions HASH Private Functions
1612   * @{
1613   */
1614 
1615 /**
1616   * @brief DMA HASH Input Data transfer completion callback.
1617   * @param hdma DMA handle.
1618   * @note  In case of HMAC processing, HASH_DMAXferCplt() initiates
1619   *        the next DMA transfer for the following HMAC step.
1620   * @retval None
1621   */
HASH_DMAXferCplt(DMA_HandleTypeDef * hdma)1622 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma)
1623 {
1624   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1625   uint32_t inputaddr;
1626   uint32_t buffersize;
1627   HAL_StatusTypeDef status;
1628 
1629   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1630   {
1631 
1632     /* Disable the DMA transfer */
1633     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1634 
1635     if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U)
1636     {
1637       /* If no HMAC processing, input data transfer is now over */
1638 
1639       /* Change the HASH state to ready */
1640       hhash->State = HAL_HASH_STATE_READY;
1641 
1642       /* Call Input data transfer complete call back */
1643 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1644       hhash->InCpltCallback(hhash);
1645 #else
1646       HAL_HASH_InCpltCallback(hhash);
1647 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1648 
1649     }
1650     else
1651     {
1652       /* HMAC processing: depending on the current HMAC step and whether or
1653       not multi-buffer processing is on-going, the next step is initiated
1654       and MDMAT bit is set.  */
1655 
1656 
1657       if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
1658       {
1659         /* This is the end of HMAC processing */
1660 
1661         /* Change the HASH state to ready */
1662         hhash->State = HAL_HASH_STATE_READY;
1663 
1664         /* Call Input data transfer complete call back
1665         (note that the last DMA transfer was that of the key
1666         for the outer HASH operation). */
1667 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1668         hhash->InCpltCallback(hhash);
1669 #else
1670         HAL_HASH_InCpltCallback(hhash);
1671 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1672 
1673         return;
1674       }
1675       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
1676       {
1677         inputaddr = (uint32_t)hhash->pHashMsgBuffPtr;     /* DMA transfer start address */
1678         buffersize = hhash->HashBuffSize;                 /* DMA transfer size (in bytes) */
1679         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
1680 
1681         /* In case of suspension request, save the new starting parameters */
1682         hhash->HashInCount = hhash->HashBuffSize;         /* Initial DMA transfer size (in bytes) */
1683         hhash->pHashInBuffPtr  = hhash->pHashMsgBuffPtr ; /* DMA transfer start address           */
1684 
1685         hhash->NbWordsAlreadyPushed = 0U;                  /* Reset number of words already pushed */
1686       }
1687       else  /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
1688       {
1689         if (hhash->DigestCalculationDisable != RESET)
1690         {
1691           /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral
1692           (case of multi-buffer HMAC processing):
1693           DCAL must not be set.
1694           Phase remains in Step 2, MDMAT remains set at this point.
1695           Change the HASH state to ready and call Input data transfer complete call back. */
1696           hhash->State = HAL_HASH_STATE_READY;
1697 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1698           hhash->InCpltCallback(hhash);
1699 #else
1700           HAL_HASH_InCpltCallback(hhash);
1701 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1702           return ;
1703         }
1704         else
1705         {
1706           /* Digest calculation is not disabled (case of single buffer input or last buffer
1707           of multi-buffer HMAC processing) */
1708           inputaddr = (uint32_t)hhash->Init.pKey;       /* DMA transfer start address */
1709           buffersize = hhash->Init.KeySize;             /* DMA transfer size (in bytes) */
1710           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;    /* Move phase from Step 2 to Step 3 */
1711           /* In case of suspension request, save the new starting parameters */
1712           hhash->HashInCount = hhash->Init.KeySize;     /* Initial size for second DMA transfer (input data) */
1713           hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* address passed to DMA, now entering data message */
1714 
1715           hhash->NbWordsAlreadyPushed = 0U;              /* Reset number of words already pushed */
1716         }
1717       }
1718 
1719       /* Configure the Number of valid bits in last word of the message */
1720       __HAL_HASH_SET_NBVALIDBITS(buffersize);
1721 
1722       /* Set the HASH DMA transfer completion call back */
1723       hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
1724 
1725       /* Enable the DMA In DMA stream */
1726       status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
1727                                 (((buffersize % 4U) != 0U) ? ((buffersize + (4U - (buffersize % 4U))) / 4U) : \
1728                                  (buffersize / 4U)));
1729 
1730       /* Enable DMA requests */
1731       SET_BIT(HASH->CR, HASH_CR_DMAE);
1732 
1733       /* Return function status */
1734       if (status != HAL_OK)
1735       {
1736         /* Update HASH state machine to error */
1737         hhash->State = HAL_HASH_STATE_ERROR;
1738       }
1739       else
1740       {
1741         /* Change HASH state */
1742         hhash->State = HAL_HASH_STATE_BUSY;
1743       }
1744     }
1745   }
1746 
1747   return;
1748 }
1749 
1750 /**
1751   * @brief DMA HASH communication error callback.
1752   * @param hdma DMA handle.
1753   * @note  HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
1754   *        can contain user code to manage the error.
1755   * @retval None
1756   */
HASH_DMAError(DMA_HandleTypeDef * hdma)1757 static void HASH_DMAError(DMA_HandleTypeDef *hdma)
1758 {
1759   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1760 
1761   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1762   {
1763     hhash->ErrorCode |= HAL_HASH_ERROR_DMA;
1764     /* Set HASH state to ready to prevent any blocking issue in user code
1765        present in HAL_HASH_ErrorCallback() */
1766     hhash->State = HAL_HASH_STATE_READY;
1767     /* Set HASH handle status to error */
1768     hhash->Status = HAL_ERROR;
1769 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1770     hhash->ErrorCallback(hhash);
1771 #else
1772     HAL_HASH_ErrorCallback(hhash);
1773 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1774     /* After error handling by code user, reset HASH handle HAL status */
1775     hhash->Status = HAL_OK;
1776 
1777   }
1778 }
1779 
1780 /**
1781   * @brief  Feed the input buffer to the HASH Peripheral.
1782   * @param  hhash HASH handle.
1783   * @param  pInBuffer pointer to input buffer.
1784   * @param  Size the size of input buffer in bytes.
1785   * @note   HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
1786   *         or not the HASH processing must be suspended. If this is the case, the
1787   *         processing is suspended when possible and the Peripheral feeding point reached at
1788   *         suspension time is stored in the handle for resumption later on.
1789   * @retval HAL status
1790   */
HASH_WriteData(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)1791 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
1792 {
1793   uint32_t buffercounter;
1794   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
1795   uint32_t tmp;
1796 
1797   for (buffercounter = 0U; buffercounter < (Size / 4U); buffercounter++)
1798   {
1799     /* Write input data 4 bytes at a time */
1800     HASH->DIN = *(uint32_t *)inputaddr;
1801     inputaddr += 4U;
1802 
1803     /* If the suspension flag has been raised and if the processing is not about
1804     to end, suspend processing */
1805     if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && (((buffercounter * 4U) + 4U) < Size))
1806     {
1807       /* wait for flag BUSY not set before  Wait for DINIS = 1*/
1808       if ((buffercounter * 4U) >= 64U)
1809       {
1810         if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1811         {
1812           return HAL_TIMEOUT;
1813         }
1814       }
1815       /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
1816       in the input buffer */
1817       if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
1818       {
1819         /* Reset SuspendRequest */
1820         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
1821 
1822         /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
1823         reached at suspension time is not saved in the same handle fields */
1824         if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
1825         {
1826           /* Save current reading and writing locations of Input and Output buffers */
1827           hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
1828           /* Save the number of bytes that remain to be processed at this point */
1829           hhash->HashInCount    =  Size - ((buffercounter * 4U) + 4U);
1830         }
1831         else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
1832         {
1833           /* Save current reading and writing locations of Input and Output buffers */
1834           hhash->pHashKeyBuffPtr  = (uint8_t *)inputaddr;
1835           /* Save the number of bytes that remain to be processed at this point */
1836           hhash->HashKeyCount  =  Size - ((buffercounter * 4U) + 4U);
1837         }
1838         else
1839         {
1840           /* Unexpected phase: unlock process and report error */
1841           hhash->State = HAL_HASH_STATE_READY;
1842           __HAL_UNLOCK(hhash);
1843           return HAL_ERROR;
1844         }
1845 
1846         /* Set the HASH state to Suspended and exit to stop entering data */
1847         hhash->State = HAL_HASH_STATE_SUSPENDED;
1848 
1849         return HAL_OK;
1850       } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))  */
1851     } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
1852   }   /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4)                 */
1853 
1854   /* At this point, all the data have been entered to the Peripheral: exit */
1855 
1856   if ((Size % 4U) != 0U)
1857   {
1858     if (hhash->Init.DataType == HASH_DATATYPE_16B)
1859     {
1860       /* Write remaining input data */
1861 
1862       if ((Size % 4U) <= 2U)
1863       {
1864         HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
1865       }
1866       if ((Size % 4U) == 3U)
1867       {
1868         HASH->DIN = *(uint32_t *)inputaddr;
1869       }
1870 
1871     }
1872     else if ((hhash->Init.DataType == HASH_DATATYPE_8B)
1873              || (hhash->Init.DataType == HASH_DATATYPE_1B))  /* byte swap or bit swap or */
1874     {
1875       /* Write remaining input data */
1876       if ((Size % 4U) == 1U)
1877       {
1878         HASH->DIN = (uint32_t) * (uint8_t *)inputaddr;
1879       }
1880       if ((Size % 4U) == 2U)
1881       {
1882         HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
1883       }
1884       if ((Size % 4U) == 3U)
1885       {
1886         tmp  = *(uint8_t *)inputaddr;
1887         tmp |= (uint32_t) * (uint8_t *)(inputaddr + 1U) << 8U;
1888         tmp |= (uint32_t) * (uint8_t *)(inputaddr + 2U) << 16U;
1889         HASH->DIN = tmp;
1890       }
1891 
1892     }
1893     else
1894     {
1895       HASH->DIN = *(uint32_t *)inputaddr;
1896     }
1897   }
1898 
1899 
1900   return  HAL_OK;
1901 }
1902 
1903 /**
1904   * @brief  Retrieve the message digest.
1905   * @param  pMsgDigest pointer to the computed digest.
1906   * @param  Size message digest size in bytes.
1907   * @retval None
1908   */
HASH_GetDigest(const uint8_t * pMsgDigest,uint8_t Size)1909 static void HASH_GetDigest(const uint8_t *pMsgDigest, uint8_t Size)
1910 {
1911   uint32_t msgdigest = (uint32_t)pMsgDigest;
1912 
1913   switch (Size)
1914   {
1915     /* Read the message digest */
1916     case 16:  /* MD5 */
1917       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1918       msgdigest += 4U;
1919       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1920       msgdigest += 4U;
1921       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1922       msgdigest += 4U;
1923       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1924       break;
1925     case 20:  /* SHA1 */
1926       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1927       msgdigest += 4U;
1928       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1929       msgdigest += 4U;
1930       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1931       msgdigest += 4U;
1932       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1933       msgdigest += 4U;
1934       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
1935       break;
1936     default:
1937       break;
1938   }
1939 }
1940 
1941 
1942 /**
1943   * @brief  Handle HASH processing Timeout.
1944   * @param  hhash HASH handle.
1945   * @param  Flag specifies the HASH flag to check.
1946   * @param  Status the Flag status (SET or RESET).
1947   * @param  Timeout Timeout duration.
1948   * @retval HAL status
1949   */
HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef * hhash,uint32_t Flag,FlagStatus Status,uint32_t Timeout)1950 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
1951                                                      uint32_t Timeout)
1952 {
1953   uint32_t tickstart = HAL_GetTick();
1954 
1955   /* Wait until flag is set */
1956   if (Status == RESET)
1957   {
1958     while (__HAL_HASH_GET_FLAG(Flag) == RESET)
1959     {
1960       /* Check for the Timeout */
1961       if (Timeout != HAL_MAX_DELAY)
1962       {
1963         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1964         {
1965           /* Set State to Ready to be able to restart later on */
1966           hhash->State  = HAL_HASH_STATE_READY;
1967           /* Store time out issue in handle status */
1968           hhash->Status = HAL_TIMEOUT;
1969 
1970           /* Process Unlocked */
1971           __HAL_UNLOCK(hhash);
1972 
1973           return HAL_TIMEOUT;
1974         }
1975       }
1976     }
1977   }
1978   else
1979   {
1980     while (__HAL_HASH_GET_FLAG(Flag) != RESET)
1981     {
1982       /* Check for the Timeout */
1983       if (Timeout != HAL_MAX_DELAY)
1984       {
1985         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1986         {
1987           /* Set State to Ready to be able to restart later on */
1988           hhash->State  = HAL_HASH_STATE_READY;
1989           /* Store time out issue in handle status */
1990           hhash->Status = HAL_TIMEOUT;
1991 
1992           /* Process Unlocked */
1993           __HAL_UNLOCK(hhash);
1994 
1995           return HAL_TIMEOUT;
1996         }
1997       }
1998     }
1999   }
2000   return HAL_OK;
2001 }
2002 
2003 
2004 /**
2005   * @brief  HASH processing in interruption mode.
2006   * @param  hhash HASH handle.
2007   * @note   HASH_IT() regularly reads hhash->SuspendRequest to check whether
2008   *         or not the HASH processing must be suspended. If this is the case, the
2009   *         processing is suspended when possible and the Peripheral feeding point reached at
2010   *         suspension time is stored in the handle for resumption later on.
2011   * @retval HAL status
2012   */
HASH_IT(HASH_HandleTypeDef * hhash)2013 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
2014 {
2015   if (hhash->State == HAL_HASH_STATE_BUSY)
2016   {
2017     /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
2018     if (hhash->HashITCounter == 0U)
2019     {
2020       /* Disable Interrupts */
2021       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2022       /* HASH state set back to Ready to prevent any issue in user code
2023          present in HAL_HASH_ErrorCallback() */
2024       hhash->State = HAL_HASH_STATE_READY;
2025       return HAL_ERROR;
2026     }
2027     else if (hhash->HashITCounter == 1U)
2028     {
2029       /* This is the first call to HASH_IT, the first input data are about to be
2030          entered in the Peripheral. A specific processing is carried out at this point to
2031          start-up the processing. */
2032       hhash->HashITCounter = 2U;
2033     }
2034     else
2035     {
2036       /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
2037         the HASH processing or the end of the current step for HMAC processing. */
2038       hhash->HashITCounter = 3U;
2039     }
2040 
2041     /* If digest is ready */
2042     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
2043     {
2044       /* Read the digest */
2045       HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2046 
2047       /* Disable Interrupts */
2048       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2049       /* Change the HASH state */
2050       hhash->State = HAL_HASH_STATE_READY;
2051       /* Reset HASH state machine */
2052       hhash->Phase = HAL_HASH_PHASE_READY;
2053       /* Call digest computation complete call back */
2054 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2055       hhash->DgstCpltCallback(hhash);
2056 #else
2057       HAL_HASH_DgstCpltCallback(hhash);
2058 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2059 
2060       return HAL_OK;
2061     }
2062 
2063     /* If Peripheral ready to accept new data */
2064     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2065     {
2066 
2067       /* If the suspension flag has been raised and if the processing is not about
2068          to end, suspend processing */
2069       if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
2070       {
2071         /* Disable Interrupts */
2072         __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2073 
2074         /* Reset SuspendRequest */
2075         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
2076 
2077         /* Change the HASH state */
2078         hhash->State = HAL_HASH_STATE_SUSPENDED;
2079 
2080         return HAL_OK;
2081       }
2082 
2083       /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and
2084         check whether the digest calculation has been triggered */
2085       if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
2086       {
2087         /* Call Input data transfer complete call back
2088            (called at the end of each step for HMAC) */
2089 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2090         hhash->InCpltCallback(hhash);
2091 #else
2092         HAL_HASH_InCpltCallback(hhash);
2093 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2094 
2095         if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2096         {
2097           /* Wait until Peripheral is not busy anymore */
2098           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2099           {
2100             /* Disable Interrupts */
2101             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2102             return HAL_TIMEOUT;
2103           }
2104           /* Initialization start for HMAC STEP 2 */
2105           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
2106           __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);  /* Set NBLW for the input message */
2107           hhash->HashInCount = hhash->HashBuffSize;         /* Set the input data size (in bytes) */
2108           hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr;   /* Set the input data address */
2109           hhash->HashITCounter = 1;                         /* Set ITCounter to 1 to indicate the start
2110                                                                of a new phase */
2111           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);               /* Enable IT (was disabled in HASH_Write_Block_Data) */
2112         }
2113         else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2114         {
2115           /* Wait until Peripheral is not busy anymore */
2116           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2117           {
2118             /* Disable Interrupts */
2119             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2120             return HAL_TIMEOUT;
2121           }
2122           /* Initialization start for HMAC STEP 3 */
2123           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;         /* Move phase from Step 2 to Step 3 */
2124           __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);   /* Set NBLW for the key */
2125           hhash->HashInCount = hhash->Init.KeySize;          /* Set the key size (in bytes) */
2126           hhash->pHashInBuffPtr = hhash->Init.pKey;          /* Set the key address */
2127           hhash->HashITCounter = 1;                          /* Set ITCounter to 1 to indicate the start
2128                                                                 of a new phase */
2129           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);                /* Enable IT (was disabled in HASH_Write_Block_Data) */
2130         }
2131         else
2132         {
2133           /* Nothing to do */
2134         }
2135       } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
2136     }  /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
2137 
2138     /* Return function status */
2139     return HAL_OK;
2140   }
2141   else
2142   {
2143     return HAL_BUSY;
2144   }
2145 }
2146 
2147 
2148 /**
2149   * @brief  Write a block of data in HASH Peripheral in interruption mode.
2150   * @param  hhash HASH handle.
2151   * @note   HASH_Write_Block_Data() is called under interruption by HASH_IT().
2152   * @retval HAL status
2153   */
HASH_Write_Block_Data(HASH_HandleTypeDef * hhash)2154 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
2155 {
2156   uint32_t inputaddr;
2157   uint32_t buffercounter;
2158   uint32_t inputcounter;
2159   uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
2160 
2161   /* If there are more than 64 bytes remaining to be entered */
2162   if (hhash->HashInCount > 64U)
2163   {
2164     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2165     /* Write the Input block in the Data IN register
2166       (16 32-bit words, or 64 bytes are entered) */
2167     for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U)
2168     {
2169       HASH->DIN = *(uint32_t *)inputaddr;
2170       inputaddr += 4U;
2171     }
2172     /* If this is the start of input data entering, an additional word
2173       must be entered to start up the HASH processing */
2174     if (hhash->HashITCounter == 2U)
2175     {
2176       HASH->DIN = *(uint32_t *)inputaddr;
2177       if (hhash->HashInCount >= 68U)
2178       {
2179         /* There are still data waiting to be entered in the Peripheral.
2180            Decrement buffer counter and set pointer to the proper
2181            memory location for the next data entering round. */
2182         hhash->HashInCount -= 68U;
2183         hhash->pHashInBuffPtr += 68U;
2184       }
2185       else
2186       {
2187         /* All the input buffer has been fed to the HW. */
2188         hhash->HashInCount = 0U;
2189       }
2190     }
2191     else
2192     {
2193       /* 64 bytes have been entered and there are still some remaining:
2194          Decrement buffer counter and set pointer to the proper
2195         memory location for the next data entering round.*/
2196       hhash->HashInCount -= 64U;
2197       hhash->pHashInBuffPtr += 64U;
2198     }
2199   }
2200   else
2201   {
2202     /* 64 or less bytes remain to be entered. This is the last
2203       data entering round. */
2204 
2205     /* Get the buffer address */
2206     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2207     /* Get the buffer counter */
2208     inputcounter = hhash->HashInCount;
2209     /* Disable Interrupts */
2210     __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
2211 
2212     /* Write the Input block in the Data IN register */
2213     for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++)
2214     {
2215       HASH->DIN = *(uint32_t *)inputaddr;
2216       inputaddr += 4U;
2217     }
2218 
2219     if (hhash->Accumulation == 1U)
2220     {
2221       /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
2222          The digest computation will be started when the last buffer data are entered. */
2223 
2224       /* Reset multi buffers accumulation flag */
2225       hhash->Accumulation = 0U;
2226       /* Change the HASH state */
2227       hhash->State = HAL_HASH_STATE_READY;
2228       /* Call Input data transfer complete call back */
2229 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2230       hhash->InCpltCallback(hhash);
2231 #else
2232       HAL_HASH_InCpltCallback(hhash);
2233 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2234     }
2235     else
2236     {
2237       /* Start the Digest calculation */
2238       __HAL_HASH_START_DIGEST();
2239       /* Return indication that digest calculation has started:
2240          this return value triggers the call to Input data transfer
2241          complete call back as well as the proper transition from
2242          one step to another in HMAC mode. */
2243       ret = HASH_DIGEST_CALCULATION_STARTED;
2244     }
2245     /* Reset buffer counter */
2246     hhash->HashInCount = 0;
2247   }
2248 
2249   /* Return whether or digest calculation has started */
2250   return ret;
2251 }
2252 
2253 /**
2254   * @brief  HMAC processing in polling mode.
2255   * @param  hhash HASH handle.
2256   * @param  Timeout Timeout value.
2257   * @retval HAL status
2258   */
HMAC_Processing(HASH_HandleTypeDef * hhash,uint32_t Timeout)2259 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
2260 {
2261   /* Ensure first that Phase is correct */
2262   if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2)
2263       && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3))
2264   {
2265     /* Change the HASH state */
2266     hhash->State = HAL_HASH_STATE_READY;
2267 
2268     /* Process Unlock */
2269     __HAL_UNLOCK(hhash);
2270 
2271     /* Return function status */
2272     return HAL_ERROR;
2273   }
2274 
2275   /* HMAC Step 1 processing */
2276   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2277   {
2278     /************************** STEP 1 ******************************************/
2279     /* Configure the Number of valid bits in last word of the message */
2280     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2281 
2282     /* Write input buffer in Data register */
2283     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2284     if (hhash->Status != HAL_OK)
2285     {
2286       return hhash->Status;
2287     }
2288 
2289     /* Check whether or not key entering process has been suspended */
2290     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2291     {
2292       /* Process Unlocked */
2293       __HAL_UNLOCK(hhash);
2294 
2295       /* Stop right there and return function status */
2296       return HAL_OK;
2297     }
2298 
2299     /* No processing suspension at this point: set DCAL bit. */
2300     __HAL_HASH_START_DIGEST();
2301 
2302     /* Wait for BUSY flag to be cleared */
2303     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2304     {
2305       return HAL_TIMEOUT;
2306     }
2307 
2308     /* Move from Step 1 to Step 2 */
2309     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
2310 
2311   }
2312 
2313   /* HMAC Step 2 processing.
2314      After phase check, HMAC_Processing() may
2315      - directly start up from this point in resumption case
2316        if the same Step 2 processing was suspended previously
2317     - or fall through from the Step 1 processing carried out hereabove */
2318   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2319   {
2320     /************************** STEP 2 ******************************************/
2321     /* Configure the Number of valid bits in last word of the message */
2322     __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
2323 
2324     /* Write input buffer in Data register */
2325     hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
2326     if (hhash->Status != HAL_OK)
2327     {
2328       return hhash->Status;
2329     }
2330 
2331     /* Check whether or not data entering process has been suspended */
2332     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2333     {
2334       /* Process Unlocked */
2335       __HAL_UNLOCK(hhash);
2336 
2337       /* Stop right there and return function status */
2338       return HAL_OK;
2339     }
2340 
2341     /* No processing suspension at this point: set DCAL bit. */
2342     __HAL_HASH_START_DIGEST();
2343 
2344     /* Wait for BUSY flag to be cleared */
2345     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2346     {
2347       return HAL_TIMEOUT;
2348     }
2349 
2350     /* Move from Step 2 to Step 3 */
2351     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
2352     /* In case Step 1 phase was suspended then resumed,
2353        set again Key input buffers and size before moving to
2354        next step */
2355     hhash->pHashKeyBuffPtr = hhash->Init.pKey;
2356     hhash->HashKeyCount    = hhash->Init.KeySize;
2357   }
2358 
2359 
2360   /* HMAC Step 3 processing.
2361       After phase check, HMAC_Processing() may
2362       - directly start up from this point in resumption case
2363         if the same Step 3 processing was suspended previously
2364      - or fall through from the Step 2 processing carried out hereabove */
2365   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
2366   {
2367     /************************** STEP 3 ******************************************/
2368     /* Configure the Number of valid bits in last word of the message */
2369     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2370 
2371     /* Write input buffer in Data register */
2372     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2373     if (hhash->Status != HAL_OK)
2374     {
2375       return hhash->Status;
2376     }
2377 
2378     /* Check whether or not key entering process has been suspended */
2379     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2380     {
2381       /* Process Unlocked */
2382       __HAL_UNLOCK(hhash);
2383 
2384       /* Stop right there and return function status */
2385       return HAL_OK;
2386     }
2387 
2388     /* No processing suspension at this point: start the Digest calculation. */
2389     __HAL_HASH_START_DIGEST();
2390 
2391     /* Wait for DCIS flag to be set */
2392     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2393     {
2394       return HAL_TIMEOUT;
2395     }
2396 
2397     /* Read the message digest */
2398     HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2399 
2400     /* Reset HASH state machine */
2401     hhash->Phase = HAL_HASH_PHASE_READY;
2402   }
2403 
2404   /* Change the HASH state */
2405   hhash->State = HAL_HASH_STATE_READY;
2406 
2407   /* Process Unlock */
2408   __HAL_UNLOCK(hhash);
2409 
2410   /* Return function status */
2411   return HAL_OK;
2412 }
2413 
2414 
2415 /**
2416   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2417   *         read the computed digest.
2418   * @note   Digest is available in pOutBuffer.
2419   * @param  hhash HASH handle.
2420   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2421   * @param  Size length of the input buffer in bytes.
2422   * @param  pOutBuffer pointer to the computed digest.
2423   * @param  Timeout Timeout value.
2424   * @param  Algorithm HASH algorithm.
2425   * @retval HAL status
2426   */
HASH_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)2427 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
2428                              uint8_t *pOutBuffer,
2429                              uint32_t Timeout, uint32_t Algorithm)
2430 {
2431   const uint8_t *pInBuffer_tmp;  /* input data address, input parameter of HASH_WriteData()         */
2432   uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
2433   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2434 
2435 
2436   /* Initiate HASH processing in case of start or resumption */
2437   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2438   {
2439     /* Check input parameters */
2440     if ((pInBuffer == NULL) || (pOutBuffer == NULL))
2441     {
2442       hhash->State = HAL_HASH_STATE_READY;
2443       return  HAL_ERROR;
2444     }
2445 
2446     /* Process Locked */
2447     __HAL_LOCK(hhash);
2448 
2449     /* Check if initialization phase has not been already performed */
2450     if (hhash->Phase == HAL_HASH_PHASE_READY)
2451     {
2452       /* Change the HASH state */
2453       hhash->State = HAL_HASH_STATE_BUSY;
2454 
2455       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2456       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2457 
2458       /* Configure the number of valid bits in last word of the message */
2459       __HAL_HASH_SET_NBVALIDBITS(Size);
2460 
2461       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2462       input parameters of HASH_WriteData() */
2463       pInBuffer_tmp = (const uint8_t *)pInBuffer;   /* pInBuffer_tmp is set to the input data address */
2464       Size_tmp = Size;             /* Size_tmp contains the input data size in bytes */
2465 
2466       /* Set the phase */
2467       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2468     }
2469     else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
2470     {
2471       /* if the Peripheral has already been initialized, two cases are possible */
2472 
2473       /* Process resumption time ... */
2474       if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2475       {
2476         /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2477         to the API input parameters but to those saved beforehand by HASH_WriteData()
2478         when the processing was suspended */
2479         pInBuffer_tmp = (const uint8_t *)hhash->pHashInBuffPtr;
2480         Size_tmp = hhash->HashInCount;
2481       }
2482       /* ... or multi-buffer HASH processing end */
2483       else
2484       {
2485         /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2486         input parameters of HASH_WriteData() */
2487         pInBuffer_tmp = (const uint8_t *)pInBuffer;
2488         Size_tmp = Size;
2489         /* Configure the number of valid bits in last word of the message */
2490         __HAL_HASH_SET_NBVALIDBITS(Size);
2491       }
2492       /* Change the HASH state */
2493       hhash->State = HAL_HASH_STATE_BUSY;
2494     }
2495     else
2496     {
2497       /* Phase error */
2498       hhash->State = HAL_HASH_STATE_READY;
2499 
2500       /* Process Unlocked */
2501       __HAL_UNLOCK(hhash);
2502 
2503       /* Return function status */
2504       return HAL_ERROR;
2505     }
2506 
2507 
2508     /* Write input buffer in Data register */
2509     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2510     if (hhash->Status != HAL_OK)
2511     {
2512       return hhash->Status;
2513     }
2514 
2515     /* If the process has not been suspended, carry on to digest calculation */
2516     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2517     {
2518       /* Start the Digest calculation */
2519       __HAL_HASH_START_DIGEST();
2520 
2521       /* Wait for DCIS flag to be set */
2522       if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2523       {
2524         return HAL_TIMEOUT;
2525       }
2526 
2527       /* Read the message digest */
2528       HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
2529 
2530       /* Change the HASH state */
2531       hhash->State = HAL_HASH_STATE_READY;
2532 
2533       /* Reset HASH state machine */
2534       hhash->Phase = HAL_HASH_PHASE_READY;
2535 
2536     }
2537 
2538     /* Process Unlocked */
2539     __HAL_UNLOCK(hhash);
2540 
2541     /* Return function status */
2542     return HAL_OK;
2543 
2544   }
2545   else
2546   {
2547     return HAL_BUSY;
2548   }
2549 }
2550 
2551 
2552 /**
2553   * @brief  If not already done, initialize the HASH peripheral then
2554   *         processes pInBuffer.
2555   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
2556   *         the Peripheral has already been initialized.
2557   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2558   *         HASH digest computation is corrupted.
2559   * @param  hhash HASH handle.
2560   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2561   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
2562   * @param  Algorithm HASH algorithm.
2563   * @retval HAL status
2564   */
HASH_Accumulate(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint32_t Algorithm)2565 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
2566                                   uint32_t Algorithm)
2567 {
2568   const uint8_t *pInBuffer_tmp;   /* input data address, input parameter of HASH_WriteData()         */
2569   uint32_t Size_tmp;  /* input data size (in bytes), input parameter of HASH_WriteData() */
2570   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2571 
2572   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2573   if ((Size % 4U) != 0U)
2574   {
2575     return  HAL_ERROR;
2576   }
2577 
2578   /* Initiate HASH processing in case of start or resumption */
2579   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2580   {
2581     /* Check input parameters */
2582     if ((pInBuffer == NULL) || (Size == 0U))
2583     {
2584       hhash->State = HAL_HASH_STATE_READY;
2585       return  HAL_ERROR;
2586     }
2587 
2588     /* Process Locked */
2589     __HAL_LOCK(hhash);
2590 
2591     /* If resuming the HASH processing */
2592     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2593     {
2594       /* Change the HASH state */
2595       hhash->State = HAL_HASH_STATE_BUSY;
2596 
2597       /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2598          to the API input parameters but to those saved beforehand by HASH_WriteData()
2599          when the processing was suspended */
2600       pInBuffer_tmp = (const uint8_t *)hhash->pHashInBuffPtr;  /* pInBuffer_tmp is set to the input data address */
2601       Size_tmp = hhash->HashInCount;          /* Size_tmp contains the input data size in bytes */
2602 
2603     }
2604     else
2605     {
2606       /* Change the HASH state */
2607       hhash->State = HAL_HASH_STATE_BUSY;
2608 
2609       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2610          input parameters of HASH_WriteData() */
2611       pInBuffer_tmp = (const uint8_t *)pInBuffer;    /* pInBuffer_tmp is set to the input data address */
2612       Size_tmp = Size;              /* Size_tmp contains the input data size in bytes */
2613 
2614       /* Check if initialization phase has already be performed */
2615       if (hhash->Phase == HAL_HASH_PHASE_READY)
2616       {
2617         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2618         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2619       }
2620 
2621       /* Set the phase */
2622       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2623 
2624     }
2625 
2626     /* Write input buffer in Data register */
2627     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2628     if (hhash->Status != HAL_OK)
2629     {
2630       return hhash->Status;
2631     }
2632 
2633     /* If the process has not been suspended, move the state to Ready */
2634     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2635     {
2636       /* Change the HASH state */
2637       hhash->State = HAL_HASH_STATE_READY;
2638     }
2639 
2640     /* Process Unlocked */
2641     __HAL_UNLOCK(hhash);
2642 
2643     /* Return function status */
2644     return HAL_OK;
2645 
2646   }
2647   else
2648   {
2649     return HAL_BUSY;
2650   }
2651 
2652 
2653 }
2654 
2655 
2656 /**
2657   * @brief  If not already done, initialize the HASH peripheral then
2658   *         processes pInBuffer in interruption mode.
2659   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
2660   *         the Peripheral has already been initialized.
2661   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2662   *         HASH digest computation is corrupted.
2663   * @param  hhash HASH handle.
2664   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2665   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
2666   * @param  Algorithm HASH algorithm.
2667   * @retval HAL status
2668   */
HASH_Accumulate_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint32_t Algorithm)2669 HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
2670                                      uint32_t Algorithm)
2671 {
2672   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2673   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2674   uint32_t SizeVar = Size;
2675 
2676   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2677   if ((Size % 4U) != 0U)
2678   {
2679     return  HAL_ERROR;
2680   }
2681 
2682   /* Initiate HASH processing in case of start or resumption */
2683   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2684   {
2685     /* Check input parameters */
2686     if ((pInBuffer == NULL) || (Size == 0U))
2687     {
2688       hhash->State = HAL_HASH_STATE_READY;
2689       return  HAL_ERROR;
2690     }
2691 
2692     /* Process Locked */
2693     __HAL_LOCK(hhash);
2694 
2695     /* If resuming the HASH processing */
2696     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2697     {
2698       /* Change the HASH state */
2699       hhash->State = HAL_HASH_STATE_BUSY;
2700     }
2701     else
2702     {
2703       /* Change the HASH state */
2704       hhash->State = HAL_HASH_STATE_BUSY;
2705 
2706       /* Check if initialization phase has already be performed */
2707       if (hhash->Phase == HAL_HASH_PHASE_READY)
2708       {
2709         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2710         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2711         hhash->HashITCounter = 1;
2712       }
2713       else
2714       {
2715         hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2716       }
2717 
2718       /* Set the phase */
2719       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2720 
2721       /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2722        fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2723        Therefore, first words are manually entered until DINIS raises, or until there
2724        is not more data to enter. */
2725       while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U))
2726       {
2727 
2728         /* Write input data 4 bytes at a time */
2729         HASH->DIN = *(uint32_t *)inputaddr;
2730         inputaddr += 4U;
2731         SizeVar -= 4U;
2732       }
2733 
2734       /* If DINIS is still not set or if all the data have been fed, stop here */
2735       if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U))
2736       {
2737         /* Change the HASH state */
2738         hhash->State = HAL_HASH_STATE_READY;
2739 
2740         /* Process Unlock */
2741         __HAL_UNLOCK(hhash);
2742 
2743         /* Return function status */
2744         return HAL_OK;
2745       }
2746 
2747       /* otherwise, carry on in interrupt-mode */
2748       hhash->HashInCount = SizeVar;               /* Counter used to keep track of number of data
2749                                                   to be fed to the Peripheral */
2750       hhash->pHashInBuffPtr = (uint8_t *)inputaddr;       /* Points at data which will be fed to the Peripheral at
2751                                                   the next interruption */
2752       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2753          the information describing where the HASH process is stopped.
2754          These variables are used later on to resume the HASH processing at the
2755          correct location. */
2756 
2757     }
2758 
2759     /* Set multi buffers accumulation flag */
2760     hhash->Accumulation = 1U;
2761 
2762     /* Process Unlock */
2763     __HAL_UNLOCK(hhash);
2764 
2765     /* Enable Data Input interrupt */
2766     __HAL_HASH_ENABLE_IT(HASH_IT_DINI);
2767 
2768     /* Return function status */
2769     return HAL_OK;
2770 
2771   }
2772   else
2773   {
2774     return HAL_BUSY;
2775   }
2776 
2777 }
2778 
2779 
2780 /**
2781   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2782   *         read the computed digest in interruption mode.
2783   * @note   Digest is available in pOutBuffer.
2784   * @param  hhash HASH handle.
2785   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2786   * @param  Size length of the input buffer in bytes.
2787   * @param  pOutBuffer pointer to the computed digest.
2788   * @param  Algorithm HASH algorithm.
2789   * @retval HAL status
2790   */
HASH_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)2791 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
2792                                 uint8_t *pOutBuffer,
2793                                 uint32_t Algorithm)
2794 {
2795   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2796   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2797   uint32_t polling_step = 0U;
2798   uint32_t initialization_skipped = 0U;
2799   uint32_t SizeVar = Size;
2800 
2801   /* If State is ready or suspended, start or resume IT-based HASH processing */
2802   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2803   {
2804     /* Check input parameters */
2805     if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
2806     {
2807       hhash->State = HAL_HASH_STATE_READY;
2808       return  HAL_ERROR;
2809     }
2810 
2811     /* Process Locked */
2812     __HAL_LOCK(hhash);
2813 
2814     /* Change the HASH state */
2815     hhash->State = HAL_HASH_STATE_BUSY;
2816 
2817     /* Initialize IT counter */
2818     hhash->HashITCounter = 1;
2819 
2820     /* Check if initialization phase has already be performed */
2821     if (hhash->Phase == HAL_HASH_PHASE_READY)
2822     {
2823       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2824       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2825 
2826       /* Configure the number of valid bits in last word of the message */
2827       __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2828 
2829 
2830       hhash->HashInCount = SizeVar;            /* Counter used to keep track of number of data
2831                                                   to be fed to the Peripheral */
2832       hhash->pHashInBuffPtr = pInBuffer;       /* Points at data which will be fed to the Peripheral at
2833                                                   the next interruption */
2834       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2835          the information describing where the HASH process is stopped.
2836          These variables are used later on to resume the HASH processing at the
2837          correct location. */
2838 
2839       hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2840     }
2841     else if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) && (SizeVar < 4U))
2842     {
2843       if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2844       {
2845         /* It remains data to enter and the Peripheral is ready to trigger DINIE,carry on as usual.
2846         Update HashInCount and pHashInBuffPtr accordingly. */
2847         hhash->HashInCount = SizeVar;
2848         hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
2849         /* Update the configuration of the number of valid bits in last word of the message */
2850         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2851         hhash->pHashOutBuffPtr = pOutBuffer;  /* Points at the computed digest */
2852       }
2853     }
2854     else
2855     {
2856       initialization_skipped = 1; /* info user later on in case of multi-buffer */
2857     }
2858 
2859     /* Set the phase */
2860     hhash->Phase = HAL_HASH_PHASE_PROCESS;
2861 
2862     /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2863       fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2864       Therefore, first words are manually entered until DINIS raises. */
2865     while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U))
2866     {
2867       polling_step = 1U; /* note that some words are entered before enabling the interrupt */
2868 
2869       /* Write input data 4 bytes at a time */
2870       HASH->DIN = *(uint32_t *)inputaddr;
2871       inputaddr += 4U;
2872       SizeVar -= 4U;
2873     }
2874 
2875     if (polling_step == 1U)
2876     {
2877       if (SizeVar == 0U)
2878       {
2879         /* If all the data have been entered at this point, it only remains to
2880          read the digest */
2881         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2882 
2883         /* Start the Digest calculation */
2884         __HAL_HASH_START_DIGEST();
2885         /* Process Unlock */
2886         __HAL_UNLOCK(hhash);
2887 
2888         /* Enable Interrupts */
2889         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2890 
2891         /* Return function status */
2892         return HAL_OK;
2893       }
2894       else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2895       {
2896         /* It remains data to enter and the Peripheral is ready to trigger DINIE,
2897            carry on as usual.
2898            Update HashInCount and pHashInBuffPtr accordingly. */
2899         hhash->HashInCount = SizeVar;
2900         hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
2901         /* Update the configuration of the number of valid bits in last word of the message */
2902         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2903         hhash->pHashOutBuffPtr = pOutBuffer;  /* Points at the computed digest */
2904         if (initialization_skipped == 1U)
2905         {
2906           hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2907         }
2908       }
2909       else
2910       {
2911         /* DINIS is not set but it remains a few data to enter (not enough for a full word).
2912            Manually enter the last bytes before enabling DCIE. */
2913         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2914         HASH->DIN = *(uint32_t *)inputaddr;
2915 
2916         /* Start the Digest calculation */
2917         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2918         __HAL_HASH_START_DIGEST();
2919         /* Process Unlock */
2920         __HAL_UNLOCK(hhash);
2921 
2922         /* Enable Interrupts */
2923         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2924 
2925         /* Return function status */
2926         return HAL_OK;
2927       }
2928     } /*  if (polling_step == 1) */
2929 
2930 
2931     /* Process Unlock */
2932     __HAL_UNLOCK(hhash);
2933 
2934     /* Enable Interrupts */
2935     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2936 
2937     /* Return function status */
2938     return HAL_OK;
2939   }
2940   else
2941   {
2942     return HAL_BUSY;
2943   }
2944 
2945 }
2946 
2947 
2948 /**
2949   * @brief  Initialize the HASH peripheral then initiate a DMA transfer
2950   *         to feed the input buffer to the Peripheral.
2951   * @param  hhash HASH handle.
2952   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2953   * @param  Size length of the input buffer in bytes.
2954   * @param  Algorithm HASH algorithm.
2955   * @retval HAL status
2956   */
HASH_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint32_t Algorithm)2957 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
2958                                  uint32_t Algorithm)
2959 {
2960   uint32_t inputaddr;
2961   uint32_t inputSize;
2962   HAL_StatusTypeDef status ;
2963   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2964 
2965   /* If State is ready or suspended, start or resume polling-based HASH processing */
2966   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2967   {
2968     /* Check input parameters */
2969     if ((pInBuffer == NULL) || (Size == 0U) ||
2970         /* Check phase coherency. Phase must be
2971            either READY (fresh start)
2972            or PROCESS (multi-buffer HASH management) */
2973         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
2974     {
2975       hhash->State = HAL_HASH_STATE_READY;
2976       return  HAL_ERROR;
2977     }
2978 
2979 
2980     /* Process Locked */
2981     __HAL_LOCK(hhash);
2982 
2983     /* If not a resumption case */
2984     if (hhash->State == HAL_HASH_STATE_READY)
2985     {
2986       /* Change the HASH state */
2987       hhash->State = HAL_HASH_STATE_BUSY;
2988 
2989       /* Check if initialization phase has already been performed.
2990          If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
2991          API is processing a new input data message in case of multi-buffer HASH
2992          computation. */
2993       if (hhash->Phase == HAL_HASH_PHASE_READY)
2994       {
2995         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2996         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2997 
2998         /* Set the phase */
2999         hhash->Phase = HAL_HASH_PHASE_PROCESS;
3000       }
3001 
3002       /* Configure the Number of valid bits in last word of the message */
3003       __HAL_HASH_SET_NBVALIDBITS(Size);
3004 
3005       inputaddr = (uint32_t)pInBuffer;     /* DMA transfer start address   */
3006       inputSize = Size;                    /* DMA transfer size (in bytes) */
3007 
3008       /* In case of suspension request, save the starting parameters */
3009       hhash->pHashInBuffPtr =  pInBuffer;  /* DMA transfer start address   */
3010       hhash->HashInCount = Size;           /* DMA transfer size (in bytes) */
3011 
3012     }
3013     /* If resumption case */
3014     else
3015     {
3016       /* Change the HASH state */
3017       hhash->State = HAL_HASH_STATE_BUSY;
3018 
3019       /* Resumption case, inputaddr and inputSize are not set to the API input parameters
3020          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3021          processing was suspended */
3022       inputaddr = (uint32_t)hhash->pHashInBuffPtr;  /* DMA transfer start address   */
3023       inputSize = hhash->HashInCount;               /* DMA transfer size (in bytes) */
3024 
3025     }
3026 
3027     /* Set the HASH DMA transfer complete callback */
3028     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3029     /* Set the DMA error callback */
3030     hhash->hdmain->XferErrorCallback = HASH_DMAError;
3031 
3032     /* Store number of words already pushed to manage proper DMA processing suspension */
3033     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3034 
3035     /* Enable the DMA In DMA stream */
3036     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
3037                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \
3038                                (inputSize / 4U)));
3039 
3040     /* Enable DMA requests */
3041     SET_BIT(HASH->CR, HASH_CR_DMAE);
3042 
3043     /* Process Unlock */
3044     __HAL_UNLOCK(hhash);
3045 
3046     /* Return function status */
3047     if (status != HAL_OK)
3048     {
3049       /* Update HASH state machine to error */
3050       hhash->State = HAL_HASH_STATE_ERROR;
3051     }
3052 
3053     return status;
3054   }
3055   else
3056   {
3057     return HAL_BUSY;
3058   }
3059 }
3060 
3061 /**
3062   * @brief  Return the computed digest.
3063   * @note   The API waits for DCIS to be set then reads the computed digest.
3064   * @param  hhash HASH handle.
3065   * @param  pOutBuffer pointer to the computed digest.
3066   * @param  Timeout Timeout value.
3067   * @retval HAL status
3068   */
HASH_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)3069 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
3070 {
3071 
3072   if (hhash->State == HAL_HASH_STATE_READY)
3073   {
3074     /* Check parameter */
3075     if (pOutBuffer == NULL)
3076     {
3077       return  HAL_ERROR;
3078     }
3079 
3080     /* Process Locked */
3081     __HAL_LOCK(hhash);
3082 
3083     /* Change the HASH state to busy */
3084     hhash->State = HAL_HASH_STATE_BUSY;
3085 
3086     /* Wait for DCIS flag to be set */
3087     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
3088     {
3089       return HAL_TIMEOUT;
3090     }
3091 
3092     /* Read the message digest */
3093     HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
3094 
3095     /* Change the HASH state to ready */
3096     hhash->State = HAL_HASH_STATE_READY;
3097 
3098     /* Reset HASH state machine */
3099     hhash->Phase = HAL_HASH_PHASE_READY;
3100 
3101     /* Process UnLock */
3102     __HAL_UNLOCK(hhash);
3103 
3104     /* Return function status */
3105     return HAL_OK;
3106 
3107   }
3108   else
3109   {
3110     return HAL_BUSY;
3111   }
3112 
3113 }
3114 
3115 
3116 /**
3117   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3118   *         read the computed digest.
3119   * @note   Digest is available in pOutBuffer.
3120   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3121   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3122   * @param  hhash HASH handle.
3123   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3124   * @param  Size length of the input buffer in bytes.
3125   * @param  pOutBuffer pointer to the computed digest.
3126   * @param  Timeout Timeout value.
3127   * @param  Algorithm HASH algorithm.
3128   * @retval HAL status
3129   */
HMAC_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)3130 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
3131                              uint8_t *pOutBuffer,
3132                              uint32_t Timeout, uint32_t Algorithm)
3133 {
3134   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3135 
3136   /* If State is ready or suspended, start or resume polling-based HASH processing */
3137   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3138   {
3139     /* Check input parameters */
3140     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3141         || (pOutBuffer == NULL))
3142     {
3143       hhash->State = HAL_HASH_STATE_READY;
3144       return  HAL_ERROR;
3145     }
3146 
3147     /* Process Locked */
3148     __HAL_LOCK(hhash);
3149 
3150     /* Change the HASH state */
3151     hhash->State = HAL_HASH_STATE_BUSY;
3152 
3153     /* Check if initialization phase has already be performed */
3154     if (hhash->Phase == HAL_HASH_PHASE_READY)
3155     {
3156       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3157       if (hhash->Init.KeySize > 64U)
3158       {
3159         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3160                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3161       }
3162       else
3163       {
3164         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3165                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3166       }
3167       /* Set the phase to Step 1 */
3168       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3169       /* Resort to hhash internal fields to feed the Peripheral.
3170          Parameters will be updated in case of suspension to contain the proper
3171          information at resumption time. */
3172       hhash->pHashOutBuffPtr  = pOutBuffer;            /* Output digest address    */
3173       hhash->pHashInBuffPtr   = pInBuffer;             /* Input data address, HMAC_Processing input
3174                                                           parameter for Step 2     */
3175       hhash->HashInCount      = Size;                  /* Input data size, HMAC_Processing input
3176                                                           parameter for Step 2        */
3177       hhash->HashBuffSize     = Size;                  /* Store the input buffer size for the whole HMAC process*/
3178       hhash->pHashKeyBuffPtr  = hhash->Init.pKey;      /* Key address, HMAC_Processing input parameter for Step
3179                                                           1 and Step 3 */
3180       hhash->HashKeyCount     = hhash->Init.KeySize;   /* Key size, HMAC_Processing input parameter for Step 1
3181                                                           and Step 3    */
3182     }
3183 
3184     /* Carry out HMAC processing */
3185     return HMAC_Processing(hhash, Timeout);
3186 
3187   }
3188   else
3189   {
3190     return HAL_BUSY;
3191   }
3192 }
3193 
3194 
3195 /**
3196   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3197   *         read the computed digest in interruption mode.
3198   * @note   Digest is available in pOutBuffer.
3199   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3200   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3201   * @param  hhash HASH handle.
3202   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3203   * @param  Size length of the input buffer in bytes.
3204   * @param  pOutBuffer pointer to the computed digest.
3205   * @param  Algorithm HASH algorithm.
3206   * @retval HAL status
3207   */
HMAC_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)3208 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
3209                                 uint8_t *pOutBuffer,
3210                                 uint32_t Algorithm)
3211 {
3212   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3213 
3214   /* If State is ready or suspended, start or resume IT-based HASH processing */
3215   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3216   {
3217     /* Check input parameters */
3218     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3219         || (pOutBuffer == NULL))
3220     {
3221       hhash->State = HAL_HASH_STATE_READY;
3222       return  HAL_ERROR;
3223     }
3224 
3225     /* Process Locked */
3226     __HAL_LOCK(hhash);
3227 
3228     /* Change the HASH state */
3229     hhash->State = HAL_HASH_STATE_BUSY;
3230 
3231     /* Initialize IT counter */
3232     hhash->HashITCounter = 1;
3233 
3234     /* Check if initialization phase has already be performed */
3235     if (hhash->Phase == HAL_HASH_PHASE_READY)
3236     {
3237       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3238       if (hhash->Init.KeySize > 64U)
3239       {
3240         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3241                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3242       }
3243       else
3244       {
3245         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3246                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3247       }
3248 
3249       /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
3250          to feed the Peripheral whatever the HMAC step.
3251          Lines below are set to start HMAC Step 1 processing where key is entered first. */
3252       hhash->HashInCount     = hhash->Init.KeySize; /* Key size                      */
3253       hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* Key address                   */
3254 
3255       /* Store input and output parameters in handle fields to manage steps transition
3256          or possible HMAC suspension/resumption */
3257       hhash->pHashKeyBuffPtr = hhash->Init.pKey;    /* Key address                   */
3258       hhash->pHashMsgBuffPtr = pInBuffer;           /* Input message address         */
3259       hhash->HashBuffSize    = Size;                /* Input message size (in bytes) */
3260       hhash->pHashOutBuffPtr = pOutBuffer;          /* Output digest address         */
3261 
3262       /* Configure the number of valid bits in last word of the key */
3263       __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3264 
3265       /* Set the phase to Step 1 */
3266       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3267     }
3268     else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
3269     {
3270       /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
3271 
3272     }
3273     else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3274     {
3275       /* Restart IT-based HASH processing after Step 2 suspension */
3276 
3277     }
3278     else
3279     {
3280       /* Error report as phase incorrect */
3281       /* Process Unlock */
3282       __HAL_UNLOCK(hhash);
3283       hhash->State = HAL_HASH_STATE_READY;
3284       return HAL_ERROR;
3285     }
3286 
3287     /* Process Unlock */
3288     __HAL_UNLOCK(hhash);
3289 
3290     /* Enable Interrupts */
3291     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
3292 
3293     /* Return function status */
3294     return HAL_OK;
3295   }
3296   else
3297   {
3298     return HAL_BUSY;
3299   }
3300 
3301 }
3302 
3303 
3304 /**
3305   * @brief  Initialize the HASH peripheral in HMAC mode then initiate the required
3306   *         DMA transfers to feed the key and the input buffer to the Peripheral.
3307   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3308   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3309   * @note   In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
3310   *         be a multiple of 4 otherwise, the HASH digest computation is corrupted.
3311   *         Only the length of the last buffer of the thread doesn't have to be a
3312   *         multiple of 4.
3313   * @param  hhash HASH handle.
3314   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3315   * @param  Size length of the input buffer in bytes.
3316   * @param  Algorithm HASH algorithm.
3317   * @retval HAL status
3318   */
HMAC_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint32_t Algorithm)3319 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
3320                                  uint32_t Algorithm)
3321 {
3322   uint32_t inputaddr;
3323   uint32_t inputSize;
3324   HAL_StatusTypeDef status ;
3325   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3326   /* If State is ready or suspended, start or resume DMA-based HASH processing */
3327   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3328   {
3329     /* Check input parameters */
3330     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) ||
3331         /* Check phase coherency. Phase must be
3332             either READY (fresh start)
3333             or one of HMAC PROCESS steps (multi-buffer HASH management) */
3334         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
3335     {
3336       hhash->State = HAL_HASH_STATE_READY;
3337       return  HAL_ERROR;
3338     }
3339 
3340 
3341     /* Process Locked */
3342     __HAL_LOCK(hhash);
3343 
3344     /* If not a case of resumption after suspension */
3345     if (hhash->State == HAL_HASH_STATE_READY)
3346     {
3347       /* Check whether or not initialization phase has already be performed */
3348       if (hhash->Phase == HAL_HASH_PHASE_READY)
3349       {
3350         /* Change the HASH state */
3351         hhash->State = HAL_HASH_STATE_BUSY;
3352         /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3353         if (hhash->Init.KeySize > 64U)
3354         {
3355           MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3356                      Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3357         }
3358         else
3359         {
3360           MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3361                      Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3362         }
3363         /* Store input aparameters in handle fields to manage steps transition
3364            or possible HMAC suspension/resumption */
3365         hhash->HashInCount = hhash->Init.KeySize;   /* Initial size for first DMA transfer (key size)      */
3366         hhash->pHashKeyBuffPtr = hhash->Init.pKey;  /* Key address                                         */
3367         hhash->pHashInBuffPtr  = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
3368         hhash->pHashMsgBuffPtr = pInBuffer;         /* Input data address                                  */
3369         hhash->HashBuffSize = Size;                 /* input data size (in bytes)                          */
3370 
3371         /* Set DMA input parameters */
3372         inputaddr = (uint32_t)(hhash->Init.pKey);   /* Address passed to DMA (start by entering Key message) */
3373         inputSize = hhash->Init.KeySize;            /* Size for first DMA transfer (in bytes) */
3374 
3375         /* Configure the number of valid bits in last word of the key */
3376         __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3377 
3378         /* Set the phase to Step 1 */
3379         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3380 
3381       }
3382       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3383       {
3384         /* Process a new input data message in case of multi-buffer HMAC processing
3385           (this is not a resumption case) */
3386 
3387         /* Change the HASH state */
3388         hhash->State = HAL_HASH_STATE_BUSY;
3389 
3390         /* Save input parameters to be able to manage possible suspension/resumption */
3391         hhash->HashInCount = Size;                /* Input message address       */
3392         hhash->pHashInBuffPtr = pInBuffer;        /* Input message size in bytes */
3393 
3394         /* Set DMA input parameters */
3395         inputaddr = (uint32_t)pInBuffer;           /* Input message address       */
3396         inputSize = Size;                          /* Input message size in bytes */
3397 
3398         if (hhash->DigestCalculationDisable == RESET)
3399         {
3400           /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
3401           __HAL_HASH_SET_NBVALIDBITS(inputSize);
3402         }
3403       }
3404       else
3405       {
3406         /* Phase not aligned with handle READY state */
3407         __HAL_UNLOCK(hhash);
3408         /* Return function status */
3409         return HAL_ERROR;
3410       }
3411     }
3412     else
3413     {
3414       /* Resumption case (phase may be Step 1, 2 or 3) */
3415 
3416       /* Change the HASH state */
3417       hhash->State = HAL_HASH_STATE_BUSY;
3418 
3419       /* Set DMA input parameters at resumption location;
3420          inputaddr and inputSize are not set to the API input parameters
3421          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3422          processing was suspended. */
3423       inputaddr = (uint32_t)(hhash->pHashInBuffPtr);  /* Input message address       */
3424       inputSize = hhash->HashInCount;                 /* Input message size in bytes */
3425     }
3426 
3427 
3428     /* Set the HASH DMA transfer complete callback */
3429     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3430     /* Set the DMA error callback */
3431     hhash->hdmain->XferErrorCallback = HASH_DMAError;
3432 
3433     /* Store number of words already pushed to manage proper DMA processing suspension */
3434     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3435 
3436     /* Enable the DMA In DMA stream */
3437     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN,  \
3438                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \
3439                                : (inputSize / 4U)));
3440 
3441     /* Enable DMA requests */
3442     SET_BIT(HASH->CR, HASH_CR_DMAE);
3443 
3444     /* Process Unlocked */
3445     __HAL_UNLOCK(hhash);
3446 
3447     /* Return function status */
3448     if (status != HAL_OK)
3449     {
3450       /* Update HASH state machine to error */
3451       hhash->State = HAL_HASH_STATE_ERROR;
3452     }
3453 
3454     /* Return function status */
3455     return status;
3456   }
3457   else
3458   {
3459     return HAL_BUSY;
3460   }
3461 }
3462 /**
3463   * @}
3464   */
3465 
3466 #endif /* HAL_HASH_MODULE_ENABLED */
3467 
3468 /**
3469   * @}
3470   */
3471 #endif /*  HASH*/
3472 /**
3473   * @}
3474   */
3475 
3476