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