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