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(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, uint8_t *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,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)754 HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
755                                      uint32_t Timeout)
756 {
757   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
758 }
759 
760 /**
761   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
762   *         processes pInBuffer.
763   * @note   Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed
764   *         several input buffers back-to-back to the Peripheral that will yield a single
765   *         HASH signature once all buffers have been entered. Wrap-up of input
766   *         buffers feeding and retrieval of digest is done by a call to
767   *         HAL_HASH_MD5_Accmlt_End().
768   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
769   *         the Peripheral has already been initialized.
770   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End()
771   *         to read it, feeding at the same time the last input buffer to the Peripheral.
772   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
773   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able
774   *         to manage the ending buffer with a length in bytes not a multiple of 4.
775   * @param  hhash HASH handle.
776   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
777   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
778   * @retval HAL status
779   */
HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)780 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
781 {
782   return  HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
783 }
784 
785 /**
786   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API.
787   * @note   Digest is available in pOutBuffer.
788   * @param  hhash HASH handle.
789   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
790   * @param  Size length of the input buffer in bytes.
791   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
792   * @param  Timeout Timeout value
793   * @retval HAL status
794   */
HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)795 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
796                                           uint8_t *pOutBuffer, uint32_t Timeout)
797 {
798   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
799 }
800 
801 /**
802   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
803   *         read the computed digest.
804   * @note   Digest is available in pOutBuffer.
805   * @param  hhash HASH handle.
806   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
807   * @param  Size length of the input buffer in bytes.
808   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
809   * @param  Timeout Timeout value
810   * @retval HAL status
811   */
HAL_HASH_SHA1_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)812 HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
813                                       uint32_t Timeout)
814 {
815   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
816 }
817 
818 /**
819   * @brief  If not already done, initialize the HASH peripheral in SHA1 mode then
820   *         processes pInBuffer.
821   * @note   Consecutive calls to HAL_HASH_SHA1_Accmlt() can be used to feed
822   *         several input buffers back-to-back to the Peripheral that will yield a single
823   *         HASH signature once all buffers have been entered. Wrap-up of input
824   *         buffers feeding and retrieval of digest is done by a call to
825   *         HAL_HASH_SHA1_Accmlt_End().
826   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
827   *         the Peripheral has already been initialized.
828   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Accmlt_End()
829   *         to read it, feeding at the same time the last input buffer to the Peripheral.
830   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
831   *         HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End() is able
832   *         to manage the ending buffer with a length in bytes not a multiple of 4.
833   * @param  hhash HASH handle.
834   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
835   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
836   * @retval HAL status
837   */
HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)838 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
839 {
840   return  HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
841 }
842 
843 /**
844   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt() API.
845   * @note   Digest is available in pOutBuffer.
846   * @param  hhash HASH handle.
847   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
848   * @param  Size length of the input buffer in bytes.
849   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
850   * @param  Timeout Timeout value
851   * @retval HAL status
852   */
HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)853 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
854                                            uint8_t *pOutBuffer, uint32_t Timeout)
855 {
856   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
857 }
858 
859 /**
860   * @}
861   */
862 
863 /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode
864   *  @brief   HASH processing functions using interrupt mode.
865   *
866 @verbatim
867  ===============================================================================
868                  ##### Interruption mode HASH processing functions #####
869  ===============================================================================
870     [..]  This section provides functions allowing to calculate in interrupt mode
871           the hash value using one of the following algorithms:
872       (+) MD5
873          (++) HAL_HASH_MD5_Start_IT()
874          (++) HAL_HASH_MD5_Accmlt_IT()
875          (++) HAL_HASH_MD5_Accmlt_End_IT()
876       (+) SHA1
877          (++) HAL_HASH_SHA1_Start_IT()
878          (++) HAL_HASH_SHA1_Accmlt_IT()
879          (++) HAL_HASH_SHA1_Accmlt_End_IT()
880 
881     [..]  API HAL_HASH_IRQHandler() manages each HASH interruption.
882 
883     [..] Note that HAL_HASH_IRQHandler() manages as well HASH Peripheral interruptions when in
884          HMAC processing mode.
885 
886 
887 @endverbatim
888   * @{
889   */
890 
891 /**
892   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
893   *         read the computed digest in interruption mode.
894   * @note   Digest is available in pOutBuffer.
895   * @param  hhash HASH handle.
896   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
897   * @param  Size length of the input buffer in bytes.
898   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
899   * @retval HAL status
900   */
HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)901 HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
902                                         uint8_t *pOutBuffer)
903 {
904   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
905 }
906 
907 /**
908   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
909   *         processes pInBuffer in interruption mode.
910   * @note   Consecutive calls to HAL_HASH_MD5_Accmlt_IT() can be used to feed
911   *         several input buffers back-to-back to the Peripheral that will yield a single
912   *         HASH signature once all buffers have been entered. Wrap-up of input
913   *         buffers feeding and retrieval of digest is done by a call to
914   *         HAL_HASH_MD5_Accmlt_End_IT().
915   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
916   *         the Peripheral has already been initialized.
917   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
918   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End_IT() is able
919   *         to manage the ending buffer with a length in bytes not a multiple of 4.
920   * @param  hhash HASH handle.
921   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
922   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
923   * @retval HAL status
924   */
HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)925 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
926 {
927   return  HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
928 }
929 
930 /**
931   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt_IT() API.
932   * @note   Digest is available in pOutBuffer.
933   * @param  hhash HASH handle.
934   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
935   * @param  Size length of the input buffer in bytes.
936   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
937   * @retval HAL status
938   */
HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)939 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
940                                              uint8_t *pOutBuffer)
941 {
942   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
943 }
944 
945 /**
946   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
947   *         read the computed digest in interruption mode.
948   * @note   Digest is available in pOutBuffer.
949   * @param  hhash HASH handle.
950   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
951   * @param  Size length of the input buffer in bytes.
952   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
953   * @retval HAL status
954   */
HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)955 HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
956                                          uint8_t *pOutBuffer)
957 {
958   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
959 }
960 
961 
962 /**
963   * @brief  If not already done, initialize the HASH peripheral in SHA1 mode then
964   *         processes pInBuffer in interruption mode.
965   * @note   Consecutive calls to HAL_HASH_SHA1_Accmlt_IT() can be used to feed
966   *         several input buffers back-to-back to the Peripheral that will yield a single
967   *         HASH signature once all buffers have been entered. Wrap-up of input
968   *         buffers feeding and retrieval of digest is done by a call to
969   *         HAL_HASH_SHA1_Accmlt_End_IT().
970   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
971   *         the Peripheral has already been initialized.
972   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
973   *         HASH digest computation is corrupted. Only HAL_HASH_SHA1_Accmlt_End_IT() is able
974   *         to manage the ending buffer with a length in bytes not a multiple of 4.
975   * @param  hhash HASH handle.
976   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
977   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
978   * @retval HAL status
979   */
HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)980 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
981 {
982   return  HASH_Accumulate_IT(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
983 }
984 
985 /**
986   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_SHA1_Accmlt_IT() API.
987   * @note   Digest is available in pOutBuffer.
988   * @param  hhash HASH handle.
989   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
990   * @param  Size length of the input buffer in bytes.
991   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
992   * @retval HAL status
993   */
HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)994 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
995                                               uint8_t *pOutBuffer)
996 {
997   return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
998 }
999 
1000 /**
1001   * @brief Handle HASH interrupt request.
1002   * @param hhash HASH handle.
1003   * @note  HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well.
1004   * @note  In case of error reported during the HASH interruption processing,
1005   *        HAL_HASH_ErrorCallback() API is called so that user code can
1006   *        manage the error. The error type is available in hhash->Status field.
1007   * @retval None
1008   */
HAL_HASH_IRQHandler(HASH_HandleTypeDef * hhash)1009 void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash)
1010 {
1011   hhash->Status = HASH_IT(hhash);
1012   if (hhash->Status != HAL_OK)
1013   {
1014     hhash->ErrorCode |= HAL_HASH_ERROR_IT;
1015 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1016     hhash->ErrorCallback(hhash);
1017 #else
1018     HAL_HASH_ErrorCallback(hhash);
1019 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1020     /* After error handling by code user, reset HASH handle HAL status */
1021     hhash->Status = HAL_OK;
1022   }
1023 }
1024 
1025 /**
1026   * @}
1027   */
1028 
1029 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode
1030   *  @brief   HASH processing functions using DMA mode.
1031   *
1032 @verbatim
1033  ===============================================================================
1034                     ##### DMA mode HASH processing functions #####
1035  ===============================================================================
1036     [..]  This section provides functions allowing to calculate in DMA mode
1037           the hash value using one of the following algorithms:
1038       (+) MD5
1039          (++) HAL_HASH_MD5_Start_DMA()
1040          (++) HAL_HASH_MD5_Finish()
1041       (+) SHA1
1042          (++) HAL_HASH_SHA1_Start_DMA()
1043          (++) HAL_HASH_SHA1_Finish()
1044 
1045     [..]  When resorting to DMA mode to enter the data in the Peripheral, user must resort
1046           to  HAL_HASH_xxx_Start_DMA() then read the resulting digest with
1047           HAL_HASH_xxx_Finish().
1048 
1049 @endverbatim
1050   * @{
1051   */
1052 
1053 /**
1054   * @brief  Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer
1055   *         to feed the input buffer to the Peripheral.
1056   * @note   Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must
1057   *         be called to retrieve the computed digest.
1058   * @param  hhash HASH handle.
1059   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1060   * @param  Size length of the input buffer in bytes.
1061   * @retval HAL status
1062   */
HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1063 HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1064 {
1065   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
1066 }
1067 
1068 /**
1069   * @brief  Return the computed digest in MD5 mode.
1070   * @note   The API waits for DCIS to be set then reads the computed digest.
1071   * @note   HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in
1072   *         HMAC MD5 mode.
1073   * @param  hhash HASH handle.
1074   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1075   * @param  Timeout Timeout value.
1076   * @retval HAL status
1077   */
HAL_HASH_MD5_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)1078 HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
1079 {
1080   return HASH_Finish(hhash, pOutBuffer, Timeout);
1081 }
1082 
1083 /**
1084   * @brief  Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer
1085   *         to feed the input buffer to the Peripheral.
1086   * @note   Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must
1087   *         be called to retrieve the computed digest.
1088   * @param  hhash HASH handle.
1089   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1090   * @param  Size length of the input buffer in bytes.
1091   * @retval HAL status
1092   */
HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1093 HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1094 {
1095   return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1096 }
1097 
1098 
1099 /**
1100   * @brief  Return the computed digest in SHA1 mode.
1101   * @note   The API waits for DCIS to be set then reads the computed digest.
1102   * @note   HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in
1103   *         HMAC SHA1 mode.
1104   * @param  hhash HASH handle.
1105   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1106   * @param  Timeout Timeout value.
1107   * @retval HAL status
1108   */
HAL_HASH_SHA1_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)1109 HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
1110 {
1111   return HASH_Finish(hhash, pOutBuffer, Timeout);
1112 }
1113 
1114 /**
1115   * @}
1116   */
1117 
1118 /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode
1119   *  @brief   HMAC processing functions using polling mode.
1120   *
1121 @verbatim
1122  ===============================================================================
1123                  ##### Polling mode HMAC processing functions #####
1124  ===============================================================================
1125     [..]  This section provides functions allowing to calculate in polling mode
1126           the HMAC value using one of the following algorithms:
1127       (+) MD5
1128          (++) HAL_HMAC_MD5_Start()
1129       (+) SHA1
1130          (++) HAL_HMAC_SHA1_Start()
1131 
1132 
1133 @endverbatim
1134   * @{
1135   */
1136 
1137 /**
1138   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1139   *         read the computed digest.
1140   * @note   Digest is available in pOutBuffer.
1141   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1142   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1143   * @param  hhash HASH handle.
1144   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1145   * @param  Size length of the input buffer in bytes.
1146   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1147   * @param  Timeout Timeout value.
1148   * @retval HAL status
1149   */
HAL_HMAC_MD5_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)1150 HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
1151                                      uint32_t Timeout)
1152 {
1153   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
1154 }
1155 
1156 /**
1157   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1158   *         read the computed digest.
1159   * @note   Digest is available in pOutBuffer.
1160   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1161   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1162   * @param  hhash HASH handle.
1163   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1164   * @param  Size length of the input buffer in bytes.
1165   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1166   * @param  Timeout Timeout value.
1167   * @retval HAL status
1168   */
HAL_HMAC_SHA1_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)1169 HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
1170                                       uint32_t Timeout)
1171 {
1172   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
1173 }
1174 
1175 /**
1176   * @}
1177   */
1178 
1179 
1180 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
1181   *  @brief   HMAC processing functions using interrupt mode.
1182   *
1183 @verbatim
1184  ===============================================================================
1185                  ##### Interrupt mode HMAC processing functions #####
1186  ===============================================================================
1187     [..]  This section provides functions allowing to calculate in interrupt mode
1188           the HMAC value using one of the following algorithms:
1189       (+) MD5
1190          (++) HAL_HMAC_MD5_Start_IT()
1191       (+) SHA1
1192          (++) HAL_HMAC_SHA1_Start_IT()
1193 
1194 @endverbatim
1195   * @{
1196   */
1197 
1198 
1199 /**
1200   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1201   *         read the computed digest in interrupt mode.
1202   * @note   Digest is available in pOutBuffer.
1203   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1204   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1205   * @param  hhash HASH handle.
1206   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1207   * @param  Size length of the input buffer in bytes.
1208   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1209   * @retval HAL status
1210   */
HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1211 HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
1212                                         uint8_t *pOutBuffer)
1213 {
1214   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
1215 }
1216 
1217 /**
1218   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1219   *         read the computed digest in interrupt mode.
1220   * @note   Digest is available in pOutBuffer.
1221   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1222   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1223   * @param  hhash HASH handle.
1224   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1225   * @param  Size length of the input buffer in bytes.
1226   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1227   * @retval HAL status
1228   */
HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1229 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size,
1230                                          uint8_t *pOutBuffer)
1231 {
1232   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
1233 }
1234 
1235 /**
1236   * @}
1237   */
1238 
1239 
1240 
1241 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
1242   *  @brief   HMAC processing functions using DMA modes.
1243   *
1244 @verbatim
1245  ===============================================================================
1246                  ##### DMA mode HMAC processing functions #####
1247  ===============================================================================
1248     [..]  This section provides functions allowing to calculate in DMA mode
1249           the HMAC value using one of the following algorithms:
1250       (+) MD5
1251          (++) HAL_HMAC_MD5_Start_DMA()
1252       (+) SHA1
1253          (++) HAL_HMAC_SHA1_Start_DMA()
1254 
1255     [..]  When resorting to DMA mode to enter the data in the Peripheral for HMAC processing,
1256           user must resort to  HAL_HMAC_xxx_Start_DMA() then read the resulting digest
1257           with HAL_HASH_xxx_Finish().
1258 
1259 @endverbatim
1260   * @{
1261   */
1262 
1263 
1264 /**
1265   * @brief  Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
1266   *         DMA transfers to feed the key and the input buffer to the Peripheral.
1267   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1268   *         to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
1269   *         the computed digest.
1270   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1271   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1272   * @param  hhash HASH handle.
1273   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1274   * @param  Size length of the input buffer in bytes.
1275   * @retval HAL status
1276   */
HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1277 HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1278 {
1279   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
1280 }
1281 
1282 
1283 /**
1284   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
1285   *         DMA transfers to feed the key and the input buffer to the Peripheral.
1286   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1287   *         to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
1288   *         the computed digest.
1289   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1290   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1291   * @param  hhash HASH handle.
1292   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1293   * @param  Size length of the input buffer in bytes.
1294   * @retval HAL status
1295   */
HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1296 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1297 {
1298   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1299 }
1300 
1301 /**
1302   * @}
1303   */
1304 
1305 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
1306   *  @brief   Peripheral State functions.
1307   *
1308 @verbatim
1309  ===============================================================================
1310                       ##### Peripheral State methods #####
1311  ===============================================================================
1312     [..]
1313     This section permits to get in run-time the state and the peripheral handle
1314     status of the peripheral:
1315       (+) HAL_HASH_GetState()
1316       (+) HAL_HASH_GetStatus()
1317 
1318     [..]
1319     Additionally, this subsection provides functions allowing to save and restore
1320     the HASH or HMAC processing context in case of calculation suspension:
1321       (+) HAL_HASH_ContextSaving()
1322       (+) HAL_HASH_ContextRestoring()
1323 
1324     [..]
1325     This subsection provides functions allowing to suspend the HASH processing
1326       (+) when input are fed to the Peripheral by software
1327           (++) HAL_HASH_SwFeed_ProcessSuspend()
1328       (+) when input are fed to the Peripheral by DMA
1329           (++) HAL_HASH_DMAFeed_ProcessSuspend()
1330 
1331 
1332 
1333 @endverbatim
1334   * @{
1335   */
1336 
1337 /**
1338   * @brief  Return the HASH handle state.
1339   * @note   The API yields the current state of the handle (BUSY, READY,...).
1340   * @param  hhash HASH handle.
1341   * @retval HAL HASH state
1342   */
HAL_HASH_GetState(HASH_HandleTypeDef * hhash)1343 HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash)
1344 {
1345   return hhash->State;
1346 }
1347 
1348 
1349 /**
1350   * @brief Return the HASH HAL status.
1351   * @note  The API yields the HAL status of the handle: it is the result of the
1352   *        latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
1353   * @param  hhash HASH handle.
1354   * @retval HAL status
1355   */
HAL_HASH_GetStatus(HASH_HandleTypeDef * hhash)1356 HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash)
1357 {
1358   return hhash->Status;
1359 }
1360 
1361 /**
1362   * @brief  Save the HASH context in case of processing suspension.
1363   * @param  hhash HASH handle.
1364   * @param  pMemBuffer pointer to the memory buffer where the HASH context
1365   *         is saved.
1366   * @note   The IMR, STR, CR then all the CSR registers are saved
1367   *         in that order. Only the r/w bits are read to be restored later on.
1368   * @note   By default, all the context swap registers (there are
1369   *         HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
1370   * @note   pMemBuffer points to a buffer allocated by the user. The buffer size
1371   *         must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
1372   * @retval None
1373   */
HAL_HASH_ContextSaving(HASH_HandleTypeDef * hhash,uint8_t * pMemBuffer)1374 void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
1375 {
1376   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1377   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1378   uint32_t i;
1379 
1380   /* Prevent unused argument(s) compilation warning */
1381   UNUSED(hhash);
1382 
1383   /* Save IMR register content */
1384   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->IMR, HASH_IT_DINI | HASH_IT_DCI);
1385   mem_ptr += 4U;
1386   /* Save STR register content */
1387   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->STR, HASH_STR_NBLW);
1388   mem_ptr += 4U;
1389   /* Save CR register content */
1390   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->CR, HASH_CR_DMAE | HASH_CR_DATATYPE | HASH_CR_MODE | HASH_CR_ALGO |
1391                                     HASH_CR_LKEY);
1392   mem_ptr += 4U;
1393   /* By default, save all CSRs registers */
1394   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
1395   {
1396     *(uint32_t *)(mem_ptr) = *(uint32_t *)(csr_ptr);
1397     mem_ptr += 4U;
1398     csr_ptr += 4U;
1399   }
1400 }
1401 
1402 
1403 /**
1404   * @brief  Restore the HASH context in case of processing resumption.
1405   * @param  hhash HASH handle.
1406   * @param  pMemBuffer pointer to the memory buffer where the HASH context
1407   *         is stored.
1408   * @note   The IMR, STR, CR then all the CSR registers are restored
1409   *         in that order. Only the r/w bits are restored.
1410   * @note   By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
1411   *         of those) are restored (all of them have been saved by default
1412   *         beforehand).
1413   * @retval None
1414   */
HAL_HASH_ContextRestoring(HASH_HandleTypeDef * hhash,uint8_t * pMemBuffer)1415 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t *pMemBuffer)
1416 {
1417   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1418   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1419   uint32_t i;
1420 
1421   /* Prevent unused argument(s) compilation warning */
1422   UNUSED(hhash);
1423 
1424   /* Restore IMR register content */
1425   WRITE_REG(HASH->IMR, (*(uint32_t *)(mem_ptr)));
1426   mem_ptr += 4U;
1427   /* Restore STR register content */
1428   WRITE_REG(HASH->STR, (*(uint32_t *)(mem_ptr)));
1429   mem_ptr += 4U;
1430   /* Restore CR register content */
1431   WRITE_REG(HASH->CR, (*(uint32_t *)(mem_ptr)));
1432   mem_ptr += 4U;
1433 
1434   /* Reset the HASH processor before restoring the Context
1435   Swap Registers (CSR) */
1436   __HAL_HASH_INIT();
1437 
1438   /* By default, restore all CSR registers */
1439   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
1440   {
1441     WRITE_REG((*(uint32_t *)(csr_ptr)), (*(uint32_t *)(mem_ptr)));
1442     mem_ptr += 4U;
1443     csr_ptr += 4U;
1444   }
1445 }
1446 
1447 
1448 /**
1449   * @brief  Initiate HASH processing suspension when in polling or interruption mode.
1450   * @param  hhash HASH handle.
1451   * @note   Set the handle field SuspendRequest to the appropriate value so that
1452   *         the on-going HASH processing is suspended as soon as the required
1453   *         conditions are met. Note that the actual suspension is carried out
1454   *         by the functions HASH_WriteData() in polling mode and HASH_IT() in
1455   *         interruption mode.
1456   * @retval None
1457   */
HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef * hhash)1458 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1459 {
1460   /* Set Handle Suspend Request field */
1461   hhash->SuspendRequest = HAL_HASH_SUSPEND;
1462 }
1463 
1464 /**
1465   * @brief  Suspend the HASH processing when in DMA mode.
1466   * @param  hhash HASH handle.
1467   * @note   When suspension attempt occurs at the very end of a DMA transfer and
1468   *         all the data have already been entered in the Peripheral, hhash->State is
1469   *         set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
1470   *         recommended to wrap-up the processing in reading the digest as usual.
1471   * @retval HAL status
1472   */
HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef * hhash)1473 HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1474 {
1475   uint32_t tmp_remaining_DMATransferSize_inWords;
1476   uint32_t tmp_initial_DMATransferSize_inWords;
1477   uint32_t tmp_words_already_pushed;
1478 
1479   if (hhash->State == HAL_HASH_STATE_READY)
1480   {
1481     return HAL_ERROR;
1482   }
1483   else
1484   {
1485 
1486     /* Make sure there is enough time to suspend the processing */
1487     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1488 
1489     if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT)
1490     {
1491       /* No suspension attempted since almost to the end of the transferred data. */
1492       /* Best option for user code is to wrap up low priority message hashing     */
1493       return HAL_ERROR;
1494     }
1495 
1496     /* Wait for BUSY flag to be reset */
1497     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1498     {
1499       return HAL_TIMEOUT;
1500     }
1501 
1502     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1503     {
1504       return HAL_ERROR;
1505     }
1506 
1507     /* Wait for BUSY flag to be set */
1508     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK)
1509     {
1510       return HAL_TIMEOUT;
1511     }
1512     /* Disable DMA channel */
1513     /* Note that the Abort function will
1514       - Clear the transfer error flags
1515       - Unlock
1516       - Set the State
1517     */
1518     if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK)
1519     {
1520       return HAL_ERROR;
1521     }
1522 
1523     /* Clear DMAE bit */
1524     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1525 
1526     /* Wait for BUSY flag to be reset */
1527     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1528     {
1529       return HAL_TIMEOUT;
1530     }
1531 
1532     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1533     {
1534       return HAL_ERROR;
1535     }
1536 
1537     /* At this point, DMA interface is disabled and no transfer is on-going */
1538     /* Retrieve from the DMA handle how many words remain to be written */
1539     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1540 
1541     if (tmp_remaining_DMATransferSize_inWords == 0U)
1542     {
1543       /* All the DMA transfer is actually done. Suspension occurred at the very end
1544          of the transfer. Either the digest computation is about to start (HASH case)
1545          or processing is about to move from one step to another (HMAC case).
1546          In both cases, the processing can't be suspended at this point. It is
1547          safer to
1548          - retrieve the low priority block digest before starting the high
1549            priority block processing (HASH case)
1550          - re-attempt a new suspension (HMAC case)
1551          */
1552       return HAL_ERROR;
1553     }
1554     else
1555     {
1556 
1557       /* Compute how many words were supposed to be transferred by DMA */
1558       tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount % 4U) != 0U) ? \
1559                                              ((hhash->HashInCount + 3U) / 4U) : (hhash->HashInCount / 4U));
1560 
1561       /* If discrepancy between the number of words reported by DMA Peripheral and
1562         the numbers of words entered as reported by HASH Peripheral, correct it */
1563       /* tmp_words_already_pushed reflects the number of words that were already pushed before
1564          the start of DMA transfer (multi-buffer processing case) */
1565       tmp_words_already_pushed = hhash->NbWordsAlreadyPushed;
1566       if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - \
1567             tmp_remaining_DMATransferSize_inWords) % 16U) != HASH_NBW_PUSHED())
1568       {
1569         tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */
1570       }
1571 
1572       /* Accordingly, update the input pointer that points at the next word to be
1573          transferred to the Peripheral by DMA */
1574       hhash->pHashInBuffPtr +=  4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ;
1575 
1576       /* And store in HashInCount the remaining size to transfer (in bytes) */
1577       hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords;
1578 
1579     }
1580 
1581     /* Set State as suspended */
1582     hhash->State = HAL_HASH_STATE_SUSPENDED;
1583 
1584     return HAL_OK;
1585 
1586   }
1587 }
1588 
1589 /**
1590   * @brief  Return the HASH handle error code.
1591   * @param  hhash pointer to a HASH_HandleTypeDef structure.
1592   * @retval HASH Error Code
1593   */
HAL_HASH_GetError(HASH_HandleTypeDef * hhash)1594 uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash)
1595 {
1596   /* Return HASH Error Code */
1597   return hhash->ErrorCode;
1598 }
1599 /**
1600   * @}
1601   */
1602 
1603 
1604 /**
1605   * @}
1606   */
1607 
1608 /** @defgroup HASH_Private_Functions HASH Private Functions
1609   * @{
1610   */
1611 
1612 /**
1613   * @brief DMA HASH Input Data transfer completion callback.
1614   * @param hdma DMA handle.
1615   * @note  In case of HMAC processing, HASH_DMAXferCplt() initiates
1616   *        the next DMA transfer for the following HMAC step.
1617   * @retval None
1618   */
HASH_DMAXferCplt(DMA_HandleTypeDef * hdma)1619 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma)
1620 {
1621   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1622   uint32_t inputaddr;
1623   uint32_t buffersize;
1624   HAL_StatusTypeDef status;
1625 
1626   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1627   {
1628 
1629     /* Disable the DMA transfer */
1630     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1631 
1632     if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U)
1633     {
1634       /* If no HMAC processing, input data transfer is now over */
1635 
1636       /* Change the HASH state to ready */
1637       hhash->State = HAL_HASH_STATE_READY;
1638 
1639       /* Call Input data transfer complete call back */
1640 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1641       hhash->InCpltCallback(hhash);
1642 #else
1643       HAL_HASH_InCpltCallback(hhash);
1644 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1645 
1646     }
1647     else
1648     {
1649       /* HMAC processing: depending on the current HMAC step and whether or
1650       not multi-buffer processing is on-going, the next step is initiated
1651       and MDMAT bit is set.  */
1652 
1653 
1654       if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
1655       {
1656         /* This is the end of HMAC processing */
1657 
1658         /* Change the HASH state to ready */
1659         hhash->State = HAL_HASH_STATE_READY;
1660 
1661         /* Call Input data transfer complete call back
1662         (note that the last DMA transfer was that of the key
1663         for the outer HASH operation). */
1664 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1665         hhash->InCpltCallback(hhash);
1666 #else
1667         HAL_HASH_InCpltCallback(hhash);
1668 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1669 
1670         return;
1671       }
1672       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
1673       {
1674         inputaddr = (uint32_t)hhash->pHashMsgBuffPtr;     /* DMA transfer start address */
1675         buffersize = hhash->HashBuffSize;                 /* DMA transfer size (in bytes) */
1676         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
1677 
1678         /* In case of suspension request, save the new starting parameters */
1679         hhash->HashInCount = hhash->HashBuffSize;         /* Initial DMA transfer size (in bytes) */
1680         hhash->pHashInBuffPtr  = hhash->pHashMsgBuffPtr ; /* DMA transfer start address           */
1681 
1682         hhash->NbWordsAlreadyPushed = 0U;                  /* Reset number of words already pushed */
1683       }
1684       else  /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
1685       {
1686         if (hhash->DigestCalculationDisable != RESET)
1687         {
1688           /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral
1689           (case of multi-buffer HMAC processing):
1690           DCAL must not be set.
1691           Phase remains in Step 2, MDMAT remains set at this point.
1692           Change the HASH state to ready and call Input data transfer complete call back. */
1693           hhash->State = HAL_HASH_STATE_READY;
1694 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1695           hhash->InCpltCallback(hhash);
1696 #else
1697           HAL_HASH_InCpltCallback(hhash);
1698 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1699           return ;
1700         }
1701         else
1702         {
1703           /* Digest calculation is not disabled (case of single buffer input or last buffer
1704           of multi-buffer HMAC processing) */
1705           inputaddr = (uint32_t)hhash->Init.pKey;       /* DMA transfer start address */
1706           buffersize = hhash->Init.KeySize;             /* DMA transfer size (in bytes) */
1707           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;    /* Move phase from Step 2 to Step 3 */
1708           /* In case of suspension request, save the new starting parameters */
1709           hhash->HashInCount = hhash->Init.KeySize;     /* Initial size for second DMA transfer (input data) */
1710           hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* address passed to DMA, now entering data message */
1711 
1712           hhash->NbWordsAlreadyPushed = 0U;              /* Reset number of words already pushed */
1713         }
1714       }
1715 
1716       /* Configure the Number of valid bits in last word of the message */
1717       __HAL_HASH_SET_NBVALIDBITS(buffersize);
1718 
1719       /* Set the HASH DMA transfer completion call back */
1720       hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
1721 
1722       /* Enable the DMA In DMA stream */
1723       status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
1724                                 (((buffersize % 4U) != 0U) ? ((buffersize + (4U - (buffersize % 4U))) / 4U) : \
1725                                  (buffersize / 4U)));
1726 
1727       /* Enable DMA requests */
1728       SET_BIT(HASH->CR, HASH_CR_DMAE);
1729 
1730       /* Return function status */
1731       if (status != HAL_OK)
1732       {
1733         /* Update HASH state machine to error */
1734         hhash->State = HAL_HASH_STATE_ERROR;
1735       }
1736       else
1737       {
1738         /* Change HASH state */
1739         hhash->State = HAL_HASH_STATE_BUSY;
1740       }
1741     }
1742   }
1743 
1744   return;
1745 }
1746 
1747 /**
1748   * @brief DMA HASH communication error callback.
1749   * @param hdma DMA handle.
1750   * @note  HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
1751   *        can contain user code to manage the error.
1752   * @retval None
1753   */
HASH_DMAError(DMA_HandleTypeDef * hdma)1754 static void HASH_DMAError(DMA_HandleTypeDef *hdma)
1755 {
1756   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1757 
1758   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1759   {
1760     hhash->ErrorCode |= HAL_HASH_ERROR_DMA;
1761     /* Set HASH state to ready to prevent any blocking issue in user code
1762        present in HAL_HASH_ErrorCallback() */
1763     hhash->State = HAL_HASH_STATE_READY;
1764     /* Set HASH handle status to error */
1765     hhash->Status = HAL_ERROR;
1766 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1767     hhash->ErrorCallback(hhash);
1768 #else
1769     HAL_HASH_ErrorCallback(hhash);
1770 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1771     /* After error handling by code user, reset HASH handle HAL status */
1772     hhash->Status = HAL_OK;
1773 
1774   }
1775 }
1776 
1777 /**
1778   * @brief  Feed the input buffer to the HASH Peripheral.
1779   * @param  hhash HASH handle.
1780   * @param  pInBuffer pointer to input buffer.
1781   * @param  Size the size of input buffer in bytes.
1782   * @note   HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
1783   *         or not the HASH processing must be suspended. If this is the case, the
1784   *         processing is suspended when possible and the Peripheral feeding point reached at
1785   *         suspension time is stored in the handle for resumption later on.
1786   * @retval HAL status
1787   */
HASH_WriteData(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size)1788 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1789 {
1790   uint32_t buffercounter;
1791   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
1792 
1793   for (buffercounter = 0U; buffercounter < Size; buffercounter += 4U)
1794   {
1795     /* Write input data 4 bytes at a time */
1796     HASH->DIN = *(uint32_t *)inputaddr;
1797     inputaddr += 4U;
1798 
1799     /* If the suspension flag has been raised and if the processing is not about
1800     to end, suspend processing */
1801     if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter + 4U) < Size))
1802     {
1803       /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
1804       in the input buffer */
1805       if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
1806       {
1807         /* Reset SuspendRequest */
1808         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
1809 
1810         /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
1811         reached at suspension time is not saved in the same handle fields */
1812         if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
1813         {
1814           /* Save current reading and writing locations of Input and Output buffers */
1815           hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
1816           /* Save the number of bytes that remain to be processed at this point */
1817           hhash->HashInCount    =  Size - (buffercounter + 4U);
1818         }
1819         else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
1820         {
1821           /* Save current reading and writing locations of Input and Output buffers */
1822           hhash->pHashKeyBuffPtr  = (uint8_t *)inputaddr;
1823           /* Save the number of bytes that remain to be processed at this point */
1824           hhash->HashKeyCount  =  Size - (buffercounter + 4U);
1825         }
1826         else
1827         {
1828           /* Unexpected phase: unlock process and report error */
1829           hhash->State = HAL_HASH_STATE_READY;
1830           __HAL_UNLOCK(hhash);
1831           return HAL_ERROR;
1832         }
1833 
1834         /* Set the HASH state to Suspended and exit to stop entering data */
1835         hhash->State = HAL_HASH_STATE_SUSPENDED;
1836 
1837         return HAL_OK;
1838       } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))  */
1839     } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
1840   }   /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4)                 */
1841 
1842   /* At this point, all the data have been entered to the Peripheral: exit */
1843   return  HAL_OK;
1844 }
1845 
1846 /**
1847   * @brief  Retrieve the message digest.
1848   * @param  pMsgDigest pointer to the computed digest.
1849   * @param  Size message digest size in bytes.
1850   * @retval None
1851   */
HASH_GetDigest(uint8_t * pMsgDigest,uint8_t Size)1852 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
1853 {
1854   uint32_t msgdigest = (uint32_t)pMsgDigest;
1855 
1856   switch (Size)
1857   {
1858     /* Read the message digest */
1859     case 16:  /* MD5 */
1860       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1861       msgdigest += 4U;
1862       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1863       msgdigest += 4U;
1864       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1865       msgdigest += 4U;
1866       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1867       break;
1868     case 20:  /* SHA1 */
1869       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1870       msgdigest += 4U;
1871       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1872       msgdigest += 4U;
1873       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1874       msgdigest += 4U;
1875       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1876       msgdigest += 4U;
1877       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
1878       break;
1879     default:
1880       break;
1881   }
1882 }
1883 
1884 
1885 
1886 /**
1887   * @brief  Handle HASH processing Timeout.
1888   * @param  hhash HASH handle.
1889   * @param  Flag specifies the HASH flag to check.
1890   * @param  Status the Flag status (SET or RESET).
1891   * @param  Timeout Timeout duration.
1892   * @retval HAL status
1893   */
HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef * hhash,uint32_t Flag,FlagStatus Status,uint32_t Timeout)1894 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
1895                                                      uint32_t Timeout)
1896 {
1897   uint32_t tickstart = HAL_GetTick();
1898 
1899   /* Wait until flag is set */
1900   if (Status == RESET)
1901   {
1902     while (__HAL_HASH_GET_FLAG(Flag) == RESET)
1903     {
1904       /* Check for the Timeout */
1905       if (Timeout != HAL_MAX_DELAY)
1906       {
1907         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1908         {
1909           /* Set State to Ready to be able to restart later on */
1910           hhash->State  = HAL_HASH_STATE_READY;
1911           /* Store time out issue in handle status */
1912           hhash->Status = HAL_TIMEOUT;
1913 
1914           /* Process Unlocked */
1915           __HAL_UNLOCK(hhash);
1916 
1917           return HAL_TIMEOUT;
1918         }
1919       }
1920     }
1921   }
1922   else
1923   {
1924     while (__HAL_HASH_GET_FLAG(Flag) != RESET)
1925     {
1926       /* Check for the Timeout */
1927       if (Timeout != HAL_MAX_DELAY)
1928       {
1929         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
1930         {
1931           /* Set State to Ready to be able to restart later on */
1932           hhash->State  = HAL_HASH_STATE_READY;
1933           /* Store time out issue in handle status */
1934           hhash->Status = HAL_TIMEOUT;
1935 
1936           /* Process Unlocked */
1937           __HAL_UNLOCK(hhash);
1938 
1939           return HAL_TIMEOUT;
1940         }
1941       }
1942     }
1943   }
1944   return HAL_OK;
1945 }
1946 
1947 
1948 /**
1949   * @brief  HASH processing in interruption mode.
1950   * @param  hhash HASH handle.
1951   * @note   HASH_IT() regularly reads hhash->SuspendRequest to check whether
1952   *         or not the HASH processing must be suspended. If this is the case, the
1953   *         processing is suspended when possible and the Peripheral feeding point reached at
1954   *         suspension time is stored in the handle for resumption later on.
1955   * @retval HAL status
1956   */
HASH_IT(HASH_HandleTypeDef * hhash)1957 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
1958 {
1959   if (hhash->State == HAL_HASH_STATE_BUSY)
1960   {
1961     /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
1962     if (hhash->HashITCounter == 0U)
1963     {
1964       /* Disable Interrupts */
1965       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
1966       /* HASH state set back to Ready to prevent any issue in user code
1967          present in HAL_HASH_ErrorCallback() */
1968       hhash->State = HAL_HASH_STATE_READY;
1969       return HAL_ERROR;
1970     }
1971     else if (hhash->HashITCounter == 1U)
1972     {
1973       /* This is the first call to HASH_IT, the first input data are about to be
1974          entered in the Peripheral. A specific processing is carried out at this point to
1975          start-up the processing. */
1976       hhash->HashITCounter = 2U;
1977     }
1978     else
1979     {
1980       /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
1981         the HASH processing or the end of the current step for HMAC processing. */
1982       hhash->HashITCounter = 3U;
1983     }
1984 
1985     /* If digest is ready */
1986     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
1987     {
1988       /* Read the digest */
1989       HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
1990 
1991       /* Disable Interrupts */
1992       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
1993       /* Change the HASH state */
1994       hhash->State = HAL_HASH_STATE_READY;
1995       /* Reset HASH state machine */
1996       hhash->Phase = HAL_HASH_PHASE_READY;
1997       /* Call digest computation complete call back */
1998 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1999       hhash->DgstCpltCallback(hhash);
2000 #else
2001       HAL_HASH_DgstCpltCallback(hhash);
2002 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2003 
2004       return HAL_OK;
2005     }
2006 
2007     /* If Peripheral ready to accept new data */
2008     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2009     {
2010 
2011       /* If the suspension flag has been raised and if the processing is not about
2012          to end, suspend processing */
2013       if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
2014       {
2015         /* Disable Interrupts */
2016         __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2017 
2018         /* Reset SuspendRequest */
2019         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
2020 
2021         /* Change the HASH state */
2022         hhash->State = HAL_HASH_STATE_SUSPENDED;
2023 
2024         return HAL_OK;
2025       }
2026 
2027       /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and
2028         check whether the digest calculation has been triggered */
2029       if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
2030       {
2031         /* Call Input data transfer complete call back
2032            (called at the end of each step for HMAC) */
2033 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2034         hhash->InCpltCallback(hhash);
2035 #else
2036         HAL_HASH_InCpltCallback(hhash);
2037 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2038 
2039         if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2040         {
2041           /* Wait until Peripheral is not busy anymore */
2042           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2043           {
2044             /* Disable Interrupts */
2045             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2046             return HAL_TIMEOUT;
2047           }
2048           /* Initialization start for HMAC STEP 2 */
2049           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
2050           __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);  /* Set NBLW for the input message */
2051           hhash->HashInCount = hhash->HashBuffSize;         /* Set the input data size (in bytes) */
2052           hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr;   /* Set the input data address */
2053           hhash->HashITCounter = 1;                         /* Set ITCounter to 1 to indicate the start
2054                                                                of a new phase */
2055           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);               /* Enable IT (was disabled in HASH_Write_Block_Data) */
2056         }
2057         else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2058         {
2059           /* Wait until Peripheral is not busy anymore */
2060           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2061           {
2062             /* Disable Interrupts */
2063             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2064             return HAL_TIMEOUT;
2065           }
2066           /* Initialization start for HMAC STEP 3 */
2067           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;         /* Move phase from Step 2 to Step 3 */
2068           __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);   /* Set NBLW for the key */
2069           hhash->HashInCount = hhash->Init.KeySize;          /* Set the key size (in bytes) */
2070           hhash->pHashInBuffPtr = hhash->Init.pKey;          /* Set the key address */
2071           hhash->HashITCounter = 1;                          /* Set ITCounter to 1 to indicate the start
2072                                                                 of a new phase */
2073           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);                /* Enable IT (was disabled in HASH_Write_Block_Data) */
2074         }
2075         else
2076         {
2077           /* Nothing to do */
2078         }
2079       } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
2080     }  /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
2081 
2082     /* Return function status */
2083     return HAL_OK;
2084   }
2085   else
2086   {
2087     return HAL_BUSY;
2088   }
2089 }
2090 
2091 
2092 /**
2093   * @brief  Write a block of data in HASH Peripheral in interruption mode.
2094   * @param  hhash HASH handle.
2095   * @note   HASH_Write_Block_Data() is called under interruption by HASH_IT().
2096   * @retval HAL status
2097   */
HASH_Write_Block_Data(HASH_HandleTypeDef * hhash)2098 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
2099 {
2100   uint32_t inputaddr;
2101   uint32_t buffercounter;
2102   uint32_t inputcounter;
2103   uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
2104 
2105   /* If there are more than 64 bytes remaining to be entered */
2106   if (hhash->HashInCount > 64U)
2107   {
2108     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2109     /* Write the Input block in the Data IN register
2110       (16 32-bit words, or 64 bytes are entered) */
2111     for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U)
2112     {
2113       HASH->DIN = *(uint32_t *)inputaddr;
2114       inputaddr += 4U;
2115     }
2116     /* If this is the start of input data entering, an additional word
2117       must be entered to start up the HASH processing */
2118     if (hhash->HashITCounter == 2U)
2119     {
2120       HASH->DIN = *(uint32_t *)inputaddr;
2121       if (hhash->HashInCount >= 68U)
2122       {
2123         /* There are still data waiting to be entered in the Peripheral.
2124            Decrement buffer counter and set pointer to the proper
2125            memory location for the next data entering round. */
2126         hhash->HashInCount -= 68U;
2127         hhash->pHashInBuffPtr += 68U;
2128       }
2129       else
2130       {
2131         /* All the input buffer has been fed to the HW. */
2132         hhash->HashInCount = 0U;
2133       }
2134     }
2135     else
2136     {
2137       /* 64 bytes have been entered and there are still some remaining:
2138          Decrement buffer counter and set pointer to the proper
2139         memory location for the next data entering round.*/
2140       hhash->HashInCount -= 64U;
2141       hhash->pHashInBuffPtr += 64U;
2142     }
2143   }
2144   else
2145   {
2146     /* 64 or less bytes remain to be entered. This is the last
2147       data entering round. */
2148 
2149     /* Get the buffer address */
2150     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2151     /* Get the buffer counter */
2152     inputcounter = hhash->HashInCount;
2153     /* Disable Interrupts */
2154     __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
2155 
2156     /* Write the Input block in the Data IN register */
2157     for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++)
2158     {
2159       HASH->DIN = *(uint32_t *)inputaddr;
2160       inputaddr += 4U;
2161     }
2162 
2163     if (hhash->Accumulation == 1U)
2164     {
2165       /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
2166          The digest computation will be started when the last buffer data are entered. */
2167 
2168       /* Reset multi buffers accumulation flag */
2169       hhash->Accumulation = 0U;
2170       /* Change the HASH state */
2171       hhash->State = HAL_HASH_STATE_READY;
2172       /* Call Input data transfer complete call back */
2173 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2174       hhash->InCpltCallback(hhash);
2175 #else
2176       HAL_HASH_InCpltCallback(hhash);
2177 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2178     }
2179     else
2180     {
2181       /* Start the Digest calculation */
2182       __HAL_HASH_START_DIGEST();
2183       /* Return indication that digest calculation has started:
2184          this return value triggers the call to Input data transfer
2185          complete call back as well as the proper transition from
2186          one step to another in HMAC mode. */
2187       ret = HASH_DIGEST_CALCULATION_STARTED;
2188     }
2189     /* Reset buffer counter */
2190     hhash->HashInCount = 0;
2191   }
2192 
2193   /* Return whether or digest calculation has started */
2194   return ret;
2195 }
2196 
2197 /**
2198   * @brief  HMAC processing in polling mode.
2199   * @param  hhash HASH handle.
2200   * @param  Timeout Timeout value.
2201   * @retval HAL status
2202   */
HMAC_Processing(HASH_HandleTypeDef * hhash,uint32_t Timeout)2203 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
2204 {
2205   /* Ensure first that Phase is correct */
2206   if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2)
2207       && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3))
2208   {
2209     /* Change the HASH state */
2210     hhash->State = HAL_HASH_STATE_READY;
2211 
2212     /* Process Unlock */
2213     __HAL_UNLOCK(hhash);
2214 
2215     /* Return function status */
2216     return HAL_ERROR;
2217   }
2218 
2219   /* HMAC Step 1 processing */
2220   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2221   {
2222     /************************** STEP 1 ******************************************/
2223     /* Configure the Number of valid bits in last word of the message */
2224     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2225 
2226     /* Write input buffer in Data register */
2227     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2228     if (hhash->Status != HAL_OK)
2229     {
2230       return hhash->Status;
2231     }
2232 
2233     /* Check whether or not key entering process has been suspended */
2234     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2235     {
2236       /* Process Unlocked */
2237       __HAL_UNLOCK(hhash);
2238 
2239       /* Stop right there and return function status */
2240       return HAL_OK;
2241     }
2242 
2243     /* No processing suspension at this point: set DCAL bit. */
2244     __HAL_HASH_START_DIGEST();
2245 
2246     /* Wait for BUSY flag to be cleared */
2247     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2248     {
2249       return HAL_TIMEOUT;
2250     }
2251 
2252     /* Move from Step 1 to Step 2 */
2253     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
2254 
2255   }
2256 
2257   /* HMAC Step 2 processing.
2258      After phase check, HMAC_Processing() may
2259      - directly start up from this point in resumption case
2260        if the same Step 2 processing was suspended previously
2261     - or fall through from the Step 1 processing carried out hereabove */
2262   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2263   {
2264     /************************** STEP 2 ******************************************/
2265     /* Configure the Number of valid bits in last word of the message */
2266     __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
2267 
2268     /* Write input buffer in Data register */
2269     hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
2270     if (hhash->Status != HAL_OK)
2271     {
2272       return hhash->Status;
2273     }
2274 
2275     /* Check whether or not data entering process has been suspended */
2276     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2277     {
2278       /* Process Unlocked */
2279       __HAL_UNLOCK(hhash);
2280 
2281       /* Stop right there and return function status */
2282       return HAL_OK;
2283     }
2284 
2285     /* No processing suspension at this point: set DCAL bit. */
2286     __HAL_HASH_START_DIGEST();
2287 
2288     /* Wait for BUSY flag to be cleared */
2289     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2290     {
2291       return HAL_TIMEOUT;
2292     }
2293 
2294     /* Move from Step 2 to Step 3 */
2295     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
2296     /* In case Step 1 phase was suspended then resumed,
2297        set again Key input buffers and size before moving to
2298        next step */
2299     hhash->pHashKeyBuffPtr = hhash->Init.pKey;
2300     hhash->HashKeyCount    = hhash->Init.KeySize;
2301   }
2302 
2303 
2304   /* HMAC Step 3 processing.
2305       After phase check, HMAC_Processing() may
2306       - directly start up from this point in resumption case
2307         if the same Step 3 processing was suspended previously
2308      - or fall through from the Step 2 processing carried out hereabove */
2309   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
2310   {
2311     /************************** STEP 3 ******************************************/
2312     /* Configure the Number of valid bits in last word of the message */
2313     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2314 
2315     /* Write input buffer in Data register */
2316     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2317     if (hhash->Status != HAL_OK)
2318     {
2319       return hhash->Status;
2320     }
2321 
2322     /* Check whether or not key entering process has been suspended */
2323     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2324     {
2325       /* Process Unlocked */
2326       __HAL_UNLOCK(hhash);
2327 
2328       /* Stop right there and return function status */
2329       return HAL_OK;
2330     }
2331 
2332     /* No processing suspension at this point: start the Digest calculation. */
2333     __HAL_HASH_START_DIGEST();
2334 
2335     /* Wait for DCIS flag to be set */
2336     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2337     {
2338       return HAL_TIMEOUT;
2339     }
2340 
2341     /* Read the message digest */
2342     HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2343 
2344     /* Reset HASH state machine */
2345     hhash->Phase = HAL_HASH_PHASE_READY;
2346   }
2347 
2348   /* Change the HASH state */
2349   hhash->State = HAL_HASH_STATE_READY;
2350 
2351   /* Process Unlock */
2352   __HAL_UNLOCK(hhash);
2353 
2354   /* Return function status */
2355   return HAL_OK;
2356 }
2357 
2358 
2359 /**
2360   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2361   *         read the computed digest.
2362   * @note   Digest is available in pOutBuffer.
2363   * @param  hhash HASH handle.
2364   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2365   * @param  Size length of the input buffer in bytes.
2366   * @param  pOutBuffer pointer to the computed digest.
2367   * @param  Timeout Timeout value.
2368   * @param  Algorithm HASH algorithm.
2369   * @retval HAL status
2370   */
HASH_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)2371 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
2372                              uint32_t Timeout, uint32_t Algorithm)
2373 {
2374   uint8_t *pInBuffer_tmp;  /* input data address, input parameter of HASH_WriteData()         */
2375   uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
2376   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2377 
2378 
2379   /* Initiate HASH processing in case of start or resumption */
2380   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2381   {
2382     /* Check input parameters */
2383     if ((pInBuffer == NULL) || (pOutBuffer == NULL))
2384     {
2385       hhash->State = HAL_HASH_STATE_READY;
2386       return  HAL_ERROR;
2387     }
2388 
2389     /* Process Locked */
2390     __HAL_LOCK(hhash);
2391 
2392     /* Check if initialization phase has not been already performed */
2393     if (hhash->Phase == HAL_HASH_PHASE_READY)
2394     {
2395       /* Change the HASH state */
2396       hhash->State = HAL_HASH_STATE_BUSY;
2397 
2398       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2399       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2400 
2401       /* Configure the number of valid bits in last word of the message */
2402       __HAL_HASH_SET_NBVALIDBITS(Size);
2403 
2404       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2405       input parameters of HASH_WriteData() */
2406       pInBuffer_tmp = pInBuffer;   /* pInBuffer_tmp is set to the input data address */
2407       Size_tmp = Size;             /* Size_tmp contains the input data size in bytes */
2408 
2409       /* Set the phase */
2410       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2411     }
2412     else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
2413     {
2414       /* if the Peripheral has already been initialized, two cases are possible */
2415 
2416       /* Process resumption time ... */
2417       if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2418       {
2419         /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2420         to the API input parameters but to those saved beforehand by HASH_WriteData()
2421         when the processing was suspended */
2422         pInBuffer_tmp = hhash->pHashInBuffPtr;
2423         Size_tmp = hhash->HashInCount;
2424       }
2425       /* ... or multi-buffer HASH processing end */
2426       else
2427       {
2428         /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2429         input parameters of HASH_WriteData() */
2430         pInBuffer_tmp = pInBuffer;
2431         Size_tmp = Size;
2432         /* Configure the number of valid bits in last word of the message */
2433         __HAL_HASH_SET_NBVALIDBITS(Size);
2434       }
2435       /* Change the HASH state */
2436       hhash->State = HAL_HASH_STATE_BUSY;
2437     }
2438     else
2439     {
2440       /* Phase error */
2441       hhash->State = HAL_HASH_STATE_READY;
2442 
2443       /* Process Unlocked */
2444       __HAL_UNLOCK(hhash);
2445 
2446       /* Return function status */
2447       return HAL_ERROR;
2448     }
2449 
2450 
2451     /* Write input buffer in Data register */
2452     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2453     if (hhash->Status != HAL_OK)
2454     {
2455       return hhash->Status;
2456     }
2457 
2458     /* If the process has not been suspended, carry on to digest calculation */
2459     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2460     {
2461       /* Start the Digest calculation */
2462       __HAL_HASH_START_DIGEST();
2463 
2464       /* Wait for DCIS flag to be set */
2465       if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2466       {
2467         return HAL_TIMEOUT;
2468       }
2469 
2470       /* Read the message digest */
2471       HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
2472 
2473       /* Change the HASH state */
2474       hhash->State = HAL_HASH_STATE_READY;
2475 
2476       /* Reset HASH state machine */
2477       hhash->Phase = HAL_HASH_PHASE_READY;
2478 
2479     }
2480 
2481     /* Process Unlocked */
2482     __HAL_UNLOCK(hhash);
2483 
2484     /* Return function status */
2485     return HAL_OK;
2486 
2487   }
2488   else
2489   {
2490     return HAL_BUSY;
2491   }
2492 }
2493 
2494 
2495 /**
2496   * @brief  If not already done, initialize the HASH peripheral then
2497   *         processes pInBuffer.
2498   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
2499   *         the Peripheral has already been initialized.
2500   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2501   *         HASH digest computation is corrupted.
2502   * @param  hhash HASH handle.
2503   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2504   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
2505   * @param  Algorithm HASH algorithm.
2506   * @retval HAL status
2507   */
HASH_Accumulate(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)2508 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2509 {
2510   uint8_t *pInBuffer_tmp;   /* input data address, input parameter of HASH_WriteData()         */
2511   uint32_t Size_tmp;  /* input data size (in bytes), input parameter of HASH_WriteData() */
2512   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2513 
2514   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2515   if ((Size % 4U) != 0U)
2516   {
2517     return  HAL_ERROR;
2518   }
2519 
2520   /* Initiate HASH processing in case of start or resumption */
2521   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2522   {
2523     /* Check input parameters */
2524     if ((pInBuffer == NULL) || (Size == 0U))
2525     {
2526       hhash->State = HAL_HASH_STATE_READY;
2527       return  HAL_ERROR;
2528     }
2529 
2530     /* Process Locked */
2531     __HAL_LOCK(hhash);
2532 
2533     /* If resuming the HASH processing */
2534     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2535     {
2536       /* Change the HASH state */
2537       hhash->State = HAL_HASH_STATE_BUSY;
2538 
2539       /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2540          to the API input parameters but to those saved beforehand by HASH_WriteData()
2541          when the processing was suspended */
2542       pInBuffer_tmp = hhash->pHashInBuffPtr;  /* pInBuffer_tmp is set to the input data address */
2543       Size_tmp = hhash->HashInCount;          /* Size_tmp contains the input data size in bytes */
2544 
2545     }
2546     else
2547     {
2548       /* Change the HASH state */
2549       hhash->State = HAL_HASH_STATE_BUSY;
2550 
2551       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2552          input parameters of HASH_WriteData() */
2553       pInBuffer_tmp = pInBuffer;    /* pInBuffer_tmp is set to the input data address */
2554       Size_tmp = Size;              /* Size_tmp contains the input data size in bytes */
2555 
2556       /* Check if initialization phase has already be performed */
2557       if (hhash->Phase == HAL_HASH_PHASE_READY)
2558       {
2559         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2560         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2561       }
2562 
2563       /* Set the phase */
2564       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2565 
2566     }
2567 
2568     /* Write input buffer in Data register */
2569     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2570     if (hhash->Status != HAL_OK)
2571     {
2572       return hhash->Status;
2573     }
2574 
2575     /* If the process has not been suspended, move the state to Ready */
2576     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2577     {
2578       /* Change the HASH state */
2579       hhash->State = HAL_HASH_STATE_READY;
2580     }
2581 
2582     /* Process Unlocked */
2583     __HAL_UNLOCK(hhash);
2584 
2585     /* Return function status */
2586     return HAL_OK;
2587 
2588   }
2589   else
2590   {
2591     return HAL_BUSY;
2592   }
2593 
2594 
2595 }
2596 
2597 
2598 /**
2599   * @brief  If not already done, initialize the HASH peripheral then
2600   *         processes pInBuffer in interruption mode.
2601   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
2602   *         the Peripheral has already been initialized.
2603   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2604   *         HASH digest computation is corrupted.
2605   * @param  hhash HASH handle.
2606   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2607   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
2608   * @param  Algorithm HASH algorithm.
2609   * @retval HAL status
2610   */
HASH_Accumulate_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)2611 HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2612 {
2613   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2614   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2615   uint32_t SizeVar = Size;
2616 
2617   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2618   if ((Size % 4U) != 0U)
2619   {
2620     return  HAL_ERROR;
2621   }
2622 
2623   /* Initiate HASH processing in case of start or resumption */
2624   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2625   {
2626     /* Check input parameters */
2627     if ((pInBuffer == NULL) || (Size == 0U))
2628     {
2629       hhash->State = HAL_HASH_STATE_READY;
2630       return  HAL_ERROR;
2631     }
2632 
2633     /* Process Locked */
2634     __HAL_LOCK(hhash);
2635 
2636     /* If resuming the HASH processing */
2637     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2638     {
2639       /* Change the HASH state */
2640       hhash->State = HAL_HASH_STATE_BUSY;
2641     }
2642     else
2643     {
2644       /* Change the HASH state */
2645       hhash->State = HAL_HASH_STATE_BUSY;
2646 
2647       /* Check if initialization phase has already be performed */
2648       if (hhash->Phase == HAL_HASH_PHASE_READY)
2649       {
2650         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2651         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2652         hhash->HashITCounter = 1;
2653       }
2654       else
2655       {
2656         hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2657       }
2658 
2659       /* Set the phase */
2660       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2661 
2662       /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2663        fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2664        Therefore, first words are manually entered until DINIS raises, or until there
2665        is not more data to enter. */
2666       while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U))
2667       {
2668 
2669         /* Write input data 4 bytes at a time */
2670         HASH->DIN = *(uint32_t *)inputaddr;
2671         inputaddr += 4U;
2672         SizeVar -= 4U;
2673       }
2674 
2675       /* If DINIS is still not set or if all the data have been fed, stop here */
2676       if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U))
2677       {
2678         /* Change the HASH state */
2679         hhash->State = HAL_HASH_STATE_READY;
2680 
2681         /* Process Unlock */
2682         __HAL_UNLOCK(hhash);
2683 
2684         /* Return function status */
2685         return HAL_OK;
2686       }
2687 
2688       /* otherwise, carry on in interrupt-mode */
2689       hhash->HashInCount = SizeVar;               /* Counter used to keep track of number of data
2690                                                   to be fed to the Peripheral */
2691       hhash->pHashInBuffPtr = (uint8_t *)inputaddr;       /* Points at data which will be fed to the Peripheral at
2692                                                   the next interruption */
2693       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2694          the information describing where the HASH process is stopped.
2695          These variables are used later on to resume the HASH processing at the
2696          correct location. */
2697 
2698     }
2699 
2700     /* Set multi buffers accumulation flag */
2701     hhash->Accumulation = 1U;
2702 
2703     /* Process Unlock */
2704     __HAL_UNLOCK(hhash);
2705 
2706     /* Enable Data Input interrupt */
2707     __HAL_HASH_ENABLE_IT(HASH_IT_DINI);
2708 
2709     /* Return function status */
2710     return HAL_OK;
2711 
2712   }
2713   else
2714   {
2715     return HAL_BUSY;
2716   }
2717 
2718 }
2719 
2720 
2721 
2722 /**
2723   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2724   *         read the computed digest in interruption mode.
2725   * @note   Digest is available in pOutBuffer.
2726   * @param  hhash HASH handle.
2727   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2728   * @param  Size length of the input buffer in bytes.
2729   * @param  pOutBuffer pointer to the computed digest.
2730   * @param  Algorithm HASH algorithm.
2731   * @retval HAL status
2732   */
HASH_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)2733 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
2734                                 uint32_t Algorithm)
2735 {
2736   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2737   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2738   uint32_t polling_step = 0U;
2739   uint32_t initialization_skipped = 0U;
2740   uint32_t SizeVar = Size;
2741 
2742   /* If State is ready or suspended, start or resume IT-based HASH processing */
2743   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2744   {
2745     /* Check input parameters */
2746     if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
2747     {
2748       hhash->State = HAL_HASH_STATE_READY;
2749       return  HAL_ERROR;
2750     }
2751 
2752     /* Process Locked */
2753     __HAL_LOCK(hhash);
2754 
2755     /* Change the HASH state */
2756     hhash->State = HAL_HASH_STATE_BUSY;
2757 
2758     /* Initialize IT counter */
2759     hhash->HashITCounter = 1;
2760 
2761     /* Check if initialization phase has already be performed */
2762     if (hhash->Phase == HAL_HASH_PHASE_READY)
2763     {
2764       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2765       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2766 
2767       /* Configure the number of valid bits in last word of the message */
2768       __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2769 
2770 
2771       hhash->HashInCount = SizeVar;            /* Counter used to keep track of number of data
2772                                                   to be fed to the Peripheral */
2773       hhash->pHashInBuffPtr = pInBuffer;       /* Points at data which will be fed to the Peripheral at
2774                                                   the next interruption */
2775       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2776          the information describing where the HASH process is stopped.
2777          These variables are used later on to resume the HASH processing at the
2778          correct location. */
2779 
2780       hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2781     }
2782     else
2783     {
2784       initialization_skipped = 1; /* info user later on in case of multi-buffer */
2785     }
2786 
2787     /* Set the phase */
2788     hhash->Phase = HAL_HASH_PHASE_PROCESS;
2789 
2790     /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2791       fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2792       Therefore, first words are manually entered until DINIS raises. */
2793     while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U))
2794     {
2795       polling_step = 1U; /* note that some words are entered before enabling the interrupt */
2796 
2797       /* Write input data 4 bytes at a time */
2798       HASH->DIN = *(uint32_t *)inputaddr;
2799       inputaddr += 4U;
2800       SizeVar -= 4U;
2801     }
2802 
2803     if (polling_step == 1U)
2804     {
2805       if (SizeVar == 0U)
2806       {
2807         /* If all the data have been entered at this point, it only remains to
2808          read the digest */
2809         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2810 
2811         /* Start the Digest calculation */
2812         __HAL_HASH_START_DIGEST();
2813         /* Process Unlock */
2814         __HAL_UNLOCK(hhash);
2815 
2816         /* Enable Interrupts */
2817         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2818 
2819         /* Return function status */
2820         return HAL_OK;
2821       }
2822       else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2823       {
2824         /* It remains data to enter and the Peripheral is ready to trigger DINIE,
2825            carry on as usual.
2826            Update HashInCount and pHashInBuffPtr accordingly. */
2827         hhash->HashInCount = SizeVar;
2828         hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
2829         /* Update the configuration of the number of valid bits in last word of the message */
2830         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2831         hhash->pHashOutBuffPtr = pOutBuffer;  /* Points at the computed digest */
2832         if (initialization_skipped == 1U)
2833         {
2834           hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2835         }
2836       }
2837       else
2838       {
2839         /* DINIS is not set but it remains a few data to enter (not enough for a full word).
2840            Manually enter the last bytes before enabling DCIE. */
2841         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2842         HASH->DIN = *(uint32_t *)inputaddr;
2843 
2844         /* Start the Digest calculation */
2845         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2846         __HAL_HASH_START_DIGEST();
2847         /* Process Unlock */
2848         __HAL_UNLOCK(hhash);
2849 
2850         /* Enable Interrupts */
2851         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2852 
2853         /* Return function status */
2854         return HAL_OK;
2855       }
2856     } /*  if (polling_step == 1) */
2857 
2858 
2859     /* Process Unlock */
2860     __HAL_UNLOCK(hhash);
2861 
2862     /* Enable Interrupts */
2863     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2864 
2865     /* Return function status */
2866     return HAL_OK;
2867   }
2868   else
2869   {
2870     return HAL_BUSY;
2871   }
2872 
2873 }
2874 
2875 
2876 /**
2877   * @brief  Initialize the HASH peripheral then initiate a DMA transfer
2878   *         to feed the input buffer to the Peripheral.
2879   * @param  hhash HASH handle.
2880   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2881   * @param  Size length of the input buffer in bytes.
2882   * @param  Algorithm HASH algorithm.
2883   * @retval HAL status
2884   */
HASH_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)2885 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2886 {
2887   uint32_t inputaddr;
2888   uint32_t inputSize;
2889   HAL_StatusTypeDef status ;
2890   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2891 
2892   /* If State is ready or suspended, start or resume polling-based HASH processing */
2893   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2894   {
2895     /* Check input parameters */
2896     if ((pInBuffer == NULL) || (Size == 0U) ||
2897         /* Check phase coherency. Phase must be
2898            either READY (fresh start)
2899            or PROCESS (multi-buffer HASH management) */
2900         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
2901     {
2902       hhash->State = HAL_HASH_STATE_READY;
2903       return  HAL_ERROR;
2904     }
2905 
2906 
2907     /* Process Locked */
2908     __HAL_LOCK(hhash);
2909 
2910     /* If not a resumption case */
2911     if (hhash->State == HAL_HASH_STATE_READY)
2912     {
2913       /* Change the HASH state */
2914       hhash->State = HAL_HASH_STATE_BUSY;
2915 
2916       /* Check if initialization phase has already been performed.
2917          If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
2918          API is processing a new input data message in case of multi-buffer HASH
2919          computation. */
2920       if (hhash->Phase == HAL_HASH_PHASE_READY)
2921       {
2922         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2923         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2924 
2925         /* Set the phase */
2926         hhash->Phase = HAL_HASH_PHASE_PROCESS;
2927       }
2928 
2929       /* Configure the Number of valid bits in last word of the message */
2930       __HAL_HASH_SET_NBVALIDBITS(Size);
2931 
2932       inputaddr = (uint32_t)pInBuffer;     /* DMA transfer start address   */
2933       inputSize = Size;                    /* DMA transfer size (in bytes) */
2934 
2935       /* In case of suspension request, save the starting parameters */
2936       hhash->pHashInBuffPtr =  pInBuffer;  /* DMA transfer start address   */
2937       hhash->HashInCount = Size;           /* DMA transfer size (in bytes) */
2938 
2939     }
2940     /* If resumption case */
2941     else
2942     {
2943       /* Change the HASH state */
2944       hhash->State = HAL_HASH_STATE_BUSY;
2945 
2946       /* Resumption case, inputaddr and inputSize are not set to the API input parameters
2947          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
2948          processing was suspended */
2949       inputaddr = (uint32_t)hhash->pHashInBuffPtr;  /* DMA transfer start address   */
2950       inputSize = hhash->HashInCount;               /* DMA transfer size (in bytes) */
2951 
2952     }
2953 
2954     /* Set the HASH DMA transfer complete callback */
2955     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
2956     /* Set the DMA error callback */
2957     hhash->hdmain->XferErrorCallback = HASH_DMAError;
2958 
2959     /* Store number of words already pushed to manage proper DMA processing suspension */
2960     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
2961 
2962     /* Enable the DMA In DMA stream */
2963     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
2964                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \
2965                                (inputSize / 4U)));
2966 
2967     /* Enable DMA requests */
2968     SET_BIT(HASH->CR, HASH_CR_DMAE);
2969 
2970     /* Process Unlock */
2971     __HAL_UNLOCK(hhash);
2972 
2973     /* Return function status */
2974     if (status != HAL_OK)
2975     {
2976       /* Update HASH state machine to error */
2977       hhash->State = HAL_HASH_STATE_ERROR;
2978     }
2979 
2980     return status;
2981   }
2982   else
2983   {
2984     return HAL_BUSY;
2985   }
2986 }
2987 
2988 /**
2989   * @brief  Return the computed digest.
2990   * @note   The API waits for DCIS to be set then reads the computed digest.
2991   * @param  hhash HASH handle.
2992   * @param  pOutBuffer pointer to the computed digest.
2993   * @param  Timeout Timeout value.
2994   * @retval HAL status
2995   */
HASH_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)2996 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
2997 {
2998 
2999   if (hhash->State == HAL_HASH_STATE_READY)
3000   {
3001     /* Check parameter */
3002     if (pOutBuffer == NULL)
3003     {
3004       return  HAL_ERROR;
3005     }
3006 
3007     /* Process Locked */
3008     __HAL_LOCK(hhash);
3009 
3010     /* Change the HASH state to busy */
3011     hhash->State = HAL_HASH_STATE_BUSY;
3012 
3013     /* Wait for DCIS flag to be set */
3014     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
3015     {
3016       return HAL_TIMEOUT;
3017     }
3018 
3019     /* Read the message digest */
3020     HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
3021 
3022     /* Change the HASH state to ready */
3023     hhash->State = HAL_HASH_STATE_READY;
3024 
3025     /* Reset HASH state machine */
3026     hhash->Phase = HAL_HASH_PHASE_READY;
3027 
3028     /* Process UnLock */
3029     __HAL_UNLOCK(hhash);
3030 
3031     /* Return function status */
3032     return HAL_OK;
3033 
3034   }
3035   else
3036   {
3037     return HAL_BUSY;
3038   }
3039 
3040 }
3041 
3042 
3043 /**
3044   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3045   *         read the computed digest.
3046   * @note   Digest is available in pOutBuffer.
3047   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3048   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3049   * @param  hhash HASH handle.
3050   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3051   * @param  Size length of the input buffer in bytes.
3052   * @param  pOutBuffer pointer to the computed digest.
3053   * @param  Timeout Timeout value.
3054   * @param  Algorithm HASH algorithm.
3055   * @retval HAL status
3056   */
HMAC_Start(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)3057 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
3058                              uint32_t Timeout, uint32_t Algorithm)
3059 {
3060   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3061 
3062   /* If State is ready or suspended, start or resume polling-based HASH processing */
3063   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3064   {
3065     /* Check input parameters */
3066     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3067         || (pOutBuffer == NULL))
3068     {
3069       hhash->State = HAL_HASH_STATE_READY;
3070       return  HAL_ERROR;
3071     }
3072 
3073     /* Process Locked */
3074     __HAL_LOCK(hhash);
3075 
3076     /* Change the HASH state */
3077     hhash->State = HAL_HASH_STATE_BUSY;
3078 
3079     /* Check if initialization phase has already be performed */
3080     if (hhash->Phase == HAL_HASH_PHASE_READY)
3081     {
3082       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3083       if (hhash->Init.KeySize > 64U)
3084       {
3085         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3086                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3087       }
3088       else
3089       {
3090         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3091                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3092       }
3093       /* Set the phase to Step 1 */
3094       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3095       /* Resort to hhash internal fields to feed the Peripheral.
3096          Parameters will be updated in case of suspension to contain the proper
3097          information at resumption time. */
3098       hhash->pHashOutBuffPtr  = pOutBuffer;            /* Output digest address    */
3099       hhash->pHashInBuffPtr   = pInBuffer;             /* Input data address, HMAC_Processing input
3100                                                           parameter for Step 2     */
3101       hhash->HashInCount      = Size;                  /* Input data size, HMAC_Processing input
3102                                                           parameter for Step 2        */
3103       hhash->HashBuffSize     = Size;                  /* Store the input buffer size for the whole HMAC process*/
3104       hhash->pHashKeyBuffPtr  = hhash->Init.pKey;      /* Key address, HMAC_Processing input parameter for Step
3105                                                           1 and Step 3 */
3106       hhash->HashKeyCount     = hhash->Init.KeySize;   /* Key size, HMAC_Processing input parameter for Step 1
3107                                                           and Step 3    */
3108     }
3109 
3110     /* Carry out HMAC processing */
3111     return HMAC_Processing(hhash, Timeout);
3112 
3113   }
3114   else
3115   {
3116     return HAL_BUSY;
3117   }
3118 }
3119 
3120 
3121 
3122 /**
3123   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3124   *         read the computed digest in interruption mode.
3125   * @note   Digest is available in pOutBuffer.
3126   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3127   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3128   * @param  hhash HASH handle.
3129   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3130   * @param  Size length of the input buffer in bytes.
3131   * @param  pOutBuffer pointer to the computed digest.
3132   * @param  Algorithm HASH algorithm.
3133   * @retval HAL status
3134   */
HMAC_Start_IT(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)3135 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t *pOutBuffer,
3136                                 uint32_t Algorithm)
3137 {
3138   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3139 
3140   /* If State is ready or suspended, start or resume IT-based HASH processing */
3141   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3142   {
3143     /* Check input parameters */
3144     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3145         || (pOutBuffer == NULL))
3146     {
3147       hhash->State = HAL_HASH_STATE_READY;
3148       return  HAL_ERROR;
3149     }
3150 
3151     /* Process Locked */
3152     __HAL_LOCK(hhash);
3153 
3154     /* Change the HASH state */
3155     hhash->State = HAL_HASH_STATE_BUSY;
3156 
3157     /* Initialize IT counter */
3158     hhash->HashITCounter = 1;
3159 
3160     /* Check if initialization phase has already be performed */
3161     if (hhash->Phase == HAL_HASH_PHASE_READY)
3162     {
3163       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3164       if (hhash->Init.KeySize > 64U)
3165       {
3166         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3167                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3168       }
3169       else
3170       {
3171         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3172                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3173       }
3174 
3175       /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
3176          to feed the Peripheral whatever the HMAC step.
3177          Lines below are set to start HMAC Step 1 processing where key is entered first. */
3178       hhash->HashInCount     = hhash->Init.KeySize; /* Key size                      */
3179       hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* Key address                   */
3180 
3181       /* Store input and output parameters in handle fields to manage steps transition
3182          or possible HMAC suspension/resumption */
3183       hhash->pHashKeyBuffPtr = hhash->Init.pKey;    /* Key address                   */
3184       hhash->pHashMsgBuffPtr = pInBuffer;           /* Input message address         */
3185       hhash->HashBuffSize    = Size;                /* Input message size (in bytes) */
3186       hhash->pHashOutBuffPtr = pOutBuffer;          /* Output digest address         */
3187 
3188       /* Configure the number of valid bits in last word of the key */
3189       __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3190 
3191       /* Set the phase to Step 1 */
3192       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3193     }
3194     else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
3195     {
3196       /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
3197 
3198     }
3199     else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3200     {
3201       /* Restart IT-based HASH processing after Step 2 suspension */
3202 
3203     }
3204     else
3205     {
3206       /* Error report as phase incorrect */
3207       /* Process Unlock */
3208       __HAL_UNLOCK(hhash);
3209       hhash->State = HAL_HASH_STATE_READY;
3210       return HAL_ERROR;
3211     }
3212 
3213     /* Process Unlock */
3214     __HAL_UNLOCK(hhash);
3215 
3216     /* Enable Interrupts */
3217     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
3218 
3219     /* Return function status */
3220     return HAL_OK;
3221   }
3222   else
3223   {
3224     return HAL_BUSY;
3225   }
3226 
3227 }
3228 
3229 
3230 
3231 /**
3232   * @brief  Initialize the HASH peripheral in HMAC mode then initiate the required
3233   *         DMA transfers to feed the key and the input buffer to the Peripheral.
3234   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3235   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3236   * @note   In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
3237   *         be a multiple of 4 otherwise, the HASH digest computation is corrupted.
3238   *         Only the length of the last buffer of the thread doesn't have to be a
3239   *         multiple of 4.
3240   * @param  hhash HASH handle.
3241   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3242   * @param  Size length of the input buffer in bytes.
3243   * @param  Algorithm HASH algorithm.
3244   * @retval HAL status
3245   */
HMAC_Start_DMA(HASH_HandleTypeDef * hhash,uint8_t * pInBuffer,uint32_t Size,uint32_t Algorithm)3246 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
3247 {
3248   uint32_t inputaddr;
3249   uint32_t inputSize;
3250   HAL_StatusTypeDef status ;
3251   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3252   /* If State is ready or suspended, start or resume DMA-based HASH processing */
3253   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3254   {
3255     /* Check input parameters */
3256     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) ||
3257         /* Check phase coherency. Phase must be
3258             either READY (fresh start)
3259             or one of HMAC PROCESS steps (multi-buffer HASH management) */
3260         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
3261     {
3262       hhash->State = HAL_HASH_STATE_READY;
3263       return  HAL_ERROR;
3264     }
3265 
3266 
3267     /* Process Locked */
3268     __HAL_LOCK(hhash);
3269 
3270     /* If not a case of resumption after suspension */
3271     if (hhash->State == HAL_HASH_STATE_READY)
3272     {
3273       /* Check whether or not initialization phase has already be performed */
3274       if (hhash->Phase == HAL_HASH_PHASE_READY)
3275       {
3276         /* Change the HASH state */
3277         hhash->State = HAL_HASH_STATE_BUSY;
3278         /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3279         if (hhash->Init.KeySize > 64U)
3280         {
3281           MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3282                      Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3283         }
3284         else
3285         {
3286           MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3287                      Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3288         }
3289         /* Store input aparameters in handle fields to manage steps transition
3290            or possible HMAC suspension/resumption */
3291         hhash->HashInCount = hhash->Init.KeySize;   /* Initial size for first DMA transfer (key size)      */
3292         hhash->pHashKeyBuffPtr = hhash->Init.pKey;  /* Key address                                         */
3293         hhash->pHashInBuffPtr  = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
3294         hhash->pHashMsgBuffPtr = pInBuffer;         /* Input data address                                  */
3295         hhash->HashBuffSize = Size;                 /* input data size (in bytes)                          */
3296 
3297         /* Set DMA input parameters */
3298         inputaddr = (uint32_t)(hhash->Init.pKey);   /* Address passed to DMA (start by entering Key message) */
3299         inputSize = hhash->Init.KeySize;            /* Size for first DMA transfer (in bytes) */
3300 
3301         /* Configure the number of valid bits in last word of the key */
3302         __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3303 
3304         /* Set the phase to Step 1 */
3305         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3306 
3307       }
3308       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3309       {
3310         /* Process a new input data message in case of multi-buffer HMAC processing
3311           (this is not a resumption case) */
3312 
3313         /* Change the HASH state */
3314         hhash->State = HAL_HASH_STATE_BUSY;
3315 
3316         /* Save input parameters to be able to manage possible suspension/resumption */
3317         hhash->HashInCount = Size;                /* Input message address       */
3318         hhash->pHashInBuffPtr = pInBuffer;        /* Input message size in bytes */
3319 
3320         /* Set DMA input parameters */
3321         inputaddr = (uint32_t)pInBuffer;           /* Input message address       */
3322         inputSize = Size;                          /* Input message size in bytes */
3323 
3324         if (hhash->DigestCalculationDisable == RESET)
3325         {
3326           /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
3327           __HAL_HASH_SET_NBVALIDBITS(inputSize);
3328         }
3329       }
3330       else
3331       {
3332         /* Phase not aligned with handle READY state */
3333         __HAL_UNLOCK(hhash);
3334         /* Return function status */
3335         return HAL_ERROR;
3336       }
3337     }
3338     else
3339     {
3340       /* Resumption case (phase may be Step 1, 2 or 3) */
3341 
3342       /* Change the HASH state */
3343       hhash->State = HAL_HASH_STATE_BUSY;
3344 
3345       /* Set DMA input parameters at resumption location;
3346          inputaddr and inputSize are not set to the API input parameters
3347          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3348          processing was suspended. */
3349       inputaddr = (uint32_t)(hhash->pHashInBuffPtr);  /* Input message address       */
3350       inputSize = hhash->HashInCount;                 /* Input message size in bytes */
3351     }
3352 
3353 
3354     /* Set the HASH DMA transfer complete callback */
3355     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3356     /* Set the DMA error callback */
3357     hhash->hdmain->XferErrorCallback = HASH_DMAError;
3358 
3359     /* Store number of words already pushed to manage proper DMA processing suspension */
3360     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3361 
3362     /* Enable the DMA In DMA stream */
3363     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN,  \
3364                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \
3365                               : (inputSize / 4U)));
3366 
3367     /* Enable DMA requests */
3368     SET_BIT(HASH->CR, HASH_CR_DMAE);
3369 
3370     /* Process Unlocked */
3371     __HAL_UNLOCK(hhash);
3372 
3373     /* Return function status */
3374     if (status != HAL_OK)
3375     {
3376       /* Update HASH state machine to error */
3377       hhash->State = HAL_HASH_STATE_ERROR;
3378     }
3379 
3380     /* Return function status */
3381     return status;
3382   }
3383   else
3384   {
3385     return HAL_BUSY;
3386   }
3387 }
3388 /**
3389   * @}
3390   */
3391 
3392 #endif /* HAL_HASH_MODULE_ENABLED */
3393 
3394 /**
3395   * @}
3396   */
3397 #endif /*  HASH*/
3398 /**
3399   * @}
3400   */
3401 
3402