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