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