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