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