1 /**
2   ******************************************************************************
3   * @file    stm32h7xx_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) 2017 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 "stm32h7xx_hal.h"
210 
211 
212 /** @addtogroup STM32H7xx_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(const 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, const uint8_t *const 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   /* Reset MDMAT bit */
387   __HAL_HASH_RESET_MDMAT();
388   /* Reset HASH handle status */
389   hhash->Status = HAL_OK;
390 
391   /* Set the HASH state to Ready */
392   hhash->State = HAL_HASH_STATE_READY;
393 
394   /* Initialise the error code */
395   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
396 
397   /* Return function status */
398   return HAL_OK;
399 }
400 
401 /**
402   * @brief  DeInitialize the HASH peripheral.
403   * @param  hhash HASH handle.
404   * @retval HAL status
405   */
HAL_HASH_DeInit(HASH_HandleTypeDef * hhash)406 HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash)
407 {
408   /* Check the HASH handle allocation */
409   if (hhash == NULL)
410   {
411     return HAL_ERROR;
412   }
413 
414   /* Change the HASH state */
415   hhash->State = HAL_HASH_STATE_BUSY;
416 
417   /* Set the default HASH phase */
418   hhash->Phase = HAL_HASH_PHASE_READY;
419 
420   /* Reset HashInCount, HashITCounter and HashBuffSize */
421   hhash->HashInCount = 0;
422   hhash->HashBuffSize = 0;
423   hhash->HashITCounter = 0;
424   /* Reset digest calculation bridle (MDMAT bit control) */
425   hhash->DigestCalculationDisable = RESET;
426 
427 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
428   if (hhash->MspDeInitCallback == NULL)
429   {
430     hhash->MspDeInitCallback = HAL_HASH_MspDeInit;
431   }
432 
433   /* DeInit the low level hardware */
434   hhash->MspDeInitCallback(hhash);
435 #else
436   /* DeInit the low level hardware: CLOCK, NVIC */
437   HAL_HASH_MspDeInit(hhash);
438 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
439 
440 
441   /* Reset HASH handle status */
442   hhash->Status = HAL_OK;
443 
444   /* Set the HASH state to Ready */
445   hhash->State = HAL_HASH_STATE_RESET;
446 
447   /* Initialise the error code */
448   hhash->ErrorCode = HAL_HASH_ERROR_NONE;
449 
450   /* Reset multi buffers accumulation flag */
451   hhash->Accumulation = 0U;
452 
453   /* Return function status */
454   return HAL_OK;
455 }
456 
457 /**
458   * @brief  Initialize the HASH MSP.
459   * @param  hhash HASH handle.
460   * @retval None
461   */
HAL_HASH_MspInit(HASH_HandleTypeDef * hhash)462 __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash)
463 {
464   /* Prevent unused argument(s) compilation warning */
465   UNUSED(hhash);
466 
467   /* NOTE : This function should not be modified; when the callback is needed,
468             HAL_HASH_MspInit() can be implemented in the user file.
469    */
470 }
471 
472 /**
473   * @brief  DeInitialize the HASH MSP.
474   * @param  hhash HASH handle.
475   * @retval None
476   */
HAL_HASH_MspDeInit(HASH_HandleTypeDef * hhash)477 __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash)
478 {
479   /* Prevent unused argument(s) compilation warning */
480   UNUSED(hhash);
481 
482   /* NOTE : This function should not be modified; when the callback is needed,
483             HAL_HASH_MspDeInit() can be implemented in the user file.
484    */
485 }
486 
487 /**
488   * @brief  Input data transfer complete call back.
489   * @note   HAL_HASH_InCpltCallback() is called when the complete input message
490   *         has been fed to the Peripheral. This API is invoked only when input data are
491   *         entered under interruption or through DMA.
492   * @note   In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set),
493   *         HAL_HASH_InCpltCallback() is called at the end of each buffer feeding
494   *         to the Peripheral.
495   * @param  hhash HASH handle.
496   * @retval None
497   */
HAL_HASH_InCpltCallback(HASH_HandleTypeDef * hhash)498 __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash)
499 {
500   /* Prevent unused argument(s) compilation warning */
501   UNUSED(hhash);
502 
503   /* NOTE : This function should not be modified; when the callback is needed,
504             HAL_HASH_InCpltCallback() can be implemented in the user file.
505    */
506 }
507 
508 /**
509   * @brief  Digest computation complete call back.
510   * @note   HAL_HASH_DgstCpltCallback() is used under interruption, is not
511   *         relevant with DMA.
512   * @param  hhash HASH handle.
513   * @retval None
514   */
HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef * hhash)515 __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash)
516 {
517   /* Prevent unused argument(s) compilation warning */
518   UNUSED(hhash);
519 
520   /* NOTE : This function should not be modified; when the callback is needed,
521             HAL_HASH_DgstCpltCallback() can be implemented in the user file.
522    */
523 }
524 
525 /**
526   * @brief  Error callback.
527   * @note   Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...)
528   *         to retrieve the error type.
529   * @param  hhash HASH handle.
530   * @retval None
531   */
HAL_HASH_ErrorCallback(HASH_HandleTypeDef * hhash)532 __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash)
533 {
534   /* Prevent unused argument(s) compilation warning */
535   UNUSED(hhash);
536 
537   /* NOTE : This function should not be modified; when the callback is needed,
538             HAL_HASH_ErrorCallback() can be implemented in the user file.
539    */
540 }
541 
542 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
543 /**
544   * @brief  Register a User HASH Callback
545   *         To be used instead of the weak (surcharged) predefined callback
546   * @param hhash HASH handle
547   * @param CallbackID ID of the callback to be registered
548   *        This parameter can be one of the following values:
549   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
550   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
551   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
552   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
553   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
554   * @param pCallback pointer to the Callback function
555   * @retval status
556   */
HAL_HASH_RegisterCallback(HASH_HandleTypeDef * hhash,HAL_HASH_CallbackIDTypeDef CallbackID,pHASH_CallbackTypeDef pCallback)557 HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID,
558                                             pHASH_CallbackTypeDef pCallback)
559 {
560   HAL_StatusTypeDef status = HAL_OK;
561 
562   if (pCallback == NULL)
563   {
564     /* Update the error code */
565     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
566     return HAL_ERROR;
567   }
568   /* Process locked */
569   __HAL_LOCK(hhash);
570 
571   if (HAL_HASH_STATE_READY == hhash->State)
572   {
573     switch (CallbackID)
574     {
575       case HAL_HASH_INPUTCPLT_CB_ID :
576         hhash->InCpltCallback = pCallback;
577         break;
578 
579       case HAL_HASH_DGSTCPLT_CB_ID :
580         hhash->DgstCpltCallback = pCallback;
581         break;
582 
583       case HAL_HASH_ERROR_CB_ID :
584         hhash->ErrorCallback = pCallback;
585         break;
586 
587       case HAL_HASH_MSPINIT_CB_ID :
588         hhash->MspInitCallback = pCallback;
589         break;
590 
591       case HAL_HASH_MSPDEINIT_CB_ID :
592         hhash->MspDeInitCallback = pCallback;
593         break;
594 
595       default :
596         /* Update the error code */
597         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
598         /* update return status */
599         status =  HAL_ERROR;
600         break;
601     }
602   }
603   else if (HAL_HASH_STATE_RESET == hhash->State)
604   {
605     switch (CallbackID)
606     {
607       case HAL_HASH_MSPINIT_CB_ID :
608         hhash->MspInitCallback = pCallback;
609         break;
610 
611       case HAL_HASH_MSPDEINIT_CB_ID :
612         hhash->MspDeInitCallback = pCallback;
613         break;
614 
615       default :
616         /* Update the error code */
617         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
618         /* update return status */
619         status =  HAL_ERROR;
620         break;
621     }
622   }
623   else
624   {
625     /* Update the error code */
626     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
627     /* update return status */
628     status =  HAL_ERROR;
629   }
630 
631   /* Release Lock */
632   __HAL_UNLOCK(hhash);
633   return status;
634 }
635 
636 /**
637   * @brief  Unregister a HASH Callback
638   *         HASH Callback is redirected to the weak (surcharged) predefined callback
639   * @param hhash HASH handle
640   * @param CallbackID ID of the callback to be unregistered
641   *        This parameter can be one of the following values:
642   *          @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
643   *          @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
644   *          @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
645   *          @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
646   *          @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
647   * @retval status
648   */
HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef * hhash,HAL_HASH_CallbackIDTypeDef CallbackID)649 HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID)
650 {
651   HAL_StatusTypeDef status = HAL_OK;
652 
653   /* Process locked */
654   __HAL_LOCK(hhash);
655 
656   if (HAL_HASH_STATE_READY == hhash->State)
657   {
658     switch (CallbackID)
659     {
660       case HAL_HASH_INPUTCPLT_CB_ID :
661         hhash->InCpltCallback = HAL_HASH_InCpltCallback;     /* Legacy weak (surcharged) input completion callback */
662         break;
663 
664       case HAL_HASH_DGSTCPLT_CB_ID :
665         hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation
666                                                                 completion callback */
667         break;
668 
669       case HAL_HASH_ERROR_CB_ID :
670         hhash->ErrorCallback = HAL_HASH_ErrorCallback;       /* Legacy weak (surcharged) error callback */
671         break;
672 
673       case HAL_HASH_MSPINIT_CB_ID :
674         hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
675         break;
676 
677       case HAL_HASH_MSPDEINIT_CB_ID :
678         hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
679         break;
680 
681       default :
682         /* Update the error code */
683         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
684         /* update return status */
685         status =  HAL_ERROR;
686         break;
687     }
688   }
689   else if (HAL_HASH_STATE_RESET == hhash->State)
690   {
691     switch (CallbackID)
692     {
693       case HAL_HASH_MSPINIT_CB_ID :
694         hhash->MspInitCallback = HAL_HASH_MspInit;           /* Legacy weak (surcharged) Msp Init */
695         break;
696 
697       case HAL_HASH_MSPDEINIT_CB_ID :
698         hhash->MspDeInitCallback = HAL_HASH_MspDeInit;       /* Legacy weak (surcharged) Msp DeInit */
699         break;
700 
701       default :
702         /* Update the error code */
703         hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
704         /* update return status */
705         status =  HAL_ERROR;
706         break;
707     }
708   }
709   else
710   {
711     /* Update the error code */
712     hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
713     /* update return status */
714     status =  HAL_ERROR;
715   }
716 
717   /* Release Lock */
718   __HAL_UNLOCK(hhash);
719   return status;
720 }
721 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
722 
723 /**
724   * @}
725   */
726 
727 /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode
728   *  @brief   HASH processing functions using polling mode.
729   *
730 @verbatim
731  ===============================================================================
732                  ##### Polling mode HASH processing functions #####
733  ===============================================================================
734     [..]  This section provides functions allowing to calculate in polling mode
735           the hash value using one of the following algorithms:
736       (+) MD5
737          (++) HAL_HASH_MD5_Start()
738          (++) HAL_HASH_MD5_Accmlt()
739          (++) HAL_HASH_MD5_Accmlt_End()
740       (+) SHA1
741          (++) HAL_HASH_SHA1_Start()
742          (++) HAL_HASH_SHA1_Accmlt()
743          (++) HAL_HASH_SHA1_Accmlt_End()
744 
745     [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
746 
747     [..]  In case of multi-buffer HASH processing (a single digest is computed while
748           several buffers are fed to the Peripheral), the user can resort to successive calls
749           to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call
750           to HAL_HASH_xxx_Accumulate_End().
751 
752 @endverbatim
753   * @{
754   */
755 
756 /**
757   * @brief  Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
758   *         read the computed digest.
759   * @note   Digest is available in pOutBuffer.
760   * @param  hhash HASH handle.
761   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
762   * @param  Size length of the input buffer in bytes.
763   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
764   * @param  Timeout Timeout value
765   * @retval HAL status
766   */
HAL_HASH_MD5_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)767 HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
768                                      uint8_t *pOutBuffer,
769                                      uint32_t Timeout)
770 {
771   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
772 }
773 
774 /**
775   * @brief  If not already done, initialize the HASH peripheral in MD5 mode then
776   *         processes pInBuffer.
777   * @note   Consecutive calls to HAL_HASH_MD5_Accmlt() can be used to feed
778   *         several input buffers back-to-back to the Peripheral that will yield a single
779   *         HASH signature once all buffers have been entered. Wrap-up of input
780   *         buffers feeding and retrieval of digest is done by a call to
781   *         HAL_HASH_MD5_Accmlt_End().
782   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
783   *         the Peripheral has already been initialized.
784   * @note   Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Accmlt_End()
785   *         to read it, feeding at the same time the last input buffer to the Peripheral.
786   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
787   *         HASH digest computation is corrupted. Only HAL_HASH_MD5_Accmlt_End() is able
788   *         to manage the ending buffer with a length in bytes not a multiple of 4.
789   * @param  hhash HASH handle.
790   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
791   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
792   * @retval HAL status
793   */
HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)794 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
795 {
796   return  HASH_Accumulate(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
797 }
798 
799 /**
800   * @brief  End computation of a single HASH signature after several calls to HAL_HASH_MD5_Accmlt() API.
801   * @note   Digest is available in pOutBuffer.
802   * @param  hhash HASH handle.
803   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
804   * @param  Size length of the input buffer in bytes.
805   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
806   * @param  Timeout Timeout value
807   * @retval HAL status
808   */
HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)809 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
810                                           uint8_t *pOutBuffer, uint32_t Timeout)
811 {
812   return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
813 }
814 
815 /**
816   * @brief  Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
817   *         read the computed digest.
818   * @note   Digest is available in pOutBuffer.
819   * @param  hhash HASH handle.
820   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
821   * @param  Size length of the input buffer in bytes.
822   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
823   * @param  Timeout Timeout value
824   * @retval HAL status
825   */
HAL_HASH_SHA1_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)826 HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
827                                       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,const uint8_t * const pInBuffer,uint32_t Size)853 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)868 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)916 HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size)940 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_IT(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)954 HAL_StatusTypeDef HAL_HASH_MD5_Accmlt_End_IT(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)970 HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size)995 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_IT(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1009 HAL_StatusTypeDef HAL_HASH_SHA1_Accmlt_End_IT(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size)1082 HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size)1112 HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const 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,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)1169 HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
1170                                      uint8_t *pOutBuffer,
1171                                      uint32_t Timeout)
1172 {
1173   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
1174 }
1175 
1176 /**
1177   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1178   *         read the computed digest.
1179   * @note   Digest is available in pOutBuffer.
1180   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1181   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1182   * @param  hhash HASH handle.
1183   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1184   * @param  Size length of the input buffer in bytes.
1185   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1186   * @param  Timeout Timeout value.
1187   * @retval HAL status
1188   */
HAL_HMAC_SHA1_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout)1189 HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
1190                                       uint8_t *pOutBuffer,
1191                                       uint32_t Timeout)
1192 {
1193   return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
1194 }
1195 
1196 /**
1197   * @}
1198   */
1199 
1200 
1201 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
1202   *  @brief   HMAC processing functions using interrupt mode.
1203   *
1204 @verbatim
1205  ===============================================================================
1206                  ##### Interrupt mode HMAC processing functions #####
1207  ===============================================================================
1208     [..]  This section provides functions allowing to calculate in interrupt mode
1209           the HMAC value using one of the following algorithms:
1210       (+) MD5
1211          (++) HAL_HMAC_MD5_Start_IT()
1212       (+) SHA1
1213          (++) HAL_HMAC_SHA1_Start_IT()
1214 
1215 @endverbatim
1216   * @{
1217   */
1218 
1219 
1220 /**
1221   * @brief  Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1222   *         read the computed digest in interrupt mode.
1223   * @note   Digest is available in pOutBuffer.
1224   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1225   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1226   * @param  hhash HASH handle.
1227   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1228   * @param  Size length of the input buffer in bytes.
1229   * @param  pOutBuffer pointer to the computed digest. Digest size is 16 bytes.
1230   * @retval HAL status
1231   */
HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1232 HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
1233                                         uint8_t *pOutBuffer)
1234 {
1235   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
1236 }
1237 
1238 /**
1239   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1240   *         read the computed digest in interrupt mode.
1241   * @note   Digest is available in pOutBuffer.
1242   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1243   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1244   * @param  hhash HASH handle.
1245   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1246   * @param  Size length of the input buffer in bytes.
1247   * @param  pOutBuffer pointer to the computed digest. Digest size is 20 bytes.
1248   * @retval HAL status
1249   */
HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer)1250 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
1251                                          uint8_t *pOutBuffer)
1252 {
1253   return  HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
1254 }
1255 
1256 /**
1257   * @}
1258   */
1259 
1260 
1261 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
1262   *  @brief   HMAC processing functions using DMA modes.
1263   *
1264 @verbatim
1265  ===============================================================================
1266                  ##### DMA mode HMAC processing functions #####
1267  ===============================================================================
1268     [..]  This section provides functions allowing to calculate in DMA mode
1269           the HMAC value using one of the following algorithms:
1270       (+) MD5
1271          (++) HAL_HMAC_MD5_Start_DMA()
1272       (+) SHA1
1273          (++) HAL_HMAC_SHA1_Start_DMA()
1274 
1275     [..]  When resorting to DMA mode to enter the data in the Peripheral for HMAC processing,
1276           user must resort to  HAL_HMAC_xxx_Start_DMA() then read the resulting digest
1277           with HAL_HASH_xxx_Finish().
1278 
1279 @endverbatim
1280   * @{
1281   */
1282 
1283 
1284 /**
1285   * @brief  Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
1286   *         DMA transfers to feed the key and the input buffer to the Peripheral.
1287   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1288   *         to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
1289   *         the computed digest.
1290   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1291   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1292   * @note   If MDMAT bit is set before calling this function (multi-buffer
1293   *          HASH processing case), the input buffer size (in bytes) must be
1294   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
1295   *          For the processing of the last buffer of the thread, MDMAT bit must
1296   *          be reset and the buffer length (in bytes) doesn't have to be a
1297   *          multiple of 4.
1298   * @param  hhash HASH handle.
1299   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1300   * @param  Size length of the input buffer in bytes.
1301   * @retval HAL status
1302   */
HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)1303 HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
1304 {
1305   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
1306 }
1307 
1308 
1309 /**
1310   * @brief  Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
1311   *         DMA transfers to feed the key and the input buffer to the Peripheral.
1312   * @note   Once the DMA transfers are finished (indicated by hhash->State set back
1313   *         to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
1314   *         the computed digest.
1315   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
1316   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1317   * @note   If MDMAT bit is set before calling this function (multi-buffer
1318   *          HASH processing case), the input buffer size (in bytes) must be
1319   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
1320   *          For the processing of the last buffer of the thread, MDMAT bit must
1321   *          be reset and the buffer length (in bytes) doesn't have to be a
1322   *          multiple of 4.
1323   * @param  hhash HASH handle.
1324   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
1325   * @param  Size length of the input buffer in bytes.
1326   * @retval HAL status
1327   */
HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)1328 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
1329 {
1330   return  HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1331 }
1332 
1333 /**
1334   * @}
1335   */
1336 
1337 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
1338   *  @brief   Peripheral State functions.
1339   *
1340 @verbatim
1341  ===============================================================================
1342                       ##### Peripheral State methods #####
1343  ===============================================================================
1344     [..]
1345     This section permits to get in run-time the state and the peripheral handle
1346     status of the peripheral:
1347       (+) HAL_HASH_GetState()
1348       (+) HAL_HASH_GetStatus()
1349 
1350     [..]
1351     Additionally, this subsection provides functions allowing to save and restore
1352     the HASH or HMAC processing context in case of calculation suspension:
1353       (+) HAL_HASH_ContextSaving()
1354       (+) HAL_HASH_ContextRestoring()
1355 
1356     [..]
1357     This subsection provides functions allowing to suspend the HASH processing
1358       (+) when input are fed to the Peripheral by software
1359           (++) HAL_HASH_SwFeed_ProcessSuspend()
1360       (+) when input are fed to the Peripheral by DMA
1361           (++) HAL_HASH_DMAFeed_ProcessSuspend()
1362 
1363 
1364 
1365 @endverbatim
1366   * @{
1367   */
1368 
1369 /**
1370   * @brief  Return the HASH handle state.
1371   * @note   The API yields the current state of the handle (BUSY, READY,...).
1372   * @param  hhash HASH handle.
1373   * @retval HAL HASH state
1374   */
HAL_HASH_GetState(const HASH_HandleTypeDef * hhash)1375 HAL_HASH_StateTypeDef HAL_HASH_GetState(const HASH_HandleTypeDef *hhash)
1376 {
1377   return hhash->State;
1378 }
1379 
1380 
1381 /**
1382   * @brief Return the HASH HAL status.
1383   * @note  The API yields the HAL status of the handle: it is the result of the
1384   *        latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
1385   * @param  hhash HASH handle.
1386   * @retval HAL status
1387   */
HAL_HASH_GetStatus(const HASH_HandleTypeDef * hhash)1388 HAL_StatusTypeDef HAL_HASH_GetStatus(const HASH_HandleTypeDef *hhash)
1389 {
1390   return hhash->Status;
1391 }
1392 
1393 /**
1394   * @brief  Save the HASH context in case of processing suspension.
1395   * @param  hhash HASH handle.
1396   * @param  pMemBuffer pointer to the memory buffer where the HASH context
1397   *         is saved.
1398   * @note   The IMR, STR, CR then all the CSR registers are saved
1399   *         in that order. Only the r/w bits are read to be restored later on.
1400   * @note   By default, all the context swap registers (there are
1401   *         HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
1402   * @note   pMemBuffer points to a buffer allocated by the user. The buffer size
1403   *         must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
1404   * @retval None
1405   */
HAL_HASH_ContextSaving(const HASH_HandleTypeDef * hhash,const uint8_t * pMemBuffer)1406 void HAL_HASH_ContextSaving(const HASH_HandleTypeDef *hhash, const uint8_t *pMemBuffer)
1407 {
1408   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1409   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1410   uint32_t i;
1411 
1412   /* Prevent unused argument(s) compilation warning */
1413   UNUSED(hhash);
1414 
1415   /* Save IMR register content */
1416   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->IMR, HASH_IT_DINI | HASH_IT_DCI);
1417   mem_ptr += 4U;
1418   /* Save STR register content */
1419   *(uint32_t *)(mem_ptr) = READ_BIT(HASH->STR, HASH_STR_NBLW);
1420   mem_ptr += 4U;
1421   /* Save CR register content */
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   mem_ptr += 4U;
1425   /* By default, save all CSRs registers */
1426   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
1427   {
1428     *(uint32_t *)(mem_ptr) = *(uint32_t *)(csr_ptr);
1429     mem_ptr += 4U;
1430     csr_ptr += 4U;
1431   }
1432 }
1433 
1434 
1435 /**
1436   * @brief  Restore the HASH context in case of processing resumption.
1437   * @param  hhash HASH handle.
1438   * @param  pMemBuffer pointer to the memory buffer where the HASH context
1439   *         is stored.
1440   * @note   The IMR, STR, CR then all the CSR registers are restored
1441   *         in that order. Only the r/w bits are restored.
1442   * @note   By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
1443   *         of those) are restored (all of them have been saved by default
1444   *         beforehand).
1445   * @retval None
1446   */
HAL_HASH_ContextRestoring(HASH_HandleTypeDef * hhash,const uint8_t * pMemBuffer)1447 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, const uint8_t *pMemBuffer)
1448 {
1449   uint32_t mem_ptr = (uint32_t)pMemBuffer;
1450   uint32_t csr_ptr = (uint32_t)HASH->CSR;
1451   uint32_t i;
1452 
1453   /* Prevent unused argument(s) compilation warning */
1454   UNUSED(hhash);
1455 
1456   /* Restore IMR register content */
1457   WRITE_REG(HASH->IMR, (*(uint32_t *)(mem_ptr)));
1458   mem_ptr += 4U;
1459   /* Restore STR register content */
1460   WRITE_REG(HASH->STR, (*(uint32_t *)(mem_ptr)));
1461   mem_ptr += 4U;
1462   /* Restore CR register content */
1463   WRITE_REG(HASH->CR, (*(uint32_t *)(mem_ptr)));
1464   mem_ptr += 4U;
1465 
1466   /* Reset the HASH processor before restoring the Context
1467   Swap Registers (CSR) */
1468   __HAL_HASH_INIT();
1469 
1470   /* By default, restore all CSR registers */
1471   for (i = HASH_NUMBER_OF_CSR_REGISTERS; i > 0U; i--)
1472   {
1473     WRITE_REG((*(uint32_t *)(csr_ptr)), (*(uint32_t *)(mem_ptr)));
1474     mem_ptr += 4U;
1475     csr_ptr += 4U;
1476   }
1477 }
1478 
1479 
1480 /**
1481   * @brief  Initiate HASH processing suspension when in polling or interruption mode.
1482   * @param  hhash HASH handle.
1483   * @note   Set the handle field SuspendRequest to the appropriate value so that
1484   *         the on-going HASH processing is suspended as soon as the required
1485   *         conditions are met. Note that the actual suspension is carried out
1486   *         by the functions HASH_WriteData() in polling mode and HASH_IT() in
1487   *         interruption mode.
1488   * @retval None
1489   */
HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef * hhash)1490 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1491 {
1492   /* Set Handle Suspend Request field */
1493   hhash->SuspendRequest = HAL_HASH_SUSPEND;
1494 }
1495 
1496 /**
1497   * @brief  Suspend the HASH processing when in DMA mode.
1498   * @param  hhash HASH handle.
1499   * @note   When suspension attempt occurs at the very end of a DMA transfer and
1500   *         all the data have already been entered in the Peripheral, hhash->State is
1501   *         set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
1502   *         recommended to wrap-up the processing in reading the digest as usual.
1503   * @retval HAL status
1504   */
HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef * hhash)1505 HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1506 {
1507   uint32_t tmp_remaining_DMATransferSize_inWords;
1508   uint32_t tmp_initial_DMATransferSize_inWords;
1509   uint32_t tmp_words_already_pushed;
1510 
1511   if (hhash->State == HAL_HASH_STATE_READY)
1512   {
1513     return HAL_ERROR;
1514   }
1515   else
1516   {
1517 
1518     /* Make sure there is enough time to suspend the processing */
1519     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1520 
1521     if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT)
1522     {
1523       /* No suspension attempted since almost to the end of the transferred data. */
1524       /* Best option for user code is to wrap up low priority message hashing     */
1525       return HAL_ERROR;
1526     }
1527 
1528     /* Wait for BUSY flag to be reset */
1529     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1530     {
1531       return HAL_TIMEOUT;
1532     }
1533 
1534     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1535     {
1536       return HAL_ERROR;
1537     }
1538 
1539     /* Wait for BUSY flag to be set */
1540     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK)
1541     {
1542       return HAL_TIMEOUT;
1543     }
1544     /* Disable DMA channel */
1545     /* Note that the Abort function will
1546       - Clear the transfer error flags
1547       - Unlock
1548       - Set the State
1549     */
1550     if (HAL_DMA_Abort(hhash->hdmain) != HAL_OK)
1551     {
1552       return HAL_ERROR;
1553     }
1554 
1555     /* Clear DMAE bit */
1556     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1557 
1558     /* Wait for BUSY flag to be reset */
1559     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1560     {
1561       return HAL_TIMEOUT;
1562     }
1563 
1564     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1565     {
1566       return HAL_ERROR;
1567     }
1568 
1569     /* At this point, DMA interface is disabled and no transfer is on-going */
1570     /* Retrieve from the DMA handle how many words remain to be written */
1571     tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1572 
1573     if (tmp_remaining_DMATransferSize_inWords == 0U)
1574     {
1575       /* All the DMA transfer is actually done. Suspension occurred at the very end
1576          of the transfer. Either the digest computation is about to start (HASH case)
1577          or processing is about to move from one step to another (HMAC case).
1578          In both cases, the processing can't be suspended at this point. It is
1579          safer to
1580          - retrieve the low priority block digest before starting the high
1581            priority block processing (HASH case)
1582          - re-attempt a new suspension (HMAC case)
1583          */
1584       return HAL_ERROR;
1585     }
1586     else
1587     {
1588 
1589       /* Compute how many words were supposed to be transferred by DMA */
1590       tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount % 4U) != 0U) ? \
1591                                              ((hhash->HashInCount + 3U) / 4U) : (hhash->HashInCount / 4U));
1592 
1593       /* If discrepancy between the number of words reported by DMA Peripheral and
1594         the numbers of words entered as reported by HASH Peripheral, correct it */
1595       /* tmp_words_already_pushed reflects the number of words that were already pushed before
1596          the start of DMA transfer (multi-buffer processing case) */
1597       tmp_words_already_pushed = hhash->NbWordsAlreadyPushed;
1598       if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - \
1599             tmp_remaining_DMATransferSize_inWords) % 16U) != HASH_NBW_PUSHED())
1600       {
1601         tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */
1602       }
1603 
1604       /* Accordingly, update the input pointer that points at the next word to be
1605          transferred to the Peripheral by DMA */
1606       hhash->pHashInBuffPtr +=  4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ;
1607 
1608       /* And store in HashInCount the remaining size to transfer (in bytes) */
1609       hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords;
1610 
1611     }
1612 
1613     /* Set State as suspended */
1614     hhash->State = HAL_HASH_STATE_SUSPENDED;
1615 
1616     return HAL_OK;
1617 
1618   }
1619 }
1620 
1621 /**
1622   * @brief  Return the HASH handle error code.
1623   * @param  hhash pointer to a HASH_HandleTypeDef structure.
1624   * @retval HASH Error Code
1625   */
HAL_HASH_GetError(const HASH_HandleTypeDef * hhash)1626 uint32_t HAL_HASH_GetError(const HASH_HandleTypeDef *hhash)
1627 {
1628   /* Return HASH Error Code */
1629   return hhash->ErrorCode;
1630 }
1631 /**
1632   * @}
1633   */
1634 
1635 
1636 /**
1637   * @}
1638   */
1639 
1640 /** @defgroup HASH_Private_Functions HASH Private Functions
1641   * @{
1642   */
1643 
1644 /**
1645   * @brief DMA HASH Input Data transfer completion callback.
1646   * @param hdma DMA handle.
1647   * @note  In case of HMAC processing, HASH_DMAXferCplt() initiates
1648   *        the next DMA transfer for the following HMAC step.
1649   * @retval None
1650   */
HASH_DMAXferCplt(DMA_HandleTypeDef * hdma)1651 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma)
1652 {
1653   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1654   uint32_t inputaddr;
1655   uint32_t buffersize;
1656   HAL_StatusTypeDef status;
1657 
1658   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1659   {
1660 
1661     /* Disable the DMA transfer */
1662     CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1663 
1664     if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U)
1665     {
1666       /* If no HMAC processing, input data transfer is now over */
1667 
1668       /* Change the HASH state to ready */
1669       hhash->State = HAL_HASH_STATE_READY;
1670 
1671       /* Call Input data transfer complete call back */
1672 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1673       hhash->InCpltCallback(hhash);
1674 #else
1675       HAL_HASH_InCpltCallback(hhash);
1676 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1677 
1678     }
1679     else
1680     {
1681       /* HMAC processing: depending on the current HMAC step and whether or
1682       not multi-buffer processing is on-going, the next step is initiated
1683       and MDMAT bit is set.  */
1684 
1685 
1686       if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
1687       {
1688         /* This is the end of HMAC processing */
1689 
1690         /* Change the HASH state to ready */
1691         hhash->State = HAL_HASH_STATE_READY;
1692 
1693         /* Call Input data transfer complete call back
1694         (note that the last DMA transfer was that of the key
1695         for the outer HASH operation). */
1696 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1697         hhash->InCpltCallback(hhash);
1698 #else
1699         HAL_HASH_InCpltCallback(hhash);
1700 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1701 
1702         return;
1703       }
1704       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
1705       {
1706         inputaddr = (uint32_t)hhash->pHashMsgBuffPtr;     /* DMA transfer start address */
1707         buffersize = hhash->HashBuffSize;                 /* DMA transfer size (in bytes) */
1708         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
1709 
1710         /* In case of suspension request, save the new starting parameters */
1711         hhash->HashInCount = hhash->HashBuffSize;         /* Initial DMA transfer size (in bytes) */
1712         hhash->pHashInBuffPtr  = hhash->pHashMsgBuffPtr ; /* DMA transfer start address           */
1713 
1714         hhash->NbWordsAlreadyPushed = 0U;                  /* Reset number of words already pushed */
1715         /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */
1716         if (hhash->DigestCalculationDisable != RESET)
1717         {
1718           /* Digest calculation is disabled: Step 2 must start with MDMAT bit set,
1719           no digest calculation will be triggered at the end of the input buffer feeding to the Peripheral */
1720           __HAL_HASH_SET_MDMAT();
1721         }
1722       }
1723       else  /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
1724       {
1725         if (hhash->DigestCalculationDisable != RESET)
1726         {
1727           /* No automatic move to Step 3 as a new message buffer will be fed to the Peripheral
1728           (case of multi-buffer HMAC processing):
1729           DCAL must not be set.
1730           Phase remains in Step 2, MDMAT remains set at this point.
1731           Change the HASH state to ready and call Input data transfer complete call back. */
1732           hhash->State = HAL_HASH_STATE_READY;
1733 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1734           hhash->InCpltCallback(hhash);
1735 #else
1736           HAL_HASH_InCpltCallback(hhash);
1737 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1738           return ;
1739         }
1740         else
1741         {
1742           /* Digest calculation is not disabled (case of single buffer input or last buffer
1743           of multi-buffer HMAC processing) */
1744           inputaddr = (uint32_t)hhash->Init.pKey;       /* DMA transfer start address */
1745           buffersize = hhash->Init.KeySize;             /* DMA transfer size (in bytes) */
1746           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;    /* Move phase from Step 2 to Step 3 */
1747           /* In case of suspension request, save the new starting parameters */
1748           hhash->HashInCount = hhash->Init.KeySize;     /* Initial size for second DMA transfer (input data) */
1749           hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* address passed to DMA, now entering data message */
1750 
1751           hhash->NbWordsAlreadyPushed = 0U;              /* Reset number of words already pushed */
1752         }
1753       }
1754 
1755       /* Configure the Number of valid bits in last word of the message */
1756       __HAL_HASH_SET_NBVALIDBITS(buffersize);
1757 
1758       /* Set the HASH DMA transfer completion call back */
1759       hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
1760 
1761       /* Enable the DMA In DMA stream */
1762       status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
1763                                 (((buffersize % 4U) != 0U) ? ((buffersize + (4U - (buffersize % 4U))) / 4U) : \
1764                                  (buffersize / 4U)));
1765 
1766       /* Enable DMA requests */
1767       SET_BIT(HASH->CR, HASH_CR_DMAE);
1768 
1769       /* Return function status */
1770       if (status != HAL_OK)
1771       {
1772         /* Update HASH state machine to error */
1773         hhash->State = HAL_HASH_STATE_ERROR;
1774       }
1775       else
1776       {
1777         /* Change HASH state */
1778         hhash->State = HAL_HASH_STATE_BUSY;
1779       }
1780     }
1781   }
1782 
1783   return;
1784 }
1785 
1786 /**
1787   * @brief DMA HASH communication error callback.
1788   * @param hdma DMA handle.
1789   * @note  HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
1790   *        can contain user code to manage the error.
1791   * @retval None
1792   */
HASH_DMAError(DMA_HandleTypeDef * hdma)1793 static void HASH_DMAError(DMA_HandleTypeDef *hdma)
1794 {
1795   HASH_HandleTypeDef *hhash = (HASH_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
1796 
1797   if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1798   {
1799     hhash->ErrorCode |= HAL_HASH_ERROR_DMA;
1800     /* Set HASH state to ready to prevent any blocking issue in user code
1801        present in HAL_HASH_ErrorCallback() */
1802     hhash->State = HAL_HASH_STATE_READY;
1803     /* Set HASH handle status to error */
1804     hhash->Status = HAL_ERROR;
1805 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1806     hhash->ErrorCallback(hhash);
1807 #else
1808     HAL_HASH_ErrorCallback(hhash);
1809 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1810     /* After error handling by code user, reset HASH handle HAL status */
1811     hhash->Status = HAL_OK;
1812 
1813   }
1814 }
1815 
1816 /**
1817   * @brief  Feed the input buffer to the HASH Peripheral.
1818   * @param  hhash HASH handle.
1819   * @param  pInBuffer pointer to input buffer.
1820   * @param  Size the size of input buffer in bytes.
1821   * @note   HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
1822   *         or not the HASH processing must be suspended. If this is the case, the
1823   *         processing is suspended when possible and the Peripheral feeding point reached at
1824   *         suspension time is stored in the handle for resumption later on.
1825   * @retval HAL status
1826   */
HASH_WriteData(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size)1827 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size)
1828 {
1829   uint32_t buffercounter;
1830   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
1831   uint32_t tmp;
1832 
1833   for (buffercounter = 0U; buffercounter < (Size / 4U); buffercounter++)
1834   {
1835     /* Write input data 4 bytes at a time */
1836     HASH->DIN = *(uint32_t *)inputaddr;
1837     inputaddr += 4U;
1838 
1839     /* If the suspension flag has been raised and if the processing is not about
1840     to end, suspend processing */
1841     if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && (((buffercounter * 4U) + 4U) < Size))
1842     {
1843       /* wait for flag BUSY not set before  Wait for DINIS = 1*/
1844       if ((buffercounter * 4U) >= 64U)
1845       {
1846         if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1847         {
1848           return HAL_TIMEOUT;
1849         }
1850       }
1851       /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
1852       in the input buffer */
1853       if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
1854       {
1855         /* Reset SuspendRequest */
1856         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
1857 
1858         /* Depending whether the key or the input data were fed to the Peripheral, the feeding point
1859         reached at suspension time is not saved in the same handle fields */
1860         if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
1861         {
1862           /* Save current reading and writing locations of Input and Output buffers */
1863           hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
1864           /* Save the number of bytes that remain to be processed at this point */
1865           hhash->HashInCount    =  Size - ((buffercounter * 4U) + 4U);
1866         }
1867         else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
1868         {
1869           /* Save current reading and writing locations of Input and Output buffers */
1870           hhash->pHashKeyBuffPtr  = (uint8_t *)inputaddr;
1871           /* Save the number of bytes that remain to be processed at this point */
1872           hhash->HashKeyCount  =  Size - ((buffercounter * 4U) + 4U);
1873         }
1874         else
1875         {
1876           /* Unexpected phase: unlock process and report error */
1877           hhash->State = HAL_HASH_STATE_READY;
1878           __HAL_UNLOCK(hhash);
1879           return HAL_ERROR;
1880         }
1881 
1882         /* Set the HASH state to Suspended and exit to stop entering data */
1883         hhash->State = HAL_HASH_STATE_SUSPENDED;
1884 
1885         return HAL_OK;
1886       } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))  */
1887     } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
1888   }   /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4)                 */
1889 
1890   /* At this point, all the data have been entered to the Peripheral: exit */
1891 
1892   if ((Size % 4U) != 0U)
1893   {
1894     if (hhash->Init.DataType == HASH_DATATYPE_16B)
1895     {
1896       /* Write remaining input data */
1897 
1898       if ((Size % 4U) <= 2U)
1899       {
1900         HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
1901       }
1902       if ((Size % 4U) == 3U)
1903       {
1904         HASH->DIN = *(uint32_t *)inputaddr;
1905       }
1906 
1907     }
1908     else if ((hhash->Init.DataType == HASH_DATATYPE_8B)
1909              || (hhash->Init.DataType == HASH_DATATYPE_1B))  /* byte swap or bit swap or */
1910     {
1911       /* Write remaining input data */
1912       if ((Size % 4U) == 1U)
1913       {
1914         HASH->DIN = (uint32_t) * (uint8_t *)inputaddr;
1915       }
1916       if ((Size % 4U) == 2U)
1917       {
1918         HASH->DIN = (uint32_t) * (uint16_t *)inputaddr;
1919       }
1920       if ((Size % 4U) == 3U)
1921       {
1922         tmp  = *(uint8_t *)inputaddr;
1923         tmp |= (uint32_t) * (uint8_t *)(inputaddr + 1U) << 8U;
1924         tmp |= (uint32_t) * (uint8_t *)(inputaddr + 2U) << 16U;
1925         HASH->DIN = tmp;
1926       }
1927 
1928     }
1929     else
1930     {
1931       HASH->DIN = *(uint32_t *)inputaddr;
1932     }
1933   }
1934 
1935 
1936   return  HAL_OK;
1937 }
1938 
1939 /**
1940   * @brief  Retrieve the message digest.
1941   * @param  pMsgDigest pointer to the computed digest.
1942   * @param  Size message digest size in bytes.
1943   * @retval None
1944   */
HASH_GetDigest(const uint8_t * pMsgDigest,uint8_t Size)1945 static void HASH_GetDigest(const uint8_t *pMsgDigest, uint8_t Size)
1946 {
1947   uint32_t msgdigest = (uint32_t)pMsgDigest;
1948 
1949   switch (Size)
1950   {
1951     /* Read the message digest */
1952     case 16:  /* MD5 */
1953       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1954       msgdigest += 4U;
1955       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1956       msgdigest += 4U;
1957       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1958       msgdigest += 4U;
1959       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1960       break;
1961     case 20:  /* SHA1 */
1962       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1963       msgdigest += 4U;
1964       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1965       msgdigest += 4U;
1966       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1967       msgdigest += 4U;
1968       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1969       msgdigest += 4U;
1970       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
1971       break;
1972     case 28:  /* SHA224 */
1973       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1974       msgdigest += 4U;
1975       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1976       msgdigest += 4U;
1977       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1978       msgdigest += 4U;
1979       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1980       msgdigest += 4U;
1981       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
1982       msgdigest += 4U;
1983       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
1984       msgdigest += 4U;
1985       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
1986       break;
1987     case 32:   /* SHA256 */
1988       *(uint32_t *)(msgdigest) = __REV(HASH->HR[0]);
1989       msgdigest += 4U;
1990       *(uint32_t *)(msgdigest) = __REV(HASH->HR[1]);
1991       msgdigest += 4U;
1992       *(uint32_t *)(msgdigest) = __REV(HASH->HR[2]);
1993       msgdigest += 4U;
1994       *(uint32_t *)(msgdigest) = __REV(HASH->HR[3]);
1995       msgdigest += 4U;
1996       *(uint32_t *)(msgdigest) = __REV(HASH->HR[4]);
1997       msgdigest += 4U;
1998       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
1999       msgdigest += 4U;
2000       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
2001       msgdigest += 4U;
2002       *(uint32_t *)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
2003       break;
2004     default:
2005       break;
2006   }
2007 }
2008 
2009 
2010 /**
2011   * @brief  Handle HASH processing Timeout.
2012   * @param  hhash HASH handle.
2013   * @param  Flag specifies the HASH flag to check.
2014   * @param  Status the Flag status (SET or RESET).
2015   * @param  Timeout Timeout duration.
2016   * @retval HAL status
2017   */
HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef * hhash,uint32_t Flag,FlagStatus Status,uint32_t Timeout)2018 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status,
2019                                                      uint32_t Timeout)
2020 {
2021   uint32_t tickstart = HAL_GetTick();
2022 
2023   /* Wait until flag is set */
2024   if (Status == RESET)
2025   {
2026     while (__HAL_HASH_GET_FLAG(Flag) == RESET)
2027     {
2028       /* Check for the Timeout */
2029       if (Timeout != HAL_MAX_DELAY)
2030       {
2031         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
2032         {
2033           /* Set State to Ready to be able to restart later on */
2034           hhash->State  = HAL_HASH_STATE_READY;
2035           /* Store time out issue in handle status */
2036           hhash->Status = HAL_TIMEOUT;
2037 
2038           /* Process Unlocked */
2039           __HAL_UNLOCK(hhash);
2040 
2041           return HAL_TIMEOUT;
2042         }
2043       }
2044     }
2045   }
2046   else
2047   {
2048     while (__HAL_HASH_GET_FLAG(Flag) != RESET)
2049     {
2050       /* Check for the Timeout */
2051       if (Timeout != HAL_MAX_DELAY)
2052       {
2053         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
2054         {
2055           /* Set State to Ready to be able to restart later on */
2056           hhash->State  = HAL_HASH_STATE_READY;
2057           /* Store time out issue in handle status */
2058           hhash->Status = HAL_TIMEOUT;
2059 
2060           /* Process Unlocked */
2061           __HAL_UNLOCK(hhash);
2062 
2063           return HAL_TIMEOUT;
2064         }
2065       }
2066     }
2067   }
2068   return HAL_OK;
2069 }
2070 
2071 
2072 /**
2073   * @brief  HASH processing in interruption mode.
2074   * @param  hhash HASH handle.
2075   * @note   HASH_IT() regularly reads hhash->SuspendRequest to check whether
2076   *         or not the HASH processing must be suspended. If this is the case, the
2077   *         processing is suspended when possible and the Peripheral feeding point reached at
2078   *         suspension time is stored in the handle for resumption later on.
2079   * @retval HAL status
2080   */
HASH_IT(HASH_HandleTypeDef * hhash)2081 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
2082 {
2083   if (hhash->State == HAL_HASH_STATE_BUSY)
2084   {
2085     /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
2086     if (hhash->HashITCounter == 0U)
2087     {
2088       /* Disable Interrupts */
2089       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2090       /* HASH state set back to Ready to prevent any issue in user code
2091          present in HAL_HASH_ErrorCallback() */
2092       hhash->State = HAL_HASH_STATE_READY;
2093       return HAL_ERROR;
2094     }
2095     else if (hhash->HashITCounter == 1U)
2096     {
2097       /* This is the first call to HASH_IT, the first input data are about to be
2098          entered in the Peripheral. A specific processing is carried out at this point to
2099          start-up the processing. */
2100       hhash->HashITCounter = 2U;
2101     }
2102     else
2103     {
2104       /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
2105         the HASH processing or the end of the current step for HMAC processing. */
2106       hhash->HashITCounter = 3U;
2107     }
2108 
2109     /* If digest is ready */
2110     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
2111     {
2112       /* Read the digest */
2113       HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2114 
2115       /* Disable Interrupts */
2116       __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2117       /* Change the HASH state */
2118       hhash->State = HAL_HASH_STATE_READY;
2119       /* Reset HASH state machine */
2120       hhash->Phase = HAL_HASH_PHASE_READY;
2121       /* Call digest computation complete call back */
2122 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2123       hhash->DgstCpltCallback(hhash);
2124 #else
2125       HAL_HASH_DgstCpltCallback(hhash);
2126 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2127 
2128       return HAL_OK;
2129     }
2130 
2131     /* If Peripheral ready to accept new data */
2132     if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2133     {
2134 
2135       /* If the suspension flag has been raised and if the processing is not about
2136          to end, suspend processing */
2137       if ((hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
2138       {
2139         /* Disable Interrupts */
2140         __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2141 
2142         /* Reset SuspendRequest */
2143         hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
2144 
2145         /* Change the HASH state */
2146         hhash->State = HAL_HASH_STATE_SUSPENDED;
2147 
2148         return HAL_OK;
2149       }
2150 
2151       /* Enter input data in the Peripheral through HASH_Write_Block_Data() call and
2152         check whether the digest calculation has been triggered */
2153       if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
2154       {
2155         /* Call Input data transfer complete call back
2156            (called at the end of each step for HMAC) */
2157 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2158         hhash->InCpltCallback(hhash);
2159 #else
2160         HAL_HASH_InCpltCallback(hhash);
2161 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2162 
2163         if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2164         {
2165           /* Wait until Peripheral is not busy anymore */
2166           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2167           {
2168             /* Disable Interrupts */
2169             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2170             return HAL_TIMEOUT;
2171           }
2172           /* Initialization start for HMAC STEP 2 */
2173           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;        /* Move phase from Step 1 to Step 2 */
2174           __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);  /* Set NBLW for the input message */
2175           hhash->HashInCount = hhash->HashBuffSize;         /* Set the input data size (in bytes) */
2176           hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr;   /* Set the input data address */
2177           hhash->HashITCounter = 1;                         /* Set ITCounter to 1 to indicate the start
2178                                                                of a new phase */
2179           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);               /* Enable IT (was disabled in HASH_Write_Block_Data) */
2180         }
2181         else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2182         {
2183           /* Wait until Peripheral is not busy anymore */
2184           if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
2185           {
2186             /* Disable Interrupts */
2187             __HAL_HASH_DISABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
2188             return HAL_TIMEOUT;
2189           }
2190           /* Initialization start for HMAC STEP 3 */
2191           hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;         /* Move phase from Step 2 to Step 3 */
2192           __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);   /* Set NBLW for the key */
2193           hhash->HashInCount = hhash->Init.KeySize;          /* Set the key size (in bytes) */
2194           hhash->pHashInBuffPtr = hhash->Init.pKey;          /* Set the key address */
2195           hhash->HashITCounter = 1;                          /* Set ITCounter to 1 to indicate the start
2196                                                                 of a new phase */
2197           __HAL_HASH_ENABLE_IT(HASH_IT_DINI);                /* Enable IT (was disabled in HASH_Write_Block_Data) */
2198         }
2199         else
2200         {
2201           /* Nothing to do */
2202         }
2203       } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
2204     }  /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
2205 
2206     /* Return function status */
2207     return HAL_OK;
2208   }
2209   else
2210   {
2211     return HAL_BUSY;
2212   }
2213 }
2214 
2215 
2216 /**
2217   * @brief  Write a block of data in HASH Peripheral in interruption mode.
2218   * @param  hhash HASH handle.
2219   * @note   HASH_Write_Block_Data() is called under interruption by HASH_IT().
2220   * @retval HAL status
2221   */
HASH_Write_Block_Data(HASH_HandleTypeDef * hhash)2222 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
2223 {
2224   uint32_t inputaddr;
2225   uint32_t buffercounter;
2226   uint32_t inputcounter;
2227   uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
2228 
2229   /* If there are more than 64 bytes remaining to be entered */
2230   if (hhash->HashInCount > 64U)
2231   {
2232     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2233     /* Write the Input block in the Data IN register
2234       (16 32-bit words, or 64 bytes are entered) */
2235     for (buffercounter = 0U; buffercounter < 64U; buffercounter += 4U)
2236     {
2237       HASH->DIN = *(uint32_t *)inputaddr;
2238       inputaddr += 4U;
2239     }
2240     /* If this is the start of input data entering, an additional word
2241       must be entered to start up the HASH processing */
2242     if (hhash->HashITCounter == 2U)
2243     {
2244       HASH->DIN = *(uint32_t *)inputaddr;
2245       if (hhash->HashInCount >= 68U)
2246       {
2247         /* There are still data waiting to be entered in the Peripheral.
2248            Decrement buffer counter and set pointer to the proper
2249            memory location for the next data entering round. */
2250         hhash->HashInCount -= 68U;
2251         hhash->pHashInBuffPtr += 68U;
2252       }
2253       else
2254       {
2255         /* All the input buffer has been fed to the HW. */
2256         hhash->HashInCount = 0U;
2257       }
2258     }
2259     else
2260     {
2261       /* 64 bytes have been entered and there are still some remaining:
2262          Decrement buffer counter and set pointer to the proper
2263         memory location for the next data entering round.*/
2264       hhash->HashInCount -= 64U;
2265       hhash->pHashInBuffPtr += 64U;
2266     }
2267   }
2268   else
2269   {
2270     /* 64 or less bytes remain to be entered. This is the last
2271       data entering round. */
2272 
2273     /* Get the buffer address */
2274     inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2275     /* Get the buffer counter */
2276     inputcounter = hhash->HashInCount;
2277     /* Disable Interrupts */
2278     __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
2279 
2280     /* Write the Input block in the Data IN register */
2281     for (buffercounter = 0U; buffercounter < ((inputcounter + 3U) / 4U); buffercounter++)
2282     {
2283       HASH->DIN = *(uint32_t *)inputaddr;
2284       inputaddr += 4U;
2285     }
2286 
2287     if (hhash->Accumulation == 1U)
2288     {
2289       /* Field accumulation is set, API only feeds data to the Peripheral and under interruption.
2290          The digest computation will be started when the last buffer data are entered. */
2291 
2292       /* Reset multi buffers accumulation flag */
2293       hhash->Accumulation = 0U;
2294       /* Change the HASH state */
2295       hhash->State = HAL_HASH_STATE_READY;
2296       /* Call Input data transfer complete call back */
2297 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
2298       hhash->InCpltCallback(hhash);
2299 #else
2300       HAL_HASH_InCpltCallback(hhash);
2301 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
2302     }
2303     else
2304     {
2305       /* Start the Digest calculation */
2306       __HAL_HASH_START_DIGEST();
2307       /* Return indication that digest calculation has started:
2308          this return value triggers the call to Input data transfer
2309          complete call back as well as the proper transition from
2310          one step to another in HMAC mode. */
2311       ret = HASH_DIGEST_CALCULATION_STARTED;
2312     }
2313     /* Reset buffer counter */
2314     hhash->HashInCount = 0;
2315   }
2316 
2317   /* Return whether or digest calculation has started */
2318   return ret;
2319 }
2320 
2321 /**
2322   * @brief  HMAC processing in polling mode.
2323   * @param  hhash HASH handle.
2324   * @param  Timeout Timeout value.
2325   * @retval HAL status
2326   */
HMAC_Processing(HASH_HandleTypeDef * hhash,uint32_t Timeout)2327 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
2328 {
2329   /* Ensure first that Phase is correct */
2330   if ((hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_1) && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_2)
2331       && (hhash->Phase != HAL_HASH_PHASE_HMAC_STEP_3))
2332   {
2333     /* Change the HASH state */
2334     hhash->State = HAL_HASH_STATE_READY;
2335 
2336     /* Process Unlock */
2337     __HAL_UNLOCK(hhash);
2338 
2339     /* Return function status */
2340     return HAL_ERROR;
2341   }
2342 
2343   /* HMAC Step 1 processing */
2344   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2345   {
2346     /************************** STEP 1 ******************************************/
2347     /* Configure the Number of valid bits in last word of the message */
2348     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2349 
2350     /* Write input buffer in Data register */
2351     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2352     if (hhash->Status != HAL_OK)
2353     {
2354       return hhash->Status;
2355     }
2356 
2357     /* Check whether or not key entering process has been suspended */
2358     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2359     {
2360       /* Process Unlocked */
2361       __HAL_UNLOCK(hhash);
2362 
2363       /* Stop right there and return function status */
2364       return HAL_OK;
2365     }
2366 
2367     /* No processing suspension at this point: set DCAL bit. */
2368     __HAL_HASH_START_DIGEST();
2369 
2370     /* Wait for BUSY flag to be cleared */
2371     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2372     {
2373       return HAL_TIMEOUT;
2374     }
2375 
2376     /* Move from Step 1 to Step 2 */
2377     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
2378 
2379   }
2380 
2381   /* HMAC Step 2 processing.
2382      After phase check, HMAC_Processing() may
2383      - directly start up from this point in resumption case
2384        if the same Step 2 processing was suspended previously
2385     - or fall through from the Step 1 processing carried out hereabove */
2386   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2387   {
2388     /************************** STEP 2 ******************************************/
2389     /* Configure the Number of valid bits in last word of the message */
2390     __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
2391 
2392     /* Write input buffer in Data register */
2393     hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
2394     if (hhash->Status != HAL_OK)
2395     {
2396       return hhash->Status;
2397     }
2398 
2399     /* Check whether or not data entering process has been suspended */
2400     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2401     {
2402       /* Process Unlocked */
2403       __HAL_UNLOCK(hhash);
2404 
2405       /* Stop right there and return function status */
2406       return HAL_OK;
2407     }
2408 
2409     /* No processing suspension at this point: set DCAL bit. */
2410     __HAL_HASH_START_DIGEST();
2411 
2412     /* Wait for BUSY flag to be cleared */
2413     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2414     {
2415       return HAL_TIMEOUT;
2416     }
2417 
2418     /* Move from Step 2 to Step 3 */
2419     hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
2420     /* In case Step 1 phase was suspended then resumed,
2421        set again Key input buffers and size before moving to
2422        next step */
2423     hhash->pHashKeyBuffPtr = hhash->Init.pKey;
2424     hhash->HashKeyCount    = hhash->Init.KeySize;
2425   }
2426 
2427 
2428   /* HMAC Step 3 processing.
2429       After phase check, HMAC_Processing() may
2430       - directly start up from this point in resumption case
2431         if the same Step 3 processing was suspended previously
2432      - or fall through from the Step 2 processing carried out hereabove */
2433   if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
2434   {
2435     /************************** STEP 3 ******************************************/
2436     /* Configure the Number of valid bits in last word of the message */
2437     __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2438 
2439     /* Write input buffer in Data register */
2440     hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2441     if (hhash->Status != HAL_OK)
2442     {
2443       return hhash->Status;
2444     }
2445 
2446     /* Check whether or not key entering process has been suspended */
2447     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2448     {
2449       /* Process Unlocked */
2450       __HAL_UNLOCK(hhash);
2451 
2452       /* Stop right there and return function status */
2453       return HAL_OK;
2454     }
2455 
2456     /* No processing suspension at this point: start the Digest calculation. */
2457     __HAL_HASH_START_DIGEST();
2458 
2459     /* Wait for DCIS flag to be set */
2460     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2461     {
2462       return HAL_TIMEOUT;
2463     }
2464 
2465     /* Read the message digest */
2466     HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2467 
2468     /* Reset HASH state machine */
2469     hhash->Phase = HAL_HASH_PHASE_READY;
2470   }
2471 
2472   /* Change the HASH state */
2473   hhash->State = HAL_HASH_STATE_READY;
2474 
2475   /* Process Unlock */
2476   __HAL_UNLOCK(hhash);
2477 
2478   /* Return function status */
2479   return HAL_OK;
2480 }
2481 
2482 
2483 /**
2484   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2485   *         read the computed digest.
2486   * @note   Digest is available in pOutBuffer.
2487   * @param  hhash HASH handle.
2488   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2489   * @param  Size length of the input buffer in bytes.
2490   * @param  pOutBuffer pointer to the computed digest.
2491   * @param  Timeout Timeout value.
2492   * @param  Algorithm HASH algorithm.
2493   * @retval HAL status
2494   */
HASH_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)2495 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
2496                              uint8_t *pOutBuffer,
2497                              uint32_t Timeout, uint32_t Algorithm)
2498 {
2499   const uint8_t *pInBuffer_tmp;  /* input data address, input parameter of HASH_WriteData()         */
2500   uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
2501   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2502 
2503 
2504   /* Initiate HASH processing in case of start or resumption */
2505   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2506   {
2507     /* Check input parameters */
2508     if ((pInBuffer == NULL) || (pOutBuffer == NULL))
2509     {
2510       hhash->State = HAL_HASH_STATE_READY;
2511       return  HAL_ERROR;
2512     }
2513 
2514     /* Process Locked */
2515     __HAL_LOCK(hhash);
2516 
2517     /* Check if initialization phase has not been already performed */
2518     if (hhash->Phase == HAL_HASH_PHASE_READY)
2519     {
2520       /* Change the HASH state */
2521       hhash->State = HAL_HASH_STATE_BUSY;
2522 
2523       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2524       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2525 
2526       /* Configure the number of valid bits in last word of the message */
2527       __HAL_HASH_SET_NBVALIDBITS(Size);
2528 
2529       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2530       input parameters of HASH_WriteData() */
2531       pInBuffer_tmp = (const uint8_t *)pInBuffer;   /* pInBuffer_tmp is set to the input data address */
2532       Size_tmp = Size;             /* Size_tmp contains the input data size in bytes */
2533 
2534       /* Set the phase */
2535       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2536     }
2537     else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
2538     {
2539       /* if the Peripheral has already been initialized, two cases are possible */
2540 
2541       /* Process resumption time ... */
2542       if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2543       {
2544         /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2545         to the API input parameters but to those saved beforehand by HASH_WriteData()
2546         when the processing was suspended */
2547         pInBuffer_tmp = (const uint8_t *)hhash->pHashInBuffPtr;
2548         Size_tmp = hhash->HashInCount;
2549       }
2550       /* ... or multi-buffer HASH processing end */
2551       else
2552       {
2553         /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2554         input parameters of HASH_WriteData() */
2555         pInBuffer_tmp = (const uint8_t *)pInBuffer;
2556         Size_tmp = Size;
2557         /* Configure the number of valid bits in last word of the message */
2558         __HAL_HASH_SET_NBVALIDBITS(Size);
2559       }
2560       /* Change the HASH state */
2561       hhash->State = HAL_HASH_STATE_BUSY;
2562     }
2563     else
2564     {
2565       /* Phase error */
2566       hhash->State = HAL_HASH_STATE_READY;
2567 
2568       /* Process Unlocked */
2569       __HAL_UNLOCK(hhash);
2570 
2571       /* Return function status */
2572       return HAL_ERROR;
2573     }
2574 
2575 
2576     /* Write input buffer in Data register */
2577     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2578     if (hhash->Status != HAL_OK)
2579     {
2580       return hhash->Status;
2581     }
2582 
2583     /* If the process has not been suspended, carry on to digest calculation */
2584     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2585     {
2586       /* Start the Digest calculation */
2587       __HAL_HASH_START_DIGEST();
2588 
2589       /* Wait for DCIS flag to be set */
2590       if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2591       {
2592         return HAL_TIMEOUT;
2593       }
2594 
2595       /* Read the message digest */
2596       HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
2597 
2598       /* Change the HASH state */
2599       hhash->State = HAL_HASH_STATE_READY;
2600 
2601       /* Reset HASH state machine */
2602       hhash->Phase = HAL_HASH_PHASE_READY;
2603 
2604     }
2605 
2606     /* Process Unlocked */
2607     __HAL_UNLOCK(hhash);
2608 
2609     /* Return function status */
2610     return HAL_OK;
2611 
2612   }
2613   else
2614   {
2615     return HAL_BUSY;
2616   }
2617 }
2618 
2619 
2620 /**
2621   * @brief  If not already done, initialize the HASH peripheral then
2622   *         processes pInBuffer.
2623   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
2624   *         the Peripheral has already been initialized.
2625   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2626   *         HASH digest computation is corrupted.
2627   * @param  hhash HASH handle.
2628   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2629   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
2630   * @param  Algorithm HASH algorithm.
2631   * @retval HAL status
2632   */
HASH_Accumulate(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint32_t Algorithm)2633 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
2634                                   uint32_t Algorithm)
2635 {
2636   const uint8_t *pInBuffer_tmp;   /* input data address, input parameter of HASH_WriteData()         */
2637   uint32_t Size_tmp;  /* input data size (in bytes), input parameter of HASH_WriteData() */
2638   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2639 
2640   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2641   if ((Size % 4U) != 0U)
2642   {
2643     return  HAL_ERROR;
2644   }
2645 
2646   /* Initiate HASH processing in case of start or resumption */
2647   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2648   {
2649     /* Check input parameters */
2650     if ((pInBuffer == NULL) || (Size == 0U))
2651     {
2652       hhash->State = HAL_HASH_STATE_READY;
2653       return  HAL_ERROR;
2654     }
2655 
2656     /* Process Locked */
2657     __HAL_LOCK(hhash);
2658 
2659     /* If resuming the HASH processing */
2660     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2661     {
2662       /* Change the HASH state */
2663       hhash->State = HAL_HASH_STATE_BUSY;
2664 
2665       /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2666          to the API input parameters but to those saved beforehand by HASH_WriteData()
2667          when the processing was suspended */
2668       pInBuffer_tmp = (const uint8_t *)hhash->pHashInBuffPtr;  /* pInBuffer_tmp is set to the input data address */
2669       Size_tmp = hhash->HashInCount;          /* Size_tmp contains the input data size in bytes */
2670 
2671     }
2672     else
2673     {
2674       /* Change the HASH state */
2675       hhash->State = HAL_HASH_STATE_BUSY;
2676 
2677       /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2678          input parameters of HASH_WriteData() */
2679       pInBuffer_tmp = (const uint8_t *)pInBuffer;    /* pInBuffer_tmp is set to the input data address */
2680       Size_tmp = Size;              /* Size_tmp contains the input data size in bytes */
2681 
2682       /* Check if initialization phase has already be performed */
2683       if (hhash->Phase == HAL_HASH_PHASE_READY)
2684       {
2685         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2686         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2687       }
2688 
2689       /* Set the phase */
2690       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2691 
2692     }
2693 
2694     /* Write input buffer in Data register */
2695     hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2696     if (hhash->Status != HAL_OK)
2697     {
2698       return hhash->Status;
2699     }
2700 
2701     /* If the process has not been suspended, move the state to Ready */
2702     if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2703     {
2704       /* Change the HASH state */
2705       hhash->State = HAL_HASH_STATE_READY;
2706     }
2707 
2708     /* Process Unlocked */
2709     __HAL_UNLOCK(hhash);
2710 
2711     /* Return function status */
2712     return HAL_OK;
2713 
2714   }
2715   else
2716   {
2717     return HAL_BUSY;
2718   }
2719 
2720 
2721 }
2722 
2723 
2724 /**
2725   * @brief  If not already done, initialize the HASH peripheral then
2726   *         processes pInBuffer in interruption mode.
2727   * @note   Field hhash->Phase of HASH handle is tested to check whether or not
2728   *         the Peripheral has already been initialized.
2729   * @note   The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2730   *         HASH digest computation is corrupted.
2731   * @param  hhash HASH handle.
2732   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2733   * @param  Size length of the input buffer in bytes, must be a multiple of 4.
2734   * @param  Algorithm HASH algorithm.
2735   * @retval HAL status
2736   */
HASH_Accumulate_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint32_t Algorithm)2737 HAL_StatusTypeDef HASH_Accumulate_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
2738                                      uint32_t Algorithm)
2739 {
2740   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2741   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2742   uint32_t SizeVar = Size;
2743 
2744   /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2745   if ((Size % 4U) != 0U)
2746   {
2747     return  HAL_ERROR;
2748   }
2749 
2750   /* Initiate HASH processing in case of start or resumption */
2751   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2752   {
2753     /* Check input parameters */
2754     if ((pInBuffer == NULL) || (Size == 0U))
2755     {
2756       hhash->State = HAL_HASH_STATE_READY;
2757       return  HAL_ERROR;
2758     }
2759 
2760     /* Process Locked */
2761     __HAL_LOCK(hhash);
2762 
2763     /* If resuming the HASH processing */
2764     if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2765     {
2766       /* Change the HASH state */
2767       hhash->State = HAL_HASH_STATE_BUSY;
2768     }
2769     else
2770     {
2771       /* Change the HASH state */
2772       hhash->State = HAL_HASH_STATE_BUSY;
2773 
2774       /* Check if initialization phase has already be performed */
2775       if (hhash->Phase == HAL_HASH_PHASE_READY)
2776       {
2777         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2778         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2779         hhash->HashITCounter = 1;
2780       }
2781       else
2782       {
2783         hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2784       }
2785 
2786       /* Set the phase */
2787       hhash->Phase = HAL_HASH_PHASE_PROCESS;
2788 
2789       /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2790        fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2791        Therefore, first words are manually entered until DINIS raises, or until there
2792        is not more data to enter. */
2793       while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 0U))
2794       {
2795 
2796         /* Write input data 4 bytes at a time */
2797         HASH->DIN = *(uint32_t *)inputaddr;
2798         inputaddr += 4U;
2799         SizeVar -= 4U;
2800       }
2801 
2802       /* If DINIS is still not set or if all the data have been fed, stop here */
2803       if ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) || (SizeVar == 0U))
2804       {
2805         /* Change the HASH state */
2806         hhash->State = HAL_HASH_STATE_READY;
2807 
2808         /* Process Unlock */
2809         __HAL_UNLOCK(hhash);
2810 
2811         /* Return function status */
2812         return HAL_OK;
2813       }
2814 
2815       /* otherwise, carry on in interrupt-mode */
2816       hhash->HashInCount = SizeVar;               /* Counter used to keep track of number of data
2817                                                   to be fed to the Peripheral */
2818       hhash->pHashInBuffPtr = (uint8_t *)inputaddr;       /* Points at data which will be fed to the Peripheral at
2819                                                   the next interruption */
2820       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2821          the information describing where the HASH process is stopped.
2822          These variables are used later on to resume the HASH processing at the
2823          correct location. */
2824 
2825     }
2826 
2827     /* Set multi buffers accumulation flag */
2828     hhash->Accumulation = 1U;
2829 
2830     /* Process Unlock */
2831     __HAL_UNLOCK(hhash);
2832 
2833     /* Enable Data Input interrupt */
2834     __HAL_HASH_ENABLE_IT(HASH_IT_DINI);
2835 
2836     /* Return function status */
2837     return HAL_OK;
2838 
2839   }
2840   else
2841   {
2842     return HAL_BUSY;
2843   }
2844 
2845 }
2846 
2847 
2848 /**
2849   * @brief  Initialize the HASH peripheral, next process pInBuffer then
2850   *         read the computed digest in interruption mode.
2851   * @note   Digest is available in pOutBuffer.
2852   * @param  hhash HASH handle.
2853   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
2854   * @param  Size length of the input buffer in bytes.
2855   * @param  pOutBuffer pointer to the computed digest.
2856   * @param  Algorithm HASH algorithm.
2857   * @retval HAL status
2858   */
HASH_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)2859 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
2860                                 uint8_t *pOutBuffer,
2861                                 uint32_t Algorithm)
2862 {
2863   HAL_HASH_StateTypeDef State_tmp = hhash->State;
2864   __IO uint32_t inputaddr = (uint32_t) pInBuffer;
2865   uint32_t polling_step = 0U;
2866   uint32_t initialization_skipped = 0U;
2867   uint32_t SizeVar = Size;
2868 
2869   /* If State is ready or suspended, start or resume IT-based HASH processing */
2870   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2871   {
2872     /* Check input parameters */
2873     if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
2874     {
2875       hhash->State = HAL_HASH_STATE_READY;
2876       return  HAL_ERROR;
2877     }
2878 
2879     /* Process Locked */
2880     __HAL_LOCK(hhash);
2881 
2882     /* Change the HASH state */
2883     hhash->State = HAL_HASH_STATE_BUSY;
2884 
2885     /* Initialize IT counter */
2886     hhash->HashITCounter = 1;
2887 
2888     /* Check if initialization phase has already be performed */
2889     if (hhash->Phase == HAL_HASH_PHASE_READY)
2890     {
2891       /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2892       MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2893 
2894       /* Configure the number of valid bits in last word of the message */
2895       __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2896 
2897 
2898       hhash->HashInCount = SizeVar;            /* Counter used to keep track of number of data
2899                                                   to be fed to the Peripheral */
2900       hhash->pHashInBuffPtr = pInBuffer;       /* Points at data which will be fed to the Peripheral at
2901                                                   the next interruption */
2902       /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2903          the information describing where the HASH process is stopped.
2904          These variables are used later on to resume the HASH processing at the
2905          correct location. */
2906 
2907       hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2908     }
2909     else if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) && (SizeVar < 4U))
2910     {
2911       if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2912       {
2913         /* It remains data to enter and the Peripheral is ready to trigger DINIE,carry on as usual.
2914         Update HashInCount and pHashInBuffPtr accordingly. */
2915         hhash->HashInCount = SizeVar;
2916         hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
2917         /* Update the configuration of the number of valid bits in last word of the message */
2918         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2919         hhash->pHashOutBuffPtr = pOutBuffer;  /* Points at the computed digest */
2920       }
2921     }
2922     else
2923     {
2924       initialization_skipped = 1; /* info user later on in case of multi-buffer */
2925     }
2926 
2927     /* Set the phase */
2928     hhash->Phase = HAL_HASH_PHASE_PROCESS;
2929 
2930     /* If DINIS is equal to 0 (for example if an incomplete block has been previously
2931       fed to the Peripheral), the DINIE interruption won't be triggered when DINIE is set.
2932       Therefore, first words are manually entered until DINIS raises. */
2933     while ((!(__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))) && (SizeVar > 3U))
2934     {
2935       polling_step = 1U; /* note that some words are entered before enabling the interrupt */
2936 
2937       /* Write input data 4 bytes at a time */
2938       HASH->DIN = *(uint32_t *)inputaddr;
2939       inputaddr += 4U;
2940       SizeVar -= 4U;
2941     }
2942 
2943     if (polling_step == 1U)
2944     {
2945       if (SizeVar == 0U)
2946       {
2947         /* If all the data have been entered at this point, it only remains to
2948          read the digest */
2949         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2950 
2951         /* Start the Digest calculation */
2952         __HAL_HASH_START_DIGEST();
2953         /* Process Unlock */
2954         __HAL_UNLOCK(hhash);
2955 
2956         /* Enable Interrupts */
2957         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2958 
2959         /* Return function status */
2960         return HAL_OK;
2961       }
2962       else if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
2963       {
2964         /* It remains data to enter and the Peripheral is ready to trigger DINIE,
2965            carry on as usual.
2966            Update HashInCount and pHashInBuffPtr accordingly. */
2967         hhash->HashInCount = SizeVar;
2968         hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
2969         /* Update the configuration of the number of valid bits in last word of the message */
2970         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2971         hhash->pHashOutBuffPtr = pOutBuffer;  /* Points at the computed digest */
2972         if (initialization_skipped == 1U)
2973         {
2974           hhash->HashITCounter = 3; /* 'cruise-speed' reached during a previous buffer processing */
2975         }
2976       }
2977       else
2978       {
2979         /* DINIS is not set but it remains a few data to enter (not enough for a full word).
2980            Manually enter the last bytes before enabling DCIE. */
2981         __HAL_HASH_SET_NBVALIDBITS(SizeVar);
2982         HASH->DIN = *(uint32_t *)inputaddr;
2983 
2984         /* Start the Digest calculation */
2985         hhash->pHashOutBuffPtr = pOutBuffer;     /* Points at the computed digest */
2986         __HAL_HASH_START_DIGEST();
2987         /* Process Unlock */
2988         __HAL_UNLOCK(hhash);
2989 
2990         /* Enable Interrupts */
2991         __HAL_HASH_ENABLE_IT(HASH_IT_DCI);
2992 
2993         /* Return function status */
2994         return HAL_OK;
2995       }
2996     } /*  if (polling_step == 1) */
2997 
2998 
2999     /* Process Unlock */
3000     __HAL_UNLOCK(hhash);
3001 
3002     /* Enable Interrupts */
3003     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
3004 
3005     /* Return function status */
3006     return HAL_OK;
3007   }
3008   else
3009   {
3010     return HAL_BUSY;
3011   }
3012 
3013 }
3014 
3015 
3016 /**
3017   * @brief  Initialize the HASH peripheral then initiate a DMA transfer
3018   *         to feed the input buffer to the Peripheral.
3019   * @note   If MDMAT bit is set before calling this function (multi-buffer
3020   *          HASH processing case), the input buffer size (in bytes) must be
3021   *          a multiple of 4 otherwise, the HASH digest computation is corrupted.
3022   *          For the processing of the last buffer of the thread, MDMAT bit must
3023   *          be reset and the buffer length (in bytes) doesn't have to be a
3024   *          multiple of 4.
3025   * @param  hhash HASH handle.
3026   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3027   * @param  Size length of the input buffer in bytes.
3028   * @param  Algorithm HASH algorithm.
3029   * @retval HAL status
3030   */
HASH_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint32_t Algorithm)3031 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
3032                                  uint32_t Algorithm)
3033 {
3034   uint32_t inputaddr;
3035   uint32_t inputSize;
3036   HAL_StatusTypeDef status ;
3037   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3038 
3039 
3040   /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
3041      (case of multi-buffer HASH processing) */
3042   assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
3043 
3044   /* If State is ready or suspended, start or resume polling-based HASH processing */
3045   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3046   {
3047     /* Check input parameters */
3048     if ((pInBuffer == NULL) || (Size == 0U) ||
3049         /* Check phase coherency. Phase must be
3050            either READY (fresh start)
3051            or PROCESS (multi-buffer HASH management) */
3052         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
3053     {
3054       hhash->State = HAL_HASH_STATE_READY;
3055       return  HAL_ERROR;
3056     }
3057 
3058 
3059     /* Process Locked */
3060     __HAL_LOCK(hhash);
3061 
3062     /* If not a resumption case */
3063     if (hhash->State == HAL_HASH_STATE_READY)
3064     {
3065       /* Change the HASH state */
3066       hhash->State = HAL_HASH_STATE_BUSY;
3067 
3068       /* Check if initialization phase has already been performed.
3069          If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
3070          API is processing a new input data message in case of multi-buffer HASH
3071          computation. */
3072       if (hhash->Phase == HAL_HASH_PHASE_READY)
3073       {
3074         /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
3075         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT, Algorithm | HASH_CR_INIT);
3076 
3077         /* Set the phase */
3078         hhash->Phase = HAL_HASH_PHASE_PROCESS;
3079       }
3080 
3081       /* Configure the Number of valid bits in last word of the message */
3082       __HAL_HASH_SET_NBVALIDBITS(Size);
3083 
3084       inputaddr = (uint32_t)pInBuffer;     /* DMA transfer start address   */
3085       inputSize = Size;                    /* DMA transfer size (in bytes) */
3086 
3087       /* In case of suspension request, save the starting parameters */
3088       hhash->pHashInBuffPtr =  pInBuffer;  /* DMA transfer start address   */
3089       hhash->HashInCount = Size;           /* DMA transfer size (in bytes) */
3090 
3091     }
3092     /* If resumption case */
3093     else
3094     {
3095       /* Change the HASH state */
3096       hhash->State = HAL_HASH_STATE_BUSY;
3097 
3098       /* Resumption case, inputaddr and inputSize are not set to the API input parameters
3099          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3100          processing was suspended */
3101       inputaddr = (uint32_t)hhash->pHashInBuffPtr;  /* DMA transfer start address   */
3102       inputSize = hhash->HashInCount;               /* DMA transfer size (in bytes) */
3103 
3104     }
3105 
3106     /* Set the HASH DMA transfer complete callback */
3107     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3108     /* Set the DMA error callback */
3109     hhash->hdmain->XferErrorCallback = HASH_DMAError;
3110 
3111     /* Store number of words already pushed to manage proper DMA processing suspension */
3112     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3113 
3114     /* Enable the DMA In DMA stream */
3115     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, \
3116                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) : \
3117                                (inputSize / 4U)));
3118 
3119     /* Enable DMA requests */
3120     SET_BIT(HASH->CR, HASH_CR_DMAE);
3121 
3122     /* Process Unlock */
3123     __HAL_UNLOCK(hhash);
3124 
3125     /* Return function status */
3126     if (status != HAL_OK)
3127     {
3128       /* Update HASH state machine to error */
3129       hhash->State = HAL_HASH_STATE_ERROR;
3130     }
3131 
3132     return status;
3133   }
3134   else
3135   {
3136     return HAL_BUSY;
3137   }
3138 }
3139 
3140 /**
3141   * @brief  Return the computed digest.
3142   * @note   The API waits for DCIS to be set then reads the computed digest.
3143   * @param  hhash HASH handle.
3144   * @param  pOutBuffer pointer to the computed digest.
3145   * @param  Timeout Timeout value.
3146   * @retval HAL status
3147   */
HASH_Finish(HASH_HandleTypeDef * hhash,uint8_t * pOutBuffer,uint32_t Timeout)3148 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t *pOutBuffer, uint32_t Timeout)
3149 {
3150 
3151   if (hhash->State == HAL_HASH_STATE_READY)
3152   {
3153     /* Check parameter */
3154     if (pOutBuffer == NULL)
3155     {
3156       return  HAL_ERROR;
3157     }
3158 
3159     /* Process Locked */
3160     __HAL_LOCK(hhash);
3161 
3162     /* Change the HASH state to busy */
3163     hhash->State = HAL_HASH_STATE_BUSY;
3164 
3165     /* Wait for DCIS flag to be set */
3166     if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
3167     {
3168       return HAL_TIMEOUT;
3169     }
3170 
3171     /* Read the message digest */
3172     HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
3173 
3174     /* Change the HASH state to ready */
3175     hhash->State = HAL_HASH_STATE_READY;
3176 
3177     /* Reset HASH state machine */
3178     hhash->Phase = HAL_HASH_PHASE_READY;
3179 
3180     /* Process UnLock */
3181     __HAL_UNLOCK(hhash);
3182 
3183     /* Return function status */
3184     return HAL_OK;
3185 
3186   }
3187   else
3188   {
3189     return HAL_BUSY;
3190   }
3191 
3192 }
3193 
3194 
3195 /**
3196   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3197   *         read the computed digest.
3198   * @note   Digest is available in pOutBuffer.
3199   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3200   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3201   * @param  hhash HASH handle.
3202   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3203   * @param  Size length of the input buffer in bytes.
3204   * @param  pOutBuffer pointer to the computed digest.
3205   * @param  Timeout Timeout value.
3206   * @param  Algorithm HASH algorithm.
3207   * @retval HAL status
3208   */
HMAC_Start(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Timeout,uint32_t Algorithm)3209 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
3210                              uint8_t *pOutBuffer,
3211                              uint32_t Timeout, uint32_t Algorithm)
3212 {
3213   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3214 
3215   /* If State is ready or suspended, start or resume polling-based HASH processing */
3216   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3217   {
3218     /* Check input parameters */
3219     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3220         || (pOutBuffer == NULL))
3221     {
3222       hhash->State = HAL_HASH_STATE_READY;
3223       return  HAL_ERROR;
3224     }
3225 
3226     /* Process Locked */
3227     __HAL_LOCK(hhash);
3228 
3229     /* Change the HASH state */
3230     hhash->State = HAL_HASH_STATE_BUSY;
3231 
3232     /* Check if initialization phase has already be performed */
3233     if (hhash->Phase == HAL_HASH_PHASE_READY)
3234     {
3235       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3236       if (hhash->Init.KeySize > 64U)
3237       {
3238         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3239                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3240       }
3241       else
3242       {
3243         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3244                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3245       }
3246       /* Set the phase to Step 1 */
3247       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3248       /* Resort to hhash internal fields to feed the Peripheral.
3249          Parameters will be updated in case of suspension to contain the proper
3250          information at resumption time. */
3251       hhash->pHashOutBuffPtr  = pOutBuffer;            /* Output digest address    */
3252       hhash->pHashInBuffPtr   = pInBuffer;             /* Input data address, HMAC_Processing input
3253                                                           parameter for Step 2     */
3254       hhash->HashInCount      = Size;                  /* Input data size, HMAC_Processing input
3255                                                           parameter for Step 2        */
3256       hhash->HashBuffSize     = Size;                  /* Store the input buffer size for the whole HMAC process*/
3257       hhash->pHashKeyBuffPtr  = hhash->Init.pKey;      /* Key address, HMAC_Processing input parameter for Step
3258                                                           1 and Step 3 */
3259       hhash->HashKeyCount     = hhash->Init.KeySize;   /* Key size, HMAC_Processing input parameter for Step 1
3260                                                           and Step 3    */
3261     }
3262 
3263     /* Carry out HMAC processing */
3264     return HMAC_Processing(hhash, Timeout);
3265 
3266   }
3267   else
3268   {
3269     return HAL_BUSY;
3270   }
3271 }
3272 
3273 
3274 /**
3275   * @brief  Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
3276   *         read the computed digest in interruption mode.
3277   * @note   Digest is available in pOutBuffer.
3278   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3279   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3280   * @param  hhash HASH handle.
3281   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3282   * @param  Size length of the input buffer in bytes.
3283   * @param  pOutBuffer pointer to the computed digest.
3284   * @param  Algorithm HASH algorithm.
3285   * @retval HAL status
3286   */
HMAC_Start_IT(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint8_t * pOutBuffer,uint32_t Algorithm)3287 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
3288                                 uint8_t *pOutBuffer,
3289                                 uint32_t Algorithm)
3290 {
3291   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3292 
3293   /* If State is ready or suspended, start or resume IT-based HASH processing */
3294   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3295   {
3296     /* Check input parameters */
3297     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U)
3298         || (pOutBuffer == NULL))
3299     {
3300       hhash->State = HAL_HASH_STATE_READY;
3301       return  HAL_ERROR;
3302     }
3303 
3304     /* Process Locked */
3305     __HAL_LOCK(hhash);
3306 
3307     /* Change the HASH state */
3308     hhash->State = HAL_HASH_STATE_BUSY;
3309 
3310     /* Initialize IT counter */
3311     hhash->HashITCounter = 1;
3312 
3313     /* Check if initialization phase has already be performed */
3314     if (hhash->Phase == HAL_HASH_PHASE_READY)
3315     {
3316       /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
3317       if (hhash->Init.KeySize > 64U)
3318       {
3319         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3320                    Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3321       }
3322       else
3323       {
3324         MODIFY_REG(HASH->CR, HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3325                    Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3326       }
3327 
3328       /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
3329          to feed the Peripheral whatever the HMAC step.
3330          Lines below are set to start HMAC Step 1 processing where key is entered first. */
3331       hhash->HashInCount     = hhash->Init.KeySize; /* Key size                      */
3332       hhash->pHashInBuffPtr  = hhash->Init.pKey ;   /* Key address                   */
3333 
3334       /* Store input and output parameters in handle fields to manage steps transition
3335          or possible HMAC suspension/resumption */
3336       hhash->pHashKeyBuffPtr = hhash->Init.pKey;    /* Key address                   */
3337       hhash->pHashMsgBuffPtr = pInBuffer;           /* Input message address         */
3338       hhash->HashBuffSize    = Size;                /* Input message size (in bytes) */
3339       hhash->pHashOutBuffPtr = pOutBuffer;          /* Output digest address         */
3340 
3341       /* Configure the number of valid bits in last word of the key */
3342       __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3343 
3344       /* Set the phase to Step 1 */
3345       hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3346     }
3347     else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
3348     {
3349       /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
3350 
3351     }
3352     else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3353     {
3354       /* Restart IT-based HASH processing after Step 2 suspension */
3355 
3356     }
3357     else
3358     {
3359       /* Error report as phase incorrect */
3360       /* Process Unlock */
3361       __HAL_UNLOCK(hhash);
3362       hhash->State = HAL_HASH_STATE_READY;
3363       return HAL_ERROR;
3364     }
3365 
3366     /* Process Unlock */
3367     __HAL_UNLOCK(hhash);
3368 
3369     /* Enable Interrupts */
3370     __HAL_HASH_ENABLE_IT(HASH_IT_DINI | HASH_IT_DCI);
3371 
3372     /* Return function status */
3373     return HAL_OK;
3374   }
3375   else
3376   {
3377     return HAL_BUSY;
3378   }
3379 
3380 }
3381 
3382 
3383 /**
3384   * @brief  Initialize the HASH peripheral in HMAC mode then initiate the required
3385   *         DMA transfers to feed the key and the input buffer to the Peripheral.
3386   * @note   Same key is used for the inner and the outer hash functions; pointer to key and
3387   *         key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
3388   * @note   In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
3389   *         be a multiple of 4 otherwise, the HASH digest computation is corrupted.
3390   *         Only the length of the last buffer of the thread doesn't have to be a
3391   *         multiple of 4.
3392   * @param  hhash HASH handle.
3393   * @param  pInBuffer pointer to the input buffer (buffer to be hashed).
3394   * @param  Size length of the input buffer in bytes.
3395   * @param  Algorithm HASH algorithm.
3396   * @retval HAL status
3397   */
HMAC_Start_DMA(HASH_HandleTypeDef * hhash,const uint8_t * const pInBuffer,uint32_t Size,uint32_t Algorithm)3398 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, const uint8_t *const pInBuffer, uint32_t Size,
3399                                  uint32_t Algorithm)
3400 {
3401   uint32_t inputaddr;
3402   uint32_t inputSize;
3403   HAL_StatusTypeDef status ;
3404   HAL_HASH_StateTypeDef State_tmp = hhash->State;
3405   /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
3406      is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
3407   assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size));
3408   /* If State is ready or suspended, start or resume DMA-based HASH processing */
3409   if ((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
3410   {
3411     /* Check input parameters */
3412     if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) ||
3413         /* Check phase coherency. Phase must be
3414             either READY (fresh start)
3415             or one of HMAC PROCESS steps (multi-buffer HASH management) */
3416         ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
3417     {
3418       hhash->State = HAL_HASH_STATE_READY;
3419       return  HAL_ERROR;
3420     }
3421 
3422 
3423     /* Process Locked */
3424     __HAL_LOCK(hhash);
3425 
3426     /* If not a case of resumption after suspension */
3427     if (hhash->State == HAL_HASH_STATE_READY)
3428     {
3429       /* Check whether or not initialization phase has already be performed */
3430       if (hhash->Phase == HAL_HASH_PHASE_READY)
3431       {
3432         /* Change the HASH state */
3433         hhash->State = HAL_HASH_STATE_BUSY;
3434         /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
3435            At the same time, ensure MDMAT bit is cleared. */
3436         if (hhash->Init.KeySize > 64U)
3437         {
3438           MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3439                      Algorithm | HASH_ALGOMODE_HMAC | HASH_HMAC_KEYTYPE_LONGKEY | HASH_CR_INIT);
3440         }
3441         else
3442         {
3443           MODIFY_REG(HASH->CR, HASH_CR_MDMAT | HASH_CR_LKEY | HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_INIT,
3444                      Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
3445         }
3446         /* Store input aparameters in handle fields to manage steps transition
3447            or possible HMAC suspension/resumption */
3448         hhash->HashInCount = hhash->Init.KeySize;   /* Initial size for first DMA transfer (key size)      */
3449         hhash->pHashKeyBuffPtr = hhash->Init.pKey;  /* Key address                                         */
3450         hhash->pHashInBuffPtr  = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
3451         hhash->pHashMsgBuffPtr = pInBuffer;         /* Input data address                                  */
3452         hhash->HashBuffSize = Size;                 /* input data size (in bytes)                          */
3453 
3454         /* Set DMA input parameters */
3455         inputaddr = (uint32_t)(hhash->Init.pKey);   /* Address passed to DMA (start by entering Key message) */
3456         inputSize = hhash->Init.KeySize;            /* Size for first DMA transfer (in bytes) */
3457 
3458         /* Configure the number of valid bits in last word of the key */
3459         __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
3460 
3461         /* Set the phase to Step 1 */
3462         hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
3463 
3464       }
3465       else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
3466       {
3467         /* Process a new input data message in case of multi-buffer HMAC processing
3468           (this is not a resumption case) */
3469 
3470         /* Change the HASH state */
3471         hhash->State = HAL_HASH_STATE_BUSY;
3472 
3473         /* Save input parameters to be able to manage possible suspension/resumption */
3474         hhash->HashInCount = Size;                /* Input message address       */
3475         hhash->pHashInBuffPtr = pInBuffer;        /* Input message size in bytes */
3476 
3477         /* Set DMA input parameters */
3478         inputaddr = (uint32_t)pInBuffer;           /* Input message address       */
3479         inputSize = Size;                          /* Input message size in bytes */
3480 
3481         if (hhash->DigestCalculationDisable == RESET)
3482         {
3483           /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
3484           __HAL_HASH_RESET_MDMAT();
3485           __HAL_HASH_SET_NBVALIDBITS(inputSize);
3486         }
3487       }
3488       else
3489       {
3490         /* Phase not aligned with handle READY state */
3491         __HAL_UNLOCK(hhash);
3492         /* Return function status */
3493         return HAL_ERROR;
3494       }
3495     }
3496     else
3497     {
3498       /* Resumption case (phase may be Step 1, 2 or 3) */
3499 
3500       /* Change the HASH state */
3501       hhash->State = HAL_HASH_STATE_BUSY;
3502 
3503       /* Set DMA input parameters at resumption location;
3504          inputaddr and inputSize are not set to the API input parameters
3505          but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3506          processing was suspended. */
3507       inputaddr = (uint32_t)(hhash->pHashInBuffPtr);  /* Input message address       */
3508       inputSize = hhash->HashInCount;                 /* Input message size in bytes */
3509     }
3510 
3511 
3512     /* Set the HASH DMA transfer complete callback */
3513     hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3514     /* Set the DMA error callback */
3515     hhash->hdmain->XferErrorCallback = HASH_DMAError;
3516 
3517     /* Store number of words already pushed to manage proper DMA processing suspension */
3518     hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3519 
3520     /* Enable the DMA In DMA stream */
3521     status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN,  \
3522                               (((inputSize % 4U) != 0U) ? ((inputSize + (4U - (inputSize % 4U))) / 4U) \
3523                                : (inputSize / 4U)));
3524 
3525     /* Enable DMA requests */
3526     SET_BIT(HASH->CR, HASH_CR_DMAE);
3527 
3528     /* Process Unlocked */
3529     __HAL_UNLOCK(hhash);
3530 
3531     /* Return function status */
3532     if (status != HAL_OK)
3533     {
3534       /* Update HASH state machine to error */
3535       hhash->State = HAL_HASH_STATE_ERROR;
3536     }
3537 
3538     /* Return function status */
3539     return status;
3540   }
3541   else
3542   {
3543     return HAL_BUSY;
3544   }
3545 }
3546 /**
3547   * @}
3548   */
3549 
3550 #endif /* HAL_HASH_MODULE_ENABLED */
3551 
3552 /**
3553   * @}
3554   */
3555 #endif /*  HASH*/
3556 /**
3557   * @}
3558   */
3559 
3560