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