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