Updated and Validated
[betaflight.git] / lib / main / STM32F7 / Drivers / STM32F7xx_HAL_Driver / Src / stm32f7xx_hal_hash.c
blob69a86070d6ba2c96b2824ebec7b3c3ab2445bb2d
1 /**
2 ******************************************************************************
3 * @file stm32f7xx_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
15 @verbatim
16 ===============================================================================
17 ##### How to use this driver #####
18 ===============================================================================
19 [..]
20 The HASH HAL driver can be used as follows:
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()
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.
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.
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 IP, the digest computation can start.
62 (#)Multi-buffer processing is possible in polling and DMA mode.
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_Start() to enter the last one and retrieve as
66 well the computed digest.
68 (##) In DMA mode, multi-buffer HASH and HMAC processing are possible.
69 (+++) HASH processing: once initialization is done, MDMAT bit must be set thru __HAL_HASH_SET_MDMAT() macro.
70 From that point, each buffer can be fed to the IP thru HAL_HASH_xxx_Start_DMA() API.
71 Before entering the last buffer, reset the MDMAT bit with __HAL_HASH_RESET_MDMAT()
72 macro then wrap-up the HASH processing in feeding the last input buffer thru the
73 same API HAL_HASH_xxx_Start_DMA(). The digest can then be retrieved with a call to
74 API HAL_HASH_xxx_Finish().
75 (+++) HMAC processing (requires to resort to extended functions):
76 after initialization, the key and the first input buffer are entered
77 in the IP with the API HAL_HMACEx_xxx_Step1_2_DMA(). This carries out HMAC step 1 and
78 starts step 2.
79 The following buffers are next entered with the API HAL_HMACEx_xxx_Step2_DMA(). At this
80 point, the HMAC processing is still carrying out step 2.
81 Then, step 2 for the last input buffer and step 3 are carried out by a single call
82 to HAL_HMACEx_xxx_Step2_3_DMA().
84 The digest can finally be retrieved with a call to API HAL_HASH_xxx_Finish().
87 (#)Context swapping.
88 (##) Two APIs are available to suspend HASH or HMAC processing:
89 (+++) HAL_HASH_SwFeed_ProcessSuspend() when data are entered by software (polling or IT mode),
90 (+++) HAL_HASH_DMAFeed_ProcessSuspend() when data are entered by DMA.
92 (##) When HASH or HMAC processing is suspended, HAL_HASH_ContextSaving() allows
93 to save in memory the IP context. This context can be restored afterwards
94 to resume the HASH processing thanks to HAL_HASH_ContextRestoring().
96 (##) Once the HASH IP has been restored to the same configuration as that at suspension
97 time, processing can be restarted with the same API call (same API, same handle,
98 same parameters) as done before the suspension. Relevant parameters to restart at
99 the proper location are internally saved in the HASH handle.
101 (#)Call HAL_HASH_DeInit() to deinitialize the HASH peripheral.
103 *** Callback registration ***
104 ===================================
105 [..]
106 (#) The compilation define USE_HAL_HASH_REGISTER_CALLBACKS when set to 1
107 allows the user to configure dynamically the driver callbacks.
108 Use function @ref HAL_HASH_RegisterCallback() to register a user callback.
110 (#) Function @ref HAL_HASH_RegisterCallback() allows to register following callbacks:
111 (+) InCpltCallback : callback for input completion.
112 (+) DgstCpltCallback : callback for digest computation completion.
113 (+) ErrorCallback : callback for error.
114 (+) MspInitCallback : HASH MspInit.
115 (+) MspDeInitCallback : HASH MspDeInit.
116 This function takes as parameters the HAL peripheral handle, the Callback ID
117 and a pointer to the user callback function.
119 (#) Use function @ref HAL_HASH_UnRegisterCallback() to reset a callback to the default
120 weak (surcharged) function.
121 @ref HAL_HASH_UnRegisterCallback() takes as parameters the HAL peripheral handle,
122 and the Callback ID.
123 This function allows to reset following callbacks:
124 (+) InCpltCallback : callback for input completion.
125 (+) DgstCpltCallback : callback for digest computation completion.
126 (+) ErrorCallback : callback for error.
127 (+) MspInitCallback : HASH MspInit.
128 (+) MspDeInitCallback : HASH MspDeInit.
130 (#) By default, after the @ref HAL_HASH_Init and if the state is HAL_HASH_STATE_RESET
131 all callbacks are reset to the corresponding legacy weak (surcharged) functions:
132 examples @ref HAL_HASH_InCpltCallback(), @ref HAL_HASH_DgstCpltCallback()
133 Exception done for MspInit and MspDeInit callbacks that are respectively
134 reset to the legacy weak (surcharged) functions in the @ref HAL_HASH_Init
135 and @ref HAL_HASH_DeInit only when these callbacks are null (not registered beforehand)
136 If not, MspInit or MspDeInit are not null, the @ref HAL_HASH_Init and @ref HAL_HASH_DeInit
137 keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
139 Callbacks can be registered/unregistered in READY state only.
140 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
141 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
142 during the Init/DeInit.
143 In that case first register the MspInit/MspDeInit user callbacks
144 using @ref HAL_HASH_RegisterCallback before calling @ref HAL_HASH_DeInit
145 or @ref HAL_HASH_Init function.
147 When The compilation define USE_HAL_HASH_REGISTER_CALLBACKS is set to 0 or
148 not defined, the callback registering feature is not available
149 and weak (surcharged) callbacks are used.
151 @endverbatim
152 ******************************************************************************
153 * @attention
155 * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
156 * All rights reserved.</center></h2>
158 * This software component is licensed by ST under BSD 3-Clause license,
159 * the "License"; You may not use this file except in compliance with the
160 * License. You may obtain a copy of the License at:
161 * opensource.org/licenses/BSD-3-Clause
163 ******************************************************************************
166 /* Includes ------------------------------------------------------------------*/
167 #include "stm32f7xx_hal.h"
170 /** @addtogroup STM32F7xx_HAL_Driver
171 * @{
173 #if defined (HASH)
175 /** @defgroup HASH HASH
176 * @brief HASH HAL module driver.
177 * @{
180 #ifdef HAL_HASH_MODULE_ENABLED
182 /* Private typedef -----------------------------------------------------------*/
183 /* Private define ------------------------------------------------------------*/
184 /** @defgroup HASH_Private_Constants HASH Private Constants
185 * @{
188 /** @defgroup HASH_Digest_Calculation_Status HASH Digest Calculation Status
189 * @{
191 #define HASH_DIGEST_CALCULATION_NOT_STARTED ((uint32_t)0x00000000U) /*!< DCAL not set after input data written in DIN register */
192 #define HASH_DIGEST_CALCULATION_STARTED ((uint32_t)0x00000001U) /*!< DCAL set after input data written in DIN register */
194 * @}
197 /** @defgroup HASH_Number_Of_CSR_Registers HASH Number of Context Swap Registers
198 * @{
200 #define HASH_NUMBER_OF_CSR_REGISTERS 54U /*!< Number of Context Swap Registers */
202 * @}
205 /** @defgroup HASH_TimeOut_Value HASH TimeOut Value
206 * @{
208 #define HASH_TIMEOUTVALUE 1000U /*!< Time-out value */
210 * @}
213 /** @defgroup HASH_DMA_Suspension_Words_Limit HASH DMA suspension words limit
214 * @{
216 #define HASH_DMA_SUSPENSION_WORDS_LIMIT 20U /*!< Number of words below which DMA suspension is aborted */
218 * @}
222 * @}
225 /* Private macro -------------------------------------------------------------*/
226 /* Private variables ---------------------------------------------------------*/
227 /* Private function prototypes -----------------------------------------------*/
228 /** @defgroup HASH_Private_Functions HASH Private Functions
229 * @{
231 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma);
232 static void HASH_DMAError(DMA_HandleTypeDef *hdma);
233 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size);
234 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, uint32_t Timeout);
235 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size);
236 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash);
237 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash);
238 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout);
240 * @}
243 /** @defgroup HASH_Exported_Functions HASH Exported Functions
244 * @{
247 /** @defgroup HASH_Exported_Functions_Group1 Initialization and de-initialization functions
248 * @brief Initialization, configuration and call-back functions.
250 @verbatim
251 ===============================================================================
252 ##### Initialization and de-initialization functions #####
253 ===============================================================================
254 [..] This section provides functions allowing to:
255 (+) Initialize the HASH according to the specified parameters
256 in the HASH_InitTypeDef and create the associated handle
257 (+) DeInitialize the HASH peripheral
258 (+) Initialize the HASH MCU Specific Package (MSP)
259 (+) DeInitialize the HASH MSP
261 [..] This section provides as well call back functions definitions for user
262 code to manage:
263 (+) Input data transfer to IP completion
264 (+) Calculated digest retrieval completion
265 (+) Error management
269 @endverbatim
270 * @{
274 * @brief Initialize the HASH according to the specified parameters in the
275 HASH_HandleTypeDef and create the associated handle.
276 * @note Only MDMAT and DATATYPE bits of HASH IP are set by HAL_HASH_Init(),
277 * other configuration bits are set by HASH or HMAC processing APIs.
278 * @note MDMAT bit is systematically reset by HAL_HASH_Init(). To set it for
279 * multi-buffer HASH processing, user needs to resort to
280 * __HAL_HASH_SET_MDMAT() macro. For HMAC multi-buffer processing, the
281 * relevant APIs manage themselves the MDMAT bit.
282 * @param hhash: HASH handle
283 * @retval HAL status
285 HAL_StatusTypeDef HAL_HASH_Init(HASH_HandleTypeDef *hhash)
287 /* Check the parameters */
288 assert_param(IS_HASH_DATATYPE(hhash->Init.DataType));
290 /* Check the hash handle allocation */
291 if(hhash == NULL)
293 return HAL_ERROR;
296 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
297 if (hhash->State == HAL_HASH_STATE_RESET)
299 /* Allocate lock resource and initialize it */
300 hhash->Lock = HAL_UNLOCKED;
302 /* Reset Callback pointers in HAL_HASH_STATE_RESET only */
303 hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */
304 hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation completion callback */
305 hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */
306 if(hhash->MspInitCallback == NULL)
308 hhash->MspInitCallback = HAL_HASH_MspInit;
311 /* Init the low level hardware */
312 hhash->MspInitCallback(hhash);
314 #else
315 if(hhash->State == HAL_HASH_STATE_RESET)
317 /* Allocate lock resource and initialize it */
318 hhash->Lock = HAL_UNLOCKED;
320 /* Init the low level hardware */
321 HAL_HASH_MspInit(hhash);
323 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
325 /* Change the HASH state */
326 hhash->State = HAL_HASH_STATE_BUSY;
328 /* Reset HashInCount, HashITCounter, HashBuffSize and NbWordsAlreadyPushed */
329 hhash->HashInCount = 0;
330 hhash->HashBuffSize = 0;
331 hhash->HashITCounter = 0;
332 hhash->NbWordsAlreadyPushed = 0;
333 /* Reset digest calculation bridle (MDMAT bit control) */
334 hhash->DigestCalculationDisable = RESET;
335 /* Set phase to READY */
336 hhash->Phase = HAL_HASH_PHASE_READY;
338 /* Set the data type bit */
339 MODIFY_REG(HASH->CR, HASH_CR_DATATYPE, hhash->Init.DataType);
340 /* Reset MDMAT bit */
341 __HAL_HASH_RESET_MDMAT();
342 /* Reset HASH handle status */
343 hhash->Status = HAL_OK;
345 /* Set the HASH state to Ready */
346 hhash->State = HAL_HASH_STATE_READY;
348 /* Initialise the error code */
349 hhash->ErrorCode = HAL_HASH_ERROR_NONE;
351 /* Return function status */
352 return HAL_OK;
356 * @brief DeInitialize the HASH peripheral.
357 * @param hhash: HASH handle.
358 * @retval HAL status
360 HAL_StatusTypeDef HAL_HASH_DeInit(HASH_HandleTypeDef *hhash)
362 /* Check the HASH handle allocation */
363 if(hhash == NULL)
365 return HAL_ERROR;
368 /* Change the HASH state */
369 hhash->State = HAL_HASH_STATE_BUSY;
371 /* Set the default HASH phase */
372 hhash->Phase = HAL_HASH_PHASE_READY;
374 /* Reset HashInCount, HashITCounter and HashBuffSize */
375 hhash->HashInCount = 0;
376 hhash->HashBuffSize = 0;
377 hhash->HashITCounter = 0;
378 /* Reset digest calculation bridle (MDMAT bit control) */
379 hhash->DigestCalculationDisable = RESET;
381 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
382 if(hhash->MspDeInitCallback == NULL)
384 hhash->MspDeInitCallback = HAL_HASH_MspDeInit;
387 /* DeInit the low level hardware */
388 hhash->MspDeInitCallback(hhash);
389 #else
390 /* DeInit the low level hardware: CLOCK, NVIC */
391 HAL_HASH_MspDeInit(hhash);
392 #endif /* (USE_HAL_HASH_REGISTER_CALLBACKS) */
395 /* Reset HASH handle status */
396 hhash->Status = HAL_OK;
398 /* Set the HASH state to Ready */
399 hhash->State = HAL_HASH_STATE_RESET;
401 /* Initialise the error code */
402 hhash->ErrorCode = HAL_HASH_ERROR_NONE;
404 /* Return function status */
405 return HAL_OK;
409 * @brief Initialize the HASH MSP.
410 * @param hhash: HASH handle.
411 * @retval None
413 __weak void HAL_HASH_MspInit(HASH_HandleTypeDef *hhash)
415 /* Prevent unused argument(s) compilation warning */
416 UNUSED(hhash);
418 /* NOTE : This function should not be modified; when the callback is needed,
419 HAL_HASH_MspInit() can be implemented in the user file.
424 * @brief DeInitialize the HASH MSP.
425 * @param hhash: HASH handle.
426 * @retval None
428 __weak void HAL_HASH_MspDeInit(HASH_HandleTypeDef *hhash)
430 /* Prevent unused argument(s) compilation warning */
431 UNUSED(hhash);
433 /* NOTE : This function should not be modified; when the callback is needed,
434 HAL_HASH_MspDeInit() can be implemented in the user file.
439 * @brief Input data transfer complete call back.
440 * @note HAL_HASH_InCpltCallback() is called when the complete input message
441 * has been fed to the IP. This API is invoked only when input data are
442 * entered under interruption or thru DMA.
443 * @note In case of HASH or HMAC multi-buffer DMA feeding case (MDMAT bit set),
444 * HAL_HASH_InCpltCallback() is called at the end of each buffer feeding
445 * to the IP.
446 * @param hhash: HASH handle.
447 * @retval None
449 __weak void HAL_HASH_InCpltCallback(HASH_HandleTypeDef *hhash)
451 /* Prevent unused argument(s) compilation warning */
452 UNUSED(hhash);
454 /* NOTE : This function should not be modified; when the callback is needed,
455 HAL_HASH_InCpltCallback() can be implemented in the user file.
460 * @brief Digest computation complete call back.
461 * @note HAL_HASH_DgstCpltCallback() is used under interruption, is not
462 * relevant with DMA.
463 * @param hhash: HASH handle.
464 * @retval None
466 __weak void HAL_HASH_DgstCpltCallback(HASH_HandleTypeDef *hhash)
468 /* Prevent unused argument(s) compilation warning */
469 UNUSED(hhash);
471 /* NOTE : This function should not be modified; when the callback is needed,
472 HAL_HASH_DgstCpltCallback() can be implemented in the user file.
477 * @brief Error callback.
478 * @note Code user can resort to hhash->Status (HAL_ERROR, HAL_TIMEOUT,...)
479 * to retrieve the error type.
480 * @param hhash: HASH handle.
481 * @retval None
483 __weak void HAL_HASH_ErrorCallback(HASH_HandleTypeDef *hhash)
485 /* Prevent unused argument(s) compilation warning */
486 UNUSED(hhash);
488 /* NOTE : This function should not be modified; when the callback is needed,
489 HAL_HASH_ErrorCallback() can be implemented in the user file.
493 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
495 * @brief Register a User HASH Callback
496 * To be used instead of the weak (surcharged) predefined callback
497 * @param hhash HASH handle
498 * @param CallbackID ID of the callback to be registered
499 * This parameter can be one of the following values:
500 * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
501 * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
502 * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
503 * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
504 * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
505 * @param pCallback pointer to the Callback function
506 * @retval status
508 HAL_StatusTypeDef HAL_HASH_RegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID, pHASH_CallbackTypeDef pCallback)
510 HAL_StatusTypeDef status = HAL_OK;
512 if(pCallback == NULL)
514 /* Update the error code */
515 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
516 return HAL_ERROR;
518 /* Process locked */
519 __HAL_LOCK(hhash);
521 if(HAL_HASH_STATE_READY == hhash->State)
523 switch (CallbackID)
525 case HAL_HASH_INPUTCPLT_CB_ID :
526 hhash->InCpltCallback = pCallback;
527 break;
529 case HAL_HASH_DGSTCPLT_CB_ID :
530 hhash->DgstCpltCallback = pCallback;
531 break;
533 case HAL_HASH_ERROR_CB_ID :
534 hhash->ErrorCallback = pCallback;
535 break;
537 case HAL_HASH_MSPINIT_CB_ID :
538 hhash->MspInitCallback = pCallback;
539 break;
541 case HAL_HASH_MSPDEINIT_CB_ID :
542 hhash->MspDeInitCallback = pCallback;
543 break;
545 default :
546 /* Update the error code */
547 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
548 /* update return status */
549 status = HAL_ERROR;
550 break;
553 else if(HAL_HASH_STATE_RESET == hhash->State)
555 switch (CallbackID)
557 case HAL_HASH_MSPINIT_CB_ID :
558 hhash->MspInitCallback = pCallback;
559 break;
561 case HAL_HASH_MSPDEINIT_CB_ID :
562 hhash->MspDeInitCallback = pCallback;
563 break;
565 default :
566 /* Update the error code */
567 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
568 /* update return status */
569 status = HAL_ERROR;
570 break;
573 else
575 /* Update the error code */
576 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
577 /* update return status */
578 status = HAL_ERROR;
581 /* Release Lock */
582 __HAL_UNLOCK(hhash);
583 return status;
587 * @brief Unregister a HASH Callback
588 * HASH Callback is redirected to the weak (surcharged) predefined callback
589 * @param hhash HASH handle
590 * @param CallbackID ID of the callback to be unregistered
591 * This parameter can be one of the following values:
592 * @arg @ref HAL_HASH_INPUTCPLT_CB_ID HASH input completion Callback ID
593 * @arg @ref HAL_HASH_DGSTCPLT_CB_ID HASH digest computation completion Callback ID
594 * @arg @ref HAL_HASH_ERROR_CB_ID HASH error Callback ID
595 * @arg @ref HAL_HASH_MSPINIT_CB_ID HASH MspInit callback ID
596 * @arg @ref HAL_HASH_MSPDEINIT_CB_ID HASH MspDeInit callback ID
597 * @retval status
599 HAL_StatusTypeDef HAL_HASH_UnRegisterCallback(HASH_HandleTypeDef *hhash, HAL_HASH_CallbackIDTypeDef CallbackID)
601 HAL_StatusTypeDef status = HAL_OK;
603 /* Process locked */
604 __HAL_LOCK(hhash);
606 if(HAL_HASH_STATE_READY == hhash->State)
608 switch (CallbackID)
610 case HAL_HASH_INPUTCPLT_CB_ID :
611 hhash->InCpltCallback = HAL_HASH_InCpltCallback; /* Legacy weak (surcharged) input completion callback */
612 break;
614 case HAL_HASH_DGSTCPLT_CB_ID :
615 hhash->DgstCpltCallback = HAL_HASH_DgstCpltCallback; /* Legacy weak (surcharged) digest computation completion callback */
616 break;
618 case HAL_HASH_ERROR_CB_ID :
619 hhash->ErrorCallback = HAL_HASH_ErrorCallback; /* Legacy weak (surcharged) error callback */
620 break;
622 case HAL_HASH_MSPINIT_CB_ID :
623 hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */
624 break;
626 case HAL_HASH_MSPDEINIT_CB_ID :
627 hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */
628 break;
630 default :
631 /* Update the error code */
632 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
633 /* update return status */
634 status = HAL_ERROR;
635 break;
638 else if(HAL_HASH_STATE_RESET == hhash->State)
640 switch (CallbackID)
642 case HAL_HASH_MSPINIT_CB_ID :
643 hhash->MspInitCallback = HAL_HASH_MspInit; /* Legacy weak (surcharged) Msp Init */
644 break;
646 case HAL_HASH_MSPDEINIT_CB_ID :
647 hhash->MspDeInitCallback = HAL_HASH_MspDeInit; /* Legacy weak (surcharged) Msp DeInit */
648 break;
650 default :
651 /* Update the error code */
652 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
653 /* update return status */
654 status = HAL_ERROR;
655 break;
658 else
660 /* Update the error code */
661 hhash->ErrorCode |= HAL_HASH_ERROR_INVALID_CALLBACK;
662 /* update return status */
663 status = HAL_ERROR;
666 /* Release Lock */
667 __HAL_UNLOCK(hhash);
668 return status;
670 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
673 * @}
676 /** @defgroup HASH_Exported_Functions_Group2 HASH processing functions in polling mode
677 * @brief HASH processing functions using polling mode.
679 @verbatim
680 ===============================================================================
681 ##### Polling mode HASH processing functions #####
682 ===============================================================================
683 [..] This section provides functions allowing to calculate in polling mode
684 the hash value using one of the following algorithms:
685 (+) MD5
686 (++) HAL_HASH_MD5_Start()
687 (++) HAL_HASH_MD5_Accumulate()
688 (+) SHA1
689 (++) HAL_HASH_SHA1_Start()
690 (++) HAL_HASH_SHA1_Accumulate()
692 [..] For a single buffer to be hashed, user can resort to HAL_HASH_xxx_Start().
694 [..] In case of multi-buffer HASH processing (a single digest is computed while
695 several buffers are fed to the IP), the user can resort to successive calls
696 to HAL_HASH_xxx_Accumulate() and wrap-up the digest computation by a call
697 to HAL_HASH_xxx_Start().
699 @endverbatim
700 * @{
704 * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
705 * read the computed digest.
706 * @note Digest is available in pOutBuffer.
707 * @param hhash: HASH handle.
708 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
709 * @param Size: length of the input buffer in bytes.
710 * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
711 * @param Timeout: Timeout value
712 * @retval HAL status
714 HAL_StatusTypeDef HAL_HASH_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
716 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
720 * @brief If not already done, initialize the HASH peripheral in MD5 mode then
721 * processes pInBuffer.
722 * @note Consecutive calls to HAL_HASH_MD5_Accumulate() can be used to feed
723 * several input buffers back-to-back to the IP that will yield a single
724 * HASH signature once all buffers have been entered. Wrap-up of input
725 * buffers feeding and retrieval of digest is done by a call to
726 * HAL_HASH_MD5_Start().
727 * @note Field hhash->Phase of HASH handle is tested to check whether or not
728 * the IP has already been initialized.
729 * @note Digest is not retrieved by this API, user must resort to HAL_HASH_MD5_Start()
730 * to read it, feeding at the same time the last input buffer to the IP.
731 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
732 * HASH digest computation is corrupted. Only HAL_HASH_MD5_Start() is able
733 * to manage the ending buffer with a length in bytes not a multiple of 4.
734 * @param hhash: HASH handle.
735 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
736 * @param Size: length of the input buffer in bytes, must be a multiple of 4.
737 * @retval HAL status
739 HAL_StatusTypeDef HAL_HASH_MD5_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
741 return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_MD5);
745 * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
746 * read the computed digest.
747 * @note Digest is available in pOutBuffer.
748 * @param hhash: HASH handle.
749 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
750 * @param Size: length of the input buffer in bytes.
751 * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
752 * @param Timeout: Timeout value
753 * @retval HAL status
755 HAL_StatusTypeDef HAL_HASH_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
757 return HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
761 * @brief If not already done, initialize the HASH peripheral in SHA1 mode then
762 * processes pInBuffer.
763 * @note Consecutive calls to HAL_HASH_SHA1_Accumulate() can be used to feed
764 * several input buffers back-to-back to the IP that will yield a single
765 * HASH signature once all buffers have been entered. Wrap-up of input
766 * buffers feeding and retrieval of digest is done by a call to
767 * HAL_HASH_SHA1_Start().
768 * @note Field hhash->Phase of HASH handle is tested to check whether or not
769 * the IP has already been initialized.
770 * @note Digest is not retrieved by this API, user must resort to HAL_HASH_SHA1_Start()
771 * to read it, feeding at the same time the last input buffer to the IP.
772 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
773 * HASH digest computation is corrupted. Only HAL_HASH_SHA1_Start() is able
774 * to manage the ending buffer with a length in bytes not a multiple of 4.
775 * @param hhash: HASH handle.
776 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
777 * @param Size: length of the input buffer in bytes, must be a multiple of 4.
778 * @retval HAL status
780 HAL_StatusTypeDef HAL_HASH_SHA1_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
782 return HASH_Accumulate(hhash, pInBuffer, Size,HASH_ALGOSELECTION_SHA1);
787 * @}
790 /** @defgroup HASH_Exported_Functions_Group3 HASH processing functions in interrupt mode
791 * @brief HASH processing functions using interrupt mode.
793 @verbatim
794 ===============================================================================
795 ##### Interruption mode HASH processing functions #####
796 ===============================================================================
797 [..] This section provides functions allowing to calculate in interrupt mode
798 the hash value using one of the following algorithms:
799 (+) MD5
800 (++) HAL_HASH_MD5_Start_IT()
801 (+) SHA1
802 (++) HAL_HASH_SHA1_Start_IT()
804 [..] API HAL_HASH_IRQHandler() manages each HASH interruption.
806 [..] Note that HAL_HASH_IRQHandler() manages as well HASH IP interruptions when in
807 HMAC processing mode.
810 @endverbatim
811 * @{
815 * @brief Initialize the HASH peripheral in MD5 mode, next process pInBuffer then
816 * read the computed digest in interruption mode.
817 * @note Digest is available in pOutBuffer.
818 * @param hhash: HASH handle.
819 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
820 * @param Size: length of the input buffer in bytes.
821 * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
822 * @retval HAL status
824 HAL_StatusTypeDef HAL_HASH_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
826 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_MD5);
831 * @brief Initialize the HASH peripheral in SHA1 mode, next process pInBuffer then
832 * read the computed digest in interruption mode.
833 * @note Digest is available in pOutBuffer.
834 * @param hhash: HASH handle.
835 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
836 * @param Size: length of the input buffer in bytes.
837 * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
838 * @retval HAL status
840 HAL_StatusTypeDef HAL_HASH_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
842 return HASH_Start_IT(hhash, pInBuffer, Size, pOutBuffer,HASH_ALGOSELECTION_SHA1);
846 * @brief Handle HASH interrupt request.
847 * @param hhash: HASH handle.
848 * @note HAL_HASH_IRQHandler() handles interrupts in HMAC processing as well.
849 * @note In case of error reported during the HASH interruption processing,
850 * HAL_HASH_ErrorCallback() API is called so that user code can
851 * manage the error. The error type is available in hhash->Status field.
852 * @retval None
854 void HAL_HASH_IRQHandler(HASH_HandleTypeDef *hhash)
856 hhash->Status = HASH_IT(hhash);
857 if (hhash->Status != HAL_OK)
859 hhash->ErrorCode |= HAL_HASH_ERROR_IT;
860 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
861 hhash->ErrorCallback(hhash);
862 #else
863 HAL_HASH_ErrorCallback(hhash);
864 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
865 /* After error handling by code user, reset HASH handle HAL status */
866 hhash->Status = HAL_OK;
871 * @}
874 /** @defgroup HASH_Exported_Functions_Group4 HASH processing functions in DMA mode
875 * @brief HASH processing functions using DMA mode.
877 @verbatim
878 ===============================================================================
879 ##### DMA mode HASH processing functions #####
880 ===============================================================================
881 [..] This section provides functions allowing to calculate in DMA mode
882 the hash value using one of the following algorithms:
883 (+) MD5
884 (++) HAL_HASH_MD5_Start_DMA()
885 (++) HAL_HASH_MD5_Finish()
886 (+) SHA1
887 (++) HAL_HASH_SHA1_Start_DMA()
888 (++) HAL_HASH_SHA1_Finish()
890 [..] When resorting to DMA mode to enter the data in the IP, user must resort
891 to HAL_HASH_xxx_Start_DMA() then read the resulting digest with
892 HAL_HASH_xxx_Finish().
893 [..] In case of multi-buffer HASH processing, MDMAT bit must first be set before
894 the successive calls to HAL_HASH_xxx_Start_DMA(). Then, MDMAT bit needs to be
895 reset before the last call to HAL_HASH_xxx_Start_DMA(). Digest is finally
896 retrieved thanks to HAL_HASH_xxx_Finish().
898 @endverbatim
899 * @{
903 * @brief Initialize the HASH peripheral in MD5 mode then initiate a DMA transfer
904 * to feed the input buffer to the IP.
905 * @note Once the DMA transfer is finished, HAL_HASH_MD5_Finish() API must
906 * be called to retrieve the computed digest.
907 * @param hhash: HASH handle.
908 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
909 * @param Size: length of the input buffer in bytes.
910 * @retval HAL status
912 HAL_StatusTypeDef HAL_HASH_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
914 return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
918 * @brief Return the computed digest in MD5 mode.
919 * @note The API waits for DCIS to be set then reads the computed digest.
920 * @note HAL_HASH_MD5_Finish() can be used as well to retrieve the digest in
921 * HMAC MD5 mode.
922 * @param hhash: HASH handle.
923 * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
924 * @param Timeout: Timeout value.
925 * @retval HAL status
927 HAL_StatusTypeDef HAL_HASH_MD5_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
929 return HASH_Finish(hhash, pOutBuffer, Timeout);
933 * @brief Initialize the HASH peripheral in SHA1 mode then initiate a DMA transfer
934 * to feed the input buffer to the IP.
935 * @note Once the DMA transfer is finished, HAL_HASH_SHA1_Finish() API must
936 * be called to retrieve the computed digest.
937 * @param hhash: HASH handle.
938 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
939 * @param Size: length of the input buffer in bytes.
940 * @retval HAL status
942 HAL_StatusTypeDef HAL_HASH_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
944 return HASH_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
949 * @brief Return the computed digest in SHA1 mode.
950 * @note The API waits for DCIS to be set then reads the computed digest.
951 * @note HAL_HASH_SHA1_Finish() can be used as well to retrieve the digest in
952 * HMAC SHA1 mode.
953 * @param hhash: HASH handle.
954 * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
955 * @param Timeout: Timeout value.
956 * @retval HAL status
958 HAL_StatusTypeDef HAL_HASH_SHA1_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
960 return HASH_Finish(hhash, pOutBuffer, Timeout);
964 * @}
967 /** @defgroup HASH_Exported_Functions_Group5 HMAC processing functions in polling mode
968 * @brief HMAC processing functions using polling mode.
970 @verbatim
971 ===============================================================================
972 ##### Polling mode HMAC processing functions #####
973 ===============================================================================
974 [..] This section provides functions allowing to calculate in polling mode
975 the HMAC value using one of the following algorithms:
976 (+) MD5
977 (++) HAL_HMAC_MD5_Start()
978 (+) SHA1
979 (++) HAL_HMAC_SHA1_Start()
982 @endverbatim
983 * @{
987 * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
988 * read the computed digest.
989 * @note Digest is available in pOutBuffer.
990 * @note Same key is used for the inner and the outer hash functions; pointer to key and
991 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
992 * @param hhash: HASH handle.
993 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
994 * @param Size: length of the input buffer in bytes.
995 * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
996 * @param Timeout: Timeout value.
997 * @retval HAL status
999 HAL_StatusTypeDef HAL_HMAC_MD5_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
1001 return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_MD5);
1005 * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1006 * read the computed digest.
1007 * @note Digest is available in pOutBuffer.
1008 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1009 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1010 * @param hhash: HASH handle.
1011 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
1012 * @param Size: length of the input buffer in bytes.
1013 * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
1014 * @param Timeout: Timeout value.
1015 * @retval HAL status
1017 HAL_StatusTypeDef HAL_HMAC_SHA1_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout)
1019 return HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout, HASH_ALGOSELECTION_SHA1);
1023 * @}
1027 /** @defgroup HASH_Exported_Functions_Group6 HMAC processing functions in interrupt mode
1028 * @brief HMAC processing functions using interrupt mode.
1030 @verbatim
1031 ===============================================================================
1032 ##### Interrupt mode HMAC processing functions #####
1033 ===============================================================================
1034 [..] This section provides functions allowing to calculate in interrupt mode
1035 the HMAC value using one of the following algorithms:
1036 (+) MD5
1037 (++) HAL_HMAC_MD5_Start_IT()
1038 (+) SHA1
1039 (++) HAL_HMAC_SHA1_Start_IT()
1041 @endverbatim
1042 * @{
1047 * @brief Initialize the HASH peripheral in HMAC MD5 mode, next process pInBuffer then
1048 * read the computed digest in interrupt mode.
1049 * @note Digest is available in pOutBuffer.
1050 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1051 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1052 * @param hhash: HASH handle.
1053 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
1054 * @param Size: length of the input buffer in bytes.
1055 * @param pOutBuffer: pointer to the computed digest. Digest size is 16 bytes.
1056 * @retval HAL status
1058 HAL_StatusTypeDef HAL_HMAC_MD5_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
1060 return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_MD5);
1064 * @brief Initialize the HASH peripheral in HMAC SHA1 mode, next process pInBuffer then
1065 * read the computed digest in interrupt mode.
1066 * @note Digest is available in pOutBuffer.
1067 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1068 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1069 * @param hhash: HASH handle.
1070 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
1071 * @param Size: length of the input buffer in bytes.
1072 * @param pOutBuffer: pointer to the computed digest. Digest size is 20 bytes.
1073 * @retval HAL status
1075 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer)
1077 return HMAC_Start_IT(hhash, pInBuffer, Size, pOutBuffer, HASH_ALGOSELECTION_SHA1);
1081 * @}
1086 /** @defgroup HASH_Exported_Functions_Group7 HMAC processing functions in DMA mode
1087 * @brief HMAC processing functions using DMA modes.
1089 @verbatim
1090 ===============================================================================
1091 ##### DMA mode HMAC processing functions #####
1092 ===============================================================================
1093 [..] This section provides functions allowing to calculate in DMA mode
1094 the HMAC value using one of the following algorithms:
1095 (+) MD5
1096 (++) HAL_HMAC_MD5_Start_DMA()
1097 (+) SHA1
1098 (++) HAL_HMAC_SHA1_Start_DMA()
1100 [..] When resorting to DMA mode to enter the data in the IP for HMAC processing,
1101 user must resort to HAL_HMAC_xxx_Start_DMA() then read the resulting digest
1102 with HAL_HASH_xxx_Finish().
1104 @endverbatim
1105 * @{
1110 * @brief Initialize the HASH peripheral in HMAC MD5 mode then initiate the required
1111 * DMA transfers to feed the key and the input buffer to the IP.
1112 * @note Once the DMA transfers are finished (indicated by hhash->State set back
1113 * to HAL_HASH_STATE_READY), HAL_HASH_MD5_Finish() API must be called to retrieve
1114 * the computed digest.
1115 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1116 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1117 * @note If MDMAT bit is set before calling this function (multi-buffer
1118 * HASH processing case), the input buffer size (in bytes) must be
1119 * a multiple of 4 otherwise, the HASH digest computation is corrupted.
1120 * For the processing of the last buffer of the thread, MDMAT bit must
1121 * be reset and the buffer length (in bytes) doesn't have to be a
1122 * multiple of 4.
1123 * @param hhash: HASH handle.
1124 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
1125 * @param Size: length of the input buffer in bytes.
1126 * @retval HAL status
1128 HAL_StatusTypeDef HAL_HMAC_MD5_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1130 return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_MD5);
1135 * @brief Initialize the HASH peripheral in HMAC SHA1 mode then initiate the required
1136 * DMA transfers to feed the key and the input buffer to the IP.
1137 * @note Once the DMA transfers are finished (indicated by hhash->State set back
1138 * to HAL_HASH_STATE_READY), HAL_HASH_SHA1_Finish() API must be called to retrieve
1139 * the computed digest.
1140 * @note Same key is used for the inner and the outer hash functions; pointer to key and
1141 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
1142 * @note If MDMAT bit is set before calling this function (multi-buffer
1143 * HASH processing case), the input buffer size (in bytes) must be
1144 * a multiple of 4 otherwise, the HASH digest computation is corrupted.
1145 * For the processing of the last buffer of the thread, MDMAT bit must
1146 * be reset and the buffer length (in bytes) doesn't have to be a
1147 * multiple of 4.
1148 * @param hhash: HASH handle.
1149 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
1150 * @param Size: length of the input buffer in bytes.
1151 * @retval HAL status
1153 HAL_StatusTypeDef HAL_HMAC_SHA1_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1155 return HMAC_Start_DMA(hhash, pInBuffer, Size, HASH_ALGOSELECTION_SHA1);
1159 * @}
1162 /** @defgroup HASH_Exported_Functions_Group8 Peripheral states functions
1163 * @brief Peripheral State functions.
1165 @verbatim
1166 ===============================================================================
1167 ##### Peripheral State methods #####
1168 ===============================================================================
1169 [..]
1170 This section permits to get in run-time the state and the peripheral handle
1171 status of the peripheral:
1172 (+) HAL_HASH_GetState()
1173 (+) HAL_HASH_GetStatus()
1175 [..]
1176 Additionally, this subsection provides functions allowing to save and restore
1177 the HASH or HMAC processing context in case of calculation suspension:
1178 (+) HAL_HASH_ContextSaving()
1179 (+) HAL_HASH_ContextRestoring()
1181 [..]
1182 This subsection provides functions allowing to suspend the HASH processing
1183 (+) when input are fed to the IP by software
1184 (++) HAL_HASH_SwFeed_ProcessSuspend()
1185 (+) when input are fed to the IP by DMA
1186 (++) HAL_HASH_DMAFeed_ProcessSuspend()
1190 @endverbatim
1191 * @{
1195 * @brief Return the HASH handle state.
1196 * @note The API yields the current state of the handle (BUSY, READY,...).
1197 * @param hhash: HASH handle.
1198 * @retval HAL HASH state
1200 HAL_HASH_StateTypeDef HAL_HASH_GetState(HASH_HandleTypeDef *hhash)
1202 return hhash->State;
1207 * @brief Return the HASH HAL status.
1208 * @note The API yields the HAL status of the handle: it is the result of the
1209 * latest HASH processing and allows to report any issue (e.g. HAL_TIMEOUT).
1210 * @param hhash: HASH handle.
1211 * @retval HAL status
1213 HAL_StatusTypeDef HAL_HASH_GetStatus(HASH_HandleTypeDef *hhash)
1215 return hhash->Status;
1219 * @brief Save the HASH context in case of processing suspension.
1220 * @param hhash: HASH handle.
1221 * @param pMemBuffer: pointer to the memory buffer where the HASH context
1222 * is saved.
1223 * @note The IMR, STR, CR then all the CSR registers are saved
1224 * in that order. Only the r/w bits are read to be restored later on.
1225 * @note By default, all the context swap registers (there are
1226 * HASH_NUMBER_OF_CSR_REGISTERS of those) are saved.
1227 * @note pMemBuffer points to a buffer allocated by the user. The buffer size
1228 * must be at least (HASH_NUMBER_OF_CSR_REGISTERS + 3) * 4 uint8 long.
1229 * @retval None
1231 void HAL_HASH_ContextSaving(HASH_HandleTypeDef *hhash, uint8_t* pMemBuffer)
1233 uint32_t mem_ptr = (uint32_t)pMemBuffer;
1234 uint32_t csr_ptr = (uint32_t)HASH->CSR;
1235 uint32_t i;
1237 /* Prevent unused argument(s) compilation warning */
1238 UNUSED(hhash);
1240 /* Save IMR register content */
1241 *(uint32_t*)(mem_ptr) = READ_BIT(HASH->IMR,HASH_IT_DINI|HASH_IT_DCI);
1242 mem_ptr+=4U;
1243 /* Save STR register content */
1244 *(uint32_t*)(mem_ptr) = READ_BIT(HASH->STR,HASH_STR_NBLW);
1245 mem_ptr+=4U;
1246 /* Save CR register content */
1247 *(uint32_t*)(mem_ptr) = READ_BIT(HASH->CR,HASH_CR_DMAE|HASH_CR_DATATYPE|HASH_CR_MODE|HASH_CR_ALGO|HASH_CR_LKEY|HASH_CR_MDMAT);
1248 mem_ptr+=4U;
1249 /* By default, save all CSRs registers */
1250 for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0U; i--)
1252 *(uint32_t*)(mem_ptr) = *(uint32_t*)(csr_ptr);
1253 mem_ptr+=4U;
1254 csr_ptr+=4U;
1260 * @brief Restore the HASH context in case of processing resumption.
1261 * @param hhash: HASH handle.
1262 * @param pMemBuffer: pointer to the memory buffer where the HASH context
1263 * is stored.
1264 * @note The IMR, STR, CR then all the CSR registers are restored
1265 * in that order. Only the r/w bits are restored.
1266 * @note By default, all the context swap registers (HASH_NUMBER_OF_CSR_REGISTERS
1267 * of those) are restored (all of them have been saved by default
1268 * beforehand).
1269 * @retval None
1271 void HAL_HASH_ContextRestoring(HASH_HandleTypeDef *hhash, uint8_t* pMemBuffer)
1273 uint32_t mem_ptr = (uint32_t)pMemBuffer;
1274 uint32_t csr_ptr = (uint32_t)HASH->CSR;
1275 uint32_t i;
1277 /* Prevent unused argument(s) compilation warning */
1278 UNUSED(hhash);
1280 /* Restore IMR register content */
1281 WRITE_REG(HASH->IMR, (*(uint32_t*)(mem_ptr)));
1282 mem_ptr+=4U;
1283 /* Restore STR register content */
1284 WRITE_REG(HASH->STR, (*(uint32_t*)(mem_ptr)));
1285 mem_ptr+=4U;
1286 /* Restore CR register content */
1287 WRITE_REG(HASH->CR, (*(uint32_t*)(mem_ptr)));
1288 mem_ptr+=4U;
1290 /* Reset the HASH processor before restoring the Context
1291 Swap Registers (CSR) */
1292 __HAL_HASH_INIT();
1294 /* By default, restore all CSR registers */
1295 for (i = HASH_NUMBER_OF_CSR_REGISTERS; i >0U; i--)
1297 WRITE_REG((*(uint32_t*)(csr_ptr)), (*(uint32_t*)(mem_ptr)));
1298 mem_ptr+=4U;
1299 csr_ptr+=4U;
1305 * @brief Initiate HASH processing suspension when in polling or interruption mode.
1306 * @param hhash: HASH handle.
1307 * @note Set the handle field SuspendRequest to the appropriate value so that
1308 * the on-going HASH processing is suspended as soon as the required
1309 * conditions are met. Note that the actual suspension is carried out
1310 * by the functions HASH_WriteData() in polling mode and HASH_IT() in
1311 * interruption mode.
1312 * @retval None
1314 void HAL_HASH_SwFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1316 /* Set Handle Suspend Request field */
1317 hhash->SuspendRequest = HAL_HASH_SUSPEND;
1321 * @brief Suspend the HASH processing when in DMA mode.
1322 * @param hhash: HASH handle.
1323 * @note When suspension attempt occurs at the very end of a DMA transfer and
1324 * all the data have already been entered in the IP, hhash->State is
1325 * set to HAL_HASH_STATE_READY and the API returns HAL_ERROR. It is
1326 * recommended to wrap-up the processing in reading the digest as usual.
1327 * @retval HAL status
1329 HAL_StatusTypeDef HAL_HASH_DMAFeed_ProcessSuspend(HASH_HandleTypeDef *hhash)
1331 uint32_t tmp_remaining_DMATransferSize_inWords;
1332 uint32_t tmp_initial_DMATransferSize_inWords;
1333 uint32_t tmp_words_already_pushed;
1335 if (hhash->State == HAL_HASH_STATE_READY)
1337 return HAL_ERROR;
1339 else
1342 /* Make sure there is enough time to suspend the processing */
1343 tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1345 if (tmp_remaining_DMATransferSize_inWords <= HASH_DMA_SUSPENSION_WORDS_LIMIT)
1347 /* No suspension attempted since almost to the end of the transferred data. */
1348 /* Best option for user code is to wrap up low priority message hashing */
1349 return HAL_ERROR;
1352 /* Wait for DMAS to be reset */
1353 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1355 return HAL_TIMEOUT;
1358 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1360 return HAL_ERROR;
1363 /* Wait for DMAS to be set */
1364 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, RESET, HASH_TIMEOUTVALUE) != HAL_OK)
1366 return HAL_TIMEOUT;
1369 /* Disable DMA channel */
1370 if (HAL_DMA_Abort(hhash->hdmain) ==HAL_OK)
1373 Note that the Abort function will
1374 - Clear the transfer error flags
1375 - Unlock
1376 - Set the State
1380 /* Clear DMAE bit */
1381 CLEAR_BIT(HASH->CR,HASH_CR_DMAE);
1383 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1385 return HAL_TIMEOUT;
1388 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS) != RESET)
1390 return HAL_ERROR;
1393 /* At this point, DMA interface is disabled and no transfer is on-going */
1394 /* Retrieve from the DMA handle how many words remain to be written */
1395 tmp_remaining_DMATransferSize_inWords = ((DMA_Stream_TypeDef *)hhash->hdmain->Instance)->NDTR;
1397 if (tmp_remaining_DMATransferSize_inWords == 0U)
1399 /* All the DMA transfer is actually done. Suspension occurred at the very end
1400 of the transfer. Either the digest computation is about to start (HASH case)
1401 or processing is about to move from one step to another (HMAC case).
1402 In both cases, the processing can't be suspended at this point. It is
1403 safer to
1404 - retrieve the low priority block digest before starting the high
1405 priority block processing (HASH case)
1406 - re-attempt a new suspension (HMAC case)
1408 return HAL_ERROR;
1410 else
1413 /* Compute how many words were supposed to be transferred by DMA */
1414 tmp_initial_DMATransferSize_inWords = (((hhash->HashInCount%4U)!=0U) ? ((hhash->HashInCount+3U)/4U): (hhash->HashInCount/4U));
1416 /* If discrepancy between the number of words reported by DMA IP and the numbers of words entered as reported
1417 by HASH IP, correct it */
1418 /* tmp_words_already_pushed reflects the number of words that were already pushed before
1419 the start of DMA transfer (multi-buffer processing case) */
1420 tmp_words_already_pushed = hhash->NbWordsAlreadyPushed;
1421 if (((tmp_words_already_pushed + tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) %16U) != HASH_NBW_PUSHED())
1423 tmp_remaining_DMATransferSize_inWords--; /* one less word to be transferred again */
1426 /* Accordingly, update the input pointer that points at the next word to be transferred to the IP by DMA */
1427 hhash->pHashInBuffPtr += 4U * (tmp_initial_DMATransferSize_inWords - tmp_remaining_DMATransferSize_inWords) ;
1429 /* And store in HashInCount the remaining size to transfer (in bytes) */
1430 hhash->HashInCount = 4U * tmp_remaining_DMATransferSize_inWords;
1434 /* Set State as suspended */
1435 hhash->State = HAL_HASH_STATE_SUSPENDED;
1437 return HAL_OK;
1443 * @brief Return the HASH handle error code.
1444 * @param hhash: pointer to a HASH_HandleTypeDef structure.
1445 * @retval HASH Error Code
1447 uint32_t HAL_HASH_GetError(HASH_HandleTypeDef *hhash)
1449 /* Return HASH Error Code */
1450 return hhash->ErrorCode;
1453 * @}
1458 * @}
1461 /** @defgroup HASH_Private_Functions HASH Private Functions
1462 * @{
1466 * @brief DMA HASH Input Data transfer completion callback.
1467 * @param hdma: DMA handle.
1468 * @note In case of HMAC processing, HASH_DMAXferCplt() initiates
1469 * the next DMA transfer for the following HMAC step.
1470 * @retval None
1472 static void HASH_DMAXferCplt(DMA_HandleTypeDef *hdma)
1474 HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1475 uint32_t inputaddr;
1476 uint32_t buffersize;
1477 HAL_StatusTypeDef status ;
1479 if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1482 /* Disable the DMA transfer */
1483 CLEAR_BIT(HASH->CR, HASH_CR_DMAE);
1485 if (READ_BIT(HASH->CR, HASH_CR_MODE) == 0U)
1487 /* If no HMAC processing, input data transfer is now over */
1489 /* Change the HASH state to ready */
1490 hhash->State = HAL_HASH_STATE_READY;
1492 /* Call Input data transfer complete call back */
1493 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1494 hhash->InCpltCallback(hhash);
1495 #else
1496 HAL_HASH_InCpltCallback(hhash);
1497 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1500 else
1502 /* HMAC processing: depending on the current HMAC step and whether or
1503 not multi-buffer processing is on-going, the next step is initiated
1504 and MDMAT bit is set. */
1507 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
1509 /* This is the end of HMAC processing */
1511 /* Change the HASH state to ready */
1512 hhash->State = HAL_HASH_STATE_READY;
1514 /* Call Input data transfer complete call back
1515 (note that the last DMA transfer was that of the key
1516 for the outer HASH operation). */
1517 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1518 hhash->InCpltCallback(hhash);
1519 #else
1520 HAL_HASH_InCpltCallback(hhash);
1521 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1523 return;
1525 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
1527 inputaddr = (uint32_t)hhash->pHashMsgBuffPtr; /* DMA transfer start address */
1528 buffersize = hhash->HashBuffSize; /* DMA transfer size (in bytes) */
1529 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */
1531 /* In case of suspension request, save the new starting parameters */
1532 hhash->HashInCount = hhash->HashBuffSize; /* Initial DMA transfer size (in bytes) */
1533 hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr ; /* DMA transfer start address */
1535 hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */
1536 /* Check whether or not digest calculation must be disabled (in case of multi-buffer HMAC processing) */
1537 if (hhash->DigestCalculationDisable != RESET)
1539 /* Digest calculation is disabled: Step 2 must start with MDMAT bit set,
1540 no digest calculation will be triggered at the end of the input buffer feeding to the IP */
1541 __HAL_HASH_SET_MDMAT();
1544 else /*case (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)*/
1546 if (hhash->DigestCalculationDisable != RESET)
1548 /* No automatic move to Step 3 as a new message buffer will be fed to the IP
1549 (case of multi-buffer HMAC processing):
1550 DCAL must not be set.
1551 Phase remains in Step 2, MDMAT remains set at this point.
1552 Change the HASH state to ready and call Input data transfer complete call back. */
1553 hhash->State = HAL_HASH_STATE_READY;
1554 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1555 hhash->InCpltCallback(hhash);
1556 #else
1557 HAL_HASH_InCpltCallback(hhash);
1558 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1559 return ;
1561 else
1563 /* Digest calculation is not disabled (case of single buffer input or last buffer
1564 of multi-buffer HMAC processing) */
1565 inputaddr = (uint32_t)hhash->Init.pKey; /* DMA transfer start address */
1566 buffersize = hhash->Init.KeySize; /* DMA transfer size (in bytes) */
1567 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */
1568 /* In case of suspension request, save the new starting parameters */
1569 hhash->HashInCount = hhash->Init.KeySize; /* Initial size for second DMA transfer (input data) */
1570 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* address passed to DMA, now entering data message */
1572 hhash->NbWordsAlreadyPushed = 0U; /* Reset number of words already pushed */
1576 /* Configure the Number of valid bits in last word of the message */
1577 __HAL_HASH_SET_NBVALIDBITS(buffersize);
1579 /* Set the HASH DMA transfert completion call back */
1580 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
1582 /* Enable the DMA In DMA Stream */
1583 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((buffersize %4U)!=0U) ? ((buffersize+(4U-(buffersize %4U)))/4U):(buffersize/4U)));
1585 /* Enable DMA requests */
1586 SET_BIT(HASH->CR, HASH_CR_DMAE);
1588 /* Return function status */
1589 if (status != HAL_OK)
1591 /* Update DAC state machine to error */
1592 hhash->State = HAL_HASH_STATE_ERROR;
1594 else
1596 /* Change DAC state */
1597 hhash->State = HAL_HASH_STATE_READY;
1602 return;
1606 * @brief DMA HASH communication error callback.
1607 * @param hdma: DMA handle.
1608 * @note HASH_DMAError() callback invokes HAL_HASH_ErrorCallback() that
1609 * can contain user code to manage the error.
1610 * @retval None
1612 static void HASH_DMAError(DMA_HandleTypeDef *hdma)
1614 HASH_HandleTypeDef* hhash = ( HASH_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
1616 if (hhash->State != HAL_HASH_STATE_SUSPENDED)
1618 hhash->ErrorCode |= HAL_HASH_ERROR_DMA;
1619 /* Set HASH state to ready to prevent any blocking issue in user code
1620 present in HAL_HASH_ErrorCallback() */
1621 hhash->State= HAL_HASH_STATE_READY;
1622 /* Set HASH handle status to error */
1623 hhash->Status = HAL_ERROR;
1624 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1625 hhash->ErrorCallback(hhash);
1626 #else
1627 HAL_HASH_ErrorCallback(hhash);
1628 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1629 /* After error handling by code user, reset HASH handle HAL status */
1630 hhash->Status = HAL_OK;
1636 * @brief Feed the input buffer to the HASH IP.
1637 * @param hhash: HASH handle.
1638 * @param pInBuffer: pointer to input buffer.
1639 * @param Size: the size of input buffer in bytes.
1640 * @note HASH_WriteData() regularly reads hhash->SuspendRequest to check whether
1641 * or not the HASH processing must be suspended. If this is the case, the
1642 * processing is suspended when possible and the IP feeding point reached at
1643 * suspension time is stored in the handle for resumption later on.
1644 * @retval HAL status
1646 static HAL_StatusTypeDef HASH_WriteData(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size)
1648 uint32_t buffercounter;
1649 __IO uint32_t inputaddr = (uint32_t) pInBuffer;
1651 for(buffercounter = 0U; buffercounter < Size; buffercounter+=4U)
1653 /* Write input data 4 bytes at a time */
1654 HASH->DIN = *(uint32_t*)inputaddr;
1655 inputaddr+=4U;
1657 /* If the suspension flag has been raised and if the processing is not about
1658 to end, suspend processing */
1659 if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4U) < Size))
1661 /* Wait for DINIS = 1, which occurs when 16 32-bit locations are free
1662 in the input buffer */
1663 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
1665 /* Reset SuspendRequest */
1666 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
1668 /* Depending whether the key or the input data were fed to the IP, the feeding point
1669 reached at suspension time is not saved in the same handle fields */
1670 if ((hhash->Phase == HAL_HASH_PHASE_PROCESS) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2))
1672 /* Save current reading and writing locations of Input and Output buffers */
1673 hhash->pHashInBuffPtr = (uint8_t *)inputaddr;
1674 /* Save the number of bytes that remain to be processed at this point */
1675 hhash->HashInCount = Size - (buffercounter + 4U);
1677 else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
1679 /* Save current reading and writing locations of Input and Output buffers */
1680 hhash->pHashKeyBuffPtr = (uint8_t *)inputaddr;
1681 /* Save the number of bytes that remain to be processed at this point */
1682 hhash->HashKeyCount = Size - (buffercounter + 4U);
1684 else
1686 /* Unexpected phase: unlock process and report error */
1687 hhash->State = HAL_HASH_STATE_READY;
1688 __HAL_UNLOCK(hhash);
1689 return HAL_ERROR;
1692 /* Set the HASH state to Suspended and exit to stop entering data */
1693 hhash->State = HAL_HASH_STATE_SUSPENDED;
1695 return HAL_OK;
1696 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS)) */
1697 } /* if ((hhash->SuspendRequest == HAL_HASH_SUSPEND) && ((buffercounter+4) < Size)) */
1698 } /* for(buffercounter = 0; buffercounter < Size; buffercounter+=4) */
1700 /* At this point, all the data have been entered to the IP: exit */
1701 return HAL_OK;
1705 * @brief Retrieve the message digest.
1706 * @param pMsgDigest: pointer to the computed digest.
1707 * @param Size: message digest size in bytes.
1708 * @retval None
1710 static void HASH_GetDigest(uint8_t *pMsgDigest, uint8_t Size)
1712 uint32_t msgdigest = (uint32_t)pMsgDigest;
1714 switch(Size)
1716 /* Read the message digest */
1717 case 16: /* MD5 */
1718 *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
1719 msgdigest+=4U;
1720 *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
1721 msgdigest+=4U;
1722 *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
1723 msgdigest+=4U;
1724 *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
1725 break;
1726 case 20: /* SHA1 */
1727 *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
1728 msgdigest+=4U;
1729 *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
1730 msgdigest+=4U;
1731 *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
1732 msgdigest+=4U;
1733 *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
1734 msgdigest+=4U;
1735 *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
1736 break;
1737 case 28: /* SHA224 */
1738 *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
1739 msgdigest+=4U;
1740 *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
1741 msgdigest+=4U;
1742 *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
1743 msgdigest+=4U;
1744 *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
1745 msgdigest+=4U;
1746 *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
1747 msgdigest+=4U;
1748 *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
1749 msgdigest+=4U;
1750 *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
1751 break;
1752 case 32: /* SHA256 */
1753 *(uint32_t*)(msgdigest) = __REV(HASH->HR[0]);
1754 msgdigest+=4U;
1755 *(uint32_t*)(msgdigest) = __REV(HASH->HR[1]);
1756 msgdigest+=4U;
1757 *(uint32_t*)(msgdigest) = __REV(HASH->HR[2]);
1758 msgdigest+=4U;
1759 *(uint32_t*)(msgdigest) = __REV(HASH->HR[3]);
1760 msgdigest+=4U;
1761 *(uint32_t*)(msgdigest) = __REV(HASH->HR[4]);
1762 msgdigest+=4U;
1763 *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[5]);
1764 msgdigest+=4U;
1765 *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[6]);
1766 msgdigest+=4U;
1767 *(uint32_t*)(msgdigest) = __REV(HASH_DIGEST->HR[7]);
1768 break;
1769 default:
1770 break;
1777 * @brief Handle HASH processing Timeout.
1778 * @param hhash: HASH handle.
1779 * @param Flag: specifies the HASH flag to check.
1780 * @param Status: the Flag status (SET or RESET).
1781 * @param Timeout: Timeout duration.
1782 * @retval HAL status
1784 static HAL_StatusTypeDef HASH_WaitOnFlagUntilTimeout(HASH_HandleTypeDef *hhash, uint32_t Flag, FlagStatus Status, uint32_t Timeout)
1786 uint32_t tickstart = HAL_GetTick();
1788 /* Wait until flag is set */
1789 if(Status == RESET)
1791 while(__HAL_HASH_GET_FLAG(Flag) == RESET)
1793 /* Check for the Timeout */
1794 if(Timeout != HAL_MAX_DELAY)
1796 if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U))
1798 /* Set State to Ready to be able to restart later on */
1799 hhash->State = HAL_HASH_STATE_READY;
1800 /* Store time out issue in handle status */
1801 hhash->Status = HAL_TIMEOUT;
1803 /* Process Unlocked */
1804 __HAL_UNLOCK(hhash);
1806 return HAL_TIMEOUT;
1811 else
1813 while(__HAL_HASH_GET_FLAG(Flag) != RESET)
1815 /* Check for the Timeout */
1816 if(Timeout != HAL_MAX_DELAY)
1818 if(((HAL_GetTick()-tickstart) > Timeout) || (Timeout == 0U))
1820 /* Set State to Ready to be able to restart later on */
1821 hhash->State = HAL_HASH_STATE_READY;
1822 /* Store time out issue in handle status */
1823 hhash->Status = HAL_TIMEOUT;
1825 /* Process Unlocked */
1826 __HAL_UNLOCK(hhash);
1828 return HAL_TIMEOUT;
1833 return HAL_OK;
1838 * @brief HASH processing in interruption mode.
1839 * @param hhash: HASH handle.
1840 * @note HASH_IT() regularly reads hhash->SuspendRequest to check whether
1841 * or not the HASH processing must be suspended. If this is the case, the
1842 * processing is suspended when possible and the IP feeding point reached at
1843 * suspension time is stored in the handle for resumption later on.
1844 * @retval HAL status
1846 static HAL_StatusTypeDef HASH_IT(HASH_HandleTypeDef *hhash)
1848 if (hhash->State == HAL_HASH_STATE_BUSY)
1850 /* ITCounter must not be equal to 0 at this point. Report an error if this is the case. */
1851 if(hhash->HashITCounter == 0U)
1853 /* Disable Interrupts */
1854 __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1855 /* HASH state set back to Ready to prevent any issue in user code
1856 present in HAL_HASH_ErrorCallback() */
1857 hhash->State = HAL_HASH_STATE_READY;
1858 return HAL_ERROR;
1860 else if (hhash->HashITCounter == 1U)
1862 /* This is the first call to HASH_IT, the first input data are about to be
1863 entered in the IP. A specific processing is carried out at this point to
1864 start-up the processing. */
1865 hhash->HashITCounter = 2U;
1867 else
1869 /* Cruise speed reached, HashITCounter remains equal to 3 until the end of
1870 the HASH processing or the end of the current step for HMAC processing. */
1871 hhash->HashITCounter = 3U;
1874 /* If digest is ready */
1875 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DCIS))
1877 /* Read the digest */
1878 HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
1880 /* Disable Interrupts */
1881 __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1882 /* Change the HASH state */
1883 hhash->State = HAL_HASH_STATE_READY;
1884 /* Call digest computation complete call back */
1885 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1886 hhash->DgstCpltCallback(hhash);
1887 #else
1888 HAL_HASH_DgstCpltCallback(hhash);
1889 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1891 return HAL_OK;
1894 /* If IP ready to accept new data */
1895 if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))
1898 /* If the suspension flag has been raised and if the processing is not about
1899 to end, suspend processing */
1900 if ( (hhash->HashInCount != 0U) && (hhash->SuspendRequest == HAL_HASH_SUSPEND))
1902 /* Disable Interrupts */
1903 __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1905 /* Reset SuspendRequest */
1906 hhash->SuspendRequest = HAL_HASH_SUSPEND_NONE;
1908 /* Change the HASH state */
1909 hhash->State = HAL_HASH_STATE_SUSPENDED;
1911 return HAL_OK;
1914 /* Enter input data in the IP thru HASH_Write_Block_Data() call and
1915 check whether the digest calculation has been triggered */
1916 if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED)
1918 /* Call Input data transfer complete call back
1919 (called at the end of each step for HMAC) */
1920 #if (USE_HAL_HASH_REGISTER_CALLBACKS == 1)
1921 hhash->InCpltCallback(hhash);
1922 #else
1923 HAL_HASH_InCpltCallback(hhash);
1924 #endif /* USE_HAL_HASH_REGISTER_CALLBACKS */
1926 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
1928 /* Wait until IP is not busy anymore */
1929 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1931 /* Disable Interrupts */
1932 __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1933 return HAL_TIMEOUT;
1935 /* Initialization start for HMAC STEP 2 */
1936 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2; /* Move phase from Step 1 to Step 2 */
1937 __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize); /* Set NBLW for the input message */
1938 hhash->HashInCount = hhash->HashBuffSize; /* Set the input data size (in bytes) */
1939 hhash->pHashInBuffPtr = hhash->pHashMsgBuffPtr; /* Set the input data address */
1940 hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start of a new phase */
1941 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */
1943 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
1945 /* Wait until IP is not busy anymore */
1946 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, HASH_TIMEOUTVALUE) != HAL_OK)
1948 /* Disable Interrupts */
1949 __HAL_HASH_DISABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
1950 return HAL_TIMEOUT;
1952 /* Initialization start for HMAC STEP 3 */
1953 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3; /* Move phase from Step 2 to Step 3 */
1954 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize); /* Set NBLW for the key */
1955 hhash->HashInCount = hhash->Init.KeySize; /* Set the key size (in bytes) */
1956 hhash->pHashInBuffPtr = hhash->Init.pKey; /* Set the key address */
1957 hhash->HashITCounter = 1; /* Set ITCounter to 1 to indicate the start of a new phase */
1958 __HAL_HASH_ENABLE_IT(HASH_IT_DINI); /* Enable IT (was disabled in HASH_Write_Block_Data) */
1960 else
1962 /* Nothing to do */
1964 } /* if (HASH_Write_Block_Data(hhash) == HASH_DIGEST_CALCULATION_STARTED) */
1965 } /* if (__HAL_HASH_GET_FLAG(HASH_FLAG_DINIS))*/
1967 /* Return function status */
1968 return HAL_OK;
1970 else
1972 return HAL_BUSY;
1978 * @brief Write a block of data in HASH IP in interruption mode.
1979 * @param hhash: HASH handle.
1980 * @note HASH_Write_Block_Data() is called under interruption by HASH_IT().
1981 * @retval HAL status
1983 static uint32_t HASH_Write_Block_Data(HASH_HandleTypeDef *hhash)
1985 uint32_t inputaddr;
1986 uint32_t buffercounter;
1987 uint32_t inputcounter;
1988 uint32_t ret = HASH_DIGEST_CALCULATION_NOT_STARTED;
1990 /* If there are more than 64 bytes remaining to be entered */
1991 if(hhash->HashInCount > 64U)
1993 inputaddr = (uint32_t)hhash->pHashInBuffPtr;
1994 /* Write the Input block in the Data IN register
1995 (16 32-bit words, or 64 bytes are entered) */
1996 for(buffercounter = 0U; buffercounter < 64U; buffercounter+=4U)
1998 HASH->DIN = *(uint32_t*)inputaddr;
1999 inputaddr+=4U;
2001 /* If this is the start of input data entering, an additional word
2002 must be entered to start up the HASH processing */
2003 if(hhash->HashITCounter == 2U)
2005 HASH->DIN = *(uint32_t*)inputaddr;
2006 if(hhash->HashInCount >= 68U)
2008 /* There are still data waiting to be entered in the IP.
2009 Decrement buffer counter and set pointer to the proper
2010 memory location for the next data entering round. */
2011 hhash->HashInCount -= 68U;
2012 hhash->pHashInBuffPtr+= 68U;
2014 else
2016 /* All the input buffer has been fed to the HW. */
2017 hhash->HashInCount = 0U;
2020 else
2022 /* 64 bytes have been entered and there are still some remaining:
2023 Decrement buffer counter and set pointer to the proper
2024 memory location for the next data entering round.*/
2025 hhash->HashInCount -= 64U;
2026 hhash->pHashInBuffPtr+= 64U;
2029 else
2031 /* 64 or less bytes remain to be entered. This is the last
2032 data entering round. */
2034 /* Get the buffer address */
2035 inputaddr = (uint32_t)hhash->pHashInBuffPtr;
2036 /* Get the buffer counter */
2037 inputcounter = hhash->HashInCount;
2038 /* Disable Interrupts */
2039 __HAL_HASH_DISABLE_IT(HASH_IT_DINI);
2041 /* Write the Input block in the Data IN register */
2042 for(buffercounter = 0U; buffercounter < ((inputcounter+3U)/4U); buffercounter++)
2044 HASH->DIN = *(uint32_t*)inputaddr;
2045 inputaddr+=4U;
2047 /* Start the Digest calculation */
2048 __HAL_HASH_START_DIGEST();
2049 /* Return indication that digest calculation has started:
2050 this return value triggers the call to Input data transfer
2051 complete call back as well as the proper transition from
2052 one step to another in HMAC mode. */
2053 ret = HASH_DIGEST_CALCULATION_STARTED;
2054 /* Reset buffer counter */
2055 hhash->HashInCount = 0;
2058 /* Return whether or digest calculation has started */
2059 return ret;
2063 * @brief HMAC processing in polling mode.
2064 * @param hhash: HASH handle.
2065 * @param Timeout: Timeout value.
2066 * @retval HAL status
2068 static HAL_StatusTypeDef HMAC_Processing(HASH_HandleTypeDef *hhash, uint32_t Timeout)
2070 /* Ensure first that Phase is correct */
2071 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))
2073 /* Change the HASH state */
2074 hhash->State = HAL_HASH_STATE_READY;
2076 /* Process Unlock */
2077 __HAL_UNLOCK(hhash);
2079 /* Return function status */
2080 return HAL_ERROR;
2083 /* HMAC Step 1 processing */
2084 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1)
2086 /************************** STEP 1 ******************************************/
2087 /* Configure the Number of valid bits in last word of the message */
2088 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2090 /* Write input buffer in Data register */
2091 hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2092 if (hhash->Status != HAL_OK)
2094 return hhash->Status;
2097 /* Check whether or not key entering process has been suspended */
2098 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2100 /* Process Unlocked */
2101 __HAL_UNLOCK(hhash);
2103 /* Stop right there and return function status */
2104 return HAL_OK;
2107 /* No processing suspension at this point: set DCAL bit. */
2108 __HAL_HASH_START_DIGEST();
2110 /* Wait for BUSY flag to be cleared */
2111 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2113 return HAL_TIMEOUT;
2116 /* Move from Step 1 to Step 2 */
2117 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_2;
2121 /* HMAC Step 2 processing.
2122 After phase check, HMAC_Processing() may
2123 - directly start up from this point in resumption case
2124 if the same Step 2 processing was suspended previously
2125 - or fall through from the Step 1 processing carried out hereabove */
2126 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2128 /************************** STEP 2 ******************************************/
2129 /* Configure the Number of valid bits in last word of the message */
2130 __HAL_HASH_SET_NBVALIDBITS(hhash->HashBuffSize);
2132 /* Write input buffer in Data register */
2133 hhash->Status = HASH_WriteData(hhash, hhash->pHashInBuffPtr, hhash->HashInCount);
2134 if (hhash->Status != HAL_OK)
2136 return hhash->Status;
2139 /* Check whether or not data entering process has been suspended */
2140 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2142 /* Process Unlocked */
2143 __HAL_UNLOCK(hhash);
2145 /* Stop right there and return function status */
2146 return HAL_OK;
2149 /* No processing suspension at this point: set DCAL bit. */
2150 __HAL_HASH_START_DIGEST();
2152 /* Wait for BUSY flag to be cleared */
2153 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_BUSY, SET, Timeout) != HAL_OK)
2155 return HAL_TIMEOUT;
2158 /* Move from Step 2 to Step 3 */
2159 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_3;
2160 /* In case Step 1 phase was suspended then resumed,
2161 set again Key input buffers and size before moving to
2162 next step */
2163 hhash->pHashKeyBuffPtr = hhash->Init.pKey;
2164 hhash->HashKeyCount = hhash->Init.KeySize;
2168 /* HMAC Step 3 processing.
2169 After phase check, HMAC_Processing() may
2170 - directly start up from this point in resumption case
2171 if the same Step 3 processing was suspended previously
2172 - or fall through from the Step 2 processing carried out hereabove */
2173 if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3)
2175 /************************** STEP 3 ******************************************/
2176 /* Configure the Number of valid bits in last word of the message */
2177 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2179 /* Write input buffer in Data register */
2180 hhash->Status = HASH_WriteData(hhash, hhash->pHashKeyBuffPtr, hhash->HashKeyCount);
2181 if (hhash->Status != HAL_OK)
2183 return hhash->Status;
2186 /* Check whether or not key entering process has been suspended */
2187 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2189 /* Process Unlocked */
2190 __HAL_UNLOCK(hhash);
2192 /* Stop right there and return function status */
2193 return HAL_OK;
2196 /* No processing suspension at this point: start the Digest calculation. */
2197 __HAL_HASH_START_DIGEST();
2199 /* Wait for DCIS flag to be set */
2200 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2202 return HAL_TIMEOUT;
2205 /* Read the message digest */
2206 HASH_GetDigest(hhash->pHashOutBuffPtr, HASH_DIGEST_LENGTH());
2209 /* Change the HASH state */
2210 hhash->State = HAL_HASH_STATE_READY;
2212 /* Process Unlock */
2213 __HAL_UNLOCK(hhash);
2215 /* Return function status */
2216 return HAL_OK;
2221 * @brief Initialize the HASH peripheral, next process pInBuffer then
2222 * read the computed digest.
2223 * @note Digest is available in pOutBuffer.
2224 * @param hhash: HASH handle.
2225 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
2226 * @param Size: length of the input buffer in bytes.
2227 * @param pOutBuffer: pointer to the computed digest.
2228 * @param Timeout: Timeout value.
2229 * @param Algorithm: HASH algorithm.
2230 * @retval HAL status
2232 HAL_StatusTypeDef HASH_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout, uint32_t Algorithm)
2234 uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */
2235 uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
2236 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2239 /* Initiate HASH processing in case of start or resumption */
2240 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2242 /* Check input parameters */
2243 if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
2245 hhash->State = HAL_HASH_STATE_READY;
2246 return HAL_ERROR;
2249 /* Process Locked */
2250 __HAL_LOCK(hhash);
2252 /* Check if initialization phase has not been already performed */
2253 if(hhash->Phase == HAL_HASH_PHASE_READY)
2255 /* Change the HASH state */
2256 hhash->State = HAL_HASH_STATE_BUSY;
2258 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2259 MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2261 /* Configure the number of valid bits in last word of the message */
2262 __HAL_HASH_SET_NBVALIDBITS(Size);
2264 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2265 input parameters of HASH_WriteData() */
2266 pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */
2267 Size_tmp = Size; /* Size_tmp contains the input data size in bytes */
2269 /* Set the phase */
2270 hhash->Phase = HAL_HASH_PHASE_PROCESS;
2272 else if (hhash->Phase == HAL_HASH_PHASE_PROCESS)
2274 /* if the IP has already been initialized, two cases are possible */
2276 /* Process resumption time ... */
2277 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2279 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2280 to the API input parameters but to those saved beforehand by HASH_WriteData()
2281 when the processing was suspended */
2282 pInBuffer_tmp = hhash->pHashInBuffPtr;
2283 Size_tmp = hhash->HashInCount;
2285 /* ... or multi-buffer HASH processing end */
2286 else
2288 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2289 input parameters of HASH_WriteData() */
2290 pInBuffer_tmp = pInBuffer;
2291 Size_tmp = Size;
2292 /* Configure the number of valid bits in last word of the message */
2293 __HAL_HASH_SET_NBVALIDBITS(Size);
2295 /* Change the HASH state */
2296 hhash->State = HAL_HASH_STATE_BUSY;
2298 else
2300 /* Phase error */
2301 hhash->State = HAL_HASH_STATE_READY;
2303 /* Process Unlocked */
2304 __HAL_UNLOCK(hhash);
2306 /* Return function status */
2307 return HAL_ERROR;
2311 /* Write input buffer in Data register */
2312 hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2313 if (hhash->Status != HAL_OK)
2315 return hhash->Status;
2318 /* If the process has not been suspended, carry on to digest calculation */
2319 if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2321 /* Start the Digest calculation */
2322 __HAL_HASH_START_DIGEST();
2324 /* Wait for DCIS flag to be set */
2325 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2327 return HAL_TIMEOUT;
2330 /* Read the message digest */
2331 HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
2333 /* Change the HASH state */
2334 hhash->State = HAL_HASH_STATE_READY;
2338 /* Process Unlocked */
2339 __HAL_UNLOCK(hhash);
2341 /* Return function status */
2342 return HAL_OK;
2345 else
2347 return HAL_BUSY;
2353 * @brief If not already done, initialize the HASH peripheral then
2354 * processes pInBuffer.
2355 * @note Field hhash->Phase of HASH handle is tested to check whether or not
2356 * the IP has already been initialized.
2357 * @note The input buffer size (in bytes) must be a multiple of 4 otherwise, the
2358 * HASH digest computation is corrupted.
2359 * @param hhash: HASH handle.
2360 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
2361 * @param Size: length of the input buffer in bytes, must be a multiple of 4.
2362 * @param Algorithm: HASH algorithm.
2363 * @retval HAL status
2365 HAL_StatusTypeDef HASH_Accumulate(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2367 uint8_t *pInBuffer_tmp; /* input data address, input parameter of HASH_WriteData() */
2368 uint32_t Size_tmp; /* input data size (in bytes), input parameter of HASH_WriteData() */
2369 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2371 /* Make sure the input buffer size (in bytes) is a multiple of 4 */
2372 assert_param(IS_HASH_POLLING_MULTIBUFFER_SIZE(Size));
2374 /* Initiate HASH processing in case of start or resumption */
2375 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2377 /* Check input parameters */
2378 if ((pInBuffer == NULL) || (Size == 0U))
2380 hhash->State = HAL_HASH_STATE_READY;
2381 return HAL_ERROR;
2384 /* Process Locked */
2385 __HAL_LOCK(hhash);
2387 /* If resuming the HASH processing */
2388 if (hhash->State == HAL_HASH_STATE_SUSPENDED)
2390 /* Change the HASH state */
2391 hhash->State = HAL_HASH_STATE_BUSY;
2393 /* Since this is resumption, pInBuffer_tmp and Size_tmp are not set
2394 to the API input parameters but to those saved beforehand by HASH_WriteData()
2395 when the processing was suspended */
2396 pInBuffer_tmp = hhash->pHashInBuffPtr; /* pInBuffer_tmp is set to the input data address */
2397 Size_tmp = hhash->HashInCount; /* Size_tmp contains the input data size in bytes */
2400 else
2402 /* Change the HASH state */
2403 hhash->State = HAL_HASH_STATE_BUSY;
2405 /* pInBuffer_tmp and Size_tmp are initialized to be used afterwards as
2406 input parameters of HASH_WriteData() */
2407 pInBuffer_tmp = pInBuffer; /* pInBuffer_tmp is set to the input data address */
2408 Size_tmp = Size; /* Size_tmp contains the input data size in bytes */
2410 /* Check if initialization phase has already be performed */
2411 if(hhash->Phase == HAL_HASH_PHASE_READY)
2413 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2414 MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2417 /* Set the phase */
2418 hhash->Phase = HAL_HASH_PHASE_PROCESS;
2422 /* Write input buffer in Data register */
2423 hhash->Status = HASH_WriteData(hhash, pInBuffer_tmp, Size_tmp);
2424 if (hhash->Status != HAL_OK)
2426 return hhash->Status;
2429 /* If the process has not been suspended, move the state to Ready */
2430 if (hhash->State != HAL_HASH_STATE_SUSPENDED)
2432 /* Change the HASH state */
2433 hhash->State = HAL_HASH_STATE_READY;
2436 /* Process Unlocked */
2437 __HAL_UNLOCK(hhash);
2439 /* Return function status */
2440 return HAL_OK;
2443 else
2445 return HAL_BUSY;
2453 * @brief Initialize the HASH peripheral, next process pInBuffer then
2454 * read the computed digest in interruption mode.
2455 * @note Digest is available in pOutBuffer.
2456 * @param hhash: HASH handle.
2457 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
2458 * @param Size: length of the input buffer in bytes.
2459 * @param pOutBuffer: pointer to the computed digest.
2460 * @param Algorithm: HASH algorithm.
2461 * @retval HAL status
2463 HAL_StatusTypeDef HASH_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Algorithm)
2465 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2467 /* If State is ready or suspended, start or resume IT-based HASH processing */
2468 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2470 /* Check input parameters */
2471 if ((pInBuffer == NULL) || (Size == 0U) || (pOutBuffer == NULL))
2473 hhash->State = HAL_HASH_STATE_READY;
2474 return HAL_ERROR;
2477 /* Process Locked */
2478 __HAL_LOCK(hhash);
2480 /* Change the HASH state */
2481 hhash->State = HAL_HASH_STATE_BUSY;
2483 /* Initialize IT counter */
2484 hhash->HashITCounter = 1;
2486 /* Check if initialization phase has already be performed */
2487 if(hhash->Phase == HAL_HASH_PHASE_READY)
2489 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2490 MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2492 /* Configure the number of valid bits in last word of the message */
2493 __HAL_HASH_SET_NBVALIDBITS(Size);
2496 hhash->HashInCount = Size; /* Counter used to keep track of number of data
2497 to be fed to the IP */
2498 hhash->pHashInBuffPtr = pInBuffer; /* Points at data which will be fed to the IP at
2499 the next interruption */
2500 /* In case of suspension, hhash->HashInCount and hhash->pHashInBuffPtr contain
2501 the information describing where the HASH process is stopped.
2502 These variables are used later on to resume the HASH processing at the
2503 correct location. */
2505 hhash->pHashOutBuffPtr = pOutBuffer; /* Points at the computed digest */
2508 /* Set the phase */
2509 hhash->Phase = HAL_HASH_PHASE_PROCESS;
2511 /* Process Unlock */
2512 __HAL_UNLOCK(hhash);
2514 /* Enable Interrupts */
2515 __HAL_HASH_ENABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
2517 /* Return function status */
2518 return HAL_OK;
2520 else
2522 return HAL_BUSY;
2529 * @brief Initialize the HASH peripheral then initiate a DMA transfer
2530 * to feed the input buffer to the IP.
2531 * @note If MDMAT bit is set before calling this function (multi-buffer
2532 * HASH processing case), the input buffer size (in bytes) must be
2533 * a multiple of 4 otherwise, the HASH digest computation is corrupted.
2534 * For the processing of the last buffer of the thread, MDMAT bit must
2535 * be reset and the buffer length (in bytes) doesn't have to be a
2536 * multiple of 4.
2537 * @param hhash: HASH handle.
2538 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
2539 * @param Size: length of the input buffer in bytes.
2540 * @param Algorithm: HASH algorithm.
2541 * @retval HAL status
2543 HAL_StatusTypeDef HASH_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2545 uint32_t inputaddr;
2546 uint32_t inputSize;
2547 HAL_StatusTypeDef status ;
2548 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2551 /* Make sure the input buffer size (in bytes) is a multiple of 4 when MDMAT bit is set
2552 (case of multi-buffer HASH processing) */
2553 assert_param(IS_HASH_DMA_MULTIBUFFER_SIZE(Size));
2555 /* If State is ready or suspended, start or resume polling-based HASH processing */
2556 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2558 /* Check input parameters */
2559 if ( (pInBuffer == NULL ) || (Size == 0U) ||
2560 /* Check phase coherency. Phase must be
2561 either READY (fresh start)
2562 or PROCESS (multi-buffer HASH management) */
2563 ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HASH_PROCESSING(hhash)))))
2565 hhash->State = HAL_HASH_STATE_READY;
2566 return HAL_ERROR;
2570 /* Process Locked */
2571 __HAL_LOCK(hhash);
2573 /* If not a resumption case */
2574 if (hhash->State == HAL_HASH_STATE_READY)
2576 /* Change the HASH state */
2577 hhash->State = HAL_HASH_STATE_BUSY;
2579 /* Check if initialization phase has already been performed.
2580 If Phase is already set to HAL_HASH_PHASE_PROCESS, this means the
2581 API is processing a new input data message in case of multi-buffer HASH
2582 computation. */
2583 if(hhash->Phase == HAL_HASH_PHASE_READY)
2585 /* Select the HASH algorithm, clear HMAC mode and long key selection bit, reset the HASH processor core */
2586 MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_CR_INIT);
2588 /* Set the phase */
2589 hhash->Phase = HAL_HASH_PHASE_PROCESS;
2592 /* Configure the Number of valid bits in last word of the message */
2593 __HAL_HASH_SET_NBVALIDBITS(Size);
2595 inputaddr = (uint32_t)pInBuffer; /* DMA transfer start address */
2596 inputSize = Size; /* DMA transfer size (in bytes) */
2598 /* In case of suspension request, save the starting parameters */
2599 hhash->pHashInBuffPtr = pInBuffer; /* DMA transfer start address */
2600 hhash->HashInCount = Size; /* DMA transfer size (in bytes) */
2603 /* If resumption case */
2604 else
2606 /* Change the HASH state */
2607 hhash->State = HAL_HASH_STATE_BUSY;
2609 /* Resumption case, inputaddr and inputSize are not set to the API input parameters
2610 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
2611 processing was suspended */
2612 inputaddr = (uint32_t)hhash->pHashInBuffPtr; /* DMA transfer start address */
2613 inputSize = hhash->HashInCount; /* DMA transfer size (in bytes) */
2617 /* Set the HASH DMA transfert complete callback */
2618 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
2619 /* Set the DMA error callback */
2620 hhash->hdmain->XferErrorCallback = HASH_DMAError;
2622 /* Store number of words already pushed to manage proper DMA processing suspension */
2623 hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
2625 /* Enable the DMA In DMA Stream */
2626 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((inputSize %4U)!=0U) ? ((inputSize+(4U-(inputSize %4U)))/4U):(inputSize/4U)));
2628 /* Enable DMA requests */
2629 SET_BIT(HASH->CR, HASH_CR_DMAE);
2631 /* Process Unlock */
2632 __HAL_UNLOCK(hhash);
2634 /* Return function status */
2635 if (status != HAL_OK)
2637 /* Update HASH state machine to error */
2638 hhash->State = HAL_HASH_STATE_ERROR;
2640 else
2642 /* Change HASH state */
2643 hhash->State = HAL_HASH_STATE_READY;
2646 return status;
2648 else
2650 return HAL_BUSY;
2655 * @brief Return the computed digest.
2656 * @note The API waits for DCIS to be set then reads the computed digest.
2657 * @param hhash: HASH handle.
2658 * @param pOutBuffer: pointer to the computed digest.
2659 * @param Timeout: Timeout value.
2660 * @retval HAL status
2662 HAL_StatusTypeDef HASH_Finish(HASH_HandleTypeDef *hhash, uint8_t* pOutBuffer, uint32_t Timeout)
2665 if(hhash->State == HAL_HASH_STATE_READY)
2667 /* Check parameter */
2668 if (pOutBuffer == NULL)
2670 return HAL_ERROR;
2673 /* Process Locked */
2674 __HAL_LOCK(hhash);
2676 /* Change the HASH state to busy */
2677 hhash->State = HAL_HASH_STATE_BUSY;
2679 /* Wait for DCIS flag to be set */
2680 if (HASH_WaitOnFlagUntilTimeout(hhash, HASH_FLAG_DCIS, RESET, Timeout) != HAL_OK)
2682 return HAL_TIMEOUT;
2685 /* Read the message digest */
2686 HASH_GetDigest(pOutBuffer, HASH_DIGEST_LENGTH());
2688 /* Change the HASH state to ready */
2689 hhash->State = HAL_HASH_STATE_READY;
2691 /* Process UnLock */
2692 __HAL_UNLOCK(hhash);
2694 /* Return function status */
2695 return HAL_OK;
2698 else
2700 return HAL_BUSY;
2707 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
2708 * read the computed digest.
2709 * @note Digest is available in pOutBuffer.
2710 * @note Same key is used for the inner and the outer hash functions; pointer to key and
2711 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
2712 * @param hhash: HASH handle.
2713 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
2714 * @param Size: length of the input buffer in bytes.
2715 * @param pOutBuffer: pointer to the computed digest.
2716 * @param Timeout: Timeout value.
2717 * @param Algorithm: HASH algorithm.
2718 * @retval HAL status
2720 HAL_StatusTypeDef HMAC_Start(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Timeout, uint32_t Algorithm)
2722 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2724 /* If State is ready or suspended, start or resume polling-based HASH processing */
2725 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2727 /* Check input parameters */
2728 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || (pOutBuffer == NULL))
2730 hhash->State = HAL_HASH_STATE_READY;
2731 return HAL_ERROR;
2734 /* Process Locked */
2735 __HAL_LOCK(hhash);
2737 /* Change the HASH state */
2738 hhash->State = HAL_HASH_STATE_BUSY;
2740 /* Check if initialization phase has already be performed */
2741 if(hhash->Phase == HAL_HASH_PHASE_READY)
2743 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
2744 if(hhash->Init.KeySize > 64U)
2746 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);
2748 else
2750 MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
2752 /* Set the phase to Step 1 */
2753 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
2754 /* Resort to hhash internal fields to feed the IP.
2755 Parameters will be updated in case of suspension to contain the proper
2756 information at resumption time. */
2757 hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */
2758 hhash->pHashInBuffPtr = pInBuffer; /* Input data address, HMAC_Processing input parameter for Step 2 */
2759 hhash->HashInCount = Size; /* Input data size, HMAC_Processing input parameter for Step 2 */
2760 hhash->HashBuffSize = Size; /* Store the input buffer size for the whole HMAC process */
2761 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address, HMAC_Processing input parameter for Step 1 and Step 3 */
2762 hhash->HashKeyCount = hhash->Init.KeySize; /* Key size, HMAC_Processing input parameter for Step 1 and Step 3 */
2765 /* Carry out HMAC processing */
2766 return HMAC_Processing(hhash, Timeout);
2769 else
2771 return HAL_BUSY;
2778 * @brief Initialize the HASH peripheral in HMAC mode, next process pInBuffer then
2779 * read the computed digest in interruption mode.
2780 * @note Digest is available in pOutBuffer.
2781 * @note Same key is used for the inner and the outer hash functions; pointer to key and
2782 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
2783 * @param hhash: HASH handle.
2784 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
2785 * @param Size: length of the input buffer in bytes.
2786 * @param pOutBuffer: pointer to the computed digest.
2787 * @param Algorithm: HASH algorithm.
2788 * @retval HAL status
2790 HAL_StatusTypeDef HMAC_Start_IT(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint8_t* pOutBuffer, uint32_t Algorithm)
2792 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2794 /* If State is ready or suspended, start or resume IT-based HASH processing */
2795 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2797 /* Check input parameters */
2798 if ((pInBuffer == NULL) || (Size == 0U) || (hhash->Init.pKey == NULL) || (hhash->Init.KeySize == 0U) || (pOutBuffer == NULL))
2800 hhash->State = HAL_HASH_STATE_READY;
2801 return HAL_ERROR;
2804 /* Process Locked */
2805 __HAL_LOCK(hhash);
2807 /* Change the HASH state */
2808 hhash->State = HAL_HASH_STATE_BUSY;
2810 /* Initialize IT counter */
2811 hhash->HashITCounter = 1;
2813 /* Check if initialization phase has already be performed */
2814 if (hhash->Phase == HAL_HASH_PHASE_READY)
2816 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits */
2817 if(hhash->Init.KeySize > 64U)
2819 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);
2821 else
2823 MODIFY_REG(HASH->CR, HASH_CR_LKEY|HASH_CR_ALGO|HASH_CR_MODE|HASH_CR_INIT, Algorithm | HASH_ALGOMODE_HMAC | HASH_CR_INIT);
2826 /* Resort to hhash internal fields hhash->pHashInBuffPtr and hhash->HashInCount
2827 to feed the IP whatever the HMAC step.
2828 Lines below are set to start HMAC Step 1 processing where key is entered first. */
2829 hhash->HashInCount = hhash->Init.KeySize; /* Key size */
2830 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* Key address */
2832 /* Store input and output parameters in handle fields to manage steps transition
2833 or possible HMAC suspension/resumption */
2834 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */
2835 hhash->pHashMsgBuffPtr = pInBuffer; /* Input message address */
2836 hhash->HashBuffSize = Size; /* Input message size (in bytes) */
2837 hhash->pHashOutBuffPtr = pOutBuffer; /* Output digest address */
2839 /* Configure the number of valid bits in last word of the key */
2840 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2842 /* Set the phase to Step 1 */
2843 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
2845 else if ((hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_1) || (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_3))
2847 /* Restart IT-based HASH processing after Step 1 or Step 3 suspension */
2850 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2852 /* Restart IT-based HASH processing after Step 2 suspension */
2855 else
2857 /* Error report as phase incorrect */
2858 /* Process Unlock */
2859 __HAL_UNLOCK(hhash);
2860 hhash->State = HAL_HASH_STATE_READY;
2861 return HAL_ERROR;
2864 /* Process Unlock */
2865 __HAL_UNLOCK(hhash);
2867 /* Enable Interrupts */
2868 __HAL_HASH_ENABLE_IT(HASH_IT_DINI|HASH_IT_DCI);
2870 /* Return function status */
2871 return HAL_OK;
2873 else
2875 return HAL_BUSY;
2883 * @brief Initialize the HASH peripheral in HMAC mode then initiate the required
2884 * DMA transfers to feed the key and the input buffer to the IP.
2885 * @note Same key is used for the inner and the outer hash functions; pointer to key and
2886 * key size are respectively stored in hhash->Init.pKey and hhash->Init.KeySize.
2887 * @note In case of multi-buffer HMAC processing, the input buffer size (in bytes) must
2888 * be a multiple of 4 otherwise, the HASH digest computation is corrupted.
2889 * Only the length of the last buffer of the thread doesn't have to be a
2890 * multiple of 4.
2891 * @param hhash: HASH handle.
2892 * @param pInBuffer: pointer to the input buffer (buffer to be hashed).
2893 * @param Size: length of the input buffer in bytes.
2894 * @param Algorithm: HASH algorithm.
2895 * @retval HAL status
2897 HAL_StatusTypeDef HMAC_Start_DMA(HASH_HandleTypeDef *hhash, uint8_t *pInBuffer, uint32_t Size, uint32_t Algorithm)
2899 uint32_t inputaddr;
2900 uint32_t inputSize;
2901 HAL_StatusTypeDef status ;
2902 HAL_HASH_StateTypeDef State_tmp = hhash->State;
2903 /* Make sure the input buffer size (in bytes) is a multiple of 4 when digest calculation
2904 is disabled (multi-buffer HMAC processing, MDMAT bit to be set) */
2905 assert_param(IS_HMAC_DMA_MULTIBUFFER_SIZE(hhash, Size));
2906 /* If State is ready or suspended, start or resume DMA-based HASH processing */
2907 if((State_tmp == HAL_HASH_STATE_READY) || (State_tmp == HAL_HASH_STATE_SUSPENDED))
2909 /* Check input parameters */
2910 if ((pInBuffer == NULL ) || (Size == 0U) || (hhash->Init.pKey == NULL ) || (hhash->Init.KeySize == 0U) ||
2911 /* Check phase coherency. Phase must be
2912 either READY (fresh start)
2913 or one of HMAC PROCESS steps (multi-buffer HASH management) */
2914 ((hhash->Phase != HAL_HASH_PHASE_READY) && (!(IS_HMAC_PROCESSING(hhash)))))
2916 hhash->State = HAL_HASH_STATE_READY;
2917 return HAL_ERROR;
2921 /* Process Locked */
2922 __HAL_LOCK(hhash);
2924 /* If not a case of resumption after suspension */
2925 if (hhash->State == HAL_HASH_STATE_READY)
2927 /* Check whether or not initialization phase has already be performed */
2928 if(hhash->Phase == HAL_HASH_PHASE_READY)
2930 /* Change the HASH state */
2931 hhash->State = HAL_HASH_STATE_BUSY;
2932 /* Check if key size is larger than 64 bytes, accordingly set LKEY and the other setting bits.
2933 At the same time, ensure MDMAT bit is cleared. */
2934 if(hhash->Init.KeySize > 64U)
2936 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);
2938 else
2940 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);
2942 /* Store input aparameters in handle fields to manage steps transition
2943 or possible HMAC suspension/resumption */
2944 hhash->HashInCount = hhash->Init.KeySize; /* Initial size for first DMA transfer (key size) */
2945 hhash->pHashKeyBuffPtr = hhash->Init.pKey; /* Key address */
2946 hhash->pHashInBuffPtr = hhash->Init.pKey ; /* First address passed to DMA (key address at Step 1) */
2947 hhash->pHashMsgBuffPtr = pInBuffer; /* Input data address */
2948 hhash->HashBuffSize = Size; /* input data size (in bytes) */
2950 /* Set DMA input parameters */
2951 inputaddr = (uint32_t)(hhash->Init.pKey); /* Address passed to DMA (start by entering Key message) */
2952 inputSize = hhash->Init.KeySize; /* Size for first DMA transfer (in bytes) */
2954 /* Configure the number of valid bits in last word of the key */
2955 __HAL_HASH_SET_NBVALIDBITS(hhash->Init.KeySize);
2957 /* Set the phase to Step 1 */
2958 hhash->Phase = HAL_HASH_PHASE_HMAC_STEP_1;
2961 else if (hhash->Phase == HAL_HASH_PHASE_HMAC_STEP_2)
2963 /* Process a new input data message in case of multi-buffer HMAC processing
2964 (this is not a resumption case) */
2966 /* Change the HASH state */
2967 hhash->State = HAL_HASH_STATE_BUSY;
2969 /* Save input parameters to be able to manage possible suspension/resumption */
2970 hhash->HashInCount = Size; /* Input message address */
2971 hhash->pHashInBuffPtr = pInBuffer; /* Input message size in bytes */
2973 /* Set DMA input parameters */
2974 inputaddr = (uint32_t)pInBuffer; /* Input message address */
2975 inputSize = Size; /* Input message size in bytes */
2977 if (hhash->DigestCalculationDisable == RESET)
2979 /* This means this is the last buffer of the multi-buffer sequence: DCAL needs to be set. */
2980 __HAL_HASH_RESET_MDMAT();
2981 __HAL_HASH_SET_NBVALIDBITS(inputSize);
2984 else
2986 /* Phase not aligned with handle READY state */
2987 __HAL_UNLOCK(hhash);
2988 /* Return function status */
2989 return HAL_ERROR;
2992 else
2994 /* Resumption case (phase may be Step 1, 2 or 3) */
2996 /* Change the HASH state */
2997 hhash->State = HAL_HASH_STATE_BUSY;
2999 /* Set DMA input parameters at resumption location;
3000 inputaddr and inputSize are not set to the API input parameters
3001 but to those saved beforehand by HAL_HASH_DMAFeed_ProcessSuspend() when the
3002 processing was suspended. */
3003 inputaddr = (uint32_t)(hhash->pHashInBuffPtr); /* Input message address */
3004 inputSize = hhash->HashInCount; /* Input message size in bytes */
3008 /* Set the HASH DMA transfert complete callback */
3009 hhash->hdmain->XferCpltCallback = HASH_DMAXferCplt;
3010 /* Set the DMA error callback */
3011 hhash->hdmain->XferErrorCallback = HASH_DMAError;
3013 /* Store number of words already pushed to manage proper DMA processing suspension */
3014 hhash->NbWordsAlreadyPushed = HASH_NBW_PUSHED();
3016 /* Enable the DMA In DMA Stream */
3017 status = HAL_DMA_Start_IT(hhash->hdmain, inputaddr, (uint32_t)&HASH->DIN, (((inputSize %4U)!=0U) ? ((inputSize+(4U-(inputSize %4U)))/4U):(inputSize/4U)));
3018 /* Enable DMA requests */
3019 SET_BIT(HASH->CR, HASH_CR_DMAE);
3021 /* Process Unlocked */
3022 __HAL_UNLOCK(hhash);
3024 /* Return function status */
3025 if (status != HAL_OK)
3027 /* Update HASH state machine to error */
3028 hhash->State = HAL_HASH_STATE_ERROR;
3030 else
3032 /* Change HASH state */
3033 hhash->State = HAL_HASH_STATE_READY;
3035 /* Return function status */
3036 return status;
3038 else
3040 return HAL_BUSY;
3044 * @}
3047 #endif /* HAL_HASH_MODULE_ENABLED */
3050 * @}
3052 #endif /* HASH*/
3054 * @}
3059 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/